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.

302 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");
}