תוכן עניינים:

כיצד ליצור ולבדוק DAC טוב יותר עם ESP32: 5 שלבים
כיצד ליצור ולבדוק DAC טוב יותר עם ESP32: 5 שלבים

וִידֵאוֹ: כיצד ליצור ולבדוק DAC טוב יותר עם ESP32: 5 שלבים

וִידֵאוֹ: כיצד ליצור ולבדוק DAC טוב יותר עם ESP32: 5 שלבים
וִידֵאוֹ: עדן חסון ואודיה - הנשיקה! 😱 2024, יולי
Anonim
כיצד ליצור ולבדוק DAC טוב יותר עם ESP32
כיצד ליצור ולבדוק DAC טוב יותר עם ESP32
כיצד ליצור ולבדוק DAC טוב יותר עם ESP32
כיצד ליצור ולבדוק DAC טוב יותר עם ESP32

ל- ESP32 2 ממירים דיגיטליים לאנלוגיים (8 סיביות). מכשירי DAC אלה מאפשרים לנו לייצר מתח שרירותי בטווח מסוים (0-3.3V) עם 8 סיביות של רזולוציה. במדריך זה אראה לך כיצד לבנות DAC ולאפיין את ביצועיו וכן להשוות אותו ל- DAC ESP32. מדדי הביצועים בהם אסתכל כוללים

  • רמת רעש
  • רוחב פס
  • חוסר לינאריות אינטגרלית
  • אי לינאריות דיפרנציאלית

כדי לבדוק מדדים אלה אשתמש ב- ADS1115.

חשוב לציין כי הערכתך של כל המדדים הללו תהיה מדויקת לא פחות ממכשיר ההתייחסות שלך (במקרה זה ה- ADS115). לדוגמה, ל- ADS115 אין דיוק של 16 סיביות בכל הנוגע לקיזוז המתח והרווח שלו. שגיאות אלה עשויות להיות גדולות עד 0.1%. עבור מערכות רבות, ניתן להתעלם משגיאות אלה כאשר הדיוק המוחלט מעורר דאגה מוגבלת.

אספקה

  • ADS1115
  • לוח ESP32
  • קרש לחם
  • חוטי מגשר
  • נגד 5 קאוהם
  • קבל קרמיקה אחד מיקרו-פאראד

שלב 1: פריסת לוח הלוח

פריסת לוח הלחם
פריסת לוח הלחם

חברו את הסיכות הבאות

בין ESP32 ל- ADS1115

3v3 VDD

GND GND

GPIO22 SCL

GPIO21 SDA

ב- ADS1115

ADDR GND (ADS115)

הכנת ה- DAC

ישנן דרכים רבות לעשות DAC. הפשוטה ביותר היא לסנן במעבר נמוך אות PWM עם נגד וקבל. יכולתי להוסיף כאן מגבר אופ כמאגר אבל רוצה לשמור על דברים פשוטים. עיצוב זה פשוט וזול ליישום עם כל מיקרו -בקר התומך ב- PWM. אני לא מתכוון לעבור כאן על תורת העיצוב (google PWM DAC).

פשוט חבר GPIO255 KOhm נגד 1 microFarad קבל gnd

עכשיו חבר חוט מגשר מהנקודה שבה הנגד פוגש את הקבל ל- A0 ב- ADS115.

שלב 2: הערכת האות לרמת הרעש

הערכת האות לרמת הרעש
הערכת האות לרמת הרעש

כדי להעריך את רמת הרעש פשוט הפעל את התסריט שלהלן. כדי להעריך זאת אנו פשוט משאירים את ה- DAC בערך קבוע ונמדוד כיצד המתח מתנדנד לאורך זמן.

בשל העיצוב של ה- DAC, הרעש יהיה הגדול ביותר כאשר אות ה- PWM נמצא במחזור עבודה של 50%. לכן כאן נעריך את זה. אנו נעריך גם את ESP32 באותה רמת אות. אנו גם נסנן את ה- DAC ESP32 עם אותו מסנן מעבר נמוך כדי להפוך את המדידה להשוואה.

בשבילי הפלט היה ברור. עיצוב ה- PWM היה בעל SNR טוב יותר מ- 6dB (פי 2 יותר טוב). ניצחון ברור ל- DAC החדש. בלבול קל אחד הוא שיש מסננים מובנים ב- ADC שהם בהחלט משפרים את ה- SNR. כך שהערכים המוחלטים עשויים להיות קשים לפרשנות. אם הייתי משתמש במסנן מסדר שני זה לא היה המקרה.

בכל אופן הקוד למטה

#לִכלוֹל

#כלול מודעות Adafruit_ADS1115; // ספריית adafruit עבור adc int16_t adc0; // הגדרת void (void) {Serial.begin (115200); // התחל ads.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 חזרות = 500; // מספר חזרות int n = 256; // מספר הדגימות ledcSetup (0, 25000, 8); // להגדיר pwm frequecny = 25000 הרץ ברזולוציה של 8 סיביות ledcAttachPin (25, 0); // הגדר pwm בפין 25 ledcWrite (0, 128); // הגדר אותו לעיכוב בחצי מחזור (הרעש הגדול ביותר) (3000); // המתן לזמן ההתיישבות צף snrPWM [חזרות]; // מערך snrs עבור PWM float snrDAC [חזרות]; // מערך snrs עבור DAC עבור (int i = 0; i <reps; i ++) {// loope over repititions for (int k = 1; k <(n+1); k ++) {// loope over samples 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; S = 0; Sp = 0; } ledcDetachPin (25); // נתק PWM מהסיכה 25 dacWrite (25, 128); // לכתוב לעיכוב DAC (3000); // המתן להסתפק ב- (int i = 0; i <reps; i ++) {// כמו לולאת PWM עבור (int k = 1; k <(n+1); k ++) {adc0 = ads.readADC_SingleEnded (0); M = Mp + (adc0 - Mp) / k; Mp = M; S = Sp + (adc0 - Mp) * (adc0 - M); Sp = S; } snrDAC = 20 * log10 (3.3 / (sqrt (S / n) *.0625 *.001)); M = 0; Mp = 0; S = 0; Sp = 0; } // עלילת SNRs בגרף אחד עבור (int i = 1; i <reps; i ++) {Serial.print ("PWM_SNR (dB):"); Serial.print (snrPWM ); Serial.print (","); Serial.print ("ESP32_SNR (dB):"); Serial.println (snrDAC ); }} לולאת void (void) {}

שלב 3: אי לינאריות אינטגרלית ואי לינאריות דיפרנציאלית

אי לינאריות אינטגרלית ואי לינאריות דיפרנציאלית
אי לינאריות אינטגרלית ואי לינאריות דיפרנציאלית

האי -לינאריות האינטגרלית היא מדד לכמה סטייה יש בערך בין מתח המוצא של DAC לקו ישר. ככל שזה גדול יותר זה גרוע יותר…

אי הליניאריות הדיפרנציאלית היא מדד בערך עד כמה השינוי הנצפה במתח (מקוד אחד למשנהו) חורג ממה שניתן לצפות מקו ישר.

התוצאות כאן היו ממש מעניינות. קודם כל, לשניהם יש פחות משגיאה של 0.5lb (ברזולוציה של 8 סיביות) וזה טוב אבל ל- PWM יש לינאריות אינטגרלית הרבה יותר טובה. לשניהם יש אי לינאריות דיפרנציאלית, אך ל- DAC ESP32 יש קוצים מוזרים מאוד. יתרה מכך, לשיטת PWM יש מבנה כלשהו לשגיאות. בעיקרו הוא מגדיל ומוריד את המתח הנכון בצורה מתחלפת.

החשד שלי הוא שזו איזו שגיאת עיגול מוזרה באופן הפקת אות PWM של 8 סיביות ב- ESP32.

אחת הדרכים לתקן זאת היא לעבור במהירות בין שני קודים סמוכים (למשל 128, 129) עם ה- PWM. עם מסנן אנלוגי נמוך, השגיאות המתקבלות יהיו ממוצעות לאפס. הדמתי זאת בתוכנה ואכן כל השגיאות נעלמו. כעת לשיטת PWM יש לינאריות מדויקת עד 16 סיביות!

כל מי שהקוד ליצירת הנתונים נמצא להלן. הפלט יהיה על הצג הטורי בפורמט.csv. פשוט העתק אותו לקובץ טקסט לעיבוד נוסף.

#לִכלוֹל

#כלול מודעות Adafruit_ADS1115; / * השתמש בזה לגרסת 16 סיביות */ int16_t adc0; הגדרת void (void) {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); for (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); }} לולאת void (void) {}

שלב 4: רוחב פס

רוחב פס
רוחב פס

אני הולך להגדיר את רוחב הפס כמו כאן כתדירות שבה יציאת ה- DAC יורדת ב -3 dB. זו מוסכמה ובמידה מסוימת שרירותית. לדוגמה, בנקודה של 6dB, ה- DAC עדיין יפיק אות שהוא רק אמפליטודה של ~ 50%.

כדי למדוד זאת אנו פשוט מעבירים גלי סינוס בתדירות הולכת וגוברת מה- DAC ל- ADC ומודדים את סטיית התקן שלהם. באופן לא מפתיע, נקודת 3dB היא ב 30Hz (1/(2*pi*5000*1e-6)).

ה- ESP32 יכול לבצע דגימת מגה אחת לשנייה. זהו ניצחון נטול ידיים עבור ה- ESP32. משרעתה אינה מתפוררת כלל באזור בדיקת רוחב הפס של 100 הרץ.

הקוד שלהלן יכול לבדוק את רוחב הפס של PWM DAC.

#לִכלוֹל

#כלול מודעות 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 ("תדר, משרעת"); for (int i = 1; i <100; i ++) {התחלה ארוכה ללא סימן = מילי (); ארוך לא חתום T = מיליס (); Sp = 0; S = 0; M = 0; Mp = 0; int k = 1; נורמת צף; בעוד ((T - התחלה) <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 = M; S = Sp + (adc0 - Mp) * (adc0 - M); Sp = S; T = מיליס (); k ++; } אם (i == 1) {norm = sqrt (S / k); } Serial.print (i); Serial.print (","); Serial.println (sqrt (S / k) / norm, 3); k = 0; }} לולאת void (void) {}

והקוד הזה יבדוק את רוחב הפס ESP32. הקפד להסיר את הקבל או שהתוצאות יהיו זהות עבור שתי השיטות.

#לִכלוֹל

#כלול מודעות 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 ("תדר, משרעת"); for (int i = 1; i <100; i ++) {התחלה ארוכה ללא סימן = מילי (); ארוך לא חתום T = מיליס (); Sp = 0; S = 0; M = 0; Mp = 0; int k = 1; נורמת צף; בעוד ((T - התחלה) <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 = M; S = Sp + (adc0 - Mp) * (adc0 - M); Sp = S; T = מיליס (); k ++; } אם (i == 1) {norm = sqrt (S / k); } Serial.print (i); Serial.print (","); Serial.println (sqrt (S / k) / norm, 3); k = 0; }} לולאת void (void) {}

שלב 5: סגירת מחשבות

עיצוב DAC החדש מנצח על לינאריות ורעש אך מפסיד ברוחב הפס. תלוי ביישום שלך אחד המדדים הללו עשוי להיות חשוב יותר מהאחר. בעזרת הליכי בדיקה אלה, אתה אמור להיות מסוגל לקבל החלטה אובייקטיבית זו!

כמו כן, אני חושב שכדאי לציין כאן כי מכיוון שפלט PWM הוא רעש נמוך, עם ליניאריות יוצאת דופן, יהיה אפשר לבנות DAC ברזולוציה הרבה יותר גבוהה עם פלט PWM (אולי אפילו 16 סיביות דיוק). זה ייקח קצת עבודה. עד אז, אני מציע לך להתראות!

מוּמלָץ: