Referencia

Interruptok

A megszakítások használhatók az ESP8266-on, de óvatosan kell őket használni, és számos korlátozásuk van:


Digitális IO

Az Arduino kivezetések számozása közvetlenül megfelel az ESP8266 GPIO kivezetések számozásának. A pinMode, digitalRead és digitalWrite funkciók a megszokott módon működnek, tehát a GPIO2 olvasásához hívja meg a digitalRead(2)-t.

A 0–15 digitális kivezetések lehetnek INPUT, OUTPUT vagy INPUT_PULLUP. A 16. kivezetés lehet INPUT, OUTPUT vagy INPUT_PULLDOWN_16. Indításkor a kivezetések INPUT-ként vannak konfigurálva.

A kivezetések más funkciókat is szolgálhatnak, például soros, I2C, SPI. Ezeket a funkciókat általában a megfelelő könyvtár aktiválja. Az alábbi diagram a népszerű ESP-12 modul kivezetés-leképezését mutatja be.

A kivezetések funkciói

A 6-11 digitális kivezetések nem láthatók ezen az ábrán, mert a legtöbb modul flash memória chip csatlakoztatására szolgál. Ha ezeket a kivezetéseket IO-ként próbálja használni, valószínűleg a program összeomlik.

Vegye figyelembe, hogy egyes kártyák és modulok (ESP-12ED, NodeMCU 1.0) a 9-es és 11-es érintkezőket is kitörik. Ezeket IO-ként lehet használni, ha a flash chip DIO módban működik (szemben a QIO-val, amely az alapértelmezett).

A pin-megszakításokat az attachInterrupt, detachInterrupt funkciók támogatják. A megszakítások bármely GPIO kivezetéshez csatolhatók, kivéve a GPIO16-ot. A szabványos Arduino megszakítási típusok támogatottak: CHANGE, RISING, FALLING. Az ISR-eknek IRAM_ATTR-nek kell lenniük a függvénydefiníció előtt.


Analóg input

MEGJEGYZÉS: Az analogRead() túl gyakori hívása a WiFi leállását okozza. Ha a WiFi üzemel, az analogRead() eredménye legalább 5 ms-ig gyorsítótárban maradhat a hatékony hívások között.

Az ESP8266 egyetlen ADC csatornával rendelkezik a felhasználók számára. Használható az ADC érintkező feszültségének vagy a modul tápfeszültségének (VCC) olvasására.

Az ADC érintkezőre adott külső feszültség olvasásához használja az analogRead(A0)-t. A csupasz ESP8266 bemeneti feszültségtartománya 0–1,0 V, azonban egyes kártyák feszültségosztókat is alkalmazhatnak. A biztonság kedvéért <1.0V tesztelhető. Ha pl. A 0,5 V ~512 körüli értékeket ad, akkor a maximális feszültség nagy valószínűséggel 1,0 V, a 3,3 V pedig károsíthatja az ESP8266-ot. A ~150 körüli értékek azonban azt jelzik, hogy a maximális feszültség valószínűleg 3,3 V.

A VCC feszültség leolvasásához használja az ESP.getVcc()-et, és az ADC kivezetést nem kell csatlakoztatni. Ezenkívül a következő sort kell hozzáadni a vázlathoz:


ADC_MODE(ADC_VCC);

Ennek a sornak minden függvényen kívül kell megjelennie, például közvetlenül a vázlat #include sorai után.


Analóg output

Az analogWrite(pin, value) engedélyezi a szoftveres PWM-et az adott kivezetésen. A PWM a 0-tól 16-ig terjedő kivezetéseken használható. Hívja az analogWrite(pin, 0) parancsot a PWM letiltásához a kivezetésen.

A value 0 és 255 között lehet (ami az Arduino alapértelmezése). A PWM tartomány megváltoztatható az analogWriteRange(new_range) vagy az analogWriteResolution(bits) meghívásával. A new_range lehet 15…65535 vagy a bits 4…16.

Az analogWriteMode(pin, value, openDrain) függvény lehetővé teszi, hogy a pinmódot OUTPUT_OPEN_DRAIN értékre állítsa az OUTPUT helyett.

MEGJEGYZÉS: Az alapértelmezett analogWrite tartomány 1023 volt a 3.0 előtti kiadásokban, de ez a külső könyvtárakkal való összeférhetetlenséghez vezetett, ami az Arduino mag alapértelmezett 256-os értékétől függ. Azok a meglévő alkalmazások, amelyek az előző 1023-as értékre támaszkodnak, hozzáadhatják az analogWriteRange(1023) hívását a setup() rutinjukhoz, hogy visszatérjenek régi viselkedésükhöz. Azon alkalmazásokon, amelyek már hívták az analogWriteRange-et, nem kell változtatni.

A PWM frekvencia alapértelmezés szerint 1 kHz. Hívja az analogWriteFreq(new_frequency) függvényt a frekvencia megváltoztatásához. Az érvényes értékek 100 Hz-től 40 000 Hz-ig terjednek.

Az ESP-nek nincs hardveres PWM-je, így a megvalósítás szoftveresen történik. Egy 40 kHz-es PWM kimenettel a CPU már meglehetősen terhelt. Minél több PWM-kimenetet használunk, és minél magasabb a frekvenciájuk, annál közelebb kerülünk a CPU-korlátokhoz, és annál kevesebb CPU-ciklus áll rendelkezésre a vázlat-végrehajtáshoz.


Időzítés és késések

A millis() és a micros() az alaphelyzetbe állítás után eltelt ezred-, illetve mikromásodpercek számát adja vissza.

A delay(ms) egy adott számú ezredmásodpercig szünetelteti a vázlatot, és lehetővé teszi a WiFi és TCP/IP feladatok futtatását. delayMicroseconds(us) szünetet tart adott számú mikroszekundumra.

Ne feledje, hogy a vázlaton kívül sok kódnak futnia kell a chipen, amikor a WiFi csatlakozik. A WiFi és TCP/IP könyvtárak lehetőséget kapnak a függőben lévő események kezelésére minden alkalommal, amikor a loop() függvény befejeződik, VAGY a delay meghívásakor. Ha a vázlatban van valahol egy ciklus, amely sok időt vesz igénybe (>50 ms) a delay hívása nélkül, érdemes lehet egy delay hívási funkcióval kiegészíteni, hogy a WiFi verem zökkenőmentesen működjön.

Van egy yield() függvény is, amely egyenértékű a delay(0)-val. A delayMicroseconds funkció viszont nem enged más feladatoknak, így 20 ezredmásodpercnél nagyobb késleltetés esetén nem javasolt a használata.


Serial

A Serial objektum ugyanúgy működik, mint egy hagyományos Arduino esetében. A hardveres FIFO-n kívül (128 bájt TX és RX esetén), a Serial további testreszabható 256 bájtos RX pufferrel rendelkezik. Ennek a szoftveres puffernek a méretét a felhasználó módosíthatja. Nagyobb vételi sebességnél nagyobb méret használata javasolt.

A ::setRxBufferSize(size_t size) metódus szükség szerint módosítja az RX puffer méretét. Ezt a ::begin() előtt kell meghívni. A méret argumentumnak legalább elég nagynak kell lennie ahhoz, hogy az olvasás előtt kapott összes adatot tartalmazza.

Csak átvitel esetén a 256 bájtos RX puffer kikapcsolható a RAM megtakarítása érdekében a SERIAL_TX_ONLY mód átadásával a Serial.begin()-nek. Egyéb módok a SERIAL_RX_ONLY és SERIAL_FULL (az alapértelmezett).

A fogadás megszakítás-vezérelt, de lekérdezéseket és foglalt várakozásokat küld. A blokkolási viselkedés a következő: A ::write() hívás nem blokkol, ha a bájtok száma belefér a TX FIFO-ban rendelkezésre álló aktuális helyre. A hívás blokkolja, ha a TX FIFO megtelt, és megvárja, amíg van hely, mielőtt további bájtokat írna bele, amíg az összes bájt meg nem íródik. Más szóval, amikor a hívás visszatér, az összes bájt beírásra került a TX FIFO-ba, de ez még nem jelenti azt, hogy az összes bájt ki lett küldve a soros vonalon. A ::read() hívás nem blokkol, még akkor sem, ha nem állnak rendelkezésre bájtok az olvasáshoz. A ::readBytes() hívás addig blokkol, amíg az olvasott bájtok száma el nem éri a bevitt argumentum által megkívánt bájtok számát. A ::flush() hívásblokkok arra várnak, hogy a TX FIFO üres legyen, mielőtt visszatérne. Javasoljuk, hogy ezt hívja meg, hogy megbizonyosodjon arról, hogy az összes bájt el lett küldve, mielőtt konfigurációt módosítana a soros porton (pl. az átviteli sebesség megváltoztatása) vagy a kártya alaphelyzetbe állítása előtt.

A Serial az UART0-t használja, amely a GPIO1 (TX) és GPIO3 (RX) érintkezőkhöz van leképezve. A Serial újra leképezhető GPIO15 (TX) és GPIO13 (RX) formátumra a Serial.swap() meghívásával a Serial.begin után. A swap ismételt hívása az UART0-t visszaképezi a GPIO1-re és a GPIO3-ra.

A Serial1 UART1-et használ, a TX pin GPIO2. Az UART1 nem használható adatfogadásra, mert általában az RX érintkezője van lefoglalva a flash chip csatlakozáshoz. A Serial1 használatához hívja a Serial1.begin(baudrate) parancsot.

Ha a Serial1 nincs használva, és a Serial nincs felcserélve - az UART0 TX-je leképezhető GPIO2-re a Serial.begin utáni Serial.set_tx(2) meghívásával vagy közvetlenül a Serial.begin(baud, config, mode, 2) paranccsal.

A Serial.begin meghívásakor a WiFi-könyvtárak diagnosztikai kimenete alapértelmezés szerint le van tiltva. A hibakeresési kimenet ismételt engedélyezéséhez hívja a Serial.setDebugOutput(true) parancsot. A hibakeresési kimenet Serial1-re való átirányításához hívja a Serial1.setDebugOutput(true) parancsot.

A printf() függvény kimenetének engedélyezéséhez a Serial.setDebugOutput(true)-t is használnia kell.

Mind a Serial, mind a Serial1 objektumok támogatják az 5, 6, 7, 8 adatbitet, páratlan (O), páros (E) és nem (N) paritást, valamint 1 vagy 2 stopbitet. A kívánt mód beállításához hívja a Serial.begin(baudrate, SERIAL_8N1), a Serial.begin(baudrate, SERIAL_6E2) stb. parancsot. Az alapértelmezett konfigurációs mód a SERIAL_8N1. A lehetőségek a következők: SERIAL_[5678][NEO][12]. Példa: a SERIAL_8N1 azt jelenti, hogy 8 bit, nincs paritás és 1 stopbit.

Mind a Serial, mind a Serial1 esetében új módszert alkalmaztak az aktuális adatátviteli sebesség beállításához. Az aktuális adatátviteli sebesség megtekintéséhez hívja a Serial.baudRate(), a Serial1.baudRate() parancsot. A visszatérési érték int, az aktuális sebesség. Például


// Állítsa az adatátviteli sebességet 57600-ra
Serial.begin(57600);

// Az aktuális adatátviteli sebesség lekérése
int br = Serial.baudRate();

// Kinyomtatja, hogy "Serial is 57600 bps"
Serial.printf("Serial is %d bps", br);

A Serial és Serial1 objektumok egyaránt a HardwareSerial osztály példányai.
Ez a hivatalos ESP8266 Software Serial könyvtár esetében is megtörténik, lásd ezt a lekérési kérelmet.
Vegye figyelembe, hogy ez a megvalósítás csak ESP8266 alapú kártyákra vonatkozik, és nem működik más Arduino kártyákkal.

A Serial-ra érkező adatok ismeretlen átviteli sebességét a Serial.detectBaudrate(time_t timeoutMillis) használatával észlelheti. Ez a módszer megpróbálja észlelni az adatátviteli sebességet maximum timeoutMillis ms-ig. Nullát ad vissza, ha nem észlelt átviteli sebességet, vagy egyébként az észlelt átviteli sebességet. A detectBaudrate() függvény a Serial.begin() meghívása előtt hívható meg, mert nincs szüksége sem a fogadópufferre, sem a SerialConfig paraméterekre.

Az uart nem tud más paramétereket észlelni, mint például a start- vagy stopbitek száma, az adatbitek száma vagy a paritás.

Maga az észlelés nem változtat az átviteli sebességen, észlelés után a szokásos módon be kell állítani a Serial.begin(detectedBaudrate) segítségével.

Az észlelés nagyon gyors, mindössze néhány bejövő bájtot vesz igénybe.

A SerialDetectBaudirate.ino a felhasználás teljes példája.


Progmem

A Program memória funkciói ugyanúgy működnek, mint egy hagyományos Arduino esetében; csak olvasható adatok és karakterláncok elhelyezése a csak olvasható memóriában, és heap felszabadítása az alkalmazás számára.

A 2.7 előtti alapverziókban a fontos különbség az, hogy az ESP8266-on a literális karakterláncok nincsenek összevonva. Ez azt jelenti, hogy ugyanaz az F("") és/vagy PSTR("") karakterláncban definiált karakterlánc fog helyet foglalni a kód minden példányához. Tehát magának kell kezelnie az ismétlődő karakterláncokat.

A 2.7-es verziótól kezdve ez már nem igaz: az r/o memórián belüli ismétlődő literális karakterláncok kezelése már megtörténik.

Van egy további segítő makró, amely megkönnyíti a const PROGMEM karakterláncok átadását olyan metódusoknak, amelyek egy FPSTR() nevű __FlashStringHelper-t vesznek igénybe. Ennek használata megkönnyíti a karakterláncok összegyűjtését. Nem egyesíti a karakterláncokat…


String response1;
response1 += F("http:");
...
String response2;
response2 += F("http:");

Az FPSTR használata…


const char HTTP[] PROGMEM = "http:";
...
{
    String response1;
    response1 += FPSTR(HTTP);
    ...
    String response2;
    response2 += FPSTR(HTTP);
}


C++


Stream-ek

Arduino API

A Stream az Arduino API egyik alapvető osztálya. A vezetékes, soros, hálózati és fájlrendszerek olyan adatfolyamok, amelyekből adatokat olvasnak vagy írnak.

A streamekkel való átvitel meglehetősen gyakori, mint például a történelmi WiFiSerial vázlat:


//ellenőrizze a kliensek adatait
//lekérni az adatokat a telnet klienstől és továbbítja az UART-hoz
while (serverClient.available()) {
  Serial.write(serverClient.read());
}

//ellenőrizze az UART adatokat
if (Serial.available()) {
  size_t len = Serial.available();
  uint8_t sbuf[len];
  Serial.readBytes(sbuf, len);
  //UART adatok küldése az összes csatlakoztatott telnet kliensnek
  if (serverClient && serverClient.connected()) {
    serverClient.write(sbuf, len);
  }
}

Észrevehető, hogy a hálózatban a soros irányban az adatok bájtonként kerülnek átvitelre, miközben az adatok rendelkezésre állnak. A másik irányban egy ideiglenes puffer jön létre a veremben, feltöltődik az elérhető soros adatokkal, majd átkerül a hálózatra.

A readBytes(puffer, long) metódus időtúllépést tartalmaz annak biztosítására, hogy az összes szükséges bájt megérkezzen. A write(puffer, hossz) (a Print::) függvény is általában blokkol, amíg a teljes puffer el nem kerül. Mindkét függvény az átvitt bájtok számát adja vissza.

A Stream osztály így működik és általánosan használatos.

A Stream::-ből származtatott osztályok általában bevezetik a read(buffer, len) metódust is, ami hasonló a readBytes(buffer, len) timeout-hoz: a visszaadott érték kisebb is lehet, mint a kért méret, ezért erre fokozottan ügyelni kell. funkció, amelyet az Arduino Client:: osztályban vezettek be (vö. AVR referencia implementáció). Ezt a funkciót más olyan osztályokban is bevezették, amelyek nem a Client::-ből származnak, pl. HardverSerial::.

Stream bővítmények

Az Stream-bővítményeket úgy tervezték, hogy kompatibilisek legyenek az Arduino API-val, és további módszereket kínálnak az átvitel hatékonyabbá és egyszerűbbé tételéhez.

A fenti soros hálózati átvitel a következőképpen írható fel:


serverClient.sendAvailable(Serial); // darabonként
Serial.sendAvailable(serverClient); // darabonként

Egy visszhangszolgáltatás így írható:


serverClient.sendAvailable(serverClient); // tcp echo szolgáltatás

Serial.sendAvailable(Serial);             // soros szoftveres visszacsatolás

A kódolási idő csökkentése mellett ezek a módszerek optimalizálják az átvitelt azáltal, hogy lehetőség szerint elkerülik a puffermásolatokat.


© Copyright 2017, Ivan Grokhotkov Revision b7c1cfbc. Fordította: Maczák András