Iniziamo, con il tutorial di oggi, ad utilizzare i pin di I/O del chip esp32. Il chip mette a disposizione 40 General Purpose I/O pads (GPIO), ovvero 40 “contatti” che possono essere utilizzati per diverse funzionalità di ingresso (input) e uscita (output).
La gestione di tali pads è abbastanza complessa: il chip esp32 consente infatti di “mappare” le diverse periferiche interne (UART, SPI…) sui vari pad tramite matrici configurabili via software. All’interno del technical reference manual è presente un diagramma che illustra questo meccanismo:
In questo primo articolo non andrò ad illustrarvi tutti i diversi registri e configurazioni… è importante però tenere presente sin da subito che per utilizzare un pin, anche solo con funzioni di I/O base, è necessaria una configurazione iniziale. Il driver del framework da includere nel proprio codice per avere a disposizione tutte le funzioni descritte di seguito è:
#include "driver/gpio.h" |
Funzionalità I/O base
Come detto, prima di poter utilizzare un pin è necessario impostare i vari registri che ne configurano i collegamenti interni. Dopo il reset del chip, molti pin sono automaticamente configurati per funzionalità di I/O base. Possiamo assicurarci che il pin scelto sia configurato per funzionalità di I/O con la funzione:
void gpio_pad_select_gpio(uint8_t gpio_num); |
Nel funzionamento come pin di I/O, i pin del chip esp32 possono essere configurati in 3 direzioni:
- input
- output
- open drain
Le relative costanti sono definite nel file gpio.h:
Vi sono alcune eccezioni, in particolare i pins > 33 possono essere utilizzati solo come input.
E’ possibile configurare la direzione di un pin con la funzione:
esp_err_t gpio_set_direction(gpio_num_t gpio_num, gpio_mode_t mode); |
gpio_num indica il pin da configurare, mentre mode è una delle tre modalità descritte sopra. Per configurare ad esempio il pin 13 come output, il comando da utilizzare sarà:
gpio_set_direction(GPIO_NUM_13, GPIO_MODE_DEF_OUTPUT); |
Possiamo leggere lo stato del pin, se configurato come input, con la funzione:
int gpio_get_level(gpio_num_t gpio_num); |
mentre se il pin è configurato come output o open drain, possiamo cambiarne lo stato con:
esp_err_t gpio_set_level(gpio_num_t gpio_num, uint32_t level); |
Pull-up e pull-down
Ogni pin è anche dotato di resistenze di pull-up e pull-down, attivabili tramite la funzione:
esp_err_t gpio_set_pull_mode(gpio_num_t gpio_num, gpio_pull_mode_t pull); |
le costanti possibili sono:
In alternativa esistono funzioni per abilitare/disabilitare le resistenze su ogni pin:
esp_err_t gpio_pullup_en(gpio_num_t gpio_num); esp_err_t gpio_pullup_dis(gpio_num_t gpio_num); esp_err_t gpio_pulldown_en(gpio_num_t gpio_num); esp_err_t gpio_pulldown_dis(gpio_num_t gpio_num); |
Configurazioni multiple
Finora abbiamo visto come configurare singolarmente i vari pin. Esiste la possibilità di configurare simultaneamente più pin, applicando a tutti la medesima configurazione.
Per prima cosa va definita una struct di tipo gpio_config_t:
gpio_config_t pin_config; |
I parametri configurabili sono:
I pin oggetto della configurazione multipla vengono inseriti nella variabile pin_bit_mask concatenando le costanti GPIO_SEL_x con l’operatore OR (|). Vediamo un paio di esempi (degli interrupt parlerò più diffusamente in un prossimo post, per ora saranno disabilitati):
[checklist]
- pin 2, 3 e 7 configurati come output, pull-up e down disabilitati:
[/checklist]
pin_config.pin_bit_mask = GPIO_SEL_2 | GPIO_SEL_3 | GPIO_SEL_7; pin_config.mode = GPIO_MODE_OUTPUT; pin_config.pull_up_en = GPIO_PULLUP_DISABLE; pin_config.pull_down_en = GPIO_PULLDOWN_DISABLE; pin_config.intr_type = GPIO_PIN_INTR_DISABLE; |
[checklist]
- pin 6 e 8 configurati come input con resistenza di pull-up abilitata:
[/checklist]
pin_config.pin_bit_mask = GPIO_SEL_6 | GPIO_SEL_8; pin_config.mode = GPIO_MODE_INPUT; pin_config.pull_up_en = GPIO_PULLUP_ENABLE; pin_config.pull_down_en = GPIO_PULLDOWN_DISABLE; pin_config.intr_type = GPIO_PIN_INTR_DISABLE; |
La configurazione viene infine applicata con la funzione gpio_config(&pin_config).
Codice
Visti i concetti base affrontati in questo tutorial, non ho preparato dei programmi dedicati… insieme al framework sono infatti distribuiti due esempi che illustrano quanto spiegato:
Hi Luca
I have read most of your web-site with interest. I wish I had found it 4 weeks ago while trying to set up Eclipse!
Excellent tutorials!
Would it be possible for you to explain how to send a data packet from a PC to the ESP32 on the same wireless home network (not accessing the external web)?
My goal is to send a simple graphic (much like your LED matrix project) to the ESP32 and use the I/O (SPI) to control some LEDs.
Would it require the ESP32 to have a fixed IP address or could the network be scanned to get the automatically assigned IP address?
Many thanks in advance.
Hi Karl, thanks for your comment! I’m working on a tutorial for using ESP32 as a server and… something also to solve the problem to “find” the ESP32 on the network 😉
Grazie per l’interessante articolo se volessi configurare come open drain utilizzando ide di Arduino come potrei farlo?
Grazie
Salve Andrea, i miei tutorial non sono per arduino, mi spiace
hello
In the Blink example how do I
Can run ‘make menuconfig’ to choose the GPIO to blink,
I cant see Any Settings in MenuConfig where I can set GPIO
in the “Example Configuration” menu… see the readme as this is an official example by Espressif