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

De HATLAB
 
(26 révisions intermédiaires par le même utilisateur non affichées)
Ligne 13 : Ligne 13 :
 
}}
 
}}
 
{{Introduction
 
{{Introduction
|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.
+
|Introduction=Ce système permet d'arroser automatiquement une plante et informe l'utilisateur du pourcentage d'humidité. Le matériel est conçu pour être modulaire (trois modules: pompe avec capteur d'humidité, ESP32 C3 et écran monochrome OLED 0.91") facile à implémenter.
 
}}
 
}}
 
{{Materials
 
{{Materials
Ligne 50 : Ligne 50 :
 
}}
 
}}
 
{{Tuto Step
 
{{Tuto Step
|Step_Title=Boitier (impression 3D)
+
|Step_Title=Boitier (impression 3D) et assemblage
 +
|Step_Content=*Le boitier du système se compose de trois parties (capot supérieur, couvercle inférieur et la partie latérale) cette décomposition facilite l'impression 3D, la maintenance du système et l'accès à ses composantes électroniques.
 +
Lien Thingiverse vers le fichier format F3D
 +
https://www.thingiverse.com/thing:5487673
 +
 
 +
*Le boitier peux être imprimé sans utilisation de mâtereaux support et sans paramètres particuliers.
 +
*le boitier est des dimensions (38mm*18.5mm*14mm) permet d'accueillir le M5Stamp C3 l'afficheur OLED et le connecteur HY2.0 4P.
 +
'''L'assemblage consiste à utiliser la colle à chaud:'''
 +
''M5Stamp C3 est collé sur le capot inférieur de telle façon soit accessible par USB-C du côté et on fixe de l'autre côté le connecteur HY2.0 4P.''
 +
''Enfin l'afficheur OLED et coller sur le couvercle supérieur de tell façon que toute la partie d'affiche soi visible.''
 
|Step_Picture_00=Système_d'arrosage_automatique_IMG_20220704_221436.jpg
 
|Step_Picture_00=Système_d'arrosage_automatique_IMG_20220704_221436.jpg
 
|Step_Picture_01=Système_d'arrosage_automatique_IMG_20220704_221336.jpg
 
|Step_Picture_01=Système_d'arrosage_automatique_IMG_20220704_221336.jpg
 +
|Step_Picture_02=Arrosage_automatique_Capture_d_cran_2022-08-29_230406.png
 +
|Step_Picture_03=Arrosage_automatique_Sans_nom_v5.png
 +
|Step_Picture_04=Arrosage_automatique_Capture_d_cran_2022-08-29_231623.png
 
}}
 
}}
 
{{Tuto Step
 
{{Tuto Step
 
|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
 
+
    moisure = ADC(Pin(4))
#Pin for moisture sensor
+
Attenuation of the ADCA gain for analog read
moisure = ADC(Pin(4))
+
    moisure.atten(ADC.ATTN_11DB)
#Attenuation of the ADCA gain for analog read
+
Pin for pump control
moisure.atten(ADC.ATTN_11DB)
+
    pump = Pin(6, Pin.OUT)
#Pin for pump control
+
Threshold irrigation point
pump = Pin(6, Pin.OUT)
+
    threshold_point = 45
#Threshold irrigation point
+
I2C setup and initialisation  
threshold_point = 45
+
    i2c = SoftI2C(scl = Pin(9), sda = Pin(8))
 
+
OLED object creation and setup
#I2C setup and initialisation  
+
    oled = ssd1306.SSD1306_I2C(128,32,i2c)
i2c = SoftI2C(scl = Pin(9), sda = Pin(8))
+
bytearray of empty droplet icon
#OLED object creation and setup
+
    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')
oled = ssd1306.SSD1306_I2C(128,32,i2c)
+
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)
  
#bytearray of empty droplet icon
+
defintion of values converting function in range (min, max)
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')
+
    def convert(x, in_min, in_max, out_min, out_max):
#bytearray of smiley face icon
+
         return (x - in_min) * (out_max - out_min) // (in_max - in_min) + out_min
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)
+
    LmoisureLevel = []
def convert(x, in_min, in_max, out_min, out_max):
+
     AvmoisureLevel = 0
     return (x - in_min) * (out_max - out_min) // (in_max - in_min) + out_min
 
  
LmoisureLevel = []
+
get 50 values of moisture and calculate the average
AvmoisureLevel = 0
+
    while True:
 
+
        moisureLevel = moisure.read()
# get 50 values of moisture and calculate the average
+
        LmoisureLevel.append(moisureLevel)
while True:
+
        if len(LmoisureLevel) == 50:
    moisureLevel = moisure.read()
+
            AvmoisureLevel = sum(LmoisureLevel)/50
    LmoisureLevel.append(moisureLevel)
+
            LmoisureLevel.pop(0)
    if len(LmoisureLevel) == 50:
+
        AvmoisureLevel = int(AvmoisureLevel)
        AvmoisureLevel = sum(LmoisureLevel)/50
+
        moisure_string = str(AvmoisureLevel)
        LmoisureLevel.pop(0)
+
clear OLED display
    AvmoisureLevel = int(AvmoisureLevel)
+
        oled.fill(0)
    moisure_string = str(AvmoisureLevel)
+
display texte
   
+
        oled.text('My plant!',10,0)
    #clear OLED display
+
Convert the analog value to moisture level (0%-100%)
    oled.fill(0)
+
        AvmoisureLevel = convert(AvmoisureLevel, 1860, 2550, 100, 0)
    #display texte
+
        w = int(AvmoisureLevel/3.3)
    oled.text('My plant!',10,0)
+
display moisture level  
    #Convert the analog value to moisture level (0%-100%)
+
        oled.text(str(AvmoisureLevel) +"%",4,20)
    AvmoisureLevel = convert(AvmoisureLevel, 1860, 2550, 100, 0)
+
display emplty droplet icon
    w = int(AvmoisureLevel/3.3)
+
        oled.blit(frameD, 100, 0)
    #display moisture level  
+
display droplet level
    oled.text(str(AvmoisureLevel) +"%",4,20)
+
        for y,row in enumerate(icon):
    #display emplty droplet icon
+
            for p in range(row[1]):
    oled.blit(frameD, 100, 0)
+
                if (y < 32 - w):
    #display droplet level
+
                    oled.pixel(99+row[0]+p,y,0 )
    for y,row in enumerate(icon):
+
                else:
        for p in range(row[1]):
+
                    oled.pixel(99+row[0]+p,y,1)
            if (y < 32 - w):
+
Control pump at given threshold point and display emoji
                oled.pixel(99+row[0]+p,y,0 )
+
        if(AvmoisureLevel < threshold_point):
            else:
+
            pump.value(1)
                oled.pixel(99+row[0]+p,y,1)
+
            oled.blit(frameS, 60, 12)
    #Control pump at given threshold point and display emoji
+
        else:
    if(AvmoisureLevel < threshold_point):
+
            pump.value(0)
        pump.value(1)
+
            oled.blit(frameH, 60, 12)
        oled.blit(frameS, 60, 12)
+
        oled.show()
    else:
 
        pump.value(0)
 
        oled.blit(frameH, 60, 12)
 
    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
 +
|Notes='''Références:'''
 +
<u>https://docs.micropython.org/en/latest/esp32/quickref.html</u> \\
 +
<u>https://github.com/adafruit/Adafruit_SSD1306</u> \\
 +
<u>https://docs.m5stack.com/en/unit/watering</u>
 +
}}
 
{{Tuto Status}}
 
{{Tuto Status}}

Version actuelle datée du 2 novembre 2022 à 12:05

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 permet d'arroser automatiquement une plante et informe l'utilisateur du pourcentage d'humidité. Le matériel est conçu pour être modulaire (trois modules: pompe avec capteur d'humidité, ESP32 C3 et écran monochrome OLED 0.91") facile à implémenter.

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) et assemblage

  • Le boitier du système se compose de trois parties (capot supérieur, couvercle inférieur et la partie latérale) cette décomposition facilite l'impression 3D, la maintenance du système et l'accès à ses composantes électroniques.

Lien Thingiverse vers le fichier format F3D https://www.thingiverse.com/thing:5487673

  • Le boitier peux être imprimé sans utilisation de mâtereaux support et sans paramètres particuliers.
  • le boitier est des dimensions (38mm*18.5mm*14mm) permet d'accueillir le M5Stamp C3 l'afficheur OLED et le connecteur HY2.0 4P.

L'assemblage consiste à utiliser la colle à chaud: M5Stamp C3 est collé sur le capot inférieur de telle façon soit accessible par USB-C du côté et on fixe de l'autre côté le connecteur HY2.0 4P. Enfin l'afficheur OLED et coller sur le couvercle supérieur de tell façon que toute la partie d'affiche soi visible.

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

Références: https://docs.micropython.org/en/latest/esp32/quickref.html \\ https://github.com/adafruit/Adafruit_SSD1306 \\ https://docs.m5stack.com/en/unit/watering