@@ -56,8 +56,10 @@ static const uint32_t MAX_TIMEOUT_MICRO_SEC = 75000;
56
56
/* To avoid that we receive a echo from a former measurement, we do not
57
57
* start a new measurement within the given time from the start of the
58
58
* former measurement of the opposite sensor.
59
+ * High values can lead to the situation that we only poll the
60
+ * primary sensor for a while!?
59
61
*/
60
- static const uint32_t SENSOR_QUIET_PERIOD_AFTER_OPPOSITE_START_MICRO_SEC = 50 * 1000 ;
62
+ static const uint32_t SENSOR_QUIET_PERIOD_AFTER_OPPOSITE_START_MICRO_SEC = 30 * 1000 ;
61
63
62
64
/* The last end (echo goes to low) of a measurement must be this far
63
65
* away before a new measurement is started.
@@ -70,7 +72,7 @@ static const uint32_t SENSOR_QUIET_PERIOD_AFTER_END_MICRO_SEC = 10 * 1000;
70
72
- With 30ms I could get stable readings down to 25/35cm only (new sensor)
71
73
- It looked fine with the old sensor for all values
72
74
*/
73
- static const uint32_t SENSOR_QUIET_PERIOD_AFTER_START_MICRO_SEC = 30 * 1000 ;
75
+ static const uint32_t SENSOR_QUIET_PERIOD_AFTER_START_MICRO_SEC = 35 * 1000 ;
74
76
75
77
/* Value of HCSR04SensorInfo::end during an ongoing measurement. */
76
78
static const uint32_t MEASUREMENT_IN_PROGRESS = 0 ;
@@ -177,6 +179,7 @@ void HCSR04SensorManager::reset() {
177
179
sensor.numberOfTriggers = 0 ;
178
180
}
179
181
lastReadingCount = 0 ;
182
+ lastSensor = 1 - primarySensor;
180
183
memset (&(startOffsetMilliseconds), 0 , sizeof (startOffsetMilliseconds));
181
184
startReadingMilliseconds = millis ();
182
185
}
@@ -198,6 +201,24 @@ void HCSR04SensorManager::setPrimarySensor(uint8_t idx) {
198
201
primarySensor = idx;
199
202
}
200
203
204
+ /* Polls for new readings, if sensors are not ready, the
205
+ * method returns false.
206
+ */
207
+ bool HCSR04SensorManager::pollDistancesAlternating () {
208
+ bool newMeasurements = false ;
209
+ if (lastSensor == primarySensor && isReadyForStart (1 - primarySensor)) {
210
+ setSensorTriggersToLow ();
211
+ lastSensor = 1 - primarySensor;
212
+ sendTriggerToSensor (1 - primarySensor);
213
+ } else if (isReadyForStart (primarySensor)) {
214
+ newMeasurements = collectSensorResults ();
215
+ setSensorTriggersToLow ();
216
+ lastSensor = primarySensor;
217
+ sendTriggerToSensor (primarySensor);
218
+ }
219
+ return newMeasurements;
220
+ }
221
+
201
222
/* Polls for new readings, if sensors are not ready, the
202
223
* method returns false. If sensors are ready and readings
203
224
* are available, data is read and updated. If the primary
@@ -210,12 +231,11 @@ bool HCSR04SensorManager::pollDistancesParallel() {
210
231
if (isReadyForStart (primarySensor)) {
211
232
setSensorTriggersToLow ();
212
233
newMeasurements = collectSensorResults ();
213
- if (isReadyForStart (1 - primarySensor)) {
234
+ const bool secondSensorIsReady = isReadyForStart (1 - primarySensor);
235
+ sendTriggerToSensor (primarySensor);
236
+ if (secondSensorIsReady) {
214
237
sendTriggerToSensor (1 - primarySensor);
215
238
}
216
- sendTriggerToSensor (primarySensor);
217
- delayMicroseconds (20 );
218
- setSensorTriggersToLow ();
219
239
}
220
240
return newMeasurements;
221
241
}
@@ -231,16 +251,20 @@ void HCSR04SensorManager::sendTriggerToSensor(uint8_t sensorId) {
231
251
HCSR04SensorInfo * const sensor = &(m_sensors[sensorId]);
232
252
updateStatistics (sensor);
233
253
sensor->end = MEASUREMENT_IN_PROGRESS; // will be updated with LOW signal
234
- sensor->trigger = sensor->start = micros (); // will be updated with HIGH signal
235
254
sensor->numberOfTriggers ++;
236
255
sensor->measurementRead = false ;
256
+ sensor->trigger = sensor->start = micros (); // will be updated with HIGH signal
237
257
digitalWrite (sensor->triggerPin , HIGH);
258
+ // 10us are specified but some sensors are more stable with 20us according
259
+ // to internet reports
260
+ delayMicroseconds (20 );
261
+ digitalWrite (sensor->triggerPin , LOW);
238
262
}
239
263
240
264
/* Checks if the given sensor is ready for a new measurement cycle.
241
265
*/
242
266
boolean HCSR04SensorManager::isReadyForStart (uint8_t sensorId) {
243
- const HCSR04SensorInfo * const sensor = &m_sensors[sensorId];
267
+ HCSR04SensorInfo * const sensor = &m_sensors[sensorId];
244
268
boolean ready = false ;
245
269
const uint32_t now = micros ();
246
270
const uint32_t start = sensor->start ;
@@ -254,10 +278,10 @@ boolean HCSR04SensorManager::isReadyForStart(uint8_t sensorId) {
254
278
}
255
279
if (digitalRead (sensor->echoPin ) != LOW) {
256
280
log_e (" Measurement done, but echo pin is high for %s sensor" , sensor->sensorLocation );
281
+ sensor->numberOfLowAfterMeasurement ++;
257
282
}
258
-
259
-
260
- } else if (microsBetween (now, start) > 2 * MAX_TIMEOUT_MICRO_SEC) {
283
+ } else if (microsBetween (now, start) > MAX_TIMEOUT_MICRO_SEC) {
284
+ sensor->numberOfToLongMeasurement ++;
261
285
// signal or interrupt was lost altogether this is an error,
262
286
// should we raise it?? Now pretend the sensor is ready, hope it helps to give it a trigger.
263
287
ready = true ;
@@ -329,7 +353,6 @@ bool HCSR04SensorManager::collectSensorResult(uint8_t sensorId) {
329
353
330
354
if (sensor->distance > 0 && sensor->distance < sensor->minDistance ) {
331
355
sensor->minDistance = sensor->distance ;
332
- sensor->lastMinUpdate = millis ();
333
356
}
334
357
sensor->measurementRead = true ;
335
358
return validReading;
@@ -355,25 +378,35 @@ uint32_t HCSR04SensorManager::getNoSignalReadings(const uint8_t sensorId) {
355
378
return m_sensors[sensorId].numberOfNoSignals ;
356
379
}
357
380
381
+ uint32_t HCSR04SensorManager::getNumberOfLowAfterMeasurement (const uint8_t sensorId) {
382
+ return m_sensors[sensorId].numberOfLowAfterMeasurement ;
383
+ }
384
+
385
+ uint32_t HCSR04SensorManager::getNumberOfToLongMeasurement (const uint8_t sensorId) {
386
+ return m_sensors[sensorId].numberOfToLongMeasurement ;
387
+ }
388
+
389
+ uint32_t HCSR04SensorManager::getNumberOfInterruptAdjustments (const uint8_t sensorId) {
390
+ return m_sensors[sensorId].numberOfInterruptAdjustments ;
391
+ }
392
+
358
393
/* During debugging I observed readings that did not get `start` updated
359
394
* By the interrupt. Since we also set start when we send the pulse to the
360
395
* sensor this adds 300 microseconds or 5 centimeters to the measured result.
361
396
* After research, is a bug in the ESP!? See https://esp32.com/viewtopic.php?t=10124
362
397
*/
363
398
uint32_t HCSR04SensorManager::getFixedStart (
364
- size_t idx, const HCSR04SensorInfo * const sensor) {
399
+ size_t idx, HCSR04SensorInfo * const sensor) {
365
400
uint32_t start = sensor->start ;
366
401
// the error appears if both sensors trigger the interrupt at the exact same
367
402
// time, if this happens, trigger time == start time
368
- if (sensor->trigger == sensor->start ) {
369
- for (size_t idx2 = 0 ; idx2 < NUMBER_OF_TOF_SENSORS; ++idx2) {
370
- if (idx2 != idx) {
371
- // it should be save to use the start value from the other sensor.
372
- const uint32_t alternativeStart = m_sensors[idx2].start ;
373
- if (microsBetween (alternativeStart, start) < 500 ) { // typically 290-310 microseconds {
374
- start = alternativeStart;
375
- }
376
- }
403
+ if (start == sensor->trigger && sensor->end != MEASUREMENT_IN_PROGRESS) {
404
+ // it should be save to use the start value from the other sensor.
405
+ const uint32_t alternativeStart = m_sensors[1 - idx].start ;
406
+ if (alternativeStart != m_sensors[1 - idx].trigger
407
+ && microsBetween (alternativeStart, start) < 500 ) { // typically 290-310 microseconds {
408
+ start = alternativeStart;
409
+ sensor->numberOfInterruptAdjustments ++;
377
410
}
378
411
}
379
412
return start;
@@ -450,6 +483,14 @@ uint16_t HCSR04SensorManager::millisSince(uint16_t milliseconds) {
450
483
uint16_t HCSR04SensorManager::medianMeasure (HCSR04SensorInfo *const sensor, uint16_t value) {
451
484
sensor->distances [sensor->nextMedianDistance ] = value;
452
485
sensor->nextMedianDistance ++;
486
+
487
+ // if we got "fantom" measures, they are <= the current measures, so remove
488
+ // all values <= the current measure from the median data
489
+ for (unsigned short & distance : sensor->distances ) {
490
+ if (distance < value) {
491
+ distance = value;
492
+ }
493
+ }
453
494
if (sensor->nextMedianDistance >= MEDIAN_DISTANCE_MEASURES) {
454
495
sensor->nextMedianDistance = 0 ;
455
496
}
0 commit comments