StandardFirmata'nın Ötesine Geçmek - Tekrar Ziyaret: 5 Adım
StandardFirmata'nın Ötesine Geçmek - Tekrar Ziyaret: 5 Adım
Anonim
StandardFirmata'nın Ötesine Geçmek - Tekrar Ziyaret Edildi
StandardFirmata'nın Ötesine Geçmek - Tekrar Ziyaret Edildi

Kısa bir süre önce, bir pymata4 kullanıcısı olan Dr. Martyn Wheeler, pymata4 kitaplığına DHT22 Nem/Sıcaklık sensörü desteği ekleme konusunda rehberlik için benimle iletişime geçti. Pymata4 kütüphanesi, Arduino muadili FirmataExpress ile birlikte, kullanıcıların Arduino cihazlarını uzaktan kontrol etmelerini ve izlemelerini sağlar. Birkaç e-posta alışverişi turunda, Dr. Wheeler hem pymata4 hem de FirmataExpress'i değiştirmede başarılı oldu. Sonuç olarak, DHT22 ve DHT11 sensörleri için destek artık pymata4 ve FirmataExpress'in standart bir parçasıdır.

2014 yılının Mayıs ayında Firmata'ya ek cihazlar için destek eklenmesi ile ilgili bir yazı yazmıştım. Yazdığım yazı üzerine düşününce, o yazı için kalem kağıda aldığımdan beri ne kadar değiştiğini fark ettim. Bu makaleye ek olarak, Dr. Wheeler çabalarını belgelemiştir ve buna da göz atmak isteyebilirsiniz.

FirmataExpress, StandardFirmata'ya dayanmaktadır ve StandardFirmata dizin yapısı gelişmiştir. Ek olarak, pymata4 API 2014'ün orijinal PyMata API'sinden biraz farklıdır. Bu makaleyi tekrar ziyaret etmek ve güncellemek için mükemmel bir zaman olduğunu düşündüm. Dr. Wheeler'ın çalışmasını temel alarak, pymata4/FirmataExpress işlevselliğinin nasıl genişletileceğini keşfedelim.

Başlamadan Önce - Arduino/Firmata Hakkında Bazı Arka Plan Bilgileri

Peki Firmata nedir? Firmata web sayfasından alıntı, "Firmata, bir ana bilgisayardaki yazılımdan mikrodenetleyicilerle iletişim kurmak için genel bir protokoldür."

Arduino Firmata, tipik olarak 57600 bps'ye ayarlanmış bir seri/USB bağlantısı kullanarak bir Arduino mikro denetleyicisi ve bir PC arasında hem komut hem de rapor bilgilerini taşımak için bir seri arabirim kullanır. Bu bağlantı üzerinden aktarılan veriler ikilidir ve protokol bir istemci/sunucu modelinde uygulanır.

Sunucu tarafı, Arduino taslağı şeklinde bir Arduino mikrodenetleyicisine yüklenir. Arduino IDE ile birlikte gelen StandardFirmata çizimi, istemci tarafından komut verildiği şekilde Arduino I/O pinlerini kontrol eder. Ayrıca giriş pin değişikliklerini ve diğer rapor bilgilerini müşteriye geri bildirir. FirmataExpress, StandardFirmata'nın genişletilmiş bir versiyonudur. 115200 bps seri bağlantı hızında çalışır.

Bu makale için kullanılan Arduino istemcisi pymata4'tür. Bir bilgisayarda yürütülen bir Python uygulamasıdır. Arduino sunucusuna hem komutlar gönderir hem de raporlar alır. Pymata4 Python'da uygulandığı için Windows, Linux (Raspberry Pi dahil) ve macOS bilgisayarlarda çalışır.

Neden Firmata'yı Kullanmalısınız?

Arduino mikrodenetleyicileri harika küçük cihazlardır, ancak işlemci ve bellek kaynakları biraz sınırlıdır. Yoğun işlemci veya bellek kullanan uygulamalar için, uygulamanın başarılı olması için kaynak talebini bir PC'ye yüklemekten başka genellikle çok az seçenek vardır.

Ancak StandardFirmata'yı kullanmanın tek nedeni bu değil. Daha hafif Arduino uygulamaları geliştirirken, bir PC, doğrudan bir Arduino mikro denetleyicisinde bulunmayan araçlar ve hata ayıklama yetenekleri sağlayabilir. "Sabit" bir istemci ve sunucu kullanmak, uygulama karmaşıklığının daha kolay yönetilen bir PC ile sınırlandırılmasına yardımcı olur. Uygulama mükemmelleştirildiğinde, özel, bağımsız bir Arduino taslağına çevrilebilir.

Neden pymata4 Kullanılır?

Yazarı olarak, elbette önyargılıyım. Bununla birlikte, son birkaç yıldır sürekli olarak bakımı yapılan tek Python tabanlı Firmata istemcisidir. Sezgisel ve kullanımı kolay bir API sağlar. StandardFirmata tabanlı eskizlere ek olarak, StandardFirmataWifI çizimini kullanırken ESP-8266 gibi cihazlar için WiFi üzerinden Firmata'yı destekler.

Ayrıca, pymata4, şu anda StandardFirmata tarafından desteklenmeyen ek sensörleri ve aktüatörleri desteklemek için bir kullanıcı tarafından kolayca genişletilecek şekilde tasarlanmıştır.

Adım 1: Firmata Protokolünü Anlamak

Firmata Protokolünü Anlamak
Firmata Protokolünü Anlamak

Arduino Firmata iletişim protokolü, verileri temsil etmek için bir veya daha fazla 7 bitlik bayt kullanan MIDI protokolünden türetilmiştir.

Firmata, kullanıcı tarafından genişletilebilir olacak şekilde tasarlanmıştır. Bu genişletilebilirliği sağlayan mekanizma, System Exclusive (SysEx) mesajlaşma protokolüdür.

Firmata Protokolü tarafından tanımlanan bir SysEx mesajının formatı, yukarıdaki çizimde gösterilmektedir. Sabit bir onaltılık 0xF0 değerine sahip bir START_SYSEX baytı ile başlar ve ardından benzersiz bir SysEx komut baytı gelir. Komut baytının değeri, onaltılık 0x00-0x7F aralığında olmalıdır. Komut baytını daha sonra belirtilmemiş sayıda 7 bitlik veri baytı takip eder. Son olarak, mesaj sabit bir onaltılık 0xF7 değeriyle bir END_SYSEX baytıyla sonlandırılır.

Firmata Veri Kodlama/Kod Çözme

Bir SysEx mesajının kullanıcı verileri kısmı bir dizi 7 bitlik bayttan oluştuğundan, birinin 128'den (0x7f) daha büyük bir değeri nasıl temsil ettiğini merak edebilirsiniz. Firmata, veriler veri bağlantısında sıralanmadan önce bu değerleri birden çok 7 bitlik bayt parçalarına ayırarak kodlar. Önce bir veri öğesinin en az anlamlı baytı (LSB) gönderilir, ardından geleneksel olarak veri öğesinin giderek daha önemli bileşenleri gönderilir. Veri öğesinin en önemli baytı (MSB), gönderilen son veri öğesidir.

Bu nasıl çalışır?

Diyelim ki bir SysEx mesajının veri kısmına 525 değerini dahil etmek istiyoruz. 525 değeri, 128 değerinden açıkça daha büyük olduğu için, onu 7 bitlik bayt "parçalarına" bölmemiz veya parçalarına ayırmamız gerekir.

İşte bunun nasıl yapıldığı.

Ondalık olarak 525 değeri, 2 baytlık bir değer olan 0x20D'nin onaltılık değerine eşittir. LSB'yi almak için değeri 0x7F ile AND'leyerek maskeleriz. Hem "C" hem de Python uygulamaları aşağıda gösterilmiştir:

// LSB'yi izole etmek için "C" uygulaması

int max_distance_LSB = max_mesafe & 0x7f; // alt baytı maskele # LSB'yi izole etmek için Python uygulaması max_distance_LSB = max_distance & 0x7F # alt baytı maskele

Maskelemeden sonra max_distance_LSB, 0x0d içerecektir. 0x20D ve 0x7F = 0x0D.

Ardından, bu 2 baytlık değer için MSB'yi izole etmemiz gerekiyor. Bunu yapmak için 0x20D değerini 7 basamak sağa kaydıracağız.

// 2 bayt değerindeki MSB'yi izole etmek için "C" uygulaması

int max_distance_MSB = max_mesafe >> 7; // yüksek sıralı baytı kaydır # 2 bayt değerindeki MSB'yi izole etmek için Python uygulaması max_distance_MSB = max_distance >> 7 # üst baytı almak için shift Kaydırmadan sonra max_distance_MSB, 0x04 değerini içerecektir.

"Yığınlaştırılmış" sıralanmış veriler alındığında, tek bir değerde yeniden birleştirilmesi gerekir. Verilerin hem "C" hem de Python'da nasıl yeniden birleştirildiği aşağıda açıklanmıştır

// 2 baytı yeniden birleştirmek için "C" uygulaması, // 7 bit değerleri tek bir değerde int max_distance = argv[0] + (argv[1] << 7); # 2 bayt, # 7 bit değerlerini tek bir değerde yeniden birleştirmek için Python uygulaması max_distance = data[0] + (data[1] << 7)

Yeniden birleştirmeden sonra, değer bir kez daha 525 ondalık veya 0x20D onaltılık değere eşittir.

Bu sökme/tekrar birleştirme işlemi, istemci veya sunucu tarafından gerçekleştirilebilir.

2. Adım: Başlayalım

Yeni bir cihazı desteklemek, hem Arduino yerleşik sunucusunda hem de PC'de yerleşik Python istemcisinde değişiklik gerektirir. Dr. Wheeler'ın çalışması gerekli değişiklikleri göstermek için kullanılacaktır.

Belki de en önemli adım, mevcut bir destekleyici cihaz kitaplığını denklemin Arduino tarafına entegre etmek mi yoksa kendinizinkini yazmak mı istediğinize karar vermektir. Mevcut bir kitaplığı bulabilirseniz, onu kullanmanın kendi kitaplığınızı sıfırdan yazmaktan çok daha kolay olması önerilir.

DHT cihaz desteği için Dr. Wheeler, uzantı kodunu DHTNew kitaplığına dayandırdı. Çok akıllıca, Dr. Wheeler, Arduino tarafında minimum engelleme sağlamak için DHTNew kütüphanesinin işlevselliğini denklemin Arduino ve pymata4 taraflarına böldü.

DHTNew'e bakarsak, aşağıdakilerin tümünü gerçekleştirir:

  • Seçilen pin dijital çıkış modunu ayarlar.
  • En son nem ve sıcaklık değerlerini almak için kodlanmış bir sinyali kapatır.
  • Hataları kontrol eder ve raporlar.
  • Alınan ham verilerden insan tarafından okunabilen sıcaklık ve nem değerlerini hesaplar.

FirmataExpress tarafında işleri olabildiğince verimli tutmak için Dr. Wheeler, Arduino'dan pymata4'e veri dönüştürme rutinlerini boşalttı.

Adım 3: FirmataExpress'i DHT Desteği için Değiştirme

FirmataExpress Dizin Ağacı

Aşağıda FirmataExpress deposunu oluşturan tüm dosyalar bulunmaktadır. Bu ağaç StandardFiramata'nınkiyle aynıdır, sadece bazı dosya adları depo adını yansıtır.

Değiştirilmesi gereken dosyalar, yanında yıldız işareti (*) olan dosyalardır.

FirmataExpress

├── * Boards.h

├── örnekler

│ └── FirmataExpress

│ ├── boardx

│ ├── * FirmataExpress.ino

│ ├── LICENSE.txt

│ └── Makefile

├── * FirmataConstants.h

├── * FirmataDefines.h

├── FirmataExpress.cpp

├── FirmataExpress.h

├── FirmataMarshaller.cpp

├── FirmataMarshaller.h

├── FirmataParser.cpp

└── FirmataParser.h

Dosyaların her birine ve yapılan değişikliklere bakalım.

Boards.h

Bu dosya, desteklenen her kart tipi için pin tipi makro tanımları içerir. Birden fazla cihazın desteklenmesi gerektiğinde desteklenen maksimum cihaz sayısını tanımlar.

DHT cihazı için bir seferde en fazla 6 cihaz bağlanabilir ve bu değer şu şekilde tanımlanır:

#ifndef MAX_DHTS

#define MAX_DHTS 6 #endif

Ayrıca isteğe bağlı olarak yeni cihaz için ister tüm kart tipleri için ister sadece ilginizi çekenler için pin tipi makrolar tanımlanabilir. Bu makrolar çoğunlukla raporlama amaçlı kullanılır ve cihazları kontrol etmek için kullanılmaz. Bu makrolar, cihazı destekleyen her iki pini de tanımlar:

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

Pin numarası dönüşümünü tanımlamak için bir makronun yanı sıra.

#define PIN_TO_DHT(p) PIN_TO_DIGITAL(p)

FirmataConstants.h

Bu dosya, Arduino'nuza hangi sürümü yüklediğinizi takip etmek için değiştirmek isteyebileceğiniz ürün yazılımı sürüm numarasını içerir. Ayrıca Firmata SysEx mesajları da dahil olmak üzere Firmata mesaj değerlerini içerir.

Bu dosyada cihazınız için yeni bir mesaj veya mesaj grubu atamanız gerekecektir. DHT için iki mesaj eklendi. Biri bir pini "DHT" pini olarak, diğeri ise en son DHT verilerini istemciye geri gönderirken bir raportör mesajı olarak yapılandırır.

statik const int DHT_CONFIG = 0x64;

statik const int DHT_DATA = 0x65;

Pin modları da bu dosyada belirtilmiştir. DHT için yeni bir pin modu oluşturuldu:

statik sabit int PIN_MODE_DHT = 0x0F; // DHT için yapılandırılmış pin

Yeni bir pin modu eklerken TOTAL_PIN_MODES ayarlanmalıdır:

statik const int TOTAL_PIN_MODES = 17;

FirmataDefines.h

Bu dosya FirmataConstants.h'ye eklenen yeni mesajları yansıtacak şekilde güncellenmelidir:

#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 answer #ifdef PIN_MOHT_DMOHT_undef::PIN_MODE_DHT

FirmataExpress.ino

Bu tartışmada, bu Arduino taslağında yapılan değişikliklerin "önemli noktalarını" ele alacağız.

FirmataExpress'in aynı anda altı adede kadar DHT cihazını destekleyebilmesi için her bir cihazın ilişkili pin numarasını, WakeUpDelay değerini ve cihaz tipini yani DHT22 veya DHT11'i takip etmek için 3 dizi oluşturuldu:

// DHT sensörleri

int numActiveDHTs = 0; // eklenen DHT sayısı uint8_t DHT_PinNumbers[MAX_DHTS]; uint8_t DHT_WakeUpDelay[MAX_DHTS]; uint8_t DHT_TYPE[MAX_DHTS];

Her iki cihaz türü de okumalar arasında yaklaşık 2 saniye gerektirdiğinden, her DHT'yi 2 saniyelik zaman diliminde yalnızca bir kez okuduğumuzdan emin olmamız gerekir. DHT cihazları ve HC-SR04 mesafe sensörleri gibi bazı cihazlara yalnızca periyodik olarak erişilir. Bu onlara çevreleriyle etkileşim kurmaları için zaman tanır.

uint8_t nextDHT = 0; // okunacak bir sonraki cihaz için dht içine dizin

uint8_t akımDHT = 0; // Hangi sensörün aktif olduğunu takip eder. int dhtNumLoops = 0; // Bir DHT'ye erişim b4 döngüsü boyunca hedeflenen sayı int dhtLoopCounter = 0; // Döngü sayacı

DHT Aygıtını Yapılandırma ve Okuma

FirmataExpress, DHT işlemi için bir pin yapılandırmak üzere bir SysEx komutu aldığında, maksimum DHT cihazı sayısının aşılmadığını doğrular. Yeni DHT desteklenebiliyorsa, DHT dizileri güncellenir. DHT türü bilinmiyorsa, bir SysEx dize mesajı oluşturulur ve pymata4'e geri iletilir.

durum 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("HATA: BİLİNMEYEN SENSÖR TÜRÜ, GEÇERLİ SENSÖRLER 11, 22"); kırmak; } // sensörü test edin DHT_PinNumbers[numActiveDHTs] = DHT_Pin; DHT_TYPE[numActiveDHTs] = DHT_type; setPinModeCallback(DHT_Pin, PIN_MODE_DHT);

FirmataExpress daha sonra DHT cihazı ile iletişim kurmaya çalışır. Herhangi bir hata varsa, hata verileriyle bir SysEx mesajı oluşturur ve SysEx mesajını pymat4'e geri gönderir. _bits değişkeni, istenirse pymata4 tarafından ek işleme için DHT cihazı tarafından döndürülen verileri tutar.

Firmata.write(START_SYSEX);

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

Geçerli veriler döndürülürse, aktif DHT'lerin sayısı artırılır. Veriler için bir sonraki DHT'yi kontrol etmeden önce kaç döngü yinelemesinin tamamlanacağını takip eden bir değişken de ayarlanır. Bu değişken, sisteme ne kadar DHT eklenirse eklensin hepsinin 2 saniyelik bir süre içinde okunacağını garanti eder.

int rv = readDhtSensor(numActiveDHTs);

if (rv == DHTLIB_OK) { numActiveDHTs++; dhtNumLoops = dhtNumLoops / numActiveDHT'ler; // her şey yolunda }

Çizimin döngü fonksiyonunda bir veya daha fazla DHT cihazı konfigüre edilmişse, bir sonraki DHT cihazı okunur. Geçerli veriler veya hata durumu, bir SysEx mesajı biçiminde pymata4'e döndürülür:

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; akımDHT = sonrakiDHT; if (nextDHT++ >= numActiveDHTs - 1) { nextDHT = 0; } if (rv == DHTLIB_OK) { // TEST CHECKSUM uint8_t toplam = _bits[0] + _bits[1] + _bits[2] + _bits[3]; if (_bits[4] != toplam) { rv = -1; } } // mesajı hata durumuyla geri gönder 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 cihazıyla iletişim kurmak için kullanılan kod, doğrudan DHTNew kitaplığından türetilmiştir:

int readDhtSensor(int indeksi){

// VERİ ALMAK İÇİN BUFFERVAR'I BAŞLAT uint8_t mask = 128; uint8_t idx = 0; // BOŞ 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) DHTLIB_ERROR_TIMEOUT döndürür; } uint32_t t = micros(); loopCnt = DHTLIB_TIMEOUT; while (digitalRead(pin) == HIGH) { if (--loopCnt == 0) DHTLIB_ERROR_TIMEOUT döndürür; } if ((micros() - t) > 40) { _bits[idx] |= mask; } mask >>= 1; if (mask == 0) // sonraki bayt? { mask = 128; idx++; } } DHTLIB_OK döndür; }

Adım 4: DHT Desteği için Pymata4'ü Değiştirme

private_constants.h

DHT'yi desteklemek için bu dosyaya hem yeni pin tipi hem de SysEx mesajlarını eklememiz gerekiyor:

# pin modları GİRİŞ = 0x00 # giriş olarak pin seti ÇIKIŞ = 0x01 # çıkış olarak pin seti ANALOG = 0x02 # analogGiriş modunda analog pin PWM = 0x03 # PWM çıkış modunda dijital pin SERVO = 0x04 # Servo çıkış modunda dijital pin I2C = 0x06 # I2C kurulumuna dahil pin STEPPER = 0x08 # step modunda herhangi bir pin SERIAL = 0x0a PULLUP = 0x0b # Pullup modunda herhangi bir pin SONAR = 0x0c # SONAR modunda herhangi bir pin TONE = 0x0d # Ton modunda herhangi bir pin PIXY = 0x0e # pixy kamera modu için ayrılmıştır DHT = 0x0f # DHT sensörü IGNORE = 0x7f # DHT SysEx komut mesajları DHT_CONFIG = 0x64 # dht yapılandırma komutu DHT_DATA = 0x65 # dht sensör yanıtı

Eklenen pin tipi ve SysEx komutları, FirmataExpress'e eklenen FirmataConstants.h içindeki değerlerle eşleşmelidir.

pymata4.py

Pymata4, gelen bir Firmata mesajını bir mesaj işleyicisi ile hızlı bir şekilde ilişkilendirmek için bir Python sözlüğü kullanır. Bu sözlüğün adı report_dispatch.

Sözlük girişinin formatı şudur:

{MessageID: [message_handler, işlenecek veri bayt sayısı]}

Gelen DHT mesajlarını işlemek için sözlüğe bir giriş eklendi:

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

Mesajdaki 7 bayt veri, Arduino dijital pin numarası, DHT cihazının tipi (22 veya 11) ve 5 bayt ham veridir.

_dht_read_response yöntemi, bildirilen hataları kontrol eder. Bildirilen herhangi bir hata yoksa, Arduino DHTNew kütüphanesinden taşınan algoritma kullanılarak nem ve sıcaklık hesaplanır.

Hesaplanan değerler, kullanıcı tarafından sağlanan bir geri arama yöntemiyle rapor edilir. Ayrıca dahili pin_data veri yapısında depolanırlar. Bildirilen son değer, dht_read yöntemi kullanılarak pin_data sorgulanarak geri çağrılabilir.

Yeni Bir DHT Aygıtını Yapılandırma

Yeni bir DHT cihazı eklerken set_pin_mode_dht metodu çağrılır. Bu yöntem, dijital pinler için pin_data'yı günceller. Ayrıca bir DHT_CONFIG SysEx mesajı oluşturur ve FirmataExpress'e gönderir.

Adım 5: Toplama

Gördüğümüz gibi, yeni bir cihaz için Firmata desteği eklemek, Arduino FirmataExpress sunucu kodunu ve Python tabanlı pymata4 istemci kodunu değiştirmenizi gerektirir. FirmataExpress kodunun hata ayıklaması zor olabilir. Hata ayıklamaya yardımcı olmak için FirmataExpress'e printData adlı bir yöntem eklendi. Bu yöntem, FirmataExpress'ten veri değerleri göndermenize izin verir ve bunları pymata4 konsolunda yazdırır.

Bu işlev, hem bir karakter dizisine bir işaretçi hem de görüntülemek istediğiniz değere ihtiyaç duyar. Veri değeri argc adlı bir değişkende yer alıyorsa, aşağıdaki parametrelerle printData'yı çağırabilirsiniz.

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

Herhangi bir sorunuz varsa, sadece bir yorum bırakın, cevaplamaktan mutluluk duyacağım.

Mutlu kodlama!

Önerilen: