RIOT propose une abstraction simple pour utiliser les convertisseurs analogiques numériques (CAN ou ADC) intégrés dans la plupart des MCU: le pilote ADC (periph/adc). Cette interface de périphérique est construite autour du concept de lignes (ADC LINES).
Pour pouvoir lire (échantillonner) une valeur, il faut au préalable initialiser la bonne ligne ADC, pour cela on précise le numéro de ligne que l'on souhaite utiliser:
#include "periph/adc.h" //Pour l'ESP32 la GPIO33 correspond à la ligne ADC 11 #define ADC_GPIO33 ADC_LINE(11) ... if(adc_init(ADC_GPIO33) < 0 ) { printf("Echec initalisation de l'entree ADC n° %u \n\r", ADC_GPIO33); } else { printf("Ligne n° %u active\n\r", ADC_GPIO33); }
Pour garantir au maximum la portabilité, il n'y a pas de relation directe entre les GPIOs et les lignes ADC, c'est la principale difficulté à l'utilisation de cette interface.
Pour déterminer quel GPIO correspond à quelle ligne, il faut consulter directement le code source. Les GPIO liées aux convertisseurs analogiques numériques pour les cartes de type ESP32-DEVKIT, NodeMCU-ESP32 et leurs clones sont déclarées dans le fichier RIOT-OS/boards/esp32-wroom-32/include/periph_conf.h
#ifndef ADC_GPIOS #define ADC_GPIOS { GPIO0 , GPIO2 , GPIO4 , GPIO12, GPIO13, GPIO14, \ GPIO15, GPIO25, GPIO26, GPIO27, GPIO32, GPIO33, \ GPIO34, GPIO35, GPIO36, GPIO39 } #endif
Le fichier utilise cette déclaration pour initialiser le tableau des lignes ADC disponibles dans le fichier RIOT-OS/boards/common/esp32/include/periph_conf_common.h:
static const gpio_t adc_channels[] = ADC_GPIOS; ... #define ADC_NUMOF ARRAY_SIZE(adc_channels)
Pour initialiser la bonne ligne, il faut déterminer l'index de la GPIO utilisée par le montage dans le tableau adc_channels[] qui correspond à la constante préprocesseur ADC_GPIOS:
Par exemple si le montage utilise la GPIO12, cette GPIO est le 4ième élément du tableau, son index est 3
On branche un potentiomètre sur le GPIO33 du d'une carte de type ESP32-DEVKIT. On cherche ici à afficher régulièrement sa valeur sur le port série.
Note: Note that the call to adc_init is needed for the reads to work. I remeber that the ESP8266 had a 1.0 V reference, maybe this is also the case here?
Déclarer l'utilisation de la fonctionnalité periph_adc dans le Makefile
# a minimal application Makefile APPLICATION = hello_adc BOARD ?= esp32-wroom-32 PORT ?= /dev/ttyUSB0 RIOTBASE ?= $(CURDIR)/../RIOT-OS FEATURES_REQUIRED += periph_timer FEATURES_REQUIRED += periph_adc # Pour une application simple n'utilisant pas les IPCs # le module core_msg peut être désactivé pour optimiser # l'occupation mémoire. # DISABLE_MODULE += core_msg USEMODULE += xtimer # Le module suivant est chargé seulement pour la cible ESP32 ifeq ($BOARD, es32-wroom-32) USEMODULE += esp_log_startup endif include $(RIOTBASE)/Makefile.include
#include <stdio.h> #include "xtimer.h" #include "periph/adc.h" #define RES ADC_RES_10BIT #define ADC_GPIO33 ADC_LINE(11) int main(void) { int sample = 0; printf("%u lignes detectees. \n\r", ADC_NUMOF); //initialisation de l'entrée ADC if(adc_init(ADC_GPIO33) < 0 ) { printf("Echec initalisation de l'entree ADC n° %u \n\r", ADC_GPIO33); } else { printf("Ligne n° %u active\n\r", ADC_GPIO33); } while(1) { //lecture du CAN sample = adc_sample(ADC_GPIO33, RES); if (sample < 0) { printf("Resolution %u invalide pour la ligne %u \n\r", RES, ADC_GPIO33); } else { printf("ADC LINE (%u): %i\n\r", ADC_GPIO33, sample); } xtimer_sleep(2); } return 0; }
Une fois le code compilé et flashé, on pourra lire sur le port série via un programme comme minicom.