สารบัญ:

Arduino และ PCF8591 ADC DAC IC: 7 ขั้นตอน
Arduino และ PCF8591 ADC DAC IC: 7 ขั้นตอน

วีดีโอ: Arduino และ PCF8591 ADC DAC IC: 7 ขั้นตอน

วีดีโอ: Arduino และ PCF8591 ADC DAC IC: 7 ขั้นตอน
วีดีโอ: #42 สอน Arduino Tutorial : Arduino PCF8591 ขยายขา Analog 2024, กรกฎาคม
Anonim
Arduino และ PCF8591 ADC DAC IC
Arduino และ PCF8591 ADC DAC IC

คุณเคยต้องการพินอินพุตแบบอะนาล็อกเพิ่มเติมในโครงการ Arduino ของคุณ แต่ไม่ต้องการแยกออกเป็นเมก้าหรือไม่? หรือคุณต้องการสร้างสัญญาณอะนาล็อก? จากนั้นตรวจสอบหัวข้อของบทช่วยสอนของเรา – NXP PCF8591 IC

มันแก้ปัญหาทั้งสองนี้เพราะมีตัวแปลง DAC (ดิจิทัลเป็นอะนาล็อก) เดียวและ ADC สี่ตัว (ตัวแปลงอนาล็อกเป็นดิจิทัล) - ทั้งหมดเข้าถึงได้ผ่านบัส I2C PCF8591 มีจำหน่ายในรูปแบบ DIP, Surface Mount และโมดูล ซึ่งทำให้ง่ายต่อการทดลอง

ก่อนดำเนินการ ดาวน์โหลดเอกสารข้อมูล PCF8591 สามารถทำงานได้ทั้ง 5V และ 3.3V ดังนั้นหากคุณใช้ Arduino Due, Raspberry Pi หรือบอร์ดพัฒนา 3.3 V อื่น ๆ คุณก็ไม่เป็นไร ตอนนี้เราจะอธิบาย DAC ก่อน ตามด้วย ADC

ขั้นตอนที่ 1: การใช้ DAC (ตัวแปลงดิจิทัลเป็นอนาล็อก)

การใช้ DAC (ตัวแปลงดิจิตอลเป็นอนาล็อก)
การใช้ DAC (ตัวแปลงดิจิตอลเป็นอนาล็อก)

DAC บน PCF8591 มีความละเอียด 8 บิต ดังนั้นจึงสามารถสร้างสัญญาณทางทฤษฎีระหว่างศูนย์โวลต์และแรงดันอ้างอิง (Vref) ได้ใน 255 ขั้นตอน เพื่อจุดประสงค์ในการสาธิต เราจะใช้ Vref ที่ 5V และคุณสามารถใช้ Vref ที่ต่ำกว่า เช่น 3.3V หรืออะไรก็ได้ที่คุณต้องการให้ค่าสูงสุดเป็น … แต่จะต้องน้อยกว่าแรงดันไฟฟ้าของแหล่งจ่าย

โปรดทราบว่าเมื่อมีโหลดบนเอาต์พุตอะนาล็อก (สถานการณ์ในโลกแห่งความเป็นจริง) แรงดันเอาต์พุตสูงสุดจะลดลง - แผ่นข้อมูล (ที่คุณดาวน์โหลด) จะแสดงการลดลง 10% สำหรับโหลด10kΩ ตอนนี้สำหรับวงจรสาธิตของเรา

สังเกตการใช้ตัวต้านทานแบบดึงขึ้น10kΩบนบัส I2C และตัวเก็บประจุ10μFระหว่าง 5V และ GND ที่อยู่บัส I2C ถูกกำหนดโดยการรวมกันของพิน A0~A2 และสำหรับ GND ที่อยู่ทั้งหมดคือ 0x90 เอาต์พุตอะนาล็อกสามารถนำมาจากพิน 15 (และมี GND อะนาล็อกแยกต่างหากบนพิน 13 นอกจากนี้ให้เชื่อมต่อพิน 13 กับ GND และวงจร GND กับ Arduino GND

เพื่อควบคุม DAC เราจำเป็นต้องส่งข้อมูลสองไบต์ อันแรกคือไบต์ควบคุม ซึ่งเปิดใช้งาน DAC อย่างง่ายๆ และเท่ากับ 1000000 (หรือ 0x40) และไบต์ถัดไปคือค่าระหว่าง 0 ถึง 255 (ระดับเอาต์พุต) สิ่งนี้แสดงให้เห็นในร่างต่อไปนี้:

// ตัวอย่าง 52.1 PCF8591 การสาธิต DAC

#include "Wire.h" #define PCF8591 (0x90 >> 1) // ที่อยู่บัส I2C เป็นโมฆะการตั้งค่า () { Wire.begin (); } void loop() { สำหรับ (int i=0; i<256; i++) { Wire.beginTransmission(PCF8591); // ปลุก PCF8591 Wire.write(0x40); // ไบต์ควบคุม - เปิด DAC (ไบนารี 1000000) Wire.write (i); // ค่าที่จะส่งไปยัง DAC Wire.endTransmission(); // สิ้นสุดการส่ง }

สำหรับ (int i=255; i>=0; --i)

{ Wire.beginTransmission (PCF8591); // ปลุก PCF8591 Wire.write(0x40); // ไบต์ควบคุม - เปิด DAC (ไบนารี 1000000) Wire.write (i); // ค่าที่จะส่งไปยัง DAC Wire.endTransmission(); // สิ้นสุดการส่ง } }

คุณสังเกตเห็นการเปลี่ยนแปลงบิตของที่อยู่บัสในคำสั่ง #define หรือไม่? Arduino ส่งที่อยู่ 7 บิต แต่ PCF8591 ต้องการ 8 บิต ดังนั้นเราจึงเลื่อนไบต์ไปหนึ่งบิต

ขั้นตอนที่ 2:

ภาพ
ภาพ

ผลลัพธ์ของภาพสเก็ตช์จะแสดงในภาพ เราได้เชื่อมต่อ Vref กับ 5V และออสซิลโลสโคปโพรบและ GND กับเอาต์พุตแบบอะนาล็อกและ GND ตามลำดับ

ขั้นตอนที่ 3:

ภาพ
ภาพ

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

// ตัวอย่าง 52.2 PCF8591 การสาธิต DAC - คลื่นไซน์

#include "Wire.h" #define PCF8591 (0x90 >> 1) // ที่อยู่บัส I2C uint8_t sine_wave[256] = { 0x80, 0x83, 0x86, 0x89, 0x8C, 0x90, 0x93, 0x96, 0x99, 0x9C, 0x9F, 0xA2, 0xA5, 0xA8, 0xAB, 0xAE, 0xB1, 0xB3, 0xB6, 0xB9, 0xBC, 0xBF, 0xC1, 0xC4, 0xC7, 0xC9, 0xCC, 0xCE, 0xD1, 0xD3, 0xD5, 0xDE0, 0xE0,E0,E 0xE2, 0xE4, 0xE6, 0xE8, 0xEA, 0xEB, 0xED, 0xEF, 0xF0, 0xF1, 0xF3, 0xF4, 0xF5, 0xF6, 0xF8, 0xF9, 0xFA, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFE, 0xFE, 0xFD, 0xFD, 0xFC, 0xFB, 0xFA, 0xFA, 0xF9, 0xF8, 0xF6, 0xF5, 0xF4, 0xF3, 0xF0, 0xF1 0xED, 0xEB, 0xEA, 0xE8, 0xE6, 0xE4, 0xE2, 0xE0, 0xDE, 0xDC, 0xDA, 0xD8, 0xD5, 0xD3, 0xD1, 0xCE, 0xCC, 0xC9, 0xC7, 0xC4, BF, 0xC1, 0xB. 0xB3, 0xB1, 0xAE, 0xAB, 0xA8, 0xA5, 0xA2, 0x9F, 0x9C, 0x99, 0x96, 0x93, 0x90, 0x8C, 0x89, 0x86, 0x83, 0x80, 0x7D, 0x7A, 0x77, 0x74, 0x74 0x67, 0x64, 0x61, 0x5E, 0x5B, 0x58, 0x55, 0x52, 0x4F, 0x4D, 0x4A, 0x47, 0x44, 0x41, 0x3F, 0x 3C, 0x39, 0x37, 0x34, 0x32, 0x2F, 0x2D, 0x2B, 0x28, 0x26, 0x24, 0x22, 0x20, 0x1E, 0x1C, 0x1A, 0x18, 0x16, 0x15, 0x13, 0x11, 0x10, 0x0, 0D0F 0x0B, 0x0A, 0x08, 0x07, 0x06, 0x06, 0x05, 0x04, 0x03, 0x03, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x07, 0x08, 0x0A, 0x0B, 0x0C, 0x0D, 0x0F, 0x10, 0x11, 0x13, 0x15, 0x16, 0x18, 0x1A, 0x1C, 0x1E, 0x2024, 0x22, 0x18, 0x1A, 0x1C, 0x1E, 0x2024, 0x22, 0x22, 0x04 0x2B, 0x2D, 0x2F, 0x32, 0x34, 0x37, 0x39, 0x3C, 0x3F, 0x41, 0x44, 0x47, 0x4A, 0x4D, 0x4F, 0x52, 0x55, 0x58, 0x5B, 0x5E, 0x61, 0x64, 0x58, 0x5B, 0x5E, 0x61, 0x64 0x70, 0x74, 0x77, 0x7A, 0x7D }; การตั้งค่าเป็นโมฆะ () { Wire.begin (); } void loop() { สำหรับ (int i=0; i<256; i++) { Wire.beginTransmission(PCF8591); // ปลุก PCF8591 Wire.write(0x40); // ไบต์ควบคุม - เปิด DAC (ไบนารี 1000000) Wire.write (sine_wave); // ค่าที่จะส่งไปยัง DAC Wire.endTransmission(); // สิ้นสุดการส่ง } }

ขั้นตอนที่ 4:

ภาพ
ภาพ

สำหรับการดัมพ์อิมเมจ DSO ต่อไปนี้ เราเปลี่ยน Vref เป็น 3.3V – สังเกตการเปลี่ยนแปลงสูงสุดบนคลื่นไซน์

ตอนนี้คุณสามารถทดลองกับ DAC เพื่อสร้างเอฟเฟกต์เสียง สัญญาณ หรือควบคุมวงจรอนาล็อกอื่นๆ

ขั้นตอนที่ 5: การใช้ ADC (ตัวแปลงอนาล็อกเป็นดิจิทัล)

หากคุณเคยใช้ฟังก์ชัน analogRead() บน Arduino ของคุณ (ย้อนกลับไปในบทที่หนึ่ง) แสดงว่าคุณคุ้นเคยกับ ADC แล้ว หากไม่มี PCF8591 เราสามารถอ่านแรงดันไฟฟ้าระหว่างศูนย์และ Vref และจะคืนค่าระหว่างศูนย์ถึง 255 ซึ่งเป็นสัดส่วนโดยตรงกับศูนย์และ Vref

ตัวอย่างเช่น การวัด 3.3V ควรคืนค่า 168 ความละเอียด (8 บิต) ของ ADC ต่ำกว่า Arduino (10 บิต) ออนบอร์ด อย่างไรก็ตาม PCF8591 สามารถทำสิ่งที่ ADC ของ Arduino ไม่สามารถทำได้ แต่เราจะไปที่นั้นในอีกสักครู่ ขั้นแรก เพียงแค่อ่านค่าของพิน ADC แต่ละตัว เราส่งไบต์ควบคุมเพื่อบอก PCF8591 ว่า ADC ใดที่เราต้องการอ่าน สำหรับ ADCs ศูนย์ถึงสาม ไบต์ควบคุมคือ 0x00, 0x01, ox02 และ 0x03 ตามลำดับ

จากนั้นเราขอข้อมูลสองไบต์กลับจาก ADC และเก็บไบต์ที่สองไว้เพื่อใช้งาน ทำไมต้องสองไบต์? PCF8591 ส่งคืนค่าที่วัดก่อนหน้านี้ก่อน แล้วจึงคืนค่าเป็นไบต์ปัจจุบัน (ดูรูปที่ 8 ในแผ่นข้อมูล) สุดท้าย หากคุณไม่ได้ใช้พิน ADC ทั้งหมด ให้เชื่อมต่อพินที่ไม่ได้ใช้กับ GND ตัวอย่างภาพสเก็ตช์ต่อไปนี้จะดึงค่าจากแต่ละพิน ADC ทีละตัว จากนั้นแสดงในจอภาพแบบอนุกรม:

#รวม "Wire.h"

#define PCF8591 (0x90 >> 1) // ที่อยู่บัส I2C #define ADC0 0x00 // ไบต์ควบคุมสำหรับการอ่าน ADC แต่ละรายการ #define ADC1 0x01 #define ADC2 0x02 #define ADC3 0x03 ไบต์ value0, value1, value2, value3; การตั้งค่าเป็นโมฆะ () { Wire.begin (); Serial.begin(9600); } วงเป็นโมฆะ () { Wire.beginTransmission (PCF8591); // ปลุก PCF8591 Wire.write (ADC0); // ไบต์ควบคุม - อ่าน ADC0 Wire.endTransmission (); // สิ้นสุดการส่ง Wire.requestFrom(PCF8591, 2); value0=Wire.read(); value0=Wire.read(); Wire.beginการส่ง(PCF8591); // ปลุก PCF8591 Wire.write (ADC1); // ไบต์ควบคุม - อ่าน ADC1 Wire.endTransmission(); // สิ้นสุดการส่ง Wire.requestFrom(PCF8591, 2); value1=Wire.read(); value1=Wire.read(); Wire.beginการส่ง(PCF8591); // ปลุก PCF8591 Wire.write (ADC2); // ไบต์ควบคุม - อ่าน ADC2 Wire.endTransmission (); // สิ้นสุดการส่ง Wire.requestFrom(PCF8591, 2); value2=Wire.read(); value2=Wire.read(); Wire.beginการส่ง(PCF8591); // ปลุก PCF8591 Wire.write (ADC3); // ไบต์ควบคุม - อ่าน ADC3 Wire.endTransmission (); // สิ้นสุดการส่ง Wire.requestFrom(PCF8591, 2); value3=Wire.read(); value3=Wire.read(); Serial.print(value0); Serial.print(" "); Serial.print(value1); Serial.print(" "); Serial.print(value2); Serial.print(" "); Serial.print(value3); Serial.print(" "); Serial.println(); }

เมื่อรันแบบร่าง คุณจะเห็นค่าของ ADC แต่ละตัวในจอภาพแบบอนุกรม แม้ว่าจะเป็นการสาธิตง่ายๆ เพื่อแสดงให้คุณเห็นวิธีการอ่าน ADC แต่ละรายการ แต่เป็นวิธีที่ยุ่งยากในการรับไบต์จาก ADC หนึ่งๆ ในแต่ละครั้ง

ขั้นตอนที่ 6:

เมื่อต้องการทำเช่นนี้ เปลี่ยนไบต์ควบคุมเพื่อขอเพิ่มอัตโนมัติ ซึ่งทำได้โดยการตั้งค่าบิต 2 ของไบต์ควบคุมเป็น 1 ดังนั้น เพื่อเริ่มต้นจาก ADC0 เราใช้ไบต์ควบคุมใหม่ของไบนารี 00000100 หรือเลขฐานสิบหก 0x04 จากนั้นขอข้อมูลห้าไบต์ (เราละเว้นไบต์แรกอีกครั้ง) ซึ่งจะทำให้ PCF8591 ส่งคืนค่าทั้งหมดในสายไบต์เดียว กระบวนการนี้แสดงให้เห็นในภาพร่างต่อไปนี้:

#รวม "Wire.h"

#define PCF8591 (0x90 >> 1) // ที่อยู่บัส I2C ไบต์ value0, value1, value2, value3; การตั้งค่าเป็นโมฆะ () { Wire.begin (); Serial.begin(9600); } วงเป็นโมฆะ () { Wire.beginTransmission (PCF8591); // ปลุก PCF8591 Wire.write(0x04); // ไบต์ควบคุม - อ่าน ADC0 จากนั้นเพิ่ม Wire.endTransmission(); // สิ้นสุดการส่ง Wire.requestFrom(PCF8591, 5); value0=Wire.read(); value0=Wire.read(); value1=Wire.read(); value2=Wire.read(); value3=Wire.read(); Serial.print(value0); Serial.print(" "); Serial.print(value1); Serial.print(" "); Serial.print(value2); Serial.print(" "); Serial.print(value3); Serial.print(" "); Serial.println(); }

ก่อนหน้านี้เรากล่าวว่า PCF8591 สามารถทำสิ่งที่ ADC ของ Arduino ไม่สามารถทำได้ และนี่คือ ADC ที่แตกต่างกัน ตรงข้ามกับ single-end ของ Arduino (กล่าวคือส่งคืนความแตกต่างระหว่างแรงดันสัญญาณบวกและ GND ค่า ADC ที่แตกต่างกันจะรับสัญญาณสองสัญญาณ (ซึ่งไม่จำเป็นต้องอ้างอิงถึงกราวด์) และส่งคืนความแตกต่างระหว่างสัญญาณทั้งสอง. ซึ่งสะดวกสำหรับการวัดการเปลี่ยนแปลงเล็กน้อยของแรงดันไฟฟ้าสำหรับโหลดเซลล์และอื่นๆ

ขั้นตอนที่ 7:

ภาพ
ภาพ

การตั้งค่า PCF8591 สำหรับ ADC ที่แตกต่างกันนั้นเป็นเรื่องง่ายในการเปลี่ยนไบต์ควบคุม หากคุณเปิดไปยังหน้าเจ็ดของแผ่นข้อมูล ให้พิจารณาประเภทต่าง ๆ ของการเขียนโปรแกรมอินพุตแบบอะนาล็อก ก่อนหน้านี้เราใช้โหมด '00' สำหรับอินพุตสี่ช่อง อย่างไรก็ตาม คุณสามารถเลือกรูปแบบอื่นๆ ที่แสดงอย่างชัดเจนได้ เช่น รูปภาพ

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

หวังว่าคุณจะพบสิ่งที่น่าสนใจ ไม่ว่าจะเป็นการเพิ่ม DAC ให้กับการทดลองของคุณ หรือเรียนรู้เพิ่มเติมเกี่ยวกับ ADC อีกเล็กน้อย โปรดพิจารณาสั่งซื้อ PCF8591 จาก PMD Way

โพสต์นี้มาถึงคุณโดย pmdway.com – ทุกอย่างสำหรับผู้ผลิตและผู้ที่ชื่นชอบอุปกรณ์อิเล็กทรอนิกส์ พร้อมบริการจัดส่งฟรีทั่วโลก

แนะนำ: