V tem vodniku bomo raziskali ESP32S, fantastično razvojno ploščo za uporabo v internetu stvari. Ta plošča, ki jo je razvilo podjetje Espressif, bi morala biti zaradi nizke cene in odličnih funkcij, naslednica NodeMCU.
Avtor teksta in fotografij: Marcelo José Rovai
Pomembno pa je tudi poudariti, da na tej novi plošči še NE delujejo vse knjižnice ali funkcije, ki ste jih vajeni pri delu z ESP8266 in/ali Arduinom. Verjetno se bo to kmalu zgodilo, zato redno preverjajte na spletni strani foruma ESP 32.
Ta vsebina je samo za naročnike
Naučili se bomo, kako programirati ESP32S v Arduino IDE, raziskali njegove najpogostejše funkcije in knjižnice ter opozorili na nekatere pomembne razlike in nove funkcije, uvedene s tem odličnim čipom.
Skratka, raziskali bomo:
- Digitalni izhod: utripajoča LED-ica
- Digitalni vhod: branje senzorja za dotik
- Analogni vhod: branje spremenljive napetosti s potenciometra
- Analogni izhod: upravljanje svetlosti LED-ice
- Analogni izhod: upravljanje položaja servomotorja
- Odčitavanje podatkov o temperaturi/vlažnosti z digitalnim senzorjem
- Povezovanje z internetom in pridobivanje lokalnega časa
- Prejemanje podatkov s preproste lokalne spletne strani, vklop/izklop LED-ice
- Prenos podatkov na preprosto lokalno spletno stran
- Vključitev OLED zaslona za lokalno predstavitev podatkov, zajetih z DHT senzorjem (temperatura in vlažnost), ter lokalnega časa.
1. korak: Glavne značilnosti ESP32S
ESP32 je plošča, ki stane okoli 11 ameriških dolarjev, in ima velike prednosti pred podobnimi ploščami za internet stvari na trgu.
Ta plošča ima dvojedrni mikroprocesor, ki je v veliko pomoč, saj ko en procesor skrbi za komunikacijo, je drugi zadolžen na primer za nadzor vhodov in izhodov. Ta funkcija bo preprečila nekatere težave, ki se pojavljajo pri ESP8266, kjer mora edini procesor prenehati nadzirati vhode/izhode, ko se ukvarja s komunikacijo. Poleg tega ima ESP32 vgrajene WIFI, BLUETOOTH, DAC, več ADC (ne le enega kot ESP8266), kapacitivne senzorje za dotik itd.. Dobra novica je, da je poraba energije skoraj enaka kot pri ESP8266.
Slika 2 prikazuje tabelo, ki nam lahko pokaže njegove glavne značilnosti in razlike v primerjavi z ESP8266:
Za več podrobnosti navedimo njegove glavne lastnosti
Ključne lastnosti:
- 240 MHz dvojedrni mikrokontroler Tensilica LX6 s 600 DMIPS
- Vgrajeni 520 KB SRAM
- Vgrajeni brezžični oddajnik 802.11 b/g/n HT40, osnovno pasovno omrežje, sklad in LwIP
- Vgrajen dvojni način Bluetooth (klasični in BLE)
- 16 MB Flash pomnilnika, ki je pomnilniško prilagojen kodnemu prostoru procesorja
- Delovna napetost od 2,3 do 3,6 V
- Delovna temperatura od -40 °C do +125 °C
- Vgrajena antena na tiskanem vezju / priključek IPEX za zunanjo anteno
Senzorji:
- Analogni ojačevalnik z izjemno nizkim šumom
- Hall senzor
- 10x kapacitivni vmesniki na dotik
- 32kHz kristalni oscilator
34x GPIO:
- 3 x UART, vključno s strojnim nadzorom pretoka
- 3 x SPI
- 2 x I2S
- 18 x vhodnih kanalov ADC
- 2 x DAC in 2 x I2C
- Vhod/izhod PWM/timerja je na voljo na vsakem pinu GPIO
- OpenOCD vmesnik za odpravljanje napak z 32 kB TRAX bufferjem
- SDIO master/slave 50 MHz
- Podpira zunanji pomnilniški SPI Flash do 16 MB
- Podpora za vmesnik SD kartice
Varnostne lastnosti:
WEP, WPA/WPA2 PSK/Enterprise
Strojno pospešeno šifriranje: AES/SHA2/Elliptical Curve Cryptography/RSA-4096
Delovanje:
- Podpira sniffer način, Station, SoftAP in Wi-Fi direct načine
- Največja hitrost prenosa podatkov 150 Mb/s@11n HT40, 72 Mb/s@11n HT20, 54 Mb/s@11g in 11 Mb/s@11b
- Največja oddajna moč 19,5 dBm@11b, 16,5 dBm@11g, 15,5 dBm@11n
- Najmanjša občutljivost sprejemnika -97 dBm
- Trajna prepustnost UDP 135 Mb/s
- Poraba energije 5 μA v stanju globokega spanja
2. korak: BoM – spisek materiala
- Komplet ESP32 Dev Kit: Razvojna plošča ESP32 (8,52 USD)
- 0,91-palčni 128×32 I2C IIC serijski modri OLED LCD zaslon (2,98 USD)
- Mikro servo: TowerPro SG90 9G Mini servo (3,80 USD)
- Senzor temperature in vlage: DHT22/AM2302 Digitalni senzor temperature in vlage (9,99 USD)
- LED in 2 x upor: 330 Ohmov in 10k Ohmov
- Potenciometer: 10k Ohm
- Razvojne plošče
3. korak: Namestitev ESP32 Arduino IDE
Za programiranje našega ESP32 bomo uporabili Arduino IDE, enako kot pri družini ESP8266.
Namestite gonilnike:
- Pomembno je, da imate v računalniku nameščen posodobljen CP210x gonilnik USB za UART. Vnesite to povezavo: usb-to-uart-bridge-vcp-drivers [1] in namestite ustrezen gonilnik za vaš operacijski sistem.
- Namestite knjižnico:
- Novost pri tem je, da nam Expressif sam v svojem GitHubu poda ustrezna navodila za namestitev knjižnice: arduino-esp32 [2]. Sledite navodilom za vaš operacijski sistem. V mojem primeru (MacOS) je namestitev zelo preprosta:
Odprite terminal in izvedite naslednji ukaz (kopiraj->prilepi in pritisnite Enter):
mkdir -p ~/Documents/Arduino/hardware/espressif && cd ~/Documents/Arduino/hardware/espressif && git clone https://github.com/espressif/arduino-esp32.git esp32 && cd esp32/tools/ && python get.py
Nato ponovno zaženite Arduino IDE in je opravljeno! V meniju “TOOLS” morate videti več plošč. Izberite ustrezno za vas. Na splošno “generična” ESP32 DEV MODULE deluje dobro.
Ko prvič odprete Arduino IDE, boste opazili, da je privzeta hitrost prenosa 921.600 baudov. To lahko povzroči nestabilnost. Spremenite jo na 115.200 baudov!
4. korak: Pozdravljen svet! Utripanje LED-ice
Kot običajno je prva stvar, ki jo naredimo, ko začnemo raziskovati nov HW, utripanje LED-ice.
V IDE pojdite v meni Primeri in odprite skico Blink.
Komplet ESP32 DevKit ima vgrajeno LED-ico, ki je povezana z GPIO 02. Pomembno je, da preverite, ali IDE samodejno prepozna “LED_BUILTIN”. Če ne, morate v kodo dodati vrstico:
int LED_BUILTIN = 2;
Vsaka ESP32 plošča ima notranjo LED-ico, ki je povezana z različnim GPIO.
/* ESP 32 Blink Turns on an LED on for one second, then off for one second, repeatedly. The ESP32 has an internal blue LED at D2 (GPIO 02) */ int LED_BUILTIN = 2; void setup() { pinMode(LED_BUILTIN, OUTPUT); } void loop() { digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level) delay(1000); // wait for a second digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW delay(1000); // wait for a second }
Spodaj utripa notranja LED-dica (upoštevajte modro svetlobo) skupaj z zunanjo, ki je priključena na GPIO 2:
Na trgu je na voljo več različnih plošč z različnimi razporeditvami priključkov. Zgornja slika prikazuje ploščo, ki jo uporabljam. Najdete jo na povezavi [3].
Odlično! DigitalWrite() deluje odlično, enako velja za ESP8266 in Arduino. Mimogrede, tudi funkcija DigitalRead() deluje enako za branje digitalnega vhoda, kot je na primer tipka.
5. korak: Senzor dotika
Premaknimo se k novi odlični funkciji, senzorju dotika!
ESP32 ima 10 notranjih kapacitivnih senzorjev za dotik. Uporabite jih lahko na primer kot tipke.
Ti senzorji so povezani z več GPIO priključki:
T0: GPIO 4
T1: GPIO 0
T2: GPIO 2
T3: GPIO 15
T4: GPIO 13
T5: GPIO 12
T6: GPIO 14
T7: GPIO 27
T8: GPIO 33
T9: GPIO 32
Za njihovo branje morate uporabiti funkcijo: touchRead(Touch Pin #);
Če želite na primer prebrati senzor na dotik 0 (T0), morate napisati nekaj takega:
int value = touchRead(4);
Ustvarimo kodo, v kateri se ob dotiku senzorja T0 (GPIO4) prižge LED-ica.
S serijskim monitorjem preverite vrednosti, ki jih odčitava senzor, in ustrezno prilagodite program.
Spodaj je celoten program:
/****************************************** ESP32 Touch Test and LED Ctrl * Touch pin ==> Touch0 is T0 which is on GPIO 4 (D4). * LED pin ==> D2 * * MJRoBot.org 6Sept17 *****************************************/ #define TOUTCH_PIN T0 // ESP32 Pin D4 #define LED_PIN 2 int touch_value = 100; void setup() { Serial.begin(115200); delay(1000); // give me time to bring up serial monitor Serial.println("ESP32 Touch Test"); pinMode(LED_PIN, OUTPUT); digitalWrite(LED_PIN, LOW); } void loop() { touch_value = touchRead(TOUTCH_PIN); Serial.println(touch_value); // get value using T0 if (touch_value < 50) { digitalWrite(LED_PIN, HIGH); } else { digitalWrite(LED_PIN, LOW); } delay(1000); }
Slika 4, kjer vidite delujoč ESP32.
6. korak: Analogni vhod
Preizkusimo, kako vnašati signale analognih vrednosti.
Skupno je na voljo 18 x 12-bitnih vhodnih kanalov ADC v primerjavi z le 1 x 10-bitnim ADC v NodeMCU.
GPIO ADC kanali:
GPIO 0 ==> ADC2_CH1
GPIO 2 ==> ADC2_CH2
GPIO 4 ==> ADC2_CH0
GPIO 12 =>== ADC2_CH5
GPIO 13 => ADC2_CH4
GPIO 14 => ADC2_CH6
GPIO 15 => ADC2_CH3
GPIO 25 => ADC2_CH8
GPIO 26 => ADC2_CH9
GPIO 27 => ADC2_CH7
GPIO 32 => ADC1_CH4
GPIO 33 => ADC1_CH5
GPIO 34 => ADC1_CH6
GPIO 35 => ADC1_CH7
GPIO 36 => ADC1_CH0
GPIO 37 => ADC1_CH1
GPIO 38 => ADC1_CH2
GPIO 39 => ADC1_CH3
Za branje analognega vhoda boste ravnali enako kot pri Arduinu in ESP8266:
int analog_value = analogRead(36);
Zelo pomembno je omeniti, da imajo ADCji na ESP32 plošči 12 bitno ločljivost (v primerjavi z 10 bitno pri ESP8266 in Arduinu), tako da je skupno območje branja ADCjev 4095 (namesto 1027 pri Arduinu in ESP8266), ko se na vhode priključi največ 3,3 V.
Za vhod uporabimo 10k Ohm potenciometer, ki ga povežemo s 3,3 V in GND. Njegov spremenljivi izhod uporabimo kot vhod za ADC priključek (GPIO 36; ADC1.0) na ESP32. Poskusite tudi z drugimi vhodi na plošči.
Zaženite naslednjo preprosto kodo: /****************************************** ESP32 Analog Input Test * Analog Input: ADC_1_0 pin ==> GPIO36 (VP). * * * MJRoBot.org 6Sept17 *****************************************/ //Analog Input #define ANALOG_PIN_0 36 int analog_value = 0; void setup() { Serial.begin(115200); delay(1000); // give me time to bring up serial monitor Serial.println("ESP32 Analog IN Test"); } void loop() { analog_value = analogRead(ANALOG_PIN_0); Serial.println(analog_value); delay(500); }
Obrnite potenciometer in na zaslonu IDE Serial Monitor opazujte meritve od nič do 4,095.
7. korak: Zatemnitev LED: analogni izhod z uporabo PWM
Če želimo na ESP8266 ali Arduinu “zatemniti LED”, lahko preprosto uporabimo ukaz, kot je analogWrite(), ki bo spreminjal vrednost PWM na izhodu in simuliral analogno vrednost. Na žalost v Arduino IDE še vedno nimamo razvitega takšnega ukaza za ESP32, vendar je zelo dobra novica, da ima vseh 36 GPIO-jev ESP32 možnost generirati PWM, kar je odlično! Le za dosego enakega rezultata moramo uporabiti bolj zapleteno kodo.
Zato sprogramirajmo enega od teh GPIO-jev tako, da bo generiral izhodni PWM signal.
Na tej povezavi [4] lahko najdete zelo dober vodič s podrobnostmi o delovanju PWM.
Prva stvar, ki jo je treba upoštevati pri ustvarjanju signala PWM, je njegova frekvenca. Uporabili bomo vrednost 5000 Hz, ki se dobro obnese pri LED-ici. Določiti moramo tudi PWM kanal za LED in ločljivost delovnega cikla PWM v bitih. Izberemo lahko kanal od 0 do 15 in ločljivost od 1 do 16 bitov. Uporabili bomo kanal 0 in ločljivost 8 bitov.
int freq = 5000; int ledChannel = 0; int resolution = 8; Uporabimo GPIO2, kjer imamo priključeno našo zunanjo LED-ico (in notranjo). #define LED_PIN 2;
Te parametre je treba določiti v setup() fazi z uporabo spodnjih
funkcij: void setup() { ledcSetup(ledChannel, freq, resolution); ledcAttachPin(LED_PIN, ledChannel); }
Če želimo prižgati LED-ico z določeno svetlostjo, moramo določiti “delovni cikel”.
Na primer, če želimo LED-ico izklopiti, mora biti delovni cikel enak nič, funkcija ledcWrite(ledChannel, dutyCycle) pa se uporabi za pošiljanje vrednosti prek določenega PWM kanala:
int dutyCycle = 0; ledcWrite(ledChannel, dutyCycle);
Različne vrednosti spremenljivke dutyCycle bodo vklopile LED-ico z različno svetlostjo. Ta dutyCycle spremenljivka se bo spreminjala od 0 do 255, če je uporabljena ločljivost 8 bitov.
Za ročno nastavitev spremenljivke dutyCycle lahko uporabimo potenciometer (povezan s spremenljivko analog_value), ko pa je njun razpon vrednosti različen, uporabimo funkcijo map, da uskladimo vhod in izhod:
dutyCycle = map(analog_value, 0, 4095, 0, 255); V nadaljevanju je prikazana celotna koda: ****************************************** * ESP32 Analog Input/Output Test * Analog Input: ADC_1_0 pin ==> GPIO36 (VP). * PWM LED pin ==> GPIO 02 * MJRoBot.org 6Sept17 *****************************************/ //Analog Input #define ANALOG_PIN_0 36 int analog_value = 0; // PMW LED #define LED_PIN 2 int freq = 5000; int ledChannel = 0; int resolution = 8; int dutyCycle = 0; void setup() { Serial.begin(115200); delay(1000); // give me time to bring up serial monitor Serial.println("ESP32 Analog IN/OUT Test"); ledcSetup(ledChannel, freq, resolution); ledcAttachPin(LED_PIN, ledChannel); ledcWrite(ledChannel, dutyCycle); } void loop() { analog_value = analogRead(ANALOG_PIN_0); Serial.println(analog_value); dutyCycle = map(analog_value, 0, 4095, 0, 255); ledcWrite(ledChannel, dutyCycle); delay(500); }
In to je to!
8. korak: Krmiljenje servo motorja
Poizkusimo krmiliti servomotor z uporabo PWM našega ESP32. Koda bo v osnovi enaka tisti, ki smo jo uporabili za nadzor svetlosti LED-ice.
Najprej si je treba zapomniti, da je frekvenca za delo z Micro Servo servomotorjem 50 Hz, zato moramo parameter frekvence spremeniti na 50 (namesto 5.000, ki smo jih uporabili pri LED).
Določiti moramo tudi PWM kanal za LED in ločljivost delovnega cikla PWM v bitih. Ponovno bomo uporabili kanal 0 in ločljivost 8 bitov.
int freq = 50; int channel = 0; int resolution = 8;
Servo bo priključen na GPIO 5.
#define SERVO_PIN 5;
Enako kot pri LED je treba te parametre določiti v fazi setup() z uporabo spodnjih funkcij:
void setup() { ledcSetup(channel, freq, resolution); ledcAttachPin(SERVO_PIN, channel); }
Da bi servo nastavili na določen kot, moramo določiti “delovni cikel”.
Na primer, če želimo servo postaviti za 90 stopinj, mora biti delovni cikel približno 21, za pošiljanje vrednosti prek PWM kanala pa je treba uporabiti funkcijo ledcWrite(ledChannel, dutyCycle):
int dutyCycle = 21; ledcWrite(channel, dutyCycle);
Različne vrednosti dutyCycle spremenljivke bodo postavile servo pod različnimi koti. Ta dutyCycle spremenljivka mora biti v razponu od 10 do 32 (ta razpon je bil dobljen ročno).
Podobno kot pri LED lahko potenciometer (povezan z analog_valuevariable spremenljivko) uporabimo za ročno nastavitev dutyCycle spremenljivke in s tem za spreminjanje položaja servo motorja. Ko so njuna območja vrednosti različna, uporabimo funkcijo map, da uskladimo vhod in izhod:
dutyCycle = map(analog_value, 0, 4095, 10, 33);
V nadaljevanju je navedena celotna koda:
/***************************************** * ESP32 Servo Control * Analog Input: ADC_1_0 pin ==> GPIO36 (VP). * PWM SERVO pin ==> GPIO 05 * * MJRoBot.org 6Sept17 *****************************************/ //Analog Input #define ANALOG_PIN_0 36 int analog_value = 0; // PMW SERVO #define SERVO_PIN 5 int freq = 50; int channel = 0; int resolution = 8; int dutyCycle = 21; void setup() { Serial.begin(115200); delay(1000); // give me time to bring up serial monitor Serial.println("ESP32 Servo Control"); ledcSetup(channel, freq, resolution); ledcAttachPin(SERVO_PIN, channel); ledcWrite(channel, dutyCycle); } void loop() { analog_value = analogRead(ANALOG_PIN_0); Serial.print(analog_value); Serial.print(" Duty Cycle ==>");
Zdaj lahko na delujemo z ultrazvočnim senzorjem montiranim na vrhu servo motorja in zgradimo IoT radar! Ampak to bo še en članek!
Korak 9: Povezava s strežnikom za točen čas
Po preizkušanju nekaterih digitalnih/analognih in vhodno-izhodnih zmogljivosti GPIO povežimo naš ESP32 v internet!
Pri družini ESP8266 smo za to uporabljali knjižnico esp8266wifi.h. Pri družini ESP32 bomo uporabili naslednjo knjižnico:
<wifi.h>
Zelo preprost primer je programiranje naše plošče tako, da zajema lokalni čas iz interneta. To je zelo dobra funkcija, ki jo je treba imeti pri projektih. Spodnja koda nam bo to omogočila:
/***************************************** * Local Time Stamp with ESP32 * Developed by Marcelo Rovai - 8 September 2017 *****************************************/ #include <NTPClient.h> #include <WiFi.h> #include <WiFiUdp.h> #define NTP_OFFSET -3 * 60 * 60 // In seconds #define NTP_INTERVAL 60 * 1000 // In miliseconds #define NTP_ADDRESS "europe.pool.ntp.org" WiFiUDP ntpUDP; NTPClient timeClient(ntpUDP, NTP_ADDRESS, NTP_OFFSET, NTP_INTERVAL); void setup() { Serial.begin(115200); timeClient.begin(); }
Korak 10: Preprost WiFi strežnik
Preizkusimo naš ESP32 kot preprost WiFi strežnik.
Odprite meni EXAMPLES v Arduino IDE in poiščite skico ESP32 WiFi/SimpleWiFiServer.ino:
O tem programu:
- WiFi Web Server LED utripa
- Ustvarjeno za Arduino 25 Nov 2012, avtor Tom Igoe
- Preneseno za Sparkfun ESP32 31.01.2017, Jan Hendrik Berlin
Preprost spletni strežnik, ki omogoča krmiljenje LED-ice prek spleta. Ta skica izpiše IP naslov vašega ESP32 WiFi omrežja na serijski monitor. Od tam lahko ta naslov odprete v spletnem brskalniku, da vklopite in izklopite LED-ico na pinu 5.
Če je IP naslov vaše plošče na primer 10.0.1.40 sta ukaza za vklop/izklop sledeča:
http://10.0.1.40/H vklopi LED-ico http://10.0.1.40/L Izklopi LED-ico
Ta primer je napisan za omrežje, ki uporablja WPA šifriranje. Za šifriranje WEP ali WPA ustrezno spremenite Wifi.begin() klic.
V vezju je LED-ica priključena na priključek št. 5.
Uporabimo program brez večjih sprememb. Zunanji LED pin spremenite v GPIO5.
Seveda, če želite, lahko spremenite kodo za GPIO2 brez spreminjanja HW.
Najprej vnesite omrežne poverilnice:
const char* ssid = "yourssid"; const char* password = "yourpasswd";
In jih naložite v ESP32.
Prva stvar, ki jo boste videli na serijskem monitorju, bo informacija, da je vaš ESP32 povezan in kakšen je njegov IP naslov:
- WiFi connected.
- IP address:
- 10.0.1.40
Odprite najljubši brskalnik in vtipkajte ta IP naslov. Prikazala se bo spletna stran.
Na njej lahko na daljavo vklopite ali izklopite LED-ico.
Korak 11: DHT 22 – odčitavanje temperature in vlažnosti
DHT11 ali DHT21 sta zelo uporabna senzorja, ki se uporabljata v projektih interneta stvari. Senzorja sta poceni in ju je enostavno vključiti v projekte.
Najprej morate imeti v svojem IDE nameščeno Adafruit knjižnico. Pojdite na njihov GitHub in prenesite posodobljeno različico te knjižnice: DHT-sensor-library [5]
Razpakirajte datoteko, jo preimenujte v DHT in celotno mapo premaknite v imenik knjižnice Arduino.
Ko sem prvič uporabil, sem dobil sporočilo:
usodna napaka: Adafruit_Sensor.h: Ni take datoteke ali imenika
Po nekaj iskanja sem ugotovil, da je treba namestiti tudi knjižnico Adafruit Unified Sensor Library. Tako sem to storil iz upravitelja knjižnic Arduino IDE. Nato je vse delovalo brezhibno, tako kot smo vajeni z Arduinom in NodeMCU.
Opravimo nekaj testov s tem senzorjem. Sledite zgornjemu električnemu diagramu in namestite DHT22, kot je prikazano na sliki (glejte senzor z “mrežo” proti sebi in preštejte 4 noge od leve proti desni):
VCC ==> 3,3 V Pin Data ==> GPIO 23 N/C PIN GND ==> GND
Med VCC in Data priključite tudi upor 10K ohmov.
To je to!
Uporabite lahko skico primera “DHT tester.ino”, ki je vključena v knjižnico, ali pa naredite svojo.
Napisal sem preprosto kodo za testiranje senzorja, kot je prikazano spodaj:
/***************************************** * ESP32 DHT Reading * DHT Input: ==> GPIO23. * * MJRoBot.org 9Sept17 *****************************************/ /* DHT */ #include "DHT.h" #define DHTPIN 23 #define DHTTYPE DHT22 DHT dht(DHTPIN, DHTTYPE); float localHum = 0; float localTemp = 0; void setup() { Serial.begin(115200); delay(1000); // give me time to bring up serial monitor Serial.println(""); Serial.println("ESP32 DHT Temperature and Humidity "); Serial.println(""); dht.begin(); } void loop() { getDHT(); Serial.print("Temp: ==>"); Serial.print(localTemp); Serial.print(" Hum ==>"); Serial.println(localHum); delay(2000); } /**** Get indoor Temp/Hum data ********/ void getDHT() { float tempIni = localTemp; float humIni = localHum; localTemp = dht.readTemperature(); localHum = dht.readHumidity(); if (isnan(localHum) || isnan(localTemp)) // Check if any reads failed and exit early (to try again). { localTemp = tempIni; localHum = humIni; return; } }
Pregled dosedanjega dela v tem članku:
- Digitalni izhod: digitalni digitalni signal: utripanje LED-ice
- digitalni vhod: Digitalni digitalni signal: branje senzorja za dotik
- Analogni vhod: Branje spremenljive napetosti s potenciometra
- Analogni izhod: Upravljanje svetlosti LED-ice
- Analogni izhod: Upravljanje položaja servoojačevalnika
- Odčitavanje podatkov o temperaturi/vlažnosti z digitalnim senzorjem
- Povezovanje z internetom in pridobivanje lokalnega časa
- Izdelava preproste spletne strani za vklop/izklop LED-ice (prejemanje podatkov)
Zavedamo se, da moramo še vedno poskusiti poslati podatke na spletno stran. Torej, naredimo to!
Podatke, pridobljene iz DHT senzorja, in analogno vrednost, ki jo zagotavlja potenciometer, bomo poslali na spletno stran, ustvarjeno za nadzor LED-ic.
Začel sem s kodo SimpleWiFiServer, uporabljeno v koraku 10, in dodal ustrezne vrstice kode za pridobitev podatkov iz potenciometra in DHT.
Upoštevajte, da sem LED-ico premaknil nazaj na GPIO 2, kot je razvidno iz električne sheme.
Prenesite celotno kodo z mojega GitHuba: ESP32_WiFi_Server_Sending_Receiving_Data.ino [6]
Upoštevajte, da sem kodo bolje organiziral in zdaj je samo loop():
void loop() { analog_value = analogRead(ANALOG_PIN_0); getDHT(); WiFiLocalWebPageCtrl(); }
Novost je funkcija “WiFiLocalWebPageCtrl()”. Vendar je to natanko tista prvotna funkcija setup(), ki se uporablja v strežniku SimpleWebServer. Kar sem vključil v to funkcijo, je tisto, kar se mora prikazati na spletni strani. (glejte zaslon za tiskanje spletne strani).
// the content of the HTTP response follows the header: //WiFiLocalWebPageCtrl(); client.print("Temperature now is: "); client.print(localTemp); client.print(" oC<br>"); client.print("Humidity now is: "); client.print(localHum); client.print(" % <br>"); client.print("<br>"); client.print("Analog Data: "); client.print(analog_value); client.print("<br>"); client.print("<br>"); client.print("Click <a href="/H">here</a> to turn the LED on.<br>"); client.print("Click <a href="/L">here</a> to turn the LED off.<br>");
Upoštevajte, da se temperatura, vlažnost in analogne vrednosti posodobijo vsakič, ko kliknete na povezave, ki se uporabljajo za nadzor LED-ice, ali ko osvežite stran.
Korak 12: Namestitev OLED zaslona
V tem priročniku bom uporabil I2C OLED 128 x 32 zaslon. Načeloma bi ESP32 po namestitvi knjižnice deloval tudi z OLED 128 x 64 zaslonom.
Ker ta zaslon krmilimo z I2C, morate z ESP32 povezati 4 priključke:
SDA ==> GPIO 21 SCL ==> GPIO 22 VCC ==> 3,3 V GND ==> GND
Nadomestite linijo:
SSD1306 display(0x3c, D3, D5);
s tole:
SSD1306 display(0x3c, 21, 22);
Spodaj je prikazan GIF, ki prikazuje delno delovanje preprostih demonstracij. Upoštevajte, da je bil ta demo zasnovan za zaslon 128 x 64, zato se zavedajte, da je v mojem primeru, kjer sem uporabil 128 x 32, grafika pomanjšana.
Korak 13: Ustvarjanje in nameščanje novih pisav
Na zaslonu lahko preprosto ustvarite in namestite nove pisave. Ustvaril sem novo pisavo, s katero lahko na OLED zaslonu 128 X 32 ustvarim približno 2 vrstici po 20 znakov.
Kako jo ustvarite? Uporabite Font Converter.
Pojdite na SSD1306 Pretvornik pisav [7], odlično orodje, ki ga je prav tako razvil Daniel Eighhoen. Tam morate izbrati:
- Družina pisave,
- vrsto (Plan Bold itd.),
- velikost (10, 20 itd.) in
- različico knjižnice (v našem primeru mora biti >=3.0.0).
Pritisnite Ustvari in voilá! V ustreznem oknu se ustvari “C Font” datoteka.
Pojdite tja in kopirajte besedilo v nov IDE zavihek. Poimenujte ga na primer: “modified_font.h”
V svojo glavno datoteko .ino na začetku vključite novo vrstico:
#include "modified_font.h"
Zgornja fotografija prikazuje novo pisavo “Hello World”, ki uporablja to novo pisavo. Čisto kodo lahko prenesete z mojega GitHuba [8]:
Upoštevajte, da morate imeti dve datoteki v Arduino IDE, če uporabljate spremenjeno pisavo!
Korak 14: Lokalno prikazovanje temperature in vlažnosti
Na OLED zaslonu zdaj prikažimo temperaturo in vlažnost, ki ju zajame DHT22 senzor.
V naši loop() funkciji bomo imeli: void loop() { getDHT(); displayData(); delay(2000); } Funkcija getDHT() je tista, ki je bila uporabljena prej. Nova funkcija je displayData(), ki je prikazana spodaj: /*********** Display Data ****************/ void displayData() { display.clear(); // clear the display display.drawString(0, 0, "temp: "); display.drawString(40, 0, String(localTemp)); display.drawString(90, 0, "oC"); display.drawString(0, 32, "hum: "); display.drawString(40, 32, String(localHum)); display.drawString(90, 32, "%"); display.display(); // write the buffer to the display delay(10); }
Zgornja fotografija prikazuje končni rezultat, Celotno datoteko lahko prenesete iz mojega GitHuba: ESP32_DHT22_SSD1306 [9].
Korak 15: Vključitev časovnega žiga
Običajno je pri zajemanju podatkov s senzorji zelo pomembno, da se zabeleži tudi čas, ko so bili podatki zbrani.
Za to uporabimo NTPClient knjižnico:
- Pojdite v Upravitelja knjižnic in poiščite “NTP”.
- Poiščite in namestite knjižnico NTPClient Fabricea Weinberga
- Odprite primer NTP odjemalca: Osnovni ali napredni.
Spremenite vrstico:
#include <ESP8266WiFi.h> s tole: #include <WiFi.h>
Vnesite poverilnice WiFi omrežja. Na serijskem monitorju morate videti dejanski čas. Pri osnovni različici bo prikazan evropski čas. Pri napredni različici ga lahko spremenite.
Zdaj združimo to TimeStamp kodo s kodo, ki smo jo razvili prej. Rezultat je prikazan na fotografijah.
Celotno kodo lahko prenesete z mojega GitHuba: ESP32_Time_Stamp_DHT22_SSD1306 [10].
Korak 16: Izbira večjega števila zaslonov
V zadnjem koraku vse skupaj združimo v fiksni zaslon s 3 informacijami:
- Temperatura
- Vlažnost
- Lokalni čas
Toda kako lahko na zaslonu prikažemo vsako od teh informacij naenkrat? Naenkrat vsega seveda ne moremo prikazati, ker je zaslon premajhen za to.
Potrebujemo mehanizem za izbiro strani. Uporabiti je mogoče več različnih mehanizmov. Običajno to storimo z več tipkami in izbirnimi meniji.
Za zabavo poskusimo nekaj, kar ni običajno. Potenciometer!
Potenciometer bomo vrteli kot radijsko številčnico in glede na odčitano vrednost bomo določili poseben “prikaz”, ki se bo prikazal na zaslonu OLED.
Določimo 4 možne prikaze: prikaz 0 ==> prikaz OFF prikaz 1 ==> lokalni čas prikaz 2 ==> temperatura prikaz 3 ==> vlažnost prikaz 4 ==> prikaz vseh informacij
Analogni vhod lahko odčita 4.095 različnih vrednosti. Mi jih potrebujemo le 5, zato da to določimo območja:
0000 - 0999: ==> prikaz 0 ==> izklop zaslona 1000-1999: ==> prikaz 1 ==> lokalni čas 2000 - 2999: ==> prikaz 2 ==> temperatura 3000 - 3999: ==> prikaz 3 ==> vlažnost 4000 - 4095: ==> prikaz 4 ==> prikaz vseh informacij
Opredelimo spremenljivko int, ki bo prejela vsebino: 0, 1, 2, 3, 4 5, odvisno od zaslona, ki se bo prikazal:
int displayNum = 0;
Zdaj moramo ustvariti funkcijo getDisplay(), ki bo prebrala vrednost potenciometra in vrnila pravilno številko zaslona (displayNum bo lokalna spremenljivka znotraj te funkcije).
Funkcija bo videti takole:
/*********** Get display ****************/ int getDisplay() { int displayNum = 0; int analog_value = analogRead(ANALOG_PIN_0); if (analog_value <= 999) displayNum = 0; else if (analog_value > 1000 && analog_value <= 1999) displayNum = 1; else if (analog_value > 2000 && analog_value <= 2999) displayNum = 2; else if (analog_value > 3000 && analog_value <= 3999) displayNum = 3; else if (analog_value > 4000 ) displayNum = 4; return displayNum; }
Funkcija displayData() pa prikaže izbrani prikaz (ali zaslon):
/*********** Display Data ****************/ void displayData(int displayNum) { String formattedTime = timeClient.getFormattedTime(); display.clear(); // clear the display switch (displayNum) { case 0: display.clear(); break; case 1: display.setFont(ArialMT_Plain_24); display.drawString(20, 31, String(formattedTime)); break; case 2: display.setFont(ArialMT_Plain_24); display.drawString(0, 31, "T:"); display.drawString(30, 31, String(localTemp)); display.drawString(100, 31, "oC"); break; case 3: display.setFont(ArialMT_Plain_24); display.drawString(0, 31, "H:"); display.drawString(30, 31, String(localHum)); display.drawString(100, 31, "%"); break; case 4: display.setFont(Open_Sans_Condensed_Light_20); display.drawString(0, 0, "t:"); display.drawString(10, 0, String(localTemp)); display.drawString(47, 0, "oC"); display.drawString(75, 0, "h:"); display.drawString(85, 0, String(localHum)); display.drawString(120, 0 , "%"); display.setFont(ArialMT_Plain_24); display.drawString(20, 31, String(formattedTime)); break; default: display.clear(); break; } display.display(); // write the buffer to the display delay(10); }
Obe funkciji bosta vključeni v našo loop() zanko:
void loop() { getDHT(); timeClient.update(); displ