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
302 lines
7.0 KiB
4 years ago
|
#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");
|
||
|
}
|