1. Materials required for hardware
First, you need a Raspberry Pi board. Here we use the Raspberry Pi Zero 2 W.
At the heart of the Raspberry Pi Zero 2 W is the RP3A0, a custom system-in-package designed by Raspberry Pi UK. Powered by a quad-core 1-bit ARM Cortex-A512 processor clocked at 53GHz and 2MB of SDRAM, the Zero 64 is five times faster than the original Raspberry Pi Zero.
Wireless LAN is built into a shielded enclosure with improved RF compliance, giving you greater flexibility when designing with the Raspberry Pi Zero 2 W.
All come in the same tiny 65mm x 30mm form factor.
1. Through LM35 temperature sensor
2. Capacitive humidity sensor
3. LDR module to obtain soil temperature, humidity, and photosensitivity
4. ADS1115 analog-to-digital converter:
Please see the introduction of ADS1115 for details:
https://blog.csdn.net/2202_75379338/article/details/134357187?spm=1001.2014.3001.5502
5. LCD display (2 inches, 8 pins)
2. Hardware circuit connection
1RaspberryPI zero 2W and LCD display
RaspberryPI zero 2W and LCD display wiring table
RaspberryPI zero 2W |
LCD display |
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 Connect RaspberryPI zero 2W and ADS1115
RaspberryPI zero 2W and ADS1115 wiring table
RaspberryPI zero 2W |
ADS1115 |
GND |
GND |
5V BCM 3(SCL) BCM 2(SDA) |
VCC SCL SDA |
3 Connect ADS1115 to each sensor
ADS1115 and various sensor wiring table
ADS1115 |
LM35 temperature sensor |
capacitive humidity sensor |
LDR module |
GND |
GND |
GDN |
GDN |
VCC A1 |
VCC Vout |
VCC |
VCC |
A2 |
AUOT |
||
A3 |
AO |
3. Code part
The key code for configuring RaspberryPI zero 2W and LCD display is as follows:
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): importRPi.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
This is a RaspberryPi class that is used to control the SPI and I2C interfaces on the RaspberryPI zero 2W, as well as control the LCD display’s backlight, reset and data/command select pins. On initialization, it sets the pins to output mode and initializes the SPI and I2C interfaces.
class LCD_2inch(lcdconfig.RaspberryPi): width=240 height = 320 # Set the width and height of the LCD screen def command(self, cmd): self.digital_write(self.DC_PIN, self.GPIO.LOW) # Set the DC pin to low level self.spi_writebyte([cmd]) # Send command through SPI bus
This is an LCD screen driver for connecting RaspberryPI zero 2W and LCD display. It defines the width and height of the screen and implements a command function for sending instructions to the screen. This function sends commands to the SPI bus and uses GPIO to control the data/command pins.
The key code for configuring RaspberryPI zero 2W and ADS1115 is as follows:
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)
The key code for configuring ADS1115 and each sensor is as follows:
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)
Display expression-related codes:
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
When the light intensity percentage is less than 20, the display shows the soil “sleep” state, which needs some light; when the light intensity percentage is greater than 20, the display screen shows the soil “happy” state, indicating that the plant is healthy; when the soil moisture When the soil humidity is less than 90, the display shows the “thirsty” state of the soil and needs some moisture; when the soil humidity is greater than 100, the display shows the “savory” state of the soil; when the soil temperature is higher than 30 degrees Celsius, the display shows the “savory” state of the soil. The soil is in a “hotty” state and needs cooling; when the soil temperature is lower than 22 degrees Celsius, the display shows the soil in a “freez” state and needs some warmth.
Final implementation code:
Final implementation program code import os importsys 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) #Bind your own computer IP address server.bind(('192.168.43.137', 8080)) #Enable monitoring 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()