#include #include #include #include #include #include #include <./User_Setup.h> #include "SPI.h" #include "Adafruit_GFX.h" //#include "./PDQ_ILI9341_config.h" //#include "PDQ_GFX.h" //#include "PDQ_ILI9341.h" #include "SD.h" // For the Adafruit shield, these are the default. #define TFT_DC 48 #define TFT_CS 49 #define DHTPIN 32 // Digital pin connected to the DHT sensor // Feather HUZZAH ESP8266 note: use pins 3, 4, 5, 12, 13 or 14 -- // Pin 15 can work but DHT must be disconnected during program upload. // Uncomment whatever type you're using! //#define DHTTYPE DHT11 // DHT 11 #define DHTTYPE DHT22 // DHT 22 (AM2302), AM2321 //#define DHTTYPE DHT21 // DHT 21 (AM2301) // Connect pin 1 (on the left) of the sensor to +5V // NOTE: If using a board with 3.3V logic like an Arduino Due connect pin 1 // to 3.3V instead of 5V! // Connect pin 2 of the sensor to whatever your DHTPIN is // Connect pin 4 (on the right) of the sensor to GROUND // Connect a 10K resistor from pin 2 (data) to pin 1 (power) of the sensor // Initialize DHT sensor. // Note that older versions of this library took an optional third parameter to // tweak the timings for faster processors. This parameter is no longer needed // as the current DHT reading algorithm adjusts itself to work on faster procs. DHT dht(DHTPIN, DHTTYPE); // Use hardware SPI (on Uno, #13, #12, #11) and the above for CS/DC TFT_ILI9341 tft = TFT_ILI9341(); extern "C" char __data_start[]; // start of SRAM data extern "C" char _end[]; // end of SRAM data (used to check amount of SRAM this program's variables use) extern "C" char __data_load_end[]; // end of FLASH (used to check amount of Flash this program's code and data uses) EveryTimer batteryupd; EveryTimer water; #include #include #include #include #include "Adafruit_seesaw.h" Adafruit_seesaw soil1; Adafruit_seesaw soil2; Adafruit_seesaw soil3; Adafruit_seesaw soil4; word pin00 = 0; word pin01 = 1; word pin02 = 2; word pin03 = 3; word pin04 = 4; word pin05 = 5; word pin06 = 6; word pin07 = 7; word pin08 = 8; word pin09 = 9; word pin10 = 10; word pin11 = 11; word pin12 = 12; word led = 13; word pin14 = 14; word pin15 = 15; word pin16 = 16; word pin17 = 17; word pin18 = 18; word SD_CS = 19; word pin20 = 20; word pin21 = 21; word pin22 = 22; word pin23 = 23; word pin24 = 24; word pin25 = 25; word pin26 = 26; word pin27 = 27; word pin28 = 28; word pin29 = 29; //word pin30 = 30; //word pin31 = 31; word pin32 = 32; word pin33 = 33; word pin34 = 34; word pin35 = 35; word pin36 = 36; word pin37 = 37; word pin38 = 38; word pin39 = 39; word pin40 = 40; word pin41 = 41; word pin42 = 42; word pin43 = 43; word pin44 = 44; word pin45 = 45; word pin46 = 46; word pin47 = 47; word pin48 = 48; word pin49 = 49; word pin50 = 50; word pin51 = 51; word pin52 = 52; word pin53 = 53; //word LCD_RD = A0; //word LCD_WR = A1; //word LCD_CD = A2; //word LCD_CS = A3; word pinA4 = A4; word pinA5 = A5; word pinA6 = A6; word pinA7 = A7; word pinA8 = A8; word pinA9 = A9; word pinA10 = A10; word pinA11 = A11; word pinA12 = A12; word pinA13 = A13; word pinA14 = A14; word pinA15 = A15; #define BLACK 0x0000 #define BLUE 0x001F #define RED 0xF800 #define GREEN 0x07E0 #define CYAN 0x07FF #define MAGENTA 0xF81F #define YELLOW 0xFFE0 #define WHITE 0xFFFF #define YP A4 #define XM A5 #define YM 30 #define XP 31 #define TS_MINX 100 #define TS_MINY 150 #define TS_MAXX 900 #define TS_MAXY 900 TouchScreen ts = TouchScreen(XP, YP, XM, YM, 333); boolean fani = false; boolean fano = false; String outtext = ""; String oldtext = ""; boolean fastboot = false; boolean debug; int menu = 0; boolean ps3 = false; boolean upd = true; boolean s1, s2, s3, s4; String outtext2 = ""; int linecount = 0; int brightness = 255; int uda[] = {45, 70, 20, 20, 300}; int sla[] = {10, 90, 300, 280}; int go = true; int trange[] = {60, 100}; int hrange[] = {55, 85}; boolean b1[] = {true, false}; boolean b2[] = {true, false}; boolean b3[] = {true, false}; boolean b4[] = {true, false}; int ud1[] = {200, 50, uda[2], 20, 300}; int ud2[] = {200, 50, uda[2], 20, 300}; int ud3[] = {200, 50, uda[2], 20, 300}; int ud4[] = {200, 50, uda[2], 20, 300}; int dispbox = 0; int udd1[] = {45, 30, 90, 0, 100}; int udd2[] = {45, 65, 80, 0, 100}; int udd3[] = {45 + 160, 30, 85, 40, 150}; int udd4[] = {45 + 160, 65, 65, 40, 150}; boolean daytime = true; int udn1[] = {45, 30, 75, 0, 100}; int udn2[] = {45, 65, 65, 0, 100}; int udn3[] = {45 + 160, 30, 80, 40, 150}; int udn4[] = {45 + 160, 65, 65, 40, 150}; void setup(void) { batteryupd.Every(10000, checkBat); water.Every(1800000, runWater); debug = true; pinMode(2, OUTPUT); digitalWrite(2, HIGH); pinMode(3, OUTPUT); digitalWrite(3, HIGH); pinMode(4, OUTPUT); digitalWrite(4, HIGH); pinMode(5, OUTPUT); digitalWrite(5, HIGH); pinMode(9, INPUT_PULLUP); // water level pins pinMode(34, INPUT_PULLUP); pinMode(35, INPUT_PULLUP); pinMode(36, INPUT_PULLUP); pinMode(37, INPUT_PULLUP); // FAN pins pinMode(30, OUTPUT); // IN pinMode(31, OUTPUT); // OUT setTime(0); Serial.begin(9600); dht.begin(); //tft.reset(); #if defined(ILI9341_RST_PIN) // reset like Adafruit does FastPin::setOutput(); FastPin::hi(); FastPin::lo(); delay(1); FastPin::hi(); #endif tft.begin(); //tft.reset(); tft.setRotation(1); boolean didDraw = true; if(!fastboot) { //if (SD.begin(SD_CS)) { //tft.fillScreen(ILI9341_WHITE); //bmpDraw("gbs.bmp", 0, 0); //delay(4000); //} else { didDraw = false; // } tft.fillScreen(ILI9341_WHITE); //yield(); //tft.fillRect(0, 0, 320, 23, ILI9341_BLACK); } clearLog(); printFastCText("Booting GreenhouseOS..."); printFastCText("Version: 0.4.1"); printFastCText(""); delay(250); if(!didDraw) { printFastCText("[FAILED] SD Card not detected!"); } printFastCText("[ OK ] Enabling powersaving features... "); // 53 characters wide example enablePS(0); pinMode(A0, INPUT); upd = true; if (!soil1.begin(0x36)) { printFastCText("[ INFO ] Soil sensor 1 unplugged."); s1 = false; } else { String out = "[ OK ] Soil sensor 1 connected. Version: "; out += (soil1.getVersion(), HEX); printFastCText(out); s1 = true; } if (!soil2.begin(0x37)) { printFastCText("[ INFO ] Soil sensor 2 unplugged."); s2 = false; } else { String out = "[ OK ] Soil sensor 2 connected. Version: "; out += (soil2.getVersion(), HEX); printFastCText(out); s2 = true; } if (!soil3.begin(0x38)) { printFastCText("[ INFO ] Soil sensor 3 unplugged."); s3 = false; } else { String out = "[ OK ] Soil sensor 3 connected. Version: "; out += (soil3.getVersion(), HEX); printFastCText(out); s3 = true; } if (!soil4.begin(0x39)) { printFastCText("[ INFO ] Soil sensor 4 unplugged."); s4 = false; } else { String out = "[ OK ] Soil sensor 4 connected. Version: "; out += (soil4.getVersion(), HEX); printFastCText(out); s4 = true; } debug = false; //getMoisture(); tft.fillScreen(ILI9341_BLACK); tft.fillRect(0, 0, 160, 20, ILI9341_WHITE); tft.setTextFont(4); tft.setTextColor(ILI9341_BLACK); String out = "Water Level:"; tft.drawString(out.c_str(), 2, 2, 2); //drawButton(0, 20, 160, 110, "Settings", "ILI9341_YELLOW"); //drawButton(160, 20, 160, 110, "Stats", "ILI9341_GREEN"); upd = false; } long screenoff; const long sec = 1000; const long mins = 1000 * 60; const long hr = 1000 * 60 * 60; void loop(void) { TSPoint p = ts.getPoint(); if (p.z > ts.pressureThreshhold) { if (screenoff < millis() && screenoff != 0) { analogWrite(6, map(sla[3], 0, 280, 25, 255)); screenoff = 0; delay(250); } else { screenoff = 0; p.x = map(p.x, TS_MINX, TS_MAXX, tft.height(), 0); p.y = map(p.y, TS_MINY, TS_MAXY, tft.width(), 0); int x = 320 - p.y; int y = p.x; if(y < 130 && y > 50 && menu == 1) { sla[3] = x - 10; if(sla[3] < 0) sla[3] = 0; if(sla[3] > 280) sla[3] = 280; analogWrite(6, map(sla[3], 0, 280, 25, 255)); drawSlider(sla); } if(menu == 3) { updUD(uda); } if(menu == 4) { if(daytime) { hmupdUD(udd1); hupdUD(udd2); tmupdUD(udd3); tupdUD(udd4); } else { hmupdUD(udn1); hupdUD(udn2); tmupdUD(udn3); tupdUD(udn4); } } if (x < 160 && y < 130) { button(0, 0); } if (x > 160 && y < 130) { button(1, 0); } if (x < 160 && y > 130) { button(0, 1); } if (x > 160 && y > 130) { button(1, 1); } } if(touch(300, -10, 40, 30, p)) { debug = !debug; if(!debug) { upd = true; tft.fillScreen(ILI9341_BLACK); tft.fillRect(0, 0, 160, 20, ILI9341_WHITE); tft.setTextColor(ILI9341_BLACK); String out = "Water Level:"; tft.drawString(out.c_str(), 2, 2, 2); checkBat(); printFastCText("[ INFO ] Exited debug mode."); } else { printFastCText("[ INFO ] Switched to debug mode."); delay(500); } } } else { if(screenoff < millis() && screenoff != 0) { analogWrite(6, 0); } else if(screenoff == 0) { screenoff = millis() + 60000; } } if ((batteryupd.m_milliseconds - millis() + batteryupd.m_lastRunTimestamp) / (sec / 4) == 0 && menu == 2 && !debug) { drawStats(); } if (upd) { if (menu == 0) { drawButton(0, 20, 160, 110, "System", ILI9341_YELLOW); drawButton(160, 20, 160, 110, "Stats", ILI9341_GREEN); drawButton(0, 130, 160, 110, "Options", ILI9341_BLUE); if(go) { drawButton(160, 130, 160, 110, "Stop", ILI9341_RED); } else { drawButton(160, 130, 160, 110, "Start", ILI9341_RED); } } if (menu == 1) { drawButton(0, 130, 160, 110, "Reset", ILI9341_GREEN); drawButton(0, 20, 320, 110, "Brightness", ILI9341_RED); drawSlider(sla); drawButton(160, 130, 160, 110, "Back", ILI9341_BLUE); } if (menu == 2) { drawButton(0, 20, 320, 220, "", ILI9341_WHITE); drawButton(160, 130, 160, 110, "Back", ILI9341_BLUE); drawStats(); if(b1[1]) { if(b1[0]) { drawButton(5, 135, 70, 45, "1*", ILI9341_GREEN); } else { drawButton(5, 135, 70, 45, "1*", ILI9341_RED); } } else { if(b1[0]) { drawButton(5, 135, 70, 45, "1", ILI9341_GREEN); } else { drawButton(5, 135, 70, 45, "1", ILI9341_RED); } } if(b2[1]) { if(b2[0]) { drawButton(85, 135, 70, 45, "2*", ILI9341_GREEN); } else { drawButton(85, 135, 70, 45, "2*", ILI9341_RED); } } else { if(b2[0]) { drawButton(85, 135, 70, 45, "2", ILI9341_GREEN); } else { drawButton(85, 135, 70, 45, "2", ILI9341_RED); } } if(b3[1]) { if(b3[0]) { drawButton(5, 190, 70, 45, "3*", ILI9341_GREEN); } else { drawButton(5, 190, 70, 45, "3*", ILI9341_RED); } } else { if(b3[0]) { drawButton(5, 190, 70, 45, "3", ILI9341_GREEN); } else { drawButton(5, 190, 70, 45, "3", ILI9341_RED); } } if(b4[1]) { if(b4[0]) { drawButton(85, 190, 70, 45, "4*", ILI9341_GREEN); } else { drawButton(85, 190, 70, 45, "4*", ILI9341_RED); } } else { if(b4[0]) { drawButton(85, 190, 70, 45, "4", ILI9341_GREEN); } else { drawButton(85, 190, 70, 45, "4", ILI9341_RED); } } } if (menu == 3) { drawButton(0, 20, 320, 220, "", ILI9341_WHITE); drawButton(160, 130, 160, 110, "Back", ILI9341_BLUE); drawUD(uda); if(b1[1]) { if(b1[0]) { drawButton(5, 135, 70, 45, "1*", ILI9341_GREEN); } else { drawButton(5, 135, 70, 45, "1*", ILI9341_RED); } } else { if(b1[0]) { drawButton(5, 135, 70, 45, "1", ILI9341_GREEN); } else { drawButton(5, 135, 70, 45, "1", ILI9341_RED); } } if(b2[1]) { if(b2[0]) { drawButton(85, 135, 70, 45, "2*", ILI9341_GREEN); } else { drawButton(85, 135, 70, 45, "2*", ILI9341_RED); } } else { if(b2[0]) { drawButton(85, 135, 70, 45, "2", ILI9341_GREEN); } else { drawButton(85, 135, 70, 45, "2", ILI9341_RED); } } if(b3[1]) { if(b3[0]) { drawButton(5, 190, 70, 45, "3*", ILI9341_GREEN); } else { drawButton(5, 190, 70, 45, "3*", ILI9341_RED); } } else { if(b3[0]) { drawButton(5, 190, 70, 45, "3", ILI9341_GREEN); } else { drawButton(5, 190, 70, 45, "3", ILI9341_RED); } } if(b4[1]) { if(b4[0]) { drawButton(85, 190, 70, 45, "4*", ILI9341_GREEN); } else { drawButton(85, 190, 70, 45, "4*", ILI9341_RED); } } else { if(b4[0]) { drawButton(85, 190, 70, 45, "4", ILI9341_GREEN); } else { drawButton(85, 190, 70, 45, "4", ILI9341_RED); } } displayText(15, 25, false, "Water", 4); displayText(15, 55, false, "amount:", 4); drawButton(160, 20, 160, 110, "Page 2", ILI9341_ORANGE); } if (menu == 4) { drawButton(160, 130, 160, 110, "Back", ILI9341_BLUE); if(daytime) { drawButton(0, 20, 320, 110, "", ILI9341_CYAN); drawButton(0, 130, 160, 110, "Night Mode", ILI9341_ORANGE); drawMirrorUD(udd1); drawUD(udd2); tdrawMirrorUD(udd3); tdrawUD(udd4); } else { drawButton(0, 20, 320, 110, "", ILI9341_DARKCYAN); drawButton(0, 130, 160, 110, "Day Mode", ILI9341_ORANGE); drawMirrorUD(udn1); drawUD(udn2); tdrawMirrorUD(udn3); tdrawUD(udn4); } } upd = false; } if(Serial.available() > 0) { String txtin = "Serial: " + Serial.readString(); int x = 0; while(txtin.length() > 53) { printFastCText(txtin.substring(0, 53)); txtin = txtin.substring(53); } printFastCText(txtin.substring(0, txtin.length() - 1)); } batteryupd.Update(); water.Update(); } ISR (WDT_vect) { wdt_disable(); // disable watchdog } // end of WDT_vect void checkBat() { String out = "Battery: "; int y = checkPin(0, 20); if(analogRead(1) > 910) { out += "Using solar."; } else { out += map(y, 572, 859, 0, 100); out += "%"; } drawButton(160, 0, 160, 20, "", ILI9341_WHITE); tft.drawString(out.c_str(), 162, 2, 2); // check water level // A37: Top // A34: Bottom /*if (digitalRead(34) == 0)*/ drawButton(140, 2, 16, 16, "", ILI9341_RED); if (digitalRead(35) == 0) drawButton(140, 2, 16, 16, "", ILI9341_ORANGE); if (digitalRead(36) == 0) drawButton(140, 2, 16, 16, "", ILI9341_YELLOW); if (digitalRead(37) == 0) drawButton(140, 2, 16, 16, "", ILI9341_GREEN); if(analogRead(1) > 910) { trange[0] = udd4[2]; trange[1] = udd3[2]; hrange[0] = udd2[2]; hrange[1] = udd1[2]; } else { trange[0] = udn4[2]; trange[1] = udn3[2]; hrange[0] = udn2[2]; hrange[1] = udn1[2]; } float h = dht.readHumidity(); float f = dht.readTemperature(true); if (f > trange[1]) { fani = true; fano = true; digitalWrite(31, HIGH); digitalWrite(30, HIGH); } else { if (h > hrange[1]) { fano = true; digitalWrite(31, HIGH); } else { fano = false; digitalWrite(31, LOW); } if (h < hrange[0]) { fani = true; digitalWrite(30, HIGH); } else { fani = false; digitalWrite(30, LOW); } } } void drawStats() { printFastCText("[ INFO ] Updating statistics."); tft.setTextColor(ILI9341_BLACK, ILI9341_WHITE); float h = dht.readHumidity(); // Read temperature as Celsius (the default) float t = dht.readTemperature(); // Read temperature as Fahrenheit (isFahrenheit = true) float f = dht.readTemperature(true); String txt = "Humidity: "; txt += h; txt += "%"; displayText(2, 30, false, txt, 4); txt = "Temperature: "; txt += f; txt += " degrees"; displayText(2, 53, false, txt, 4); txt = (water.m_milliseconds - millis() + water.m_lastRunTimestamp) / 60000 + 1; // ceil instead of floor txt += " minutes until water"; displayText(2, 76, false, txt, 4); tft.setTextColor(ILI9341_BLACK); // moisture, temperature, next cycle, how much water, power usage, sensor connections if(fani) { drawButton(5, 100, 150, 35, "Intake Fan", ILI9341_GREEN); } else { drawButton(5, 100, 150, 35, "Intake Fan", ILI9341_RED); } if(fano) { drawButton(165, 100, 150, 35, "Exhaust Fan", ILI9341_GREEN); } else { drawButton(165, 100, 150, 35, "Exhaust Fan", ILI9341_RED); } drawButton(165, 125, 150, 5, "", ILI9341_WHITE); drawButton(165, 130, 150, 5, "", ILI9341_BLUE); drawButton(5, 125, 150, 10, "", ILI9341_WHITE); } int checkPin(byte pin, int count) { int out = 0; for (int x = 0; x < count; x++) { out += analogRead(pin); delay(10); } out /= count; return out; } void runWater() { drawButton(0, 20, 320, 220, "Watering! Please wait.", ILI9341_WHITE); upd = true; pinMode(7, OUTPUT); digitalWrite(7, HIGH); delay(1000); getMoisture(); if(s1 && map(soil1.touchRead(0), 0, 1023, 0, 100) <= 50 && b1[0]) { int td = 50 - map(soil1.touchRead(0), 0, 1023, 0, 100); if(b1[1]) { td *= 5 * ud1[2] / 100.0; } else { td *= 5 * uda[2] / 100.0; } String out = "[ INFO ] Running water on box 1 for "; out += td / 10.0; out += " sec."; printFastCText(out); digitalWrite(2, LOW); delay(td * 100); digitalWrite(2, HIGH); } if(s2 && map(soil2.touchRead(0), 0, 1023, 0, 100) <= 50 && b2[0]) { int td = 50 - map(soil2.touchRead(0), 0, 1023, 0, 100); if(b2[1]) { td *= 5 * ud2[2] / 100.0; } else { td *= 5 * uda[2] / 100.0; } String out = "[ INFO ] Running water on box 2 for "; out += td / 10.0; out += " sec."; printFastCText(out); digitalWrite(3, LOW); delay(td * 100); digitalWrite(3, HIGH); } if(s3 && map(soil3.touchRead(0), 0, 1023, 0, 100) <= 50 && b3[0]) { int td = 50 - map(soil3.touchRead(0), 0, 1023, 0, 100); if(b3[1]) { td *= 5 * ud3[2] / 100.0; } else { td *= 5 * uda[2] / 100.0; } String out = "[ INFO ] Running water on box 3 for "; out += td / 10.0; out += " sec."; printFastCText(out); digitalWrite(4, LOW); delay(td * 100); digitalWrite(4, HIGH); } if(s4 && map(soil4.touchRead(0), 0, 1023, 0, 100) <= 50 && b4[0]) { int td = 50 - map(soil4.touchRead(0), 0, 1023, 0, 100); if(b4[1]) { td *= 5 * ud4[2] / 100.0; } else { td *= 5 * uda[2] / 100.0; } String out = "[ INFO ] Running water on box 4 for "; out += td / 10.0; out += " sec."; printFastCText(out); digitalWrite(5, LOW); delay(td * 100); digitalWrite(5, HIGH); } digitalWrite(7, LOW); } void getMoisture() { float h = dht.readHumidity(); // Read temperature as Celsius (the default) float t = dht.readTemperature(); // Read temperature as Fahrenheit (isFahrenheit = true) float f = dht.readTemperature(true); String txt = "[ OK ] Humidity: "; txt += h; txt += "%, Temperature: "; txt += f; txt += " F"; printFastCText(txt); if (s1) { float t1 = soil1.getTemp(); int sm1 = map(soil1.touchRead(0), 0, 1023, 0, 100); if(sm1 > 6000 && t1 < 1) { s1 = false; printFastCText("[ INFO ] Soil sensor 1 unplugged."); } else { printS1(t1, sm1); } } else if (!s1) { if (soil1.begin(0x36)) { clearLog(); s1 = true; printFastCText("[ INFO ] Soil sensor 1 connected."); float t1 = soil1.getTemp(); int sm1 = map(soil1.touchRead(0), 0, 1023, 0, 100); printS1(t1, sm1); } } if (s2) { float t2 = soil2.getTemp(); int sm2 = map(soil2.touchRead(0), 0, 1023, 0, 100); if(sm2 > 6000 && t2 < 1) { s2 = false; printFastCText("[ INFO ] Soil sensor 2 unplugged."); } else { printS2(t2, sm2); } } else if (!s2) { if (soil2.begin(0x37)) { clearLog(); s2 = true; printFastCText("[ INFO ] Soil sensor 2 connected."); float t2 = soil2.getTemp(); int sm2 = map(soil2.touchRead(0), 0, 1023, 0, 100); printS2(t2, sm2); } } if (s3) { float t3 = soil3.getTemp(); int sm3 = map(soil3.touchRead(0), 0, 1023, 0, 100); if(sm3 > 6000 && t3 < 1) { s3 = false; printFastCText("[ INFO ] Soil sensor 3 unplugged."); } else { printS3(t3, sm3); } } else if (!s3) { if (soil3.begin(0x38)) { clearLog(); s3 = true; printFastCText("[ INFO ] Soil sensor 3 connected."); float t3 = soil3.getTemp(); int sm3 = map(soil3.touchRead(0), 0, 1023, 0, 100); printS3(t3, sm3); } } if (s4) { float t4 = soil4.getTemp(); int sm4 = map(soil4.touchRead(0), 0, 1023, 0, 100); if(sm4 > 6000 && t4 < 1) { s4 = false; printFastCText("[ INFO ] Soil sensor 4 unplugged."); } else { printS4(t4, sm4); } } else if (!s4) { if (soil4.begin(0x39)) { clearLog(); s4 = true; printFastCText("[ INFO ] Soil sensor 4 connected."); float t4 = soil4.getTemp(); int sm4 = map(soil4.touchRead(0), 0, 1023, 0, 100); printS4(t4, sm4); } } } void printS1(float t, int sm) { String out = "[ OK ] Soil sensor 1 temperature: "; out += t; out += " C, "; out += (t * 9.0 / 5.0 + 32); out += " F"; printFastCText(out); out = ""; out += "[ OK ] Soil sensor 1 moisture: "; out += sm; out += "%"; printFastCText(out); } void printS2(float t, int sm) { String out = "[ OK ] Soil sensor 2 temperature: "; out += t; out += " C, "; out += (t * 9.0 / 5.0 + 32); out += " F"; printFastCText(out); out = ""; out += "[ OK ] Soil sensor 2 moisture: "; out += sm; out += "%"; printFastCText(out); } void printS3(float t, int sm) { String out = "[ OK ] Soil sensor 3 temperature: "; out += t; out += " C, "; out += (t * 9.0 / 5.0 + 32); out += " F"; printFastCText(out); out = ""; out += "[ OK ] Soil sensor 3 moisture: "; out += sm; out += "%"; printFastCText(out); } void printS4(float t, int sm) { String out = "[ OK ] Soil sensor 4 temperature: "; out += t; out += " C, "; out += (t * 9.0 / 5.0 + 32); out += " F"; printFastCText(out); out = ""; out += "[ OK ] Soil sensor 4 moisture: "; out += sm; out += "%"; printFastCText(out); } void enablePS(int level) { if (level > 0) { for(int x = 0; x <= 19; x++) { if(x != 8) { pinMode(x, OUTPUT); digitalWrite(x, LOW); } } for(int x = 32; x <= 53; x++) { pinMode(x, OUTPUT); digitalWrite(x, LOW); } printFastCText("[ OK ] Enabled Level 1 powersaving."); } else { printFastCText("[FAILED] Powersaving: Argument must be > 0."); } if(level > 1) { Serial.end(); power_adc_disable(); //power_spi_disable(); // needed for screen power_usart0_disable(); power_usart1_disable(); power_usart2_disable(); power_timer1_disable(); power_timer2_disable(); power_timer3_disable(); power_timer4_disable(); power_timer5_disable(); //power_twi_disable(); // twi needed for soil sensors / i2c printFastCText("[ OK ] Enabled Level 2 powersaving."); } if(level > 2) { // disable ADC ADCSRA = 0; //power_all_disable(); ps3 = true; printFastCText("[ OK ] Enabled Level 3 powersaving."); printFastCText("[ INFO ] All powersaving features enabled."); } } void clearLog() { outtext = ""; outtext2 = ""; linecount = 0; tft.fillScreen(ILI9341_BLACK); } void printFastCText(String text) { // NOTE: text MUST be under 53 characters long! (this is how the code runs faster) linecount ++; if (linecount > 30) { outtext2 = outtext2.substring(53); //scrollAddress(8); } if (text.length() < 53) { outtext2 += text; for (int x = text.length(); x < 53; x++) { outtext2 += " "; } } else { outtext2 += text; } if (debug) { tft.setCursor(0, 0); tft.setTextColor(ILI9341_WHITE, ILI9341_BLACK); tft.setTextSize(1); tft.setTextFont(1); tft.print(outtext2); } } void scrollAddress(uint16_t vsp) { tft.writecommand(ILI9341_VSCRSADD); // Vertical scrolling pointer tft.writedata(vsp>>8); tft.writedata(vsp); } void drawButton(int x, int y, int w, int h, char* text, word color) { if(debug) return; //tft.fillRect(x, y, w, h, ILI9341_BLACK); tft.setTextFont(4); tft.fillRect(x, y, w, h, color); tft.drawCentreString(text, x + w/2, y + h/2 - 15, 4); } void button(int x, int y) { if (menu == 0) { if (x == 0 && y == 0) { menu = 1; upd = true; } if (x == 1 && y == 0) { menu = 2; upd = true; } if (x == 0 && y == 1) { menu = 3; upd = true; } if (x == 1 && y == 1) { if(go) { water.Stop(); upd = true; go = false; } else { water.Start(); upd = true; go = true; } delay(250); } } else if (menu == 1) { if (x == 0 && y == 1) { drawButton(0, 0, 320, 240, "", ILI9341_BLACK); pinMode(9, OUTPUT); digitalWrite(9, LOW); // RESET } if (x == 1 && y == 1) { menu = 0; upd = true; delay(125); } } else if (menu == 2) { if (x == 1 && y == 1) { menu = 0; upd = true; delay(125); } } else if (menu == 3) { if (x == 1 && y == 1) { menu = 0; upd = true; dispbox = 0; updBoxMenu(1); updBoxMenu(2); updBoxMenu(3); updBoxMenu(4); delay(125); } if (x == 1 && y == 0) { menu = 4; daytime = true; upd = true; } TSPoint p = ts.getPoint(); p.x = map(p.x, TS_MINX, TS_MAXX, tft.height(), 0); p.y = map(p.y, TS_MINY, TS_MAXY, tft.width(), 0); if(touch(0, 130, 80, 55, p)) { updBoxMenu(1); drawBoxMenu(1); updBoxMenu(1); } if(touch(80, 130, 80, 55, p)) { updBoxMenu(2); drawBoxMenu(2); updBoxMenu(2); } if(touch(0, 185, 80, 55, p)) { updBoxMenu(3); drawBoxMenu(3); updBoxMenu(3); } if(touch(80, 185, 80, 55, p)) { updBoxMenu(4); drawBoxMenu(4); updBoxMenu(4); } } else if (menu == 4) { if (x == 1 && y == 1) { menu = 3; upd = true; delay(125); } if (x == 0 && y == 1) { daytime = !daytime; upd = true; delay(125); } } // skip 4 lol, oops else if (menu == 5) { if (x == 1 && y == 0) { updBoxMenu(dispbox); } if (x == 1 && y == 1) { menu = 3; upd = true; } if (x == 0 && y == 1) { if(dispbox == 1) { b1[0] = !b1[0]; printFastCText("[ INFO ] Toggling box 1."); } if(dispbox == 2) { b2[0] = !b2[0]; printFastCText("[ INFO ] Toggling box 2."); } if(dispbox == 3) { b3[0] = !b3[0]; printFastCText("[ INFO ] Toggling box 3."); } if(dispbox == 4) { b4[0] = !b4[0]; printFastCText("[ INFO ] Toggling box 4."); } drawBoxMenu(dispbox); updBoxMenu(dispbox); } } delay(50); } void displayText(int x, int y, boolean center, String text, int size) { if (debug) return; if (center) { tft.drawCentreString(text.c_str(), x, y, size); } else { tft.drawString(text.c_str(), x, y, size); } } void drawSlider(int data[]) { int x = data[0]; int y = data[1]; int w = data[2]; int d = data[3]; drawButton(x, y, w, 20, "", ILI9341_BLACK); drawButton(x + d, y, 20, 20, "", ILI9341_GREEN); } void drawUD(int data[]) { int x = data[0]; int y = data[1]; int d = data[2]; tft.fillTriangle(x + 75, y + 20, x + 90, y - 5, x + 105, y + 20, ILI9341_BLACK); tft.fillTriangle(x + 75, y + 30, x + 90, y + 55, x + 105, y + 30, ILI9341_BLACK); String out = ""; out += d; out += "%"; //tft.fillRect(x, y + 15, 70, 25, ILI9341_WHITE); tft.drawString(out.c_str(), x, y + 15, 4); //tft.fillRect(x + d, y, 20, 20, ILI9341_GREEN); } void drawMirrorUD(int data[]) { int x = data[0]; int y = data[1]; int d = data[2]; tft.fillTriangle(x - 40, y + 20, x - 25, y - 5, x - 10, y + 20, ILI9341_BLACK); tft.fillTriangle(x - 40, y + 30, x - 25, y + 55, x - 10, y + 30, ILI9341_BLACK); String out = ""; out += d; out += "%"; //tft.fillRect(x, y + 15, 70, 25, ILI9341_WHITE); tft.drawString(out.c_str(), x, y + 15, 4); //tft.fillRect(x + d, y, 20, 20, ILI9341_GREEN); } void tdrawUD(int data[]) { int x = data[0]; int y = data[1]; int d = data[2]; tft.fillTriangle(x + 75, y + 20, x + 90, y - 5, x + 105, y + 20, ILI9341_BLACK); tft.fillTriangle(x + 75, y + 30, x + 90, y + 55, x + 105, y + 30, ILI9341_BLACK); String out = ""; out += d; //tft.fillRect(x, y + 15, 70, 25, ILI9341_WHITE); tft.drawString(out.c_str(), x, y + 15, 4); tft.drawCircle(x + 40, y + 18, 3, ILI9341_BLACK); tft.drawString("F", x + 43, y + 15, 4); //tft.fillRect(x + d, y, 20, 20, ILI9341_GREEN); } void tdrawMirrorUD(int data[]) { int x = data[0]; int y = data[1]; int d = data[2]; tft.fillTriangle(x - 40, y + 20, x - 25, y - 5, x - 10, y + 20, ILI9341_BLACK); tft.fillTriangle(x - 40, y + 30, x - 25, y + 55, x - 10, y + 30, ILI9341_BLACK); String out = ""; out += d; //tft.fillRect(x, y + 15, 70, 25, ILI9341_WHITE); tft.drawString(out.c_str(), x, y + 15, 4); tft.drawCircle(x + 40, y + 18, 3, ILI9341_BLACK); tft.drawString("F", x + 43, y + 15, 4); //tft.fillRect(x + d, y, 20, 20, ILI9341_GREEN); } void updUD(int data[]) { int x = data[0]; int y = data[1]; int d = data[2]; int xt = 0; int yt = 0; TSPoint p = ts.getPoint(); if (p.z > ts.pressureThreshhold) { p.x = map(p.x, TS_MINX, TS_MAXX, tft.height(), 0); p.y = map(p.y, TS_MINY, TS_MAXY, tft.width(), 0); Serial.print("X = "); Serial.print(320 - p.y); Serial.print("\tY = "); Serial.print(p.x); Serial.print("\tPressure = "); Serial.println(p.z); xt = 320 - p.y; yt = p.x; if (xt >= x + 70 && xt <= x + 110) { if (yt <= y + 15 && yt >= y - 30 && d < data[4]) { // UP data[2] += 20; d += 20; String out = ""; out += d; out += "%"; drawButton(x, y + 15, 70, 25, "", ILI9341_WHITE); tft.drawString(out.c_str(), x, y + 15, 4); } else if (yt >= y + 15 && yt <= y + 60 && d > data[3]) { // DOWN data[2] -= 20; d -= 20; String out = ""; out += d; out += "%"; drawButton(x, y + 15, 70, 25, "", ILI9341_WHITE); tft.drawString(out.c_str(), x, y + 15, 4); } } } } void hupdUD(int data[]) { int x = data[0]; int y = data[1]; int d = data[2]; int xt = 0; int yt = 0; TSPoint p = ts.getPoint(); if (p.z > ts.pressureThreshhold) { p.x = map(p.x, TS_MINX, TS_MAXX, tft.height(), 0); p.y = map(p.y, TS_MINY, TS_MAXY, tft.width(), 0); Serial.print("X = "); Serial.print(320 - p.y); Serial.print("\tY = "); Serial.print(p.x); Serial.print("\tPressure = "); Serial.println(p.z); xt = 320 - p.y; yt = p.x; if (xt >= x + 70 && xt <= x + 110) { if (yt <= y + 15 && yt >= y - 30 && d < data[4]) { // UP data[2] += 5; d += 5; String out = ""; out += d; out += "%"; drawButton(x, y + 15, 70, 25, "", ILI9341_WHITE); tft.drawString(out.c_str(), x, y + 15, 4); } else if (yt >= y + 15 && yt <= y + 60 && d > data[3]) { // DOWN data[2] -= 5; d -= 5; String out = ""; out += d; out += "%"; drawButton(x, y + 15, 70, 25, "", ILI9341_WHITE); tft.drawString(out.c_str(), x, y + 15, 4); } } } } void hmupdUD(int data[]) { int x = data[0]; int y = data[1]; int d = data[2]; int xt = 0; int yt = 0; TSPoint p = ts.getPoint(); if (p.z > ts.pressureThreshhold) { p.x = map(p.x, TS_MINX, TS_MAXX, tft.height(), 0); p.y = map(p.y, TS_MINY, TS_MAXY, tft.width(), 0); Serial.print("X = "); Serial.print(320 - p.y); Serial.print("\tY = "); Serial.print(p.x); Serial.print("\tPressure = "); Serial.println(p.z); xt = 320 - p.y; yt = p.x; if (xt >= x - 40 && xt <= x - 10) { if (yt <= y + 15 && yt >= y - 30 && d < data[4]) { // UP data[2] += 5; d += 5; String out = ""; out += d; out += "%"; drawButton(x, y + 15, 70, 25, "", ILI9341_WHITE); tft.drawString(out.c_str(), x, y + 15, 4); } else if (yt >= y + 15 && yt <= y + 60 && d > data[3]) { // DOWN data[2] -= 5; d -= 5; String out = ""; out += d; out += "%"; drawButton(x, y + 15, 70, 25, "", ILI9341_WHITE); tft.drawString(out.c_str(), x, y + 15, 4); } } } } void tupdUD(int data[]) { int x = data[0]; int y = data[1]; int d = data[2]; int xt = 0; int yt = 0; TSPoint p = ts.getPoint(); if (p.z > ts.pressureThreshhold) { p.x = map(p.x, TS_MINX, TS_MAXX, tft.height(), 0); p.y = map(p.y, TS_MINY, TS_MAXY, tft.width(), 0); Serial.print("X = "); Serial.print(320 - p.y); Serial.print("\tY = "); Serial.print(p.x); Serial.print("\tPressure = "); Serial.println(p.z); xt = 320 - p.y; yt = p.x; if (xt >= x + 70 && xt <= x + 110) { if (yt <= y + 15 && yt >= y - 30 && d < data[4]) { // UP data[2] += 5; d += 5; String out = ""; out += d; drawButton(x, y + 15, 70, 25, "", ILI9341_WHITE); tft.drawString(out.c_str(), x, y + 15, 4); tft.drawCircle(x + 40, y + 18, 3, ILI9341_BLACK); tft.drawString("F", x + 43, y + 15, 4); } else if (yt >= y + 15 && yt <= y + 60 && d > data[3]) { // DOWN data[2] -= 5; d -= 5; String out = ""; out += d; drawButton(x, y + 15, 70, 25, "", ILI9341_WHITE); tft.drawString(out.c_str(), x, y + 15, 4); tft.drawCircle(x + 40, y + 18, 3, ILI9341_BLACK); tft.drawString("F", x + 43, y + 15, 4); } } } } void tmupdUD(int data[]) { int x = data[0]; int y = data[1]; int d = data[2]; int xt = 0; int yt = 0; TSPoint p = ts.getPoint(); if (p.z > ts.pressureThreshhold) { p.x = map(p.x, TS_MINX, TS_MAXX, tft.height(), 0); p.y = map(p.y, TS_MINY, TS_MAXY, tft.width(), 0); Serial.print("X = "); Serial.print(320 - p.y); Serial.print("\tY = "); Serial.print(p.x); Serial.print("\tPressure = "); Serial.println(p.z); xt = 320 - p.y; yt = p.x; if (xt >= x - 40 && xt <= x - 10) { if (yt <= y + 15 && yt >= y - 30 && d < data[4]) { // UP data[2] += 5; d += 5; String out = ""; out += d; drawButton(x, y + 15, 70, 25, "", ILI9341_WHITE); tft.drawString(out.c_str(), x, y + 15, 4); tft.drawCircle(x + 40, y + 18, 3, ILI9341_BLACK); tft.drawString("F", x + 43, y + 15, 4); } else if (yt >= y + 15 && yt <= y + 60 && d > data[3]) { // DOWN data[2] -= 5; d -= 5; String out = ""; out += d; drawButton(x, y + 15, 70, 25, "", ILI9341_WHITE); tft.drawString(out.c_str(), x, y + 15, 4); tft.drawCircle(x + 40, y + 18, 3, ILI9341_BLACK); tft.drawString("F", x + 43, y + 15, 4); } } } } boolean touch(int x, int y, int w, int h, TSPoint p) { int xt = 320 - p.y; int yt = p.x; if(xt >= x && xt <= x + w && yt >= y && yt <= y + h) return true; return false; } void drawBoxMenu(int box) { dispbox = box; if(box == 0) { menu = 4; upd = true; return; } menu = 5; drawButton(0, 20, 320, 220, "", ILI9341_WHITE); if (box == 1) { if(!b1[0]) { displayText(15, 35, false, "Plant Box 1 Disabled", 4); drawButton(0, 130, 160, 110, "Enable", ILI9341_GREEN); } if(b1[0]) { displayText(15, 35, false, "Plant Box 1 Enabled", 4); drawButton(0, 130, 160, 110, "Disable", ILI9341_RED); } drawButton(160, 130, 160, 110, "Back", ILI9341_BLUE); drawUD(ud1); displayText(15, 65, false, "Water amount:", 4); } if (box == 2) { if(!b2[0]) { displayText(15, 35, false, "Plant Box 2 Disabled", 4); drawButton(0, 130, 160, 110, "Enable", ILI9341_GREEN); } if(b2[0]) { displayText(15, 35, false, "Plant Box 2 Enabled", 4); drawButton(0, 130, 160, 110, "Disable", ILI9341_RED); } drawButton(160, 130, 160, 110, "Back", ILI9341_BLUE); drawUD(ud2); displayText(15, 65, false, "Water amount:", 4); } if (box == 3) { if(!b3[0]) { displayText(15, 35, false, "Plant Box 3 Disabled", 4); drawButton(0, 130, 160, 110, "Enable", ILI9341_GREEN); } if(b3[0]) { displayText(15, 35, false, "Plant Box 3 Enabled", 4); drawButton(0, 130, 160, 110, "Disable", ILI9341_RED); } drawButton(160, 130, 160, 110, "Back", ILI9341_BLUE); drawUD(ud3); displayText(15, 65, false, "Water amount:", 4); } if (box == 4) { if(!b4[0]) { displayText(15, 35, false, "Plant Box 4 Disabled", 4); drawButton(0, 130, 160, 110, "Enable", ILI9341_GREEN); } if(b4[0]) { displayText(15, 35, false, "Plant Box 4 Enabled", 4); drawButton(0, 130, 160, 110, "Disable", ILI9341_RED); } drawButton(160, 130, 160, 110, "Back", ILI9341_BLUE); drawUD(ud4); displayText(15, 65, false, "Water amount:", 4); } } void updBoxMenu(int box) { if(box == 0) { return; } if (box == 1) { if(!b1[1]) { ud1[2] = uda[2]; updUD(ud1); if(ud1[2] != uda[2]) { b1[1] = true; if(box == dispbox) { drawButton(15, 95, 100, 30, "", ILI9341_WHITE); } } else { displayText(15, 95, false, "In sync", 4); } } else { updUD(ud1); if(ud1[2] == uda[2]) { b1[1] = false; if(box == dispbox) { displayText(15, 95, false, "In sync", 4); } } } } if (box == 2) { if(!b2[1]) { ud2[2] = uda[2]; updUD(ud2); if(ud2[2] != uda[2]) { b2[1] = true; if(box == dispbox) { drawButton(15, 95, 100, 30, "", ILI9341_WHITE); } } else { displayText(15, 95, false, "In sync", 4); } } else { updUD(ud2); if(ud2[2] == uda[2]) { b2[1] = false; if(box == dispbox) { displayText(15, 95, false, "In sync", 4); } } } } if (box == 3) { if(!b3[1]) { ud3[2] = uda[2]; updUD(ud3); if(ud3[2] != uda[2]) { b3[1] = true; if(box == dispbox) { drawButton(15, 95, 100, 30, "", ILI9341_WHITE); } } else { displayText(15, 95, false, "In sync", 4); } } else { updUD(ud3); if(ud3[2] == uda[2]) { b3[1] = false; if(box == dispbox) { displayText(15, 95, false, "In sync", 4); } } } } if (box == 4) { if(!b4[1]) { ud4[2] = uda[2]; updUD(ud4); if(ud4[2] != uda[2]) { b4[1] = true; if(box == dispbox) { drawButton(15, 95, 100, 30, "", ILI9341_WHITE); } } else { displayText(15, 95, false, "In sync", 4); } } else { updUD(ud4); if(ud4[2] == uda[2]) { b4[1] = false; if(box == dispbox) { displayText(15, 95, false, "In sync", 4); } } } } }