Raspberry Pi Zero 2 W Development Flower Pot Pet

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()