Click Mushroom Cloud Creation to follow us
IoT Agricultural Soil Nutrient and Weather Station Monitoring System
Introduction
To monitor the growing environment of crops outdoors and in greenhouses, I designed an IoT agricultural monitoring system using Unihiker as the main monitoring core, combined with RS485 soil sensors, temperature and humidity sensors, CO2 sensors, environmental light sensors, etc. It collects soil nutrient data from different nodes, including temperature, humidity, pH, and NPK data, as well as air CO2, temperature, humidity, and light data. It is also equipped with a camera to capture the growth of crops. Unihiker uploads the data to the local server of Lattepanda via wireless WIFI, and we can use the Flask web interface to view the data, and if needed, monitor crops in real-time. This system not only records the environmental data of the greenhouse but also sets up an outdoor weather station with Unihiker to monitor important outdoor environmental parameters in real-time, including wind direction, wind speed, temperature, atmospheric pressure, and rainfall. All uploaded cloud data can provide real-time analysis support for soil nutrients, environmental light, and environmental parameters, as well as provide data marking and learning foundation for future smart agriculture development. The overall program is written in Python, with features such as automatic operation and automatic reconnection after disconnection. The Lattepanda server can display the online status and data of different nodes, and if a node has a problem, it will show that the node is offline, facilitating timely maintenance.
Using this system, we can better detect, control, and study breeding and plant growth. Combined with local monitoring data, we can grasp the environmental parameters and images in the greenhouse in real-time, carry out data collection, data processing, data visualization, and data analysis, and design reasonable plans for future scientific breeding and seedling cultivation.
Hardware List
-
Soil NPK Sensor x5
-
Lattepanda 3 delta x1
-
Unihiker x6
-
CO2 Sensor x3
-
Environmental Light Sensor x3
-
Weather Station SEN0186 x1
-
485 to UART Module x5
-
Temperature and Humidity Sensor x1
-
Unihiker Expansion Board x6
-
Power Adapter x6
-
SCI x 6
-
WIFI Surveillance Camera x1
-
Camera x5
-
Router x1
-
Waterproof Box x6
-
Power Adapter Module x 6
Functions
-
Real-time monitoring of key environmental indicators in the “one-meter field” inside the greenhouse (soil parameters: soil temperature and humidity, soil pH, soil nutrient salts, environmental parameters: CO2 concentration, temperature and humidity, light intensity).
-
Seedling monitoring: Automatic command to take pictures at set intervals, automatically displaying the latest crop seedling images.
-
Weather station monitoring: Real-time monitoring of outdoor weather conditions (wind direction, wind speed, temperature, atmospheric pressure, and rainfall).
-
Displaying monitored data in the cloud.
-
Offline node device online warning.
Solution Topology Diagram
Unihiker Air Board as the main monitoring core, combined with RS485 soil sensors, I2C temperature and humidity sensors, I2C CO2 sensors, I2C environmental light sensors, etc., to collect soil nutrients from different nodes, including temperature, humidity, pH, and NPK data, while also collecting air CO2, temperature, humidity, environmental light, etc., and equipped with a USB camera connected to the Unihiker Air Board to capture the growth of crops. All Unihiker and Lattepanda nodes are on the same local area network, and the Air Board uploads data to the local server of Lattepanda via wireless WIFI.
In the weather station node, Unihiker collects weather station data via UART communication.
Important Technical Indicators
1. Soil Sensor: Used to detect soil nutrient data
-
Soil temperature and humidity, pH value, NPK data
2. Lattepanda 3 delta: Used as the local server
-
Processor: Intel® Celeron® N5105
-
CPU: 2.0~2.9GHz, quad-core, quad-thread
-
GPU: Intel® UHD Graphics (Frequency: 450 – 800MHz)
-
Memory: LPDDR4 8GB 2933MHz
-
Storage: 64GB eMMC V5.1
3. Unihiker: Used as the main control for each node
-
CPU: Domestic 4-core 1.2GHz
-
Memory: 512MB DDR3
-
Storage: 16GB eMMC
-
Built-in Operating System: Debian
-
Wi-Fi: 2.4G
-
Bluetooth: 4.0
-
Physical Buttons: Home button, A/B buttons
-
Screen: 2.8-inch 240*320 TFT color screen
-
Power Supply: Type-C 5V power supply
-
Working Voltage: 3.3V
-
Maximum Working Current: 2000mA
-
Interfaces:
USB Type-C 1
USB TYPE-A 1
microSD card interface 1
3Pin I/O 4 (including 3 PWM 2 ADC)
4Pin I2C 2
Traffic and Storage Estimation
Assuming each node uploads data (including image data) every 5 minutes, with each node’s data being about 1kb and each JPG image being about 30kb, the image files can be directly saved on Lattepanda, and the node data can be stored in the Siot database on the server. If there is additional memory demand, consider increasing the memory module on Lattepanda.
Hardware Connection
1. Taking Node 1 Soil Cultivated Lettuce as an Example, Node 1 – Node 5 Wiring is the Same
USB camera and Air Board USB connection.
RS485 soil sensor, 485 to UART module (DFR0845), and Unihiker expansion board (MBT0008) connection method is as follows. The 485 to UART module and soil sensor are connected using terminal blocks for a more secure connection, and the 485 to UART module and Unihiker expansion board use DuPont wires for connection, it is recommended to use hot melt glue for secondary fixing to prevent loosening of wires.
SCI, sensors (SEN0536, SEN0540, SEN0334) and Unihiker connection method as shown:
2. Weather Station Node
The Weather Station (SEN0186) and Unihiker expansion board (MBT0008) connection method is as follows, using DuPont wires for connection, it is recommended to use hot melt glue for secondary fixing to prevent loosening of wires.
3. Power Supply:
Use FIT0639 and power adapter module to supply power to Unihiker and expansion board (MBT0008).
Setting up the Environment on the LP Server:
Install Server Program Siot
1. Download the Windows version of SIoT, unzip it, and double-click start SIoT.bat to start SIoT. After starting, a command window will pop up to start the server.
2. Enter 127.0.0.1:8080 in the browser to open the web port, login account is siot, password is dfrobot. After opening, you can create a Topic or view messages.
Install Web Application Framework Flask
1. Install Python 3.7 on Windows, download the webpage:
2. Install the Flask library in Python
3. Visit the project website to download the code (see section six), and run the Flask program
cd flask-demo
flask-start.py
4. Enter the URL to access http://127.0.0.1:5000/index (you need to start Siot V2 first to use this Flask Web), on this webpage, you can select to view the sensor data of the nodes via the buttons above.
Router Settings
Log in to the router page on Lattepanda to set the fixed IP for Lattepanda and six Unihikers.
Code:
1. Unihiker taking Node 1 Soil Cultivated Lettuce as an example
(Please enable Unihiker’s startup setting)
# -*- coding: utf-8 -*-import timefrom dfrobot_rp2040_sci import *from pinpong.board import Board, UARTimport serial import timeimport siotimport osfrom unihiker import GUIimport requestsimport base64 import cv2
Board(""").begin() # Initialize, select board type, if not specified, it will auto-detect
SCI1 = DFRobot_RP2040_SCI_IIC(addr=0x21)
u_gui=GUI()# Hard serial port 1 P0-RX P3-TX
uart1 = UART() # ser = serial.Serial("/dev/ttyUSB0",115200,timeout=0.5)# Initialize serial port baud_rate baud rate, bits data bits (8/9) parity parity (0 no parity/1 odd parity/2 even parity) stop stop bits (1/2)
uart1.init(baud_rate = 9600, bits=8, parity=0, stop = 1)
soil_tem_text=u_gui.draw_text(text="soil temperature:NAN",x=0,y=0,font_size=16, color="#0000FF")
soil_hum_text=u_gui.draw_text (text="soil humidity:NAN",x=0,y=30,font_size=16, color="#0000FF")
soil_ph_text=u_gui.draw_text(text="soil ph:NAN",x=0,y=60,font_size=16, color="#0000FF")
soil_N_text=u_gui.draw_text(text="soil N:NAN",x=0,y=90,font_size=16, color="#0000FF")
soil_P_text=u_gui.draw_text(text="soil P:NAN",x=0,y=120,font_size=16, color="#0000FF")
soil_K_text=u_gui.draw_text(text="soil K:NAN",x=0,y=150,font_size=16, color="#0000FF")
CO2_text = u_gui.draw_text(text="CO2:NAN",x=0,y=180,font_size=16, color="#0000FF")
status_text = u_gui.draw_text(text="01_status:NAN",x=0,y=270,font_size=16, color="#0000FF")
air_tem_text=u_gui.draw_text(text="air temperature:NAN",x=0,y=210,font_size=16, color="#0000FF")
air_hum_text=u_gui.draw_text(text="air humidity:NAN",x=0,y=240,font_size=16, color="#0000FF")#lux_text=u_gui.draw_text(text="light lux:NAN",x=0,y=270,font_size=16, color="#0000FF")
while SCI1.begin() != 0: print("Initialization Sensor Universal Adapter Board failed.") time.sleep(1)
print("Initialization Sensor Universal Adapter Board done.")
# Command to send to the sensor
buf = [0x02, 0x03, 0x00, 0x00, 0x00, 0x0A, 0xC5,0xFE]
# Return command 04 sensor address; 03 function code; 14 data length; '00', 'e7' temperature; '00', '00' humidity; 00 00 blank; '00', '28' pH;'00', '00', '00', '00', '00', '00' nitrogen, phosphorus, potassium; '00', '00', '00', '00' blank; '25', '80' baud rate 9600; 25, b2 checksum
#['04', '03', '14', '00', 'e7', '00', '00', '00', '00', '00', '28', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '25', '80', '25', 'b2']
def calc_crc(string): #print(string) #data = bytearray.fromhex(string)
data = ['{:02x}'.format(i) for i in string] #print(data) data = " ".join(data) data = data.replace('0x','') global data2 data2 = data print(data2) data = bytearray.fromhex(data)
crc = 0xFFFF for pos in data: crc ^= pos for i in range(8): if ((crc & 1) != 0): crc >>= 1 crc ^= 0xA001 else: crc >>= 1 return hex(((crc & 0xff) << 8) + (crc >> 8))
def send_photos():
photos_path = '/root/photos' photos_path_list = os.listdir(photos_path) photos_path_list.sort(reverse=False) photos_quan = len(photos_path_list)
photos_count = photos_quan+1 print("count:"+str(photos_count)) cap = cv2.VideoCapture(0) cap.set(cv2.CAP_PROP_FRAME_WIDTH, 320) # Set camera image width cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 240) # Set camera image height cap.set(cv2.CAP_PROP_BUFFERSIZE, 1) # Set OpenCV internal image buffer, can greatly improve image real-time performance.
ret, frame = cap.read() if ret == True: cv2.imwrite(photos_path+'/Frame'+ str(photos_count) +'.jpg', frame) print("save photo!") cap.release()
with open(photos_path+'/Frame'+ str(photos_count) +'.jpg','rb') as f: # b64encode is encoding, b64decode is decoding data = base64.b64encode(f.read()) src = "data:image/{ext};base64,{data}".format(ext='jpg', data=str(data)) #print(src) #print(len(src))
siot.publish_save(topic="siot/节点1/image", data=src) siot.publish_save(topic="siot/image", data=src) print("photos send ok") f.close() status_text.config(text="04_status: photo send ok",x=0,y=290) photos_count = int(photos_count) + 1
flag = 1count=0
while True: air_tem_value=SCI1.get_value0("Temp_Air") air_tem_t = "Temp_Air: "+str(air_tem_value)+"℃" air_tem_text.config(text=air_tem_t,x=0,y=210) air_hum_value=SCI1.get_value0("Humi_Air") air_hum__t = "Humi_Air: "+str(air_hum_value)+"%RH" air_hum_text.config(text=air_hum__t,x=0,y=240)
print("-----------write buf-----------") uart1.write(buf) time.sleep(1) count=0 while uart1.any()==0: print("any:"+str(count)) count=count+1 if count>10: break time.sleep(0.1)
while uart1.any()>0: print("while2:"+str(uart1.any())) #print(uart1.read(uart1.any())) time.sleep(0.01) if uart1.read(1)[0] == 0x02: print("11") time.sleep(0.01) if uart1.read(1)[0] == 0x03: time.sleep(0.01) print("while2:"+str(uart1.any())) data = uart1.read(23) data.insert(0,0x02) data.insert(1,0x03) #print(data) crc = calc_crc((data)) #print(data[11],data(12)) print("crc="+str(crc))
if crc == '0x0': print(data2) data3 = data2.split() #print(str(data3[10])+str(data3[11]))
soil_tem = int(str(data3[3])+str(data3[4]),16)/10 soil_ph = int(str(data3[9])+str(data3[10]),16)/10 soil_hum = int(str(data3[5])+str(data3[6]),16)/10 soil_N = int(str(data3[11])+str(data3[12]),16) soil_P = int(str(data3[13])+str(data3[14]),16) soil_K = int(str(data3[15])+str(data3[16]),16)
soil_ph_t = "soil_ph:"+ str(soil_ph) soil_ph_text.config(text= soil_ph_t ,x=0,y=60) soil_hum_t = "soil_hum: "+str(soil_hum)+"%" soil_hum_text.config(text= soil_hum_t ,x=0,y=30) soil_tem_t = "soil_tem:"+str(soil_tem)+"℃" soil_tem_text.config(text= soil_tem_t ,x=0,y=0) soil_N_t = "soil_N: "+str(soil_N)+"mg/kg" soil_N_text.config(text= soil_N_t ,x=0,y=90) soil_P_t = "soil_P: "+str(soil_P)+"mg/kg" soil_P_text.config(text= soil_P_t ,x=0,y=120) soil_K_t = "soil_K: "+str(soil_K)+"mg/kg" soil_K_text.config(text= soil_K_t ,x=0,y=150)
try : my_variable = requests.get("http://10.1.2.3/wifi/status") print(my_variable.text) status = my_variable.text.split('"')[11] print("wifi: "+status)
status_text.config(text="01_wifi:"+status,x=0,y=270)
siot.init(client_id="unihiker01",server="10.168.1.100",port=1883,user="siot",password="dfrobot") siot.connect() siot.loop() siot.getsubscribe(topic="siot/节点1/土壤温度") siot.getsubscribe(topic="siot/节点1/土壤湿度") siot.getsubscribe(topic="siot/节点1/土壤pH") siot.getsubscribe(topic="siot/节点1/土壤氮") siot.getsubscribe(topic="siot/节点1/土壤磷") siot.getsubscribe(topic="siot/节点1/土壤钾") #siot.getsubscribe(topic="siot/节点1/二氧化碳") siot.getsubscribe(topic="siot/节点1/空气温度") siot.getsubscribe(topic="siot/节点1/空气湿度") siot.getsubscribe(topic="siot/image") siot.getsubscribe(topic="siot/节点1/image")
siot.publish_save(topic="siot/节点1/土壤温度", data=soil_tem) siot.publish_save(topic="siot/节点1/土壤pH", data=soil_ph) siot.publish_save(topic="siot/节点1/土壤湿度", data=soil_hum) siot.publish_save(topic="siot/节点1/土壤氮", data=soil_N) siot.publish_save(topic="siot/节点1/土壤磷", data=soil_P) siot.publish_save(topic="siot/节点1/土壤钾", data=soil_K) siot.publish_save(topic="siot/节点1/空气温度", data=air_tem_value) siot.publish_save(topic="siot/节点1/空气湿度", data=air_hum_value)
if flag == 50: flag = 0 send_photos()
print("send ok") siot.stop() status_text.config(text="01_status: data send ok",x=0,y=270) time.sleep(3600) except : print("wifi正在重连!") status_text.config(text="wifi正在重连!",x=0,y=270) my_variable = requests.get("http://10.1.2.3/wifi/connect?ssid=dfrobot&password=dfrobot2017") # ssid和password后面改为需要连接的wifi名字密码 print(my_variable.text) time.sleep(60) print("查看WiFi连接情况:") my_variable = requests.get("http://10.1.2.3/wifi/status") print(my_variable.text) status = my_variable.text.split('"')[11] print(status) status_text.config(text="01_wifi:"+status,x=0,y=270)
2. Unihiker Weather Station
# -*- coding: utf-8 -*-import timefrom pinpong.board import Board, UARTimport siotimport os
Board("UNIHIKER").begin() # Initialize, select board type, if not specified, it will auto-detect
# Air Board hard serial port 1 P0-RX P3-TX
uart1 = UART() # Initialize serial port baud_rate baud rate, bits data bits (8/9) parity parity (0 no parity/1 odd parity/2 even parity) stop stop bits (1/2)
uart1.init(baud_rate = 9600, bits=8, parity=0, stop = 1) #uart1.init() # Weather station baud rate is 9600
siot.init(client_id="hostclient01",server="10.1.2.3",port=1883,user="siot",password="dfrobot")
while True: databuffer = "" #print(len("c000s000g000t082r000p000h48b10022*3C")) Default word length buf = uart1.readline() #uart1.write(buf) #b = type(buf) #print(b) if buf is None: print("recv None") else: for i in buf: #print(i) a = chr(i) databuffer = databuffer + a
length = len(databuffer) print(databuffer) if length == 38: # If data length is 38 print("databuffer:",databuffer) # Print and display data string
'''Parse to get wind direction data''' try: WindDirection = int(databuffer[1:4]) except: WindDirection = 0 if 0 <= WindDirection and WindDirection < 22.5 or 337.5<=WindDirection and WindDirection < 360: WindDirection_dir = 'S' if 22.5 <= WindDirection and WindDirection < 67.5: WindDirection_dir = 'SW' if 67.5 <= WindDirection and WindDirection < 112.5: WindDirection_dir = 'W' if 112.5 <= WindDirection and WindDirection < 157.5: WindDirection_dir = 'NW' if 157.5 <= WindDirection and WindDirection < 202.5: WindDirection_dir = 'N' if 202.5 <= WindDirection and WindDirection < 247.5: WindDirection_dir = 'NE' if 247.5 <= WindDirection and WindDirection < 292.5: WindDirection_dir = 'E' if 292.5 <= WindDirection and WindDirection < 337.5: WindDirection_dir = 'SE' print("WindDirection:" +str(WindDirection) +" degree","WindDirection_dir:"+WindDirection_dir)
'''Parse to get wind speed data'''# 1 mile per hour = 1609.34 meters/3600 seconds = 0.44703889m/s # Average wind speed for the previous minute try: WindSpeedAverage = round(0.44704 * float(databuffer[5:8]),1) except: WindSpeedAverage = 0 print("Average Wind Speed (One Minute):" + str(WindSpeedAverage) + "m/s ") # Maximum wind speed for the previous five minutes try: WindSpeedMax = round(0.44704 * float(databuffer[9:12]),1) except: WindSpeedMax = 0 print("Max Wind Speed (Five Minutes):" + str(WindSpeedMax) + "m/s")
'''Parse temperature data'''# Celsius = (Fahrenheit-32)*5/9 try: Temperature = round((float(databuffer[13:16]) - 32.00) * 5.00 / 9.00,2) except: Temperature = 0 print("Temperature:" + str(Temperature)+ "℃ ") # print("Temperature:" + "{:.2f}".format(Temperature)+ "C ")
'''Parse humidity data''' try: Humidity = round(float(databuffer[25:27]) ,1) except: Humidity = 0 print("Humidity:" + str(Humidity) +"% ")
'''Parse barometric pressure data''' try: BarPressure = round(float(databuffer[28:33])/ 10.00,1) except: BarPressure = 0 print("BarPressure:" + str(BarPressure) + "hPa")
else: # If length is not 38, then set data to empty databuffer = ""
time.sleep(0.5)
3. Flask Server Program
# -*- coding: UTF-8 -*-from flask import Flask,Response,render_template,requestflask_app = Flask(__name__)
# Event callback function
def rec_route_funca(): print("b click") return "rount_func"
def rec_route_funcb(): print("b click") return "b"
def rec_index(): return render_template("test.html")
@flask_app.route('/index',methods=['GET','POST'])
def route_index(): return rec_index()
flask_app.run(host='0.0.0.0', port=5000, threaded=True)
4. Server Program (Save Images, Query Node Online Status)
# -*- coding: UTF-8 -*-# MindPlus# Pythonimport timeimport siotimport os
ip = ['ping 10.168.1.114','ping 10.168.1.117','ping 10.168.1.118','ping 10.168.1.122','ping 10.168.1.115','ping 10.168.1.112']
# Event callback function
def on_message_callback(client, userdata, msg): global P1 global N1 global K1
global P5 global N5 global K5
global sendata1 global sendata5 global sendataw global sendata
global weather_hum global weather_tem
global indoor_hum global indoor_tem
if (msg.topic.find("表格")!=-1): pass else: if (msg.topic.find("节点1/土壤氮")!=-1): N1 = msg.payload.decode() print(msg.topic) print(N1) if (msg.topic.find("节点1/土壤磷")!=-1): P1 = msg.payload.decode() print(msg.topic) print(P1) if (msg.topic.find("节点1/土壤钾")!=-1): K1 = msg.payload.decode() print(msg.topic) print(K1)
status = ((not (P1 == 0)) and (not (N1 == 0)))
if ((not (status == 0)) and (not (K1 == 0))): sendata1 = N1 +","+ P1 +","+ K1 print(sendata1) siot.publish_save(topic="siot/节点1/氮磷钾总和表格", data=sendata1)
if (msg.topic.find("节点5/土壤氮")!=-1): N5 = msg.payload.decode() print(msg.topic) print(N5) if (msg.topic.find("节点5/土壤磷")!=-1): P5 = msg.payload.decode() print(msg.topic) print(P5) if (msg.topic.find("节点5/土壤钾")!=-1): K5 = msg.payload.decode() print(msg.topic) print(K5)
status = ((not (P5 == 0)) and (not (N5 == 0)))
if ((not (status == 0)) and (not (K5 == 0))): sendata5 = N5 +","+ P5 +","+ K5 print(sendata5) siot.publish_save(topic="siot/节点5/氮磷钾总和表格", data=sendata5)
if (msg.topic.find("气象站/温度")!=-1): weather_tem = msg.payload.decode() print((str(msg.topic) + str(weather_tem))) if (msg.topic.find("气象站/湿度")!=-1): weather_hum = msg.payload.decode() print((str(msg.topic) + str(weather_hum)))
if ((not (weather_hum == 0)) and (not (weather_tem == 0))): sendataw = weather_hum+ "," + weather_tem print(sendataw) siot.publish_save(topic="siot/气象站/温湿度表格", data=sendataw)
if (msg.topic.find("节点1/温度")!=-1): weather_tem = msg.payload.decode() print((str(msg.topic) + str(weather_tem))) if (msg.topic.find("节点1/湿度")!=-1): weather_hum = msg.payload.decode() print((str(msg.topic) + str(weather_hum))) if ((not (indoor_hum == 0)) and (not (indoor_tem == 0))): sendata = indoor_hum+ "," + indoor_tem print(sendata) siot.publish_save(topic="siot/节点1/温湿度表格", data=sendata)
siot.init(client_id="",server="10.168.1.100",port=1883,user="siot",password="dfrobot")
siot.set_callback(on_message_callback)
siot.connect()siot.loop()P1 = 0N1 = 0K1 = 0
P5 = 0N5 = 0K5 = 0
weather_hum = 0weather_tem = 0
indoor_tem = 0indoor_hum = 0
siot.getsubscribe(topic="siot/节点1/温湿度表格")
siot.getsubscribe(topic="siot/气象站/温湿度表格")siot.getsubscribe(topic="siot/气象站/温度")siot.getsubscribe(topic="siot/气象站/湿度")
siot.getsubscribe(topic="siot/节点1/温度")siot.getsubscribe(topic="siot/节点1/湿度")
siot.getsubscribe(topic="siot/devicestatus")
siot.getsubscribe(topic="siot/节点1/氮磷钾总和表格")siot.getsubscribe(topic="siot/节点1/土壤氮")siot.getsubscribe(topic="siot/节点1/土壤磷")siot.getsubscribe(topic="siot/节点1/土壤钾")
siot.getsubscribe(topic="siot/节点5/氮磷钾总和表格")siot.getsubscribe(topic="siot/节点5/土壤氮")siot.getsubscribe(topic="siot/节点5/土壤磷")siot.getsubscribe(topic="siot/节点5/土壤钾")
while True: outdev = 0 online = 0 for i in ip: result = os.popen(i) status = result.read() loc = "unreachable" in status print(loc) if loc != True: loc = status.find('Lost') loss_data = status[loc+7]
if loss_data == '4': outdev = outdev+1 else: online = online+1 else: outdev = outdev+1
output = str(online) + ','+ str(outdev) print("online,outdev:") print(output) siot.publish_save(topic="siot/devicestatus", data=output) print("send ok") time.sleep(100)
Visit the project to download the complete program:
https://github.com/polamaxu/AgriculturalSmartSystem
Conclusion
This IoT agricultural monitoring system can stably detect soil nutrients, including temperature, humidity, pH, and NPK data, while also monitoring the growing environment of crops outdoors and in greenhouses. Through wireless WIFI, it uploads greenhouse environment and outdoor weather station sensor data and images to the cloud in real-time, providing necessary data support for soil nutrients, environmental light, and environmental parameter analysis, supporting precise agriculture for households.
FAQ
1. Unihiker keeps showing wifi reconnecting?
Check if the screen is cycling through displaying wifi connected -> wifi reconnecting. If so, please restart the siot server on lattepanda. If not, please check if the router is functioning properly.
2. Unihiker shows error: runtimeerror: analog map retrieval time out.
Return to the Unihiker menu page and rerun the program. If it still cannot be resolved, you can flash the processor firmware. Method: https://www.Unihiker.com/wiki/faq
3. How to remotely monitor the screens of various Air Boards?
Use the built-in remote software remote desktop connection in Windows, enter the IP of the Air to access.
4. How to remotely control and view the programs of various Air Boards?
Use mobaXterm.exe, select the corresponding IP of the Air to open the command line interface of the system running on the Air Board. The account is siot, and the password is dfrobot.
Previous Recommendations
[Event] Raspberry Pi Project Solicitation Event (Participate for a prize, let’s play together!)
Notice on the 2024 National Teacher-Student Information Literacy Improvement Practical Activity (25th Student Activity)
Wei Xiongying: Strengthening Information Technology Experimental Teaching, Enhancing the Educational Value of Information Technology
[Ministry of Education Notice] The 2023 Edition of the Basic Directory for Experimental Teaching in Primary and Secondary Schools Has Been Officially Released
Notice on the 11th National Primary and Secondary School STEAM Education Conference
[New Curriculum Standard] Cross-Disciplinary Case of Information Technology – Eighth Grade Campus Weather Station System
[Outstanding Cases in Competitions] Intelligent Plant Seedling Cultivation Data Collection System
[Outstanding Cases in Competitions] Low Carbon Life – Monitoring and Utilization of Carbon Dioxide Generated by Traditional Vinegar Brewing Process
[Outstanding Cases in Competitions] Challenge Game – Magic Mirror Legend Brave Rescue Little Pig
[Outstanding Cases in Competitions] Smart Campus “Happy Farm” IoT Visualization Data Platform
Leave a Comment
Your email address will not be published. Required fields are marked *