一、硬件需要用到的材料
首先需要一块树莓派的板子哈,这里我们用到的是Raspberry Pi Zero 2 W。
Raspberry Pi Zero 2 W 的核心是 RP3A0,这是一款由英国 Raspberry Pi 设计的定制系统级封装。Zero 64 配备主频为 53GHz 的四核 1 位 ARM Cortex-A512 处理器和 2MB 的 SDRAM,速度是原始 Raspberry Pi Zero 的五倍。
无线局域网内置于屏蔽外壳中,具有改进的射频合规性,在使用 Raspberry Pi Zero 2 W 进行设计时为您提供更大的灵活性。
所有这些都采用相同的 65 毫米× 30 毫米的微型外形尺寸。
1、通过LM35温度传感器
2、电容式湿度传感器
3、LDR模块来获取土壤的温度、湿度、光敏强度
4、ADS1115模数转换器:

详细请看ADS1115的介绍:
https://blog.youkuaiyun.com/2202_75379338/article/details/134357187?spm=1001.2014.3001.5502
5、LCD显示屏(2寸 8引脚)
二、硬件电路连接
1RaspberryPI zero 2W与LCD显示屏
RaspberryPI zero 2W与LCD显示屏接线表
RaspberryPI zero 2W | LCD显示屏 |
GND | GDN |
3.3V BCM 10(MOSI) BCM 11(SCLK) | VCC DIN CLK |
BCM 8(CE0) | CS |
BCM 25 | DC |
BCM 27(PCM_D) | RST |
BCM 15(RXD) | BL |
2连接RaspberryPI zero 2W与ADS1115
RaspberryPI zero 2W与ADS1115接线表
ADS1115 | |
GND | GND |
5V BCM 3(SCL) BCM 2(SDA) | VCC SCL SDA |
3连接ADS1115与各传感器
ADS1115与各个传感器接线表
ADS1115 | LM35温度传感器 | 电容式湿度传感器 | LDR模块 |
GND | GND | GDN | GDN |
VCC A1 | VCC Vout | VCC
| VCC |
A2 | AUOT | ||
A3 | AO |
三、代码部分
对RaspberryPI zero 2W和LCD显示屏进行配置的关键部分代码如下:
class RaspberryPi:
def __init__(self,spi=spidev.SpiDev(0,0),spi_freq=40000000,rst = 27,dc = 25,bl = 18,bl_freq=1000,i2c=None,i2c_freq=100000):
import RPi.GPIO
self.np=np
self.RST_PIN= rst
self.DC_PIN = dc
self.BL_PIN = bl
self.SPEED =spi_freq
self.BL_freq=bl_freq
self.GPIO = RPi.GPIO
#self.GPIO.cleanup()
self.GPIO.setmode(self.GPIO.BCM)
self.GPIO.setwarnings(False)
self.GPIO.setup(self.RST_PIN, self.GPIO.OUT)
self.GPIO.setup(self.DC_PIN, self.GPIO.OUT)
self.GPIO.setup(self.BL_PIN, self.GPIO.OUT)
self.GPIO.output(self.BL_PIN, self.GPIO.HIGH)
#Initialize SPI
self.SPI = spi
if self.SPI!=None :
self.SPI.max_speed_hz = spi_freq
self.SPI.mode = 0b00
这是一个RaspberryPi类,它用于控制RaspberryPI zero 2W上的SPI和I2C接口,以及控制LCD显示屏的背光、复位和数据/命令选择引脚。在初始化时,它将引脚设置为输出模式,并将SPI和I2C接口初始化。
class LCD_2inch(lcdconfig.RaspberryPi):
width = 240
height = 320 # 设置LCD屏幕的宽度和高度
def command(self, cmd):
self.digital_write(self.DC_PIN, self.GPIO.LOW) # 设置DC引脚为低电平
self.spi_writebyte([cmd]) # 通过SPI总线发送命令
这是一个LCD屏幕的驱动程序,用于连接RaspberryPI zero 2W和LCD显示屏。它定义了屏幕的宽度和高度,并实现了一个命令函数,用于向屏幕发送指令。该函数将命令发送给SPI总线,并使用GPIO控制数据/命令引脚。
对RaspberryPI zero 2W和ADS1115进行配置的关键部分代码如下:
import board
import busio
import time
i2c = busio.I2C(board.SCL, board.SDA)
import adafruit_ads1x15.ads1115 as ADS
from adafruit_ads1x15.analog_in import AnalogIn
ads = ADS.ADS1115(i2c)
chan = AnalogIn(ads, ADS.P2)
while True:
print(chan.value)
time.sleep(0.1)
对ADS1115与各传感器进行配置的关键部分代码如下:
i2c = busio.I2C(board.SCL, board.SDA)
ads = ADS.ADS1115(i2c)
Moisture_channel = AnalogIn(ads, ADS.P2)
LDR_channel = AnalogIn(ads, ADS.P3)
LM35_channel = AnalogIn(ads, ADS.P1)
ADC_16BIT_MAX = 65536
lm35_constant = 10.0/1000
ads_InputRange = 4.096 #For Gain = 1; Otherwise change accordingly
ads_bit_Voltage = (ads_InputRange * 2) / (ADC_16BIT_MAX - 1)
显示表情相关代码:
while True:
# Read the specified ADC channels using the previously set gain value.
LDR_Value = LDR_channel.value
LDR_Percent = _map(LDR_Value, 22500, 50, 0, 100)
Moisture_Value = Moisture_channel.value
Moisture_Percent = _map(Moisture_Value, 31000, 15500, 0, 100)
ads_ch0 = LM35_channel.value
ads_Voltage_ch0 = ads_ch0 * ads_bit_Voltage
Temperature = int(ads_Voltage_ch0 / lm35_constant)
print("Temperature = ", Temperature)
print("Light Intensity = ", LDR_Percent)
print("Moisture % = ", Moisture_Percent)
if (LDR_Percent < 20):
if(LowIn_DataSent == 0):
client.send(bytes('sleep','utf-8'))
HighIn_DataSent = 0
LowIn_DataSent = 1
elif (LDR_Percent > 20):
if(HighIn_DataSent == 0):
client.send(bytes('happy','utf-8'))
HighIn_DataSent = 1
LowIn_DataSent = 0
if (Moisture_Percent < 90):
Moisture_Recent = Moisture_Percent
if(Thirsty_DataSent == 0):
client.send(bytes('thirsty','utf-8'))
Thirsty_DataSent = 1
Savory_DataSent = 0
Happy_DataSent = 0
elif (Moisture_Percent > 100):
Moisture_Recent = Moisture_Percent
if(Happy_DataSent == 0):
client.send(bytes('savory','utf-8'))
Happy_DataSent = 1
Savory_DataSent = 0
Thirsty_DataSent = 0
if(Temperature>30):
if(TemperatureDataSent == 0):
client.send(bytes('hotty','utf-8'))
TemperatureDataSent = 1
elif(Temperature<22):
if(TemperatureDataSent == 0):
client.send(bytes('freez','utf-8'))
TemperatureDataSent = 1
else:
TemperatureDataSent = 0
当光照强度百分比小于20时,显示屏表现出土壤“sleep”的状态,需要一些光照;当光照强度百分比大于20时,显示屏表现出土壤“happy”的状态,表示植物很健康;当土壤湿度小于90时,显示屏表现出土壤“thirsty”的状态,需要一些水分;当土壤湿度大于100时,显示屏表现出土壤“savory”的状态;当土壤温度高于30摄氏度时,显示屏表现出土壤“hotty”的状态,需要降温;当土壤温度低于22摄氏度时,显示屏表现出土壤“freez”的状态,需要一些温暖。
最终实现代码:
最终实现程序代码
import os
import sys
import logging
import spidev as SPI
sys.path.append("..")
from lib import LCD_2inch
from PIL import Image,ImageDraw,ImageFont
import socket
# Raspberry Pi pin configuration:
RST = 27
DC = 25
BL = 18
bus = 0
device = 0
logging.basicConfig(level=logging.DEBUG)
directory = os.getcwd()
#Server For Data Reception
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #绑定自己的电脑IP地址
server.bind(('192.168.43.137', 8080)) #开启监听
server.listen(5)
doInterrupt = 0
showOn = 0
def show(emotion):
global doInterrupt, showOn, disp
try:
disp = LCD_2inch.LCD_2inch(spi=SPI.SpiDev(bus, device),spi_freq=90000000,rst=RST,dc=DC,bl=BL)
disp.Init() # Initialize library.
#disp.clear() # Clear display.
bg = Image.new("RGB", (disp.width, disp.height), "BLACK")
draw = ImageDraw.Draw(bg)
# display with hardware SPI:
for i in range(180):
if (doInterrupt==1):
doInterrupt = 0
break
else:
image = Image.open(directory+'/emotion/'+emotion+'/frame'+str(i)+'.png')
image = image.rotate(180)
disp.ShowImage(image)
showOn = 0
disp.module_exit()
logging.info("quit:")
except IOError as e:
logging.info(e)
except KeyboardInterrupt:
disp.module_exit()
logging.info("quit:")
exit()
def main():
global doInterrupt, showOn
previousData = 'happy'
show('happy')
conn, addr = server.accept()
conn.settimeout(1000)
while True:
try:
data = conn.recv(1024).decode()
#print(data)
if (previousData != data):
print(data)
doInterrupt = 1
previousData = data
show(data)
except socket.timeout:
if showOn!=1:
show(previousData)
if __name__=='__main__':
try:
main()
except KeyboardInterrupt:
exit()