ESP8266 : assurer la lecture régulière des capteurs dans l'ESP8266 en même temps que la gestion des requêtes

1- Problématique

Dans le projet, il faudra assurer le fonctionnement autonome de la ventilation dans l'ESP8266.

C'est-à-dire que si la température augmente au-dessus d'un seuil, il faudra que la ventilation s'enclenche automatiquement sans passer par le wifi.

Tester le programme suivant afin de mieux cerner le problème :

#-------appel des bibliothèques
try:
    import usocket as socket
except:
    import socket
from machine import Pin, ADC
from time import sleep
import network
import esp
esp.osdebug(None)
import gc
gc.collect()
import onewire
import ds18x20
ow = onewire.OneWire(Pin(4))
sensor = ds18x20.DS18X20(ow)
#--------connexion wifi
ssid = '***'
password = '***'
station = network.WLAN(network.STA_IF)
station.active(True)
station.connect(ssid, password)
print('Attente connexion')
while station.isconnected() == False:
    print('.', end = " ")
    sleep(1)
print('Connexion réussie')
#affichage des paramètres de connexion de l'ESP
print ("ESP32 : Adresse IP, masque, passerelle et DNS", station.ifconfig())

def read_sensor():
    global tempVal
    roms = sensor.scan()
    sensor.convert_temp()
    tempVal=sensor.read_temp(roms[0])
    print(tempVal)
    sleep(1)
    
def web_page():
    html = """<html>
    <head><meta name="viewport" charset="utf-8"
        content="width=device-width, initial-scale=1">
    </head>
    <body>
        <h1>ESP8266</h1>
        <p>température : """+str(tempVal)+"""</p>
    </body>
    </html>"""
    return html
#=======================================================
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('', 80))
s.listen(2)
while True:
    print("début boucle")
    conn, addr = s.accept()
    print('Connexion depuis %s' % str(addr))
    request = conn.recv(1024)
    #print('Content = %s' % str(request))
    read_sensor()
    response = web_page()
    conn.send('HTTP/1.1 200 OK\n')
    conn.send('Content-Type: text/html\n')
    conn.send('Connection: close\n\n')
    conn.sendall(response)
    conn.close()
    print("connexion fermée")

Analyse

- lancer le script dans Thonny afin d'analyser le fonctionnement du programme principal :

- observer les messages dans la console afin de savoir à quel numéro de ligne le programme est en pause

- sur votre navigateur, saisir l'adresse IP de votre ESP et valider : dans la boucle while True le programme est rendu à combien de tour ?

On en déduit facilement que le programme attend qu'une requête soit traitée pour que la lecture du capteur puisse être faite.

Avec ce fonctionnement, la lecture d'un capteur ne se fait que s'il y a une requête, il est donc impossible de faire une régulation autonome !

2- Solution : lecture de capteur

Voici script qui apporte plusieurs améliorations :

- la fonction init_wifi() initialise le wifi et est appelée au début du programme principal (À conserver tel quel pour le projet).

- la fonction read_sensor() de lecture du capteur ds18b20 inclut la gestion des erreurs de lecture

- la fonction onRequest() permet de gérer l'attente d'une requête et la réponse à envoyer. À remarquer que la lecture du capteur ne se fait plus dans le traitement de la requête.

- la boucle du programme principal devient très facile à comprendre.

Tester et examiner le programme afin de vérifier son fonctionnement.

#-------appel des bibliothèques
try:
    import usocket as socket
except:
    import socket
from machine import Pin, ADC
from time import sleep
import network
import esp
esp.osdebug(None)
import gc
gc.collect()
import onewire
import ds18x20
ow = onewire.OneWire(Pin(4))
sensor = ds18x20.DS18X20(ow)
#--------connexion wifi
def init_wifi():
    ssid = '***'
    password = '***'
    station = network.WLAN(network.STA_IF)
    station.active(True)
    station.connect(ssid, password)
    print('Attente connexion')
    while station.isconnected() == False:
        print('.', end = " ")
        sleep(1)
    print('Connexion réussie')
    #affichage des paramètres de connexion de l'ESP
    print ("ESP32 : Adresse IP, masque, passerelle et DNS", station.ifconfig())

def read_sensor():
    global tempVal
    roms = sensor.scan()
    sensor.convert_temp()
    #----gestion des erreurs de lecture du capteur ds18b20
    try:
        tempVal=sensor.read_temp(roms[0])
    except:
        pass
    print(tempVal)
    
def web_page():
    html = """<html>
    <head><meta name="viewport" charset="utf-8"
        content="width=device-width, initial-scale=1">
    </head>
    <body>
        <h1>ESP8266</h1>
        <p>température : """+str(tempVal)+"""</p>
    </body>
    </html>"""
    return html

def onRequest():
    s.settimeout(2) #scan requete maxi 2s - ne pas changer
    #----gestion des erreurs de lecture sur le port
    try:
        conn, addr = s.accept()
    except OSError as er:
        pass
    else:
        print('Connexion depuis %s' % str(addr))
        request = conn.recv(1024)
        response = web_page()
        conn.send('HTTP/1.1 200 OK\n')
        conn.send('Content-Type: text/html\n')
        conn.send('Connexion: close\n\n')
        conn.sendall(response)
        conn.close()
        print("connexion fermée")    
#============================================================
init_wifi()
#protocole HTTP : ouverture du port pour écoute sur wifi
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('', 80))
s.listen(2)  #--autorise jusqu'à 2 clients en même temps
while True:
    read_sensor()
    onRequest()

3- Solution : commande d'une led

Tester et examiner le script pour commander une led.

#-------appel des bibliothèques
try:
    import usocket as socket
except:
    import socket
from machine import Pin
from time import sleep
import network
import esp
esp.osdebug(None)
import gc
gc.collect()
#--------définition des ports de l'ESP
led1 = Pin(13, Pin.OUT)
led2 = Pin(15, Pin.OUT)
#--------connexion wifi
def init_wifi():
    ssid = '***'
    password = '***'
    station = network.WLAN(network.STA_IF)
    station.active(True)
    station.connect(ssid, password)
    print('Attente connexion')
    while station.isconnected() == False:
        print('.', end = " ")
        sleep(1)
    print('Connexion réussie')
    #affichage des paramètres de connexion de l'ESP
    print ("ESP32 : Adresse IP, masque, passerelle et DNS", station.ifconfig())

def web_page():
    html = """<html>
    <head><meta name="viewport"
        content="width=device-width, initial-scale=1">
        <title>ESP8266 Serveur Web</title>
        <style>
            html {
               font-family: Helvetica;
               margin: 0px auto;
               text-align: center;}
           h1 {
               color: #0F3376;
               padding: 2vh;}
           p {font-size: 24px;
           }
           .button {
               background-color: #4CAF50;   /* Vert */
               border: none;
               border-radius: 6px;   /* Angle arrondi */
               color: white;
               padding: 15px 32px;
               text-align: center;
               text-decoration: none;
               font-size: 30px; }
           .buttonOff { background-color: #f44336; /* Rouge */ }
        </style>
    </head>
    <body>
        <h1>Commande LED</h1>
        <p><a href="/?led=on"><button class="button">Allumer LED</button></a></p>
        <p><a href="/?led=off"><button class="button buttonOff">Eteindre LED</button></a></p>
    </body>
    </html>"""
    return html

def onRequest():
    s.settimeout(2) #scan requete maxi 2s - ne pas changer
    #----gestion des erreurs de lecture sur le port
    try:
        conn, addr = s.accept()
    except OSError as er:
        pass
    else:
        request = conn.recv(1024)
        requete= str(request)
        #--Analyse de la requete
        if "GET /?led=on" in requete:
            print("LED1 ON")
            led1.value(1)
        if "GET /?led=off" in requete:
            print("LED1 OFF")
            led1.value(0)
        response = web_page()
        conn.send('HTTP/1.1 200 OK\n')
        conn.send('Content-Type: text/html\n')
        conn.send('Connexion: close\n\n')
        conn.sendall(response)
        conn.close()
        print("connexion fermée")

init_wifi() s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.bind(('', 80)) #port 80 dédié au protocole http s.listen(2) while True: onRequest()

4- Améliorer votre programme de l'activité précédente

En vous aidant des codes ci-dessus, améliorer le code de l'activité précédente pour :

- incorporer les fonctions présentées ci-dessus,

- observer dans la console l'affichage régulier des valeurs des capteurs