大数跨境
0
0

物联网农业土壤养分和气象站监测系统

物联网农业土壤养分和气象站监测系统 蘑菇云创造
2023-12-12
1
导读:物联网农业土壤养分和气象站监测系统

点击 蘑菇云创造 关注我们


物联网农业土壤养分和气象站监测系统


前言


为监测户外和大棚的作物生长环境,我设计了一个物联网农业监测系统,使用Unihiker作为主要的监测核心,并结合了RS485土壤传感器,温湿度传感器,CO2传感器,环境光传感器等,采集不同节点的土壤养分,包括温湿度、PH和氮磷钾数据,同时采集空气二氧化碳、温湿度,环境光等的数据,同时还配备了摄像头,对作物的成长进行拍摄。Unihiker通过无线WIFI将数据上传至Lattepanda的本地服务器,我们可以使用Flask Web网页端查看数据,如果需要还可以对作物进行实时的监测。这个系统不仅记录大棚温室的环境数据,我还设立了一个Unihiker室外气象站,实时监测户外的重要环境参数,包括风向、风速、温度、气压和雨量。所有上传云端的数据,可以提供实时分析土壤养分、环境光照和环境参数的数据支持,以及为今后的智能农业发展提供数据标记和学习的基础。整体程序使用Python编写,具有自动运行和断网自动重连等功能。Lattepanda服务器可以显示不同节点的在线状态和数据,如果有节点出现问题,会显示节点不在线,方便及时维护。


利用此系统,我们可以更好地检测、控制、研究育种和植物生长。结合本地监测数据,实时掌握大棚内环境参数和图像,进行数据的采集、数据处理、数据可视化、数据分析等环节,为今后科学化育种育苗栽种进行合理方案设计。



硬件清单


  1. 土壤氮磷钾传感器 x5

  2. Lattepanda 3 delta x1

  3. Unihiker x6

  4. 二氧化碳传感器 X3

  5. 环境光传感器 X3

  6. 气象站 SEN0186 x1

  7. 485转UART模块 X5

  8. 温湿度传感器 X1

  9. Unihiker扩展板 X6

  10. Power Adapter X6

  11. SCI x 6

  12. WIFI 监控摄像头 x1

  13. 摄像头 x5

  14. 路由器 x1

  15. 防水箱体 x6

  16. 电源转接模块 x 6


功能


  • 实时监测大棚内“一米田”内主要环境指标(土壤参数:土壤温湿度、土壤pH、土壤营养盐,环境参数:二氧化碳浓度 、温湿度、光照强度)。

  • 苗情监测:图像采集按时自动发送命令远程拍照,自动展示最新作物苗情图片。

  • 气象站监测:实时监测大棚外气象情况(风向、风速、温度、气压和雨量)。

  • 将监测到的数据在云端显示。

  • 离线节点设备在线预警。



方案拓扑图


Unihiker行空板作为主要的监测核心,并结合了RS485土壤传感器,I2C 温湿度传感器,I2C CO2传感器,I2C 环境光传感器等,采集不同节点的土壤养分,包括温湿度、PH和氮磷钾数据,同时采集空气二氧化碳、温湿度,环境光等的数据,同时还配备了USB摄像头连接Unihiker行空板,对作物的成长进行拍摄。各个节点的Unihiker和Lattepanda都在同一个局域网下,行空板通过无线WIFI将数据上传至Lattepanda的本地服务器。


在气象站节点中,Unihiker通过UART通讯收集气象站数据。


重要技术指标


1、土壤传感器:用于检测土壤养分数据

  • 土壤温湿度,PH值,氮磷钾数据


2、Lattepanda 3 delta:用做本地服务器

  • 处理器: Intel®赛扬®N5105

  • CPU: 2.0~2.9GHz,四核,四线程

  • GPU: Intel®UHD显卡(频率:450 - 800MHz)

  • 内存:LPDDR4 8GB 2933MHz

  • 存储:64GB eMMC V5.1


3、Unihiker:用做每个节点的主控

  • CPU: 国产 4核 1.2GHz

  • 内存: 512MB DDR3

  • 硬盘: 16GB eMMC

  • 内置操作系统:Debian

  • Wi-Fi:  2.4G

  • 蓝牙:  4.0

  • 实体按键:Home按键,A/B按键

  • 幕:2.8寸240*320 TFT彩屏

  • 供电: Type-C 5V供电

  • 工作电压:3.3V

  • 最大工作电流: 2000mA

  • 接口:

    USB  Type-C 1

    USB  TYPE-A 1

    microSD卡接口 1

    3Pin I/O 4  (其中支持3路PWM 2路ADC)

    4Pin I2C 2


流量和存储估算


按每个节点每5分钟上传一次数据(含图片数据),每个节点数据约为1kb,每张JPG图片约为30kb,图片文件可以直接保存在Lattepanda上,节点数据保存在服务器的Siot数据库中,如果有额外内存需求,可以考虑Lattepanda增加内存条。


硬件连接


1. 以节点1土培生菜为例,节点1-节点5接线相同



USB摄像头和行空板的USB连接。


RS485土壤传感器,485转UART模块(DFR0845)和Uihiker扩展板(MBT0008)连接方式如下表。485转UART模块和土壤传感器之间使用接线柱连接较牢固,485转UART模块和Uihiker扩展板使用杜邦线连接,建议使用热熔胶二次固定,防止电线松动。



SCI,传感器(SEN0536,SEN0540 ,SEN0334)和Uihiker连接方式如图:


2.气象站节点

气象站(SEN0186)和 Uihiker扩展板(MBT0008)连接方式如下表,使用杜邦线连接,建议使用热熔胶二次固定,防止电线松动。



3. 供电:

使用FIT0639和电源转接模块,给Uihiker和扩展板(MBT0008)整体供电。


在LP服务器搭建环境:


安装服务器程序Siot

1、下载windows版本的SIoT解压,双击start SIoT.bat即可启动SIoT,启动之后会弹出命令窗口启动服务器。



2、在浏览器输入 127.0.0.1:8080 即可打开网页端口,登录账号为siot,密码为dfrobot,打开后可以新建Topic或查看消息。



安装Web应用框架Flask

1、windows安装python3.7,下载网页:

2、Python安装flask库



3、访问项目网址下载代码(见第六节),并运行Flask程序


cd flask-demo
flask-start.py



4、网址输入访问http://127.0.0.1:5000/index(需要先启动Siot V2,才可以使用这个Flask Web),在这个网页中,你可以通过上方的按钮选择查看节点的传感器数据。



路由器设置

在lattepanda网页登录路由器页面设置,固定Lattepanda、六个Unihiker的IP。



代码:


1. Unihiker 以节点1 土培生菜为例

(请开启Unihiker开机自启动设置)

# -*- 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() #初始化,选择板型,不输入板型则进行自动识别SCI1 = DFRobot_RP2040_SCI_IIC(addr=0x21)u_gui=GUI()#硬串口1 P0-RX P3-TXuart1 = UART() # ser = serial.Serial("/dev/ttyUSB0",115200,timeout=0.5)#初始化串口 baud_rate 波特率, bits 数据位数(8/9) parity奇偶校验(0 无校验/1 奇校验/2 偶校验) stop 停止位(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.")
#发送给传感器的指令buf = [0x02, 0x03, 0x00, 0x00, 0x00, 0x0A, 0xC5,0xFE]
#返回指令 04传感器地址;03功能码;14数据长度;'00', 'e7'温度;'00', '00'湿度;00 00 空白;'00', '28'ph;'00', '00', '00', '00', '00', '00'氮磷钾;'00', '00', '00', '00'空白;'25', '80'波特率960025,b2校验和#['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) #设置摄像头图像宽度 cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 240) #设置摄像头图像高度 cap.set(cv2.CAP_PROP_BUFFERSIZE, 1) #设置OpenCV内部的图像缓存,可以极大提高图像的实时性。
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是编码,b64decode是解码 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 气象站

# -*- coding: utf-8 -*-import timefrom pinpong.board import Board, UARTimport siotimport os
Board("UNIHIKER").begin() #初始化,选择板型,不输入板型则进行自动识别#行空板硬串口1 P0-RX P3-TXuart1 = UART() #初始化串口 baud_rate 波特率, bits 数据位数(8/9) parity奇偶校验(0 无校验/1 奇校验/2 偶校验) stop 停止位(1/2)uart1.init(baud_rate = 9600, bits=8, parity=0, stop = 1) #uart1.init() #气象站波特率为9600siot.init(client_id="hostclient01",server="10.1.2.3",port=1883,user="siot",password="dfrobot")while True: databuffer = "" #print(len("c000s000g000t082r000p000h48b10022*3C"))默认字长 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: # 如果数据长度为38 print("databuffer:",databuffer) # 打印显示数据串
'''解析获取其中的风向数据''' 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)
'''解析获取其中的风速数据'''# 1英里每小时=1609.34米/3600秒=0.44703889m/s # 前一分钟的平均风速 try: WindSpeedAverage = round(0.44704 * float(databuffer[5:8]),1) except: WindSpeedAverage = 0 print("Average Wind Speed (One Minute):" + str(WindSpeedAverage) + "m/s ") # 前五分钟的最大风速 try: WindSpeedMax = round(0.44704 * float(databuffer[9:12]),1) except: WindSpeedMax = 0 print("Max Wind Speed (Five Minutes):" + str(WindSpeedMax) + "m/s")
'''解析其中的温度数据'''# 摄氏度=(华氏度-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 ")
'''解析其中的湿度数据''' try: Humidity = round(float(databuffer[25:27]) ,1) except: Humidity = 0 print("Humidity:" + str(Humidity) +"% ")
'''解析其中的气压数据''' try: BarPressure = round(float(databuffer[28:33])/ 10.00,1) except: BarPressure = 0 print("BarPressure:" + str(BarPressure) + "hPa")
else: # 如果长度不是38,那么就令数据为空 databuffer = ""
time.sleep(0.5)

3. Flask服务器程序

#  -*- coding: UTF-8 -*-from flask import Flask,Response,render_template,requestflask_app = Flask(__name__)
# 事件回调函数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. 服务器程序(保存图片,查询节点在线状态)

#  -*- 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']
# 事件回调函数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)


访问项目下载完整程序:

https://github.com/polamaxu/AgriculturalSmartSystem


总结


该物联网农业监测系统能够稳定地检测土壤养分,包括温湿度、PH和氮磷钾数据,同时还能监测户外和大棚的作物生长环境。通过无线WIFI,将大棚环境和室外气象站的传感器数据和图片实时上传云端,提供土壤养分、环境光照、环境参数的实时分析,为家庭精准农业提供必要的数据支持。


FAQ


1、Unihiker 一直显示wifi正在重连?

观察屏幕是否循环显示wifi connected->wifi 正在重连。如果有,请重启lattepanda上的siot服务器。如果没有出现,请检查路由器是否正常。


2、Unihiker 显示报错:runtimeerror:analog map retrieal time out.

返回Unihiker 菜单页面,重新运行程序,如果还无法解决,可以刷处理器固件,方法:https://www.Unihiker.com/wiki/faq


3、如何远程监控各个行空板的屏幕?

使用windows自带的远程软件remote desktop connection,填入行空的ip来访问


4、如何远程控制查看各个行空板的程序?

使用mobaXterm.exe,选择行空对应的ip就可以打开行空板的系统运行命令行界面,账号是siot,密码是dfrobot。







往期推荐

【活动】树莓派项目征集活动(参与就有奖,一起来玩!)

关于举办2024年全国师生信息素养提升实践活动(第二十五届学生活动)的通知

魏雄鹰:加强信息科技实验教学,发挥信息科技育人价值

【教育部通知】2023年版中小学实验教学基本目录正式发布

关于举办第十一届中小学STEAM教育大会的通知

【新课标】信息科技跨学科案例-八年级 校园气象站系统

【比赛优秀案例】智能植物育苗养护数据采集系统

【比赛优秀案例】低碳生活-传统酿醋工艺产生的二氧化碳的监测和利用

【比赛优秀案例】闯关游戏-魔镜传奇 勇敢救小猪

【比赛优秀案例】智慧校园“开心农场”物联网可视化数据平台


【声明】内容源于网络
0
0
蘑菇云创造
蘑菇云是DFRobot旗下专注于AI人工智能、创客、STEAM、劳动教育的科技创新教育品牌;以为中国培养下一代科技创新人才为使命,为学校提供k12全龄段科技创新教育解决方案。
内容 969
粉丝 0
蘑菇云创造 蘑菇云是DFRobot旗下专注于AI人工智能、创客、STEAM、劳动教育的科技创新教育品牌;以为中国培养下一代科技创新人才为使命,为学校提供k12全龄段科技创新教育解决方案。
总阅读1.4k
粉丝0
内容969