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.

307 lines
7.2 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() {
pinMode(SPEAKER_PIN, OUTPUT);
digitalWrite(SPEAKER_PIN, LOW);
//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;
digitalWrite(SPEAKER_PIN, HIGH);
} else if (alarmState == 1 and second > 500 and second < 600) {
alarmState = 0;
digitalWrite(SPEAKER_PIN, LOW);
} else if (alarmState == -1) {
digitalWrite(SPEAKER_PIN, LOW);
}
} else {
digitalWrite(SPEAKER_PIN, LOW);
}
}
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");
}