Here is the full code. It is receiving the signal from the ultrasonic sensor, controlling the touch screen and sending signals to the relay. The relay has two states: in the first state, the rain water solenoid valve is open and the city water solenoid valve is closed. In the other relay state, the status of the solenoid valves are reverse. The valves only use electricity when changing state. And the system is setup to be on city water when the relay is not powered. I can switch off the solenoid valves with a manual switch to turn the solenoid valves manually.
REM1: Some text in French but it should not be an issue to understand the code.
REM2: I copy / paste some code and did not cleaned, yet, everything I am not using
PART1 (9000 characters limit)
#include <Elegoo_GFX.h> // Core graphics library
#include <Elegoo_TFTLCD.h> // Hardware-specific library
#include <TouchScreen.h>
#define DEV_MODE false
// Accessories pin settings
#define RELAY 26
#define ECHO_PIN 28
#define TRIGGER_PIN 29
// Electrovalve switching time
#define SWITCHING_DELAY 45000
// Measured distance at full tank
#define FULL_TANK 20.0
// Measured distance at empty tank
#define EMPTY_TANK 150.0
// Needed percentage to automatically switch from rain water to city water
#define AUTOMATIC_SWITCH_TO_CITY_WATER 15
// Needed percentage to automatically switch from city water to rain water
#define AUTOMATIC_SWITCH_TO_RAIN_WATER 50
// Safety count for bad_following_reading to switch to city water
#define BAD_FOLLOWING_BAD_READING_SAFETY_COUNT 500
// Status messages
#define NO_MESSAGE ""
#define INITIALISATION "Initialisation"
#define MEASURE_ERROR "Erreur de mesures"
#define CHANGE_TO_CITY "Changement en cours Pluie -> Ville"
#define CHANGE_TO_RAIN "Changement en cours Ville -> Pluie"
#define NO_CAPACITY_READ "Capacité non détectée"
// Buttons name
char buttonlabels[3][6] = {"Ville", "Pluie", "Fixe"};
// The control pins for the LCD can be assigned to any digital or
// analog pins...but we'll use the analog pins as this allows us to
// double up the pins with the touch screen (see the TFT paint example).
#define LCD_CS A3 // Chip Select goes to Analog 3
#define LCD_CD A2 // Command/Data goes to Analog 2
#define LCD_WR A1 // LCD Write goes to Analog 1
#define LCD_RD A0 // LCD Read goes to Analog 0
#define LCD_RESET A4 // Can alternately just connect to Arduino's reset pin
// For the Arduino Mega, use digital pins 22 through 29
// (on the 2-row header at the end of the board).
// Assign human-readable names to some common 16-bit color values:
#define BLACK 0x0000
#define BLUE 0x001F
#define RED 0xF800
#define GREEN 0x07E0
#define CYAN 0x07FF
#define MAGENTA 0xF81F
#define YELLOW 0xFFE0
#define WHITE 0xFFFF
// Color definitions
#define ILI9341_BLACK 0x0000 /* 0, 0, 0 */
#define ILI9341_NAVY 0x000F /* 0, 0, 128 */
#define ILI9341_DARKGREEN 0x03E0 /* 0, 128, 0 */
#define ILI9341_DARKCYAN 0x03EF /* 0, 128, 128 */
#define ILI9341_MAROON 0x7800 /* 128, 0, 0 */
#define ILI9341_PURPLE 0x780F /* 128, 0, 128 */
#define ILI9341_OLIVE 0x7BE0 /* 128, 128, 0 */
#define ILI9341_LIGHTGREY 0xC618 /* 192, 192, 192 */
#define ILI9341_DARKGREY 0x7BEF /* 128, 128, 128 */
#define ILI9341_BLUE 0x001F /* 0, 0, 255 */
#define ILI9341_GREEN 0x07E0 /* 0, 255, 0 */
#define ILI9341_CYAN 0x07FF /* 0, 255, 255 */
#define ILI9341_RED 0xF800 /* 255, 0, 0 */
#define ILI9341_MAGENTA 0xF81F /* 255, 0, 255 */
#define ILI9341_YELLOW 0xFFE0 /* 255, 255, 0 */
#define ILI9341_WHITE 0xFFFF /* 255, 255, 255 */
#define ILI9341_ORANGE 0xFD20 /* 255, 165, 0 */
#define ILI9341_GREENYELLOW 0xAFE5 /* 173, 255, 47 */
#define ILI9341_PINK 0xF81F
/******************* UI details */
#define BUTTON_X 55
#define BUTTON_Y 150
#define BUTTON_W 80
#define BUTTON_H 30
#define BUTTON_SPACING_X 50
#define BUTTON_SPACING_Y 20
#define BUTTON_TEXTSIZE 2
// text box where numbers go
#define TEXT_X 10
#define TEXT_Y 10
#define TEXT_W 220
#define TEXT_H 50
#define TEXT_TSIZE 3
#define TEXT_TCOLOR ILI9341_WHITE
char *textfield = (char*)malloc(10 * sizeof(char));
#define YP A3 // must be an analog pin, use "An" notation!
#define XM A2 // must be an analog pin, use "An" notation!
#define YM 9 // can be a digital pin
#define XP 8 // can be a digital pin
//Touch For New ILI9341 TP
#define TS_MINX 120
#define TS_MAXX 900
#define TS_MINY 70
#define TS_MAXY 920
// We have a status line
#define STATUS_X 10
#define STATUS_Y 65
// We have a measure line
#define MEASURE_X 10
#define MEASURE_Y 300
// Touch screen boundaries
#define MINPRESSURE 10
#define MAXPRESSURE 1000
Elegoo_TFTLCD tft(LCD_CS, LCD_CD, LCD_WR, LCD_RD, LCD_RESET);
TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300);
// If using the shield, all control and data lines are fixed, and
// a simpler declaration can optionally be used:
// Elegoo_TFTLCD tft;
Elegoo_GFX_Button buttons[3];
/* create 3 buttons, in classic candybar phone style */
uint16_t buttoncolors[3] = {ILI9341_WHITE, ILI9341_BLUE, ILI9341_BLACK};
uint16_t buttontextcolors[3] = {ILI9341_BLUE, ILI9341_WHITE, ILI9341_RED};
// Sonar setup
#define MAX_DISTANCE 200
uint16_t cycle = 0;
uint16_t measure;
char *measureString = (char*)malloc(100 * sizeof(char));
// Program variables
bool isFixed = false;
bool isRainWater = false;
int bad_following_reading = 0;
// DEV variables
int dev_measure = 0;
void setup(void) {
status(INITIALISATION);
Serial.begin(9600);
tft.reset();
uint16_t identifier = tft.readID();
identifier = detectLCD(identifier);
tft.begin(identifier);
tft.setRotation(2);
tft.fillScreen(BLACK);
// create buttons
// Ville row 0 col 0
setButton(0, 0, 0, 0, ILI9341_BLUE, ILI9341_WHITE);
// Pluie row 0 col 1
setButton(1, 0, 1, 0, ILI9341_BLACK, ILI9341_WHITE);
// Fixe row 1 col 1
setButton(2, 1, 0, 65, ILI9341_BLACK, ILI9341_RED);
pinMode(RELAY, OUTPUT);
digitalWrite(RELAY, LOW);
pinMode(TRIGGER_PIN, OUTPUT);
pinMode(ECHO_PIN, INPUT_PULLUP);
// create 'text field'
tft.drawRect(TEXT_X, TEXT_Y, TEXT_W, TEXT_H, ILI9341_WHITE);
sonarMeasure();
status(NO_MESSAGE);
}
// Add button
void setButton(int index, int row, int col, int offset, uint16_t buttoncolor, uint16_t buttontextcolor) {
int x = BUTTON_X+col *(BUTTON_W+BUTTON_SPACING_X) + offset;
int y = BUTTON_Y+row*(BUTTON_H+BUTTON_SPACING_Y);
buttons[index].initButton(&tft, // x, y, w, h, outline, fill, text
x,
y,
BUTTON_W, BUTTON_H, ILI9341_WHITE, buttoncolor, buttontextcolor,
buttonlabels[index], BUTTON_TEXTSIZE);
buttons[index].drawButton();
}
void loop(void) {
// Sonar
sonarMeasure();
// Touch screen
digitalWrite(13, HIGH);
TSPoint p = ts.getPoint();
digitalWrite(13, LOW);
pinMode(XM, OUTPUT);
pinMode(YP, OUTPUT);
if (p.z > MINPRESSURE && p.z < MAXPRESSURE) {
// scale from 0->1023 to tft.width
p.x = map(p.x, TS_MINX, TS_MAXX, tft.width(), 0);
p.y = (tft.height()-map(p.y, TS_MINY, TS_MAXY, tft.height(), 0));
}
// go thru all the buttons, checking if they were pressed
for (uint8_t b=0; b<3; b++) {
if (buttons[b].contains(p.x, p.y)) {
//Serial.print("Pressing: "); Serial.println(b);
buttons[b].press(true); // tell the button it is pressed
} else {
buttons[b].press(false); // tell the button it is NOT pressed
}
}
// now we can ask the buttons if their state has changed
for (uint8_t b=0; b<3; b++) {
if (buttons[b].justReleased()) {
// Serial.print("Released: "); Serial.println(b);
buttons[b].drawButton(); // draw normal
}
if (buttons[b].justPressed()) {
// City button!
if (b == 0) {
Serial.println(F("City pressed"));
cityButtonPressed();
}
// Rain button!
if (b == 1) {
Serial.println(F("Rain pressed"));
rainButtonPressed();
}
// Fixe button!
if (b == 2) {
fixeButtonPressed();
}
delay(100); // UI debouncing
}
}
}