Food shortage is the next global crisis we are about experience after Covid-19 pandemic and the effect of this is much bigger than Covid-19. As a Sri Lankan we are already facing the problem and it is about to expand to entire world. Obviously climate changes are most vital and biggest problem in 21st century but it is kind an umbrella term for all the crises we are facing today. However, I am going to find a solution to this urgent crisis "food shortage".
To overcome the food shortage our government is suggested to create and improve home garden and as a result a lot of people tend to cultivate edible plants in their home garden but the problem is how monitor the plantation with busy life style. For example I always forget to water my plants daily basis. So my solution is the automation with AI. I am planning to develop a system that it will monitor soil moisture, temperature and humidity and automate the watering system according to the environment condition using Seeed Studio LoRaWAN Dev Kit. This is actually a small fraction of the total solution. I am planning to expand this system with computer vision where we can use AI based model to identify the crops growth, plant deceases, pest and weeds. This is going to be a total monitoring system.
How the Solution Works?Automated watering system : using soil moisture, temperature and humidity sensors data and using pre-train AI model the system command electronically controlled water valve to provide the water to plant (how much water need for the plant will be decided by the AI model.
Crops monitoring system : Currently I am working on a research project where I am collecting plants samples with different diseases, pests and weed to build an AI model to predict whether plant is healthy or not. I will collect plant image data using Grove - Vision AI Module and pass it to my AI model for predict and there user can have total monitoring over their home garden.
Wio Terminal KitThe Wio Terminal is a SAMD51-based microcontroller with Wireless Connectivity powered by Realtek RTL8720DN that’s compatible with Arduino and MicroPython. Currently, wireless connectivity is only supported by Arduino. It runs at 120MHz (Boost up to 200MHz), 4MB External Flash and 192KB RAM. It supports both Bluetooth and Wi-Fi providing backbone for IoT projects. The Wio Terminal itself is equipped with a 2.4” LCD Screen, onboard IMU(LIS3DHTR), Microphone, Buzzer, microSD card slot, Light sensor, and Infrared Emitter(IR 940nm). On top of that, it also has two multifunctional Grove ports for Grove Ecosystem and 40 Raspberry pi compatible pin GPIO for more add-ons.
The kit is available at https://www.seeedstudio.com/Seeed-Studio-LoRaWAN-Dev-Kit-p-5370.html
Let's Build with Me...First we need to build a Bluetooth control water pump. For this we need submersible water pump, relay module and ESP32.
Here is the circuit diagram.
For the programming ESP32 you need to have Arduino IDE 2 and you need to install ESP32 into the Arduino IDE. Click here to get info for setting up your development environment. Once you have done the setup part you can use below code to test your Bluetooth powered water pump.
#include "BLEDevice.h"
#include <Wire.h>
#define bleServerName "Wio Micro Agro"
#define ONBOARD_LED 2
#define PUMP_PIN 3
static BLEUUID pumpServiceUUID("180f");
static BLEUUID pumpCharacteristicUUID("2a19");
static boolean doConnect = false;
static boolean connected = false;
static BLEAddress *pServerAddress;
static BLERemoteCharacteristic* pumpCharacteristic;
const uint8_t notificationOn[] = {0x1, 0x0};
const uint8_t notificationOff[] = {0x0, 0x0};
char* pumpChar;
boolean newPumpState = false;
bool connectToServer(BLEAddress pAddress) {
BLEClient* pClient = BLEDevice::createClient();
pClient->connect(pAddress);
Serial.println(" - Connected to server");
BLERemoteService* pRemoteService = pClient->getService(pumpServiceUUID);
if (pRemoteService == nullptr) {
Serial.print("Failed to find our service UUID: ");
Serial.println(pumpServiceUUID.toString().c_str());
return (false);
}
pumpCharacteristic = pRemoteService->getCharacteristic(pumpCharacteristicUUID);
if (pumpCharacteristic == nullptr) {
Serial.print("Failed to find our characteristic UUID");
return false;
}
Serial.println(" - Found our characteristics");
pumpCharacteristic->registerForNotify(pumpNotifyCallback);
return true;
}
class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
void onResult(BLEAdvertisedDevice advertisedDevice) {
if (advertisedDevice.getName() == bleServerName) {
advertisedDevice.getScan()->stop();
pServerAddress = new BLEAddress(advertisedDevice.getAddress());
doConnect = true;
Serial.println("Device found. Connecting!");
}
}
};
static void pumpNotifyCallback(BLERemoteCharacteristic* pBLERemoteCharacteristic,
uint8_t* pData, size_t length, bool isNotify) {
pumpChar = (char*)pData;
newPumpState = true;
}
void setup() {
Serial.begin(115200);
Serial.println("Starting Arduino BLE Client application...");
BLEDevice::init("");
BLEScan* pBLEScan = BLEDevice::getScan();
pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
pBLEScan->setActiveScan(true);
pBLEScan->start(30);
pinMode(ONBOARD_LED, OUTPUT);
pinMode(PUMP_PIN, OUTPUT);
}
void loop() {
if (doConnect == true) {
if (connectToServer(*pServerAddress)) {
Serial.println("We are now connected to the BLE Server.");
pumpCharacteristic->getDescriptor(BLEUUID((uint16_t)0x4545))->writeValue((uint8_t*)notificationOn, 2, true);
connected = true;
} else {
Serial.println("We have failed to connect to the server; Restart your device to scan for nearby BLE server again.");
}
doConnect = false;
}
std::string value = pumpCharacteristic->readValue();
Serial.print("Pump state by BLE server = ");
Serial.println(value.c_str());
if(value=="on"){
Serial.println("On");
digitalWrite(ONBOARD_LED, HIGH);
digitalWrite(PUMP_PIN, HIGH);
}
else{
Serial.println("Off");
digitalWrite(ONBOARD_LED, LOW);
digitalWrite(PUMP_PIN, LOW);
}
delay(1000);
}
For testing the pump you can use "Bluetooth Serial Terminal Android App". To switch on the pump sent "pump001-on" and to switch off the pump send "pump001-off" using the serial command.
Next, let's setup the Wio Terminal to read temperature, humidity and soil moisture and display on the TFT LCD screen.
Click here you can find a complete guide how to setup Wio terminal. The guide is very descriptive and straight forward to follow with the lot of videos.
Let's start building sensor and display component. For this you need followings.
Connect your Grove SHT40 temperature sensor to Wio terminal using one of the cable provided with the kit as shown in above illustration.
Download below 2 libraries and install them inside Arduino by
Sketch -> Include library -> Add.ZIP library
Use below code snippet to try yourself to check the sensors.
#include <Arduino.h>
#include <SensirionI2CSht4x.h>
#include <Wire.h>
SensirionI2CSht4x sht4x;
void setup() {
Serial.begin(115200);
while (!Serial) {
delay(100);
}
Wire.begin();
uint16_t error;
char errorMessage[256];
sht4x.begin(Wire);
uint32_t serialNumber;
error = sht4x.serialNumber(serialNumber);
if (error) {
Serial.print("Error trying to execute serialNumber(): ");
errorToString(error, errorMessage, 256);
Serial.println(errorMessage);
} else {
Serial.print("Serial Number: ");
Serial.println(serialNumber);
}
}
void loop() {
uint16_t error;
char errorMessage[256];
delay(1000);
float temperature;
float humidity;
error = sht4x.measureHighPrecision(temperature, humidity);
if (error) {
Serial.print("Error trying to execute measureHighPrecision(): ");
errorToString(error, errorMessage, 256);
Serial.println(errorMessage);
} else {
Serial.print("Temperature:");
Serial.print(temperature);
Serial.print("\t");
Serial.print("Humidity:");
Serial.println(humidity);
}
}
Let's connect soil moisture sensor with Wio terminal. The soil moisture sensor is simple analog sensor therefore you do not need to downlead or install any library. Simply plug in the sensor into Wio Terminal Grove connector and upload the below code.
int sensorPin = A0;
int sensorValue = 0;
void setup() {
Serial.begin(9600);
}
void loop() {
// read the value from the sensor:
sensorValue = analogRead(sensorPin);
Serial.print("Moisture = " );
Serial.println(sensorValue);
delay(1000);
}
As you can see how easy to connect Grove sensors into the Wio Terminal and programming Wio Terminal in this way. The complete code you can find in the attachment section.
Now let's move to see how to display these sensor value in Wio Terminal display.
For LCD you have to download one library called Seeed Arduino LCD. Follow the same instructions above to install the library. You can find complete guide in here.
Seeed Studio provides comprehensive user guides for the entire Wio Terminal development journey and you can find it here. I highly recommend you refer those if you find any difficulty.
Next install the Adafruit Zero DMA Library by
- Navigate to Sketch -> Library manager -> Manage library
- Search for Adafruit Zero DMA and click Install.
#include <Arduino.h>
#include <SensirionI2CSht4x.h>
#include <Wire.h>
#include "TFT_eSPI.h"
SensirionI2CSht4x sht4x;
int sensorPin = A0;
int sensorValue = 0;
TFT_eSPI tft;
TFT_eSprite spr = TFT_eSprite(&tft);
void setup() {
Serial.begin(115200);
while (!Serial) {
delay(100);
}
Wire.begin();
uint16_t error;
char errorMessage[256];
sht4x.begin(Wire);
uint32_t serialNumber;
error = sht4x.serialNumber(serialNumber);
if (error) {
Serial.print("Error trying to execute serialNumber(): ");
errorToString(error, errorMessage, 256);
Serial.println(errorMessage);
} else {
Serial.print("Serial Number: ");
Serial.println(serialNumber);
}
tft.begin();
tft.setRotation(3);
spr.createSprite(TFT_HEIGHT, TFT_WIDTH);
}
void loop() {
uint16_t error;
char errorMessage[256];
float temperature;
float humidity;
float moisture;
String pump = "OFF";
error = sht4x.measureHighPrecision(temperature, humidity);
if (error) {
Serial.print("Error trying to execute measureHighPrecision(): ");
errorToString(error, errorMessage, 256);
Serial.println(errorMessage);
}
delay(1000);
// read the value from the sensor:
sensorValue = analogRead(sensorPin);
moisture = map(sensorValue, 1023, 0, 100, 0);
delay(1000);
// Drawing header
spr.fillSprite(TFT_WHITE);
spr.fillRect(0, 0, 320, 50, TFT_OLIVE);
spr.setTextColor(TFT_WHITE);
spr.setTextSize(3);
spr.drawString("Wio Micro Agro", 30, 15);
spr.drawFastVLine(150, 50, 190, TFT_OLIVE);
spr.drawFastHLine(0, 140, 320, TFT_OLIVE);
// Display
spr.fillRect(0, 50, 150, 90, TFT_RED);
spr.setTextColor(TFT_WHITE);
spr.setTextSize(2);
spr.drawString("Temperature",10,65);
spr.setTextSize(3);
spr.drawNumber(temperature, 50,95);
spr.drawString("C", 90,95);
// Display humidity
spr.fillRect(0, 140, 150, 100, TFT_NAVY);
spr.setTextColor(TFT_WHITE);
spr.setTextSize(2);
spr.drawString("Humidity",25,160);
spr.setTextSize(3);
spr.drawNumber(humidity, 30,190);
spr.drawString("%RH", 70,190);
// Display soil moisture
spr.fillRect(150, 50, 170, 90, TFT_DARKGREEN);
spr.setTextColor(TFT_WHITE);
spr.setTextSize(2);
spr.drawString("Soil Moisture",160,65);
spr.setTextSize(3);
spr.drawNumber(moisture, 200,95);
spr.drawString("%", 240, 95);
// Display water pump status
spr.fillRect(150, 140, 170, 100, TFT_YELLOW);
spr.setTextColor(TFT_BLACK);
spr.setTextSize(2);
spr.drawString("Water Pump",180,160);
spr.setTextSize(3);
spr.drawString(pump, 205,190);
spr.pushSprite(0,0);
delay(50);
}
The output looks like this.
For the complete code please refer attachment section.
Let's command water pump using Bluetooth. Previously we have built the Bluetooth powered water pump now time control it using Wio Terminal.
In order to Bluetooth to work there are few steps you have to follow. It is better if you can follow the instructions are given by Seeed. Click here to access to guide and continue this afterward.
Important once you've done firmware update, in order to exist from "Burn RTL87..." mode upload any sketch into the Wio Terminal using Arduino IDELet's Us Use Bluetooth
Basically BLE (Bluetooth Low Energy) acts as a server/client. Here BLE water pump controller acts as a client and Wio Terminal acts as a BLE server. I have already provided the client code earlier and also I attached it to the attachement section. Using this tutorial you get better understanding of BLE.
For the BLE server code please check the below code
#include <rpcBLEDevice.h>
#include <BLEServer.h>
#define SERVICE_UUID "180f"
#define CHARACTERISTIC_UUID "2a19"
#define DESCRIPTOR_UUID "4545"
BLECharacteristic *pCharacteristic;
class MyCallbacks: public BLECharacteristicCallbacks {
void onWrite(BLECharacteristic *pCharacteristic) {
std::string rxValue = pCharacteristic->getValue();
if (rxValue.length() > 0) {
Serial.println("*********");
Serial.print("Received Value: ");
for (int i = 0; i < rxValue.length(); i++)
Serial.print(rxValue[i]);
Serial.println();
Serial.println("*********");
}
}
};
void setup() {
Serial.begin(115200);
while(!Serial){};
Serial.println("Starting BLE work!");
BLEDevice::init("Wio Micro Agro");
BLEServer *pServer = BLEDevice::createServer();
BLEService *pService = pServer->createService(SERVICE_UUID);
pCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID,
BLECharacteristic::PROPERTY_READ |
BLECharacteristic::PROPERTY_WRITE
);
pCharacteristic->setAccessPermissions(GATT_PERM_READ | GATT_PERM_WRITE);
BLEDescriptor *pDescriptor = pCharacteristic->createDescriptor(
DESCRIPTOR_UUID,
ATTRIB_FLAG_VOID | ATTRIB_FLAG_ASCII_Z,
GATT_PERM_READ | GATT_PERM_WRITE,
2
);
pCharacteristic->setValue("123");
pCharacteristic->setCallbacks(new MyCallbacks());
pService->start();
BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
pAdvertising->addServiceUUID(SERVICE_UUID);
pAdvertising->setScanResponse(true);
pAdvertising->setMinPreferred(0x06); // functions that help with iPhone connections issue
pAdvertising->setMinPreferred(0x12);
BLEDevice::startAdvertising();
Serial.println("Characteristic defined! Now you can read it in your phone!");
}
void loop() {
if (Serial.available()) {
static char value[20] ;
sprintf(value, "%d", Serial.read());
pCharacteristic->setValue(value);
}
delay(2000);
}
You can refer this guide from Seeed for Wio Terminal as BLE server. Now let's add sensor reading with the BLE code together. Since the code is very lengthy I added it to attachment section for your reference.
Incompatible: While I was combining two parts (sensor/LCD and BLE) it seemsed like LCD related libirary and BLE related libraries are having complicts and I could not be able to proceed further. Therefore I paused my work untill I find a way to sort out the issue.
I would really appreciate your time that you spent up to this point to build with me this project. Once I've found a solution I will continue the project.
Why do we need AI ?Even though I couldn't find the solution for the above issue I would like to share some information about what I was planning to do. This AI based smart watering system check the soil moisture level to turn on the pump but we do not have any clue how much water need for the plant. This water requirement is depend on the plant and environment condition so my plan was to build regression model (temperature and humidity will be the feature of the model) to calculate the water requirement (simply we can decide how many seconds or minutes we need to keep on the water pump). In that way we can manage the water requirement and also we can minimixe the water usage and prevent wasting of water. Because water is the utmost important thing for living beings.
Comments
Please log in or sign up to comment.