diff --git a/main.ino b/main.ino new file mode 100644 index 0000000..2bbaceb --- /dev/null +++ b/main.ino @@ -0,0 +1,290 @@ +#include +#include +#include + +const char* ssid = "OpenWrt"; +const char* password = "La1003000902"; +WebServer server(80); + + +const int motorPin = 11; // Change this to the pin number connected to the motor relay +const int sensorPin = 16; // Change this to the pin number connected to the moisture sensor + + +//storage +void writeLongToEEPROM(int address, long value) { + // write the four bytes of the long integer to EEPROM + EEPROM.write(address, (value >> 24) & 0xFF); + EEPROM.write(address + 1, (value >> 16) & 0xFF); + EEPROM.write(address + 2, (value >> 8) & 0xFF); + EEPROM.write(address + 3, value & 0xFF); + EEPROM.commit(); +} +long readLongFromEEPROM(int address) { + // read the four bytes of the long integer from EEPROM + byte b1 = EEPROM.read(address); + byte b2 = EEPROM.read(address + 1); + byte b3 = EEPROM.read(address + 2); + byte b4 = EEPROM.read(address + 3); + // combine the four bytes to form a long integer + long value = ((long)b1 << 24) | ((long)b2 << 16) | ((long)b3 << 8) | (long)b4; + return value; +} + + + +//moisture +const int maxAnalogValue = 80000; +const int numReadings = 10; // Number of readings to average +int readings[numReadings]; // Array to store readings +int readingIndex = 0; // Current index in array +int total = 0; // Running total of readings from history +int moisture = 0; //current calculated moisture level +int getMoisture(){ + //motor is messing with readings + bool mot = getMotor(); + setMotor(true); + delay(10); + // Read the sensor value and add it to the total + total -= readings[readingIndex]; + readings[readingIndex] = analogRead(sensorPin); + total += readings[readingIndex]; + // Move to the next index in the array + readingIndex = (readingIndex + 1) % numReadings; + // Calculate the average value + moisture = total / numReadings; + setMotor(mot); + return moisture; +} +int getMoisturePercent(){ + int m = getMoisture(); + //TODO:fix percentage calculation + m = map(m,0,8000,0,100); + return m; +} + + +//desired moisture +int desiredMoisture; // The desired moisture level +const int desiredMoistureAddress = 0; // Address to store the desired moisture level in EEPROM +void setDesiredMoisture(int m){ + if (abs(m - desiredMoisture) >= 50) { + desiredMoisture = m; + writeLongToEEPROM(desiredMoistureAddress, desiredMoisture); + + } +} + +void setDesiredMoisturePercent(int m){ + //todo map from percent + setDesiredMoisture(m); +} + +int getDesiredMoisture(){ + desiredMoisture = readLongFromEEPROM(desiredMoistureAddress); + return desiredMoisture; +} + +int getDesiredMoisturePercent(){ + int m = getDesiredMoisturePercent(); + //todo map + return m; +} + + +//motor +bool motorSpinning = false; +void setMotor(bool state){ + state = state; //add a ! if need to invert command + digitalWrite(motorPin, state); + motorSpinning = state; +} +bool getMotor(){ + return motorSpinning; +} + + +//trigger watering +void waterTrigger(){ + // Add some wiggle room to the desired moisture level + int d = getDesiredMoisture(); + int m = getMoisture(); + bool mot = getMotor(); + int threshold = d * 0.1; + int lowerThreshold = d - threshold; + int upperThreshold = d + threshold; + + // Check if the moisture level is below the lower threshold + if (m < lowerThreshold) { + if (!mot){ + setMotor(true); + } + } + // Check if the moisture level is above the upper threshold + else if (m > upperThreshold) { + if (mot){ + setMotor(false); + } + } +} + + +//Webinterface +void webserver() { + String html = "Moisture Control"; + + //script + html += ""; + + //html + html += ""; + html += "

Moisture Control

"; + html += "

Moisture: "+String( getMoisture())+"

"; + html += "

Desired Moisture: "+String( getDesiredMoisture())+"

"; + html += "

Pumps running: "+String(getMotor())+"

"; + html += ""; + html += ""; + html += "

Set new target for desired moisture:"; + html += "
"; + html += ""; + html += ""; + + //style + html += ""; + + server.send(200, "text/html", html); +} + +void webserverMoisture() { + String response = String(moisture); + server.send(200, "text/plain", response); +} + +void webserverDesiredMoisture() { + if (server.hasArg("desiredMoisture")) { + int newDesiredMoisture = server.arg("desiredMoisture").toInt(); + setDesiredMoisture(newDesiredMoisture); + String response = String(getDesiredMoisture()); + server.send(200, "text/plain", response); + } else { + String response = String(getDesiredMoisture()); + server.send(200, "text/plain", response); + } +} + +void webserverPump() { + if (server.hasArg("set")) { + int setMotorsWeb = server.arg("set").toInt(); + //TODO: add write pump status + if (setMotorsWeb == 1){ + setMotor(true); + }else if (setMotorsWeb == 0){ + setMotor(false); + } + server.send(200, "text/plain", "OK"); + } else { + String response = String(getMotor()); + server.send(200, "text/plain", response); + } +} + + +void setup() { + Serial.begin(115200); + + pinMode(motorPin, OUTPUT); + digitalWrite(motorPin, LOW); + //not really needed + pinMode(12, OUTPUT); + digitalWrite(12, LOW); + + pinMode(sensorPin, INPUT); + + + + // Read the desired moisture level from EEPROM address 0 + EEPROM.begin(128); + desiredMoisture = readLongFromEEPROM(0); + + + + WiFi.begin(ssid, password); + while (WiFi.status() != WL_CONNECTED) { + delay(1000); + Serial.println("Connecting to WiFi..."); + } + + Serial.println("WiFi connected"); + Serial.print("IP address: "); + Serial.println(WiFi.localIP()); + + server.on("/", webserver); + server.on("/moisture", webserverMoisture); + server.on("/desired-moisture", webserverDesiredMoisture); + server.on("/pump", webserverPump); + server.begin(); +} + +unsigned long previousMillis = 0; +const long interval = 1000; // interval in milliseconds +void loop() { + unsigned long currentMillis = millis(); + if (currentMillis - previousMillis >= interval) { + // save the last time you blinked the LED + previousMillis = currentMillis; + waterTrigger(); + } + server.handleClient(); +}