Съдържание:

Преминаване отвъд стандартната фирма - повторно посещение: 5 стъпки
Преминаване отвъд стандартната фирма - повторно посещение: 5 стъпки

Видео: Преминаване отвъд стандартната фирма - повторно посещение: 5 стъпки

Видео: Преминаване отвъд стандартната фирма - повторно посещение: 5 стъпки
Видео: Часть 5 - Аудиокнига Э. М. Форстера «Говардс-Энд» (главы 30–38) 2024, Ноември
Anonim
Преминаване отвъд StandardFirmata - Наново
Преминаване отвъд StandardFirmata - Наново

Преди малко с мен се свърза д -р Мартин Уилър, потребител на pymata4, за насоки за добавяне на поддръжка за DHT22 сензор за влажност/температура към библиотеката pymata4. Библиотеката pymata4, съвместно с Arduino, FirmataExpress, позволява на потребителите да управляват и наблюдават своите устройства Arduino от разстояние. В рамките на няколко кръга от обмен на имейли, д -р Уилър успя успешно да промени както pymata4, така и FirmataExpress. В резултат на това поддръжката на сензорите DHT22 и DHT11 вече е стандартна част от pymata4 и FirmataExpress.

През май 2014 г. написах статия за добавяне на поддръжка към Firmata за допълнителни устройства. Размишлявайки върху тази статия, осъзнах колко много се е променило, откакто взех писалка на хартия за тази статия. В допълнение към тази статия, д -р Уилър документира усилията си и може да пожелаете да проверите и това.

FirmataExpress се основава на StandardFirmata, а структурата на директориите StandardFirmata се е развила. В допълнение, API на pymata4 също е доста различен от оригиналния PyMata API от 2014 г. Мислех, че това ще бъде идеалният момент да преразгледаме и актуализираме тази статия. Използвайки работата на д -р Уилър като основа, нека проучим как да разширим функционалността на pymata4/FirmataExpress.

Преди да започнем - малко основна информация за Arduino/Firmata

И така, какво е Firmata? Цитирайки от уеб страницата на Firmata, "Firmata е общ протокол за комуникация с микроконтролери от софтуер на хост компютър."

Arduino Firmata използва сериен интерфейс за транспортиране както на команда, така и на информация за доклад между микроконтролер Arduino и компютър, обикновено използвайки серийна/USB връзка, зададена на 57600 bps. Данните, прехвърлени през тази връзка, са двоични и протоколът е внедрен в клиент/сървър модел.

Сървърната страна се качва на микроконтролер Arduino под формата на скица на Arduino. Скицата StandardFirmata, включена в Arduino IDE, контролира I/O пиновете на Arduino, както е заповядано от клиента. Той също така докладва промените на входния щифт и друга информация за отчета обратно на клиента. FirmataExpress е разширена версия на StandardFirmata. Той работи със скорост на серийна връзка 115200 bps.

Клиентът на Arduino, използван за тази статия, е pymata4. Това е приложение на Python, което се изпълнява на компютър. Той едновременно изпраща команди до и получава отчети от сървъра на Arduino. Тъй като pymata4 е внедрен в Python, той работи на Windows, Linux (включително Raspberry Pi) и macOS компютри.

Защо да използвате Firmata?

Микроконтролерите Arduino са прекрасни малки устройства, но ресурсите на процесора и паметта са донякъде ограничени. За приложения, които имат интензивен процесор или памет, често има малък избор, освен да се разтоварва търсенето на ресурси на компютър, за да може приложението да бъде успешно.

Но това не е единствената причина да използвате StandardFirmata. Когато разработвате по -леки приложения Arduino, компютърът може да предостави инструменти и възможности за отстраняване на грешки, които не са директно достъпни на микроконтролер Arduino. Използването на "фиксиран" клиент и сървър помага да се ограничи сложността на приложението до компютър, който се управлява по -лесно. След като приложението бъде усъвършенствано, то може да бъде преведено в персонализирана, самостоятелна скица на Arduino.

Защо да използвате pymata4?

Като негов автор, разбира се, съм пристрастен. Като се има предвид това, това е единственият базиран на Python клиент на Firmata, който се поддържа непрекъснато през последните няколко години. Той осигурява интуитивен и лесен за използване API. В допълнение към скици, базирани на StandardFirmata, Той поддържа Firmata през WiFi за устройства като ESP-8266, когато използва скицата StandardFirmataWifI.

Също така, pymata4 е проектиран да бъде лесно разширен от потребител, за да поддържа допълнителни сензори и задвижвания, които понастоящем не се поддържат от StandardFirmata.

Стъпка 1: Разбиране на протокола Firmata

Разбиране на протокола Firmata
Разбиране на протокола Firmata

Комуникационният протокол Arduino Firmata се извлича от MIDI протокола, който използва един или повече 7-битови байта за представяне на данни.

Firmata е проектиран да бъде разширяван от потребителя. Механизмът, който осигурява тази разширяемост, е протоколът за съобщения System Exclusive (SysEx).

Форматът на съобщение SysEx, както е дефинирано от протокола Firmata, е показан на илюстрацията по -горе. Той започва с байт START_SYSEX с фиксирана стойност от шестнадесетичен 0xF0 и е последван от уникален байт за команда SysEx. Стойността на командния байт трябва да бъде в диапазона на шестнадесетичен 0x00-0x7F. След това командният байт е последван от неуточнен брой 7-битови байтове данни. И накрая, съобщението се прекратява с END_SYSEX байт, с фиксирана стойност от шестнадесетичен 0xF7.

Кодиране/декодиране на данни на Firmata

Тъй като частта от потребителски данни на съобщение SysEx се състои от поредица от 7-битови байта, може да се чудите как една представлява стойност, по-голяма от 128 (0x7f)? Firmata кодира тези стойности, като ги разглобява на множество 7-битови байтови парчета, преди данните да бъдат маршалирани по връзката за данни. Първо се изпраща най -малко значимият байт (LSB) на елемент от данни, последван от все по -значими компоненти на елемента от данни по конвенция. Най -значимият байт (MSB) на елемента от данни е последният изпратен елемент от данни.

Как работи това?

Да речем, че искаме да включим стойност 525 в частта от данни на съобщение на SysEx. Тъй като стойност 525 очевидно е по-голяма от стойност 128, трябва да я разделим или разглобим на 7-битови байтови „парчета“.

Ето как се прави това.

Стойността на 525 в десетичен знак е еквивалентна на шестнадесетичната стойност на 0x20D, 2-байтова стойност. За да получим LSB, маскираме стойността, като я изпратим с 0x7F. И двете реализации "C" и Python са показани по -долу:

// „C“изпълнение за изолиране на LSB

int max_distance_LSB = max_distance & 0x7f; // маскиране на долния байт # изпълнение на Python за изолиране на LSB max_distance_LSB = max_distance & 0x7F # маска на долния байт

След маскиране, max_distance_LSB ще съдържа 0x0d. 0x20D & 0x7F = 0x0D.

След това трябва да изолираме MSB за тази 2-байтова стойност. За да направим това, ще изместим стойността на 0x20D надясно, на 7 места.

// "C" изпълнение за изолиране на MSB от 2 байтова стойност

int max_distance_MSB = max_distance >> 7; // изместване на байта от висок ред # реализация на Python за изолиране на MSB от 2 байта max_distance_MSB = max_distance >> 7 # shift за получаване на горния байт След преместване max_distance_MSB ще съдържа стойност 0x04.

Когато се получат „нарязаните“маршалирани данни, те трябва да бъдат събрани отново в една стойност. Ето как данните се сглобяват отново и в "C", и в Python

// "C" реализация за повторно сглобяване на 2 байта, // 7 битови стойности в една стойност int max_distance = argv [0] + (argv [1] << 7); # Реализация на Python за повторно сглобяване на 2 -байтовите, # 7 -битовите стойности в една стойност max_distance = data [0] + (data [1] << 7)

След повторно сглобяване стойността отново се равнява на 525 десетична или 0x20D шестнадесетична.

Този процес на разглобяване/сглобяване може да се извърши или от клиента, или от сървъра.

Стъпка 2: Нека започнем

Поддръжката на ново устройство изисква промени както в резидентния сървър на Arduino, така и в резидентния клиент на Python. Работата на д -р Уилър ще бъде използвана за илюстриране на необходимите модификации.

Може би най -важната стъпка е да решите дали искате да интегрирате съществуваща библиотека за поддържащи устройства в Arduino страната на уравнението или да напишете своя собствена. Препоръчва се, ако можете да намерите съществуваща библиотека, да е много по -лесно да я използвате, отколкото да напишете своя собствена от нулата.

За поддръжка на DHT устройства д -р Уилър основава своя разширителен код на библиотеката DHTNew. Много умно, д -р Уилър раздели функционалността на библиотеката на DHTNew през Arduino и pymata4 страни на уравнението, за да осигури минимално блокиране от страна на Arduino.

Ако погледнем DHTNew, той изпълнява всички от следните неща:

  • Задава избрания режим на цифров изход.
  • Часовник кодира сигнал за извличане на най -новите стойности на влажност и температура.
  • Проверява и докладва всички грешки.
  • Изчислява стойности за температура и влажност, които могат да се четат от човека, от извлечените необработени данни.

За да поддържа нещата възможно най -ефективни от страна на FirmataExpress, д -р Уилър разтовари процедурите за преобразуване на данни от Arduino към pymata4.

Стъпка 3: Промяна на FirmataExpress за DHT поддръжка

Дървото на директориите на FirmataExpress

По -долу са всички файлове, които съдържат хранилището на FirmataExpress. Това дърво е идентично с това на StandardFiramata, само че някои от имената на файловете отразяват името на хранилището.

Файловете, които се нуждаят от промяна, са тези, които имат звездичка (*) до себе си.

FirmataExpress

├── * Табла.ч

Examples── примери

│ └── FirmataExpress

│ ├── бордx

│ ├── * FirmataExpress.ino

│ ├── LICENSE.txt

│ └── Makefile

├── * FirmataConstants.h

├── * FirmataDefines.h

├── FirmataExpress.cpp

├── FirmataExpress.h

├── FirmataMarshaller.cpp

├── FirmataMarshaller.h

├── FirmataParser.cpp

└── FirmataParser.h

Нека разгледаме всеки от файловете и промените, които са направени.

Табла.ч

Този файл съдържа дефиниции за макроси за всеки от поддържаните типове платки. Той определя максималния брой поддържани устройства, когато трябва да се поддържат повече от едно устройство.

За DHT устройството могат да бъдат свързани до 6 устройства едновременно и тази стойност се определя като:

#ifndef MAX_DHTS

#дефинирайте MAX_DHTS 6 #endif

Също така, макроси от тип pin могат да бъдат дефинирани по избор за новото устройство, или за всички видове платки, или само за тези, които представляват интерес за вас. Тези макроси се използват най -вече за отчитане и не се използват за управление на устройствата. Тези макроси определят двата пина, които поддържат устройството:

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

Както и макрос за дефиниране на пин-номер преобразуване.

#define PIN_TO_DHT (p) PIN_TO_DIGITAL (p)

FirmataConstants.h

Този файл съдържа номера на версията на фърмуера, който може да искате да промените, за да следите коя версия сте заредили на вашия Arduino. Той също така съдържа стойностите на съобщенията Firmata, включително съобщенията Firmata SysEx.

В този файл ще трябва да зададете ново съобщение или набор от съобщения за вашето устройство. За DHT бяха добавени две съобщения. Единият конфигурира щифт като „DHT“щифт, а другият като съобщение на репортер, когато изпраща най -новите DHT данни обратно на клиента.

static const int DHT_CONFIG = 0x64;

статичен const int DHT_DATA = 0x65;

Режимите на закрепване също са посочени в този файл. За DHT е създаден нов режим на закрепване:

статичен const int PIN_MODE_DHT = 0x0F; // пин конфигуриран за DHT

Когато добавяте нов режим на закрепване, TOTAL_PIN_MODES трябва да се коригира:

статичен const int TOTAL_PIN_MODES = 17;

FirmataDefines.h

Този файл трябва да бъде актуализиран, за да отразява новите съобщения, добавени към FirmataConstants.h:

#ifdef DHT_CONFIG #undef DHT_CONFIG #endif #define DHT_CONFIG firmata:: DHT_CONFIG // DHT заявка #ifdef DHT_DATA #undef DHT_DATA #endif #define DHT_DATA firmata:: DHT_DATA // DHT отговор:: PIN_MODE_DHT

FirmataExpress.ino

В тази дискусия ще разгледаме „най-важните точки“на промените, направени в тази скица на Arduino.

За да може FirmataExpress да поддържа до шест DHT устройства едновременно, бяха създадени 3 масива за проследяване на всеки от свързания с устройството пинов номер, неговата стойност WakeUpDelay и типа на устройството, тоест DHT22 или DHT11:

// DHT сензори

int numActiveDHTs = 0; // брой прикачени DHT uint8_t DHT_PinNumbers [MAX_DHTS]; uint8_t DHT_WakeUpDelay [MAX_DHTS]; uint8_t DHT_TYPE [MAX_DHTS];

Тъй като и двата типа устройства изискват приблизително 2 секунди между четенията, трябва да се уверим, че четем всеки DHT само веднъж в рамките на 2 секунди. Някои устройства, като например DHT устройствата и HC-SR04 сензорите за разстояние, са достъпни само периодично. Това им дава време да си взаимодействат със средата си.

uint8_t следващDHT = 0; // индексиране в dht за следващо устройство за четене

uint8_t currentDHT = 0; // Проследява кой сензор е активен. int dhtNumLoops = 0; // Целеви брой пъти през цикъл b4 достъп до DHT int dhtLoopCounter = 0; // Брояч на цикли

Конфигуриране и четене на DHT устройството

Когато FirmataExpress получава команда SysEx за конфигуриране на щифт за DHT операция, той проверява дали не е надвишен максималният брой DHT устройства. Ако новият DHT може да се поддържа, DHT масивите се актуализират. Ако типът DHT е неизвестен, се създава низово съобщение на SysEx и се предава обратно на pymata4

случай DHT_CONFIG: int DHT_Pin = argv [0]; int DHT_type = argv [1]; if (numActiveDHTs <MAX_DHTS) {if (DHT_type == 22) {DHT_WakeUpDelay [numActiveDHTs] = 1; } иначе ако (DHT_type == 11) {DHT_WakeUpDelay [numActiveDHTs] = 18; } else {Firmata.sendString ("ГРЕШКА: НЕИЗВЕСТЕН ТИП СЕНЗОР, ВАЛИДНИ СЕНЗОРИ СА 11, 22"); прекъсване; } // тестваме сензора DHT_PinNumbers [numActiveDHTs] = DHT_Pin; DHT_TYPE [numActiveDHTs] = DHT_тип; setPinModeCallback (DHT_Pin, PIN_MODE_DHT);

След това FirmataExpress се опитва да комуникира с DHT устройството. Ако има грешки, той формира съобщение на SysEx с данните за грешките и изпраща съобщението на SysEx обратно на pymat4. Променливата _bits съдържа данните, върнати от DHT устройството за допълнителна обработка от pymata4, ако желаете.

Firmata.write (START_SYSEX);

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

Ако се върнат валидни данни, броят на активните DHT се увеличава. Променлива, която следи колко итерации на цикъла да завърши, преди да провери следващия DHT за данни, също се коригира. Тази променлива гарантира, че без значение колко DHT са добавени към системата, всички те ще бъдат прочетени в рамките на период от 2 секунди.

int rv = readDhtSensor (numActiveDHTs);

if (rv == DHTLIB_OK) {numActiveDHTs ++; dhtNumLoops = dhtNumLoops / numActiveDHTs; // всичко е наред}

Ако едно или повече DHT устройства са конфигурирани в цикличната функция на скицата, следващото DHT устройство се чете. Или валидните данни, или състоянието на тяхната грешка се връщат на pymata4 под формата на съобщение 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 (_бит [4]! = сума) {rv = -1; }} // изпраща съобщението обратно със състояние на грешка Firmata.write (START_SYSEX); Firmata.write (DHT_DATA); Firmata.write (current_pin); Firmata.write (current_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);}}

Кодът, използван за комуникация с DHT устройството, се извлича директно от библиотеката DHTNew:

int readDhtSensor (int индекс) {

// INIT BUFFERVAR ЗА ПОЛУЧАВАНЕ НА ДАННИ uint8_t mask = 128; uint8_t idx = 0; // ПРАЗЕН БУФЕР // 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) връщане DHTLIB_ERROR_TIMEOUT;} uint32_t t = micros (); loopCnt = DHTLIB_TIMEOUT; while (digitalRead (pin) == HIGH) {if (--loopCnt == 0) връщане на DHTLIB_ERROR_TIMEOUT;} if ((micros ()-t)> 40) {_bits [idx] | = mask;} mask >> = 1; if (mask == 0) // следващ байт? {Mask = 128; idx ++;}} връщане на DHTLIB_OK;}

Стъпка 4: Промяна на Pymata4 за DHT поддръжка

private_constants.h

За да поддържаме DHT, трябва да добавим както новите пин-тип, така и SysEx съобщения към този файл:

# пинов режим INPUT = 0x00 # щифт зададен като вход OUTPUT = 0x01 # щифт зададен като изход ANALOG = 0x02 # аналогов извод в аналогов режим на въвеждане PWM = 0x03 # цифров извод в PWM изходен режим SERVO = 0x04 # цифров извод в режим на серво изход I2C = 0x06 # щифт, включен в настройката на I2C STEPPER = 0x08 # всеки щифт в стъпков режим SERIAL = 0x0a PULLUP = 0x0b # Всеки щифт в режим на извличане SONAR = 0x0c # Всеки щифт в режим SONAR TONE = 0x0d # Всеки щифт в тон режим PIXY = 0x0e # запазено за режим pixy камера DHT = 0x0f # DHT сензор IGNORE = 0x7f # DHT SysEx команда съобщения DHT_CONFIG = 0x64 # dht конфигурационна команда DHT_DATA = 0x65 # dht отговор на сензора

Добавеният тип пин и командите SysEx трябва да съвпадат със стойностите във FirmataConstants.h, добавени към FirmataExpress.

pymata4.py

Pymata4 използва речник на Python за бързо свързване на входящо съобщение Firmata с манипулатор на съобщения. Името на този речник е report_dispatch.

Форматът за запис в речника е:

{MessageID: [message_handler, брой байтове данни за обработка]}

В речника е добавен запис за обработка на входящи DHT съобщения:

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

7 -те байта данни в съобщението са цифров пинов номер на Arduino, типът на DHT устройството (22 или 11) и 5 -те байта необработени данни.

Методът _dht_read_response проверява за съобщени грешки. Ако няма съобщени грешки, влажността и температурата се изчисляват с помощта на алгоритъма, пренесен от библиотеката Arduino DHTNew.

Изчислените стойности се отчитат чрез предоставен от потребителя метод за обратно повикване. Те също се съхраняват във вътрешната структура от данни pin_data. Последната отчетена стойност може да бъде извикана чрез опросване на pin_data чрез метода dht_read.

Конфигуриране на ново DHT устройство

При добавяне на ново DHT устройство се извиква методът set_pin_mode_dht. Този метод актуализира pin_data за цифрови пинове. Той също така създава и изпраща DHT_CONFIG SysEx съобщение до FirmataExpress.

Стъпка 5: Приключване

Както видяхме, добавянето на поддръжка на Firmata за ново устройство изисква да промените кода на сървъра на Arduino FirmataExpress и клиентския код на Python, базиран на Python. Кодът на FirmataExpress може да бъде предизвикателство за отстраняване на грешки. Метод, наречен printData, беше добавен към FirmataExpress, за да помогне за отстраняване на грешки. Този метод ви позволява да изпращате стойности на данни от FirmataExpress и ще ги отпечатва на конзолата pymata4.

Тази функция изисква както указател към символен низ, така и стойността, която искате да видите. Ако стойността на данните се съдържа в променлива, наречена argc, можете да извикате printData със следните параметри.

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

Ако имате въпроси, просто оставете коментар и ще се радвам да отговоря.

Честито кодиране!

Препоръчано: