You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
301 lines
7.0 KiB
301 lines
7.0 KiB
#include <Wire.h> |
|
#include <Adafruit_GFX.h> |
|
#include <Adafruit_SSD1306.h> |
|
|
|
#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<TEMP_QUEUE_LENGTH; i++){ |
|
byte barHeight = tempQueue.lookup(i); |
|
if(barHeight < minValue) barHeight = minValue; |
|
barHeight = map(barHeight, minValue, maxValue, 2, 58); |
|
display.fillRect(i * 2, SCREEN_HEIGHT - barHeight, 1, barHeight, WHITE); |
|
} |
|
} |
|
|
|
void alarmSettingState(byte bUp, byte bDown){ |
|
updateRelay(); |
|
|
|
if (bUp == 1) { |
|
alarmState = 0; |
|
} |
|
if (bDown == 1) { |
|
alarmState = -1; |
|
} |
|
|
|
displayCurrentTemp(); |
|
|
|
display.setTextSize(1); |
|
display.setCursor(0,40); |
|
display.print("Alarm temp: "); |
|
display.print(targetTemp + ALARM_TEMP_DELTA); |
|
display.print(" "); |
|
display.cp437(true); |
|
display.write(167); |
|
display.setTextSize(1); |
|
display.print("C"); |
|
|
|
display.setTextSize(2); |
|
display.setCursor(0,50); |
|
if (alarmState == -1){ |
|
display.print("Alarm OFF"); |
|
} else { |
|
display.print("Alarm ON"); |
|
} |
|
} |
|
|
|
void displayCurrentTemp(){ |
|
display.setTextSize(1); |
|
display.setCursor(0,10); |
|
display.print("Current: "); |
|
display.setTextSize(2); |
|
display.setCursor(0,20); |
|
display.print(airTempSensor.getTemperature()); |
|
display.print(" "); |
|
display.setTextSize(1); |
|
display.cp437(true); |
|
display.write(167); |
|
display.setTextSize(2); |
|
display.print("C"); |
|
}
|
|
|