Skip to content

Commit

Permalink
Merge pull request #635 from tyeth/use_analogReadMilliVolts-for-esp32…
Browse files Browse the repository at this point in the history
…-scaledAnalogRead-false

Use analogReadMilliVolts for esp32 and update hysteresis
  • Loading branch information
tyeth authored Nov 15, 2024
2 parents 18f08eb + 9c6187f commit 0e9993b
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 23 deletions.
107 changes: 85 additions & 22 deletions src/components/analogIO/Wippersnapper_AnalogIO.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,16 +87,20 @@ void Wippersnapper_AnalogIO::setADCResolution(int resolution) {
analogReadResolution(16);
_nativeResolution = 12;
#elif defined(ARDUINO_ARCH_ESP32)
scaleAnalogRead = true;
_nativeResolution = 13;
scaleAnalogRead = false; // handled in bsp (analogReadResolution)
analogReadResolution(resolution); // 16 bit values (shifted from 12 or 13bit)
#if defined(ESP32S3)
_nativeResolution = 13; // S3 ADC is 13-bit, others are 12-bit
#else
_nativeResolution = 12;
#endif
#elif defined(ARDUINO_ARCH_RP2040)
scaleAnalogRead = true;
_nativeResolution = 10;
#else
scaleAnalogRead = true;
_nativeResolution = 10;
#endif

_adcResolution = resolution;
}

Expand Down Expand Up @@ -232,8 +236,12 @@ uint16_t Wippersnapper_AnalogIO::getPinValue(int pin) {
*/
/**********************************************************/
float Wippersnapper_AnalogIO::getPinValueVolts(int pin) {
#ifdef ARDUINO_ARCH_ESP32
return analogReadMilliVolts(pin) / 1000.0;
#else
uint16_t rawValue = getPinValue(pin);
return rawValue * getAref() / 65536;
#endif
}

/******************************************************************/
Expand Down Expand Up @@ -303,20 +311,70 @@ bool Wippersnapper_AnalogIO::encodePinEvent(
return true;
}

/**********************************************************/
/*!
@brief Calculates the hysteresis for the pin value.
@param pin
The desired analog pin to calculate hysteresis for.
@param pinValRaw
The pin's raw value.
@param pinValThreshHi
The pin's high threshold value.
@param pinValThreshLow
The pin's low threshold value.
*/
/**********************************************************/
void calculateHysteresis(analogInputPin pin, uint16_t pinValRaw,
uint16_t &pinValThreshHi, uint16_t &pinValThreshLow) {
// All boards ADC values scaled to 16bit, in future we may need to
// adjust dynamically
uint16_t maxDecimalValue = 65535;

// Calculate threshold values - using DEFAULT_HYSTERISIS for first third
// (1/3) of the range, then 2x DEFAULT_HYSTERISIS for the middle 1/3,
// and 4x DEFAULT_HYSTERISIS for the last 1/3. This should allow a more
// wifi blip tolerant threshold for the both ends of the range.
float CURRENT_HYSTERISIS;
if (pinValRaw < maxDecimalValue / 3) {
CURRENT_HYSTERISIS = maxDecimalValue * DEFAULT_HYSTERISIS;
} else if (pinValRaw < (maxDecimalValue / 3) * 2) {
CURRENT_HYSTERISIS = maxDecimalValue * DEFAULT_HYSTERISIS * 2;
} else {
CURRENT_HYSTERISIS = maxDecimalValue * DEFAULT_HYSTERISIS * 4;
}
// get the threshold values for previous pin value, but don't overflow
float overflowableThHi = pin.prvPinVal + CURRENT_HYSTERISIS;
float overflowableThLow = pin.prvPinVal - CURRENT_HYSTERISIS;
if (overflowableThHi > maxDecimalValue) {
pinValThreshHi = maxDecimalValue;
} else {
pinValThreshHi = overflowableThHi;
}
if (overflowableThLow < 0) {
pinValThreshLow = 0;
} else {
pinValThreshLow = overflowableThLow;
}
}

/**********************************************************/
/*!
@brief Checks if pin's period is expired.
@param currentTime
The current software timer value.
@param pin
The desired analog pin to check
@param periodOffset
Offset to add to the pin's period (used for on_change).
@returns True if pin's period expired, False otherwise.
*/
/**********************************************************/
bool Wippersnapper_AnalogIO::timerExpired(long currentTime,
analogInputPin pin) {
if (currentTime - pin.prvPeriod > pin.period && pin.period != 0L)
bool Wippersnapper_AnalogIO::timerExpired(long currentTime, analogInputPin pin,
long periodOffset) {
if (pin.period + periodOffset != 0L &&
currentTime - pin.prvPeriod > (pin.period + periodOffset)) {
return true;
}
return false;
}

Expand All @@ -335,9 +393,8 @@ void Wippersnapper_AnalogIO::update() {
if (_analog_input_pins[i].enabled == true) {

// Does the pin execute on-period?
if ((long)millis() - _analog_input_pins[i].prvPeriod >
_analog_input_pins[i].period &&
_analog_input_pins[i].period != 0L) {
if (_analog_input_pins[i].period != 0L &&
timerExpired(millis(), _analog_input_pins[i])) {
WS_DEBUG_PRINT("Executing periodic event on A");
WS_DEBUG_PRINTLN(_analog_input_pins[i].pinName);

Expand All @@ -359,41 +416,47 @@ void Wippersnapper_AnalogIO::update() {
encodePinEvent(_analog_input_pins[i].pinName,
_analog_input_pins[i].readMode, pinValRaw, pinValVolts);

// IMPT - reset the digital pin
// mark last execution time
_analog_input_pins[i].prvPeriod = millis();
}
// Does the pin execute on_change?
else if (_analog_input_pins[i].period == 0L) {

// not first run and timer not expired, skip
if (_analog_input_pins[i].prvPeriod != 0L &&
!timerExpired(millis(), _analog_input_pins[i], 500)) {
continue;
}

// note: on-change requires ADC DEFAULT_HYSTERISIS to check against prv
// pin value
uint16_t pinValRaw = getPinValue(_analog_input_pins[i].pinName);

uint16_t _pinValThreshHi =
_analog_input_pins[i].prvPinVal +
(_analog_input_pins[i].prvPinVal * DEFAULT_HYSTERISIS);
uint16_t _pinValThreshLow =
_analog_input_pins[i].prvPinVal -
(_analog_input_pins[i].prvPinVal * DEFAULT_HYSTERISIS);
// check if pin value has changed enough
uint16_t pinValThreshHi, pinValThreshLow;
calculateHysteresis(_analog_input_pins[i], pinValRaw, pinValThreshHi,
pinValThreshLow);

if (pinValRaw > _pinValThreshHi || pinValRaw < _pinValThreshLow) {
if (_analog_input_pins[i].prvPeriod == 0 ||
pinValRaw > pinValThreshHi || pinValRaw < pinValThreshLow) {
// Perform voltage conversion if we need to
if (_analog_input_pins[i].readMode ==
wippersnapper_pin_v1_ConfigurePinRequest_AnalogReadMode_ANALOG_READ_MODE_PIN_VOLTAGE) {
pinValVolts = pinValRaw * getAref() / 65536;
pinValVolts = getPinValueVolts(_analog_input_pins[i].pinName);
}

// Publish pin event to IO
encodePinEvent(_analog_input_pins[i].pinName,
_analog_input_pins[i].readMode, pinValRaw,
pinValVolts);

} else {
// WS_DEBUG_PRINTLN("ADC has not changed enough, continue...");
// mark last execution time
_analog_input_pins[i].prvPeriod = millis();

} else { // ADC has not changed enough
continue;
}
// set the pin value in the digital pin object for comparison on next
// run
// set the pin value in the digital pin object for comparison next run
_analog_input_pins[i].prvPinVal = pinValRaw;
}
}
Expand Down
3 changes: 2 additions & 1 deletion src/components/analogIO/Wippersnapper_AnalogIO.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ class Wippersnapper_AnalogIO {
void setADCResolution(int resolution);
int getADCresolution();
int getNativeResolution();
bool timerExpired(long currentTime, analogInputPin pin);
bool timerExpired(long currentTime, analogInputPin pin,
long periodOffset = 0);

void update();
bool encodePinEvent(
Expand Down

0 comments on commit 0e9993b

Please sign in to comment.