Mot-clé - micropython

Fil des billets

mardi 8 novembre 2016

Se connecter à l'ESP8266 avec ampy d'Adafruit pour plus de facilité

Dans les articles précédents (ici et ici), nous avons proposé de téléverser des fichiers sur l'ESP8266/NodeMCU à l'aide de l'utilitaire webcli.py fourni avec WebREPL. Si l'on accède physiquement à la puce (via le port série), il est possible d'utiliser l'utilitaire Ampy développé par Adafruit.

  1. Installons adafruit-ampy avec pip (pip3 si Python3)
pip3 install adafruit-ampy

Il se peut qu'il faille lancer cette commande en root ou avec sudo selon votre distribution.

  1. Flashons micropython sur le NodeMCU/ESP8266 sans surprise :
esptool.py --port /dev/ttyUSB0 --baud 460800 erase_flash
esptool.py --port /dev/ttyUSB0 --baud 460800 write_flash --flash_size=8m 0 /path/to/esp8266-20161017-v1.8.5.bin
  1. Après re-démarrage, connectons-nous à l'ESP8266 pour vérifier que tout fonctionne correctement :
picocom /dev/ttyUSB0 -b 115200
  1. Connectons-nous alors à l'aide d'ampy et affichons la liste des fichiers contenus sur la puce avec l'option "ls" :
ampy -p /dev/ttyUSB0 ls

Sur l'ESP8266 fraîchement flashé, on verra seulement le fichier "boot.py".

  1. Pour ajouter un fichier, il faut utiliser l'option "put"
ampy -p /dev/ttyUSB0 put /path/to/file

Les commandes disponibles avec ampy sont :

  get    Télécharger un fichier depuis la puce.
  ls     Lister le contenu de la puce.
  mkdir  Créer un dossier sur la puce.
  put    Téléverser un fichier sur la puce.
  reset  Provoquer un soft reset/reboot de la puce.
  rm     Supprimer un fichier de la puce.
  run    Exécuter un script sur la puce et afficher la sortie standard.

ampy from Adafruit to connect to ESP8266

In past articles, we mentioned WebREPL and webcli.py tool to connect and upload files to the ESP8266 board equipped with Python. I recently discovered a new tool that does the job even better: adafruit-ampy. It works well with NodeMCU-embarked ESP8266 chips.

  1. Download and install adafruit-ampy with pip (in the following I will assume you are equipped with Python 3)
pip3 install adafruit-ampy

Depending on your Linux distribution, you may have to run this with sudo or as root.

  1. Let's flash our ESP8266 with micropython with esptool.py
esptool.py --port /dev/ttyUSB0 --baud 460800 erase_flash
esptool.py --port /dev/ttyUSB0 --baud 460800 write_flash --flash_size=8m 0 /path/to/esp8266-20161017-v1.8.5.bin
  1. Let's reboot the board after a couple of seconds. We can connect to it with picocom for example to check that the command line is fully accessible and the micropython system works.
picocom /dev/ttyUSB0 -b 115200
  1. Now let's connect with ampy to list the files on the board:
ampy -p /dev/ttyUSB0 ls

On a freshly booted ESP8266/NodeMCU, I only see "boot.py".

  1. To add a file, just use the "put" command:
ampy -p /dev/ttyUSB0 put /path/to/file

For the reference, the commands available are:

  get    Retrieve a file from the board.
  ls     List contents of a directory on the board.
  mkdir  Create a directory on the board.
  put    Put a file on the board.
  reset  Perform soft reset/reboot of the board.
  rm     Remove a file from the board.
  run    Run a script and print its output.

mardi 25 octobre 2016

Un couple d'enfer : ESP8266 et DS18B20, un petit objet connecté à quelques euros qui mesure la température et la transmet par Wifi

Nous avons parlé de l'ESP8266 propulsé par micropython dans le billet précent. Parmi la multitude d'application possible, nous allons voir aujourd'hui comment coupler l'ESP8266 à une sonde DS18B20 pour relever périodiquement la température d'une pièce et transférer la valeur en Wifi à une base InfluxDB.

Principe

Nous parlons ici de mesure de température dans un lieu de vie : une prise de température toutes les 10 minutes est suffisante. Nous allons dès lors mettre en place le fonctionnement suivant pour l'ESP8266 :

  1. allumage, mise en route du Wifi, connexion au Wifi local
  2. mesure à 10 reprises de la température
  3. suppression des 2 valeurs extrêmes supérieures et des 2 valeurs extrêmes inférieures
  4. moyenne des 6 valeurs restantes
  5. envoi de la valeur à une base de données InfluxDB au moyen d'une requête POST
  6. mise en sommeil de l'ESP8266 pour 10 minutes

A la sortie de la mise en sommeil le cycle recommence.

En outre, un minuteur logiciel provoquera un redémarrage de l'ESP8266 s'il est bloqué 2 minutes sans arriver au bout de son cycle.

Branchements

Rien de sorcier : on alimente la sonde 1-wire DS18B20 en 3.3V (comme l'ESP8266), on en relie les masses et on place le pin de données de la sonde 1-wire sur un GPIO adéquat de l'ESP8266. Il ne faudra pas oublier la résistance de 4.7 kOhms entre le pin Vin et le pin Data de la sonde ! Et pour permettre la sortie du sommeil, il faudra relier le pin RESET (RST) de l'ESP8266 avec le GPIO 16 (celui de l'alarme RTC).

Code sur l'ESP8266

Nous allons placer le code ci-dessous dans le fichier main.py qui sera ensuite envoyé sur l'ESP8266 à l'aide des outils évoqués dans le billet précent :

./webrepl_cli.py /path/to/main.py 192.168.4.1:/

Le code intégral, fortement commenté, est là :

import socket
import time
import machine #pour accéder aux GPIOs
import onewire, ds18x20 #pour lire la sonde 1-wire
import urequests  #pour envoyer la requête POST
from machine import Timer

#Faire flasher i fois la petite LED bleue de la puce ESP8266
def do_flashes(i):
    if i<1:
        i=1
    pin = machine.Pin(2, machine.Pin.OUT)
    for z in range(0,i):
        time.sleep_ms(250)
        pin.value(not pin.value())
        time.sleep_ms(250)
        pin.value(not pin.value())
    pin.value(1) #On s'assure que la LED finit dans l'état "éteint"

#Se connecter au Wifi local
def do_connect():
    import network
    sta_if = network.WLAN(network.STA_IF)
    if not sta_if.isconnected():
        print('connecting to network...')
        sta_if.active(True)
        sta_if.connect('SSID', 'password') #Remplacer le nom du SSID et le mot de passe de connexion
        while not sta_if.isconnected():
            pass
    print('network config:', sta_if.ifconfig())  #On imprime l'IP de la puce une fois connectée, pratique pour déboguer sur le port série
    do_flashes(4)

#Effectuer une requête POST sur une URL InfluxDB (ou autre)
def http_post(data):
    url = 'https://path.to.influx.db/write?db=dbname'
    data = ("temperature,tag1=x1,tag2=x2 value=%s" %
(str(data)))
    resp = urequests.post(url, data=data)

#Effectuer une mesure sur le GPIO 4
def do_ds18b20():
    dat = machine.Pin(4)
    ds = ds18x20.DS18X20(onewire.OneWire(dat)) #On crée l'objet OneWire
    roms = ds.scan()  #On scanne le bus pour trouver toutes les sondes
    print('found devices:', roms)

    #On mesure 10 fois la température
    if len(roms)>0:
        templist = []
        for i in range(10):
            ds.convert_temp()
            time.sleep_ms(1000) #On attend 1 seconde entre chaque prise de mesure pour laisser le temps à la sonde de se réinitialiser
            temp = ds.read_temp(roms[0])
            templist.append(temp)
        templist.remove(max(templist)) #On supprime les valeurs extrêmes
        templist.remove(max(templist))
        templist.remove(min(templist))
        templist.remove(min(templist))
        sum_of_temps = 0
        for temp in templist:
            sum_of_temps = sum_of_temps + temp
        final_temp = sum_of_temps/6
        print('Final temp: ', final_temp)
        return final_temp

#Redémarre l'ESP8266, "machine.reset" est équivalent à un redémarrage électrique
def force_reset():
    print("Machine inactive for too long, this is not normal, rebooting!")
    machine.reset()

#Regarde si l'ESP8266 se réveille d'un sommeil profond (et non d'un (re)démarrage électrique)
if machine.reset_cause() == machine.DEEPSLEEP_RESET:
    print('Woke from a deep sleep')

#On active le minuteur qui provoque le redémarrage dans 2 minutes
tim = Timer(-1)
tim.init(period=120000, mode=Timer.ONE_SHOT, callback=lambda
t:force_reset())

do_flashes(2) #On signale le démarrage du travail par 2 clignotements
do_connect() #Connexion au Wifi
time.sleep_ms(2000) #On attend 2 secondes
temp = do_ds18b20() #On mesure la température
http_post(temp) #On l'envoie sur InfluxDB

print('set RTC alarm to wake up later')
rtc = machine.RTC() 
rtc.irq(trigger=rtc.ALARM0, wake=machine.DEEPSLEEP) #On configure RTC.ALARM0 pour être capable de re-démarrer le périphérique
rtc.alarm(rtc.ALARM0, 600000) #  Après 600 secondes RTC.ALARM0 redémarrera la machine !
#Petit compte à rebours, pratique pour l'interrompre par Ctrl+C, quand l'on veut se connecter à l'ESP8266 pour en modifier le comportement
print('deep sleep in 20 seconds')
time.sleep_ms(15000)
print('deep sleep in 5 seconds')
time.sleep_ms(2000)
print('deep sleep in 3 seconds')
time.sleep_ms(1000)
print('deep sleep in 2 seconds')
time.sleep_ms(2000)
print('deep sleep in 1 seconds')
time.sleep_ms(1000)
print('deep sleep now! waking up in 600 seconds')
machine.deepsleep()

Et voilà une petite sonde qui prend la température toutes les 10 minutes.

Consommation ?

Un petit test rapide a montré que mon ESP8266 monté sur un kit de développement NodeMCU v1.0 (je pressens que la consommation serait moindre sans le kit de développement) :

  • demande ~100 mA lors des périodes de fonctionnement
  • demande <~10 mA lors de la phase de sommeil

C'est à creuser plus finement mais cela donne déjà quelques ordres de grandeur.

dimanche 23 octobre 2016

Micropython sur ESP8266, l'électronique toujours plus libre et puissante !

L'ESP8266 est un petite puce développée par Espressif qui a de multiples qualités :

  • elle dispose d'un petit coeur programmable
  • elle se connecte en Wifi ou/et se comporte comme un point d'accès Wifi
  • elle est fort peu onéreuse (quelques euros à peine)
  • elle a été largement adoptée par de nombreux bricoleurs de la blogosphère et on trouve une abondante littérature à son sujet

Initialement, elle a été beaucoup utilisée comme extension Wifi peu chère pour montages Arduino.

Mais ses qualités l'ont peu à peu rendu intéressante et utilisable seule : différents micro-systèmes ont été portés sur l'ESP8266 et l'ont peu à peu transformé en puce Wifi programmable. Ainsi, sur certains montages simples (internet des choses, domotique...) elle remplacera aisément un Arduino ou un Raspberry Pi et apportera en sus faible coût, faible consommation et encombrement réduit.

Nous allons voir dans ces lignes comment démarrer avec cette carte en l'équipement du micro-système micropython. Micropython a été porté récemment sur ESP8266 et le code en a été libéré suite à une campagne Kickstarter fructueuse.

Commençons par le matériel

La puce ESP8266 ressemble à ceci dans sa version 12 (qui est la plus performance notamment avec le plus grand nombre d'entrées-sorties) : esp8266-esp12.jpg

Pour un usage plus facile, on pourra la préférer pré-montée au sein d'un kit de développement qui en rendra :

  • l'alimentation facile (en USB 5V, la puce elle-même ne supporte que 3.3V)
  • le flashage aisé (toujours au travers d'un port USB fourni)
  • également le reset facilité à l'aide d'un bouton poussoir
  • enfin l'utilisation facile sur une breadboard pour prototypage

En inconvénient, la consommation électrique sera un peu plus forte et l'encombrement sera plus important. Mais passée la phase de prototypage, rien n'empêche d'utiliser la carte seule !

Parmi les kits de développement pratiques, on peut noter les planches NodeMCU (prendre la v1) qui sont très bien, sont libres (code source ici) et ressemblent à ceci : NodeMCU_DEVKIT_1.0.jpg

Attention toutefois à la correspondance des pins de la planche de développement et les GPIOs de l'ESP8266 : D1, D2, ... ne correspondent pas à GPIO1, GPIO2... Cf. le schéma ci-dessous : NODEMCU_DEVKIT_V1.0_PINMAP.png

Envoyons Micropython

Une fois en possession d'une puce ESP8266 et de son kit de développement, il suffit de s'y connecter à l'aide d'un câble USB et un nouveau périphérique /dev/ttyUSB0 doit devenir disponible pour le système.

On peut alors :

  • télécharger la dernière version du système micropython ici en prenant bien la version pour ESP8266
  • installer esptools.py sur sa machine par exemple avec la commande
pip install esptool
  • vider la mémoire actuelle de l'ESP8266 (pour éviter tout problème) avec la commande
esptool.py --port /dev/ttyUSB0 erase_flash
  • puis envoyer micropython (remplacer esp8266.bin par le fichier que vous avez obtenu sur le site de micropython)
esptool.py --port /dev/ttyUSB0 --baud 460800 write_flash --flash_size=8m 0 /path/to/esp8266.bin

Premier usage via le port série

Après redémarrage de la puce, on peut s'y connecter en série au travers de l'USB par exemple avec picocom (ou un autre logiciel de son choix) :

picocom /dev/ttyUSB0 -b 115200

et on obtient alors une console REPL Python qui permet d'exécuter toute commande de son choix dans l'environnement micropython.

Par exemple pour changer l'état d'un GPIO (attention à la numérotation, cf supra), on pourra appeler les commandes suivantes :

pin = machine.Pin(2, machine.Pin.OUT)
pin.value(1)
pin.value(0)

qui feront basculer en état HIGH/LOW le GPIO2 (D4 sur la planche de développement).

Usage au travers de WebREPL

Encore plus pratique, il est possible de se connecter à l'ESP8266 et à la console Python au travers du Wifi. Pour ce faire, l'ESP8266 se positionne comme un point d'accès Wifi auquel on peut se connecter : le mot de passe de connexion est "micropythoN".

Une fois connecté, on peut appeler l'ESP8266 à l'adresse 192.168.4.1 et se connecter à la console Python à l'aide de WebREPL, une page avec un peu de javascript qui aide à se connecter à la console REPL depuis un navigateur.

Il suffit de télécharger le contenu du dépôt WebREPL et lancer le fichier webrepl.html.

Envoyer un fichier sur l'ESP8266

Pour envoyer un fichier sur l'ESP8266, par exemple un fichier main.py qui sera exécuté à chaque lancement après initialisation, on pourra utiliser le commande outil webrepl_cli.py livré dans le dépôt WebREPL.

Connecté au point d'accès de l'ESP8266, la commande :

./webrepl_cli.py /path/to/main.py 192.168.4.1:/

se chargera de copier le fichier main.py à la racine de l'ESP8266.

Main.py pour tout contrôler

Dès lors, il est possible de placer le code de son choix dans le fichier main.py à la racine de l'ESP8266 pour l'asservir et lui faire exécuter le code de son choix.

On pourra par exemple :

  • désactiver le point d'accès
  • faire se connecter l'ESP8266 à un réseau WIfi local
  • faire agir l'ESP8266 sur le réseau (envoi de paquets, exécution de requêtes diverses...)
  • jouer avec les ports GPIOs

Les idées ne vous manqueront certainement pas pour peupler le fichier main.py. Voilà un bon point de départ dans la documentation de micropython sur ESP8266.