สารบัญ:

Going Beyond StandardFirmata - เยี่ยมชมอีกครั้ง: 5 ขั้นตอน
Going Beyond StandardFirmata - เยี่ยมชมอีกครั้ง: 5 ขั้นตอน

วีดีโอ: Going Beyond StandardFirmata - เยี่ยมชมอีกครั้ง: 5 ขั้นตอน

วีดีโอ: Going Beyond StandardFirmata - เยี่ยมชมอีกครั้ง: 5 ขั้นตอน
วีดีโอ: 🌟ENG SUB | Martial Universe EP 01 - 36 Full Version | Yuewen Animation 2024, กรกฎาคม
Anonim
Going Beyond StandardFirmata - มาเยือนอีกครั้ง
Going Beyond StandardFirmata - มาเยือนอีกครั้ง

ไม่นานมานี้ ฉันได้รับการติดต่อจาก Dr. Martyn Wheeler ผู้ใช้ pymata4 เพื่อขอคำแนะนำในการเพิ่มการรองรับเซ็นเซอร์ความชื้น/อุณหภูมิ DHT22 ให้กับไลบรารี pymata4 ไลบรารี pymata4 ร่วมกับ FirmataExpress ของ Arduino ช่วยให้ผู้ใช้สามารถควบคุมและตรวจสอบอุปกรณ์ Arduino ได้จากระยะไกล ภายในการแลกเปลี่ยนอีเมลสองสามรอบ Dr. Wheeler ประสบความสำเร็จในการแก้ไขทั้ง pymata4 และ FirmataExpress ด้วยเหตุนี้ การรองรับเซ็นเซอร์ DHT22 และ DHT11 จึงกลายเป็นส่วนมาตรฐานของ pymata4 และ FirmataExpress

ในเดือนพฤษภาคม 2014 ฉันได้เขียนบทความเกี่ยวกับการเพิ่มการรองรับ Firmata สำหรับอุปกรณ์เพิ่มเติม เมื่อพิจารณาจากบทความนั้น ฉันก็ตระหนักว่ามีการเปลี่ยนแปลงไปมากเพียงใดตั้งแต่ฉันหยิบปากกามาเขียนบทความนั้น นอกจากบทความนี้ ดร.วีลเลอร์ยังได้บันทึกความพยายามของเขา และคุณอาจต้องการตรวจสอบด้วยเช่นกัน

FirmataExpress ขึ้นอยู่กับ StandardFirmata และโครงสร้างไดเร็กทอรี StandardFirmata ก็พัฒนาขึ้น นอกจากนี้ pymata4 API ยังค่อนข้างแตกต่างจาก PyMata API ดั้งเดิมของปี 2014 เล็กน้อย ฉันคิดว่านี่จะเป็นเวลาที่เหมาะสมที่สุดในการทบทวนและอัปเดตบทความนั้น โดยใช้งานของ Dr. Wheeler เป็นพื้นฐาน มาสำรวจวิธีขยายฟังก์ชันการทำงานของ pymata4/FirmataExpress กัน

ก่อนที่เราจะเริ่มต้น - ข้อมูลพื้นฐานบางประการเกี่ยวกับ Arduino/Firmata

Firmata คืออะไร? อ้างอิงจากหน้าเว็บ Firmata "Firmata เป็นโปรโตคอลทั่วไปสำหรับการสื่อสารกับไมโครคอนโทรลเลอร์จากซอฟต์แวร์บนคอมพิวเตอร์โฮสต์"

Arduino Firmata ใช้อินเทอร์เฟซแบบอนุกรมเพื่อส่งทั้งคำสั่งและรายงานข้อมูลระหว่างไมโครคอนโทรลเลอร์ Arduino และพีซี โดยทั่วไปจะใช้ลิงก์ซีเรียล/USB ที่ตั้งค่าไว้ที่ 57600 bps ข้อมูลที่ถ่ายโอนผ่านลิงค์นี้เป็นไบนารี และโปรโตคอลถูกนำไปใช้ในโมเดลไคลเอนต์/เซิร์ฟเวอร์

ฝั่งเซิร์ฟเวอร์ถูกอัปโหลดไปยังไมโครคอนโทรลเลอร์ Arduino ในรูปแบบของร่าง Arduino ร่าง StandardFirmata ที่มาพร้อมกับ Arduino IDE จะควบคุมพิน Arduino I/O ตามที่ลูกค้าสั่ง นอกจากนี้ยังรายงานการเปลี่ยนแปลงพินอินพุตและข้อมูลรายงานอื่นๆ กลับไปยังลูกค้าอีกด้วย FirmataExpress เป็นเวอร์ชันขยายของ StandardFirmata มันทำงานที่ความเร็วลิงค์แบบอนุกรมที่ 115200 bps

ไคลเอนต์ Arduino ที่ใช้สำหรับบทความนี้คือ pymata4 เป็นแอปพลิเคชั่น Python ที่ทำงานบนพีซี ทั้งสองส่งคำสั่งไปยังและรับรายงานจากเซิร์ฟเวอร์ Arduino เนื่องจากมีการใช้ pymata4 ใน Python จึงทำงานบน Windows, Linux (รวมถึง Raspberry Pi) และคอมพิวเตอร์ macOS

ทำไมต้องใช้ Firmata?

ไมโครคอนโทรลเลอร์ Arduino เป็นอุปกรณ์ขนาดเล็กที่ยอดเยี่ยม แต่ทรัพยากรโปรเซสเซอร์และหน่วยความจำค่อนข้างจำกัด สำหรับแอปพลิเคชันที่ใช้โปรเซสเซอร์หรือหน่วยความจำมาก มักมีทางเลือกเพียงเล็กน้อยแต่ต้องลดความต้องการทรัพยากรลงในพีซีเพื่อให้แอปพลิเคชันประสบความสำเร็จ

แต่นั่นไม่ใช่เหตุผลเดียวที่ใช้ StandardFirmata เมื่อพัฒนาแอพพลิเคชั่น Arduino น้ำหนักเบา พีซีสามารถจัดหาเครื่องมือและความสามารถในการดีบักที่ไม่มีในไมโครคอนโทรลเลอร์ Arduino โดยตรง การใช้ไคลเอ็นต์และเซิร์ฟเวอร์ที่ "คงที่" จะช่วยจำกัดความซับซ้อนของแอปพลิเคชันไว้ในพีซี ซึ่งจัดการได้ง่ายกว่า เมื่อแอปพลิเคชันสมบูรณ์แล้ว ก็สามารถแปลเป็นร่าง Arduino แบบสแตนด์อโลนแบบกำหนดเองได้

ทำไมต้องใช้ pymata4?

แน่นอนว่าฉันเป็นคนลำเอียง อย่างที่กล่าวไปแล้วว่าเป็นไคลเอนต์ Firmata ที่ใช้ Python เพียงตัวเดียวที่ได้รับการดูแลอย่างต่อเนื่องในช่วงหลายปีที่ผ่านมา มี API ที่ใช้งานง่ายและใช้งานง่าย นอกจากการสเก็ตช์แบบ StandardFirmata แล้ว ยังรองรับ Firmata ผ่าน WiFi สำหรับอุปกรณ์อย่างเช่น ESP-8266 เมื่อใช้ร่าง StandardFirmataWifI

นอกจากนี้ pymata4 ยังได้รับการออกแบบให้ผู้ใช้ขยายได้ง่ายเพื่อรองรับเซ็นเซอร์และแอคทูเอเตอร์เพิ่มเติมที่ StandardFirmata ไม่รองรับในปัจจุบัน

ขั้นตอนที่ 1: ทำความเข้าใจ Firmata Protocol

ทำความเข้าใจกับ Firmata Protocol
ทำความเข้าใจกับ Firmata Protocol

โปรโตคอลการสื่อสาร Arduino Firmata มาจากโปรโตคอล MIDI ซึ่งใช้ไบต์ 7 บิตอย่างน้อยหนึ่งไบต์เพื่อแสดงข้อมูล

Firmata ได้รับการออกแบบมาให้ผู้ใช้ขยายได้ กลไกที่ช่วยให้ขยายได้นี้คือโปรโตคอลการส่งข้อความ System Exclusive (SysEx)

รูปแบบของข้อความ SysEx ตามที่กำหนดโดย Firmata Protocol แสดงในภาพประกอบด้านบน โดยเริ่มต้นด้วยไบต์ 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 เราปิดบังค่าโดย AND'ing ด้วย 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; // shift ไบต์ลำดับสูง # การใช้งาน 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 บนพีซี งานของ Dr. Wheeler จะถูกนำมาใช้เพื่อแสดงการดัดแปลงที่จำเป็น

บางทีขั้นตอนที่สำคัญที่สุดคือการตัดสินใจว่าคุณต้องการรวมไลบรารีอุปกรณ์ที่รองรับที่มีอยู่เข้ากับด้าน Arduino ของสมการหรือเขียนของคุณเอง ขอแนะนำว่าถ้าคุณสามารถหาห้องสมุดที่มีอยู่ได้ จะใช้ง่ายกว่าการเขียนของคุณเองตั้งแต่เริ่มต้น

สำหรับการสนับสนุนอุปกรณ์ DHT Dr. Wheeler ได้ใช้รหัสส่วนขยายของเขาในไลบรารี DHTNew อย่างชาญฉลาด ดร. วีลเลอร์ได้แบ่งการทำงานของไลบรารี DHTNew ข้ามด้าน Arduino และ pymata4 ของสมการเพื่อให้มีการบล็อกน้อยที่สุดในด้าน Arduino

หากเราดูที่ DHTNew การดำเนินการทั้งหมดต่อไปนี้:

  • ตั้งค่าโหมดเอาต์พุตดิจิตอลพินที่เลือก
  • จับเวลาสัญญาณที่เข้ารหัสเพื่อรับค่าความชื้นและอุณหภูมิล่าสุด
  • ตรวจสอบและรายงานข้อผิดพลาดใด ๆ
  • คำนวณค่าอุณหภูมิและความชื้นที่มนุษย์อ่านได้จากข้อมูลดิบที่ดึงมา

เพื่อให้สิ่งต่าง ๆ มีประสิทธิภาพมากที่สุดบนฝั่ง FirmataExpress Dr. Wheeler ได้ลดขั้นตอนการแปลงข้อมูลจาก Arduino ไปเป็น pymata4

ขั้นตอนที่ 3: การปรับเปลี่ยน FirmataExpress สำหรับ DHT Support

โครงสร้างไดเรกทอรี FirmataExpress

ด้านล่างนี้คือไฟล์ทั้งหมดที่ประกอบด้วยที่เก็บ FirmataExpress แผนผังนี้เหมือนกับ StandardFiramata เพียงว่าชื่อไฟล์บางชื่อสะท้อนถึงชื่อที่เก็บ

ไฟล์ที่ต้องแก้ไขคือไฟล์ที่มีเครื่องหมายดอกจัน (*) อยู่ข้างๆ

FirmataExpress

├── * Boards.h

├── ตัวอย่าง

│ └── FirmataExpress

│ ├── บอร์ดx

│ ├── * FirmataExpress.ino

│ ├── LICENSE.txt

│ └── เมคไฟล์

├── * FirmataConstants.h

├── * FirmataDefines.h

├── FirmataExpress.cpp

├── FirmataExpress.h

├── FirmataMarshaller.cpp

├── FirmataMarshaller.h

├── FirmataParser.cpp

└── FirmataParser.h

มาดูไฟล์แต่ละไฟล์และการเปลี่ยนแปลงที่ทำกัน

Boards.h

ไฟล์นี้มีคำจำกัดความมาโครประเภทพินสำหรับบอร์ดแต่ละประเภทที่รองรับ กำหนดจำนวนอุปกรณ์สูงสุดที่รองรับเมื่อต้องรองรับอุปกรณ์มากกว่าหนึ่งเครื่อง

สำหรับอุปกรณ์ DHT สามารถเชื่อมต่ออุปกรณ์ได้สูงสุด 6 เครื่องในแต่ละครั้ง และค่านี้ถูกกำหนดเป็น:

#ifndef MAX_DHTS

#define MAX_DHTS 6 #endif

นอกจากนี้ อาจกำหนดมาโครประเภทพินสำหรับอุปกรณ์ใหม่ ไม่ว่าจะเป็นสำหรับบอร์ดทุกประเภทหรือเฉพาะรายการที่คุณสนใจ มาโครเหล่านี้ส่วนใหญ่ใช้เพื่อวัตถุประสงค์ในการรายงานและไม่ได้ใช้เพื่อควบคุมอุปกรณ์ มาโครเหล่านี้กำหนดหมุดทั้งสองที่รองรับอุปกรณ์:

#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 ล่าสุดกลับไปยังไคลเอนต์

ค่าคงที่คงที่ int DHT_CONFIG = 0x64;

ค่าคงที่คงที่ int DHT_DATA = 0x65;

โหมดพินถูกระบุในไฟล์นี้ด้วย สำหรับ DHT มีการสร้างโหมดพินใหม่:

ค่าคงที่ int PIN_MODE_DHT = 0x0F; // พินกำหนดค่าสำหรับ DHT

เมื่อเพิ่มโหมดพินใหม่ ต้องปรับ TOTAL_PIN_MODES:

ค่าคงที่คงที่ int TOTAL_PIN_MODES = 17;

FirmataDefines.h

ไฟล์นี้ต้องได้รับการอัปเดตเพื่อแสดงข้อความใหม่ที่เพิ่มไปยัง 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 ตอบกลับ #ifdef PIN_MODE_DHT_DE_Ddefine::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 nextDHT = 0; // ทำดัชนีเป็น dht สำหรับอุปกรณ์ถัดไปที่จะอ่าน

uint8_t ปัจจุบันDHT = 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]; ถ้า (numActiveDHTs < MAX_DHTS) { ถ้า (DHT_type == 22) { DHT_WakeUpDelay [numActiveDHTs] = 1; } else if (DHT_type == 11) { DHT_WakeUpDelay[numActiveDHTs] = 18; } อื่น { Firmata.sendString ("ข้อผิดพลาด: ประเภทเซ็นเซอร์ที่ไม่รู้จัก เซ็นเซอร์ที่ถูกต้องคือ 11, 22"); หยุดพัก; } // ทดสอบเซ็นเซอร์ DHT_PinNumbers[numActiveDHTs] = DHT_Pin; DHT_TYPE[numActiveDHTs] = DHT_type; 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_type); สำหรับ (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);

ถ้า (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; ปัจจุบันDHT = nextDHT; if (nextDHT++ >= numActiveDHTs - 1) { nextDHT = 0; } if (rv == DHTLIB_OK) { // TEST CHECKSUM uint8_t sum = _bits[0] + _bits[1] + _bits[2] + _bits[3]; ถ้า (_bits[4] != ผลรวม) { rv = -1; } } // ส่งข้อความกลับพร้อมสถานะข้อผิดพลาด Firmata.write(START_SYSEX); Firmata.write(DHT_DATA); Firmata.write(current_pin); Firmata.write(current_type); สำหรับ (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) 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) // ไบต์ถัดไป? { mask = 128; idx++; } } ส่งคืน DHTLIB_OK; }

ขั้นตอนที่ 4: การปรับเปลี่ยน Pymata4 สำหรับ DHT Support

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 config DHT_DATA = 0x65 # dht เซ็นเซอร์ตอบกลับ

ประเภทพินที่เพิ่มและคำสั่ง SysEx ต้องตรงกับค่าใน FirmataConstants.h ที่เพิ่มใน FirmataExpress

pymata4.py

Pymata4 ใช้พจนานุกรม Python เพื่อเชื่อมโยงข้อความ Firmata ขาเข้ากับตัวจัดการข้อความอย่างรวดเร็ว ชื่อของพจนานุกรมนี้คือ report_dispatch

รูปแบบของรายการพจนานุกรมคือ:

{รหัสข้อความ: [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 และรหัสไคลเอนต์ pymata4 ที่ใช้ Python รหัส FirmataExpress สามารถแก้ปัญหาได้ยาก มีการเพิ่มวิธีการที่เรียกว่า printData ใน FirmataExpress เพื่อช่วยในการดีบัก วิธีนี้ช่วยให้คุณส่งค่าข้อมูลจาก FirmataExpress และพิมพ์บนคอนโซล pymata4

ฟังก์ชันนี้ต้องการทั้งตัวชี้ไปยังสตริงอักขระและค่าที่คุณต้องการดู หากค่าข้อมูลอยู่ในตัวแปรที่เรียกว่า argc คุณอาจเรียก printData ด้วยพารามิเตอร์ต่อไปนี้

printData((ถ่าน*)"argc= ", argc);

หากคุณมีคำถามใด ๆ เพียงแค่แสดงความคิดเห็นและเรายินดีที่จะตอบ

มีความสุขในการเข้ารหัส!

แนะนำ: