@@ -87,16 +87,20 @@ void Wippersnapper_AnalogIO::setADCResolution(int resolution) {
87
87
analogReadResolution (16 );
88
88
_nativeResolution = 12 ;
89
89
#elif defined(ARDUINO_ARCH_ESP32)
90
- scaleAnalogRead = true ;
91
- _nativeResolution = 13 ;
90
+ scaleAnalogRead = false ; // handled in bsp (analogReadResolution)
91
+ analogReadResolution (resolution); // 16 bit values (shifted from 12 or 13bit)
92
+ #if defined(ESP32S3)
93
+ _nativeResolution = 13 ; // S3 ADC is 13-bit, others are 12-bit
94
+ #else
95
+ _nativeResolution = 12 ;
96
+ #endif
92
97
#elif defined(ARDUINO_ARCH_RP2040)
93
98
scaleAnalogRead = true ;
94
99
_nativeResolution = 10 ;
95
100
#else
96
101
scaleAnalogRead = true ;
97
102
_nativeResolution = 10 ;
98
103
#endif
99
-
100
104
_adcResolution = resolution;
101
105
}
102
106
@@ -232,8 +236,12 @@ uint16_t Wippersnapper_AnalogIO::getPinValue(int pin) {
232
236
*/
233
237
/* *********************************************************/
234
238
float Wippersnapper_AnalogIO::getPinValueVolts (int pin) {
239
+ #ifdef ARDUINO_ARCH_ESP32
240
+ return analogReadMilliVolts (pin) / 1000.0 ;
241
+ #else
235
242
uint16_t rawValue = getPinValue (pin);
236
243
return rawValue * getAref () / 65536 ;
244
+ #endif
237
245
}
238
246
239
247
/* *****************************************************************/
@@ -303,20 +311,70 @@ bool Wippersnapper_AnalogIO::encodePinEvent(
303
311
return true ;
304
312
}
305
313
314
+ /* *********************************************************/
315
+ /* !
316
+ @brief Calculates the hysteresis for the pin value.
317
+ @param pin
318
+ The desired analog pin to calculate hysteresis for.
319
+ @param pinValRaw
320
+ The pin's raw value.
321
+ @param pinValThreshHi
322
+ The pin's high threshold value.
323
+ @param pinValThreshLow
324
+ The pin's low threshold value.
325
+ */
326
+ /* *********************************************************/
327
+ void calculateHysteresis (analogInputPin pin, uint16_t pinValRaw,
328
+ uint16_t &pinValThreshHi, uint16_t &pinValThreshLow) {
329
+ // All boards ADC values scaled to 16bit, in future we may need to
330
+ // adjust dynamically
331
+ uint16_t maxDecimalValue = 65535 ;
332
+
333
+ // Calculate threshold values - using DEFAULT_HYSTERISIS for first third
334
+ // (1/3) of the range, then 2x DEFAULT_HYSTERISIS for the middle 1/3,
335
+ // and 4x DEFAULT_HYSTERISIS for the last 1/3. This should allow a more
336
+ // wifi blip tolerant threshold for the both ends of the range.
337
+ float CURRENT_HYSTERISIS;
338
+ if (pinValRaw < maxDecimalValue / 3 ) {
339
+ CURRENT_HYSTERISIS = maxDecimalValue * DEFAULT_HYSTERISIS;
340
+ } else if (pinValRaw < (maxDecimalValue / 3 ) * 2 ) {
341
+ CURRENT_HYSTERISIS = maxDecimalValue * DEFAULT_HYSTERISIS * 2 ;
342
+ } else {
343
+ CURRENT_HYSTERISIS = maxDecimalValue * DEFAULT_HYSTERISIS * 4 ;
344
+ }
345
+ // get the threshold values for previous pin value, but don't overflow
346
+ float overflowableThHi = pin.prvPinVal + CURRENT_HYSTERISIS;
347
+ float overflowableThLow = pin.prvPinVal - CURRENT_HYSTERISIS;
348
+ if (overflowableThHi > maxDecimalValue) {
349
+ pinValThreshHi = maxDecimalValue;
350
+ } else {
351
+ pinValThreshHi = overflowableThHi;
352
+ }
353
+ if (overflowableThLow < 0 ) {
354
+ pinValThreshLow = 0 ;
355
+ } else {
356
+ pinValThreshLow = overflowableThLow;
357
+ }
358
+ }
359
+
306
360
/* *********************************************************/
307
361
/* !
308
362
@brief Checks if pin's period is expired.
309
363
@param currentTime
310
364
The current software timer value.
311
365
@param pin
312
366
The desired analog pin to check
367
+ @param periodOffset
368
+ Offset to add to the pin's period (used for on_change).
313
369
@returns True if pin's period expired, False otherwise.
314
370
*/
315
371
/* *********************************************************/
316
- bool Wippersnapper_AnalogIO::timerExpired (long currentTime,
317
- analogInputPin pin) {
318
- if (currentTime - pin.prvPeriod > pin.period && pin.period != 0L )
372
+ bool Wippersnapper_AnalogIO::timerExpired (long currentTime, analogInputPin pin,
373
+ long periodOffset) {
374
+ if (pin.period + periodOffset != 0L &&
375
+ currentTime - pin.prvPeriod > (pin.period + periodOffset)) {
319
376
return true ;
377
+ }
320
378
return false ;
321
379
}
322
380
@@ -335,9 +393,8 @@ void Wippersnapper_AnalogIO::update() {
335
393
if (_analog_input_pins[i].enabled == true ) {
336
394
337
395
// Does the pin execute on-period?
338
- if ((long )millis () - _analog_input_pins[i].prvPeriod >
339
- _analog_input_pins[i].period &&
340
- _analog_input_pins[i].period != 0L ) {
396
+ if (_analog_input_pins[i].period != 0L &&
397
+ timerExpired (millis (), _analog_input_pins[i])) {
341
398
WS_DEBUG_PRINT (" Executing periodic event on A" );
342
399
WS_DEBUG_PRINTLN (_analog_input_pins[i].pinName );
343
400
@@ -359,41 +416,47 @@ void Wippersnapper_AnalogIO::update() {
359
416
encodePinEvent (_analog_input_pins[i].pinName ,
360
417
_analog_input_pins[i].readMode , pinValRaw, pinValVolts);
361
418
362
- // IMPT - reset the digital pin
419
+ // mark last execution time
363
420
_analog_input_pins[i].prvPeriod = millis ();
364
421
}
365
422
// Does the pin execute on_change?
366
423
else if (_analog_input_pins[i].period == 0L ) {
367
424
425
+ // not first run and timer not expired, skip
426
+ if (_analog_input_pins[i].prvPeriod != 0L &&
427
+ !timerExpired (millis (), _analog_input_pins[i], 500 )) {
428
+ continue ;
429
+ }
430
+
368
431
// note: on-change requires ADC DEFAULT_HYSTERISIS to check against prv
369
432
// pin value
370
433
uint16_t pinValRaw = getPinValue (_analog_input_pins[i].pinName );
371
434
372
- uint16_t _pinValThreshHi =
373
- _analog_input_pins[i].prvPinVal +
374
- (_analog_input_pins[i].prvPinVal * DEFAULT_HYSTERISIS);
375
- uint16_t _pinValThreshLow =
376
- _analog_input_pins[i].prvPinVal -
377
- (_analog_input_pins[i].prvPinVal * DEFAULT_HYSTERISIS);
435
+ // check if pin value has changed enough
436
+ uint16_t pinValThreshHi, pinValThreshLow;
437
+ calculateHysteresis (_analog_input_pins[i], pinValRaw, pinValThreshHi,
438
+ pinValThreshLow);
378
439
379
- if (pinValRaw > _pinValThreshHi || pinValRaw < _pinValThreshLow) {
440
+ if (_analog_input_pins[i].prvPeriod == 0 ||
441
+ pinValRaw > pinValThreshHi || pinValRaw < pinValThreshLow) {
380
442
// Perform voltage conversion if we need to
381
443
if (_analog_input_pins[i].readMode ==
382
444
wippersnapper_pin_v1_ConfigurePinRequest_AnalogReadMode_ANALOG_READ_MODE_PIN_VOLTAGE) {
383
- pinValVolts = pinValRaw * getAref () / 65536 ;
445
+ pinValVolts = getPinValueVolts (_analog_input_pins[i]. pinName ) ;
384
446
}
385
447
386
448
// Publish pin event to IO
387
449
encodePinEvent (_analog_input_pins[i].pinName ,
388
450
_analog_input_pins[i].readMode , pinValRaw,
389
451
pinValVolts);
390
452
391
- } else {
392
- // WS_DEBUG_PRINTLN("ADC has not changed enough, continue...");
453
+ // mark last execution time
454
+ _analog_input_pins[i].prvPeriod = millis ();
455
+
456
+ } else { // ADC has not changed enough
393
457
continue ;
394
458
}
395
- // set the pin value in the digital pin object for comparison on next
396
- // run
459
+ // set the pin value in the digital pin object for comparison next run
397
460
_analog_input_pins[i].prvPinVal = pinValRaw;
398
461
}
399
462
}
0 commit comments