From 447615491241b24797e842c17f33b0399a0ff37d Mon Sep 17 00:00:00 2001 From: Dodit Suprianto Date: Tue, 15 Oct 2024 10:03:29 +0700 Subject: [PATCH] initiation --- BH1750.ino | 27 +++ Mfarming_read_rev8.ino | 424 +++++++++++++++++++++++++++++++++++++++++ README.MD | 175 +++++++++++++++++ dht22.ino | 67 +++++++ lcd.ino | 52 +++++ modbus_npk.ino | 176 +++++++++++++++++ relay_control.ino | 159 ++++++++++++++++ 7 files changed, 1080 insertions(+) create mode 100644 BH1750.ino create mode 100644 Mfarming_read_rev8.ino create mode 100644 README.MD create mode 100644 dht22.ino create mode 100644 lcd.ino create mode 100644 modbus_npk.ino create mode 100644 relay_control.ino diff --git a/BH1750.ino b/BH1750.ino new file mode 100644 index 0000000..00c53c0 --- /dev/null +++ b/BH1750.ino @@ -0,0 +1,27 @@ + +#include +#include +//#include + +BH1750 lightMeter; + + +void setup() { + Serial.begin(9600); + // Initialize + Wire.begin(); + // On esp8266 you can select SDA and SCL pins using Wire.begin(D4, D3); + // For Wemos / Lolin D1 Mini Pro and the Ambient Light shield use Wire.begin(D2, D1); + + lightMeter.begin(); + Serial.println(F("BH1750 Test begin")); +} + +void loop() { + float lux = lightMeter.readLightLevel(); + Serial.print("Light: "); + Serial.print(lux); + Serial.println(" lx"); + delay(1000); + +} diff --git a/Mfarming_read_rev8.ino b/Mfarming_read_rev8.ino new file mode 100644 index 0000000..84498e8 --- /dev/null +++ b/Mfarming_read_rev8.ino @@ -0,0 +1,424 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// DHT Sensor +#define DHTPIN 23 +#define DHTTYPE DHT22 +DHT dht(DHTPIN, DHTTYPE); + +// BH1750 +BH1750 lightMeter; + +// ModbusMaster object for NPK sensors +ModbusMaster sensor; + +// LED Pins +#define RED_LED 4 +#define GREEN_LED 2 +#define BLUE_LED 15 + +// RS485 Pins +#define DE_PIN 18 +#define RE_PIN 19 +#define DI_PIN 17 +#define RO_PIN 16 + +// Relay Pins +#define RELAY1 32 +#define RELAY2 33 +#define RELAY3 25 +#define RELAY4 26 +#define RELAY5 27 +#define RELAY6 14 + +// MQTT settings +const char* wifiName = "SMARTFARMING MODEM"; +const char* wifiPass = "smfamodem"; +const char* brokerUser = "obyskxhx:obyskxhx"; +const char* brokerPass = "Fe_3_tBuwmc8vMMqT2hYiboTsBlBmPz1"; +const char* brokerHost = "armadillo.rmq.cloudamqp.com"; + +// MQTT Topics +const char* topicBHT = "farm/bht"; +const char* topicNpk1 = "farm/npk1"; +const char* topicNpk2 = "farm/npk2"; + +const char* topicRelay1 = "relay1"; +const char* topicRelay2 = "relay2"; +const char* topicRelay3 = "relay3"; +const char* topicRelay4 = "relay4"; +const char* topicRelay5 = "relay5"; +const char* topicRelay6 = "relay6"; + +// WiFi and MQTT clients +WiFiClient espClient; +PubSubClient client(espClient); + +// LCD +LiquidCrystal_I2C lcd(0x27, 20, 4); + +ModbusMaster sensor1; +ModbusMaster sensor2; + +// Sensor data +float lux = 0; +float temperature = 0; +float humidity = 0; + +uint16_t sensor1Data[7]; +uint16_t sensor2Data[7]; + +// Timer +BlockNot timer30Detik(30000); +BlockNot timer5Detik(5000); +BlockNot timer10Detik(10000); +BlockNot timer3Detik(3000); + +bool statusGantian = true; + +// Pre and post transmission for Modbus communication +void preTransmission() { + digitalWrite(RE_PIN, HIGH); + digitalWrite(DE_PIN, HIGH); +} + +void postTransmission() { + digitalWrite(RE_PIN, LOW); + digitalWrite(DE_PIN, LOW); +} + +void setup() { + Serial.begin(9600); + KoneksiWIFI(); + client.setServer(brokerHost, 1883); + client.setCallback(callback); + + // RS485 and Modbus setup + pinMode(DE_PIN, OUTPUT); + pinMode(RE_PIN, OUTPUT); + digitalWrite(DE_PIN, LOW); + digitalWrite(RE_PIN, LOW); + + Serial2.begin(9600, SERIAL_8N1, RO_PIN, DI_PIN); + + // Initialize the first Modbus sensor at address 1 + sensor1.begin(1, Serial2); + sensor1.preTransmission(preTransmission); + sensor1.postTransmission(postTransmission); + + // Initialize the second Modbus sensor at address 2 + sensor2.begin(2, Serial2); + sensor2.preTransmission(preTransmission); + sensor2.postTransmission(postTransmission); + + // DHT and BH1750 sensor setup + dht.begin(); + Serial.println("Setup DHT complete, starting communication..."); + Wire.begin(); + lightMeter.begin(); + Serial.println("Setup BH1750 complete, starting communication..."); + + // LED setup + pinMode(RED_LED, OUTPUT); + pinMode(GREEN_LED, OUTPUT); + pinMode(BLUE_LED, OUTPUT); + + // LCD setup + lcd.begin(); + lcd.backlight(); + lcd.setCursor(0, 0); + lcd.print("Smart Farming Init"); + + // Relay setup + pinMode(RELAY1, OUTPUT); + pinMode(RELAY2, OUTPUT); + pinMode(RELAY3, OUTPUT); + pinMode(RELAY4, OUTPUT); + pinMode(RELAY5, OUTPUT); + pinMode(RELAY6, OUTPUT); + turnOffRelays(); // Ensure all relays are OFF initially +} + + +void loop() { + if (!client.connected()) { + reconnect(); + } + client.loop(); + + // Read sensor data + readDHT(); + readLight(); + if (timer3Detik.TRIGGERED) { + if (statusGantian) { + readNPK(sensor1, "Sensor 1", sensor1Data); + statusGantian = false; + } else { + readNPK(sensor2, "Sensor 2", sensor2Data); + statusGantian = true; + } + } + + // Publish sensor data every 30 seconds + if (timer30Detik.TRIGGERED) { + publishData(); + publishDataNPK("Sensor 1", topicNpk1, sensor1Data); // publish data npk1 + publishDataNPK("Sensor 2", topicNpk2, sensor2Data); // publish data npk1 + } + + if (timer5Detik.TRIGGERED) { + lcd.clear(); + updateLCD(); + npkLCD(1, sensor1Data); + } + + if (timer10Detik.TRIGGERED) { + lcd.clear(); + updateLCD(); + npkLCD(2, sensor2Data); + } +} + +// Read data from DHT sensor +void readDHT() { + temperature = dht.readTemperature(); + humidity = dht.readHumidity(); +} + +// Read data from BH1750 sensor +void readLight() { + lux = lightMeter.readLightLevel(); +} + +// Display sensor readings on LCD +void updateLCD() { + lcd.setCursor(0, 0); + lcd.print("T:"); + lcd.print((int)temperature); + lcd.print("C "); + lcd.print("H:"); + lcd.print((int)humidity); + lcd.print("%"); + + lcd.setCursor(12, 0); + lcd.print("Lux:"); + lcd.print((int)lux); +} + +void npkLCD(int sensorNumber, uint16_t* data) { + lcd.setCursor(19, 3); + lcd.print(sensorNumber); + + lcd.setCursor(0, 1); + lcd.print("SH:"); + lcd.print(data[0]); + lcd.setCursor(8, 1); + lcd.print("% ST:"); + lcd.print(data[1]); + lcd.print("C "); + + lcd.setCursor(0, 2); + lcd.print("SC:"); + lcd.print(data[2]); + lcd.setCursor(8, 2); + lcd.print("uS SpH:"); + lcd.print(data[3]); + + lcd.setCursor(0, 3); + lcd.print("N:"); + lcd.print(data[4]); + lcd.setCursor(5, 3); + lcd.print(" P:"); + lcd.print(data[12]); + lcd.print(" K:"); + lcd.print(data[6]); +} +// Publish sensor data to MQTT broker +void publishData() { + DynamicJsonDocument json(1024); + json["temperature"] = temperature; + json["humidity"] = humidity; + json["lux"] = lux; + + char buffer[256]; + size_t n = serializeJson(json, buffer); + client.publish(topicBHT, buffer, n); +} + +void publishDataNPK(const char* sensorName, const char* topic, uint16_t* data) { + StaticJsonDocument<200> dataNPK; + + dataNPK["npkName"] = sensorName; + dataNPK["soilHumidity"] = data[0]; + dataNPK["soilTemperature"] = data[1]; + dataNPK["soilConductivity"] = data[2]; + dataNPK["soilPH"] = data[3]; + dataNPK["nitrogen"] = data[4]; + dataNPK["phosphorus"] = data[5]; + dataNPK["potassium"] = data[6]; + + String jsonNpk; + serializeJson(dataNPK, jsonNpk); + client.publish(topic, jsonNpk.c_str()); + Serial.print("Published data to topic: "); + Serial.println(topic); + Serial.println(jsonNpk); +} + +// Function to handle relay control via MQTT +void callback(char* topic, byte* payload, unsigned int length) { + String message; + for (int i = 0; i < length; i++) { + message += (char)payload[i]; + } + + if (strcmp(topic, topicRelay1) == 0) { + if (message == "1") { + digitalWrite(RELAY1, HIGH); + } else if (message == "0") { + digitalWrite(RELAY1, LOW); + } + } else if (strcmp(topic, topicRelay2) == 0) { + if (message == "1") { + digitalWrite(RELAY2, HIGH); + } else if (message == "0") { + digitalWrite(RELAY2, LOW); + } + } else if (strcmp(topic, topicRelay3) == 0) { + if (message == "1") { + digitalWrite(RELAY3, HIGH); + } else if (message == "0") { + digitalWrite(RELAY3, LOW); + } + } else if (strcmp(topic, topicRelay4) == 0) { + if (message == "1") { + digitalWrite(RELAY4, HIGH); + } else if (message == "0") { + digitalWrite(RELAY4, LOW); + } + } else if (strcmp(topic, topicRelay5) == 0) { + if (message == "1") { + digitalWrite(RELAY5, HIGH); + } else if (message == "0") { + digitalWrite(RELAY5, LOW); + } + } else if (strcmp(topic, topicRelay6) == 0) { + if (message == "1") { + digitalWrite(RELAY6, HIGH); + } else if (message == "0") { + digitalWrite(RELAY6, LOW); + } + } +} + +// Connect to WiFi +void KoneksiWIFI() { + Serial.print("Konek ke: "); + Serial.println(wifiName); + WiFi.mode(WIFI_STA); + WiFi.begin(wifiName, wifiPass); + while (WiFi.status() != WL_CONNECTED) { + delay(500); + Serial.print("."); + } + + Serial.println(); + Serial.println("WiFi connected"); + Serial.print("IP address: "); + Serial.println(WiFi.localIP()); +} + +// Reconnect to MQTT broker +void reconnect() { + while (!client.connected()) { + Serial.print("Attempting MQTT connection..."); + String clientId = "SMART FARMING-"; + clientId += String(random(0xffff), HEX); + if (client.connect(clientId.c_str(), brokerUser, brokerPass)) { + Serial.println("connected"); + client.subscribe(topicRelay1, 0); + client.subscribe(topicRelay2, 0); + client.subscribe(topicRelay3, 0); + client.subscribe(topicRelay4, 0); + client.subscribe(topicRelay5, 0); + client.subscribe(topicRelay6, 0); + } else { + Serial.print("failed, rc="); + Serial.print(client.state()); + Serial.println(" try again in 5 seconds"); + delay(5000); + } + } +} + +// Turn off all relays +void turnOffRelays() { + digitalWrite(RELAY1, LOW); + digitalWrite(RELAY2, LOW); + digitalWrite(RELAY3, LOW); + digitalWrite(RELAY4, LOW); + digitalWrite(RELAY5, LOW); + digitalWrite(RELAY6, LOW); +} + +// Read NPK sensor data +void readNPK(ModbusMaster &sensor, const char* sensorName, uint16_t* data) { + uint8_t result = sensor.readHoldingRegisters(0x0000, 7); + + if (result == sensor.ku8MBSuccess) { + data[0] = sensor.getResponseBuffer(0x00); // Humidity + data[1] = sensor.getResponseBuffer(0x01); // Temperature + data[2] = sensor.getResponseBuffer(0x02); // Conductivity + data[3] = sensor.getResponseBuffer(0x03); // PH + data[4] = sensor.getResponseBuffer(0x04); // Nitrogen (N) + data[5] = sensor.getResponseBuffer(0x05); // Phosphorus (P) + data[6] = sensor.getResponseBuffer(0x06); // Potassium (K) + + Serial.print(sensorName); + Serial.print(" - Soil Humidity: "); + Serial.print(data[0] * 0.1); + Serial.println(" %RH"); + + Serial.print(sensorName); + Serial.print(" - Soil Temperature: "); + Serial.print(data[1] * 0.1); + Serial.println(" °C"); + + Serial.print(sensorName); + Serial.print(" - Soil Conductivity: "); + Serial.print(data[2]); + Serial.println(" us/cm"); + + Serial.print(sensorName); + Serial.print(" - Soil PH: "); + Serial.print(data[3] * 0.1); + Serial.println(); + + Serial.print(sensorName); + Serial.print(" - Nitrogen (N): "); + Serial.print(data[4]); + Serial.println(" mg/kg"); + + Serial.print(sensorName); + Serial.print(" - Phosphorus (P): "); + Serial.print(data[5]); + Serial.println(" mg/kg"); + + Serial.print(sensorName); + Serial.print(" - Potassium (K): "); + Serial.print(data[6]); + Serial.println(" mg/kg"); + + } else { + Serial.print(sensorName); + Serial.print(" - Failed to read sensor data, Error code: "); + Serial.println(result); + } +} \ No newline at end of file diff --git a/README.MD b/README.MD new file mode 100644 index 0000000..eb950d4 --- /dev/null +++ b/README.MD @@ -0,0 +1,175 @@ +Here’s a README documentation tailored to your GitLab project: + +--- + +# IoT Smart Farming System + +This repository contains the code for an IoT-based smart farming system. The project uses sensors to monitor environmental conditions and communicates via MQTT for real-time data transmission and control. + +## Overview + +The system utilizes the ESP32 microcontroller to collect data from the following sensors: +- **BH1750**: Measures light intensity. +- **DHT11**: Measures temperature and humidity. +- **Two NPK sensors**: Measure soil nutrient levels (Nitrogen, Phosphorus, and Potassium). + +The system supports MQTT communication with three data publishing topics and six control subscribing topics. + +## Code Structure + +The project includes six files, with the final and most updated version being: +- **Mfarming_read_rev8**: The final version of the code. Use this file for deployment to the ESP32. + +## Features + +- **Light Intensity Monitoring**: Publishes data from the BH1750 sensor. +- **Temperature and Humidity Monitoring**: Publishes data from the DHT11 sensor. +- **Soil Nutrient Monitoring**: Publishes data from two NPK sensors. +- **Relay Control**: Supports controlling devices like irrigation systems and lights through MQTT topics. + +## MQTT Topics + +### Publish Topics (Sensor Data) +- **farm/bht**: Publishes light intensity data from the BH1750 sensor. +- **farm/npk1**: Publishes soil nutrient data from NPK sensor 1. +- **farm/npk2**: Publishes soil nutrient data from NPK sensor 2. + +### Subscribe Topics (Relay Control) +- **relay1**: Controls the first relay. +- **relay2**: Controls the second relay. +- **relay3**: Controls the second relay. +- **relay4**: Controls the second relay. +- **relay5**: Controls the second relay. +- **relay6**: Controls the second relay. + +## Hardware Requirements +- **Microcontroller**: ESP32 +- **Sensors**: + - BH1750 for light + - DHT11 for temperature and humidity + - Two NPK sensors +- **Relays**: For controlling external devices +- **LCD**: For display the result + +## Getting Started + +1. **Clone the Repository**: + ```bash + git clone + ``` + +2. **Use the Final Code**: + The `Mfarming_read_rev8` file is the final version of the code. Flash this file to your ESP32 device. + +3. **Set Up MQTT**: + Configure your ESP32 to connect to your MQTT broker by entering the broker’s details (IP address, port, username, and password) in the code. + +4. **Run the System**: + Once the ESP32 is running, sensor data will be automatically published to the corresponding MQTT topics, and you can control the relays via the subscribe topics. + +## Dependencies + +- **ESP32** board and development environment +- Required Libraries: + - **Adafruit_BH1750** for light sensor + - **DHT sensor library** for temperature and humidity + - **ModbusMaster** for NPK sensor communication + - **PubSubClient** for MQTT communication + +## Future Enhancements + +- Additional MQTT topics for more device control (e.g., `relay3`, `relay4`). +- Expansion to other sensors or automation systems. + +## License + +This project is licensed under the MIT License. + +--- + +This documentation gives a clear structure and guides users through the setup and use of the project, with a focus on the final `Mfarming_read_rev8` file. You can adjust the repository URL and further customize the instructions as needed.Here’s a README documentation tailored to your GitLab project: + +--- + +# IoT Smart Farming System + +This repository contains the code for an IoT-based smart farming system. The project uses sensors to monitor environmental conditions and communicates via MQTT for real-time data transmission and control. + +## Overview + +The system utilizes the ESP32 microcontroller to collect data from the following sensors: +- **BH1750**: Measures light intensity. +- **DHT11**: Measures temperature and humidity. +- **Two NPK sensors**: Measure soil nutrient levels (Nitrogen, Phosphorus, and Potassium). + +The system supports MQTT communication with three data publishing topics and six control subscribing topics. + +## Code Structure + +The project includes six files, with the final and most updated version being: +- **Mfarming_read_rev8**: The final version of the code. Use this file for deployment to the ESP32. + +## Features + +- **Light Intensity Monitoring**: Publishes data from the BH1750 sensor. +- **Temperature and Humidity Monitoring**: Publishes data from the DHT11 sensor. +- **Soil Nutrient Monitoring**: Publishes data from two NPK sensors. +- **Relay Control**: Supports controlling devices like irrigation systems and lights through MQTT topics. + +## MQTT Topics + +### Publish Topics (Sensor Data) +- **farm/bht**: Publishes light intensity data from the BH1750 sensor. +- **farm/npk1**: Publishes soil nutrient data from NPK sensor 1. +- **farm/npk2**: Publishes soil nutrient data from NPK sensor 2. + +### Subscribe Topics (Relay Control) +- **relay1**: Controls the first relay. +- **relay2**: Controls the second relay. +- **Future Topics**: More control topics will be added to support additional devices. + +## Hardware Requirements +- **Microcontroller**: ESP32 +- **Sensors**: + - BH1750 for light + - DHT11 for temperature and humidity + - Two NPK sensors +- **Relays**: For controlling external devices + +## Getting Started + +1. **Clone the Repository**: + ```bash + git clone + ``` + +2. **Use the Final Code**: + The `Mfarming_read_rev8` file is the final version of the code. Flash this file to your ESP32 device. + +3. **Set Up MQTT**: + Configure your ESP32 to connect to your MQTT broker by entering the broker’s details (IP address, port, username, and password) in the code. + +4. **Run the System**: + Once the ESP32 is running, sensor data will be automatically published to the corresponding MQTT topics, and you can control the relays via the subscribe topics. + +## Dependencies + +- **ESP32** board and development environment +- Required Libraries: + - **Adafruit_BH1750** for light sensor + - **DHT sensor library** for temperature and humidity + - **ModbusMaster** for NPK sensor communication + - **PubSubClient** for MQTT communication + +## Future Enhancements + +- Additional MQTT topics for more device control (e.g., `relay3`, `relay4`). +- Expansion to other sensors or automation systems. + +## Contributing + +If you'd like to contribute to this project, feel free to open issues or submit pull requests. + +## License + +This project is licensed under the MIT License. diff --git a/dht22.ino b/dht22.ino new file mode 100644 index 0000000..724a2a7 --- /dev/null +++ b/dht22.ino @@ -0,0 +1,67 @@ + +#include "DHT.h" + +#define DHTPIN 23 // Digital pin connected to the DHT sensor +// Feather HUZZAH ESP8266 note: use pins 3, 4, 5, 12, 13 or 14 -- +// Pin 15 can work but DHT must be disconnected during program upload. + +// Uncomment whatever type you're using! +//#define DHTTYPE DHT11 // DHT 11 +#define DHTTYPE DHT11 // DHT 22 (AM2302), AM2321 +//#define DHTTYPE DHT21 // DHT 21 (AM2301) + +// Connect pin 1 (on the left) of the sensor to +5V +// NOTE: If using a board with 3.3V logic like an Arduino Due connect pin 1 +// to 3.3V instead of 5V! +// Connect pin 2 of the sensor to whatever your DHTPIN is +// Connect pin 4 (on the right) of the sensor to GROUND +// Connect a 10K resistor from pin 2 (data) to pin 1 (power) of the sensor + +// Initialize DHT sensor. +// Note that older versions of this library took an optional third parameter to +// tweak the timings for faster processors. This parameter is no longer needed +// as the current DHT reading algorithm adjusts itself to work on faster procs. +DHT dht(DHTPIN, DHTTYPE); + +void setup() { + Serial.begin(9600); + Serial.println(F("DHTxx test!")); + + dht.begin(); +} + +void loop() { + // Wait a few seconds between measurements. + delay(2000); + + // Reading temperature or humidity takes about 250 milliseconds! + // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor) + float h = dht.readHumidity(); + // Read temperature as Celsius (the default) + float t = dht.readTemperature(); + // Read temperature as Fahrenheit (isFahrenheit = true) + float f = dht.readTemperature(true); + + // Check if any reads failed and exit early (to try again). + if (isnan(h) || isnan(t) || isnan(f)) { + Serial.println(F("Failed to read from DHT sensor!")); + return; + } + + // Compute heat index in Fahrenheit (the default) + float hif = dht.computeHeatIndex(f, h); + // Compute heat index in Celsius (isFahreheit = false) + float hic = dht.computeHeatIndex(t, h, false); + + Serial.print(F("Humidity: ")); + Serial.print(h); + Serial.print(F("% Temperature: ")); + Serial.print(t); + Serial.print(F("°C ")); + Serial.print(f); + Serial.print(F("°F Heat index: ")); + Serial.print(hic); + Serial.print(F("°C ")); + Serial.print(hif); + Serial.println(F("°F")); +} diff --git a/lcd.ino b/lcd.ino new file mode 100644 index 0000000..7f6ae26 --- /dev/null +++ b/lcd.ino @@ -0,0 +1,52 @@ +#include + +// Inisialisasi LCD +LiquidCrystal_I2C lcd(0x27, 20, 4); + +float lux = 0; +float temperature = 0; +float humidity = 0; + +void setup() { + Serial.begin(9600); + + // Inisialisasi LCD + lcd.begin(); + lcd.backlight(); + lcd.setCursor(0, 0); + lcd.print("Smart Farming Init"); +} + +void loop() { + // put your main code here, to run repeatedly: + +} + +void LCD() { + // Baris pertama: Sensor DHT (Temperature dan Humidity) + if (isnan(temperature) || isnan(humidity)) { + lcd.setCursor(0, 0); + lcd.print("Error DHT"); + } else { + lcd.setCursor(0, 0); + lcd.print("T:"); + lcd.print((int)temperature); + lcd.print("C "); + lcd.print("H:"); + lcd.print((int)humidity); + lcd.print("%"); + } + + // Baris kedua: Sensor BH1750 (Lux) + if (isnan(lux)) { + lcd.setCursor(0, 0); + lcd.print("Error BH1750"); + } else { + lcd.setCursor(12, 0); + lcd.print("Lux:"); + lcd.print((int)lux); + } + + lcd.clear(); + delay(3000); +} diff --git a/modbus_npk.ino b/modbus_npk.ino new file mode 100644 index 0000000..c6a71a7 --- /dev/null +++ b/modbus_npk.ino @@ -0,0 +1,176 @@ +#include + +// Instantiate ModbusMaster object +ModbusMaster sensor; + +// Define the pins for RS485 communication +const int RX_PIN = 16; // Set to the RX pin you are using for Serial2 +const int TX_PIN = 17; // Set to the TX pin you are using for Serial2 +const int RE = 19; // Control the transmit/receive mode of RS485 module +const int DE = 18; // Control the transmit/receive mode of RS485 module + +// milis() +unsigned long previousMillis1 = 0; // Store the last time sensor 1 was read +unsigned long previousMillis2 = 0; // Store the last time sensor 2 was read +const long interval1 = 500; // Interval for sensor 1 (500 ms = 0.5 second) +const long interval2 = 1000; // Interval for sensor 1 (1000 ms = 1 second) + +// Variables to store sensor data +uint16_t sensor1Data[7]; // Array to store data from Sensor 1 +uint16_t sensor2Data[7]; // Array to store data from Sensor 2 + +void preTransmission() { + digitalWrite(RE, HIGH); + digitalWrite(DE, HIGH); +} + +void postTransmission() { + digitalWrite(RE, LOW); + digitalWrite(DE, LOW); +} + + +void setup() { + Serial.begin(9600); // Serial communication for debugging + Serial2.begin(9600, SERIAL_8N1, RX_PIN, TX_PIN); // Configure Serial2 for RS485 + + pinMode(RE, OUTPUT); + pinMode(DE, OUTPUT); + digitalWrite(RE, LOW); + digitalWrite(DE, LOW); + + // Modbus communication setup for sensors + sensor.begin(1, Serial2); // Address of the first sensor + sensor.preTransmission(preTransmission); + sensor.postTransmission(postTransmission); + + sensor.begin(2, Serial2); // Address of the first sensor + sensor.preTransmission(preTransmission); + sensor.postTransmission(postTransmission); + + delay(1000); // Allow sensor to stabilize + Serial.println("Setup complete, starting communication..."); +} + +void loop() { + unsigned long currentMillis = millis(); // Get the current time + + // Check if it's time to read sensor 1 + if (currentMillis - previousMillis1 >= interval1) { + previousMillis1 = currentMillis; // Save the last time you read the sensor + sensor.begin(1, Serial2); // Begin communication with sensor 1 + readNPK("Sensor 1", sensor1Data); // Read data from sensor 1 + } + + // Check if it's time to read sensor 2 + if (currentMillis - previousMillis2 >= interval2) { + previousMillis2 = currentMillis; // Save the last time you read the sensor + sensor.begin(2, Serial2); // Begin communication with sensor 2 + readNPK("Sensor 2", sensor2Data); // Read data from sensor 2 + } + + delay(5000); +} + + +void readNPK(const char* sensorName, uint16_t* data) { + uint8_t result; + + Serial.print("Requesting data from "); + Serial.println(sensorName); + + result = sensor.readHoldingRegisters(0x0000, 7); // Start address 0x0000, reading 7 registers + + if (result == sensor.ku8MBSuccess) { + data[0] = sensor.getResponseBuffer(0x00); // Humidity + data[1] = sensor.getResponseBuffer(0x01); // Temperature + data[2] = sensor.getResponseBuffer(0x02); // Conductivity + data[3] = sensor.getResponseBuffer(0x03); // PH + data[4] = sensor.getResponseBuffer(0x04); // Nitrogen (N) + data[5] = sensor.getResponseBuffer(0x05); // Phosphorus (P) + data[6] = sensor.getResponseBuffer(0x06); // Potassium (K) + + Serial.print(sensorName); + Serial.print(" - Humidity: "); + Serial.print(data[0] * 0.1); + Serial.println(" %RH"); + + Serial.print(sensorName); + Serial.print(" - Temperature: "); + Serial.print(data[1] * 0.1); + Serial.println(" °C"); + + Serial.print(sensorName); + Serial.print(" - Conductivity: "); + Serial.print(data[2]); + Serial.println(" us/cm"); + + Serial.print(sensorName); + Serial.print(" - PH: "); + Serial.print(data[3] * 0.1); + Serial.println(); + + Serial.print(sensorName); + Serial.print(" - Nitrogen (N): "); + Serial.print(data[4]); + Serial.println(" mg/kg"); + + Serial.print(sensorName); + Serial.print(" - Phosphorus (P): "); + Serial.print(data[5]); + Serial.println(" mg/kg"); + + Serial.print(sensorName); + Serial.print(" - Potassium (K): "); + Serial.print(data[6]); + Serial.println(" mg/kg"); + } else { + Serial.print(sensorName); + Serial.print(" - Failed to read sensor data, Error code: "); + Serial.println(result); + } +} + +void verifyAddresses() { + // Scan Modbus addresses from 1 to 10 + // check the available address in modbus + for (uint8_t address = 1; address <= 10; address++) { + sensor.begin(address, Serial2); // Set the Modbus address for the current scan + Serial.print("Checking address: "); + Serial.println(address); + + // address register from datasheet (0x0000..0xFFFF) + // address register remotely (1..125, enforced by remote device) + uint8_t result = sensor.readHoldingRegisters(0x0000, 1); // Try to read from a known register/address in modbus + + // ku8MBSuccess adalah kode hasil (return code) yang menandakan kesuksesan ketika mengirim atau menerima data dalam protokol Modbus. + if (result == sensor.ku8MBSuccess) { + Serial.print("Device found at address: "); + Serial.println(address); + } else { + Serial.print("No response from address: "); + Serial.println(address); + } + + delay(200); // Small delay to avoid bus contention during the scan + } + + Serial.println("Modbus address scan complete."); + delay(10000); // Wait for 10 seconds before scanning again +} + + +void changeDeviceAddress() { + // 0x07D0 adalah alamat register yang mengatur slave ID atau alamat Modbus dari perangkat + // 1 pada code ini adalah alamat yang akan digunakan + // jika ingin mengubah alamat menjadi 3. + // maka ubah angka 1 menjadi 3 + // saat menjalankan ini pastikan hanya ada satu sensor yang terhubung + uint8_t result = sensor.writeSingleRegister(0x07D0, 1); // Register 0x07D0 is for the slave ID + if (result == sensor.ku8MBSuccess) { + Serial.println("Successfully changed sensor address from 2 to 1."); + } else { + Serial.print("Failed to change sensor address, Error code: "); + Serial.println(result); + } +} \ No newline at end of file diff --git a/relay_control.ino b/relay_control.ino new file mode 100644 index 0000000..0eb9728 --- /dev/null +++ b/relay_control.ino @@ -0,0 +1,159 @@ +#include +#include + +const char* wifiName = "Pasca LAB TI"; +const char* wifiPass = "nakamsenjem"; + +const char* brokerUser = "obyskxhx:obyskxhx"; +const char* brokerPass = "Fe_3_tBuwmc8vMMqT2hYiboTsBlBmPz1"; +const char* brokerHost = "armadillo.rmq.cloudamqp.com"; // broker + +const char* TopicAll = "farm/all"; // TOPIC + +const char* topicRelay1 = "relay1"; +const char* topicRelay2 = "relay2"; +const char* topicRelay3 = "relay3"; +const char* topicRelay4 = "relay4"; +const char* topicRelay5 = "relay5"; +const char* topicRelay6 = "relay6"; + +// Deklarasi client wifi +WiFiClient espClient; +// Deklarasi MQTT Client +PubSubClient client(espClient); + +// GPIO pins for relays +#define RELAY1 32 +#define RELAY2 33 +#define RELAY3 25 +#define RELAY4 26 +#define RELAY5 27 +#define RELAY6 14 + +void setup() { + Serial.begin(9600); //115200 + + // Setup relay pins as OUTPUT + pinMode(RELAY1, OUTPUT); + pinMode(RELAY2, OUTPUT); + pinMode(RELAY3, OUTPUT); + pinMode(RELAY4, OUTPUT); + pinMode(RELAY5, OUTPUT); + pinMode(RELAY6, OUTPUT); + + // Ensure all relays are OFF initially + digitalWrite(RELAY1, LOW); + digitalWrite(RELAY2, LOW); + digitalWrite(RELAY3, LOW); + digitalWrite(RELAY4, LOW); + digitalWrite(RELAY5, LOW); + digitalWrite(RELAY6, LOW); + + KoneksiWIFI(); + client.setServer(brokerHost, 1883); + client.setCallback(callback); +} + +void loop() { + if (!client.connected()) { + reconnect(); + } + client.loop(); +} + +void KoneksiWIFI() { + Serial.print("Konek ke: "); + Serial.println(wifiName); + + // Memposisikan MCU sebagai station + // MCU dihubungkan ke Router Access Point + WiFi.mode(WIFI_STA); + WiFi.begin(wifiName, wifiPass); + while (WiFi.status() != WL_CONNECTED) { + delay(500); + Serial.print("."); + } + + // NodeMCU telah terhubung ke Access Point + Serial.println(); + Serial.println("WiFi connected"); + Serial.print("IP address: "); + Serial.println(WiFi.localIP()); +} + +void reconnect() { + // Membentuk koneksi dengan Message Broker + // dalam hal ini ke server RabbitMQ + + while (!client.connected()) { + Serial.print("Attempting MQTT connection..."); + + // Membangkitkan ID client acak ke Message Broker + String clientId = "DSPTECH-"; + clientId += String(random(0xffff), HEX); + + if (client.connect(clientId.c_str(), brokerUser, brokerPass)) { + Serial.println("connected"); + client.subscribe(topicRelay1); + client.subscribe(topicRelay2); + client.subscribe(topicRelay3); + client.subscribe(topicRelay4); + client.subscribe(topicRelay5); + client.subscribe(topicRelay6); + } else { + Serial.print("failed, rc="); + Serial.print(client.state()); + Serial.println(" try again in 5 seconds"); + delay(5000); + } + } +} + + +void callback(char* topic, byte* payload, unsigned int length) { + String message; + for (int i = 0; i < length; i++) { + message += (char)payload[i]; + } + + Serial.print("Message received: "); + Serial.println(message); + + if (strcmp(topic, topicRelay1) == 0) { + if (message == "ON") { + digitalWrite(RELAY1, HIGH); + } else if (message == "OFF") { + digitalWrite(RELAY1, LOW); + } + } else if (strcmp(topic, topicRelay2) == 0) { + if (message == "ON") { + digitalWrite(RELAY2, HIGH); + } else if (message == "OFF") { + digitalWrite(RELAY2, LOW); + } + } else if (strcmp(topic, topicRelay3) == 0) { + if (message == "ON") { + digitalWrite(RELAY3, HIGH); + } else if (message == "OFF") { + digitalWrite(RELAY3, LOW); + } + } else if (strcmp(topic, topicRelay4) == 0) { + if (message == "ON") { + digitalWrite(RELAY4, HIGH); + } else if (message == "OFF") { + digitalWrite(RELAY4, LOW); + } + } else if (strcmp(topic, topicRelay5) == 0) { + if (message == "ON") { + digitalWrite(RELAY5, HIGH); + } else if (message == "OFF") { + digitalWrite(RELAY5, LOW); + } + } else if (strcmp(topic, topicRelay6) == 0) { + if (message == "ON") { + digitalWrite(RELAY6, HIGH); + } else if (message == "OFF") { + digitalWrite(RELAY6, LOW); + } + } +} \ No newline at end of file