You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

636 lines
15 KiB
C++

#include <EveryTimer.h>
#include <OneShotTimer.h>
#include <TimeLib.h>
#include <TFT_FastPin.h>
#include <TFT_ILI9341.h>
#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 <TouchScreen.h>
#include <avr/power.h>
#include <avr/sleep.h>
#include <avr/wdt.h>
#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<ILI9341_RST_PIN>::setOutput();
FastPin<ILI9341_RST_PIN>::hi();
FastPin<ILI9341_RST_PIN>::lo();
delay(1);
FastPin<ILI9341_RST_PIN>::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);
}