Indholdsfortegnelse:

Going Beyond Standard Firmata - Revideret: 5 trin
Going Beyond Standard Firmata - Revideret: 5 trin

Video: Going Beyond Standard Firmata - Revideret: 5 trin

Video: Going Beyond Standard Firmata - Revideret: 5 trin
Video: Как устроена IT-столица мира / Russian Silicon Valley (English subs) 2024, Juli
Anonim
Going Beyond Standard Firmata - Revideret
Going Beyond Standard Firmata - Revideret

For kort tid siden blev jeg kontaktet af Dr. Martyn Wheeler, en pymata4 -bruger, for at få vejledning i tilføjelse af understøttelse af DHT22 fugtigheds-/temperatursensor til pymata4 -biblioteket. Pymata4 -biblioteket, sammen med dets Arduino -modstykke, FirmataExpress, giver brugerne mulighed for at styre og overvåge deres Arduino -enheder eksternt. Inden for et par runder med e -mail -udvekslinger havde Dr. Wheeler succes med at ændre både pymata4 og FirmataExpress. Som et resultat er understøttelse af DHT22- og DHT11 -sensorerne nu en standard del af pymata4 og FirmataExpress.

I maj 2014 skrev jeg en artikel om tilføjelse af support til Firmata til yderligere enheder. Når jeg reflekterede over den artikel, indså jeg, hvor meget der har ændret sig, siden jeg tog pen til papir for den artikel. Ud over denne artikel dokumenterede Dr. Wheeler sin indsats, og du vil måske også tjekke det ud.

FirmataExpress er baseret på StandardFirmata, og StandardFirmata -biblioteksstrukturen har udviklet sig. Derudover er pymata4 API også en hel del anderledes end den oprindelige PyMata API fra 2014. Jeg tænkte, at dette ville være det perfekte tidspunkt at genbesøge og opdatere den artikel. Lad os undersøge, hvordan vi kan udvide pymata4/FirmataExpress -funktionaliteten ved hjælp af Dr. Wheelers arbejde som grundlag.

Inden vi begynder - Nogle baggrundsoplysninger om Arduino/Firmata

Så hvad er Firmata? Citeret fra Firmata -websiden, "Firmata er en generisk protokol til kommunikation med mikrokontrollere fra software på en værtscomputer."

Arduino Firmata bruger en seriel grænseflade til at transportere både kommando- og rapporteringsoplysninger mellem en Arduino -mikrokontroller og en pc, typisk ved hjælp af et serielt/USB -link indstillet til 57600 bps. De data, der overføres på tværs af dette link, er binære, og protokollen er implementeret i en klient/server -model.

Serversiden uploades til en Arduino -mikrokontroller i form af en Arduino -skitse. StandardFirmata -skitsen, der følger med Arduino IDE, styrer Arduino I/O -benene, som kommandoen befalder. Det rapporterer også input pin ændringer og andre rapport oplysninger tilbage til klienten. FirmataExpress er en udvidet version af StandardFirmata. Den kører med en seriel linkhastighed på 115200 bps.

Arduino -klienten, der bruges til denne artikel, er pymata4. Det er et Python -program, der udføres på en pc. Det både sender kommandoer til og modtager rapporter fra Arduino -serveren. Fordi pymata4 er implementeret i Python, kører det på Windows, Linux (herunder Raspberry Pi) og macOS -computere.

Hvorfor bruge Firmata?

Arduino mikrokontrollere er vidunderlige små enheder, men processor- og hukommelsesressourcer er noget begrænsede. For applikationer, der er processor- eller hukommelseskrævende, er der ofte lidt andet valg end at aflaste ressourcebehovet til en pc, for at applikationen kan lykkes.

Men det er ikke den eneste grund til at bruge StandardFirmata. Ved udvikling af lettere Arduino -applikationer kan en pc levere værktøjer og fejlfindingsfunktioner, der ikke er direkte tilgængelige på en Arduino -mikrokontroller. Brug af en "fast" klient og server hjælper med at begrænse applikationskompleksiteten til en pc, der lettere administreres. Når applikationen er perfektioneret, kan den oversættes til en brugerdefineret, selvstændig Arduino -skitse.

Hvorfor bruge pymata4?

Som forfatter er jeg selvfølgelig forudindtaget. Når det er sagt, er det den eneste Python-baserede Firmata-klient, der er blevet vedligeholdt løbende i løbet af de sidste mange år. Det giver en intuitiv og brugervenlig API. Ud over StandardFirmata-baserede skitser understøtter den Firmata over WiFi for enheder som ESP-8266, når du bruger StandardFirmataWifI-skitsen.

Pymata4 blev også designet til let at kunne udvides af en bruger til at understøtte yderligere sensorer og aktuatorer, der ikke i øjeblikket understøttes af StandardFirmata.

Trin 1: Forståelse af Firmata -protokollen

Forståelse af Firmata -protokollen
Forståelse af Firmata -protokollen

Arduino Firmata-kommunikationsprotokollen er afledt af MIDI-protokollen, der bruger en eller flere 7-bit bytes til at repræsentere data.

Firmata er designet til at være brugerudvidelig. Mekanismen, der giver denne udvidelse, er meddelelsesprotokollen System Exclusive (SysEx).

Formatet på en SysEx -besked, som defineret af Firmata -protokollen, er vist i illustrationen ovenfor. Det begynder med en START_SYSEX -byte med en fast værdi på hexadecimal 0xF0 og efterfølges af en unik SysEx -kommandobyte. Værdien af kommandobyten skal være i området hexadecimal 0x00-0x7F. Kommandobyten efterfølges derefter af et uspecificeret antal 7-bit databyte. Endelig afsluttes meddelelsen med en END_SYSEX -byte med en fast værdi på hexadecimal 0xF7.

Firmata Data Encoding/Decoding

Da brugerdatadelen af en SysEx-besked består af en række 7-bit bytes, kan du undre dig over, hvordan man repræsenterer en værdi større end 128 (0x7f)? Firmata koder for disse værdier ved at adskille dem i flere 7-bit byte-klumper, før dataene marcheres på tværs af dataforbindelsen. Den mindst signifikante byte (LSB) for et datapost sendes først, efterfulgt af stadig større komponenter i dataposten efter konvention. Den væsentligste byte (MSB) for dataelementet er det sidste datapost, der blev sendt.

Hvordan virker det?

Lad os sige, at vi ønsker at inkorporere en værdi 525 i datadelen af en SysEx -besked. Da en værdi på 525 klart er større end en værdi på 128, skal vi opdele eller adskille den i 7-bit byte "klumper".

Sådan gøres det.

Værdien på 525 i decimal svarer til den hexadecimale værdi på 0x20D, en 2-byte værdi. For at få LSB maskerer vi værdien ved at AND'e den med 0x7F. Både "C" og Python -implementeringer er vist nedenfor:

// "C" -implementering for at isolere LSB

int max_distance_LSB = max_distance & 0x7f; // masker den lavere byte # Python -implementering for at isolere LSB max_distance_LSB = max_distance & 0x7F # maskere den lavere byte

Efter maskering indeholder max_distance_LSB 0x0d. 0x20D & 0x7F = 0x0D.

Dernæst skal vi isolere MSB for denne 2-byte værdi. For at gøre dette vil vi flytte værdien af 0x20D til højre, 7 steder.

// "C" implementering for at isolere MSB med 2 byte værdi

int max_distance_MSB = max_distance >> 7; // skift den høje orden byte # Python -implementering for at isolere MSB med 2 byte værdi max_distance_MSB = max_distance >> 7 # shift for at få den øvre byte Efter skift vil max_distance_MSB indeholde en værdi på 0x04.

Når de "chunkified" marshaled -data modtages, skal de samles igen til en enkelt værdi. Her er hvordan dataene samles igen i både "C" og Python

// "C" -implementering til at samle de 2 byte, // 7 bit værdier i en enkelt værdi int max_distance = argv [0] + (argv [1] << 7); # Python -implementering for at samle de 2 byte, # 7 bitværdier til en enkelt værdi max_distance = data [0] + (data [1] << 7)

Efter genmontering er værdien igen lig med 525 decimaler eller 0x20D hexadecimal.

Denne adskillelses-/genmonteringsproces kan udføres af enten klienten eller serveren.

Trin 2: Lad os komme i gang

Understøttelse af en ny enhed kræver ændringer af både Arduino resident -serveren og PC -resident Python -klienten. Dr. Wheelers arbejde vil blive brugt til at illustrere de nødvendige ændringer.

Måske er det vigtigste trin at beslutte, om du ønsker at integrere et eksisterende understøttende enhedsbibliotek i Arduino -siden af ligningen eller skrive dit eget. Det anbefales, at hvis du kan finde et eksisterende bibliotek, er det langt enklere at bruge det end at skrive dit eget fra bunden.

Til støtte for DHT -enheder baserede Dr. Wheeler sin udvidelseskode på DHTNew -biblioteket. Meget smart opdelte Dr. Wheeler funktionaliteten af DHTNew -biblioteket på tværs af Arduino- og pymata4 -siderne af ligningen for at give minimal blokering på Arduino -siden.

Hvis vi ser på DHTNew, udfører det alt følgende:

  • Indstiller den valgte pin digitale udgangstilstand.
  • Lokker et kodet signal for at hente de nyeste fugtigheds- og temperaturværdier.
  • Kontrollerer og rapporterer eventuelle fejl.
  • Beregner værdier for temperatur og fugtighed, der kan læses af mennesker fra de rådata, der er hentet.

For at holde tingene så effektive som muligt på FirmataExpress -siden, læssede Dr. Wheeler datakonverteringsrutinerne fra Arduino til pymata4.

Trin 3: Ændring af FirmataExpress til DHT -understøttelse

FirmataExpress -biblioteketræet

Nedenfor er alle de filer, der omfatter FirmataExpress -depotet. Dette træ er identisk med StandardFiramata, bare at nogle af filnavne afspejler depotets navn.

Filerne, der skal ændres, er dem, der har en stjerne (*) ved siden af.

FirmataExpress

├── * Tavler.h

├── eksempler

│ └── FirmataExpress

│ ├── boardx

│ ├── * FirmataExpress.ino

│ ├── LICENS.txt

│ └── Makefile

├── * FirmataConstants.h

├── * FirmataDefines.h

├── FirmataExpress.cpp

├── FirmataExpress.h

├── FirmataMarshaller.cpp

├── FirmataMarshaller.h

├── FirmataParser.cpp

└── FirmataParser.h

Lad os se på hver af filerne og de ændringer, der blev foretaget.

Bestyrelser.h

Denne fil indeholder makrodefinitioner af pin-type for hver af de understøttede korttyper. Det definerer det maksimale antal enheder, der understøttes, når mere end én enhed skal understøttes.

For DHT -enheden kan der tilsluttes op til 6 enheder ad gangen, og denne værdi er defineret som:

#ifndef MAX_DHTS

#define MAX_DHTS 6 #endif

Der kan også valgfrit defineres pin-type makroer til den nye enhed, enten for alle korttyper eller bare dem, der er af interesse for dig. Disse makroer bruges mest til rapporteringsformål og bruges ikke til styring af enhederne. Disse makroer definerer begge stifter, der understøtter enheden:

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

Samt en makro til at definere en pin-nummer konvertering.

#define PIN_TO_DHT (p) PIN_TO_DIGITAL (p)

FirmataConstants.h

Denne fil indeholder firmwareversionsnummeret, som du måske ønsker at ændre for at holde styr på, hvilken version du har indlæst på din Arduino. Den indeholder også Firmata -meddelelsesværdier, herunder Firmata SysEx -meddelelser.

Du skal tildele en ny besked eller et sæt meddelelser til din enhed i denne fil. For DHT blev der tilføjet to meddelelser. Den ene konfigurerer en nål som en “DHT” -nål, og den anden, som en reporterbesked, når de nyeste DHT -data sendes tilbage til klienten.

statisk const int DHT_CONFIG = 0x64;

statisk const int DHT_DATA = 0x65;

Pin -tilstande er også angivet i denne fil. Til DHT blev der oprettet en ny pin -tilstand:

statisk const int PIN_MODE_DHT = 0x0F; // pin konfigureret til DHT

Når du tilføjer en ny pin -tilstand, skal TOTAL_PIN_MODES justeres:

statisk const int TOTAL_PIN_MODES = 17;

FirmataDefines.h

Denne fil skal opdateres for at afspejle de nye meddelelser, der er føjet til FirmataConstants.h:

#ifdef DHT_CONFIG # undef DHT_CONFIG #endif #define DHT_CONFIG firmata:: DHT_CONFIG // DHT anmodning #ifdef DHT_DATA #undef DHT_DATA #endif #define DHT_DATA firmata:: DHT_DATA // DHT besvare #ifdef PIN_MODE_DHT #undef PIN_MODE_DHT #endif #define PIN_MODE_DHT firmata:: PIN_MODE_DHT

FirmataExpress.ino

I denne diskussion vil vi dække "højdepunkterne" i de ændringer, der er foretaget i denne Arduino-skitse.

For at FirmataExpress kunne understøtte op til seks DHT -enheder samtidigt, blev der oprettet 3 arrays for at holde styr på hver af enhedens tilhørende pin -nummer, dens WakeUpDelay -værdi og enhedstypen, det vil sige DHT22 eller DHT11:

// DHT -sensorer

int numActiveDHTs = 0; // antal vedhæftede DHT'er uint8_t DHT_PinNumbers [MAX_DHTS]; uint8_t DHT_WakeUpDelay [MAX_DHTS]; uint8_t DHT_TYPE [MAX_DHTS];

Fordi begge enhedstyper kræver cirka 2 sekunder mellem læsninger, skal vi sørge for, at vi kun læser hver DHT én gang i tidsrammen på 2 sekunder. Nogle enheder, f.eks. DHT-enheder og HC-SR04-afstandssensorer, er kun tilgængelige periodisk. Dette giver dem tid til at interagere med deres omgivelser.

uint8_t nextDHT = 0; // indekser i dht for næste enhed, der skal læses

uint8_t currentDHT = 0; // Holder styr på hvilken sensor der er aktiv. int dhtNumLoops = 0; // Mål antal gange gennem loop b4, der får adgang til en DHT int dhtLoopCounter = 0; // Sløjfe tæller

Konfiguration og læsning af DHT -enheden

Når FirmataExpress modtager en SysEx -kommando for at konfigurere en pin til DHT -drift, bekræfter den, at det maksimale antal DHT -enheder ikke er overskredet. Hvis den nye DHT kan understøttes, opdateres DHT -arrays. Hvis DHT -typen er ukendt, oprettes en SysEx -strengmeddelelse og sendes tilbage til pymata4

sag DHT_CONFIG: int DHT_Pin = argv [0]; int DHT_type = argv [1]; if (numActiveDHTs <MAX_DHTS) {if (DHT_type == 22) {DHT_WakeUpDelay [numActiveDHTs] = 1; } ellers hvis (DHT_type == 11) {DHT_WakeUpDelay [numActiveDHTs] = 18; } else {Firmata.sendString ("FEJL: UKendt SENSORTYPE, Gyldige sensorer ER 11, 22"); pause; } // test sensoren DHT_PinNumbers [numActiveDHTs] = DHT_Pin; DHT_TYPE [numActiveDHTs] = DHT_type; setPinModeCallback (DHT_Pin, PIN_MODE_DHT);

FirmataExpress forsøger derefter at kommunikere med DHT -enheden. Hvis der er fejl, danner den en SysEx -meddelelse med fejldataene og sender SysEx -meddelelsen tilbage til pymat4. Variablen _bits gemmer de data, der returneres af DHT -enheden til yderligere behandling af pymata4, hvis det ønskes.

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);

Hvis gyldige data returneres, øges antallet af aktive DHT'er. En variabel, der holder styr på, hvor mange loop -iterationer, der skal udføres, inden den næste DHT kontrolleres for data, justeres også. Denne variabel sikrer, at uanset hvor mange DHT'er der føjes til systemet, vil de alle blive læst inden for en periode på 2 sekunder.

int rv = readDhtSensor (numActiveDHTs);

hvis (rv == DHTLIB_OK) {numActiveDHTs ++; dhtNumLoops = dhtNumLoops / numActiveDHTs; // alt i orden}

Hvis en eller flere DHT -enheder er konfigureret i skitsens loop -funktion, læses den næste DHT -enhed. Enten returneres de gyldige data eller dets fejlstatus til pymata4 i form af en SysEx -meddelelse:

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 = næsteDHT; hvis (nextDHT ++> = numActiveDHTs - 1) {nextDHT = 0; } hvis (rv == DHTLIB_OK) {// TEST CHECKSUM uint8_t sum = _bits [0] + _bits [1] + _bits [2] + _bits [3]; hvis (_bits [4]! = sum) {rv = -1; }}} // send beskeden tilbage med en fejlstatus Firmata.write (START_SYSEX); Firmata.write (DHT_DATA); Firmata.write (current_pin); Firmata.write (nuværende_type); 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);}}

Koden, der bruges til at kommunikere med DHT -enheden, stammer direkte fra DHTNew -biblioteket:

int readDhtSensor (int index) {

// INIT BUFFERVAR FOR AT MODTAGE DATA uint8_t mask = 128; uint8_t idx = 0; // TOM BUFFER // 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) returner 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] | = maske;} maske >> = 1; hvis (mask == 0) // næste byte? {Mask = 128; idx ++;}} returner DHTLIB_OK;}

Trin 4: Ændring af Pymata4 til DHT -understøttelse

private_constants.h

For at understøtte DHT skal vi tilføje både den nye pin-type og SysEx-meddelelser til denne fil:

# pin tilstande INPUT = 0x00 # pin indstillet som input OUTPUT = 0x01 # pin indstillet som output ANALOG = 0x02 # analog pin i analog Input mode PWM = 0x03 # digital pin i PWM output mode SERVO = 0x04 # digital pin i Servo output mode I2C = 0x06 # pin inkluderet i I2C opsætning STEPPER = 0x08 # enhver pin i stepper mode SERIAL = 0x0a PULLUP = 0x0b # Enhver pin i pullup mode SONAR = 0x0c # Enhver pin i SONAR mode TONE = 0x0d # Enhver pin i tonefunktion PIXY = 0x0e # forbeholdt pixy kameratilstand DHT = 0x0f # DHT sensor IGNORE = 0x7f # DHT SysEx kommandobeskeder DHT_CONFIG = 0x64 # dht config kommando DHT_DATA = 0x65 # dht sensor svar

Den tilføjede pin -type og SysEx -kommandoer skal matche værdierne i FirmataConstants.h tilføjet til FirmataExpress.

pymata4.py

Pymata4 bruger en Python -ordbog til hurtigt at forbinde en indgående Firmata -besked med en beskedhåndterer. Navnet på denne ordbog er report_dispatch.

Formatet for en ordbogspost er:

{MessageID: [message_handler, antal databyte, der skal behandles]}

En post blev tilføjet til ordbogen for at håndtere indgående DHT -meddelelser:

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

De 7 byte data i meddelelsen er Arduino digitalt pin -nummer, typen af DHT -enhed (22 eller 11) og de 5 bytes rådata.

Metoden _dht_read_response kontrollerer eventuelle rapporterede fejl. Hvis der ikke er rapporterede fejl, beregnes luftfugtighed og temperatur ved hjælp af algoritmen, der sendes fra Arduino DHTNew -biblioteket.

De beregnede værdier rapporteres via en brugerleveret tilbagekaldsmetode. De gemmes også i den interne pin_data datastruktur. Den sidste rapporterede værdi kan blive tilbagekaldt ved at afstemme pin_data ved hjælp af dht_read -metoden.

Konfiguration af en ny DHT -enhed

Når du tilføjer en ny DHT -enhed, kaldes metoden set_pin_mode_dht. Denne metode opdaterer pin_data for digitale pins. Det opretter og sender også en DHT_CONFIG SysEx -besked til FirmataExpress.

Trin 5: Indpakning

Som vi har set, kræver tilføjelse af Firmata-understøttelse til en ny enhed, at du ændrer Arduino FirmataExpress-serverkoden og den Python-baserede pymata4-klientkode. FirmataExpress -kode kan være udfordrende at fejlsøge. En metode kaldet printData blev føjet til FirmataExpress for at hjælpe med fejlfinding. Denne metode giver dig mulighed for at sende dataværdier fra FirmataExpress og udskrive dem på pymata4 -konsollen.

Denne funktion kræver både en markør til en tegnstreng og den værdi, du ønsker at se. Hvis dataværdien er indeholdt i en variabel kaldet argc, kan du kalde printData med følgende parametre.

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

Hvis du har spørgsmål, er det bare at efterlade en kommentar, så svarer jeg gerne.

Glad kodning!

Anbefalede: