amc:ss2025:group-f:start
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
amc:ss2025:group-f:start [2025/07/28 20:29] – [5. Discussion and Conclusion] 33784_students.hsrw | amc:ss2025:group-f:start [2025/07/29 22:36] (current) – paul-christian.thoma | ||
---|---|---|---|
Line 1: | Line 1: | ||
====== | ====== | ||
+ | **Applied Measurement and Control 2025** | ||
+ | |||
Paul-Christian Thoma(32436)-Elham Mohammadi(32475)-Deniz-Zeynep Adem(33784) | Paul-Christian Thoma(32436)-Elham Mohammadi(32475)-Deniz-Zeynep Adem(33784) | ||
Line 16: | Line 18: | ||
By combining local sensing, cloud-based logic, and remote monitoring tools, this system provides a scalable, modular approach to smart irrigation in home or laboratory environments. | By combining local sensing, cloud-based logic, and remote monitoring tools, this system provides a scalable, modular approach to smart irrigation in home or laboratory environments. | ||
- | {{ amc: | + | {{ : |
**Figure 1.** Automated Plant Watering System Prototype | **Figure 1.** Automated Plant Watering System Prototype | ||
Line 123: | Line 125: | ||
The following diagrams, created using Tinkercad, illustrate the complete hardware connections for both the Sensor and Pump nodes in the system. | The following diagrams, created using Tinkercad, illustrate the complete hardware connections for both the Sensor and Pump nodes in the system. | ||
- | {{ amc: | + | {{ :amc: |
**Figure 2.** Schematic Diagram of Sensor Setup (designed by Deniz-Zeynep Adem) | **Figure 2.** Schematic Diagram of Sensor Setup (designed by Deniz-Zeynep Adem) | ||
| | ||
- | {{ amc: | + | {{ :amc: |
**Figure 3.** Schematic Diagram of Pump Setup (designed by Deniz-Zeynep Adem) | **Figure 3.** Schematic Diagram of Pump Setup (designed by Deniz-Zeynep Adem) | ||
Line 138: | Line 140: | ||
| | ||
+ | |||
<code cpp> | <code cpp> | ||
#include < | #include < | ||
Line 151: | Line 154: | ||
// Google Apps Script webhook URL for sending data to Google Sheets | // Google Apps Script webhook URL for sending data to Google Sheets | ||
- | const char GOOGLE_SHEET_URL[] = " | + | const char GOOGLE_SHEET_URL[] = " |
// MQTT Topics | // MQTT Topics | ||
Line 185: | Line 188: | ||
// Format data as JSON payload | // Format data as JSON payload | ||
- | String | + | String |
+ | if (status == "Dry" | ||
+ | action = "Pump is ON 💧"; | ||
+ | } else if (status == "Moist") { | ||
+ | action = "OK 👍"; | ||
+ | } else { | ||
+ | action = "Alert ⚠️ Maintenance Needed"; | ||
+ | } | ||
+ | |||
+ | String jsonPayload = "{\" | ||
+ | " | ||
+ | " | ||
Serial.println(" | Serial.println(" | ||
Line 213: | Line 228: | ||
if (millis() - lastRead > readInterval) { | if (millis() - lastRead > readInterval) { | ||
int value = analogRead(sensorPin); | int value = analogRead(sensorPin); | ||
- | String status = value > threshold ? " | + | String status = value > threshold ? " |
// Publish raw value and status to MQTT topics | // Publish raw value and status to MQTT topics | ||
Line 229: | Line 244: | ||
// If soil is dry, send water command | // If soil is dry, send water command | ||
- | if (status | + | if (status.startsWith(" |
mqtt.publish(COMMAND_TOPIC, | mqtt.publish(COMMAND_TOPIC, | ||
} | } | ||
Line 246: | Line 261: | ||
#include < | #include < | ||
#include < | #include < | ||
- | #include < | + | #include < |
+ | #include < | ||
- | // WiFi credentials | + | // Wi-Fi credentials |
- | const char* ssid = "YOUR_WIFI_SSID"; | + | const char* ssid = "iotlab"; |
- | const char* password = "YOUR_WIFI_PASSWORD"; | + | const char* password = "iotlab18"; |
- | // MQTT broker | + | // MQTT broker |
const char* mqtt_server = " | const char* mqtt_server = " | ||
+ | const char* control_topic = " | ||
- | WiFiClient espClient; | + | // Google Apps Script Web App URL |
- | PubSubClient client(espClient); | + | const char* google_script_url = " |
- | Servo pumpServo; | + | WiFiClient espClient; |
- | const int servoPin = 5; // Pin connected to the servo | + | PubSubClient client(espClient); |
+ | |||
+ | Servo pumpServo; | ||
+ | const int servoPin = 5; | ||
- | // Function to connect to WiFi | ||
void setup_wifi() { | void setup_wifi() { | ||
+ | Serial.print(" | ||
WiFi.begin(ssid, | WiFi.begin(ssid, | ||
while (WiFi.status() != WL_CONNECTED) { | while (WiFi.status() != WL_CONNECTED) { | ||
Line 271: | Line 291: | ||
} | } | ||
- | // Callback function that handles incoming MQTT messages | + | void postToGoogleSheet(const String& status, const String& action) { |
+ | if (WiFi.status() == WL_CONNECTED) { | ||
+ | HTTPClient http; | ||
+ | http.begin(google_script_url); | ||
+ | http.addHeader(" | ||
+ | |||
+ | | ||
+ | String payload = " | ||
+ | |||
+ | int httpResponseCode = http.POST(payload); | ||
+ | Serial.print(" | ||
+ | Serial.println(httpResponseCode); | ||
+ | http.end(); | ||
+ | } else { | ||
+ | Serial.println(" | ||
+ | } | ||
+ | } | ||
void callback(char* topic, byte* payload, unsigned int length) { | void callback(char* topic, byte* payload, unsigned int length) { | ||
- | String msg = ""; | + | String msg = ""; |
- | for (int i = 0; i < length; i++) msg += (char)payload[i]; | + | for (unsigned |
- | msg.trim(); | + | |
+ | } | ||
+ | msg.trim(); | ||
- | Serial.print(" | + | Serial.print(" |
Serial.print(topic); | Serial.print(topic); | ||
- | Serial.print(": | + | Serial.print(" |
Serial.println(msg); | Serial.println(msg); | ||
- | | + | if (String(topic) == control_topic) { |
- | | + | if (msg == " |
- | if (msg == " | + | pumpServo.write(180); |
- | pumpServo.write(180); | + | Serial.println(" |
+ | postToGoogleSheet(" | ||
} else if (msg == " | } else if (msg == " | ||
- | pumpServo.write(90); | + | pumpServo.write(90); |
+ | Serial.println(" | ||
+ | postToGoogleSheet(" | ||
} | } | ||
} | } | ||
} | } | ||
- | // Function to (re)connect to MQTT and subscribe to topic | ||
void reconnect() { | void reconnect() { | ||
while (!client.connected()) { | while (!client.connected()) { | ||
- | Serial.print(" | + | Serial.print(" |
- | if (client.connect(" | + | if (client.connect(" |
Serial.println(" | Serial.println(" | ||
- | client.subscribe(" | + | client.subscribe(control_topic); |
} else { | } else { | ||
Serial.print(" | Serial.print(" | ||
- | Serial.println(client.state()); | + | Serial.print(client.state()); |
- | delay(2000); | + | delay(2000); |
} | } | ||
} | } | ||
Line 308: | Line 349: | ||
void setup() { | void setup() { | ||
- | Serial.begin(115200); | + | Serial.begin(115200); |
- | setup_wifi(); | + | setup_wifi(); |
- | pumpServo.attach(servoPin); | + | pumpServo.attach(servoPin); |
- | pumpServo.write(90); | + | pumpServo.write(90); |
- | + | client.setServer(mqtt_server, | |
- | client.setServer(mqtt_server, | + | client.setCallback(callback); |
- | client.setCallback(callback); | + | |
} | } | ||
void loop() { | void loop() { | ||
- | if (!client.connected()) reconnect(); | + | if (!client.connected()) |
- | client.loop(); | + | |
+ | } | ||
+ | client.loop(); | ||
} | } | ||
</ | </ | ||
Line 456: | Line 498: | ||
**4. Integrate the Web App URL into Your ESP32 Code** | **4. Integrate the Web App URL into Your ESP32 Code** | ||
- | In your ESP32 Arduino code, update the `GOOGLE_SHEET_URL`: | + | In your ESP32 Arduino code, update the `GOOGLE_SHEET_URL` |
'' | '' | ||
Line 464: | Line 506: | ||
'' | '' | ||
- | |||
- | // | ||
- | |||
Line 472: | Line 511: | ||
**5. Upload and Run the ESP32 Code** | **5. Upload and Run the ESP32 Code** | ||
- | Upload your finalized ESP32 code via Arduino IDE or PlatformIO. | + | Upload your finalized ESP32 code via Arduino IDE. |
* **The ESP32 will:** | * **The ESP32 will:** | ||
Line 495: | Line 534: | ||
**Google Apps Script Codes:** | **Google Apps Script Codes:** | ||
+ | <code cpp> | ||
+ | function doPost(e) { | ||
try { | try { | ||
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(" | const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(" | ||
const data = JSON.parse(e.postData.contents); | const data = JSON.parse(e.postData.contents); | ||
+ | |||
const status = data.status || ""; | const status = data.status || ""; | ||
const moisture = data.moisture || ""; | const moisture = data.moisture || ""; | ||
const action = data.action || ""; | const action = data.action || ""; | ||
const timestamp = new Date(); | const timestamp = new Date(); | ||
- | | + | |
+ | | ||
sheet.insertRows(2, | sheet.insertRows(2, | ||
- | sheet.getRange(2, | + | sheet.getRange(2, |
- | sheet.getRange(2, | + | sheet.getRange(2, |
- | sheet.getRange(2, | + | sheet.getRange(2, |
- | sheet.getRange(2, | + | sheet.getRange(2, |
- | // Optional: | + | |
+ | // Send emails if there is an alert | ||
if (action.toLowerCase().includes(" | if (action.toLowerCase().includes(" | ||
- | | + | |
- | const subject = " | + | `Soil Alert!\nStatus: ${status}\nMoisture: |
- | const message = `An alert has been logged in your system:\n\n` + | + | |
- | `Status: ${status}\nMoisture: | + | |
- | MailApp.sendEmail(emailAddress, | + | |
} | } | ||
+ | |||
return ContentService.createTextOutput(" | return ContentService.createTextOutput(" | ||
- | } catch (error) { | + | } catch (err) { |
- | Logger.log(" | + | return ContentService.createTextOutput(" |
- | return ContentService.createTextOutput(" | + | |
| | ||
} | } | ||
+ | } | ||
+ | |||
+ | </ | ||
====== | ====== | ||
Line 533: | Line 576: | ||
Below is a video showcasing the node-Red flow and showing the code and possible errors that came up and how they were fixed. Starting with the discussion part of this documentation. | Below is a video showcasing the node-Red flow and showing the code and possible errors that came up and how they were fixed. Starting with the discussion part of this documentation. | ||
- | https:// | + | {{ : |
**Figure 4.** Documentation of the data in note-red (designed by Paul-Christian Thoma) | **Figure 4.** Documentation of the data in note-red (designed by Paul-Christian Thoma) | ||
Line 582: | Line 624: | ||
- | {{youtube> | + | {{youtube> |
- | + | ||
- | + | ||
+ | {{youtube> | ||
+ | {{youtube> | ||
amc/ss2025/group-f/start.1753727384.txt.gz · Last modified: 2025/07/28 20:29 by 33784_students.hsrw