Kazalo:

Prekoračitev standardaFirmata - ponovno obiskano: 5 korakov
Prekoračitev standardaFirmata - ponovno obiskano: 5 korakov

Video: Prekoračitev standardaFirmata - ponovno obiskano: 5 korakov

Video: Prekoračitev standardaFirmata - ponovno obiskano: 5 korakov
Video: Часть 2 - Аудиокнига «Тесс из рода д'Эрбервиллей» Томаса Харди (гл. 08–14) 2024, Julij
Anonim
Prekoračitev standardnih firm - ponovno obiskano
Prekoračitev standardnih firm - ponovno obiskano

Pred kratkim me je poklical dr. Martyn Wheeler, uporabnik pymata4, za navodila pri dodajanju podpore za senzor vlažnosti/temperature DHT22 v knjižnico pymata4. Knjižnica pymata4 skupaj s svojim kolegom iz Arduina, FirmataExpress, uporabnikom omogoča daljinsko upravljanje in spremljanje njihovih naprav Arduino. V nekaj krogih izmenjave e -pošte je dr. Wheeler uspel spremeniti tako pymata4 kot FirmataExpress. Posledično je podpora za senzorje DHT22 in DHT11 zdaj standardni del pymata4 in FirmataExpress.

Maja 2014 sem napisal članek o dodajanju podpore Firmata za dodatne naprave. Ob razmišljanju o tem članku sem spoznal, koliko se je spremenilo, odkar sem za ta članek vzela pisalo. Poleg tega članka je dr. Wheeler dokumentiral svoja prizadevanja in morda boste želeli preveriti tudi to.

FirmataExpress temelji na StandardFirmata, struktura imenikov StandardFirmata pa se je razvila. Poleg tega je API pymata4 precej drugačen od prvotnega API -ja PyMata iz leta 2014. Mislil sem, da bi bil to pravi čas za ponovni ogled in posodobitev tega članka. Na podlagi dela dr. Wheelerja raziščimo, kako razširiti funkcionalnost pymata4/FirmataExpress.

Preden začnemo - Nekaj osnovnih informacij o Arduinu/Firmati

Kaj je torej Firmata? Citiram s spletne strani Firmata: "Firmata je generični protokol za komunikacijo z mikrokrmilniki iz programske opreme na gostiteljskem računalniku."

Arduino Firmata uporablja serijski vmesnik za prenos podatkov o ukazih in poročilih med mikrokrmilnikom Arduino in osebnim računalnikom, običajno z uporabo serijske/USB povezave, nastavljene na 57600 b/s. Podatki, preneseni prek te povezave, so binarni, protokol pa je izveden v modelu odjemalec/strežnik.

Strežniška stran je naložena na mikrokrmilnik Arduino v obliki skice Arduino. Skica StandardFirmata, vključena v Arduino IDE, nadzoruje vhodno -izhodne zatiče Arduino, kot jim naroči odjemalec. Stranki poroča tudi o spremembah vhodnih zatičev in drugih informacijah poročila. FirmataExpress je razširjena različica StandardFirmata. Deluje s hitrostjo serijske povezave 115200 b / s.

Odjemalec Arduino, uporabljen za ta članek, je pymata4. To je aplikacija Python, ki se izvaja v računalniku. Oba pošilja ukaze in prejema poročila s strežnika Arduino. Ker se pymata4 izvaja v Pythonu, deluje v sistemih Windows, Linux (vključno z Raspberry Pi) in računalnikih macOS.

Zakaj uporabljati Firmata?

Arduino mikrokrmilniki so čudovite majhne naprave, vendar so procesorski in pomnilniški viri nekoliko omejeni. Za aplikacije, ki zahtevajo veliko procesorja ali pomnilnika, pogosto ni druge izbire, kot da naložite povpraševanje po virih v računalnik, da bo aplikacija uspešna.

Vendar to ni edini razlog za uporabo StandardFirmata. Pri razvoju lažjih aplikacij Arduino lahko osebni računalnik ponudi orodja in možnosti za odpravljanje napak, ki niso neposredno na voljo na mikrokrmilniku Arduino. Uporaba "fiksnega" odjemalca in strežnika pomaga omejiti kompleksnost aplikacije na osebni računalnik, ki ga je lažje upravljati. Ko je aplikacija izpopolnjena, jo lahko prevedemo v samostojno skico Arduino po meri.

Zakaj uporabljati pymata4?

Ker sem njen avtor, sem seveda pristranski. Kot rečeno, je to edini odjemalec Firmata s Pythonom, ki se v zadnjih nekaj letih stalno vzdržuje. Zagotavlja intuitiven in enostaven za uporabo API. Poleg skic, ki temeljijo na StandardFirmata, podpira Firmata prek WiFi za naprave, kot je ESP-8266, ko uporabljate skico StandardFirmataWifI.

Prav tako je bil pymata4 zasnovan tako, da ga uporabnik zlahka razširi za podporo dodatnih senzorjev in aktuatorjev, ki jih StandardFirmata trenutno ne podpira.

1. korak: Razumevanje protokola Firmata

Razumevanje protokola Firmata
Razumevanje protokola Firmata

Komunikacijski protokol Arduino Firmata izhaja iz protokola MIDI, ki za prikaz podatkov uporablja enega ali več 7-bitnih bajtov.

Firmata je bila zasnovana tako, da je uporabniško razširljiva. Mehanizem, ki zagotavlja to razširljivost, je protokol za pošiljanje sporočil System Exclusive (SysEx).

Oblika sporočila SysEx, kot je opredeljena s protokolom Firmata, je prikazana na zgornji sliki. Začne se z bajtom START_SYSEX s fiksno vrednostjo šestnajstiškega 0xF0, sledi pa mu edinstven bajt ukaza SysEx. Vrednost bajta ukaza mora biti v območju šestnajstiškega 0x00-0x7F. Ukaznemu bajtu nato sledi nedoločeno število 7-bitnih podatkovnih bajtov. Nazadnje se sporočilo konča z bajtom END_SYSEX s fiksno vrednostjo šestnajstiškega 0xF7.

Kodiranje/dekodiranje podatkov podjetja Firmata

Ker je del uporabniških podatkov sporočila SysEx sestavljen iz serije 7-bitnih bajtov, se lahko vprašate, kako eden predstavlja vrednost, večjo od 128 (0x7f)? Firmata te vrednosti kodira tako, da jih razstavi na več 7-bitnih kosov bajtov, preden se podatki razvrstijo po podatkovni povezavi. Najprej se pošlje najmanj pomemben bajt (LSB) podatkovne postavke, po konvenciji pa sledijo vse pomembnejše komponente podatkovne postavke. Najpomembnejši bajt (MSB) podatkovne postavke je zadnja poslana podatkovna postavka.

Kako to deluje?

Recimo, da želimo vključiti vrednost 525 v podatkovni del sporočila SysEx. Ker je vrednost 525 očitno večja od vrednosti 128, jo moramo razdeliti ali razstaviti na 7-bitne "bajke".

Evo, kako se to naredi.

Vrednost 525 v decimalki je enakovredna šestnajstiški vrednosti 0x20D, 2-bajtni vrednosti. Če želimo dobiti LSB, prikrijemo vrednost tako, da jo AND označimo z 0x7F. Spodaj sta prikazani izvedbi »C« in Python:

// Izvajanje "C" za izolacijo LSB

int max_distance_LSB = max_distance & 0x7f; // prikriva spodnji bajt # Implementacija Pythona za izolacijo LSB max_distance_LSB = max_distance & 0x7F # maska spodnjega bajta

Po maskiranju bo max_distance_LSB vseboval 0x0d. 0x20D & 0x7F = 0x0D.

Nato moramo izolirati MSB za to 2-bajtno vrednost. Če želite to narediti, bomo vrednost 0x20D premaknili v desno, 7 mest.

// Izvajanje "C" za izolacijo MSB z 2 bajtno vrednostjo

int max_distance_MSB = max_distance >> 7; // premaknemo bajt visokega reda # Implementacija Python, da izolira MSB z 2 bajtno vrednostjo max_distance_MSB = max_distance >> 7 # shift, da dobimo zgornji bajt Po premiku bo max_distance_MSB vseboval vrednost 0x04.

Ko so prejeti "razčlenjeni" združeni podatki, jih je treba znova sestaviti v eno samo vrednost. Tukaj je opisano, kako se podatki ponovno sestavijo v "C" in Pythonu

// izvedba "C" za ponovno sestavljanje 2 bajtov, // 7 -bitne vrednosti v eno samo vrednost int max_distance = argv [0] + (argv [1] << 7); # Izvedba Python za ponovno sestavljanje 2 -bajtnih, # 7 -bitnih vrednosti v eno samo vrednost max_distance = data [0] + (podatki [1] << 7)

Po ponovnem sestavljanju je vrednost spet enaka 525 decimalnim ali 0x20D šestnajstiškim.

Ta postopek demontaže/ponovne montaže lahko izvede odjemalec ali strežnik.

2. korak: Začnimo

Podpora nove naprave zahteva spremembe tako v rezidenčnem strežniku Arduino kot v odjemalcu Python v PC -ju. Delo dr. Wheelerja bo uporabljeno za ponazoritev potrebnih sprememb.

Morda je najpomembnejši korak odločitev, ali želite integrirati obstoječo knjižnico podpornih naprav v Arduinovo stran enačbe ali napisati svojo. Priporočljivo je, da je, če najdete obstoječo knjižnico, veliko lažje uporabljati kot pisati svojo iz nič.

Za podporo naprav DHT je dr. Wheeler svojo razširitveno kodo utemeljil v knjižnici DHTNew. Zelo pametno je dr. Wheeler razdelil funkcionalnost knjižnice DHTNew po straneh enačbe Arduino in pymata4, da bi zagotovil minimalno blokiranje na strani Arduino.

Če pogledamo DHTNew, izvede vse naslednje:

  • Nastavi izbrani način digitalnega izhoda pin.
  • Ura kodiranega signala za pridobitev najnovejših vrednosti vlažnosti in temperature.
  • Preveri in poroča o morebitnih napakah.
  • Izračuna vrednosti temperature in vlažnosti, ki jih lahko bere človek, iz pridobljenih surovih podatkov.

Da bi bile stvari na strani FirmataExpress čim bolj učinkovite, je dr. Wheeler naložil rutino pretvorbe podatkov iz Arduina v pymata4.

3. korak: Spremenite FirmataExpress za podporo DHT

Drevo imenika FirmataExpress

Spodaj so vse datoteke, ki sestavljajo skladišče FirmataExpress. To drevo je enako tistemu pri StandardFiramata, le da nekatera imena datotek odražajo ime skladišča.

Datoteke, ki jih je treba spremeniti, so tiste, ki imajo ob sebi zvezdico (*).

FirmataExpress

── * Plošče.h

Examples── primeri

Ir └── FirmataExpress

│ ├── deskax

├── * FirmataExpress.ino

│ ├── LICENSE.txt

Fi └── Makefile

├── * FirmataConstants.h

├── * FirmataDefines.h

├── FirmataExpress.cpp

├── FirmataExpress.h

├── FirmataMarshaller.cpp

├── FirmataMarshaller.h

├── FirmataParser.cpp

└── FirmataParser.h

Poglejmo vsako datoteko in spremembe, ki so bile narejene.

Deske.h

Ta datoteka vsebuje definicije makrov tipa pin za vsako od podprtih vrst plošč. Določa največje število podprtih naprav, kadar je treba podpreti več naprav.

Za napravo DHT je lahko hkrati povezanih do 6 naprav, ta vrednost pa je definirana kot:

#ifndef MAX_DHTS

#define MAX_DHTS 6 #endif

Za novo napravo so lahko po izbiri določeni tudi makri tipa pin, bodisi za vse vrste plošč ali samo za tiste, ki vas zanimajo. Ti makri se večinoma uporabljajo za poročanje in se ne uporabljajo za nadzor naprav. Ti makri določajo oba zatiča, ki podpirata napravo:

#define IS_PIN_DHT (p) (IS_PIN_DIGITAL (p) && (p) - 2 <MAX_DHTS)

Pa tudi makro za določitev pretvorbe pin številk.

#define PIN_TO_DHT (p) PIN_TO_DIGITAL (p)

FirmataConstants.h

Ta datoteka vsebuje številko različice vdelane programske opreme, ki jo boste morda želeli spremeniti, da boste spremljali, katero različico ste naložili na svoj Arduino. Vsebuje tudi vrednosti sporočil Firmata, vključno s sporočili Firmata SysEx.

V tej datoteki boste morali svoji napravi dodeliti novo sporočilo ali niz sporočil. Za DHT sta bili dodani dve sporočili. Eden konfigurira pin kot "DHT" pin, drugi pa kot poročevalsko sporočilo, ko pošilja najnovejše podatke DHT nazaj odjemalcu.

static const int DHT_CONFIG = 0x64;

static const int DHT_DATA = 0x65;

V tej datoteki so določeni tudi načini pripenjanja. Za DHT je bil ustvarjen nov način pin:

static const int PIN_MODE_DHT = 0x0F; // pin nastavljen za DHT

Ko dodajate nov način zatikanja, je treba prilagoditi TOTAL_PIN_MODES:

static const int TOTAL_PIN_MODES = 17;

FirmataDefines.h

To datoteko je treba posodobiti, da bo odražala nova sporočila, dodana na FirmataConstants.h:

#ifdef DHT_CONFIG #undef DHT_CONFIG #endif #define DHT_CONFIG firmata: DHT_CONFIG // zahteva DHT #ifdef DHT_DATA #undef DHT_DATA #endif #define DHT_DATA firmata:: DHT_DATA // DHT odgovor #iFD_DM PIN_DM:: PIN_MODE_DHT

FirmataExpress.ino

V tej razpravi bomo obravnavali "vrhunce" sprememb, ki so bile narejene na tej skici Arduino.

Da bi FirmataExpress lahko hkrati podpiral do šest naprav DHT, so bili ustvarjeni 3 nizi za sledenje vsake povezane številke pina naprave, njene vrednosti WakeUpDelay in vrste naprave, to je DHT22 ali DHT11:

// DHT senzorji

int numActiveDHTs = 0; // število priloženih DHT -jev uint8_t DHT_PinNumbers [MAX_DHTS]; uint8_t DHT_WakeUpDelay [MAX_DHTS]; uint8_t DHT_TYPE [MAX_DHTS];

Ker obe vrsti naprav med branji potrebujeta približno 2 sekundi, moramo poskrbeti, da bomo vsak DHT prebrali le enkrat v 2-sekundnem časovnem okviru. Do nekaterih naprav, kot so naprave DHT in senzorji razdalje HC-SR04, dostopate le občasno. To jim daje čas za interakcijo s svojim okoljem.

uint8_t naslednjiDHT = 0; // indeksiramo v dht za naslednjo napravo za branje

uint8_t tokDHT = 0; // Spremlja, kateri senzor je aktiven. int dhtNumLoops = 0; // Ciljno število krat skozi zanko b4, ki dostopa do DHT int dhtLoopCounter = 0; // Števec zank

Konfiguriranje in branje naprave DHT

Ko FirmataExpress prejme ukaz SysEx za konfiguracijo zatiča za delovanje DHT, preveri, da največje število naprav DHT ni preseženo. Če je mogoče podpreti nov DHT, se polja DHT posodobijo. Če vrsta DHT ni znana, se ustvari sporočilo o nizu SysEx, ki se pošlje nazaj na pymata4

primer DHT_CONFIG: int DHT_Pin = argv [0]; int DHT_type = argv [1]; if (numActiveDHTs <MAX_DHTS) {if (DHT_type == 22) {DHT_WakeUpDelay [numActiveDHTs] = 1; } drugače če (DHT_type == 11) {DHT_WakeUpDelay [numActiveDHTs] = 18; } else {Firmata.sendString ("NAPAKA: NEPOZNAT TIP SENZORJA, VELJAVNI SENZORJI 11, 22"); zlom; } // preskus senzorja DHT_PinNumbers [numActiveDHTs] = DHT_Pin; DHT_TYPE [numActiveDHTs] = vrsta DHT_; setPinModeCallback (DHT_Pin, PIN_MODE_DHT);

FirmataExpress nato poskuša komunicirati z napravo DHT. Če pride do napak, ustvari sporočilo SysEx s podatki o napaki in pošlje sporočilo SysEx nazaj na pymat4. Spremenljivka _bits vsebuje podatke, ki jih naprava DHT vrne, da jih pymata4 po potrebi dodatno obdela.

Firmata.write (START_SYSEX);

Firmata.write (DHT_DATA); Firmata.write (DHT_Pin); Firmata.write (tip DHT_); for (uint8_t i = 0; i> 7 & 0x7f); } Firmata.write (abs (rv)); Firmata.write (1); Firmata.write (END_SYSEX);

Če se vrnejo veljavni podatki, se število aktivnih DHT poveča. Prilagodljiva je tudi spremenljivka, ki spremlja, koliko iteracij zanke je treba dokončati, preden preveri podatke naslednje DHT. Ta spremenljivka zagotavlja, da bodo ne glede na to, koliko DHT dodanih sistemu, vse prebrane v obdobju 2 sekund.

int rv = readDhtSensor (numActiveDHTs);

if (rv == DHTLIB_OK) {numActiveDHTs ++; dhtNumLoops = dhtNumLoops / numActiveDHT; // vse v redu}

Če je bila ena ali več naprav DHT konfigurirano v funkciji zanke skice, se prebere naslednja naprava DHT. Veljavni podatki ali stanje napake se vrnejo v pymata4 v obliki sporočila SysEx:

if (dhtLoopCounter ++> dhtNumLoops) {if (numActiveDHTs) {int rv = readDhtSensor (nextDHT); uint8_t current_pin = DHT_PinNumbers [nextDHT]; uint8_t current_type = DHT_TYPE [nextDHT]; dhtLoopCounter = 0; trenutniDHT = naslednjiDHT; if (nextDHT ++> = numActiveDHTs - 1) {nextDHT = 0; } if (rv == DHTLIB_OK) {// TEST CHECKSUM uint8_t sum = _bits [0] + _bits [1] + _bits [2] + _bits [3]; if (_bit [4]! = vsota) {rv = -1; }} // sporočilo pošljemo nazaj s statusom napake Firmata.write (START_SYSEX); Firmata.write (DHT_DATA); Firmata.write (current_pin); Firmata.write (trenutni_tip); for (uint8_t i = 0; i <sizeof (_bits) - 1; ++ i) {Firmata.write (_bits ); // Firmata.write (_bits ;} Firmata.write (abs (rv)); Firmata.write (0); Firmata.write (END_SYSEX);}}

Koda, ki se uporablja za komunikacijo z napravo DHT, izhaja neposredno iz knjižnice DHTNew:

int readDhtSensor (int indeks) {

// INIT BUFFERVAR ZA PREJEM PODATKOV uint8_t mask = 128; uint8_t idx = 0; // PRAZNI BUFER // memset (_bit, 0, sizeof (_bits)); for (uint8_t i = 0; i 5 BYTES for (uint8_t i = 40; i! = 0; i--) {loopCnt = DHTLIB_TIMEOUT; while (digitalRead (pin) == LOW) {if (--loopCnt == 0) return DHTLIB_ERROR_TIMEOUT;} uint32_t t = micros (); loopCnt = DHTLIB_TIMEOUT; while (digitalRead (pin) == HIGH) {if (--loopCnt == 0) vrne DHTLIB_ERROR_TIMEOUT;} if ((micros ()-t)> 40) {_bits [idx] | = mask;} mask >> = 1; if (mask == 0) // naslednji bajt? {Mask = 128; idx ++;}} vrni DHTLIB_OK;}

4. korak: Spremenite Pymata4 za podporo DHT

private_constants.h

Za podporo DHT moramo tej datoteki dodati tako nova sporočila pin-type kot SysEx:

# pin načina INPUT = 0x00 # pin nastavljen kot vhod OUTPUT = 0x01 # pin nastavljen kot izhod ANALOG = 0x02 # analogni pin v analognem načinu vhoda PWM = 0x03 # digitalni pin v izhodnem načinu PWM SERVO = 0x04 # digitalni pin v načinu servo izhoda I2C = 0x06 # nožica vključena v nastavitev I2C STEPPER = 0x08 # kateri koli zatič v koračnem načinu SERIAL = 0x0a PULLUP = 0x0b # Vsak pin v načinu vlečenja SONAR = 0x0c # Vsak pin v načinu SONAR TONE = 0x0d # Vsak pin v tonskem načinu PIXY = 0x0e # rezervirano za način kamere pixy DHT = 0x0f # tipalo DHT IGNORE = 0x7f # sporočila ukaza DHT SysEx DHT_CONFIG = 0x64 # dht config ukaz DHT_DATA = 0x65 # dht odgovor senzorja

Dodana vrsta pin in ukazi SysEx se morajo ujemati z vrednostmi v FirmataConstants.h, ki so dodane v FirmataExpress.

pymata4.py

Pymata4 uporablja slovar Python za hitro povezovanje dohodnega sporočila Firmata z upravljalnikom sporočil. Ime tega slovarja je report_dispatch.

Oblika vnosa v slovar je:

{MessageID: [message_handler, število podatkovnih bajtov za obdelavo]}

V slovar je bil dodan vnos za obravnavo dohodnih sporočil DHT:

{PrivateConstants. DHT_DATA: [self._dht_read_response, 7]}

7 bajtov podatkov v sporočilu je številka digitalnega PIN -a Arduino, vrsta naprave DHT (22 ali 11) in 5 bajtov neobdelanih podatkov.

Metoda _dht_read_response preveri vse prijavljene napake. Če ni prijavljenih napak, se vlažnost in temperatura izračunata po algoritmu, prenesenem iz knjižnice Arduino DHTNew.

Izračunane vrednosti so sporočene z uporabniško metodo povratnega klica. Prav tako so shranjeni v notranji podatkovni strukturi pin_data. Zadnjo sporočeno vrednost lahko prikličete z anketo pin_data z metodo dht_read.

Konfiguriranje nove naprave DHT

Pri dodajanju nove naprave DHT se pokliče metoda set_pin_mode_dht. Ta metoda posodobi pin_data za digitalne zatiče. Prav tako ustvari in pošlje sporočilo DHT_CONFIG SysEx podjetju FirmataExpress.

5. korak: Zaključek

Kot smo videli, dodajanje podpore Firmata za novo napravo zahteva, da spremenite kodo strežnika Arduino FirmataExpress in kodo odjemalca pymata4, ki temelji na Pythonu. Odpravljanje napak pri kodi FirmataExpress je lahko zahtevno. Za pomoč pri odpravljanju napak je bila FirmataExpressu dodana metoda, imenovana printData. Ta metoda vam omogoča pošiljanje podatkovnih vrednosti iz FirmataExpress in jih natisne na konzoli pymata4.

Ta funkcija zahteva tako kazalec na niz znakov kot vrednost, ki si jo želite ogledati. Če je vrednost podatkov v spremenljivki, imenovani argc, lahko pokličete printData z naslednjimi parametri.

printData ((char*) "argc =", argc);

Če imate kakršna koli vprašanja, pustite komentar in z veseljem vam bom odgovoril.

Veselo kodiranje!

Priporočena: