#include #include #include #include "button.h" #include "relay.h" #include "temperature_sensor.h" #include "queue.h" #define AIR_TEMP_SENSOR_PIN A1 #define RELAY_PIN 6 #define SPEAKER_PIN 7 #define BUTTON_RIGHT_PIN 8 #define BUTTON_LEFT_PIN 9 #define BUTTON_DOWN_PIN 10 #define BUTTON_UP_PIN 11 #define MAX_STATE 4 // Amount of display states #define SCREEN_WIDTH 128 // OLED display width, in pixels #define SCREEN_HEIGHT 64 // OLED display height, in pixels #define TEMP_DELTA 4 // Minimum temperature difference before relay is toggled #define ALARM_TEMP_DELTA 15 // Minimum temperature difference before the alarm wil sound #define TEMP_PLOT_INTERVAL 60000 // Amount of milliseconds between temperature measuring points in the plot byte state = 0; int targetTemp = 70; int alarmState = 0; long lastTempQueue = -1000000; Button buttonUp(BUTTON_UP_PIN); Button buttonDown(BUTTON_DOWN_PIN); Button buttonLeft(BUTTON_LEFT_PIN); Button buttonRight(BUTTON_RIGHT_PIN); Relay relay(RELAY_PIN); // Pass pin, reference voltage, and a,b,c coefficients TemperatureSensor airTempSensor(AIR_TEMP_SENSOR_PIN, 10000, 0.0010626977757858514, 0.00025567427237838396, -8.706543235296982e-8); // Declaration for an SSD1306 display connected to I2C (SDA, SCL pins) Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1); Queue tempQueue; void setup() { //Serial.begin(9600); if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { //Serial.println(F("SSD1306 allocation failed")); for(;;); } display.setRotation(2); display.clearDisplay(); display.setTextColor(WHITE); airTempSensor.preload(); } void loop() { updateAirTemp(); byte bUp = buttonUp.getState(); byte bDown = buttonDown.getState(); byte bLeft = buttonLeft.getState(); byte bRight = buttonRight.getState(); if (bRight >= 1){ if(state >= MAX_STATE) state = 0; else state += 1; } if (bLeft >= 1){ if(state <= 0) state = MAX_STATE; else state -= 1; } display.clearDisplay(); displayMenuBar(); switch (state) { case 0: targetTempState(bUp, bDown); break; case 1: manualState(bUp, bDown); break; case 2: uptimeState(bUp, bDown); break; case 3: tempPlotState(bUp, bDown); break; case 4: alarmSettingState(bUp, bDown); break; } display.display(); } void updateAirTemp(){ airTempSensor.update(); if(millis() - lastTempQueue > TEMP_PLOT_INTERVAL){ tempQueue.push(airTempSensor.getTemperature()); lastTempQueue = millis(); } } void updateRelay(){ float temperature = airTempSensor.getTemperature(); if (temperature - targetTemp >= TEMP_DELTA){ //Temp too high relay.off(); } else if (targetTemp - temperature >= TEMP_DELTA) { //Temp too low relay.on(); } if(temperature - targetTemp >= ALARM_TEMP_DELTA){ int second = millis() % 1000; if(alarmState == 0 and second < 100){ alarmState = 1; tone(SPEAKER_PIN, 440, 400); } if(alarmState == 1 and second > 500 and second < 600){ alarmState = 0; tone(SPEAKER_PIN, 554, 400); } } } void targetTempState(byte bUp, byte bDown){ updateRelay(); switch(bUp){ case 1: targetTemp +=1; break; case 2: targetTemp +=1; break; case 3: targetTemp +=3; break; } switch(bDown){ case 1: targetTemp -=1; break; case 2: targetTemp -=1; break; case 3: targetTemp -=3; break; } displayCurrentTemp(); // Target Temp display.setTextSize(1); display.setCursor(0,40); display.print("Target: "); display.setTextSize(2); display.setCursor(0,50); display.print(targetTemp); display.print(" "); display.setTextSize(1); display.cp437(true); display.write(167); display.setTextSize(2); display.print("C"); //display.drawRect(0, 0, display.width(), display.height(), SSD1306_WHITE); } void manualState(byte bUp, byte bDown) { if (bUp == 1) { relay.on(); } if (bDown == 1) { relay.off(); } displayCurrentTemp(); display.setTextSize(1); display.setCursor(0,40); display.print("Manual Mode"); display.setTextSize(2); display.setCursor(0,50); if (relay.getState()){ display.print("Heater ON"); } else { display.print("Heater OFF"); } } void uptimeState(byte bUp, byte bDown){ updateRelay(); unsigned int seconds = millis()/1000; //convect milliseconds to seconds unsigned int minutes=seconds/60; //convert seconds to minutes unsigned int hours=minutes/60; //convert minutes to hours seconds=seconds-(minutes*60); //subtract the coverted seconds to minutes in order to display 59 secs max minutes=minutes-(hours*60); //subtract the coverted minutes to hours in order to display 59 minutes max displayCurrentTemp(); display.setTextSize(1); display.setCursor(0,40); display.print("Uptime:"); display.setTextSize(2); display.setCursor(0,50); if(hours < 10) display.print(0); display.print(hours); display.print(":"); if(minutes < 10) display.print(0); display.print(minutes); display.print(":"); if(seconds < 10) display.print(0); display.print(seconds); } void displayMenuBar(){ byte space = display.width() / (MAX_STATE + 1); for (byte i = 0; i < MAX_STATE + 1; i++){ if (i == state) display.fillCircle(space * i + space / 2, 3, 3, WHITE); else display.drawCircle(space * i + space / 2, 3, 3, WHITE); } } void tempPlotState(byte bUp, byte bDown){ updateRelay(); byte maxValue = tempQueue.getMax(); byte minValue = tempQueue.getMin(); if(minValue > 99) minValue = 99; display.setTextSize(1); if(maxValue > 99)display.setCursor(110,8); else display.setCursor(116,8); display.print(maxValue); display.setCursor(116,57); display.print(minValue); if(maxValue - minValue < 10){ minValue -= 1; maxValue += 1; } for (int i=0; i