Cuprins:

Mergi dincolo de StandardFirmata - Revizuit: 5 pași
Mergi dincolo de StandardFirmata - Revizuit: 5 pași

Video: Mergi dincolo de StandardFirmata - Revizuit: 5 pași

Video: Mergi dincolo de StandardFirmata - Revizuit: 5 pași
Video: Part 1 - The Age of Innocence Audiobook by Edith Wharton (Chs 1-9) 2024, Noiembrie
Anonim
Going Beyond StandardFirmata - Revizitat
Going Beyond StandardFirmata - Revizitat

Cu puțin timp în urmă, am fost contactat de Dr. Martyn Wheeler, un utilizator pymata4, pentru îndrumări privind adăugarea suportului pentru senzorul de umiditate / temperatură DHT22 la biblioteca pymata4. Biblioteca pymata4, împreună cu omologul său Arduino, FirmataExpress, permite utilizatorilor să-și controleze și să monitorizeze dispozitivele Arduino de la distanță. În câteva runde de schimburi de e-mail, Dr. Wheeler a reușit să modifice atât pymata4, cât și FirmataExpress. Ca urmare, suportul pentru senzorii DHT22 și DHT11 este acum o parte standard a pymata4 și FirmataExpress.

În mai 2014, am scris un articol despre adăugarea de asistență la Firmata pentru dispozitive suplimentare. Reflectând la acest articol, mi-am dat seama cât de mult s-a schimbat de când am luat pixul pe hârtie pentru acel articol. În plus față de acest articol, Dr. Wheeler și-a documentat eforturile și s-ar putea să doriți să verificați și asta.

FirmataExpress se bazează pe StandardFirmata, iar structura directorului StandardFirmata a evoluat. În plus, API-ul pymata4 este, de asemenea, destul de diferit de API-ul PyMata original din 2014. M-am gândit că acesta ar fi momentul perfect pentru a revizita și actualiza acel articol. Folosind activitatea Dr. Dr. Wheeler ca bază, să explorăm cum să extindem funcționalitatea pymata4 / FirmataExpress.

Înainte de a începe - Câteva informații despre Arduino / Firmata

Deci, ce este Firmata? Citând de pe pagina web Firmata, „Firmata este un protocol generic pentru comunicarea cu microcontrolere din software de pe un computer gazdă.”

Arduino Firmata folosește o interfață serială pentru a transporta atât comanda, cât și raportarea informațiilor între un microcontroler Arduino și un PC, utilizând de obicei o legătură serial / USB setată la 57600 bps. Datele transferate prin acest link sunt binare, iar protocolul este implementat într-un model client / server.

Partea server este încărcată pe un microcontroler Arduino sub forma unei schițe Arduino. Schița StandardFirmata, inclusă cu Arduino IDE, controlează pinii I / O Arduino, așa cum este comandat de client. De asemenea, raportează clientului modificările pinului de intrare și alte informații de raportare. FirmataExpress este o versiune extinsă a StandardFirmata. Acesta rulează la o viteză a legăturii seriale de 115200 bps.

Clientul Arduino utilizat pentru acest articol este pymata4. Este o aplicație Python care este executată pe un PC. Ambele trimit comenzi și primesc rapoarte de la serverul Arduino. Deoarece pymata4 este implementat în Python, acesta rulează pe computerele Windows, Linux (inclusiv Raspberry Pi) și MacOS.

De ce să folosiți Firmata?

Microcontrolerele Arduino sunt mici dispozitive minunate, dar procesorul și resursele de memorie sunt oarecum limitate. Pentru aplicațiile care necesită procesor sau memorie, există adesea puține opțiuni decât să descărcați cererea de resurse pe un PC pentru ca aplicația să aibă succes.

Dar acesta nu este singurul motiv pentru utilizarea StandardFirmata. Atunci când dezvoltați aplicații Arduino cu greutate mai redusă, un PC poate oferi instrumente și capabilități de depanare care nu sunt disponibile direct pe un microcontroler Arduino. Utilizarea unui client și server „fix” ajută la limitarea complexității aplicației la un PC, care este mai ușor de gestionat. Odată ce aplicația este perfecționată, aceasta poate fi tradusă într-o schiță Arduino personalizată, independentă.

De ce să folosiți pymata4?

Fiind autorul său, desigur, sunt părtinitor. Acestea fiind spuse, este singurul client Firmata bazat pe Python care a fost întreținut continuu în ultimii ani. Oferă un API intuitiv și ușor de utilizat. În plus față de schițele bazate pe StandardFirmata, acceptă Firmata prin WiFi pentru dispozitive precum ESP-8266 atunci când se utilizează schița StandardFirmataWifI.

De asemenea, pymata4 a fost proiectat pentru a fi extins cu ușurință de către un utilizator pentru a suporta senzori și actuatori suplimentari care nu sunt în prezent suportați de StandardFirmata.

Pasul 1: Înțelegerea protocolului Firmata

Înțelegerea protocolului Firmata
Înțelegerea protocolului Firmata

Protocolul de comunicații Arduino Firmata este derivat din protocolul MIDI, care utilizează unul sau mai mulți octeți pe 7 biți pentru a reprezenta date.

Firmata a fost conceput pentru a fi extensibil de către utilizator. Mecanismul care asigură această extensibilitate este protocolul de mesagerie System Exclusive (SysEx).

Formatul unui mesaj SysEx, așa cum este definit de Protocolul Firmata, este prezentat în ilustrația de mai sus. Începe cu un octet START_SYSEX cu o valoare fixă de hexazecimal 0xF0 și este urmat de un octet de comandă SysEx unic. Valoarea octetului de comandă trebuie să fie în intervalul hexazecimal 0x00-0x7F. Octetul de comandă este apoi urmat de un număr nespecificat de octeți de date pe 7 biți. În cele din urmă, mesajul este terminat cu un octet END_SYSEX, cu o valoare fixă de hexazecimal 0xF7.

Codificarea / decodarea datelor Firmata

Deoarece porțiunea de date de utilizator a unui mesaj SysEx constă dintr-o serie de octeți pe 7 biți, vă puteți întreba cum reprezintă o valoare mai mare de 128 (0x7f)? Firmata codifică acele valori dezasamblându-le în mai multe bucăți de octeți de 7 biți înainte ca datele să fie reunite pe legătura de date. Cel mai puțin semnificativ octet (LSB) al unui articol de date este trimis mai întâi, urmat de componente din ce în ce mai semnificative ale articolului de date prin convenție. Cel mai semnificativ octet (MSB) al articolului de date este ultimul articol de date trimis.

Cum funcționează asta?

Să presupunem că dorim să încorporăm o valoare 525 în partea de date a unui mesaj SysEx. Deoarece o valoare de 525 este în mod clar mai mare decât o valoare de 128, trebuie să o împărțim sau să o dezasamblăm în „bucăți” de 7 biți de octeți.

Iată cum se face acest lucru.

Valoarea de 525 în zecimal este echivalentă cu valoarea hexazecimală de 0x20D, o valoare de 2 octeți. Pentru a obține LSB, mascăm valoarea prin AND'ing-o cu 0x7F. Atât implementările „C”, cât și implementările Python sunt prezentate mai jos:

// Implementarea „C” pentru izolarea LSB

int max_distance_LSB = max_distance & 0x7f; // mascați octetul inferior # Implementarea Python pentru a izola LSB max_distance_LSB = max_distance & 0x7F # mascați octetul inferior

După mascare, max_distance_LSB va conține 0x0d. 0x20D și 0x7F = 0x0D.

Apoi, trebuie să izolăm MSB pentru această valoare de 2 octeți. Pentru a face acest lucru, vom deplasa valoarea 0x20D spre dreapta, 7 locuri.

// Implementarea „C” pentru a izola MSB cu valoare de 2 octeți

int max_distance_MSB = max_distance >> 7; // comutați octetul de comandă înaltă # Implementarea Python la MSB izolat cu valoare de 2 octeți max_distance_MSB = max_distance >> 7 # shift pentru a obține octetul superior După schimbare, max_distance_MSB va conține o valoare de 0x04.

Când se recepționează datele „blocate”, acestea trebuie reasamblate într-o singură valoare. Iată cum sunt reasamblate datele atât în „C”, cât și în Python

// Implementarea „C” pentru a reasambla cei 2 octeți, // valori de 7 biți într-o singură valoare int max_distance = argv [0] + (argv [1] << 7); # Implementare Python pentru a reasambla valorile de 2 octeți, # 7 biți într-o singură valoare max_distance = data [0] + (data [1] << 7)

După reasamblare, valoarea este din nou egală cu 525 zecimal sau 0x20D hexadecimal.

Acest proces de demontare / reasamblare poate fi realizat fie de client, fie de server.

Pasul 2: Să începem

Suportarea unui dispozitiv nou necesită modificări atât pentru serverul rezident Arduino, cât și pentru clientul Python rezident pe PC. Lucrarea Dr. Wheeler va fi utilizată pentru a ilustra modificările necesare.

Poate cel mai important pas este să decideți dacă doriți să integrați o bibliotecă de dispozitive de suport existentă în partea Arduino a ecuației sau să scrieți propria dvs. Se recomandă ca, dacă puteți găsi o bibliotecă existentă, este mult mai simplu să o folosiți decât să o scrieți de la zero.

Pentru suportul dispozitivului DHT, Dr. Wheeler și-a bazat codul de extensie pe biblioteca DHTNew. Foarte inteligent, Dr. Wheeler a împărțit funcționalitatea bibliotecii DHTNew pe laturile Arduino și pymata4 ale ecuației pentru a oferi o blocare minimă pe partea Arduino.

Dacă ne uităm la DHTNew, acesta efectuează toate următoarele:

  • Setează modul de ieșire digitală pin selectat.
  • Afișează un semnal codat pentru a recupera cele mai recente valori ale umidității și temperaturii.
  • Verifică și raportează orice erori.
  • Calculează valorile citite de om de temperatură și umiditate din datele brute preluate.

Pentru a menține lucrurile cât mai eficiente posibil pe partea FirmataExpress, Dr. Wheeler a descărcat rutinele de conversie a datelor din Arduino în pymata4.

Pasul 3: Modificarea FirmataExpress pentru asistență DHT

Arborele directorului FirmataExpress

Mai jos sunt toate fișierele care cuprind depozitul FirmataExpress. Acest arbore este identic cu cel al StandardFiramata, doar că unele dintre numele fișierelor reflectă numele depozitului.

Fișierele care necesită modificări sunt cele care au lângă ele un asterisc (*).

FirmataExpress

├── * Panouri.h

├── exemple

│ └── FirmataExpress

│ ├── boardx

│ ├── * FirmataExpress.ino

│ ├── LICENȚĂ.txt

│ └── Makefile

├── * FirmataConstants.h

├── * FirmataDefines.h

├── FirmataExpress.cpp

├── FirmataExpress.h

├── FirmataMarshaller.cpp

├── FirmataMarshaller.h

├── FirmataParser.cpp

└── FirmataParser.h

Să analizăm fiecare dintre fișiere și modificările care au fost făcute.

Panouri.h

Acest fișier conține definiții macro de tip pin pentru fiecare dintre tipurile de plăci acceptate. Acesta definește numărul maxim de dispozitive acceptate atunci când mai multe dispozitive trebuie să fie acceptate.

Pentru dispozitivul DHT, pot fi conectate până la 6 dispozitive simultan și această valoare este definită ca:

#ifndef MAX_DHTS

#define MAX_DHTS 6 #endif

De asemenea, macro-urile tip pin pot fi definite opțional pentru noul dispozitiv, fie pentru toate tipurile de plăci, fie doar pentru cele care vă interesează. Aceste macro-uri sunt utilizate în principal în scopuri de raportare și nu sunt utilizate pentru controlul dispozitivelor. Aceste macro-uri definesc atât pinii care acceptă dispozitivul:

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

La fel ca și o macro pentru a defini o conversie PIN.

#define PIN_TO_DHT (p) PIN_TO_DIGITAL (p)

FirmataConstants.h

Acest fișier conține numărul versiunii firmware, pe care ați putea dori să îl modificați pentru a urmări ce versiune ați încărcat pe Arduino. De asemenea, conține valorile mesajelor Firmata, inclusiv mesajele Firmata SysEx.

Va trebui să atribuiți un mesaj nou sau un set de mesaje pentru dispozitivul dvs. din acest fișier. Pentru DHT, au fost adăugate două mesaje. Unul configurează un PIN ca pin „DHT”, iar celălalt, ca mesaj de reporter, atunci când trimiteți cele mai recente date DHT clientului.

static const int DHT_CONFIG = 0x64;

static const int DHT_DATA = 0x65;

Modurile PIN sunt, de asemenea, specificate în acest fișier. Pentru DHT, a fost creat un nou mod pin:

static const int PIN_MODE_DHT = 0x0F; // pin configurat pentru DHT

Când adăugați un nou mod pin, TOTAL_PIN_MODES trebuie ajustat:

static const int TOTAL_PIN_MODES = 17;

FirmataDefines.h

Acest fișier trebuie actualizat pentru a reflecta noile mesaje adăugate la FirmataConstants.h:

#ifdef DHT_CONFIG # undef DHT_CONFIG #endif #define DHT_CONFIG firmata:: DHT_CONFIG // DHT request #ifdef DHT_DATA #undef DHT_DATA #endif #define DHT_DATA firmata:: DHT_DATA // DHT reply #if_DIF_DIF_DIF:: PIN_MODE_DHT

FirmataExpress.ino

În această discuție, vom acoperi „punctele culminante” ale modificărilor aduse acestei schițe Arduino.

Pentru ca FirmataExpress să accepte până la șase dispozitive DHT simultan, au fost create 3 matrici pentru a ține evidența fiecărui număr PIN asociat dispozitivului, valoarea WakeUpDelay și tipul dispozitivului, adică DHT22 sau DHT11:

// Senzori DHT

int numActiveDHTs = 0; // numărul de DHT-uri atașate uint8_t DHT_PinNumbers [MAX_DHTS]; uint8_t DHT_WakeUpDelay [MAX_DHTS]; uint8_t DHT_TYPE [MAX_DHTS];

Deoarece ambele tipuri de dispozitive necesită aproximativ 2 secunde între citiri, trebuie să ne asigurăm că citim fiecare DHT o singură dată în intervalul de timp de 2 secunde. Unele dispozitive, cum ar fi dispozitivele DHT și senzorii de distanță HC-SR04, sunt accesate numai periodic. Acest lucru le permite să interacționeze cu mediile lor.

uint8_t nextDHT = 0; // indexați în dht pentru ca dispozitivul următor să fie citit

uint8_t currentDHT = 0; // Urmărește ce senzor este activ. int dhtNumLoops = 0; // Numărul țintă de ori prin bucla b4 accesând un DHT int dhtLoopCounter = 0; // Contor buclă

Configurarea și citirea dispozitivului DHT

Când FirmataExpress primește o comandă SysEx pentru a configura un pin pentru funcționarea DHT, verifică dacă nu a fost depășit numărul maxim de dispozitive DHT. Dacă noul DHT poate fi acceptat, matricile DHT sunt actualizate. Dacă tipul DHT este necunoscut, se creează un mesaj șir SysEx și se transmite înapoi către pymata4

caz 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 ("EROARE: TIP DE SENZOR NECUNOSCUT, SENZORII VALABILI SUNT 11, 22"); pauză; } // testați senzorul DHT_PinNumbers [numActiveDHTs] = DHT_Pin; DHT_TYPE [numActiveDHTs] = DHT_type; setPinModeCallback (DHT_Pin, PIN_MODE_DHT);

FirmataExpress încearcă apoi să comunice cu dispozitivul DHT. Dacă există erori, acesta formează un mesaj SysEx cu datele de eroare și trimite mesajul SysEx înapoi la pymat4. Variabila _bits conține datele returnate de dispozitivul DHT pentru procesare suplimentară de către pymata4, dacă se dorește.

Firmata.write (START_SYSEX);

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

Dacă se returnează date valide, numărul DHT-urilor active este incrementat. O variabilă care ține evidența numărului de iterații de buclă pentru a finaliza înainte de a verifica următorul DHT pentru date este, de asemenea, ajustată. Această variabilă asigură că, indiferent de câte DHT-uri sunt adăugate la sistem, toate vor fi citite într-o perioadă de 2 secunde.

int rv = readDhtSensor (numActiveDHTs);

if (rv == DHTLIB_OK) {numActiveDHTs ++; dhtNumLoops = dhtNumLoops / numActiveDHTs; // totul este bine }

Dacă unul sau mai multe dispozitive DHT au fost configurate în funcția de buclă a schiței, atunci se citește următorul dispozitiv DHT. Fie datele valide, fie starea erorii sale sunt returnate la pymata4 sub forma unui mesaj 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; 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 (_bits [4]! = sum) {rv = -1; }} // trimite mesajul înapoi cu o stare de eroare Firmata.write (START_SYSEX); Firmata.write (DHT_DATA); Firmata.write (curent_pin); Firmata.write (tip_actual); 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);}}

Codul utilizat pentru a comunica cu dispozitivul DHT este derivat direct din biblioteca DHTNew:

int readDhtSensor (int index) {

// INIȚIAȚI BUFFERVARUL PENTRU PRIMAREA DATELOR uint8_t mask = 128; uint8_t idx = 0; // BUFFER GOL // 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) return DHTLIB_ERROR_TIMEOUT;} if ((micros () - t)> 40) {_bits [idx] | = mask;} mask >> = 1; if (mask == 0) // octet următor? {Mask = 128; idx ++;}} return DHTLIB_OK;}

Pasul 4: Modificarea Pymata4 pentru asistență DHT

private_constants.h

Pentru a suporta DHT, trebuie să adăugăm atât fișierele noi, cât și mesajele SysEx în acest fișier:

# moduri pin INPUT = 0x00 # pin setat ca intrare OUTPUT = 0x01 # pin setat ca ieșire ANALOG = 0x02 # pin analogic în modul de intrare analog PWM = 0x03 # pin digital în modul de ieșire PWM SERVO = 0x04 # pin digital în modul de ieșire servo I2C = 0x06 # pin inclus în configurarea I2C STEPPER = 0x08 # orice pin în modul pas SERIAL = 0x0a PULLUP = 0x0b # Orice pin în modul pullup SONAR = 0x0c # Orice pin în modul SONAR TONE = 0x0d # Orice pin în modul ton PIXY = 0x0e # rezervat pentru modul cameră pixy DHT = 0x0f # senzor DHT IGNORE = 0x7f # mesaje de comandă DHT SysEx DHT_CONFIG = 0x64 # dht config command DHT_DATA = 0x65 # dht răspuns senzor

Tipul de pin adăugat și comenzile SysEx trebuie să corespundă valorilor din FirmataConstants.h adăugate la FirmataExpress.

pymata4.py

Pymata4 folosește un dicționar Python pentru a asocia rapid un mesaj Firmata primit cu un handler de mesaje. Numele acestui dicționar este report_dispatch.

Formatul pentru o intrare în dicționar este:

{MessageID: [message_handler, numărul de octeți de date de procesat]}

O intrare a fost adăugată în dicționar pentru a gestiona mesajele DHT primite:

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

Cei 7 octeți de date din mesaj sunt numărul PIN-ului digital Arduino, tipul dispozitivului DHT (22 sau 11) și cei 5 octeți de date brute.

Metoda _dht_read_response verifică eventualele erori raportate. Dacă nu există erori raportate, umiditatea și temperatura sunt calculate utilizând algoritmul portat din biblioteca Arduino DHTNew.

Valorile calculate sunt raportate printr-o metodă de apelare furnizată de utilizator. Ele sunt, de asemenea, stocate în structura internă de date pin_data. Ultima valoare raportată poate fi reamintită prin sondarea pin_data folosind metoda dht_read.

Configurarea unui nou dispozitiv DHT

Când adăugați un dispozitiv DHT nou, se apelează metoda set_pin_mode_dht. Această metodă actualizează pin_data pentru pinii digitali. De asemenea, creează și trimite un mesaj DHT_CONFIG SysEx către FirmataExpress.

Pasul 5: încheierea

După cum am văzut, adăugarea suportului Firmata pentru un dispozitiv nou necesită modificarea codului serverului Arduino FirmataExpress și a codului client pymata4 bazat pe Python. Codul FirmataExpress poate fi dificil de depanat. O metodă numită printData a fost adăugată la FirmataExpress pentru a ajuta la depanare. Această metodă vă permite să trimiteți valori de date de la FirmataExpress și le va imprima pe consola pymata4.

Această funcție necesită atât un pointer către un șir de caractere, cât și valoarea pe care doriți să o vizualizați. Dacă valoarea datelor este conținută într-o variabilă numită argc, puteți apela printData cu următorii parametri.

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

Dacă aveți întrebări, lăsați un comentariu și vă voi răspunde cu plăcere.

Codificare fericită!

Recomandat: