diff --git a/PureSpaIO.cpp b/PureSpaIO.cpp index e348fef..a8d04fb 100644 --- a/PureSpaIO.cpp +++ b/PureSpaIO.cpp @@ -484,7 +484,7 @@ void PureSpaIO::setDesiredWaterTempCelsius(int temp) changeWaterTemp(-1); int sleep = 100; // ms - int changeTries = WATER_TEMP::SET_MAX - WATER_TEMP::SET_MIN + 3; + int changeTries = 3; int setTemp = UNDEF::INT; do { @@ -492,7 +492,6 @@ void PureSpaIO::setDesiredWaterTempCelsius(int temp) int readTries = 5*BLINK::PERIOD/sleep; int newSetTemp = UNDEF::INT; ESP.wdtFeed(); - delay(BLINK::PERIOD); do { delay(sleep); @@ -510,18 +509,22 @@ void PureSpaIO::setDesiredWaterTempCelsius(int temp) } else { - // success, check direction and change + // update change tries based on inital delta + if (setTemp == UNDEF::INT) + { + changeTries += abs(newSetTemp - temp); + } + + // change temperature by 1 degree setTemp = newSetTemp; if (temp > setTemp) { - if (!changeWaterTemp(+1)) - changeWaterTemp(+1); + changeWaterTemp(+1); changeTries--; } else if (temp < setTemp) { - if (!changeWaterTemp(-1)) - changeWaterTemp(-1); + changeWaterTemp(-1); changeTries--; } } @@ -682,6 +685,9 @@ bool PureSpaIO::waitBuzzerOff() const /** * change water temperature setpoint by 1 degree and wait for confirmation (blocking) * + * notes: + * - WiFi is temporarily put to sleep to improve receive decoding reliability + * * @param up press up (> 0) or down (< 0) button * @return true if beep was received, false if no beep was received until timeout */ @@ -689,36 +695,49 @@ bool PureSpaIO::changeWaterTemp(int up) { if (isPowerOn() && state.error == ERROR_NONE) { - // perform button action waitBuzzerOff(); //DEBUG_MSG("\nP "); + #ifndef FORCE_WIFI_SLEEP WiFi.setSleepMode(WIFI_LIGHT_SLEEP); #endif - int tries = BUTTON::ACK_TIMEOUT/BUTTON::ACK_CHECK_PERIOD; + + // perform button action + int tries = BUTTON::PRESS_SHORT_COUNT*CYCLE::PERIOD/BUTTON::ACK_CHECK_PERIOD; if (up > 0) { - buttons.toggleTempUp = BUTTON::PRESS_COUNT; + buttons.toggleTempUp = BUTTON::PRESS_SHORT_COUNT; while (buttons.toggleTempUp && tries) { delay(BUTTON::ACK_CHECK_PERIOD); tries--; } + buttons.toggleTempUp = 0; } else if (up < 0) { - buttons.toggleTempDown = BUTTON::PRESS_COUNT; + buttons.toggleTempDown = BUTTON::PRESS_SHORT_COUNT; while (buttons.toggleTempDown && tries) { delay(BUTTON::ACK_CHECK_PERIOD); tries--; } + buttons.toggleTempDown = 0; + } + + // wait for buzzer + tries = (BUTTON::PRESS_COUNT - BUTTON::PRESS_SHORT_COUNT)*CYCLE::PERIOD/BUTTON::ACK_CHECK_PERIOD; + while (!state.buzzer && tries) + { + delay(BUTTON::ACK_CHECK_PERIOD); + tries--; } + #ifndef FORCE_WIFI_SLEEP WiFi.setSleepMode(WIFI_NONE_SLEEP); #endif - if (tries && state.buzzer) + if (state.buzzer) { return true; } @@ -1117,96 +1136,62 @@ ICACHE_RAM_ATTR inline void PureSpaIO::decodeLED() } } -ICACHE_RAM_ATTR inline void PureSpaIO::decodeButton() +ICACHE_RAM_ATTR inline void PureSpaIO::updateButtonState(volatile unsigned int& buttonPressCount) { - if (isrState.frameValue & FRAME_BUTTON::FILTER) + if (buttonPressCount) { - //DEBUG_MSG("F"); - if (buttons.toggleFilter) + if (state.buzzer) + { + buttonPressCount = 0; + } + else { isrState.reply = true; - buttons.toggleFilter--; + buttonPressCount--; } } +} + +ICACHE_RAM_ATTR inline void PureSpaIO::decodeButton() +{ + if (isrState.frameValue & FRAME_BUTTON::FILTER) + { + //DEBUG_MSG("F"); + updateButtonState(buttons.toggleFilter); + } else if (isrState.frameValue & FRAME_BUTTON::HEATER) { //DEBUG_MSG("H"); - if (buttons.toggleHeater) - { - isrState.reply = true; - buttons.toggleHeater--; - } + updateButtonState(buttons.toggleHeater); } else if (isrState.frameValue & FRAME_BUTTON::BUBBLE) { //DEBUG_MSG("B"); - if (buttons.toggleBubble) - { - isrState.reply = true; - buttons.toggleBubble--; - //if (!buttons.toggleBubble) - //{ - // DEBUG_MSG("\nFBO"); - //} - } + updateButtonState(buttons.toggleBubble); } else if (isrState.frameValue & FRAME_BUTTON::POWER) { //DEBUG_MSG(" P"); - if (buttons.togglePower) - { - isrState.reply = true; - buttons.togglePower--; - } + updateButtonState(buttons.togglePower); } else if (isrState.frameValue & FRAME_BUTTON::TEMP_UP) { //DEBUG_MSG("U"); - if (buttons.toggleTempUp) - { - if (state.buzzer) - { - buttons.toggleTempUp = 0; - } - else - { - isrState.reply = true; - buttons.toggleTempUp--; - } - } + updateButtonState(buttons.toggleTempUp); } else if (isrState.frameValue & FRAME_BUTTON::TEMP_DOWN) { //DEBUG_MSG("D"); - if (buttons.toggleTempDown) - { - if (state.buzzer) - { - buttons.toggleTempDown = 0; - } - else - { - isrState.reply = true; - buttons.toggleTempDown--; - } - } + updateButtonState(buttons.toggleTempDown); } #ifdef MODEL_SJB_HS else if (isrState.frameValue & FRAME_BUTTON::DISINFECTION) { - if (buttons.toggleDisinfection) - { - isrState.reply = true; - buttons.toggleDisinfection--; - } + updateButtonState(buttons.toggleDisinfection); } else if (isrState.frameValue & FRAME_BUTTON::JET) { - if (buttons.toggleJet) - { - isrState.reply = true; - buttons.toggleJet--; - } + updateButtonState(buttons.toggleJet); } #endif else if (isrState.frameValue & FRAME_BUTTON::TEMP_UNIT) diff --git a/PureSpaIO.h b/PureSpaIO.h index a3e49e9..e9ffed6 100644 --- a/PureSpaIO.h +++ b/PureSpaIO.h @@ -77,33 +77,34 @@ * * telegram order: * - * 32 frames, repeating every 21 ms (5x digit 1-4, 5x LEDs, 1x buttons 1-7) + * 25 cue frames and 32/34 data frames (5x digit 1-4, 5x LEDs, 1x buttons 1-7/9), repeating every 21 ms * - * CD1 - * CD2 - * CD3 - * CD4 - * CL - * CD1 - * CD2 - * CD3 - * CD4 - * CL - * CD1 - * CD2 - * CD3 - * CD4 - * CL - * CD1 - * CD2 - * CD3 - * CD4 - * CL - * CD1 - * CD2 - * CD3 - * CD4 - * CBBBBBBBL + * C D1 + * C D2 + * C D3 + * C D4 + * C L + * C D1 + * C D2 + * C D3 + * C D4 + * C L + * C D1 + * C D2 + * C D3 + * C D4 + * C L + * C D1 + * C D2 + * C D3 + * C D4 + * C L + * C D1 + * C D2 + * C D3 + * C D4 + * C BBBBBBB L [SB-H20] + * C BBBBBBBBB L [SJB-HS] * * * Build Notes: @@ -196,40 +197,46 @@ class PureSpaIO class CYCLE { public: - static const unsigned int TOTAL_FRAMES = 32; // number of frames in each cycle - static const unsigned int DISPLAY_FRAMES = 5; // number of digit frame groups in each cycle - static const unsigned int PERIOD = 21; // ms, period of frame cycle +#if defined MODEL_SB_H20 + static const unsigned int BUTTON_FRAMES = 7; // number of button frames in each cycle +#elif defined MODEL_SJB_HS + static const unsigned int BUTTON_FRAMES = 9; // number of button frames in each cycle +#endif + static const unsigned int TOTAL_FRAMES = 25 + BUTTON_FRAMES; // number of frames in each cycle + static const unsigned int DISPLAY_FRAME_GROUPS = 5; // number of digit frame groups in each cycle + static const unsigned int PERIOD = 21; // ms, period of frame cycle @todo might be longer for SJB-HS static const unsigned int RECEIVE_TIMEOUT = 50*CYCLE::PERIOD; // ms }; class FRAME { public : - static const unsigned int BITS = 16; + static const unsigned int BITS = 16; // bits per frame static const unsigned int FREQUENCY = CYCLE::TOTAL_FRAMES/CYCLE::PERIOD; // frames/ms }; class BLINK { public: - static const unsigned int PERIOD = 500; // ms, temp will blink 8 times in 4000 ms - static const unsigned int TEMP_FRAMES = PERIOD/4*FRAME::FREQUENCY; // sample duration of desired temp after blank display + static const unsigned int PERIOD = 500; // ms, temp will blink 8 times in 4000 ms + static const unsigned int TEMP_FRAMES = PERIOD/4*FRAME::FREQUENCY; // sample duration of desired temp after blank display static const unsigned int STOPPED_FRAMES = 2*PERIOD*FRAME::FREQUENCY; // must be longer than single blink duration }; class CONFIRM_FRAMES { public: - static const unsigned int REGULAR = 3; // ms, for values which do not blink - static const unsigned int NOT_BLINKING = BLINK::PERIOD/2*FRAME::FREQUENCY/CYCLE::DISPLAY_FRAMES; // ms, must be high enough to tell from blinking + static const unsigned int REGULAR = 3; // frames, for values which do not blink + static const unsigned int NOT_BLINKING = BLINK::PERIOD/2*FRAME::FREQUENCY/CYCLE::DISPLAY_FRAME_GROUPS; // frames, must be high enough to tell from blinking }; class BUTTON { public: - static const unsigned int PRESS_COUNT = BLINK::PERIOD/CYCLE::PERIOD - 4; // must be long enough to trigger, but short enough to avoid double trigger - static const unsigned int ACK_CHECK_PERIOD = 10; // ms - static const unsigned int ACK_TIMEOUT = 2*PRESS_COUNT*CYCLE::PERIOD; // ms + static const unsigned int PRESS_COUNT = BLINK::PERIOD/CYCLE::PERIOD; // cycles, must be long enough to activate buzzer + static const unsigned int PRESS_SHORT_COUNT = 340/CYCLE::PERIOD; // cycles, must be long enough to trigger, but short enough to avoid double trigger + static const unsigned int ACK_CHECK_PERIOD = 10; // ms + static const unsigned int ACK_TIMEOUT = 2*PRESS_COUNT*CYCLE::PERIOD; // ms }; private: @@ -302,6 +309,7 @@ class PureSpaIO static ICACHE_RAM_ATTR inline void decodeDisplay(); static ICACHE_RAM_ATTR inline void decodeLED(); static ICACHE_RAM_ATTR inline void decodeButton(); + static ICACHE_RAM_ATTR inline void updateButtonState(volatile unsigned int& buttonPressCount); private: // ISR variables diff --git a/common.h b/common.h index 819ebc3..635e6db 100644 --- a/common.h +++ b/common.h @@ -51,7 +51,7 @@ namespace CONFIG { - const char WIFI_VERSION[] = "1.0.6.0"; // 23.07.2023 + const char WIFI_VERSION[] = "1.0.6.1"; // 24.07.2023 // WiFi parameters const unsigned long WIFI_MAX_DISCONNECT_DURATION = 900000; // [ms] 5 min until reboot