Skip to content

Commit

Permalink
Regulating temp using buttons.
Browse files Browse the repository at this point in the history
  • Loading branch information
MarPta committed Dec 14, 2022
1 parent 5c7b2cf commit 2dc9408
Show file tree
Hide file tree
Showing 3 changed files with 118 additions and 102 deletions.
15 changes: 9 additions & 6 deletions Soft/esp32_iot_thermostat/.vscode/extensions.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
{
// See http://go.microsoft.com/fwlink/?LinkId=827846
// for the documentation about the extensions.json format
"recommendations": [
"platformio.platformio-ide"
]
}
// See http://go.microsoft.com/fwlink/?LinkId=827846
// for the documentation about the extensions.json format
"recommendations": [
"platformio.platformio-ide"
],
"unwantedRecommendations": [
"ms-vscode.cpptools-extension-pack"
]
}
2 changes: 1 addition & 1 deletion Soft/esp32_iot_thermostat/platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ platform = espressif32
board = esp32dev
framework = arduino
monitor_speed = 115200

monitor_flags = --filter=esp32_exception_decoder
lib_deps =
https://github.com/adafruit/Adafruit_Sensor
https://github.com/adafruit/DHT-sensor-library
Expand Down
203 changes: 108 additions & 95 deletions Soft/esp32_iot_thermostat/src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,18 @@ const uint8_t dhtPin = 17;
const uint8_t displayCsPin = 14; // Chip selection output
const uint8_t displayWrPin = 27; // Read clock output
const uint8_t displayDataPin = 26; // Serial data output
const uint8_t DISPLAY_LED = 13;
const uint8_t displayLedPin = 13;
const uint8_t buttonUpPin = 5;
const uint8_t buttonDownPin = 18;
const uint8_t buttonOkPin = 19;
const uint16_t buttonPressDelay = 200; // [ms]
const uint16_t displayNightLightThreshold = 300; // 0-4096
const uint16_t displayNightLightMax = 80; // 0-1023
const uint16_t displayModDelay = 3000; // [ms]
const uint8_t defaultLowTemp = 10; // [°C]
const uint8_t defaultHighTemp = 20; // [°C]
const uint16_t displayNightLightMax = 80; // 0-1023
const uint16_t displayReturnDelay = 3000; // [ms]
const float defaultLowTemp = 10.0; // [°C]
const float defaultHighTemp = 20.0; // [°C]
const float desiredTempStep = 0.2; // [°C]
const uint8_t defaultHeatMode = 0;

// LED PWM properties
const uint16_t freq = 5000;
Expand All @@ -25,130 +31,137 @@ const uint8_t resolution = 10;

const uint8_t photoresistorPin = 35;
const uint8_t relayPin = 16;
const float desiredTempMax = 30.0; // [°C]
const float desiredTempMin = 5.0; // [°C]
const float hysteresisUpTemp = 0.3; // [°C]
const float hysteresisDownTemp = 0.3; // [°C]
const float desiredTempMax = 25.0; // [°C]
const float desiredTempMin = 3.0; // [°C]
const float hysteresisUpTemp = 0.5; // [°C]
const float hysteresisDownTemp = 0.5; // [°C]

struct stateVector{
float actualTemp = 0.0; // [°C]
float desiredTempLow = defaultLowTemp; // [°C]
float measuredTemp = 0.0; // [°C]
float measuredHum = 0.0; // [%]
int16_t measuredIlluminance = 0; // 12-bit reading
float desiredTempLow = defaultLowTemp; // [°C]
float desiredTempHigh = defaultHighTemp; // [°C]
bool heatHigh = false; // Choose desired temp: 0->desiredTempLow, 1->desiredTempHigh
float relHum = 0.0; // [%]
uint8_t heatMode = 0; // Select desired temp variable: 0-desiredTempLow, 1-desiredTempHigh
bool relayOn = false;
int16_t illuminance = 0; // 12-bit reading
int16_t displayBrightness = 0; // 10-bit output
uint8_t displayState = 0; // 0-measuredTemp, 1-desiredTemp
} currentStateVector;
uint8_t displayState = 0; // 0-measuredTemp, 1-desiredTemp
} sv;

DHT dht(dhtPin, DHT22);
Preferences flashPreferences;
Preferences preferencesCF;
OnOffRegulator heatRegulator;
HT1621_universal lcd(displayCsPin, displayWrPin, displayDataPin);
Encoder encoder1(1);

template <typename T>
T clamp(T value, T min, T max) {
if (value < min)
return min;
if (value > max)
return max;
return value;
}

void setup() {
Serial.begin(115200);

lcd.init();
digitalWrite(relayPin, 0);
dht.begin();
//digitalWrite(relayPin, false);
pinMode(relayPin, OUTPUT);
pinMode(DISPLAY_LED, OUTPUT);
pinMode(buttonUpPin, INPUT_PULLDOWN);
pinMode(buttonDownPin, INPUT_PULLDOWN);
pinMode(buttonOkPin, INPUT_PULLDOWN);

ledcSetup(ledChannel, freq, resolution);
ledcAttachPin(DISPLAY_LED, ledChannel);
ledcAttachPin(displayLedPin, ledChannel);
pinMode(displayLedPin, OUTPUT);

dht.begin();

flashPreferences.begin("desiredTemps", false); // RW-mode (second parameter false).
currentStateVector.desiredTempLow = flashPreferences.getFloat("desiredTempLow", defaultLowTemp);
currentStateVector.desiredTempHigh = flashPreferences.getFloat("desiredTempHigh", defaultHighTemp);
currentStateVector.heatHigh = flashPreferences.getBool("heatHigh", false);
flashPreferences.end();
preferencesCF.begin("settings", false);
sv.desiredTempLow = preferencesCF.getFloat("desiredTempLow", defaultLowTemp);
sv.desiredTempHigh = preferencesCF.getFloat("desiredTempHigh", defaultHighTemp);
sv.heatMode = preferencesCF.getBool("heatMode", defaultHeatMode);
preferencesCF.end();

heatRegulator.setParameters(hysteresisUpTemp, hysteresisDownTemp, desiredTempMax, desiredTempMin);
}

void loop() {

// Updating sensor data
float t = dht.readTemperature();
float h = dht.readHumidity();
if (isnan(h) || isnan(t)) {
Serial.println(F("Failed to read from DHT sensor!"));
}
else {
currentStateVector.actualTemp = t;
currentStateVector.relHum = h;
sv.measuredTemp = t;
sv.measuredHum = h;
}
sv.measuredIlluminance = analogRead(photoresistorPin);

// Automatic control
static float desiredTemp = 0.0;
if(sv.heatMode == 0) {
// Night mode
desiredTemp = sv.desiredTempLow;
}
else if(sv.heatMode == 1) {
// Day mode
desiredTemp = sv.desiredTempHigh;
}
sv.relayOn = heatRegulator.getRegAction(desiredTemp, sv.measuredTemp);

int16_t brightness = displayNightLightThreshold - sv.measuredIlluminance;
if(brightness < 0) {
brightness = 0;
}
else if(brightness > displayNightLightMax) {
brightness = displayNightLightMax;
}
currentStateVector.illuminance = analogRead(photoresistorPin);
sv.displayBrightness = brightness;

Serial.print("Temperature: ");
Serial.print(currentStateVector.actualTemp);
Serial.println(" *C");
Serial.println(currentStateVector.illuminance);
// Handle UI
bool buttonUpPressed = false;
bool buttonDownPressed = false;
bool buttonOkPressed = false;

Serial.print("Temp Low: ");
Serial.print(currentStateVector.desiredTempLow);
Serial.print(" Temp High: ");
Serial.print(currentStateVector.desiredTempHigh);
Serial.print(" HeatHigh: ");
Serial.println(currentStateVector.heatHigh);
static uint32_t buttonLastPressed = 0;

// Automatic control
if(currentStateVector.heatHigh)
currentStateVector.relayOn = heatRegulator.getRegAction(currentStateVector.desiredTempHigh, currentStateVector.actualTemp);
else
currentStateVector.relayOn = heatRegulator.getRegAction(currentStateVector.desiredTempLow, currentStateVector.actualTemp);

currentStateVector.displayBrightness = displayNightLightThreshold - currentStateVector.illuminance;
currentStateVector.displayBrightness = clamp<int>(currentStateVector.displayBrightness, 0, displayNightLightMax);

static uint32_t lastMovedEnc = 0;
switch(currentStateVector.displayState) {
case 0:
lcd.displayCelsius(currentStateVector.actualTemp);
if(encoder1.getDiff() != 0) {
currentStateVector.displayState = 1;
lastMovedEnc = millis();
}
break;
case 1:
int16_t diff = encoder1.getDiff();
if(diff != 0)
lastMovedEnc = millis();
if(currentStateVector.heatHigh == 0) {
currentStateVector.desiredTempLow += diff * 0.05;
currentStateVector.desiredTempLow = clamp<float>(currentStateVector.desiredTempLow, desiredTempMin, desiredTempMax);
lcd.displayCelsius(currentStateVector.desiredTempLow);
}
else {
currentStateVector.desiredTempHigh += diff * 0.05;
currentStateVector.desiredTempHigh = clamp<float>(currentStateVector.desiredTempHigh, desiredTempMin, desiredTempMax);
lcd.displayCelsius(currentStateVector.desiredTempHigh);
}
if(millis() > lastMovedEnc + displayModDelay) {
currentStateVector.displayState = 0;
}
break;
};

/*char message[20];
snprintf (message, 20, "%.1f", currentStateVector.actualTemp);
mqttClient.publish(tempTopic, message);*/
if(millis() > (buttonLastPressed + buttonPressDelay)) {
buttonUpPressed = digitalRead(buttonUpPin);
buttonDownPressed = digitalRead(buttonDownPin);
buttonOkPressed = digitalRead(buttonOkPin);
}

if(buttonUpPressed || buttonDownPressed || buttonOkPressed) {
buttonLastPressed = millis();
}
float tempChange = -desiredTempStep*buttonDownPressed + desiredTempStep*buttonUpPressed;

if(sv.displayState == 0) {
// Display measured temp
lcd.displayCelsius(sv.measuredTemp);

if(buttonUpPressed || buttonDownPressed || buttonOkPressed) {
sv.displayState = 1;
}
}
else if(sv.displayState == 1) {
// Display desired temp of the current heat mode
if(sv.heatMode == 0) {
sv.desiredTempLow += tempChange;
lcd.displayCelsius(sv.desiredTempLow);
}
else if(sv.heatMode == 1) {
sv.desiredTempHigh += tempChange;
lcd.displayCelsius(sv.desiredTempHigh);
}

if(millis() > buttonLastPressed + displayReturnDelay) {
// save selected temp
sv.displayState = 0;

preferencesCF.begin("settings", false);
preferencesCF.putFloat("desiredTempLow", sv.desiredTempLow);
preferencesCF.putFloat("desiredTempHigh", sv.desiredTempHigh);
preferencesCF.end();
}
}

// Updating actuators accoring to current StateVector variables
digitalWrite(relayPin, currentStateVector.relayOn);
ledcWrite(ledChannel, currentStateVector.displayBrightness);
digitalWrite(relayPin, !sv.relayOn);
ledcWrite(ledChannel, sv.displayBrightness);

delay(20);
delay(100);
}

0 comments on commit 2dc9408

Please sign in to comment.