Skip to content

Commit 0e9993b

Browse files
authored
Merge pull request #635 from tyeth/use_analogReadMilliVolts-for-esp32-scaledAnalogRead-false
Use analogReadMilliVolts for esp32 and update hysteresis
2 parents 18f08eb + 9c6187f commit 0e9993b

File tree

2 files changed

+87
-23
lines changed

2 files changed

+87
-23
lines changed

src/components/analogIO/Wippersnapper_AnalogIO.cpp

Lines changed: 85 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -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
/**********************************************************/
234238
float 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
}

src/components/analogIO/Wippersnapper_AnalogIO.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,8 @@ class Wippersnapper_AnalogIO {
6363
void setADCResolution(int resolution);
6464
int getADCresolution();
6565
int getNativeResolution();
66-
bool timerExpired(long currentTime, analogInputPin pin);
66+
bool timerExpired(long currentTime, analogInputPin pin,
67+
long periodOffset = 0);
6768

6869
void update();
6970
bool encodePinEvent(

0 commit comments

Comments
 (0)