ESP32

De Knowledge base

Après l'ESP 8266 qui est déja fantastique tournons nous vers l'ESP 32 et son module debase ESP-Wroom 32.

Installation

Installation sous windows

Installation du driver série

Le module ESP-Wroom 32 est fournit dans mon cas avec une interface USB Série non pas FTDI mais... CP2102.

On télécharge les drivers ici: https://www.silabs.com/products/development-tools/software/usb-to-uart-bridge-vcp-drivers

C'est un gros ZIP que l'on extrait et on lance l'installateur qui va bien (pour moi Windows 7 64 bits).

A la fin on a un port COM de plus... moi c'est COM30 qui s'appelle Silicom labs CP210x...

Installtion de l'env de dev sous arduino

Maintenant il suffit d'ajouter :

https://dl.espressif.com/dl/package_esp32_index.json

dans les URL de cartes (Fichier | Préférence | Url cartes supplémentaires)

Apres avoir installé l'IDE Arduino il faut l'ouvrir et... le refermer.

Une fois l'IDE fermé on utilise GIT :

$ git clone https://github.com/espressif/arduino-esp32
Cloning into 'arduino-esp32'...
remote: Counting objects: 6329, done.
remote: Compressing objects: 100% (20/20), done.
remote: Total 6329 (delta 7), reused 13 (delta 4), pack-reused 6305
Receiving objects: 100% (6329/6329), 99.59 MiB | 1.20 MiB/s, done.
Resolving deltas: 100% (3492/3492), done.
Checking connectivity... done.

Généralités

On retrouve ici des sujets qui concernent globalement l'architecture ESP32.

RTC memory

On peut vouloir garder un contexte entre deux redémarrage de l'ESP32. Dans ce cas on peut utiliser la mémoire flash mais celle ci à un nombre de cycle d'écriture maximum avant de... mourir. Le nombre cycle max est variable en fonction des circuits mais est de l'ordre de 100 000.

Cela parait beaucoup mais imaginons que l'on crée un système qui, pour économiser de la batterie, se réveille toute les 10 min avant de se rendormir. Alors on "tue" la mémoire flash en... 277 heures soit 11 jours. C'est donc impossible.

Il existe un moyen simple c'est le concept de RTC memory. (Pas grand chose à voir avec le concept de "real time clock" mais passons.) Pour cela pas besoin de librairie ou d'includes spéciaux... il suffit de déclarer la variable avec le préfixe : RTC_DATA_ATTR.

RTC_DATA_ATTR int bootCount=0;

Après un reset HARD ou SOFT la valeur de bootCount est remise à zéro mais après un "deep sleep" non.

Le petit exemple ci dessous aide à comprendre

  1. #include <rom/rtc.h>
  2.  
  3. RTC_DATA_ATTR int rtcBootCount = 0;
  4. int bootCount=0;
  5.  
  6. void setup(){
  7.   Serial.begin(115200);
  8.   delay(500);
  9.   Serial.printf("\n\n%d\n%d  %d\n",rtc_get_reset_reason(0),rtcBootCount,bootCount);
  10.   bootCount = bootCount+1;
  11.   rtcBootCount = rtcBootCount+1;  
  12.   delay(3000);
  13.  
  14.   //ESP.restart();
  15.   //abort();
  16.   esp_sleep_enable_timer_wakeup(0); 
  17.   esp_deep_sleep_start();
  18. }
  19.  
  20. void loop(){
  21. }

Tels quel on voit bien que la valeur de bootCount est remise à zéro a chaque boot alors que rtcBootCount continue à être incrémenté. (les lignes 16 et 17 sont un deep sleep de.. zéro micro secondes)

En revanche un reset HARD ou les deux valeurs restent a zéro. De même si on fait une Soft reset (Ligne 14) ou un abort (ligne 15)

Exemples

Sur le port série si on se connecte en 115200 N,8,1 on voit le message de boot :

ets Jun  8 2016 00:22:57
 
rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
flash read err, 1000
Falling back to built-in command interpreter.
OK
>ets Jun  8 2016 00:22:57
 
rst:0x10 (RTCWDT_RTC_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0x00
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3ffc0000,len:0
load:0x3ffc0000,len:2304
load:0x40078000,len:3788
ho 0 tail 12 room 4
load:0x40098000,len:532
entry 0x4009813c
 
 
**************************************
*       hello espressif ESP32!       *
*        2nd boot is running!        *
*            version (V0.1)          *
**************************************
compile time 18:16:58
 
  SPI Speed      : 40MHz
  SPI Mode       : DIO
  SPI Flash Size : 4MB
Partition Table:
## Label            Usage          Type ST Offset   Length
 0 factory          factory app      00 00 00010000 00100000
 1 rfdata           RF data          01 01 00110000 00040000
 2 wifidata         WiFi data        01 02 00150000 00040000
End of partition table
Loading app partition at offset 00010000
section 0: paddr=0x00000020 vaddr=0x00000000 size=0x0ffe8 ( 65512)
section 1: paddr=0x00010010 vaddr=0x3f400010 size=0x05b64 ( 23396) map
section 2: paddr=0x00015b7c vaddr=0x3ffba720 size=0x01378 (  4984) load
section 3: paddr=0x00016efc vaddr=0x40080000 size=0x00400 (  1024) load
section 4: paddr=0x00017304 vaddr=0x40080400 size=0x126ac ( 75436) load
section 5: paddr=0x000299b8 vaddr=0x00000000 size=0x06658 ( 26200)
section 6: paddr=0x00030018 vaddr=0x400d0018 size=0x325b4 (206260) map
start: 0x400807ac
 
Initializing heap allocator:
Region 19: 3FFBBA98 len 00024568 tag 0
Region 25: 3FFE8000 len 00018000 tag 1
Pro cpu up.
Pro cpu start user code
nvs_flash_init
frc2_timer_task_hdl:3ffbc564, prio:22, stack:2048
tcpip_task_hdlxxx : 3ffbeca8, prio:20,stack:2048
phy_version: 80, Aug 26 2016, 13:04:06, 0
pp_task_hdl : 3ffc34f0, prio:23, stack:8192
 
:>enter uart init
uart init wait fifo succeed
exit uart init
 
IDF version : master(db93bceb)
 
WIFI LIB version : master(934d079b)
 
ssc version : master(r283 4d376412)
 
!!!ready!!!
mode : softAP(32:ae:a4:80:9e:78)
dhcp server start:(ip: 192.168.4.1, mask: 255.255.255.0, gw: 192.168.4.1)
 
+WIFI:AP_START

Ok la connexion est parfaite.

Carte Standard DOIT MCU

ESP32 DoIt
Generic ESP32 WROOM32 breakout

On la trouve partout sur Amazon, ligntinthebox, aliexpress,...

C'est un ESP WROOM32 avec :

  • Un adaptateur UART USB
  • Deux boutons (RESET et GMIO0)
  • Une LED sur le port GPIO 02 (rouge ou bleu selon les modèles) active au niveau Arduino HIGH.
  • Une LES POWER (rouge)

Merci à http://wiki.jelectronique.com/doku.php?id=esp32 pour l'image.

Carte Adafruit HUZZAH32 - ESP32 Feather

Dans l'IDE on a directement la carte ESP32 Feather donc tout va bien.

Référence chez le fabricant

Tant que tout n'est pas décrit ici... on se réfère à : https://learn.adafruit.com/adafruit-huzzah32-esp32-feather

Port I2C

Normalement le port I2C sur ESP 32 c'est GPIO 21 et GPIO 22. Sur notre breakout ils sont bêtement marqués SDA SCL sans précisions et c'est en fait :

SSD1306  display(0x3c,23,22);

Pourquoi... mystère.

Lecture de la charge batterie

Les données sont imparfaites sur internet. Je suis reparti de la base: Le shéma du Adafuit ESP32 HUZZAH feather. https://github.com/adafruit/Adafruit-HUZZAH32-ESP32-Feather-PCB

On y voit que le "pont diviseur" entre VBAT et l'entrée analogique A13 "sacrifiée" à la tâche de mesure de la tension batterie est constitué de deux résistances de 100K.

AdafruitESP30 pontdiv.png

D'autre part dans le datasheet ESP32 on voit que l'ADC est sur 12 bits (0--4095) avec une "full range" à Vcc soitenviron 3.2V (3.29 dans mon cas)

Donc :

  • La tension mesurée est V bat / 2
  • Le tout avec 0=0v et 4095=Vcc (3.2V)

Donc de facon générique l'entrée analogique est convertie en Volts par

U=analogRead/(4096/Vcc)

Donc pour VBAT sur A13

Vbat=2*analogRead/(4096/Vcc)

L'exemple ci-dessous affiche la tension sur un écran OLED car si on passe sur le port série... on peut pas débrancher le cable USB pour tester l'alim sur Batterie.

#include <Wire.h>  // Only needed for Arduino 1.6.5 and earlier
#include "SSD1306.h" // alias for `#include "SSD1306Wire.h"`
 
#define RATIO 2
SSD1306  display(0x3c,23,22);
 
const int analogInPin = A13;  
int sensorValue = 0;       
void setup() {
 Serial.begin(115200);
  Serial.println();
  Serial.println("ready");
  // Initialising the UI will init the display too.
  display.init();
  display.flipScreenVertically();
}
 
void loop() {
  sensorValue = analogRead(analogInPin);
  Serial.println(sensorValue);
  display.clear();
  display.setFont(ArialMT_Plain_10);
  display.drawString(0, 0, String(sensorValue));
  display.setFont(ArialMT_Plain_16); display.drawString(0,16, String(sensorValue/(4096.0/3.29)));  display.setFont(ArialMT_Plain_10);  display.drawString(50,16+4, "V  (input A13)");
  display.setFont(ArialMT_Plain_16); display.drawString(0,32, String(RATIO*sensorValue/(4096.0/3.29)));  display.setFont(ArialMT_Plain_10);   display.drawString(50,32+4, "V  (vbat)");
  display.display();  
  delay(1000);
}

20180221 152124.jpg

Bon mon voltmètre dit 4.10 V (pour 3.75 affiché... bof). On peut cependant l'utiliser pour dire : "IL EST TEMPS DE RECHARGER LA BATTERIE" ou pour afficher une jauge analogique a 4 barrettes du styles de celles sur les téléphones.

Un article détailles ces problèmes sur : https://www.esp32.com/viewtopic.php?t=1045

Avec le SDK de NATIF on peut jouer sur l'atténuation en lecture. Il faudrait faire des essais.

Carte Wemos ESP32 OLED

C'est une carte ESP32 qui n'est pas très chère (8-9€) et qui comporte un écran OLED I2C !!!

Dès que vous la branchez ça vous donne un bel affichage de démo! Ne paniquons pas avec les premiers essais "moches" qui vont suivre on peut facilement remettre la belle démo.

Arduino IDE

Dans l'IDE Arduino on choisit la carte :

WEMOS LOLIN32

Et zou ça marche!

Ecran OLED I2C

On peut utiliser les sketchs que j'ai déjà donnés pour la carte Adafruit HUZZAH Esp8266_huzzah#I2C

En revanche les "pins" par défaut de la librairie Wire ne sont pas les bonnes donc il faut, à la place de :

 Wire.begin();

Mais plutôt :

 Wire.begin(5,4);

Et la sortie du sketch nous donne :

I2C Scanner 

Scanning...
Appareil I2C trouve a cette adresse 0x3C  !
Fin

Scanning...
Appareil I2C trouve a cette adresse 0x3C  !
Fin

C'est le même écran OLED que celui utilisé dans mon exemple pour HUZZAH :

En revanche la librairie Adafruit ne marche pas avec l'ESP32. Il faut télécharger : https://github.com/squix78/esp8266-oled-ssd1306

Dans les exemples on à une entré ESP32 et 8266 OLED... qui contient un exemple : Simple Demo.

Ouvrez le et corrigez :

SSD1306  display(0x3c, D3, D5);

par :

SSD1306  display(0x3c, 5,4);

Et on retrouve notre belle démo du début!


On peur jouer avec l'écran (il y a d'autres exemples n'oubliez pas de changer les pins à chaque coup). Pour le reste c'est une carte comme les autres.

Carte Wemos 18650

Encore une carte spécifique. Elle comporte un chargeur et un support pour une batterie 18650 de 3000 mAh.

Elle marche bien à une exception près : Branchée sur le port USB standard avec la batterie on a des brownout (reset pour cause d'alim trop faible) a chaque allumage du wifi.

Ca marche dans les cas suivants :

  • Branchée sur le PC et avec la batterie mais WIFI éteint
  • Wifi en marche, branchée sur le PC mais sans la batterie
  • Wifi ON batterie branchée mais pas branchée sur le PC

Donc ça reste utilisable mais un peu difficile pour la mise au point avec la batterie....

Brochage

La sérigraphie est assez difficile à lire donc voici le pinout:

Diwmore-bat-pinout.jpg

  • La led bleu est sur la sortie GPIO16

Specificités / Arduino

Les ESP32 ne se programme pas toujours comme un Arduino. Certaines différences sont données ci-dessous.

base64

Attention sur l'SP32 il y a une bibliotheque pour encoder un texte en base64.

#include <Base64.h>

Ne donne pas acces à la lib Arduino habituelle mais à un objet qui ne gère qu'une chose : l'encodage base64.

  String s=b.encode("texte a encoder");

C'est simple et efficace!

En revanche ça doit être fait pour créer des certificats en base64 parce que ça insère un "line feed" (0x0A).

Pour une chaîne ne comportant qu'un saut de ligne :

int pos=s.charAt(10);
s.remove(pos-1,1);

Si il y en a plus d'un il faudra... faire une boucle. Bon exercice, allez-y je relève les copies dans 5 min.