#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 // 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); String outtext = ""; String oldtext = ""; boolean fastboot = false; boolean debug; boolean ps3 = false; boolean upd = true; boolean s1, s2, s3, s4; String outtext2 = ""; int linecount = 0; 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); setTime(0); Serial.begin(9600); //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(""); 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(); } const int sec = 1000; const int min = 1000 * 60; const int hr = 1000 * 60 * 60; void loop(void) { 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(p.x); Serial.print("\tY = "); Serial.print(p.y); Serial.print("\tPressure = "); Serial.println(p.z); } if (ps3) { ADCSRA = 0; } 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)); } unsigned long mil = millis(); /*String tmp = "["; if(mil / 1000 < 10) { tmp += " "; } else if(mil / 1000 < 100) { tmp += " "; } else if(mil / 1000 < 1000) { tmp += " "; } else if(mil / 1000 < 10000) { tmp += " "; } else if(mil / 1000 < 100000) { tmp += " "; } else if(mil / 1000 < 1000000) { tmp += " "; } tmp += mil / 1000; tmp += "."; if(mil % 1000 < 10) { tmp += "00"; } else if(mil % 1000 < 100) { tmp += "0"; } tmp += mil % 1000; tmp += "]";*/ //printFastCText(tmp); //tft.scrollTo(320); /*if(mil % 20000 < 500) { getMoisture(); delay(500); //tft.scrollTo(480); //tft.setAddrWindow(320, 0, 320, 240); upd = true; }*/ // change upd to true if screen update needed if(!debug && upd) { tft.fillScreen(ILI9341_BLACK); tft.fillRect(0, 0, 160, 20, ILI9341_WHITE); tft.setCursor(2, 2); 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; } batteryupd.Update(); water.Update(); } ISR (WDT_vect) { wdt_disable(); // disable watchdog } // end of WDT_vect void checkBat() { if(debug) { String out = "[ OK ] Battery: "; int y = 0; for(int x = 0; x < 20; x++) { y += analogRead(0); delay(10); } if(analogRead(1) > 910) { out += map(y / 20, 572, 859, 0, 100) - 20; } else { out += map(y / 20, 572, 859, 0, 100); } out += "%, Raw: "; out += y/20; out += "."; if(analogRead(1) > 910) { out += ". Battery Charging."; } printFastCText(out); } else { String out = "Battery: "; int y = 0; for(int x = 0; x < 20; x++) { y += analogRead(0); delay(10); } if(analogRead(1) > 910) { out += map(y / 20, 572, 859, 0, 100) - 20; } else { out += map(y / 20, 572, 859, 0, 100); } out += "%"; if(analogRead(1) > 910) { out += " Charging"; } tft.fillRect(160, 0, 160, 20, ILI9341_WHITE); tft.drawString(out.c_str(), 162, 2, 2); } } void runWater() { getMoisture(); if(s1 && map(soil1.touchRead(0), 0, 1023, 0, 100) <= 50) { int td = 50 - map(soil1.touchRead(0), 0, 1023, 0, 100); 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) { int td = 50 - map(soil2.touchRead(0), 0, 1023, 0, 100); 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) { int td = 50 - map(soil3.touchRead(0), 0, 1023, 0, 100); 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) { int td = 50 - map(soil4.touchRead(0), 0, 1023, 0, 100); 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); } } void getMoisture() { 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.fillScreen(BLACK); tft.setCursor(0, 0); tft.setTextColor(ILI9341_WHITE, ILI9341_BLACK); tft.setTextSize(1); //int cursory = linecount * 8; //for (int x = linecount - 1; x >= 0; x--) { //tft.setCursor(0, cursory - 8); //tft.fillRect(0, cursory - 8, 320, 8, BLACK); //tft.fillScreen(ILI9341_BLACK); tft.print(outtext2); //cursory -= 8; //} } } 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, char* color) { tft.setTextFont(4); tft.fillRect(x, y, w, h, color); tft.drawCentreString(text, x + w/2, y + h/2 - 15, 4); }