@@ -87,16 +87,20 @@ void Wippersnapper_AnalogIO::setADCResolution(int resolution) {
8787 analogReadResolution (16 );
8888 _nativeResolution = 12 ;
8989#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
9297#elif defined(ARDUINO_ARCH_RP2040)
9398 scaleAnalogRead = true ;
9499 _nativeResolution = 10 ;
95100#else
96101 scaleAnalogRead = true ;
97102 _nativeResolution = 10 ;
98103#endif
99-
100104 _adcResolution = resolution;
101105}
102106
@@ -232,8 +236,12 @@ uint16_t Wippersnapper_AnalogIO::getPinValue(int pin) {
232236*/
233237/* *********************************************************/
234238float Wippersnapper_AnalogIO::getPinValueVolts (int pin) {
239+ #ifdef ARDUINO_ARCH_ESP32
240+ return analogReadMilliVolts (pin) / 1000.0 ;
241+ #else
235242 uint16_t rawValue = getPinValue (pin);
236243 return rawValue * getAref () / 65536 ;
244+ #endif
237245}
238246
239247/* *****************************************************************/
@@ -303,20 +311,70 @@ bool Wippersnapper_AnalogIO::encodePinEvent(
303311 return true ;
304312}
305313
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+
306360/* *********************************************************/
307361/* !
308362 @brief Checks if pin's period is expired.
309363 @param currentTime
310364 The current software timer value.
311365 @param pin
312366 The desired analog pin to check
367+ @param periodOffset
368+ Offset to add to the pin's period (used for on_change).
313369 @returns True if pin's period expired, False otherwise.
314370*/
315371/* *********************************************************/
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)) {
319376 return true ;
377+ }
320378 return false ;
321379}
322380
@@ -335,9 +393,8 @@ void Wippersnapper_AnalogIO::update() {
335393 if (_analog_input_pins[i].enabled == true ) {
336394
337395 // 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])) {
341398 WS_DEBUG_PRINT (" Executing periodic event on A" );
342399 WS_DEBUG_PRINTLN (_analog_input_pins[i].pinName );
343400
@@ -359,41 +416,47 @@ void Wippersnapper_AnalogIO::update() {
359416 encodePinEvent (_analog_input_pins[i].pinName ,
360417 _analog_input_pins[i].readMode , pinValRaw, pinValVolts);
361418
362- // IMPT - reset the digital pin
419+ // mark last execution time
363420 _analog_input_pins[i].prvPeriod = millis ();
364421 }
365422 // Does the pin execute on_change?
366423 else if (_analog_input_pins[i].period == 0L ) {
367424
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+
368431 // note: on-change requires ADC DEFAULT_HYSTERISIS to check against prv
369432 // pin value
370433 uint16_t pinValRaw = getPinValue (_analog_input_pins[i].pinName );
371434
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);
378439
379- if (pinValRaw > _pinValThreshHi || pinValRaw < _pinValThreshLow) {
440+ if (_analog_input_pins[i].prvPeriod == 0 ||
441+ pinValRaw > pinValThreshHi || pinValRaw < pinValThreshLow) {
380442 // Perform voltage conversion if we need to
381443 if (_analog_input_pins[i].readMode ==
382444 wippersnapper_pin_v1_ConfigurePinRequest_AnalogReadMode_ANALOG_READ_MODE_PIN_VOLTAGE) {
383- pinValVolts = pinValRaw * getAref () / 65536 ;
445+ pinValVolts = getPinValueVolts (_analog_input_pins[i]. pinName ) ;
384446 }
385447
386448 // Publish pin event to IO
387449 encodePinEvent (_analog_input_pins[i].pinName ,
388450 _analog_input_pins[i].readMode , pinValRaw,
389451 pinValVolts);
390452
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
393457 continue ;
394458 }
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
397460 _analog_input_pins[i].prvPinVal = pinValRaw;
398461 }
399462 }
0 commit comments