สารบัญ:
- เสบียง
- ขั้นตอนที่ 1: วางเขียงหั่นขนม
- ขั้นตอนที่ 2: ประเมินสัญญาณถึงระดับเสียงรบกวน
- ขั้นตอนที่ 3: ความไม่เชิงเส้นเชิงปริพันธ์และความไม่เชิงเส้นเชิงอนุพันธ์
- ขั้นตอนที่ 4: แบนด์วิดท์
- ขั้นตอนที่ 5: ปิดความคิด
วีดีโอ: วิธีสร้างและทดสอบ DAC ที่ดีขึ้นด้วย ESP32: 5 ขั้นตอน
2024 ผู้เขียน: John Day | [email protected]. แก้ไขล่าสุด: 2024-01-30 13:03
ESP32 มีตัวแปลงดิจิทัลเป็นอนาล็อก (DAC) 8 บิต 2 ตัว DAC เหล่านี้ช่วยให้เราสร้างแรงดันไฟฟ้าตามอำเภอใจได้ภายในช่วงที่กำหนด (0-3.3V) ด้วยความละเอียด 8 บิต ในคำแนะนำนี้ ฉันจะแสดงวิธีสร้าง DAC และกำหนดลักษณะการทำงานของมัน รวมทั้งเปรียบเทียบกับ ESP32 DAC ดัชนีประสิทธิภาพฉันจะดูรวมถึง
- ระดับเสียง
- แบนด์วิดธ์
- ความไม่เชิงเส้นเชิงปริพันธ์
- ความไม่เชิงเส้นเชิงอนุพันธ์
เพื่อทดสอบดัชนีเหล่านี้ ฉันจะใช้ ADS1115
สิ่งสำคัญคือต้องทราบว่าการประเมินดัชนีทั้งหมดของคุณจะแม่นยำเท่ากับอุปกรณ์อ้างอิงของคุณเท่านั้น (ในกรณีนี้คือ ADS115) ตัวอย่างเช่น ADS115 ไม่มีความแม่นยำ 16 บิตเมื่อพูดถึงการชดเชยแรงดันไฟฟ้าและอัตราขยาย ข้อผิดพลาดเหล่านี้อาจมีขนาดใหญ่ถึง 0.1% สำหรับระบบจำนวนมาก ข้อผิดพลาดเหล่านี้สามารถละเลยได้เมื่อมีความกังวลอย่างจำกัดถึงความถูกต้องสมบูรณ์
เสบียง
- ADS1115
- บอร์ด ESP32
- เขียงหั่นขนม
- สายจัมเปอร์
- ตัวต้านทาน 5 kOhm
- ตัวเก็บประจุเซรามิกไมโครฟารัด 1 ตัว
ขั้นตอนที่ 1: วางเขียงหั่นขนม
ต่อหมุดต่อไปนี้
ระหว่าง ESP32 และ ADS1115
3v3 VDD
GND GND
GPIO22 SCL
GPIO21 SDA
ที่ ADS1115
ADDR GND (ADS115)
การทำ DAC
มีหลายวิธีในการสร้าง DAC วิธีที่ง่ายที่สุดคือกรองสัญญาณความถี่ต่ำผ่านสัญญาณ PWM พร้อมตัวต้านทานและตัวเก็บประจุ ฉันสามารถเพิ่ม op-amp ที่นี่เป็นบัฟเฟอร์ได้ แต่ต้องการให้สิ่งต่าง ๆ ง่ายขึ้น การออกแบบนี้ง่ายและราคาถูกในการใช้งานกับไมโครคอนโทรลเลอร์ที่รองรับ PWM ฉันจะไม่พูดถึงทฤษฎีการออกแบบที่นี่ (google PWM DAC)
เพียงเชื่อมต่อตัวต้านทาน GPIO255 KOhm 1 microFarad Capacitor gnd
ตอนนี้เชื่อมต่อสายจัมเปอร์จากจุดที่ตัวต้านทานตรงกับตัวเก็บประจุถึง A0 บน ADS115
ขั้นตอนที่ 2: ประเมินสัญญาณถึงระดับเสียงรบกวน
ในการประเมินระดับเสียง ให้เรียกใช้สคริปต์ด้านล่าง ในการประเมินสิ่งนี้ เราเพียงแค่ปล่อยให้ DAC เป็นค่าคงที่และวัดว่าแรงดันไฟฟ้าผันผวนอย่างไรเมื่อเวลาผ่านไป
เนื่องจากการออกแบบ DAC เสียงรบกวนจะสูงสุดเมื่อสัญญาณ PWM อยู่ที่ 50% รอบการทำงาน ดังนั้นนี่คือที่ที่เราจะประเมิน เราจะประเมิน ESP32 ที่ระดับสัญญาณเดียวกันนี้ด้วย นอกจากนี้เรายังจะกรอง ESP32 DAC ด้วยตัวกรองความถี่ต่ำเดียวกัน เพื่อให้สามารถเปรียบเทียบการวัดได้
สำหรับฉันผลลัพธ์นั้นชัดเจน การออกแบบ PWM มี SNR ที่ดีกว่า >6dB (ดีกว่า 2 เท่า) ชัยชนะที่ชัดเจนสำหรับ DAC ใหม่ ความสับสนเล็กน้อยประการหนึ่งคือมีตัวกรองที่สร้างขึ้นใน ADC ที่เพิ่มประสิทธิภาพ SNR ได้อย่างแน่นอนที่สุด ดังนั้นค่าสัมบูรณ์อาจตีความได้ยาก ถ้าฉันใช้ตัวกรองอันดับสอง จะไม่เป็นเช่นนั้น
รหัสอยู่ด้านล่าง
#รวม
#include โฆษณา Adafruit_ADS1115; // ห้องสมุด adafruit สำหรับ adc int16_t adc0; // การตั้งค่าเป็นโมฆะ (เป็นโมฆะ) { Serial.begin (115200); // เริ่มโฆษณาแบบอนุกรม setGain(GAIN_TWO); // 2x ได้รับ +/- 2.048V 1 บิต =0.0625mV ads.begin(); // เริ่ม adc float M = 0; // ค่าเฉลี่ยเริ่มต้นลอย Mp = 0; // previouos หมายถึง float S = 0; // ความแปรปรวนเริ่มต้นลอย Sp = 0; // ความแปรปรวนก่อนหน้า const int reps = 500; // จำนวนการทำซ้ำ int n = 256; // จำนวนตัวอย่าง ledcSetup(0, 25000, 8); // ตั้งค่า pwm frequecny =25000 Hz ที่ความละเอียด 8 บิต ledcAttachPin(25, 0); // ตั้งค่า pwm บนพิน 25 ledcWrite(0, 128); // ตั้งค่าเป็นครึ่งรอบการทำงาน (เสียงรบกวนที่ใหญ่ที่สุด) ล่าช้า (3000); // รอการชำระเวลา float snrPWM[reps]; // อาร์เรย์ของ snrs สำหรับ PWM float snrDAC[reps]; // อาร์เรย์ของ snrs สำหรับ DAC สำหรับ (int i = 0; i < reps; i++) { // loope over repititions for (int k = 1; k < (n + 1); k++) { // loope เหนือตัวอย่าง adc0 = ads.readADC_SingleEnded(0); // อ่าน M = Mp + (adc0 - Mp) / k; // คำนวณค่าเฉลี่ยกลิ้ง Mp = M; // ตั้งค่าค่าเฉลี่ยก่อนหน้า S = Sp + (adc0 - Mp) * (adc0 - M); // คำนวณความแปรปรวนการกลิ้ง Sp = S; // ตั้งค่าความแปรปรวนก่อนหน้า } // snr เป็น dB snrPWM = 20 * log10(3.3 / (sqrt(S / n) *.0625 *.001)); // รีเซ็ตค่า M = 0; Mp = 0; ส = 0; Sp = 0; } ledcDetachPin(25); // ถอด PWM ออกจากพิน 25 dacWrite (25, 128); // เขียนไปยัง DAC ล่าช้า (3000); // รอชำระ (int i = 0; i < reps; i++) { // เหมือนกับ PWM loop for (int k = 1; k < (n + 1); k++) { adc0 = ads.readADC_SingleEnded (0); M = Mp + (adc0 - Mp) / k; Mp = ม; S = Sp + (adc0 - Mp) * (adc0 - M); Sp = S; } snrDAC = 20 * log10(3.3 / (sqrt(S / n) *.0625 *.001)); ม = 0; Mp = 0; ส = 0; Sp = 0; } // พล็อต SNR บนกราฟเดียวสำหรับ (int i = 1; i < reps; i++) { Serial.print("PWM_SNR(dB):"); Serial.print(snrPWM[ผม]); Serial.print(", "); Serial.print("ESP32_SNR(dB):"); Serial.println(snrDAC); } } โมฆะลูป (โมฆะ) { }
ขั้นตอนที่ 3: ความไม่เชิงเส้นเชิงปริพันธ์และความไม่เชิงเส้นเชิงอนุพันธ์
ความไม่เชิงเส้นเชิงปริพันธ์คือการวัดค่าความเบี่ยงเบนโดยประมาณระหว่างแรงดันเอาต์พุต DAC กับเส้นตรงของคุณ ยิ่งโตยิ่งแย่…
ความไม่เชิงเส้นเชิงอนุพันธ์คือการวัดคร่าวๆ ว่าการเปลี่ยนแปลงของแรงดันไฟฟ้าที่สังเกตได้ (จากโค้ดหนึ่งไปยังโค้ดถัดไป) เบี่ยงเบนไปจากสิ่งที่คาดหวังจากเส้นตรงมากน้อยเพียงใด
ผลลัพธ์ที่นี่น่าสนใจจริงๆ อย่างแรกเลย ทั้งคู่มีข้อผิดพลาดน้อยกว่า 0.5lsb (ที่ความละเอียด 8 บิต) ซึ่งถือว่าดี แต่ PWM มีความเป็นเส้นตรงของอินทิกรัลที่ดีกว่ามาก ทั้งสองมีความไม่เชิงเส้นเชิงอนุพันธ์ที่เปรียบเทียบกันได้ แต่ ESP32 DAC มีหนามแหลมที่แปลกประหลาดมาก ยิ่งไปกว่านั้น วิธี PWM มีโครงสร้างบางอย่างเกี่ยวกับข้อผิดพลาด โดยพื้นฐานแล้วจะเกินและ undershoots แรงดันไฟฟ้าที่ถูกต้องในแบบสลับกัน
ความสงสัยของฉันคือนี่เป็นข้อผิดพลาดในการปัดเศษแปลก ๆ ในการสร้างสัญญาณ PWM 8 บิตบน ESP32
วิธีหนึ่งในการแก้ไขปัญหานี้คือวนรอบอย่างรวดเร็วระหว่างสองรหัสที่อยู่ติดกัน (เช่น 128, 129) กับ PWM ด้วยตัวกรองสัญญาณความถี่ต่ำแบบอะนาล็อก ข้อผิดพลาดที่ได้จะเฉลี่ยเป็นศูนย์ ฉันจำลองสิ่งนี้ในซอฟต์แวร์และข้อผิดพลาดทั้งหมดหายไปอย่างแน่นอน ตอนนี้วิธี PWM มีความเป็นเส้นตรงที่แม่นยำถึง 16 บิต!
ใครก็ตามที่รหัสเพื่อสร้างข้อมูลอยู่ด้านล่าง เอาต์พุตจะอยู่บนจอภาพอนุกรมในรูปแบบ.csv เพียงคัดลอกไปยังไฟล์ข้อความเพื่อดำเนินการต่อไป
#รวม
#include โฆษณา Adafruit_ADS1115; /* ใช้สำหรับเวอร์ชัน 16 บิต */ int16_t adc0; การตั้งค่าเป็นโมฆะ (เป็นโมฆะ) { Serial.begin (115200); ads.setGain(GAIN_ONE); // 2x ได้รับ +/- 2.048V 1 บิต = 1mV 0.0625mV ads.begin(); ledcSetup(0, 25000, 8); ledcAttachPin(25, 0); Serial.println("คาดหวัง, สังเกต"); ledcWrite(0, 2); ล่าช้า (3000); สำหรับ (int i = 2; i <255; i++) { ledcWrite(0, i); ล่าช้า (100); adc0 = ads.readADC_SingleEnded(0); ลอยตัว = (i / 256.0 * 3.3) / 4.096 * 32767; Serial.print (คาดว่า); Serial.print(", "); Serial.println(adc0); } } โมฆะลูป (โมฆะ) { }
ขั้นตอนที่ 4: แบนด์วิดท์
ฉันจะกำหนดแบนด์วิดธ์ตามความถี่ที่เอาต์พุตของ DAC ลดลง 3dB นี่เป็นอนุสัญญาและในระดับหนึ่งโดยพลการ ตัวอย่างเช่น ที่จุด 6dB DAC จะยังคงส่งสัญญาณออก โดยจะมีแอมพลิจูดประมาณ 50%
เพื่อวัดสิ่งนี้ เราเพียงแค่ส่งคลื่นไซน์ที่ความถี่ที่เพิ่มขึ้นจาก DAC ไปยัง ADC และวัดค่าเบี่ยงเบนมาตรฐานของพวกมัน ไม่น่าแปลกใจเลยที่จุด 3dB อยู่ที่ 30Hz (1/(2*pi*5000*1e-6))
ESP32 สามารถทำตัวอย่างได้ 1 เมกะต่อวินาที นี่เป็นชัยชนะแบบลงมือสำหรับ ESP32 แอมพลิจูดของมันไม่ลดลงเลยในพื้นที่ทดสอบแบนด์วิดท์ 100Hz
รหัสด้านล่างสามารถทดสอบแบนด์วิดท์ PWM DAC
#รวม
#include โฆษณา Adafruit_ADS1115; /* ใช้สำหรับเวอร์ชัน 16 บิต */ int16_t adc0; int16_t adc1; การตั้งค่าเป็นโมฆะ (เป็นโมฆะ) { float M; ลอย Mp = 0; ลอย S = 0; ลอย Sp = 0; Serial.begin(115200); ads.setGain(GAIN_ONE); // 1x ได้รับ +/- 4.096V 1 บิต = 2mV 0.125mV ads.begin(); ledcSetup(0, 25000, 8); ledcAttachPin(25, 0); ล่าช้า (5000); Serial.println("ความถี่, แอมพลิจูด"); สำหรับ (int i = 1; i <100; i++) { unsigned long start = millis(); ยาวที่ไม่ได้ลงนาม T = millis(); Sp = 0; ส = 0; ม = 0; Mp = 0; int k = 1; บรรทัดฐานลอย ในขณะที่ ((T - start) < 1000) { int out = 24 * sin(2 * PI * i * (T - start) / 1000.0) + 128; ledcWrite(0, ออก); adc0 = ads.readADC_SingleEnded(0); M = Mp + (adc0 - Mp) / k; Mp = ม; S = Sp + (adc0 - Mp) * (adc0 - M); Sp = S; T = มิลลิวินาที (); เค++; } if (i == 1) { norm = sqrt(S / k); } Serial.print(i); Serial.print(", "); Serial.println(sqrt(S / k) / บรรทัดฐาน 3); k = 0; } } โมฆะลูป (โมฆะ) { }
และรหัสนี้จะทดสอบแบนด์วิดธ์ ESP32 ตรวจสอบให้แน่ใจว่าได้ถอดตัวเก็บประจุออก ไม่เช่นนั้นผลลัพธ์จะเหมือนกันสำหรับทั้งสองวิธี
#รวม
#include โฆษณา Adafruit_ADS1115; /* ใช้สำหรับเวอร์ชัน 16 บิต */ int16_t adc0; int16_t adc1; การตั้งค่าเป็นโมฆะ (เป็นโมฆะ) { float M; ลอย Mp = 0; ลอย S = 0; ลอย Sp = 0; Serial.begin(115200); ads.setGain(GAIN_ONE); // 1x ได้รับ +/- 4.096V 1 บิต = 2mV 0.125mV ads.begin(); ล่าช้า (5000); Serial.println("ความถี่, แอมพลิจูด"); สำหรับ (int i = 1; i <100; i++) { unsigned long start = millis(); ยาวที่ไม่ได้ลงนาม T = millis(); Sp = 0; ส = 0; ม = 0; Mp = 0; int k = 1; บรรทัดฐานลอย ในขณะที่ ((T - start) < 1000) { int out = 24 * sin(2 * PI * i * (T - start) / 1000.0) + 128; dacWrite(25, ออก); adc0 = ads.readADC_SingleEnded(0); M = Mp + (adc0 - Mp) / k; Mp = ม; S = Sp + (adc0 - Mp) * (adc0 - M); Sp = S; T = มิลลิวินาที (); เค++; } if (i == 1) { norm = sqrt(S / k); } Serial.print(i); Serial.print(", "); Serial.println(sqrt(S / k) / บรรทัดฐาน 3); k = 0; } } โมฆะลูป (โมฆะ) { }
ขั้นตอนที่ 5: ปิดความคิด
การออกแบบ DAC ใหม่ชนะด้วยเส้นตรงและสัญญาณรบกวน แต่สูญเสียแบนด์วิดท์ ดัชนีเหล่านี้อาจมีความสำคัญมากกว่าดัชนีอื่นๆ ทั้งนี้ขึ้นอยู่กับแอปพลิเคชันของคุณ ด้วยขั้นตอนการทดสอบเหล่านี้ คุณควรจะสามารถตัดสินใจได้อย่างเป็นกลาง!
นอกจากนี้ ฉันคิดว่ามันคุ้มค่าที่จะชี้ให้เห็นที่นี่ว่าเนื่องจากเอาต์พุต PWM มีสัญญาณรบกวนต่ำ ด้วยความเป็นเส้นตรงที่ยอดเยี่ยม จึงควรเป็นไปได้ที่จะสร้าง DAC ที่มีความละเอียดสูงกว่ามากด้วยเอาต์พุต PWM (อาจมีความแม่นยำถึง 16 บิต) นั่นจะใช้เวลาทำงาน ถึงเวลานั้น ฉันขอลาก่อน!
แนะนำ:
Raspberry Pi Audio Dac-Amp-Streamer: 14 ขั้นตอน
Raspberry Pi Audio Dac-Amp-Streamer: เปลี่ยนหมวกเสียง Google AIY ที่ล้าสมัยให้เป็นอุปกรณ์สตรีมเสียงสเตอริโอแบบไม่มีหัวโดยเฉพาะ ตอนนี้ชุดเสียง Google AIY ใกล้จะครบสองปีแล้ว คุณอาจพบว่าความแปลกใหม่นั้นเสื่อมโทรมไปบ้างแล้ว หรือคุณอาจสงสัยว่าการท่องเว็บของคุณ
USB Audio DAC: 12 ขั้นตอน
USB Audio DAC: ใช้ไดรเวอร์มาตรฐาน ใช้งานได้กับ Windows, Mac และลีนุกซ์หลายรุ่น แต่จำกัดประสิทธิภาพไว้ที่ 16 บิต, 48 kHzBalanced (pro) เอาต์พุตระดับไลน์ที่ด้านหลัง (XLR / 6.35 มม.) ระดับสายปลายเดี่ยว (pro) เอาต์พุตที่ด้านหน้า (RCA)ไม่มีเอาต์พุต s
แหล่งที่มาปัจจุบัน DAC AD5420 และ Arduino: 4 ขั้นตอน (พร้อมรูปภาพ)
DAC AD5420 และ Arduino แหล่งที่มาปัจจุบัน: สวัสดีในบทความนี้ ฉันต้องการแบ่งปันประสบการณ์ของฉันกับตัวแปลงดิจิทัลเป็นแอนะล็อก AD5420 ในปัจจุบัน ซึ่งมีลักษณะดังต่อไปนี้: ความละเอียด 16 บิตและความซ้ำซากจำเจช่วงเอาต์พุตปัจจุบัน: 4 mA ถึง 20 mA, 0 mA ถึง 20 mA หรือ 0 mA เ
เริ่มต้นใช้งาน ESP32 - การติดตั้งบอร์ด ESP32 ใน Arduino IDE - ESP32 Blink Code: 3 ขั้นตอน
เริ่มต้นใช้งาน ESP32 | การติดตั้งบอร์ด ESP32 ใน Arduino IDE | รหัสการกะพริบของ ESP32: ในคำแนะนำนี้ เราจะดูวิธีการเริ่มทำงานกับ esp32 และวิธีการติดตั้งบอร์ด esp32 ลงใน Arduino IDE และเราจะตั้งโปรแกรม esp 32 เพื่อเรียกใช้โค้ดกะพริบโดยใช้ arduino ide
ESP32: คุณรู้หรือไม่ว่า DAC คืออะไร: 7 ขั้นตอน
ESP32: คุณรู้หรือไม่ว่า DAC คืออะไร: วันนี้ เราจะพูดถึงสองประเด็น อันแรกคือ DAC (Digital-to-Analog Converter) ฉันคิดว่ามันเป็นสิ่งสำคัญเพราะตัวอย่างเช่นเราสร้างเอาต์พุตเสียงใน ESP32 ปัญหาที่สองที่เราจะพูดถึงในวันนี้คือ oscil