123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299 |
- #include "AppCore.h"
-
- #define HIBERNATE_DELAY 5000
- #define SENSORS_CHECK_INTERVAL 2000
- #define SENSORS_REQUEST_DELAY 750
- #define TEMP_TRIGGER 10
- #define LCD_CHAR_SENSOR 1
-
- #define PIN_ONEWIRE 12
- #define PIN_BTN_MODE 11
- #define PIN_BTN_MINUS 10
- #define PIN_BTN_PLUS 9
- #define PIN_LCD_LED 8
- #define PIN_LCD_RS 7
- #define PIN_LCD_ENABLE 6
- #define PIN_LCD_D0 5
- #define PIN_LCD_D1 4
- #define PIN_LCD_D2 3
- #define PIN_LCD_D3 2
-
- #define BUTTONS_COUNT (sizeof(g_buttons) / sizeof(*g_buttons))
- #define MODE_SEQUENCE_COUNT (sizeof(m_modeSequence) / sizeof(*m_modeSequence))
-
- AppCore::AppCore()
- : m_appCoreState{
- .appState = {
- .lastSensorRequestMs = 0,
- .hasReadSensors = true,
- .water = {
- .current = TEMP_T_INVALID,
- .setting = 0,
- .isActive = false
- },
- .heater = {
- .current = TEMP_T_INVALID,
- .setting = 0,
- .isActive = false
- }
- },
- .uiState = {
- .state = Lighting,
- .lastOpMs = 0,
- .modeSequenceIndex = MODE_SEQUENCE_COUNT - 1,
- .isUpdateNeeded = true
- }
- }
- , m_modeSequence{WaterSetting, HeaterSetting, Lighting}
- , m_btnMode{PIN_BTN_MODE}
- , m_btnMinus{PIN_BTN_MINUS}
- , m_btnPlus{PIN_BTN_PLUS}
- , m_buttons{&m_btnMode, &m_btnMinus, &m_btnPlus}
- , m_lcd{PIN_LCD_RS, PIN_LCD_ENABLE, PIN_LCD_D0, PIN_LCD_D1, PIN_LCD_D2, PIN_LCD_D3}
- , m_oneWire{PIN_ONEWIRE}
- , m_sensors{&m_oneWire}
- , m_sensor1{0}
- {
- }
-
- void AppCore::setup()
- {
- m_sensors.begin();
- m_sensors.getAddress(m_sensor1, 0);
- m_sensors.setWaitForConversion(false);
-
- for (auto& g_button : m_buttons)
- {
- g_button->begin();
- }
-
- pinMode(PIN_LCD_LED, OUTPUT);
- digitalWrite(PIN_LCD_LED, 1);
-
- m_lcd.begin(16, 2);
- byte sensorChar[8] = {
- B00100,
- B01110,
- B01110,
- B01110,
- B01110,
- B11111,
- B11111,
- B01110,
- };
- m_lcd.createChar(LCD_CHAR_SENSOR, sensorChar);
-
- Serial.begin(9600);
-
- bool allButtonsPressed = true;
- for (auto& g_button : m_buttons)
- {
- allButtonsPressed = allButtonsPressed && g_button->isPressed();
- }
- if (!allButtonsPressed)
- {
- m_storage.load(m_appCoreState);
- }
- else
- {
- m_storage.save(m_appCoreState);
- }
- }
-
- void AppCore::loop()
- {
- const auto& currentMs = millis();
-
- if (currentMs - m_appCoreState.appState.lastSensorRequestMs >= SENSORS_CHECK_INTERVAL)
- {
- m_appCoreState.appState.lastSensorRequestMs = currentMs;
- m_appCoreState.appState.hasReadSensors = false;
- m_sensors.requestTemperaturesByAddress(m_sensor1);
- }
- if (currentMs - m_appCoreState.appState.lastSensorRequestMs >= SENSORS_REQUEST_DELAY &&
- !m_appCoreState.appState.hasReadSensors)
- {
- m_appCoreState.appState.hasReadSensors = true;
- auto raw = m_sensors.getTempC(m_sensor1);
- temp_t temp = TEMP_T_INVALID;
- if (raw != DEVICE_DISCONNECTED_C)
- {
- temp = (temp_t) (raw * 2);
- }
-
- if (temp != m_appCoreState.appState.water.current)
- {
- m_appCoreState.appState.water.current = temp;
- m_appCoreState.uiState.isUpdateNeeded = true;
- }
- }
-
-
- for (auto& pButton : m_buttons)
- {
- pButton->read();
- if (pButton->isPressed())
- {
- m_appCoreState.uiState.lastOpMs = currentMs;
- break;
- }
- }
-
-
- if (m_appCoreState.uiState.state == Hibernate)
- {
- for (auto& pButton : m_buttons)
- {
- if (pButton->wasReleased())
- {
- setState(Lighting);
- break;
- }
- }
- }
- else
- {
- if (currentMs - m_appCoreState.uiState.lastOpMs >= HIBERNATE_DELAY)
- {
- setState(Hibernate);
- }
- else
- {
- if (m_btnMode.wasReleased())
- {
- m_appCoreState.uiState.modeSequenceIndex =
- (m_appCoreState.uiState.modeSequenceIndex + 1) % MODE_SEQUENCE_COUNT;
- setState(m_modeSequence[m_appCoreState.uiState.modeSequenceIndex]);
- }
- else if (m_btnMinus.wasReleased() || m_btnPlus.wasReleased())
- {
- BoilerItemState* itemState = nullptr;
- if (m_appCoreState.uiState.state == WaterSetting)
- {
- itemState = &m_appCoreState.appState.water;
- }
- else if (m_appCoreState.uiState.state == HeaterSetting)
- {
- itemState = &m_appCoreState.appState.heater;
- }
-
- if (itemState)
- {
- if (m_btnMinus.wasReleased())
- {
- --itemState->setting;
- }
- else if (m_btnPlus.wasReleased())
- {
- ++itemState->setting;
- }
- m_appCoreState.uiState.isUpdateNeeded = true;
- }
- }
- }
- }
-
- checkBoilerItem(m_appCoreState.appState.water);
- checkBoilerItem(m_appCoreState.appState.heater);
-
- if (m_appCoreState.uiState.isUpdateNeeded)
- {
- printState();
- }
- }
-
- void AppCore::setState(
- UiStateEnum state
- )
- {
- char tmp[50];
- snprintf(tmp, sizeof(tmp), "Changing state %i => %i", m_appCoreState.uiState.state, state);
- Serial.println(tmp);
-
- if (state == Lighting)
- {
- digitalWrite(PIN_LCD_LED, 1);
- }
- else if (state == Hibernate)
- {
- digitalWrite(PIN_LCD_LED, 0);
- m_appCoreState.uiState.modeSequenceIndex = MODE_SEQUENCE_COUNT - 1;
- m_storage.save(m_appCoreState);
- }
- m_appCoreState.uiState.state = state;
- m_appCoreState.uiState.isUpdateNeeded = true;
- }
-
- void AppCore::checkBoilerItem(
- BoilerItemState& boilerItemState
- )
- {
- if (!boilerItemState.isActive && boilerItemState.current != TEMP_T_INVALID &&
- boilerItemState.current <= boilerItemState.setting - TEMP_TRIGGER)
- {
- boilerItemState.isActive = true;
- m_appCoreState.uiState.isUpdateNeeded = true;
- }
- else if (boilerItemState.isActive &&
- (boilerItemState.current == TEMP_T_INVALID || boilerItemState.current >= boilerItemState.setting))
- {
- boilerItemState.isActive = false;
- m_appCoreState.uiState.isUpdateNeeded = true;
- }
- }
-
- void AppCore::printState()
- {
- Serial.println("Updating display");
-
- m_lcd.setCursor(0, 0);
- printStateLine('S', m_appCoreState.appState.water, m_appCoreState.uiState.state == WaterSetting,
- m_appCoreState.appState.water.isActive);
- m_lcd.setCursor(0, 1);
- printStateLine('C', m_appCoreState.appState.heater, m_appCoreState.uiState.state == HeaterSetting,
- m_appCoreState.appState.heater.isActive);
- m_appCoreState.uiState.isUpdateNeeded = false;
- }
-
- void
- AppCore::printStateLine(
- char prefix
- , const BoilerItemState& boilerItemState
- , bool isModifying
- , bool isActive
- )
- {
- char curTmp[7], setTmp[7], tmp[17];
- tempToStr(curTmp, boilerItemState.current);
- tempToStr(setTmp, boilerItemState.setting);
- int count = snprintf(tmp, sizeof(tmp), "%c: %s [%s]%c%c", prefix, curTmp, setTmp, isModifying ? '<' : ' ',
- isActive ? LCD_CHAR_SENSOR : ' ');
- for (; count < 17; ++count)
- {
- tmp[count] = ' ';
- }
- tmp[count] = 0;
- m_lcd.print(tmp);
- }
-
- void AppCore::tempToStr(
- char* out
- , temp_t temp
- )
- {
- if (temp == TEMP_T_INVALID)
- {
- strcpy(out, " -- ");
- }
- else
- {
- char tmp[7];
- dtostrf(temp / 2.0f, 2, 1, tmp);
- auto len = 4 - strlen(tmp);
- for (auto i = 0; i < len; ++i)
- {
- out[i] = ' ';
- }
- strcpy(&out[len], tmp);
- }
- }
|