Taula de continguts:

Més enllà de StandardFirmata: revisió: 5 passos
Més enllà de StandardFirmata: revisió: 5 passos

Vídeo: Més enllà de StandardFirmata: revisió: 5 passos

Vídeo: Més enllà de StandardFirmata: revisió: 5 passos
Vídeo: Сложный случай 😰 Аллергия на гель лак 🤯 Онихолизис ногтей 2024, Desembre
Anonim
Més enllà de StandardFirmata: revisitat
Més enllà de StandardFirmata: revisitat

Fa poc, em vaig contactar amb el Dr. Martyn Wheeler, usuari de pymata4, per obtenir informació sobre com afegir suport per al sensor d’humitat / temperatura DHT22 a la biblioteca pymata4. La biblioteca pymata4, juntament amb el seu homòleg Arduino, FirmataExpress, permet als usuaris controlar i controlar els seus dispositius Arduino de forma remota. En algunes rondes d'intercanvis de correu electrònic, el Dr. Wheeler va tenir èxit en la modificació de pymata4 i FirmataExpress. Com a resultat, el suport per als sensors DHT22 i DHT11 és ara una part estàndard de pymata4 i FirmataExpress.

Al maig de 2014, vaig escriure un article sobre com afegir suport a Firmata per a dispositius addicionals. Reflexionant sobre aquest article, em vaig adonar del molt que ha canviat des que vaig agafar paper a aquest article. A més d’aquest article, el Dr. Wheeler va documentar els seus esforços i és possible que vulgueu comprovar-ho també.

FirmataExpress es basa en StandardFirmata i l’estructura de directoris StandardFirmata ha evolucionat. A més, l’API pymata4 també és força diferent de l’API original PyMata del 2014. Vaig pensar que aquest seria el moment perfecte per revisar i actualitzar aquest article. Utilitzant el treball del doctor Wheeler com a base, explorem com ampliar la funcionalitat de pymata4 / FirmataExpress.

Abans de començar: informació bàsica sobre Arduino / Firmata

Llavors, què és Firmata? Citant des de la pàgina web de Firmata, "Firmata és un protocol genèric per comunicar-se amb microcontroladors des del programari d'un ordinador amfitrió".

Arduino Firmata utilitza una interfície sèrie per transportar informació d’ordres i informes entre un microcontrolador Arduino i un PC, normalment mitjançant un enllaç sèrie / USB establert a 57600 bps. Les dades transferides a través d’aquest enllaç són binàries i el protocol s’implementa en un model client / servidor.

El costat del servidor es carrega a un microcontrolador Arduino en forma d'esbós Arduino. L'esbós StandardFirmata, inclòs amb l'IDE Arduino, controla els pins d'E / S d'Arduino, tal com ho ordena el client. També informa els canvis dels pins d'entrada i altra informació d'informe al client. FirmataExpress és una versió ampliada de StandardFirmata. Funciona a una velocitat d'enllaç sèrie de 115200 bps.

El client Arduino utilitzat per a aquest article és pymata4. És una aplicació Python que s’executa en un PC. Tant envia comandes com rep informes des del servidor Arduino. Com que pymata4 està implementat a Python, s'executa en equips Windows, Linux (inclòs Raspberry Pi) i macOS.

Per què utilitzar Firmata?

Els microcontroladors Arduino són petits dispositius meravellosos, però els recursos de processador i memòria són una mica limitats. Per a les aplicacions que requereixen processador o memòria, sovint hi ha poques opcions que descarregar la demanda de recursos a un PC perquè l’aplicació tingui èxit.

Però aquesta no és l'única raó per utilitzar StandardFirmata. Quan es desenvolupen aplicacions Arduino de menor pes, un PC pot proporcionar eines i funcions de depuració que no estan disponibles directament en un microcontrolador Arduino. L'ús d'un client i un servidor "fixos" ajuda a limitar la complexitat de l'aplicació a un PC, que es gestiona més fàcilment. Un cop s'ha perfeccionat l'aplicació, es pot traduir a un esbós personalitzat i independent d'Arduino.

Per què utilitzar pymata4?

En ser el seu autor, per descomptat, estic tendenciosa. Dit això, és l'únic client Firmata basat en Python que s'ha mantingut contínuament durant els darrers anys. Ofereix una API intuïtiva i fàcil d’utilitzar. A més dels esbossos basats en StandardFirmata, admet Firmata per WiFi per a dispositius com l’ESP-8266 quan s’utilitza l’esbós StandardFirmataWifI.

A més, pymata4 va ser dissenyat per ampliar-lo fàcilment per l'usuari per donar suport a sensors i actuadors addicionals que no són compatibles actualment amb StandardFirmata.

Pas 1: entendre el protocol Firmata

Comprensió del protocol Firmata
Comprensió del protocol Firmata

El protocol de comunicacions Arduino Firmata es deriva del protocol MIDI, que utilitza un o més bytes de 7 bits per representar les dades.

Firmata va ser dissenyat per ser extensible per l'usuari. El mecanisme que proporciona aquesta extensibilitat és el protocol de missatgeria exclusiu del sistema (SysEx).

El format d’un missatge SysEx, tal com el defineix el protocol Firmata, es mostra a la il·lustració anterior. Comença amb un byte START_SYSEX amb un valor fix de 0xF0 hexadecimal i el segueix un byte d’ordre SysEx únic. El valor del byte de l'ordre ha d'estar en l'interval 0x00-0x7F hexadecimal. A continuació, el byte d'ordre segueix un nombre no especificat de bytes de dades de 7 bits. Finalment, el missatge es finalitza amb un byte END_SYSEX, amb un valor fix de 0xF7 hexadecimal.

Codificació / descodificació de dades Firmata

Com que la part de dades de l'usuari d'un missatge SysEx consta d'una sèrie de bytes de 7 bits, us podeu preguntar com es representa un valor superior a 128 (0x7f)? Firmata codifica aquests valors desmuntant-los en diversos trossos de bytes de 7 bits abans que les dades es controlin a través de l'enllaç de dades. El byte menys significatiu (LSB) d’un element de dades s’envia primer, seguit de components cada vegada més significatius del document de dades per convenció. El byte més significatiu (MSB) de l'element de dades és l'últim element de dades enviat.

Com funciona?

Suposem que volem incorporar un valor 525 a la part de dades d’un missatge SysEx. Com que un valor de 525 és clarament superior a un valor de 128, hem de dividir-lo o desmuntar-lo en "trossos" de 7 bits de bytes.

Aquí es fa com es fa això.

El valor de 525 en decimal equival al valor hexadecimal de 0x20D, un valor de 2 bytes. Per obtenir el LSB, emmascarem el valor AND'ing amb 0x7F. A continuació es mostren les implementacions "C" i Python:

// Implementació "C" per aïllar LSB

int max_distance_LSB = max_distance & 0x7f; // emmascarar el byte inferior # Implementació de Python per aïllar LSB max_distance_LSB = max_distance & 0x7F # mascarar el byte inferior

Després de l’emmascarament, max_distance_LSB contindrà 0x0d. 0x20D i 0x7F = 0x0D.

A continuació, hem d’aïllar el MSB d’aquest valor de 2 bytes. Per fer-ho, canviarem el valor de 0x20D cap a la dreta, 7 llocs.

// Implementació "C" per aïllar MSB de valor de 2 bytes

int max_distance_MSB = max_distance >> 7; // canvieu el byte d’ordre alt # Implementació Python a MSB isolat de valor de 2 bytes max_distance_MSB = max_distance >> 7 # shift per obtenir el byte superior Després del canvi, max_distance_MSB contindrà un valor de 0x04.

Quan es reben les dades analitzades "fragmentades", s'han de tornar a muntar en un valor únic. A continuació s'explica com es tornen a muntar les dades tant a "C" com a Python

// Implementació "C" per tornar a muntar els 2 bytes, // Valors de 7 bits en un valor únic int max_distance = argv [0] + (argv [1] << 7); Implementació de # Python per tornar a muntar els valors de 2 bytes de # 7 bits en un sol valor max_distance = data [0] + (data [1] << 7)

Després del muntatge, el valor torna a ser igual a 525 decimal o 0x20D hexadecimal.

Aquest procés de desmuntatge / muntatge el pot realitzar el client o el servidor.

Pas 2: Comencem

El suport d’un nou dispositiu requereix canvis tant al servidor resident d’Arduino com al client Python resident al PC. El treball del Dr. Wheeler s’utilitzarà per il·lustrar les modificacions necessàries.

Potser el pas més important sigui decidir si voleu integrar una biblioteca de dispositius de suport existent al costat de l'equació Arduino o escriure la vostra. Es recomana que, si podeu trobar una biblioteca existent, sigui molt més senzill d’utilitzar-la que escriure la vostra pròpia des de zero.

Per obtenir assistència de dispositius DHT, el Dr. Wheeler va basar el seu codi d’extensió a la biblioteca DHTNew. De forma molt intel·ligent, el Dr. Wheeler va dividir la funcionalitat de la biblioteca DHTNew pels costats Arduino i pymata4 de l’equació per proporcionar un bloqueig mínim al costat Arduino.

Si observem DHTNew, realitza tot el següent:

  • Estableix el mode de sortida digital de pin seleccionat.
  • Rellota un senyal codificat per recuperar els últims valors d’humitat i temperatura.
  • Comprova i informa dels errors.
  • Calcula els valors de temperatura i humitat llegibles per l’home a partir de les dades brutes recuperades.

Per mantenir les coses el més eficients possibles al costat de FirmataExpress, el Dr. Wheeler va descarregar les rutines de conversió de dades de l’Arduino a pymata4.

Pas 3: Modificació de FirmataExpress per a l'assistència de DHT

L’arbre del directori FirmataExpress

A continuació es mostren tots els fitxers que formen el dipòsit FirmataExpress. Aquest arbre és idèntic al de StandardFiramata, només que alguns dels noms de fitxer reflecteixen el nom del dipòsit.

Els fitxers que necessiten modificació són els que tenen un asterisc (*) al costat.

FirmataExpress

├── * Taulers.h

├── exemples

│ └── FirmataExpress

│ ├── boardx

│ ├── * FirmataExpress.ino

│ ├── LLICÈNCIA.txt

│ └── Makefile

├── * FirmataConstants.h

├── * FirmataDefines.h

├── FirmataExpress.cpp

├── FirmataExpress.h

├── FirmataMarshaller.cpp

├── FirmataMarshaller.h

├── FirmataParser.cpp

└── FirmataParser.h

Vegem cadascun dels fitxers i els canvis que es van fer.

Taulers.h

Aquest fitxer conté definicions de macro tipus pin per a cadascun dels tipus de taules compatibles. Defineix el nombre màxim de dispositius admesos quan cal suportar més d'un dispositiu.

Per al dispositiu DHT, es poden connectar fins a 6 dispositius alhora i aquest valor es defineix com:

#ifndef MAX_DHTS

#define MAX_DHTS 6 #endif

A més, les macros tipus pin es poden definir opcionalment per al nou dispositiu, ja sigui per a tots els tipus de taulers o només per als que us interessin. Aquestes macros s'utilitzen principalment amb finalitats d'informes i no s'utilitzen per controlar els dispositius. Aquestes macros defineixen els dos pins que admeten el dispositiu:

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

Així com una macro per definir una conversió de número de pin.

#define PIN_TO_DHT (p) PIN_TO_DIGITAL (p)

FirmataConstants.h

Aquest fitxer conté el número de versió del firmware, que és possible que vulgueu modificar per fer un seguiment de la versió que heu carregat al vostre Arduino. També conté els valors dels missatges de Firmata, inclosos els missatges de Firmata SysEx.

Haureu d'assignar un missatge nou o un conjunt de missatges al vostre dispositiu en aquest fitxer. Per al DHT, es van afegir dos missatges. Un configura un PIN com a PIN "DHT" i l'altre, com a missatge d'un reporter, quan s'envien les dades DHT més recents al client.

static const int DHT_CONFIG = 0x64;

static const int DHT_DATA = 0x65;

Els modes Pin també s’especifiquen en aquest fitxer. Per al DHT, es va crear un nou mode de pin:

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

En afegir un nou mode de pin, cal ajustar els TOTAL_PIN_MODES:

static const int TOTAL_PIN_MODES = 17;

FirmataDefines.h

Aquest fitxer s’ha d’actualitzar per reflectir els nous missatges afegits a FirmataConstants.h:

#ifdef DHT_CONFIG # undef DHT_CONFIG #endif #define DHT_CONFIG firmata:: DHT_CONFIG // Sol·licitud DHT #ifdef DHT_DATA #undef DHT_DATA #endif #define DHT_DATA firmata:: DHT_DATA // DHT reply #ifde_ PIN_MODE:: PIN_MODE_DHT

FirmataExpress.ino

En aquesta discussió, tractarem els "punts àlgids" dels canvis realitzats en aquest esbós d'Arduino.

Per tal que FirmataExpress admeti fins a sis dispositius DHT simultàniament, es van crear 3 matrius per fer un seguiment de cada número de PIN associat del dispositiu, el seu valor WakeUpDelay i el tipus de dispositiu, que és DHT22 o DHT11:

// Sensors DHT

int numActiveDHTs = 0; // nombre de DHT adjunts uint8_t DHT_PinNumbers [MAX_DHTS]; uint8_t DHT_WakeUpDelay [MAX_DHTS]; uint8_t DHT_TYPE [MAX_DHTS];

Com que els dos tipus de dispositius requereixen aproximadament 2 segons entre les lectures, hem d’assegurar-nos que llegim cada DHT només una vegada en el període de 2 segons. Alguns dispositius, com ara els dispositius DHT i els sensors de distància HC-SR04, només s’accedeixen periòdicament. Això els permet interaccionar amb els seus entorns.

uint8_t nextDHT = 0; // indexar a dht perquè es llegeixi el següent dispositiu

uint8_t currentDHT = 0; // Realitza un seguiment de quin sensor està actiu. int dhtNumLoops = 0; // Nombre objectiu de vegades a través del bucle b4 accedint a un DHT int dhtLoopCounter = 0; // Comptador de bucles

Configuració i lectura del dispositiu DHT

Quan FirmataExpress rep una ordre SysEx per configurar un pin per al funcionament DHT, verifica que no s'ha superat el nombre màxim de dispositius DHT. Si es pot donar suport a la nova DHT, s’actualitzen les matrius de DHT. Si es desconeix el tipus DHT, es crea un missatge de cadena SysEx que es transmet de nou a pymata4

cas 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 ("ERROR: TIPUS DE SENSOR DESCONEGUT, ELS SENSORS VÀLIDS SÓN 11, 22"); trencar; } // proveu el sensor DHT_PinNumbers [numActiveDHTs] = DHT_PinNumbers; DHT_TYPE [numActiveDHTs] = DHT_type; setPinModeCallback (DHT_Pin, PIN_MODE_DHT);

FirmataExpress intenta llavors comunicar-se amb el dispositiu DHT. Si hi ha errors, forma un missatge SysEx amb les dades d'error i envia el missatge SysEx a pymat4. La variable _bits conté les dades retornades pel dispositiu DHT per a un processament addicional per part de pymata4 si es desitja.

Firmata.write (START_SYSEX);

Firmata.write (DHT_DATA); Firmata.write (DHT_Pin); Firmata.write (tipus_DHT); per a (uint8_t i = 0; i> 7 i 0x7f); } Firmata.write (abs (rv)); Firmata.write (1); Firmata.write (END_SYSEX);

Si es retornen dades vàlides, s'incrementa el nombre de DHT actives. També s'ajusta una variable que fa un seguiment de les iteracions de bucle que cal completar abans de comprovar si hi ha dades a la propera DHT. Aquesta variable assegura que, independentment de quantes DHT s’afegeixin al sistema, es llegiran totes en un període de 2 segons.

int rv = readDhtSensor (numActiveDHTs);

if (rv == DHTLIB_OK) {numActiveDHTs ++; dhtNumLoops = dhtNumLoops / numActiveDHTs; // tot bé}

Si s'han configurat un o més dispositius DHT a la funció de bucle de l'esbós, es llegeix el següent dispositiu DHT. Les dades vàlides o el seu estat d'error es retornen a pymata4 en forma de missatge 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 = següentDHT; 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]! = suma) {rv = -1; }} // envieu el missatge amb un estat d’error Firmata.write (START_SYSEX); Firmata.write (DHT_DATA); Firmata.write (pin_actual); Firmata.write (tipus_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);}}

El codi utilitzat per comunicar-se amb el dispositiu DHT es deriva directament de la biblioteca DHTNew:

int readDhtSensor (índex int) {

// INICI BUFFERVAR PER RECIBIR DADES uint8_t mask = 128; uint8_t idx = 0; // BUFER BUIT // 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) // next byte? {Mask = 128; idx ++;}} return DHTLIB_OK;}

Pas 4: Modificació de Pymata4 per a l'assistència DHT

private_constants.h

Per donar suport al DHT, hem d'afegir tant els nous missatges tipus pin com SysEx a aquest fitxer:

# pin modes INPUT = 0x00 # pin set as input OUTPUT = 0x01 # pin set as output ANALOG = 0x02 # pin analògic en mode d’entrada analògic PWM = 0x03 # pin digital en mode de sortida PWM SERVO = 0x04 # pin digital en mode de sortida servo I2C = 0x06 # pin inclòs a la configuració I2C STEPPER = 0x08 # qualsevol pin en mode pas SERIAL = 0x0a PULLUP = 0x0b # Qualsevol pin en mode pullup SONAR = 0x0c # Qualsevol pin en mode SONAR TONE = 0x0d # Qualsevol pin en mode de to PIXY = 0x0e # reservat per al mode de càmera pixy DHT = 0x0f # sensor DHT IGNORE = 0x7f # missatges d’ordre DHT SysEx DHT_CONFIG = 0x64 # dht config command DHT_DATA = 0x65 # dht resposta del sensor

El tipus de pin afegit i les ordres SysEx han de coincidir amb els valors de FirmataConstants.h afegits a FirmataExpress.

pymata4.py

Pymata4 utilitza un diccionari Python per associar ràpidament un missatge Firmata entrant amb un gestor de missatges. El nom d’aquest diccionari és report_dispatch.

El format d’una entrada de diccionari és:

{MessageID: [message_handler, nombre de bytes de dades a processar]}

S'ha afegit una entrada al diccionari per gestionar els missatges DHT entrants:

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

Els 7 bytes de dades del missatge són el número de pin digital Arduino, el tipus de dispositiu DHT (22 o 11) i els 5 bytes de dades brutes.

El mètode _dht_read_response comprova si hi ha errors comunicats. Si no es notifiquen errors, la humitat i la temperatura es calculen mitjançant l'algorisme portat des de la biblioteca Arduino DHTNew.

Els valors calculats s’informen mitjançant un mètode de devolució de trucada subministrat per l’usuari. També s’emmagatzemen a l’estructura interna de dades pin_data. Es pot recuperar l'últim valor comunicat mitjançant l'enquesta de pin_data mitjançant el mètode dht_read.

Configuració d’un nou dispositiu DHT

En afegir un dispositiu DHT nou, es diu el mètode set_pin_mode_dht. Aquest mètode actualitza els pin_data dels pins digitals. També crea i envia un missatge DHS_CONFIG SysEx a FirmataExpress.

Pas 5: finalitzar

Com hem vist, afegir suport Firmata per a un nou dispositiu requereix que modifiqueu el codi del servidor Arduino FirmataExpress i el codi client pymata4 basat en Python. El codi FirmataExpress pot ser difícil de depurar. Es va afegir un mètode anomenat printData a FirmataExpress per ajudar a depurar. Aquest mètode us permet enviar valors de dades des de FirmataExpress i els imprimirà a la consola pymata4.

Aquesta funció requereix tant un punter cap a una cadena de caràcters com el valor que voleu veure. Si el valor de les dades es troba en una variable anomenada argc, podeu trucar a printData amb els paràmetres següents.

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

Si teniu cap pregunta, deixeu un comentari i estaré encantat de respondre-us.

Feliç codificació!

Recomanat: