在过去,我国农业自动化程度较低,与发达国家存在着较显著的差距。现如今,随着现代科技的不断进步,农业自动化水平日渐提高,越来越多的传感器、显示屏等电子设备被应用在农业中,随时随地监测农作物的生长,以便在环境不佳时进行改善。
在这节课上,让我们结合DFRobot Python学习利器-行空板,一起来设计一个智慧农业可视化系统,模拟一下现代农业中对于庄稼生长环境的监测与改善吧!
将通过土壤湿度传感器检测到的土壤湿度值显示在屏幕上,同时,设置自动和手动两个模式,在自动模式下,当检测到的土壤湿度值过低时,通过外接继电器和水泵自动浇水,同时行空板屏幕上出现浇水的图示;在手动模式下,可通过点击屏幕上按钮的方式进行浇水和关水。点击“切换模式”按钮可实现手动与自动两个模式的变换。
1、认识土壤湿度传感器、继电器、水泵
2、学习使用unihiker库显示按钮的方法
3、学习使用Pinpong库使土壤湿度传感器检测数据的方法
4、学习使用Pinpong库控制继电器的方法
5、学习使用继电器控制水泵浇水的方法
硬件清单:
软件使用:Mind+编程软件x1
其他: 1、带植物的花盆 x1
2、盛有水的烧杯 x1
3、十字/一字两用螺丝刀 x1
1、土壤湿度传感器
这是一个简易的水分传感器,可用于检测土壤的水分。当土壤缺水时,传感器输出值将减小,反之将增大。传感器表面做了镀金处理,可以延长它的使用寿命。
土壤湿度传感器在使用时需要将两金属条充分插入土壤中,并等待数秒直至数据稳定后,通过显示屏模块或软件可以读取土壤湿度对应的数值。
Tip1:不同土壤介质的测量值会存在差异。土壤中的水分存在分布不均的情况,数据仅能代表局部湿度。Tip2:传感器顶部的塑料部分不防水,请勿将传感器整个埋入土中。
2、继电器
继电器是一种用小电流去控制大电流运作的具有隔离功能的自动开关元件。
虽然行空板的供电电压5V大于水泵的最小工作电压4.5V,但是实际驱动起来运行会很不稳定。这里,我们借助继电器模块,外接电源来驱动水泵工作。
3、水泵
水泵是输送液体或使液体增压的机械。可放置水中直接使用,4.5~12V宽电压供电范围。可用来为植物浇水,甚至为鱼缸换水。
4、unihiker库GUI类add_button()方法显示按钮
GUI类中的add_button()方法可以实现在行空板屏幕上显示一个按钮控件,在编程时,通过“对象.方法名()”的形式来实现功能,同时,此方法会返回一个控件对象,使用变量存储起来方便后续进行对象更新操作。
from unihiker import GUI # 导入unihiker库GUI模块
gui = GUI() # 实例化gui对象
# 定义按钮被点击后的功能
def click_A(): # 定义点击按钮A时的操作--切换图片
img.config(w=240, h=320, image='img/浇水1.png')
button_A = gui.add_button(x=50, y=260, w=70, h=40, text="浇水", onclick=click_A ,state='disabled')
其中,参数x和y分别表示按钮的横纵坐标位置,w和h表示按钮的宽度和高度,text指的是按钮上显示的文字,onclick表示按钮被点击后所触发的功能,这里,我们需要先将功能以回调函数的形式设定好,state表示的是按钮的状态,按钮有两种状态,normal表示正常可被点击的状态,disabled表示不可被点击状态,此时按钮显示灰色。
5、Pinpong库Pin类write_digital()方法实现数字输出
Pinpong库中Pin类的write_digital()方法可以实现数字输出,在使用前,我们需要先导入Pinpong库,初始化行空板,实例化Pin类来创建一个引脚对象。
from pinpong.board import Board, Pin # 导入pinpong库下的Board, Pin模块
Board().begin() # 初始化,选择板型和端口号,不输入则进行自动识别
relay = Pin(Pin.P23, Pin.OUT) # 初始化23引脚为数字输出模式
relay.write_digital(1) # 控制继电器引脚为高电平,打开继电器
其中,Pin与Board 类似,都是pinpong.board包下的模块。“Pin.P23”指的是板子上继电器所在的23号引脚,“(Pin.P23, Pin.OUT)”是在定义P23引脚为数字输出模式,之后将它传入Pin类中进行实例化,得到一个引脚对象并存入变量relay中。最后通过write_digital()方法给引脚输出指定的电平,“1”为高电平,“0”为低电平。
6、Pinpong库Pin类read_analog()方法读取模拟量
Pinpong库中Pin类中的read_analog()方法可以读取模拟量。在使用前,我们需要先导入Pinpong库,初始化行空板,实例化Pin类来创建一个引脚对象。
from pinpong.board import Board, Pin # 导入pinpong库下的Board, Pin模块
Board().begin() # 初始化,选择板型和端口号,不输入则进行自动识别
adc0 = Pin(Pin.P21, Pin.ANALOG) # 初始化21引脚为模拟输入模式
Soil_moisture_value = adc0.read_analog() # 读取模拟值
其中,Pin与Board 类似,都是pinpong.board包下的模块。“Pin.P21”指的是板子上土壤湿度传感器所在的21号引脚,“(Pin.P21, Pin.ANALOG)”是在设置P21引脚为模拟输入模式,之后将它传入Pin类中进行实例化,得到一个引脚对象并存入变量adc0中。最后通过read_analog()方法检测读取模拟值并将其存储到变量Soil_moisture_value中。
Tips:行空板上的各个引脚并不是支持所有的模式,具体情况可参考下表。
硬件引脚 | 功能 |
ADC | P0 P1 P2 P3 P4 P10 P21 P22 |
PWM | P0 P2 P3 P10 P16 P21 P22 P23 |
数字输入、数字输出 | 所有引脚均可 |
在屏幕上添加一张智慧农业背景图,并显示一个设定的初始湿度值50,同时添加两个按钮,实现按下浇水按钮后,切换浇水背景图,按下关水按钮后,切换回原始背景图,来模拟真实的按钮控制浇水的功能。
通过USB连接线将行空板连接到计算机
STEP1:创建与保存项目文件
启动Mind+,另存项目并命名为“008、智慧农业可视化系统”。
STEP2:创建与保存Python文件
创建一个Python程序文件“main1.py”,双击打开。
STEP3:导入图片文件夹
在项目文件夹中导入背景图文件夹。(图片文件夹与程序文件同在项目文件夹中,下载链接见附录1)
STEP4:程序编写
(1) 导入所需功能库
在这个任务中,我们需要使用unihiker库中的GUI模块来在屏幕上显示文字,因此,我们首先需要导入它,同时,由于后续在程序运行中时需要设置一定的延时,因此,我们还需导入time时间库。
from unihiker import GUI # 导入unihiker库GUI模块import time # 导入time库 |
(2) 实例化GUI类并显示初始背景图
在使用unihiker库中的GUI模块前,我们需要先实例化GUI类,来创建一个对象,以便使用该类中的各种方法。
之后,我们在屏幕上显示一张初始的背景图。
gui = GUI() # 实例化gui对象# 显示背景图片img = gui.draw_image(w=240, h=320, image='img/关水1.png') |
(3) 定义按钮被点击后的功能
由于后续我们将在屏幕上添加两个按钮,通过点击来触发浇水和关水的功能,因此,在这里,我们先定义两个函数,在“click_A()”中设定切换浇水图的功能,在“click_B()”中设定切换关水图的功能,以便在后续调用。
# 定义回调函数def click_A(): # 定义点击按钮A时的操作--切换图片 img.config(w=240, h=320, image='img/浇水1.png') def click_B(): # 定义点击按钮B时的操作--切换图片 img.config(w=240, h=320, image='img/关水1.png') |
(4) 定义按钮显示参数
接着,我们可以在行空板的屏幕上显示两个表示“浇水”和“关水”的按钮,并设置按钮被点击后触发的功能。
# 显示按钮'''显示按钮并设置按钮点击后触发的功能'''button_A = gui.add_button(x=50, y=260, w=70, h=40, text="浇水", onclick=click_A)button_B = gui.add_button(x=140, y=260, w=70, h=40, text="关水", onclick=click_B) |
(5) 显示土壤湿度值
之后,我们在屏幕上绘制两个填充矩形并显示文字“湿度值”以及给定的土壤湿度值“50”。
# 绘制填充矩形并在矩形框内显示文字gui.fill_rect(x=65, y=35, w=70, h=30, color="white")gui.fill_rect(x=148, y=35, w=55, h=30, color="white")gui.draw_text(x=68, y=36, color="red", text='湿度值:')text = gui.draw_text(x=160, y=36, color="red", text="50") # 显示初始湿度值:50 |
(6) 显示表情
最后,为了能够保持屏幕内容的长久显示,我们使程序处于运行状态。
while True: # 循环 time.sleep(1) # delay1秒 |
Tips:完整示例程序如下:
from unihiker import GUI # 导入unihiker库GUI模块import time # 导入time库 gui = GUI() # 实例化gui对象 # 显示背景图片img = gui.draw_image(w=240, h=320, image='img/关水1.png') # 定义回调函数def click_A(): # 定义点击按钮A时的操作--切换图片 img.config(w=240, h=320, image='img/浇水1.png') def click_B(): # 定义点击按钮B时的操作--切换图片 img.config(w=240, h=320, image='img/关水1.png') # 显示按钮'''显示按钮并设置按钮点击后触发的功能'''button_A = gui.add_button(x=50, y=260, w=70, h=40, text="浇水", onclick=click_A)button_B = gui.add_button(x=140, y=260, w=70, h=40, text="关水", onclick=click_B) # 绘制填充矩形并在矩形框内显示文字gui.fill_rect(x=65, y=35, w=70, h=30, color="white")gui.fill_rect(x=148, y=35, w=55, h=30, color="white")gui.draw_text(x=68, y=36, color="red", text='湿度值:')text = gui.draw_text(x=160, y=36, color="red", text="50") # 显示初始湿度值:50 while True: # 循环 time.sleep(1) # delay1秒 |
STEP1:远程连接行空板并运行
STEP2:观察效果
观察行空板,可以看到在智慧农业的背景图上,显示着固定的土壤湿度值50,同时下方有两个按钮。点击浇水按钮后,会有一个洒水无人机出现,模拟实际的浇水场景,点击关水按钮后,无人机消失,停止浇水。
通过外接土壤湿度传感器来实时检测湿度值并显示,同时,设置自动和手动两个模式,在自动模式下,当检测到的土壤湿度值过低时,通过外接继电器和水泵来自动浇水;在手动模式下,可通过点击屏幕上按钮的方式进行浇水;模式之间也可手动切换。
STEP1:将土壤湿度传感器接入行空板的P21引脚,继电器接入行空板的P23引脚
STEP2:利用螺丝刀将水泵正负线与转接头连接起来,步骤与成型图如下,
(1)松掉转接头螺丝
(2)将线插入,注意正负(棕/红—正;蓝/黑—负)
(3)拧紧螺丝
STEP3:利用继电器将12V电源开关与水泵的转接头连接起来
STEP4:将继电器开关拨至NO端
Tips:继电器上有一个开关,NO 为断开,表示默认继电器状态为断开,需要程序写入一个高电平,控制其闭合;NC 为闭合,表示默认继电器状态为闭合,需要程序写入一个低电平,控制其断开。这里,我们设定默认状态为断开。
STEP5:将水泵固定在满水的烧杯中
Tips:水泵不能空转,必须将黑色水泵头沉入水中,否则可能会烧毁硬件。
STEP6:将水管和土壤湿度传感器插入花盆中
STEP1:创建与保存项目文件
新建一个Python程序文件“main2.py”,双击打开。
Step2:程序编写
(1)导入Pinpong库并初始化板子和引脚
这里,我们需要使用外接的土壤湿度传感器和继电器,因此,我们需要补充导入Pinpong库中的Board、Pin两个模块,并初始化行空板和引脚。
from pinpong.board import Board, Pin # 导入pinpong库下的Board, Pin模块Board().begin() # 初始化行空板adc0 = Pin(Pin.P21, Pin.ANALOG) # 初始化21引脚为模拟输入模式relay = Pin(Pin.P23, Pin.OUT) # 初始化23引脚为数字输出模式 |
(2)更新按钮点击后的功能
接下来,我们在定义的按钮A、B的回调函数中,补充继电器的输出,以便在浇水按钮被点击后,继电器输出高电平实现浇水,而关水按钮被点击后,继电器输出低电平停止浇水。
# 定义回调函数def click_A(): # 定义点击按钮A时的操作--切换显示浇水图片 img.config(w=240, h=320, image='img/浇水1.png') relay.write_digital(1) # 控制继电器引脚为高电平,打开继电器 def click_B(): # 定义点击按钮B时的操作--切换显示关水图片 img.config(w=240, h=320, image='img/关水1.png') relay.write_digital(0) # 继电器低电平 |
(3)定义模式切换按钮功能
由于我们将在屏幕上添加一个按钮以进行模式的切换,因此,我们先定义一个该按钮的回调函数。
这里,我们先定义一个自动模式的标志位,并用1和0表示其开关。之后,在回调函数中,我们对原来的模式进行判别,如果原来为手动模式,那么“切换模式”按钮被点击后模式就更新为自动,此时A、B按钮的状态更新为不可被点击,标志位变为1。反正,原来为自动模式,点击“切换模式”按钮后,模式更新为手动,A、B按钮恢复正常,标志位变为0。
is_auto_mode = 1 # 定义一个标志位--自动模式,1为开,0为关def click_C(): # 定义点击按钮C时的操作--切换模式 global is_auto_mode if is_auto_mode == 0: # 如果自动模式标志位为0, 即原来为手动模式,那么点击后 text_mode.config(text="自动") button_A.config(state='disabled') # 设置按钮状态为disabled,表示无法点击 button_B.config(state='disabled') is_auto_mode = 1 # 设置自动模式标志位为1 ,即打开自动模式 elif is_auto_mode == 1: # 如果自动模式标准位为1, 即原来为自动模式,那么点击后 text_mode.config(text="手动") button_A.config(state='normal') # 设置按钮状态为normal,表示可以被点击 button_B.config(state='normal') is_auto_mode = 0 # 设置自动模式标志位为0 ,即打开手动模式 |
(4)显示填充矩形和文字
接着,我们在屏幕上再显示两个填充矩形和文字,用以表示当前的模式。
gui.fill_rect(x=100, y=160, w=70, h=30, color="white") # 绘制矩形以显示“当前模式”gui.fill_rect(x=180, y=160, w=50, h=30, color="white") # 绘制矩形以显示模式类型text_2 = gui.draw_text(x=105, y=163, color="red", text="当前模式:",font_size=11) # 显示文字“当前模式:”text_mode = gui.draw_text(x=190, y=163, color="red", text="自动",font_size=11) # 显示模式类型 |
(5)定义按钮显示参数
之后,我们设定初始时为自动模式,因此我们需要调整A、B按钮处于不可被点击的状态,同时,我们再在屏幕上添加一个“切换模式”按钮用于进行自动和手动两个模式的切换。
# 显示按钮'''显示按钮并设置按钮点击后触发的功能,以及按钮初始时处于不可被点击状态'''button_A = gui.add_button(x=50, y=260, w=70, h=40, text="浇水", onclick=click_A ,state='disabled') button_B = gui.add_button(x=140, y=260, w=70, h=40, text="关水", onclick=click_B ,state='disabled')button_C = gui.add_button(x=10, y=160, w=70, h=30, text="切换模式", onclick=click_C) |
(6)定义自动浇水功能函数
在自动模式下,我们需要设置自动浇水的功能,因此在这里,我们定义一个函数,在其中设定一个阈值并对土壤湿度值进行判别,当湿度值小于设定的阈值时,浇水3秒。
# 定义湿度值较低时自动补水3秒def auto_watering(): '''定义湿度值较低时自动补水3秒''' if Soil_moisture_value < 2120: click_A() time.sleep(3) click_B() |
(7)使用传感器检测土壤湿度
最后,我们设定每隔一秒通过土壤湿度传感器检测数据,并且在自动模式下进行自动浇水。
while True: # 循环 Soil_moisture_value = adc0.read_analog() # 读取模拟值 print(Soil_moisture_value) # 打印显示湿度值 if is_auto_mode == 1 : # 如果处于自动模式 auto_watering() # 自动补水 text_value.config(text=Soil_moisture_value) # 更新湿度值 time.sleep(1) # delay1秒 |
Tips:完整示例程序如下:
from unihiker import GUI # 导入unihiker库GUI模块from pinpong.board import Board, Pin # 导入pinpong库下的Board, Pin模块import time # 导入time库 gui = GUI() # 实例化gui对象 Board().begin() # 初始化行空板adc0 = Pin(Pin.P21, Pin.ANALOG) # 初始化21引脚为模拟输入模式relay = Pin(Pin.P23, Pin.OUT) # 初始化23引脚为数字输出模式 # 显示背景图片img = gui.draw_image(w=240, h=320, image='img/关水1.png') # 定义回调函数def click_A(): # 定义点击按钮A时的操作--切换显示浇水图片 img.config(w=240, h=320, image='img/浇水1.png') relay.write_digital(1) # 控制继电器引脚为高电平,打开继电器 def click_B(): # 定义点击按钮B时的操作--切换显示关水图片 img.config(w=240, h=320, image='img/关水1.png') relay.write_digital(0) # 继电器低电平 is_auto_mode = 1 # 定义一个标志位--自动模式,1为开,0为关def click_C(): # 定义点击按钮C时的操作--切换模式 global is_auto_mode if is_auto_mode == 0: # 如果自动模式标志位为0, 即原来为手动模式,那么点击后 text_mode.config(text="自动") button_A.config(state='disabled') # 设置按钮状态为disabled,表示无法点击 button_B.config(state='disabled') is_auto_mode = 1 # 设置自动模式标志位为1 ,即打开自动模式 elif is_auto_mode == 1: # 如果自动模式标准位为1, 即原来为自动模式,那么点击后 text_mode.config(text="手动") button_A.config(state='normal') # 设置按钮状态为normal,表示可以被点击 button_B.config(state='normal') is_auto_mode = 0 # 设置自动模式标志位为0 ,即打开手动模式 # 绘制填充矩形并在矩形框内显示文字gui.fill_rect(x=65, y=35, w=70, h=30, color="white") # 绘制矩形以显示“湿度值”gui.fill_rect(x=148, y=35, w=55, h=30, color="white") # 绘制矩形以显示湿度值数据gui.fill_rect(x=100, y=160, w=70, h=30, color="white") # 绘制矩形以显示“当前模式”gui.fill_rect(x=180, y=160, w=50, h=30, color="white") # 绘制矩形以显示模式类型 text_1 = gui.draw_text(x=68, y=36, color="red", text='湿度值:') # 显示文字“湿度值:”text_value = gui.draw_text(x=155, y=36, color="red", text="") # 显示湿度值数据text_2 = gui.draw_text(x=105, y=163, color="red", text="当前模式:",font_size=11) # 显示文字“当前模式:”text_mode = gui.draw_text(x=190, y=163, color="red", text="自动",font_size=11) # 显示模式类型 # 显示按钮'''显示按钮并设置按钮点击后触发的功能,以及按钮初始时处于不可被点击状态'''button_A = gui.add_button(x=50, y=260, w=70, h=40, text="浇水", onclick=click_A ,state='disabled') button_B = gui.add_button(x=140, y=260, w=70, h=40, text="关水", onclick=click_B ,state='disabled')button_C = gui.add_button(x=10, y=160, w=70, h=30, text="切换模式", onclick=click_C) # 定义湿度值较低时自动补水3秒def auto_watering(): '''定义湿度值较低时自动补水3秒''' if Soil_moisture_value < 2120: click_A() time.sleep(3) click_B() while True: # 循环 Soil_moisture_value = adc0.read_analog() # 读取模拟值 print(Soil_moisture_value) # 打印显示湿度值 if is_auto_mode == 1 : # 如果处于自动模式 auto_watering() # 自动补水 text_value.config(text=Soil_moisture_value) # 更新湿度值 time.sleep(1) # delay1秒 |
STEP1:将12V电源开关插上220V电源插座
STEP2:远程连接行空板并运行程序观察效果
点击运行后,观察行空板,可以看到初始时模式为自动,此时浇水和关水两个按钮为灰色,不可被点击,检测到的土壤湿度值为1967左右,小于我们设定的阈值2120,之后水泵开始自动抽水至花盆中,很快湿度值升高,达到2123,此时水泵停止抽水。
点击“切换模式”按钮后,当前的模式变为手动,按钮变回正常状态,此时,点击“浇水”按钮,水泵同样开始工作,点击“关水”按钮后,水泵就停了下来。
Tips:程序中的阈值“2120”是我们依据实验情况设定的植物缺水时的临界值,不同的植物对水的需求量耐热度不同。水量不足时需在烧杯中补水。
想一想,对于本实验,你觉得还有什么需要进一步优化的吗,自己试一试吧!或者给我们留言!
更多行空板Python入门教程请关注“蘑菇云创客”公众号。
审核编辑:符乾江
全部0条评论
快来发表一下你的评论吧 !