#include <Arduino.h>
#include <U8g2lib.h> //U8G2
#include <Wire.h> // library for IIC communication
#include <dht.h> // DHTLib
#include <Adafruit_Debounce.h> // Adafruit Debounce
// Pins
#define ssButtonPin 0
#define mtButtonPin 1
#define upButtonPin 2
#define dnButtonPin 3
#define nxButtonPin 4
#define dhtSensorPin 5
#define relayPin 6
// end Pins
// buttons
Adafruit_Debounce SSButton(ssButtonPin, LOW); // Start/Stop button
Adafruit_Debounce MTButton(mtButtonPin, LOW); // Material button
Adafruit_Debounce UPButton(upButtonPin, LOW); // Up button
Adafruit_Debounce DNButton(dnButtonPin, LOW); // Down button
Adafruit_Debounce NXButton(nxButtonPin, LOW); // Next button
// end buttons
// Display
U8G2_SSD1306_128X64_NONAME_F_HW_I2C oled(U8G2_R0, /* reset=*/U8X8_PIN_NONE); // initialization for the used OLED display
unsigned long lastDisplay = 0;
static const unsigned char image_Star[] U8X8_PROGMEM = { 0x49, 0x2a, 0x1c, 0x7f, 0x1c, 0x2a, 0x49 };
static const unsigned char image_Temperature[] U8X8_PROGMEM = { 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x40, 0x01, 0x40, 0x01, 0x40, 0x01, 0x40, 0x01, 0x40, 0x01, 0x40, 0x01, 0x20, 0x02, 0xe0, 0x03, 0xe0, 0x03, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
static const unsigned char image_Humidity[] U8X8_PROGMEM = { 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0xc0, 0x03, 0xe0, 0x07, 0xf0, 0x0f, 0xf0, 0x0f, 0xf8, 0x1f, 0xf8, 0x1f, 0xd8, 0x1f, 0xd8, 0x1f, 0x98, 0x1f, 0x70, 0x0e, 0xe0, 0x07, 0x80, 0x01, 0x00, 0x00 };
// three dots
byte dotCount = 0;
const char *dots[] = { " ", ".", "..", "..." };
unsigned long lastDot = 0;
char buffer[32]; // helper buffer to construct a string to be displayed
// end Display
// Delay
unsigned long delayTime = 70; // 70 sec
unsigned long delayStart = 0; // the time the delay started
bool delayRunning = false; // true if still waiting for delay to finish
// end Deiay
// DHT
dht DHT;
int CurTemp = 0;
int CurHum = 0;
unsigned long lastDHT = 0;
// end DHT
// Settings
// material table
typedef struct {
char matherial[8];
byte temp_low;
byte temp_high;
unsigned long duration;
} MatTempDur_t;
const MatTempDur_t Settings[8] PROGMEM = {
{ "TPU", 40, 45, 14400 },
{ "PLA", 40, 50, 14400 },
{ "PETG", 60, 65, 14400 },
{ "ABS", 65, 75, 14400 },
{ "Nylon", 75, 90, 14400 },
{ "ASA", 80, 85, 14400 },
{ "PC", 80, 90, 25200 },
{ "Custom", 0, 0, 14400 }
};
byte matSel = 0;
char curMat[8] = "";
byte curTempLow = 0;
byte curTempHigh = 0;
// underscores
typedef struct {
byte x1;
byte x2;
byte y;
} Underscores_t;
const Underscores_t Underscores[4] PROGMEM = {
{ 85, 95, 10 },
{ 100, 110, 10 },
{ 85, 95, 32 },
{ 102, 111, 32 }
};
byte curUnderscore = 0;
// Relay status
bool RelayOn;
//
void setup() {
SSButton.begin();
MTButton.begin();
UPButton.begin();
DNButton.begin();
NXButton.begin();
Serial.begin(115200); // Any baud rate should work
Serial.println(F("setup - init"));
oled.begin();
// setup display
oled.setFont(u8g2_font_helvB08_tf);
oled.clearBuffer(); // clear the internal memory
oled.setFont(u8g2_font_helvB08_tf);
sprintf_P(buffer, PSTR("FilaDry"));
oled.drawStr(48, 20, buffer);
sprintf_P(buffer, PSTR("v1.0"));
oled.drawStr(52, 38, buffer);
oled.setFont(u8g2_font_helvR08_tf);
sprintf_P(buffer, PSTR("[email protected]"));
oled.drawStr(10, 58, buffer);
oled.sendBuffer();
delay(5000);
// get settings
strcpy_P(curMat, Settings[matSel].matherial);
curTempLow = pgm_read_byte(&Settings[matSel].temp_low);
curTempHigh = pgm_read_byte(&Settings[matSel].temp_high);
delayTime = pgm_read_dword(&Settings[matSel].duration);
// setup Temp/Hum display
int chk = DHT.read22(dhtSensorPin);
if (chk == DHTLIB_OK) {
CurTemp = (int)DHT.temperature;
CurHum = (int)DHT.humidity;
}
lastDHT = millis();
// setup relay
digitalWrite(relayPin, HIGH);
RelayOn = false;
pinMode(relayPin, OUTPUT);
}
void loop() {
processButtons();
processDHT();
checkDelay(); // call the led task may just return
controlRelay();
display();
}
void processButtons() {
//Start/Stop
SSButton.update();
if (SSButton.justPressed()) {
startStopDelay();
delay(25); // Add a small debouncing delay
}
if (!delayRunning) {
// Material
MTButton.update();
if (MTButton.justPressed()) {
buttonMat();
delay(25); // Add a small debouncing delay
}
// Up
UPButton.update();
if (UPButton.justPressed()) {
buttonUp();
delay(25); // Add a small debouncing delay
}
//Down
DNButton.update();
if (DNButton.justPressed()) {
buttonDn();
delay(25); // Add a small debouncing delay
}
//Next item
NXButton.update();
if (NXButton.justPressed()) {
buttonNx();
delay(25); // Add a small debouncing delay
}
}
}
void processDHT() {
if (millis() - lastDHT >= 10 * 1000UL) {
int chk = DHT.read22(dhtSensorPin);
if (chk == DHTLIB_OK) {
CurTemp = (int)DHT.temperature;
CurHum = (int)DHT.humidity;
}
lastDHT = millis();
}
}
void startStopDelay() {
// start delay
if (delayRunning) {
delay(100);
delayRunning = false;
} else {
delay(100);
delayStart = millis();
delayRunning = true;
}
}
void buttonMat() {
matSel += 1;
if (matSel > 7) { matSel = 0; }
strcpy_P(curMat, Settings[matSel].matherial);
curTempLow = pgm_read_byte(&Settings[matSel].temp_low);
curTempHigh = pgm_read_byte(&Settings[matSel].temp_high);
delayTime = pgm_read_dword(&Settings[matSel].duration);
}
void buttonUp() {
// curUnderscore positions
// 0 - hours
// 1 - minutes
// 2 - low temp
// 3 - high temp
switch (curUnderscore) {
case 0:
if (delayTime <= 82800) { delayTime += 3600; }
break;
case 1:
if (delayTime <= 86340) { delayTime += 60; }
break;
case 2:
curTempLow += 1;
if (curTempLow >= 90) { curTempLow = 90; }
break;
case 3:
curTempHigh += 1;
if (curTempHigh >= 90) { curTempHigh = 90; }
break;
}
}
void buttonDn() {
// curUnderscore positions
// 0 - hours
// 1 - minutes
// 2 - low temp
// 3 - high temp
switch (curUnderscore) {
case 0:
if (delayTime >= 3600) { delayTime -= 3600; }
break;
case 1:
if (delayTime >= 60) { delayTime -= 60; }
break;
case 2:
if (curTempLow <= 25) {
curTempLow = 25;
} else {
curTempLow -= 1;
}
break;
case 3:
if (curTempHigh <= 25) {
curTempHigh = 25;
} else {
curTempHigh -= 1;
}
break;
}
}
void buttonNx() {
curUnderscore += 1;
if (curUnderscore > 3) { curUnderscore = 0; }
}
void controlRelay() {
// relay is active-low
if (delayRunning) {
if (CurTemp <= curTempLow) {
digitalWrite(relayPin, LOW);
RelayOn = true;
} else {
if (CurTemp >= curTempHigh) {
digitalWrite(relayPin, HIGH);
RelayOn = false;
}
}
} else {
digitalWrite(relayPin, HIGH);
RelayOn = false;
}
}
void checkDelay() {
// check if delay has timed out
if (delayRunning && ((millis() - delayStart) / 1000 >= delayTime)) {
delayRunning = false; // finished delay -- single shot, once only
}
}
void display() {
if (millis() - lastDisplay >= 250UL) { // refresh display every 500ms
oled.clearBuffer(); // clear the internal memory
// 1st row
oled.setFont(u8g2_font_helvB08_tf);
if (delayRunning) {
unsigned long tme = (delayTime - (millis() - delayStart) / 1000); //Time we are converting. This can be passed from another function.
int sec = tme % 60;
tme=(tme-sec)/60;
int mins = tme % 60;
tme=(tme-mins)/60;
int hr = tme;
// status line
sprintf_P(buffer, PSTR("%S %s"), F("Drying"), dots[dotCount]);
oled.drawStr(0, 8, buffer);
oled.setFont(u8g2_font_helvR08_tf);
if (millis() - lastDot >= 1 * 1000UL) {
dotCount += 1;
if (dotCount > 4) {
dotCount = 0;
}
lastDot = millis();
}
if (RelayOn) {
oled.setBitmapMode(1);
oled.drawXBMP(63, 0, 7, 7, image_Star);
}
// time left
sprintf_P(buffer, PSTR("%02d:%02d:%02d"), hr, mins, sec);
oled.drawStr(85, 8, buffer);
} else {
unsigned long tme = delayTime;
int sec = tme % 60;
tme=(tme-sec)/60;
int mins = tme % 60;
tme=(tme-mins)/60;
int hr = tme;
sprintf_P(buffer, PSTR("%S"), F("Ready"));
oled.drawStr(0, 8, buffer);
oled.setFont(u8g2_font_helvR08_tf);
// time left
sprintf_P(buffer, PSTR("%02d:%02d:%02d"), hr, mins, sec);
oled.drawStr(85, 8, buffer);
// underscores
if (matSel == 7) {
oled.drawLine(pgm_read_byte(&Underscores[curUnderscore].x1), pgm_read_byte(&Underscores[curUnderscore].y), pgm_read_byte(&Underscores[curUnderscore].x2), pgm_read_byte(&Underscores[curUnderscore].y));
}
}
// end of 1st row
// matherial
sprintf_P(buffer, PSTR("%s"), curMat);
oled.drawStr(0, 30, buffer);
sprintf_P(buffer, PSTR("%02d-%02d %cC"), curTempLow, curTempHigh, '\xb0');
oled.drawStr(85, 30, buffer);
// cur temp hum
oled.drawXBMP(0, 48, 16, 16, image_Temperature);
oled.drawXBMP(58, 48, 16, 16, image_Humidity);
oled.setFont(u8g2_font_helvB08_tf);
sprintf_P(buffer, PSTR("%02d %cC"), CurTemp, '\xb0');
oled.drawStr(17, 60, buffer);
sprintf_P(buffer, PSTR("%02d %%"), CurHum);
oled.drawStr(79, 60, buffer);
oled.sendBuffer();
lastDisplay = millis();
}
}