Sadržaj:

Idite dalje od standardnih firmi - ponovno posjetite: 5 koraka
Idite dalje od standardnih firmi - ponovno posjetite: 5 koraka
Anonim
Ići dalje od standardnih firmi - ponovno posjetiti
Ići dalje od standardnih firmi - ponovno posjetiti

Nedavno me je kontaktirao dr. Martyn Wheeler, korisnik pymata4, radi smjernica u dodavanju podrške za DHT22 senzor vlažnosti/temperature u biblioteku pymata4. Biblioteka pymata4, zajedno sa svojim kolegom iz Arduina, FirmataExpress, omogućava korisnicima daljinsko upravljanje i nadgledanje njihovih Arduino uređaja. U nekoliko rundi razmjene e -pošte, dr. Wheeler je uspio izmijeniti pymata4 i FirmataExpress. Kao rezultat toga, podrška za senzore DHT22 i DHT11 sada je standardni dio pymata4 i FirmataExpress.

U svibnju 2014. napisao sam članak o dodavanju podrške Firmati za dodatne uređaje. Razmišljajući o tom članku, shvatio sam koliko se promijenilo otkad sam uzeo olovku za papir za taj članak. Osim ovog članka, dr. Wheeler je dokumentirao svoje napore, pa biste možda htjeli provjeriti i to.

FirmataExpress je zasnovan na StandardFirmata, a struktura direktorija StandardFirmata je evoluirala. Osim toga, pymata4 API se također prilično razlikuje od originalnog PyMata API -a iz 2014. Mislio sam da bi ovo bilo savršeno vrijeme za ponovni posjet i ažuriranje tog članka. Koristeći rad dr. Wheelera kao osnovu, istražimo kako proširiti funkcionalnost pymata4/FirmataExpress.

Prije nego što počnemo - neke osnovne informacije o Arduinu/Firmati

Pa šta je Firmata? Citirajući sa web stranice Firmata, "Firmata je generički protokol za komunikaciju sa mikrokontrolerima iz softvera na računaru domaćinu."

Arduino Firmata koristi serijsko sučelje za prijenos i komandnih i izvještajnih podataka između Arduino mikrokontrolera i računala, obično koristeći serijsku/USB vezu postavljenu na 57600 bps. Podaci koji se prenose preko ove veze su binarni, a protokol je implementiran u klijent/poslužiteljski model.

Strana servera je učitana na Arduino mikrokontroler u obliku Arduino skice. Skica StandardFirmata, uključena u Arduino IDE, kontrolira Arduino I/O pinove, prema nalogu klijenta. On također izvještava klijenta o promjenama ulaznog pina i drugim informacijama o izvještaju. FirmataExpress je proširena verzija StandardFirmata. Radi brzinom serijske veze od 115200 bps.

Arduino klijent koji se koristi za ovaj članak je pymata4. To je Python aplikacija koja se izvršava na računaru. Oboje šalje naredbe i prima izvještaje s Arduino servera. Budući da je pymata4 implementiran u Python, radi na Windows, Linux (uključujući Raspberry Pi) i macOS računarima.

Zašto koristiti Firmatu?

Arduino mikrokontroleri su divni mali uređaji, ali procesorski i memorijski resursi donekle su ograničeni. Za aplikacije koje zahtijevaju procesore ili memoriju često nema drugog izbora nego prenijeti zahtjev za resursima na računalo kako bi aplikacija bila uspješna.

Ali to nije jedini razlog korištenja StandardFirmata. Prilikom razvoja lakših Arduino aplikacija, računalo može pružiti alate i mogućnosti otklanjanja pogrešaka koji nisu izravno dostupni na Arduino mikrokontroleru. Korištenje "fiksnog" klijenta i poslužitelja pomaže ograničiti složenost aplikacije na računalo, kojim se lakše upravlja. Nakon što se aplikacija usavrši, može se prevesti u prilagođenu, samostalnu Arduino skicu.

Zašto koristiti pymata4?

Kao njen autor, naravno, pristrasan sam. S obzirom na to, to je jedini Pyram-bazirani Firmata klijent koji se kontinuirano održava posljednjih nekoliko godina. Pruža intuitivan i jednostavan za korištenje API. Osim skica zasnovanih na StandardFirmati, podržava Firmata preko WiFi-a za uređaje poput ESP-8266 kada se koristi skica StandardFirmataWifI.

Također, pymata4 je dizajniran tako da ga korisnik može lako proširiti za podršku dodatnih senzora i aktuatora koje trenutno ne podržava StandardFirmata.

Korak 1: Razumijevanje Firmata protokola

Razumevanje Firmata protokola
Razumevanje Firmata protokola

Arduino Firmata komunikacijski protokol izveden je iz MIDI protokola, koji koristi jedan ili više 7-bitnih bajtova za predstavljanje podataka.

Firmata je dizajnirana tako da se može proširiti na korisnika. Mehanizam koji omogućava ovu proširivost je protokol za razmjenu poruka System Exclusive (SysEx).

Format poruke SysEx, definiran protokolom Firmata, prikazan je na gornjoj ilustraciji. Počinje s START_SYSEX bajtom s fiksnom vrijednošću heksadecimalnog 0xF0, a nakon njega slijedi jedinstveni bajt naredbe SysEx. Vrijednost naredbenog bajta mora biti u rasponu heksadecimalnog 0x00-0x7F. Nakon naredbenog bajta slijedi neodređen broj 7-bitnih bajtova podataka. Konačno, poruka se završava s END_SYSEX bajtom, s fiksnom vrijednošću heksadecimalnog 0xF7.

Firmata kodiranje/dekodiranje podataka

Budući da se dio korisničkih podataka SysEx poruke sastoji od niza 7-bitnih bajtova, možda ćete se zapitati kako jedan predstavlja vrijednost veću od 128 (0x7f)? Firmata kodira te vrijednosti rastavljajući ih na više 7-bitnih dijelova bajtova prije nego što se podaci razmjeste preko podatkovne veze. Najprije se šalje najmanje značajan bajt (LSB) stavke podataka, a zatim slijede sve značajnije komponente stavke podataka prema konvenciji. Najvažniji bajt (MSB) stavke podataka je posljednja poslata stavka podataka.

Kako ovo funkcionira?

Recimo da želimo uključiti vrijednost 525 u dio podataka SysEx poruke. Budući da je vrijednost 525 očito veća od vrijednosti 128, moramo je podijeliti ili rastaviti na 7-bitne "komade" bajtova.

Evo kako se to radi.

Vrijednost 525 u decimalnom zapisu ekvivalentna je heksadecimalnoj vrijednosti 0x20D, vrijednosti od 2 bajta. Da bismo dobili LSB, maskiramo vrijednost AND pomoću "0x7F". I "C" i Python implementacije su prikazane ispod:

// "C" implementacija za izolaciju LSB -a

int max_distance_LSB = max_distance & 0x7f; // maskiranje donjeg bajta # Python implementacija za izolaciju LSB max_distance_LSB = max_distance & 0x7F # maska donjeg bajta

Nakon maskiranja, max_distance_LSB će sadržavati 0x0d. 0x20D & 0x7F = 0x0D.

Zatim moramo izolirati MSB za ovu 2-bajtnu vrijednost. Da bismo to učinili, pomjerit ćemo vrijednost 0x20D udesno, za 7 mjesta.

// "C" implementacija za izolaciju MSB -a od 2 bajta

int max_distance_MSB = max_distanca >> 7; // prebacivanje bajta visokog reda # Python implementacija za izolaciju MSB -a od 2 bajta max_distance_MSB = max_distance >> 7 # shift za dobivanje gornjeg bajta Nakon premještanja, max_distance_MSB će sadržavati vrijednost 0x04.

Kad se dobiju "zrnasti" raspoređeni podaci, potrebno ih je ponovno sastaviti u jednu vrijednost. Evo kako se podaci ponovo sastavljaju u "C" i Pythonu

// "C" implementacija za ponovno sastavljanje 2 bajta, // 7 bitnih vrijednosti u jednu vrijednost int max_distance = argv [0] + (argv [1] << 7); # Python implementacija za ponovno sastavljanje 2 -bajtnih, # 7 -bitnih vrijednosti u jednu vrijednost max_distance = data [0] + (data [1] << 7)

Nakon ponovnog sastavljanja, vrijednost je opet jednaka 525 decimalnih ili 0x20D heksadecimalnih.

Ovaj proces rastavljanja/ponovnog sastavljanja može izvesti klijent ili server.

Korak 2: Počnimo

Podrška novog uređaja zahtijeva promjene i na Arduino rezidentnom serveru i na rezidentnom Python klijentu. Rad dr. Wheelera će se koristiti za ilustraciju neophodnih izmjena.

Možda je najvažniji korak odlučiti želite li integrirati postojeću biblioteku podržanih uređaja u Arduino stranu jednadžbe ili napisati vlastitu. Preporučuje se da je, ako pronađete postojeću biblioteku, daleko jednostavnije koristiti nego pisati vlastitu od nule.

Za podršku DHT uređaja, dr. Wheeler je svoj kod proširenja zasnovao na biblioteci DHTNew. Vrlo pametno, dr. Wheeler je podijelio funkcionalnost DHTNew biblioteke na Arduino i pymata4 strane jednadžbe kako bi osigurao minimalno blokiranje na Arduino strani.

Ako pogledamo DHTNew, on izvodi sve sljedeće:

  • Postavlja odabrani pin način digitalnog izlaza.
  • Sat kodira signal za dohvaćanje najnovijih vrijednosti vlažnosti i temperature.
  • Provjerava i prijavljuje sve greške.
  • Izračunava vrijednosti temperature i vlažnosti koje čitaju ljudi iz preuzetih sirovih podataka.

Kako bi stvari bile što efikasnije na strani FirmataExpress -a, dr. Wheeler je izbacio rutinu pretvorbe podataka s Arduina na pymata4.

Korak 3: Izmjena FirmataExpress -a za DHT podršku

Stablo direktorija FirmataExpress

Ispod su sve datoteke koje sadrže spremište FirmataExpress. Ovo stablo je identično onom u StandardFiramata, samo što neki od naziva datoteka odražavaju naziv spremišta.

Datoteke koje je potrebno izmijeniti su one koje imaju zvjezdicu (*) pored sebe.

FirmataExpress

├── * Boards.h

├── primjeri

│ └── FirmataExpress

│ ├── boardx

│ ├── * FirmataExpress.ino

│ ├── LICENSE.txt

│ └── Makefile

├── * FirmataConstants.h

├── * FirmataDefines.h

├── FirmataExpress.cpp

├── FirmataExpress.h

├── FirmataMarshaller.cpp

├── FirmataMarshaller.h

├── FirmataParser.cpp

└── FirmataParser.h

Pogledajmo svaku datoteku i promjene koje su napravljene.

Boards.h

Ova datoteka sadrži pin definicije makroa za svaki od podržanih tipova ploča. Definira najveći broj podržanih uređaja kada je potrebno podržati više uređaja.

Za DHT uređaj, do 6 uređaja može biti povezano odjednom i ova vrijednost je definirana kao:

#ifndef MAX_DHTS

#define MAX_DHTS 6 #endif

Također, makroi tipa pin mogu se opcionalno definirati za novi uređaj, bilo za sve tipove ploča ili samo za one koji vas zanimaju. Ovi makroi se uglavnom koriste za izvještavanje i ne koriste se za kontrolu uređaja. Ovi makroi definiraju oba pina koji podržavaju uređaj:

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

Kao i makro za definiranje konverzije pin broja.

#define PIN_TO_DHT (p) PIN_TO_DIGITAL (p)

FirmataConstants.h

Ova datoteka sadrži broj verzije firmvera, koji biste možda htjeli izmijeniti kako biste pratili koju ste verziju učitali na svoj Arduino. Sadrži i vrijednosti poruka Firmata, uključujući poruke Firmata SysEx.

Morate dodijeliti novu poruku ili skup poruka za svoj uređaj u ovoj datoteci. Za DHT su dodane dvije poruke. Jedan konfiguriše pin kao „DHT“pin, a drugi kao reportersku poruku kada šalje najnovije DHT podatke nazad klijentu.

static const int DHT_CONFIG = 0x64;

static const int DHT_DATA = 0x65;

Načini pin -a su takođe navedeni u ovoj datoteci. Za DHT je stvoren novi pin način:

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

Prilikom dodavanja novog pin načina, TOTAL_PIN_MODES se mora prilagoditi:

static const int TOTAL_PIN_MODES = 17;

FirmataDefines.h

Ova datoteka se mora ažurirati kako bi odražavala nove poruke dodane na FirmataConstants.h:

#ifdef DHT_CONFIG #undef DHT_CONFIG #endif #define DHT_CONFIG firmata:: DHT_CONFIG // DHT zahtev #ifdef DHT_DATA #undef DHT_DATA #endif #define DHT_DATA firmata:: DHT_DATA // DHT odgovor:: PIN_MODE_DHT

FirmataExpress.ino

U ovoj raspravi pokriti ćemo „vrhunce“promjena napravljenih na ovoj Arduino skici.

Kako bi FirmataExpress podržavao do šest DHT uređaja istovremeno, stvorena su 3 niza za praćenje svakog od PIN -ova povezanog uređaja, njegove vrijednosti WakeUpDelay i vrste uređaja, to je DHT22 ili DHT11:

// DHT senzori

int numActiveDHTs = 0; // broj DHT -ova uint8_t DHT_PinNumbers [MAX_DHTS]; uint8_t DHT_WakeUpDelay [MAX_DHTS]; uint8_t DHT_TYPE [MAX_DHTS];

Budući da oba tipa uređaja zahtijevaju približno 2 sekunde između čitanja, moramo se pobrinuti da svaki DHT očitamo samo jednom u vremenskom okviru od 2 sekunde. Nekim uređajima, poput DHT uređaja i senzora udaljenosti HC-SR04, pristupa se samo povremeno. To im daje vremena za interakciju sa svojim okruženjem.

uint8_t nextDHT = 0; // indeksira u dht za sljedeći uređaj za čitanje

uint8_t currentDHT = 0; // Prati koji je senzor aktivan. int dhtNumLoops = 0; // Ciljani broj puta kroz petlju b4 koji pristupa DHT -u int dhtLoopCounter = 0; // Brojač petlji

Konfiguriranje i čitanje DHT uređaja

Kada FirmataExpress primi naredbu SysEx za konfiguriranje pina za DHT rad, provjerava da nije premašen maksimalni broj DHT uređaja. Ako se može podržati novi DHT, DHT nizovi se ažuriraju. Ako tip DHT -a nije poznat, kreira se poruka u nizu SysEx -a i šalje natrag na pymata4

slučaj DHT_CONFIG: int DHT_Pin = argv [0]; int DHT_type = argv [1]; if (numActiveDHTs <MAX_DHTS) {if (DHT_type == 22) {DHT_WakeUpDelay [numActiveDHTs] = 1; } else if (DHT_type == 11) {DHT_WakeUpDelay [numActiveDHTs] = 18; } else {Firmata.sendString ("GREŠKA: NEPOZNATI TIP SENZORA, VAŽNI SENZORI SU 11, 22"); break; } // testiranje senzora DHT_PinNumbers [numActiveDHTs] = DHT_Pin; DHT_TYPE [numActiveDHTs] = DHT_tip; setPinModeCallback (DHT_Pin, PIN_MODE_DHT);

FirmataExpress zatim pokušava komunicirati s DHT uređajem. Ako postoje greške, on formira SysEx poruku s podacima o grešci i šalje poruku SysEx natrag na pymat4. Varijabla _bits sadrži podatke koje vraća DHT uređaj za dodatnu obradu od strane pymata4 ako to želi.

Firmata.write (START_SYSEX);

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

Ako se vrate valjani podaci, broj aktivnih DHT -ova se povećava. Također se prilagođava varijabla koja prati koliko iteracija petlje treba dovršiti prije provjere sljedećeg DHT -a za podatke. Ova varijabla osigurava da će se, bez obzira na to koliko DHT -a dodano sistemu, sve pročitati u roku od 2 sekunde.

int rv = readDhtSensor (numActiveDHTs);

if (rv == DHTLIB_OK) {numActiveDHTs ++; dhtNumLoops = dhtNumLoops / numActiveDHTs; // sve u redu}

Ako je jedan ili više DHT uređaja konfigurirano u funkciji petlje skice, tada se čita sljedeći DHT uređaj. Ili se važeći podaci ili njihov status greške vraćaju na pymata4 u obliku poruke SysEx:

if (dhtLoopCounter ++> dhtNumLoops) {if (numActiveDHTs) {int rv = readDhtSensor (nextDHT); uint8_t current_pin = DHT_PinBrojevi [nextDHT]; uint8_t current_type = DHT_TYPE [nextDHT]; dhtLoopCounter = 0; currentDHT = nextDHT; 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]! = zbir) {rv = -1; }} // šalje poruku nazad sa statusom greške 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);}}

Kôd koji se koristi za komunikaciju s DHT uređajem izveden je izravno iz biblioteke DHTNew:

int readDhtSensor (int indeks) {

// INIT BUFFERVAR ZA PRIMANJE PODATAKA uint8_t mask = 128; uint8_t idx = 0; // PRAZNI BUFER // memset (_bits, 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) vrati DHTLIB_ERROR_TIMEOUT;} if ((micros ()-t)> 40) {_bits [idx] | = mask;} mask >> = 1; if (mask == 0) // sljedeći bajt? {Mask = 128; idx ++;}} vrati DHTLIB_OK;}

Korak 4: Izmjena Pymata4 za DHT podršku

private_constants.h

Da bismo podržali DHT, ovoj datoteci moramo dodati i nove pin-type i SysEx poruke:

# pin načina INPUT = 0x00 # pin je postavljen kao ulaz OUTPUT = 0x01 # pin je postavljen kao izlaz ANALOG = 0x02 # analogni pin u analognom modu Ulaz PWM = 0x03 # digitalni pin u modu PWM izlaza SERVO = 0x04 # digitalni pin u načinu Servo izlaza I2C = 0x06 # pin uključen u I2C postavljanje STEPPER = 0x08 # bilo koji pin u stepper modu SERIAL = 0x0a PULLUP = 0x0b # Bilo koji pin u pullup modu SONAR = 0x0c # Bilo koji pin u SONAR modu TONE = 0x0d # Bilo koji pin u tonskom načinu rada PIXY = 0x0e # rezervirano za način rada pixy kamere DHT = 0x0f # DHT senzor IGNORE = 0x7f # Poruke naredbe DHT SysEx DHT_CONFIG = 0x64 # dht config naredba DHT_DATA = 0x65 # dht odgovor senzora

Dodani tip pina i naredbe SysEx moraju odgovarati vrijednostima u FirmataConstants.h dodane u FirmataExpress.

pymata4.py

Pymata4 koristi Python rječnik za brzo povezivanje dolazne Firmata poruke s rukovaocem porukama. Naziv ovog rječnika je report_dispatch.

Format unosa u rječniku je:

{MessageID: [message_handler, broj bajtova podataka za obradu]}

U rječnik je dodan unos za obradu dolaznih DHT poruka:

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

7 bajta podataka u poruci su Arduino broj digitalnog pina, tip DHT uređaja (22 ili 11) i 5 bajtova neobrađenih podataka.

Metoda _dht_read_response provjerava ima li prijavljenih grešaka. Ako nema prijavljenih grešaka, vlažnost i temperatura se izračunavaju pomoću algoritma prenesenog iz Arduino DHTNew biblioteke.

Izračunate vrijednosti se prijavljuju putem metode povratnog poziva koju je dostavio korisnik. Oni su također pohranjeni u internoj strukturi podataka pin_data. Zadnja prijavljena vrijednost može se opozvati anketiranjem pin_data metodom dht_read.

Konfiguriranje novog DHT uređaja

Prilikom dodavanja novog DHT uređaja poziva se metoda set_pin_mode_dht. Ova metoda ažurira pin_data za digitalne pinove. Također stvara i šalje DHT_CONFIG SysEx poruku na FirmataExpress.

Korak 5: Zaključak

Kao što smo vidjeli, dodavanje Firmata podrške za novi uređaj zahtijeva od vas da promijenite Arduino FirmataExpress poslužiteljski kod i Pyman-bazirani kod klijenta pymata4. Otklanjanje grešaka u FirmataExpress kodu može biti izazovno. Metoda zvana printData dodana je FirmataExpressu radi lakšeg otklanjanja grešaka. Ova metoda vam omogućuje slanje vrijednosti podataka s FirmataExpress -a i ispisuje ih na konzoli pymata4.

Ova funkcija zahtijeva i pokazivač na niz znakova i vrijednost koju želite vidjeti. Ako je vrijednost podataka sadržana u varijabli koja se zove argc, možete pozvati printData sa sljedećim parametrima.

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

Ako imate bilo kakvih pitanja, ostavite komentar, a ja ću vam rado odgovoriti.

Sretno kodiranje!

Preporučuje se: