Système d'arrosage automatique : Différence entre versions

De HATLAB
Ligne 57 : Ligne 57 :
 
|Step_Title=Programmation
 
|Step_Title=Programmation
 
|Step_Content=#Micropython code for ESP32 M5Stamp C3 microcontroller
 
|Step_Content=#Micropython code for ESP32 M5Stamp C3 microcontroller
#***OLED dispaly 128*32 with I2C
+
    #***OLED dispaly 128*32 with I2C
#***M5STACK Watering Unit - Soil Moisture Sensor and Water Pump
+
    #***M5STACK Watering Unit - Soil Moisture Sensor and Water Pump
  
#import of libraries
+
    #import of libraries
from machine import Pin, SoftI2C, ADC
+
    from machine import Pin, SoftI2C, ADC
from time import sleep
+
    from time import sleep
import ssd1306
+
    import ssd1306
import gfx
+
    import gfx
import framebuf
+
    import framebuf
  
#Pin for moisture sensor
+
    #Pin for moisture sensor
moisure = ADC(Pin(4))
+
    moisure = ADC(Pin(4))
#Attenuation of the ADCA gain for analog read
+
    #Attenuation of the ADCA gain for analog read
moisure.atten(ADC.ATTN_11DB)
+
    moisure.atten(ADC.ATTN_11DB)
#Pin for pump control
+
    #Pin for pump control
pump = Pin(6, Pin.OUT)
+
    pump = Pin(6, Pin.OUT)
#Threshold irrigation point
+
    #Threshold irrigation point
threshold_point = 45
+
    threshold_point = 45
  
#I2C setup and initialisation  
+
    #I2C setup and initialisation  
i2c = SoftI2C(scl = Pin(9), sda = Pin(8))
+
    i2c = SoftI2C(scl = Pin(9), sda = Pin(8))
#OLED object creation and setup
+
    #OLED object creation and setup
oled = ssd1306.SSD1306_I2C(128,32,i2c)
+
    oled = ssd1306.SSD1306_I2C(128,32,i2c)
  
#bytearray of empty droplet icon
+
    #bytearray of empty droplet icon
droplet = bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x80\x00\x00\x03\xc0\x00\x00\x02@\x00\x00\x06`\x00\x00\x0c0\x00\x00\x08\x10\x00\x00\x18\x18\x00\x00\x10\x08\x00\x000\x0c\x00\x00`\x06\x00\x00@\x02\x00\x00@\x02\x00\x00\xc0\x03\x00\x00\x80\x01\x00\x00\x80\x01\x00\x01\x80\x01\x80\x01\x00\x00\x80\x01\x00\x08\x80\x01\x00\x08\x80\x00\x80\t\x00\x00\x80\x19\x00\x00\xc03\x00\x00A\xe6\x00\x000\x0c\x00\x00\x18\x18\x00\x00\x07\xe0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
+
    droplet = bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x80\x00\x00\x03\xc0\x00\x00\x02@\x00\x00\x06`\x00\x00\x0c0\x00\x00\x08\x10\x00\x00\x18\x18\x00\x00\x10\x08\x00\x000\x0c\x00\x00`\x06\x00\x00@\x02\x00\x00@\x02\x00\x00\xc0\x03\x00\x00\x80\x01\x00\x00\x80\x01\x00\x01\x80\x01\x80\x01\x00\x00\x80\x01\x00\x08\x80\x01\x00\x08\x80\x00\x80\t\x00\x00\x80\x19\x00\x00\xc03\x00\x00A\xe6\x00\x000\x0c\x00\x00\x18\x18\x00\x00\x07\xe0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
#bytearray of smiley face icon
+
    #bytearray of smiley face icon
smiley_face = bytearray(b'\x01\xf0\x00\x06\x0e\x00\x18\x01\x00\x10\x00\xc0 \x00@@\x00 C\x08 \x81\x0c \x80\x00\x10\x80\x00\x10\x80\x00\x10\x88\x01\x10\x84\x02 F\x04 A\x9c  `@0\x00\x80\x08\x01\x80\x07\x0e\x00\x01\xf0\x00')
+
    smiley_face = bytearray(b'\x01\xf0\x00\x06\x0e\x00\x18\x01\x00\x10\x00\xc0 \x00@@\x00 C\x08 \x81\x0c \x80\x00\x10\x80\x00\x10\x80\x00\x10\x88\x01\x10\x84\x02 F\x04 A\x9c  `@0\x00\x80\x08\x01\x80\x07\x0e\x00\x01\xf0\x00')
#bytearray of sad face icon
+
    #bytearray of sad face icon
sad_face = bytearray(b'\x01\xf8\x00\x06\x06\x00\x18\x01\x80\x10\x00\x80 \x00@@\x00 A\x08 \x83\x0c \x80\x00\x10\x80\x00\x10\x80\x00\x10\x81\xf8\x10\x82\x04 D\x02 L\x02` \x00@0\x00\x80\x08\x01\x80\x07\x0e\x00\x01\xf0\x00')
+
    sad_face = bytearray(b'\x01\xf8\x00\x06\x06\x00\x18\x01\x80\x10\x00\x80 \x00@@\x00 A\x08 \x83\x0c \x80\x00\x10\x80\x00\x10\x80\x00\x10\x81\xf8\x10\x82\x04 D\x02 L\x02` \x00@0\x00\x80\x08\x01\x80\x07\x0e\x00\x01\xf0\x00')
#bytearray of filled droplet icon
+
    #bytearray of filled droplet icon
icon = [
+
    icon = [
        [0,0],
+
            [0,0],
        [0,0],
+
            [0,0],
        [0,0],
+
            [0,0],
        [0,0],
+
            [0,0],
        [0,0],
+
            [0,0],
        [16,2],
+
            [16,2],
        [16,2],
+
            [16,2],
        [15,4],
+
            [15,4],
        [14,6],
+
            [14,6],
        [14,6],
+
            [14,6],
        [13,8],
+
            [13,8],
        [12,10],
+
            [12,10],
        [12,10],
+
            [12,10],
        [11,12],
+
            [11,12],
        [11,12],
+
            [11,12],
        [11,12],
+
            [11,12],
        [10,14],
+
            [10,14],
        [10,14],
+
            [10,14],
        [10,14],
+
            [10,14],
        [10,14],
+
            [10,14],
        [10,14],
+
            [10,14],
        [10,14],
+
            [10,14],
        [10,14],
+
            [10,14],
        [10,14],
+
            [10,14],
        [11,12],
+
            [11,12],
        [11,12],
+
            [11,12],
        [13,8],
+
            [13,8],
        [15,4],
+
            [15,4],
        [0,0],
+
            [0,0],
        [0,0],
+
            [0,0],
        [0,0],
+
            [0,0],
        [0,0],
+
            [0,0],
      ]
+
          ]
#Creation of frame buffer from icons
+
    #Creation of frame buffer from icons
frameD = framebuf.FrameBuffer(droplet, 32, 32, framebuf.MONO_HLSB)
+
    frameD = framebuf.FrameBuffer(droplet, 32, 32, framebuf.MONO_HLSB)
frameH = framebuf.FrameBuffer(smiley_face, 20, 20, framebuf.MONO_HLSB)
+
    frameH = framebuf.FrameBuffer(smiley_face, 20, 20, framebuf.MONO_HLSB)
frameS = framebuf.FrameBuffer(sad_face, 20, 20, framebuf.MONO_HLSB)
+
    frameS = framebuf.FrameBuffer(sad_face, 20, 20, framebuf.MONO_HLSB)
  
#defintion of values converting function in range (min, max)
+
    #defintion of values converting function in range (min, max)
def convert(x, in_min, in_max, out_min, out_max):
+
    def convert(x, in_min, in_max, out_min, out_max):
    return (x - in_min) * (out_max - out_min) // (in_max - in_min) + out_min
+
        return (x - in_min) * (out_max - out_min) // (in_max - in_min) + out_min
  
LmoisureLevel = []
+
    LmoisureLevel = []
AvmoisureLevel = 0
+
    AvmoisureLevel = 0
  
# get 50 values of moisture and calculate the average
+
    # get 50 values of moisture and calculate the average
while True:
+
    while True:
    moisureLevel = moisure.read()
+
        moisureLevel = moisure.read()
    LmoisureLevel.append(moisureLevel)
+
        LmoisureLevel.append(moisureLevel)
    if len(LmoisureLevel) == 50:
+
        if len(LmoisureLevel) == 50:
        AvmoisureLevel = sum(LmoisureLevel)/50
+
            AvmoisureLevel = sum(LmoisureLevel)/50
        LmoisureLevel.pop(0)
+
            LmoisureLevel.pop(0)
    AvmoisureLevel = int(AvmoisureLevel)
+
        AvmoisureLevel = int(AvmoisureLevel)
    moisure_string = str(AvmoisureLevel)
+
        moisure_string = str(AvmoisureLevel)
   
+
       
    #clear OLED display
+
        #clear OLED display
    oled.fill(0)
+
        oled.fill(0)
    #display texte
+
        #display texte
    oled.text('My plant!',10,0)
+
        oled.text('My plant!',10,0)
    #Convert the analog value to moisture level (0%-100%)
+
        #Convert the analog value to moisture level (0%-100%)
    AvmoisureLevel = convert(AvmoisureLevel, 1860, 2550, 100, 0)
+
        AvmoisureLevel = convert(AvmoisureLevel, 1860, 2550, 100, 0)
    w = int(AvmoisureLevel/3.3)
+
        w = int(AvmoisureLevel/3.3)
    #display moisture level  
+
        #display moisture level  
    oled.text(str(AvmoisureLevel) +"%",4,20)
+
        oled.text(str(AvmoisureLevel) +"%",4,20)
    #display emplty droplet icon
+
        #display emplty droplet icon
    oled.blit(frameD, 100, 0)
+
        oled.blit(frameD, 100, 0)
    #display droplet level
+
        #display droplet level
    for y,row in enumerate(icon):
+
        for y,row in enumerate(icon):
        for p in range(row[1]):
+
            for p in range(row[1]):
            if (y < 32 - w):
+
                if (y < 32 - w):
                oled.pixel(99+row[0]+p,y,0 )
+
                    oled.pixel(99+row[0]+p,y,0 )
            else:
+
                else:
                oled.pixel(99+row[0]+p,y,1)
+
                    oled.pixel(99+row[0]+p,y,1)
    #Control pump at given threshold point and display emoji
+
        #Control pump at given threshold point and display emoji
    if(AvmoisureLevel < threshold_point):
+
        if(AvmoisureLevel < threshold_point):
        pump.value(1)
+
            pump.value(1)
        oled.blit(frameS, 60, 12)
+
            oled.blit(frameS, 60, 12)
    else:
+
        else:
        pump.value(0)
+
            pump.value(0)
        oled.blit(frameH, 60, 12)
+
            oled.blit(frameH, 60, 12)
    oled.show()
+
        oled.show()
 
|Step_Picture_00=Système_d'arrosage_automatique_Micropython-logo.svg_-768x782.png
 
|Step_Picture_00=Système_d'arrosage_automatique_Micropython-logo.svg_-768x782.png
 
}}
 
}}
 
{{Notes}}
 
{{Notes}}
 
{{Tuto Status}}
 
{{Tuto Status}}

Version du 29 août 2022 à 22:36

Une Création de avatarMouhsine dans les catégories Électronique, Maison, Robotique, Science & Biologie, Alimentation & Agriculture. Dernière modification le 2/11/2022 par Mmoumni.

Système d'arrosage automatique IMG 20220707 224549.png

système d'arrosage automatique miniature, connecté sur cloud ou en local. Permets d'arroser de façon autonome une plante en fonction de l'humidité de la terre.

Licence : CERN Open Hardware Licence v1.2

Système d'arrosage automatique IMG 20220707 224549.png

Introduction

Ce système sera détaillé dans les étapes de ce tutoriel en deux versions matériellement identiques (version non connectée et version accessible par internet/ réseaux). La partie matérielle est conçue de façon d'être modulable (trois modules : pompe avec capteur humidité, ESP32 C3 et afficheur OLED Monochrome 0.91") facile à mettre en œuvre.

Liste des matériaux

  • Un module pompe avec capteur d'humidité intégrer ( = 12 €)
  • Un microcontrôleur type ESP32 ( = 8 €)
  • Une afficheur OLED 0.91" I2C ( = 4 €)
  • connecteur femelle type HY2.0 4P ( = 0.6 €)
  • Fils souple (coloré)

Liste des outils

  • Une imprimante 3D avec ces outils
  • Logiciel de conception 3D (CAO)
  • Ordinateur (PC, Raspberry pi 3 ou 4, ...) avec logiciel IDE Thonny
  • Fer à souder et étain
  • pinces de sertissage / dénudage

Etape n°1 - câblage

Choix des fils:

  • Les fils standard de câblage d'électroniques section max 0.3mm²
  • préférable de choisir les couleurs noir et rouge pour les alimentations et des autres couleur pour GPIO.

NB: ce projet nécessite peu des fils (langueur total max 20 cm)

Câblage du ESP32 et l'afficheur OLED et connecteur HY2.0-4P câbler les 3 éléments comme indiquer dans le diagramme (voir figure), utiliser des langueurs des fils la plus court possible, sachant que l'afficheur sera monté juste en haute du ESP32 et le connecteur juste à coté d'antenne (ESP32), cela permet de mettre l'ensemble dans un petit boitier.

Etape n°2 - Boitier (impression 3D)

Etape n°3 - Programmation

[[Step_Content::#Micropython code for ESP32 M5Stamp C3 microcontroller

   #***OLED dispaly 128*32 with I2C
   #***M5STACK Watering Unit - Soil Moisture Sensor and Water Pump
   #import of libraries
   from machine import Pin, SoftI2C, ADC
   from time import sleep
   import ssd1306
   import gfx
   import framebuf
   #Pin for moisture sensor
   moisure = ADC(Pin(4))
   #Attenuation of the ADCA gain for analog read
   moisure.atten(ADC.ATTN_11DB)
   #Pin for pump control
   pump = Pin(6, Pin.OUT)
   #Threshold irrigation point
   threshold_point = 45
   #I2C setup and initialisation 
   i2c = SoftI2C(scl = Pin(9), sda = Pin(8))
   #OLED object creation and setup
   oled = ssd1306.SSD1306_I2C(128,32,i2c)
   #bytearray of empty droplet icon
   droplet = bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x80\x00\x00\x03\xc0\x00\x00\x02@\x00\x00\x06`\x00\x00\x0c0\x00\x00\x08\x10\x00\x00\x18\x18\x00\x00\x10\x08\x00\x000\x0c\x00\x00`\x06\x00\x00@\x02\x00\x00@\x02\x00\x00\xc0\x03\x00\x00\x80\x01\x00\x00\x80\x01\x00\x01\x80\x01\x80\x01\x00\x00\x80\x01\x00\x08\x80\x01\x00\x08\x80\x00\x80\t\x00\x00\x80\x19\x00\x00\xc03\x00\x00A\xe6\x00\x000\x0c\x00\x00\x18\x18\x00\x00\x07\xe0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
   #bytearray of smiley face icon
   smiley_face = bytearray(b'\x01\xf0\x00\x06\x0e\x00\x18\x01\x00\x10\x00\xc0 \x00@@\x00 C\x08 \x81\x0c \x80\x00\x10\x80\x00\x10\x80\x00\x10\x88\x01\x10\x84\x02 F\x04 A\x9c  `@0\x00\x80\x08\x01\x80\x07\x0e\x00\x01\xf0\x00')
   #bytearray of sad face icon
   sad_face = bytearray(b'\x01\xf8\x00\x06\x06\x00\x18\x01\x80\x10\x00\x80 \x00@@\x00 A\x08 \x83\x0c \x80\x00\x10\x80\x00\x10\x80\x00\x10\x81\xf8\x10\x82\x04 D\x02 L\x02` \x00@0\x00\x80\x08\x01\x80\x07\x0e\x00\x01\xf0\x00')
   #bytearray of filled droplet icon
   icon = [
           [0,0],
           [0,0],
           [0,0],
           [0,0],
           [0,0],
           [16,2],
           [16,2],
           [15,4],
           [14,6],
           [14,6],
           [13,8],
           [12,10],
           [12,10],
           [11,12],
           [11,12],
           [11,12],
           [10,14],
           [10,14],
           [10,14],
           [10,14],
           [10,14],
           [10,14],
           [10,14],
           [10,14],
           [11,12],
           [11,12],
           [13,8],
           [15,4],
           [0,0],
           [0,0],
           [0,0],
           [0,0],
          ]
   #Creation of frame buffer from icons
   frameD = framebuf.FrameBuffer(droplet, 32, 32, framebuf.MONO_HLSB)
   frameH = framebuf.FrameBuffer(smiley_face, 20, 20, framebuf.MONO_HLSB)
   frameS = framebuf.FrameBuffer(sad_face, 20, 20, framebuf.MONO_HLSB)
   #defintion of values converting function in range (min, max)
   def convert(x, in_min, in_max, out_min, out_max):
       return (x - in_min) * (out_max - out_min) // (in_max - in_min) + out_min
   LmoisureLevel = []
   AvmoisureLevel = 0
   # get 50 values of moisture and calculate the average
   while True:
       moisureLevel = moisure.read()
       LmoisureLevel.append(moisureLevel)
       if len(LmoisureLevel) == 50:
           AvmoisureLevel = sum(LmoisureLevel)/50
           LmoisureLevel.pop(0)
       AvmoisureLevel = int(AvmoisureLevel)
       moisure_string = str(AvmoisureLevel)
       
       #clear OLED display
       oled.fill(0)
       #display texte
       oled.text('My plant!',10,0)
       #Convert the analog value to moisture level (0%-100%)
       AvmoisureLevel = convert(AvmoisureLevel, 1860, 2550, 100, 0)
       w = int(AvmoisureLevel/3.3)
       #display moisture level 
       oled.text(str(AvmoisureLevel) +"%",4,20)
       #display emplty droplet icon
       oled.blit(frameD, 100, 0)
       #display droplet level
       for y,row in enumerate(icon):
           for p in range(row[1]):
               if (y < 32 - w):
                   oled.pixel(99+row[0]+p,y,0 )
               else:
                   oled.pixel(99+row[0]+p,y,1)
       #Control pump at given threshold point and display emoji
       if(AvmoisureLevel < threshold_point):
           pump.value(1)
           oled.blit(frameS, 60, 12)
       else:
           pump.value(0)
           oled.blit(frameH, 60, 12)
       oled.show()]]

Notes et références