Fyzikální kabinet FyzKAB

Články Moduly ESP32 a ESP32-CAM ESP32 – Jak používat GPIO piny?

ESP32 – Jak používat GPIO piny?

Přestože jsme v předchozím článku psali, že modul ESP32 je pro pokročilé vývojáře, zkusíme dnešní text zaměřit právě na ty začínající. Přišlo nám totiž poněkud „unfair“ zacílit na lidi, kteří již něco v IoT mají za sebou a případné začínající zájemce o danou problematiku tak okamžitě „hodit přes palubu“. Dnešní článek tedy bude základním seznámením s možnostmi modulu ESP32 z hlediska používání a zapojení pinů, které by mělo pomoci právě těm, co chtějí s ESP32 začít. Pro zkušenější vývojáře, kteří třeba mají jistě zkušenosti s modulem Arduino, sem zkusíme propašovat pár informací, které se nám podařilo k modulu ESP32 zjistit a které snad ocení i tito zkušenější.

Nejdříve se podíváme, co od modulu ESP32 můžeme očekávat. Začneme popisem vstupů a výstupů, které nám modul poskytuje. Především to jsou:


Funkce ADC (analogově digitální převodník) a DAC (převodník digitálního signálu na analogový) jsou přiřazeny konkrétním statickým pinům (viz dále). Naopak se můžeme rozhodnout, které GPIO piny budou UART, I2C, SPI, PWM atd. – stačí to definovat v kódu. Ačkoli můžete ve svém programu definovat vlastnosti některých pinů, ve výchozím nastavení jsou piny standardně přiřazeny. Následující obrázek to ukazuje pro desku ESP32 DEVKIT V1 DOIT ve verzi s 36 piny. Umístění pinů se může měnit v závislosti na výrobci dané desky, vždy si najděte správný „pinout“ (rozložení pinů) pro Vaši desku ESP32. POZOR, k zakoupení jsou i desky, které mají na sobě natištěné špatné popisky, pak je třeba se řídit popisem vývodů staženým z internetu. (ale to jsou snad jen výjimky!)

ESP32 - pinout
zdroj obrázku: https://randomnerdtutorials.com/esp32-pinout-reference-gpios/

Kromě toho existují kolíky se specifickými funkcemi, které jsou vhodné nebo nevhodné pro konkrétní projekt. Existují piny (např. GPIO 6–11), na které je třeba dávat pozor.

Následující tabulka ukazuje jednotlivé vývody, které jsou okomentovány. Zeleně zvýrazněné piny lze libovolně použít. Ty, které jsou zvýrazněny žlutě, lze použít, ale je t5eba jim věnovat pozornost, protože mohou mít neočekávané chování hlavně při spouštění modulu ESP32. Piny zvýrazněné červeně se nedoporučují používat (buď jako vstupy nebo výstupy, dle červeného označení).

 GPIO pin   vstup   výstup   Poznámka 
0 pulled up OK Vstup držen přes rezistor na úrovni HIGH
Výstup při spouštění vydává signál PWM
1 TX pin OK výstup ladění při spouštění
2 OK OK připojeno k integrované LED
3 OK RX pin úroveň HIGH při spouštění
4 OK OK  
5 OK OK při spouštění vydává PWM signál
6 --- --- připojeno k integrované paměti SPI flash
7 --- --- připojeno k integrované paměti SPI flash
8 --- --- připojeno k integrované paměti SPI flash
9 --- --- připojeno k integrované paměti SPI flash
10 --- --- připojeno k integrované paměti SPI flash
11 --- --- připojeno k integrované paměti SPI flash
12 OK OK spouštění selže, pokud je na vstupu úroveň HIGH
13 OK OK  
14 OK OK při spouštění vydává PWM signál
15 OK OK při spouštění vydává PWM signál
16 OK OK  
17 OK OK  
18 OK OK  
19 OK OK  
21 OK OK  
22 OK OK  
23 OK OK  
25 OK OK  
26 OK OK  
27 OK OK  
32 OK OK  
33 OK OK  
34 OK --- pouze vstup
35 OK --- pouze vstup
36 OK --- pouze vstup
39 OK --- pouze vstup

 


Digitální vstupy a digitální výstupy

Téměř všechny piny modulu ESP32 (viz tabulka výše) lze použít jako digitální vstup nebo výstup. Jejich směr lze přepnout zavoláním funkce a to v libovolném okamžiku. To znamená, že jeden pin může jednu chvíli sloužit jako vstup a poté i jako výstup (možná vás teď nenapadá, k čemu by to bylo dobré, ale občas se to opravdu hodí). Jelikož se jedná o digitální piny, napětí na nich je modulem ESP32 interpretováno pomocí dvou logických hodnot – HIGH a LOW, neboli pravda a nepravda, často také logická jedna a nula. Moduly ESP32 pracují s pozitivní TTL logikou, kde logická jedna (HIGH) je reprezentována napětím blízkým napájecímu (3,3 V) a logická nula, (LOW), je napětí blízké 0 V. Tyto hodnoty lze na výstup nastavit, nebo je naopak na vstupu číst.


   Poznámka:
Maximální provozní (vstupní/výstupní) proud GPIO pinů je 40 mA (podle datového listu čipu ESP32). Doporučuje se však udržovat tento proud pod hranicí 20 mA.
 

Nastavení digitálního výstupu

Prvním krokem je pochopitelně volba režimu pro daný pin, tedy nejprve musíte nastavit GPIO pin, který chceme ovládat jako VÝSTUP. V prostředí Arduino IDE, konkrétně v jazyce „Wiring“, použijeme příkaz pinMode(), který má dva vstupní parametry – číslo GPIO pinu a klíčové slovo OUTPUT.

Například příkaz: pinMode(2, OUTPUT) nastaví GPIO pin číslo 2 do režimu výstupu.

Pokud chceme na tento výstupní GPIO pin odeslat jeden ze dvou možných stavů (HIGH/LOW), použijeme příkaz digitalWrite().

Například takto:
digitalWrite(2, LOW);
digitalWrite(2, HIGH);

Výrazy HIGH a LOW lze též nastavit čísly 1 a 0, ale zpravidla se využívají tyto v prostředí Arduino IDE předdefinované konstanty HIGH a LOW.

Ukázka – blikání LED:

Využijeme-li informace (viz předchozí tabulka pinů), že k pinu GPIO 2 je na desce ESP32 připojena vestavěná LED, můžeme naši desku ESP32 rozblikat. K tomu nám poslouží následující kód:

/* BLIKANI */

// funkce SETUP se spusti jednou pri stisknuti tlacitka reset nebo pri zapnuti desky.
void setup() {
  pinMode(2, OUTPUT);   // nastavi GPIO2 pin jako vystup.
}

// funkce LOOP bezi stale dokola.
void loop() {
  digitalWrite(ledPin, HIGH);   // rozsviti LED diodu (HIGH = napeti 3,3 V na pinu)
  delay(1000);   // cekani jednu vterinu
  digitalWrite(ledPin, LOW);   // zhasnuti LED diody (LOW = napeti 0 V na pinu)
  delay(1000);   // cekani jednu vterinu
}


Po spuštění kódu by na desce ESP32 měla blikat malá modrá LED (na některých deskách červená).

ESP32 interni LED - blikani

 

Čtení digitálního vstupu

Obdobně předchozímu můžeme digitální informaci též načítat. Příkladem nám může být test stisknutého tlačítka, přerušení světelné závory  apod. I nyní musíme nejdříve nastavit daný GPIO pin do požadovaného stavu, tedy do stavu VSTUP. To opět učiníme příkazem pinMode(). Při nastavení digitálního vstupu jsou však k dispozici 3 režimy:

  1. INPUT – vstup detekuje takovou hodnotu, která je na příslušný pin připojena. Jinými slovy, logická úroveň na nezapojeném vstupu není definována. Pokud chceme pomocí tohoto režimu načítat stav tlačítka, musíme při daných stavech (stisknuto/nestisknuto) vyřešit napětí na vstupu. Ukážeme si to v následujícím příkladu.
  2. INPUT_PULLUP – vstup je „držen“ na hodnotě 3,3 V pomocí vnitřního pull-up rezistoru modulu ESP32. Není-li na vstupu nic připojeno, je vstup nastaven na úrovni HIGH, při přivedení úrovně LOW na vstup, je detekována hodnota LOW. Zároveň vnitřní pull-up rezistor zabraňuje zkratu, ke kterému by jinak při přímém setkání úrovní HIGH a LOW došlo.
  3. INPUT_PULLDOWN – podobně jako u předchozího nastavení, je úroveň vstupy fixována na některou z úrovní, zde je vstup „stažena“ na úroveň LOW (pomocí vnitřního tzv. pull-down rezistoru). Nezapojený vstup je detekován jako LOW, při připojení úrovně HIGH má vstup úroveň HIGH (zkrat opět nehrozí)

Poznámka:
Z technické dokumentace modulu ESP32 plyne, že vnitřní pull-up a pull-down rezistor má hodnotu 45 kΩ.

Příklad nastavení GPIO pinu 4 jako digitálního vstupu: pinMode(4, INPUT);

Chceme-li přečíst digitální vstup, kupříkladu do proměnné uložit stav tlačítka, použijeme funkci digitalRead(), která má jako argument číslo GPIO pinu, na který se dotazujeme, např.:

promenna = digitalRead(4);

Opět je dobré se podívat do tabulky pinů, které piny lze pro vstup bez problémů využít!

Ukázka – rozsvěcení LED tlačítkem:

Abychom si ukázali, jak používat digitální vstupy a digitální výstupy, vytvoříme jednoduchý příklad projektu s tlačítkem a externí LED. Princip celého příkladu bude jednoduchý – načteme stav tlačítka a dle tohoto stavu rozsvítíme LED, jak je znázorněno na následujícím obrázku.

tlacitko - LED

Na nepájivém poli sestavíme následující obvod (viz schéma). Tlačítko připojíme na GPIO pin 4, který přes externí pull-down rezistor (asi 10 kΩ) spojíme se zemí (GND). LED připojíme přes rezistor (150–330 Ω) mezi zem a pin 5. GPIO pin 5 bude při rozsvícení LED schopen dodat dostatek energie pro napájení LED, na druhou stranu piny GPIO nelze obdobným způsobem použít například k napájení motoru! (Vzpomeňme na zmíněnou proudovou podmínku, dle které každý výstup může dodávat proud maximálně 40 mA)

tlacitko + LED - schema
zdroj obrázku: https://randomnerdtutorials.com/esp32-digital-inputs-outputs-arduino/

Zkopírujme následující kód do prostředí Arduino IDE. Princip kódu najdete v komentářích

/* TEST TLACITKA */

const int buttonPin = 4;   // nastaveni pinu pro tlacitko
const int ledPin = 5;   // nastaveni pinu pro LED
int buttonState = 0;  // promenna pro ulozeni stavu tlačítka

// funkce SETUP se spusti jednou pri stisknuti tlacitka reset nebo pri zapnuti desky.
void setup() {
  pinMode(buttonPin, INPUT);   // nastaveni pinu tlačítka do rezimu INPUT
  pinMode(ledPin, OUTPUT);   // nastaveni pinu LED do rezimu OUTPUT
}

// funkce LOOP bezi stale dokola.
void loop() {
  buttonState = digitalRead(buttonPin);   // nacteni stavu tlacitka
  if (buttonState == HIGH) {   // pokud je tlacitko stisknuto, je pushbutton HIGH
    digitalWrite(ledPin, HIGH);   // nastav na vystup HIGH - rozsvit LED
  } else {
    digitalWrite(ledPin, LOW);   // jinak nastav na vystup LOW - zhasni LED
  }
}


Po nahrání kódu otestujeme svůj obvod. LED by se měla rozsvítit po stisknutí tlačítka, zhasnout po jeho uvolnění:

tlacitko + LED - foto 1     tlacitko + LED - foto 2
zdroj obrázku: https://randomnerdtutorials.com/esp32-digital-inputs-outputs-arduino/

Poznámka:
Pokud bychom v předešlém kódu (první řádek v proceduře SETUP) změnili nastavení pinu buttonPin na režim INPUT_PULLDOWN, došlo by ke spojení pinu GPIO 4 proti zemi interním rezistorem modulu ESP32. Mohli bychom tedy z našeho zapojení externí rezistor připojený nyní k tlačítku zcela vynechat. Takže jediná změna této řádky na podobu:

pinMode(buttonPin, INPUT_PULLDOWN);   // nastaveni pinu tlačítka do rezimu INPUT_PULLDOWN

dokáže zachovat funkčnost celého zapojení i při zjednodušení elektronické části.

 


Výstupy PWM

PWM (tedy „pulzně šířková modulace“) výstup je jakýmsi přechodem mezi digitálním a analogovým výstupem. Jde o cyklické přepínání výstupu mezi stavy LOW a HIGH. Podle toho, jaká je „šířka“ zapnutého stavu (HIGH) ku šířce vypnutému stavu (LOW) dochází k výslednému stavu na daném výstupu. I když se tedy jedná o digitální výstup, kdy na výstupu jsou stavy LOW a HIGH, ve svém důsledku se výstup chová, jakoby se na něm měnilo napětí analogově. Všechny piny modulu ESP32, které mohou fungovat jako výstupy, lze použít i jako piny PWM.

PWM - diagram

Ukážeme si, jak generovat PWM signály na výstupech modulu ESP32 (pomocí programu v prostředí Arduino IDE). Vytvoříme jednoduchý obvod, který bude regulovat svit LED. Modul ESP32 má PWM řadič se 16 nezávislými kanály (0-15), které lze konfigurovat pro generování PWM signálů s různými vlastnostmi, takže pak zkusíme i regulovat svit několika LED na sobě nezávisle.

Ukázka – regulace svitu LED pomocí PWM:

Pro začátek si na nepájivém poli vytvoříme následující obvod, ve kterém připojíme LED přes ochranný rezistor (cca 150–330 Ω) mezi pin GPIO16 a zem (pin GND).

PWM - schema
zdroj obrázku: https://randomnerdtutorials.com/esp32-pwm-arduino-ide/

Při programování PWM výstupu musíme nejdříve zvolit kanál PWM (0–15), poté musíte nastavit frekvenci generovaného signálu PWM. Pro LED je vhodné použít frekvenci 5 000 Hz. Musíte také nastavit rozlišení výstupního pracovního cyklu signálu. Tedy na kolik dílů lze rozdělit interval mezi zcela vypnutým („0% duty cycle“) a zcela zapnutým stavem („100% duty cycle“). Nastavit můžeme rozlišení od 1 do 16 bitů. Pro náš příklad použijeme 8-bitové rozlišení, což znamená, že jas LED můžete ovládat pomocí hodnoty od 0 do 255. Pro generování různých signálů PWM můžete zvolit jiné vlastnosti, než jsou tyto.

Na závěr pracovního nastavení PWM kanálu musíme určit, na kterém GPIO pinu se bude signál generovat. K tomu použijete následující funkci:

ledcAttachPin(GPIO, channel)

Tato funkce přijímá dva argumenty. První je číslo GPIO pinu, na kterém bude PWM signál. Druhý argument je číslo kanálu, který bude daný PWM signál generovat.

Pro ovládání jasu LED pomocí PWM použijete následující funkci, kde argument „channel“ určuje PWM kanál a argument „dutycycle“ udává aktuálně nastavený poměr PWM signálu:

ledcWrite(channel, dutycycle)

Zkopírujte následující kód do svého Arduino IDE. Princip kódu najdete v komentářích:

/* TEST PWM */

const int ledPin1 = 16;   // nastaveni GPIO 16 pro PWM vystup
// definice PWM vlastnosti
const int freq = 5000;   // frekvence 5000 Hz
const int ledChannel = 0;   // cislo kanalu
const int resolution = 8;   // 8-bitove rozliseni (0-255)

// funkce SETUP se spusti jednou pri stisknuti tlacitka reset nebo pri zapnuti desky.
void setup() {
  ledcSetup(ledChannel, freq, resolution);   // nastaveni LED PWM funkcionality
  ledcAttachPin(ledPin1, ledChannel);   // pripojeni kanalu k ovladanemu GPIO
}

// funkce LOOP bezi stale dokola.
void loop() {
  for(int dutyCycle = 0; dutyCycle <= 255; dutyCycle++) {   // zvysovani svitu LED
    ledcWrite(ledChannel, dutyCycle);   // zmena svitu LED pomoci PWM
    delay(15);   // nech LED PWM sviti 15 ms, pak se zvys dutyCycle
  }

  for(int dutyCycle = 255; dutyCycle >= 0; dutyCycle--) {   // snizovani svitu LED
    ledcWrite(ledChannel, dutyCycle);   // změna svitu LED pomoci PWM
    delay(15);   // nech LED PWM sviti 15 ms, pak se zvys dutyCycle
  }
}


Nahrajte kód do svého ESP32. Ujistěte se, že máte vybranou správnou desku a port COM. Podívejte se na svůj obvod. Měli byste vidět stmívající se a postupně se rozsvěcující LED.

PWM - foto 1

 

Nastavení stejného PWM signálu na různé GPIO

Můžeme získat PWM signál ze stejného kanálu na několika různých GPIO pinech. Abychom toho dosáhli, stačí asociovat tyto GPIO piny se stejným kanálem. Pro ukázku si upravíme předchozí příklad tak, abychom regulovali 3 různé LED diody pomocí stejného signálu PWM (ze stejného kanálu).

Přidejte do předchozího obvodu další dvě LED diody podle následujícího schématu:

PWM - 3 LED - schema
zdroj obrázku: https://randomnerdtutorials.com/esp32-pwm-arduino-ide/

Předchozí kód upravme na následující kód (stačí přidat červené řádky):

/* TEST PWM - 3 LED */

const int ledPin1 = 16;   // nastaveni GPIO 16 pro PWM vystup
const int ledPin2 = 17;   // nastaveni GPIO 17 pro 2. PWM vystup
const int ledPin3 = 5;   // nastaveni GPIO 5 pro 3. PWM vystup
// definice PWM vlastnosti
const int freq = 5000;   // frekvence 5000 Hz
const int ledChannel = 0;   // cislo kanalu
const int resolution = 8;   // 8-bitove rozliseni (0-255)

// funkce SETUP se spusti jednou pri stisknuti tlacitka reset nebo pri zapnuti desky.
void setup() {
  ledcSetup(ledChannel, freq, resolution);   // nastaveni LED PWM funkcionality
  ledcAttachPin(ledPin1, ledChannel);   // pripojeni kanalu k ovladanemu GPIO
  ledcAttachPin(ledPin2, ledChannel);   // pripojeni kanalu k ovladanemu GPIO
  ledcAttachPin(ledPin3, ledChannel);   // pripojeni kanalu k ovladanemu GPIO
}

// funkce LOOP bezi stale dokola.
void loop() {
  for(int dutyCycle = 0; dutyCycle <= 255; dutyCycle++) {   // zvysovani svitu LED
    ledcWrite(ledChannel, dutyCycle);   // zmena svitu LED pomoci PWM
    delay(15);   // nech LED PWM sviti 15 ms, pak se zvys dutyCycle
  }

  for(int dutyCycle = 255; dutyCycle >= 0; dutyCycle--) {   // snizovani svitu LED
    ledcWrite(ledChannel, dutyCycle);   // změna svitu LED pomoci PWM
    delay(15);   // nech LED PWM sviti 15 ms, pak se zvys dutyCycle
  }
}


Tak co, byly to velké změny? Kupříkladu procedura LOOP se nezměnila vůbec!

Po nahrání kódu do obvodu ESP32 bychom měli vidět, jak všechny tři diody LED současně zvyšují a snižují jas.

PWM - 3 LED - foto
zdroj obrázku: https://randomnerdtutorials.com/esp32-pwm-arduino-ide/

 


Analogové vstupy (ADC)

čtení analogových vstupů pomocí ESP32 je stejně snadné jako načítání vstupů digitálních. Jediným rozdílem je to, že získaná hodnota nebude mít jen dvojici možných stavů LOW a HIGH, ale celou množinu možných čísel z daného rozsahu. Načtení analogové hodnoty pomocí modulu ESP32 tedy znamená, že můžete měřit různé úrovně napětí mezi 0 V a 3,3 V. Naměřené napětí je pak přiřazeno hodnotě mezi 0 a 4095, ve které 0 V odpovídá 0 a 3,3 V odpovídá maximální hodnotě, tedy 4095. Libovolné napětí mezi 0 V a 3,3 V dostane odpovídající hodnotu mezi nimi.

Pro načítání analogového signálu na vstupním pinu použijeme funkci analogRead(GPIO), která přijímá jako argument GPIO číslo pinu, který chcete načíst.

ADC je nelineární

V ideálním případě bychom při použití ADC pinů modulu ESP32 očekávali lineární chování. To se však bohužel neděje! Získáme trochu „podivné“ chování, jak ukazuje následující graf:

ESP32-ADC Linarity
zdroj obrázku: https://deepbluembedded.com/esp32-adc-tutorial-read-analog-voltage-arduino/

Toto chování znamená, že modul ESP32 není schopen rozlišit napětí přibližně od 3,2 V do 3,3 V. Při obou těchto napětích získáme stejnou hodnotu 4095. Něco podobného nastává i pro velmi nízké hodnoty napětí mezi 0 V a 0,1 V, to získáváme stále stejnou hodnotu: 0. Je dobré to mít toto při používání analogových pinů modulu ESP32 stále na paměti!

Poznámka:
Tento problém se různě řeší na elektronických fórech. Přístup je vesměs dvojí – buď to dané aplikaci zase tolik nevadí, nebo lze ve svém programu použít „korekční“ knihovnu, která načtená data trochu přepočítává s ohledem na skutečný tvar křivky. Příkladem takové knihovny pro korekci linearity je následující příspěvek na GITHUBu: https://github.com/e-tinkers/esp32-adc-calibrate

Čtení analogových vstupů

čtení analogového vstupu modulu ESP32 je pomocí funkce analogRead(GPIO). Funkce přijímá parametr GPIO, který odpovídá číslu pinu, který chceme načítat. Modul ESP32 podporuje načítání ADC na 18 různých kanálech. Na desce DEVKIT V1 DOIT (verze s 30 GPIO) je k dispozici pouze 15 kanálů.

Piny, které lze použít pro načítání analogového signálu jsou na následujícím obrázku označeny červeným okrajem. (Jak již bylo řečeno, tyto analogové vstupní piny mají 12bitové rozlišení. To znamená, že když čtete analogový vstup, jeho rozsah se může nabývat hodnotu od 0 do 4095)

ESP32 - ADC pins
zdroj obrázku: https://randomnerdtutorials.com/esp32-adc-analog-read-arduino-ide/


   Poznámka:
Piny značené v obrázku jako ADC2 nelze použít při současném požívání Wi-Fi. Pokud je tedy používáte s Wi-Fi a máte potíže se získáváním hodnot z ADC2 GPIO pinů, použijte místo toho piny GPIO označené ADC1, to by mělo váš problém vyřešit.
 

Další užitečné funkce pro ADC vstupy

S piny ADC lze použít i další a pokročilejší funkce, které mohou být užitečné v jiných projektech.

  • analogReadResolution(rozlišení) – nastavení počtu bitů určující rozlišení, například hodnota 9 určuje vstupní hodnoty 0–511, maximální hodnota 12 odpovídá maximálnímu rozlišení (0–4095). Výchozí hodnota je 12bitové rozlišení.
  • analogSetCycles(cykly) – nastavení počtu cyklů na jeden vzorek. Výchozí hodnota je 8. (rozsah: 1 až 255)
  • analogSetSamples(vzorky) – nastavení počtu vzorků v rozsahu. Výchozí hodnota je 1 vzorek. (to může ovlivnit citlivost)
  • analogSetClockDiv(útlum) – nastavení děliče pro hodiny ADC. Výchozí hodnota je 1 (rozsah: 1 až 255)
  • analogSetAttenuation(útlum) – nastaví útlum vstupu pro všechny ADC piny. Výchozí je ADC_11db. Akceptované hodnoty:
    • ADC_0db – nenastaví se žádný útlum. ADC může měřit až přibližně 800 mV (1V na vstupu = načtená hodnota 1088).
    • ADC_2_5db – vstupní napětí na ADC bude zeslabeno, tím se rozsah měření zvětší až na cca. 1100 mV. (1V na vstupu = načtená hodnota 3722).
    • ADC_6db – vstupní napětí na ADC bude zeslabeno, tím se rozsah měření zvětší až na cca. 1350 mV. (1V na vstupu = načtená hodnota 3033).
    • ADC_11db – vstupní napětí na ADC bude zeslabeno, tím se rozsah měření zvětší až na cca. 2 600 mV.(1V na vstupu = načtená hodnota 1575).
  • analogSetPinAttenuation(pin, útlum) – nastaví útlum vstupu pro zadaný ADC pin. Výchozí hodnota je ADC_11db. Hodnoty útlumu jsou stejné jako u předchozí funkce.
  • adcAttachPin(pin) – připojí daný pin k ADC (také vymaže jakýkoli jiný analogový režim, který by mohl být zapnutý). Funkce vrací výsledek TRUE nebo FALSE.
  • adcStart(pin) – spustí převod ADC na sběrnici připojeného pinu
  • adcBusy(pin) – zkontroluje, zda právě běží převod na sběrnici ADC pinu (vrací hodnotu TRUE nebo FALSE)
  • resultadcEnd(pin) – získá výsledek převodu, vrátí 16-bitové celé číslo.

 

Ukázka – načítání potenciometru:

Možná nás předchozí odstavec vyděsil, raději si tedy zkusíme nějaký názorný příklad. Vytvoříme si tedy jednoduchý příklad pro čtení analogové hodnoty z potenciometru. Připojíme k modulu ESP32 potenciometr podle následujícího schématu. Střední kolík potenciometru (tzv. jezdec) připojíme k GPIO pinu číslo 34.

ESP32 - Analog input - schema
zdroj obrázku: https://deepbluembedded.com/esp32-adc-tutorial-read-analog-voltage-arduino/

Potenciometr v tomto zapojení slouží jako tzv. dělič napětí. Při jeho otáčení se na jezdci (střední kolík) mění napětí v rozsahu 0–3,3 V. Toto napětí budeme načítat a vypisovat na sériový výstup modulu ESP32. Tyto hodnoty si zobrazíme v Serial Monitoru, který je součástí prostředí Arduino IDE.

/* Pripojený potenciometr na pinu GPIO 34 (Analog ADC1_CH6) */

const int potPin = 34;   // cislo GPIO pinu, kde je pripojeny potenciometr
int potValue = 0;   // promenna pro ulozeni hodnoty z potenciometru

// funkce SETUP se spusti jednou pri stisknuti tlacitka reset nebo pri zapnuti desky.
void setup() {
  Serial.begin(115200);   // prenosova rychlost serioveho vystupu
  delay(1000);   // nech cas 1s pro aplikaci nasteveni
}

// funkce LOOP bezi stale dokola.
void loop() {
  potValue = analogRead(potPin);   // nacteni analogove hodnoty na potenciometru
  Serial.println(potValue);   // vypsani nactene hodnoty na seriový výstup
  delay(500);   // pockej 0,5 s, pak se vse opakuje
}


Zkopírujte výše uvedený kód do prostředí Arduino IDE, zkompilujte a nahrajte svého modulu ESP32. Po stisknutí resetovacího tlačítka modulu ESP32 otevřete okno Serial Monitoru s přenosovou rychlostí 115200. Otáčejte potenciometrem a uvidíte, jak se načtené hodnoty zobrazující se v Serial Monitoru mění.

ESP32 - Analog input - foto
zdroj obrázku: https://deepbluembedded.com/esp32-adc-tutorial-read-analog-voltage-arduino/

Maximální hodnota, kterou získáte, je 4095 a minimální hodnota je 0.

ESP32 - Analog input - Serial Monitor

 


Analogové výstupy (DAC)

Vývojová deska ESP32 má dva integrované 8-bitové digitálně analogové převodníky DAC, které se používají k převodu digitálních signálů na analogové. Dva 8-bitové kanály DAC jsou připojené k GPIO 25 (kanál 1) a GPIO 26 (kanál 2). Zápisem hodnoty z rozsahu 0–255 tak můžeme na pinech GPIO 25 a 26 generovat výstupní napětí v rozmezí 0–3,3 V. To má mnoho možných využití v řadě aplikací, zejména tam, kde něco potřebujeme řídit napětím a nemůžeme využít řízení pomocí PWM. Je ale potřeba si opět uvědomit, že výstupy modulu ESP32 mají své proudové limity a výstupu DAC v tom nejsou výjimkou.

Poznámky:
I když oficiální dokumentace modulu ESP32 slibuje na DAC výstupu při výstupní hodnotě 255 napětí rovno napájecímu (3,3 V), měření na reálných obvodech to moc nepotvrzují. Podobně je to i s minimální hodnotou 0 V. Spíše počítejme s napěťovým rozsahem 0,05–3,16 V (měřeno při Ucc = 3,28 V).
 
Při práci s DAC je také třeba trochu „pohlídat“ linearitu. Je z hlediska linearity lepší používat DAC jako zdroj výstupní napětí/proudu (MAX proud 10 mA!), než jako „vstup pro stahování proudu“ k zemi. (je myšleno jako napěťově proměnný pin, do něhož by vtékal proud z místa vyššího napětí)

DAC výstupy můžeme ovládat dvojím způsobem:

  1. použití příkazu dacWrite(GPIO, hodnota), kde argument GPIO odpovídá číslu pinu zvoleného DAC výstupu (tedy buď 25, nebo 26) a argument hodnota určuje generovanou výstupní analogovou hodnotu (rozsah 0 255)
     
  2. využití ovladače DAC připojeného knihovnou „driver/dac.h“, ve které se musí ADC výstup nastavit pomocí funkce dac_output_enable(DAC_CHANNEL_1), kde konstanta DAC_CHANNEL_1 odpovídá výstupnímu kanálu na pinu 25, konstanta DAC_CHANNEL_2 pak pinu 26. Výstupní hodnotu pak na výstupní kanál zapíšeme pomocí funkce dac_output_voltage(DAC_CHANNEL_1, hodnota)

    Ovladač DAC umožňuje nejen výstupním kanálům nastavit zvolené napětí, ale i využít výstupní kanály pro výstup hudby prostřednictvím protokolu I2S (Inter-IC Sound), kdy je levý kanál I2S namapován na kanál DAC 2 a pravý kanál I2S na kanál DAC 1.


    Další zajímavou možností ovladače DAC je konfigurace DAC výstupů na generátor harmonického průběhu. Případné zájemce o využití těchto možností odkazujeme na popis výrobce modulu ESP32: https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/dac.html

 

Ukázka – analogový výstup DAC (generátor funkce sinus):

Jako ukázku si zde uvedeme program, který bude sloužit jako generátor napěťového harmonického průběhu na GPIO pinu 25. V programu využijeme prvního způsobu řízení DAC výstupů, tedy bez ovladače z knihovny dac.h.

/* Test DAC vystupu */

float vystup;   // promenna pro vystupni hodnotu

// funkce SETUP se spusti jednou pri stisknuti tlacitka reset nebo pri zapnuti desky.
void setup() {
   // i kdyz je procedura SETUP prazdna, musi byt deklarovana, jinak nastane chyba pri kompilaci
}

// funkce LOOP bezi stale dokola.
void loop() {
  for (int deg = 0; deg < 360; deg++) {   // probiha se uhel od 0 do 360 stupnu
    vystup = 128 + 80 * (sin(deg*PI/180));   // vypocet vystupni hodnoty vystupni funkce sin (PI je zabudovana konstanta)
    dacWrite(25, int(vystup));   // zapis vystupu na DAC (prevedeno na cele cislo)
    delayMicroseconds(50);   // pauza na 50 microsekud (mozne zpomaleni)
  }
}


Pro ověření funkčnosti DAC výstupu právě vytvořeného generátoru, použijeme osciloskop. GPIO pin 25 připojíme na vertikální vstup (napěťový rozsah DAC výstupu modulu ESP32 bude 0–3,3 V), pro vykreslení vygenerovaného průběhu zvolíme vhodnou časovou základnu (frekvence generovaného signálu je přibližně 50 Hz).

ESP32 - sinus generator
zdroj obrázku: https://techexplorations.com/guides/esp32/begin/transformation/

Bohužel ani DAC výstup není zcela lineární, proto v krajních hodnotách (okolo 0 a 255) dochází k jistému zkreslení. Proto si všimněte, že generované hodnoty pro výstup (proměnná vystup) nejsou v plném rozsahu 0-255, ale funkce je vypočítávána okolo prostřední hodnoty 128 s amplitudou jen 80.

 


Dotykové (kapacitní) piny

Kromě všech výše popsaných vstupů a výstupů modul ESP32 disponuje i kapacitními dotykovými piny. Počty těchto pinů se mohou lišit podle desek jednotlivých výrobců, vždy si to ověřte dle platného pinout Vaší desky ESP32. Hledejte piny označené popisem „Touch“, např. jako na následujícím obrázku (dotykové piny jsou zvýrazněny modrými rámečky)

ESP32 - touch sensors - pinout
zdroj obrázku: https://microcontrollerslab.com/esp32-touch-sensor-button-example/

Pokud používáte tuto vývojovou desku, nemusíte ve svém projektu používat speciální dotykové senzory jako přídavnou součástku. Kapacitní piny jsou v modulu zabudovány. Kapacitní dotykové senzory lze použít k detekci jakýchkoli elektrických a magnetických vln okolo. U těchto dotykových senzorů můžeme místo tlačítek použít kupříkladu malou dotykovou destičku.

Ukázka – načítání dotykového pinu:

Pojďme se tedy podívat, jak pracovat s dotykovými piny a jak přečíst elektrické změny na těchto pinech. Vyveďme si z desky ESP32 pin GPIO4 pomocí vodiče s neizolovaným koncem.

ESP32 - touch sensors - pinout
zdroj obrázku: https://microcontrollerslab.com

Ve výše uvedeném schématu zapojení se používá touch0, který je mapován pomocí pinu GPIO 4. Podíváme se, jak v prostředí Arduino IDE napsat kód pro měření hodnoty dotykového senzoru a odeslat tuto hodnotu na Serial Monitor (součást prostředí Arduino IDE).

Abychom mohli načítat dotykový senzor, použijeme funkci touchRead(touch_pin_number), která se používá ke čtení hodnoty dotykového senzoru spojené se zadaným dotykovým pinem. Pokud například chcete použít dotykový pin označený Touch0 (viz obr), jednoduše použijete tuto funkci ve tvaru touchRead(T0).

Raději si to ukážeme v následujícím programu. Zkopírujte následující kód do svého Arduino IDE. Princip kódu najdete vysvětlený v komentářích

/* Touch pin TEST */

int touch_sensor_value;   // promenna pro načtenou hodnotu na T0

// funkce SETUP se spusti jednou pri stisknuti tlacitka reset nebo pri zapnuti desky.
void setup() {
  Serial.begin(115200);   // nastaveni prenosove rychlosti serioveho vystupu
}

// funkce LOOP bezi stale dokola.
loop() {
  touch_sensor_value = touchRead(T0);   // nacteni dotykove hodnoty na T0 (pinu GPIO4)
  Serial.print("Touch0 value is = ");   // vypsani zprávy na Serial Monitor
  Serial.println(touch_sensor_value);   // vypsani nactene hodnoty Serial Monitor
  delay(1000);   // počkat 1s, pak vse opakovat
}


Pokud se nedotkneme neizolovaného konce vodiče připojeného k pinu GPIO 4, uvidíte v  okně Serial Monitoru vyšší hodnoty výstupu dotykového senzoru. Jakmile se dotknete neizolované části vodiče připojeného k GPIO 4, začnou hodnoty klesat.

ESP32 - touch sensors - values
zdroj obrázku: https://microcontrollerslab.com

Nyní se podíváme na praktičtější příklad použití dotykového pinu modulu ESP32. Opět budeme rozsvěcet LED (jak originální! 😉). Namísto použití klasického externího tlačítka použijeme malou dotykovou plošku. K tomu ale musíme najít práh dotykového pinu, tedy rozhodující hodnotu, pod kterou bude stav senzoru vyhodnocen jako sepnuté tlačítko a naopak nad touto hodnotou program bude reagovat, jakoby bylo tlačítko rozepnuté.

Prahovou hodnotu najdeme pomocí předchozího programu, kdy budeme sledovat vstupní hodnoty dotykového senzoru v Serial Monitoru. Například, pokud budou hodnoty bez dotyku v rozmezí 60–80 a po dotyku mezi hodnotami 20–30, můžeme za prahovou hodnotu zvolit něco mezi 40 až 50. V následujícím kódu zvolíme za prahovou hodnotu číslo 45.

Vytvoříme následující zapojení. Dotykový senzor můžeme vytvořit z kousku plechu nebo proužku alobalu. LED připojíme přes ochranný rezistor (150–330 Ω) mezi piny GPIO 22 a zem (GND).

ESP32 - touch sensors + LED
zdroj obrázku: https://microcontrollerslab.com

Zkopírujte následující kód do prostředí Arduino IDE. Princip kódu najdete vysvětlený v komentářích:

/* Touch pin ovlada LED */

const int LED_PIN_NUMBER = 22;   // nastaveni pinu pro LED
const int VALUE_THRESHOLD = 45;   // zvolena prahova hodnota
int TOUCH_SENSOR_VALUE;   // promenna pro nactenou hodnotu na T0

// funkce SETUP se spusti jednou pri stisknuti tlacitka reset nebo pri zapnuti desky.
void setup() {
  pinMode(LED_PIN_NUMBER, OUTPUT);   // nastaveni pinu 22 do stavu OUTPUT
}

// funkce LOOP bezi stale dokola.
void loop() {
  TOUCH_SENSOR_VALUE = touchRead(T0);   // nacteni dotykove hodnoty na T0
  if (TOUCH_SENSOR_VALUE < VALUE_THRESHOLD) {   // pokud je nactena hodnota mensi nez prah
    digitalWrite(LED_PIN_NUMBER, HIGH);   // rozsviceni LED (pin 22 na HIGH)
  } else {
    digitalWrite(LED_PIN_NUMBER, LOW);   // zhasnuti LED (pin 22 na LOW)
  }
}

 

Závěr

V dnešním poměrně dlouhém článku jsme si představili základní možnosti užití pinů modulu ESP32, včetně několika jednoduchých praktických ukázek. Berme výše uvedené řádky jako úvod do práce s modulem ESP32. Snad to aspoň trochu pomohlo začátečníkům v prvotním seznámení s modulem ESP32, pokročilým uživatelům to snad umožnilo ucelit a sumarizovat jejich dosavadní poznatky.

Pozorný čtenář si jistě všiml, že z počátečního výčtu funkcí pinů modulu ESP32 jsme se zde nevěnovali jednotlivým rozhraním: SPI, UART, I2C a I2S. To je pravda! Této problematice se chceme věnovat později a průběžně, kdy u jednotlivých čidel, které zde chceme postupně prezentovat a které tato rozhraní i s příslušnými komunikačními protokoly využívají. Jak uvidíme, tak zpravidla budeme využívat některou z podpůrných knihoven, která stejně vše potřebné vyřeší za nás. V některém z dalších článků nás jistě čeká spojení modulu ESP32 s  čidlem teploty a vlhkosti, popřípadě s I2C LCD displejem, kde to názorně uvidíme.

Snad i dnešní informace o základní funkcionalitě pinů modulu ESP32 mám otevřely dveře k zajímavým projektům. Tak toho využijme a nebojme se začít „bastlit“ elektronické projekty s modulem ESP32!

UPOZORNĚNÍ:
Nesouhlasíme s vyřazením Newtonových zákonů, Ohmova zákona a zákona zachování energie z učiva fyziky základních škol v České republice!