תוכן עניינים:
- אספקה
- שלב 1: פריסת לוח הלוח
- שלב 2: הערכת האות לרמת הרעש
- שלב 3: אי לינאריות אינטגרלית ואי לינאריות דיפרנציאלית
- שלב 4: רוחב פס
- שלב 5: סגירת מחשבות
וִידֵאוֹ: כיצד ליצור ולבדוק DAC טוב יותר עם ESP32: 5 שלבים
2024 מְחַבֵּר: John Day | [email protected]. שונה לאחרונה: 2024-01-30 09:12
ל- 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 סיביות דיוק). זה ייקח קצת עבודה. עד אז, אני מציע לך להתראות!
מוּמלָץ:
בנה לחצן הפעלה טוב יותר של Raspberry Pi: 4 שלבים
בנה לחצן הפעלה טוב יותר של Raspberry Pi: קל מאוד לבצע לחצן כיבוי או כיבוי של פטל. יש הרבה פרויקטים כאלה באינטרנט וכמה כאן ב- Instructables, אבל אף אחד מהם (שאני יכול לראות) לא אומר לך מתי ה- Pi שלך למעשה סיים לכבות ומכאן שזה
למד טוב יותר בעזרת מנורת שולחן חכמה - IDC2018IOT: 10 שלבים (עם תמונות)
למד טוב יותר עם מנורת שולחן חכמה - IDC2018IOT: אנשים בעולם המערבי מבלים הרבה זמן בישיבה. ליד השולחן, מסתובבים, צופים בטלוויזיה ועוד. לפעמים, ישיבה רבה מדי עלולה לפגוע בגופך ולפגוע ביכולות המיקוד שלך. ההליכה והקימה לאחר זמן נתון חיונית לכל
מקודד סיבובי טוב יותר: 4 שלבים
מקודד סיבובי טוב יותר: אם אי פעם ניסית להשתמש במקודד סיבוב מהמדף לפרויקט שלך סביר שאכזבת. בין אם זה נבע מהקושי בהגדרה או מהבקרות הלא מדויקות. הייתה לי אותה בעיה אז החלטתי לתקן אותה. עיצבתי תוכנות תלת מימד
כיצד להפוך את קליפ Tek Gun שלך לכוון טוב יותר: 4 שלבים
כיצד להפוך את קליפ Tek Gun שלך לכוון טוב יותר: אז אתה רוצה לגרום לאקדח Clip Tek שלך להיות מטרה טובה יותר? אני אגיד לך איך לעשות את זה. הדרך הטובה ביותר לשפר את המטרה שלך היא באמצעות מכוון לייזר. זה יעלה לך פחות מ 10 $
הפוך את הלם למכוניות ה- RC לקצר יותר לטיפול טוב יותר במהירויות גבוהות: 5 שלבים
הפוך את הלם למכוניות RC שלך לקצר יותר לטיפול טוב יותר במהירויות גבוהות: במדריך זה אראה לך כיצד לקצר את הזעזועים שלך כך שתוכל לקרב את המכונית שלך לקרקע, כך שתוכל לבצע סיבובים במהירות גבוהה יותר בלי לנפנף. עוד מדריך כיצד לבצע תחזוקה במכוניות שלך מזעזעים כל כך