Πίνακας περιεχομένων:

Πώς να φτιάξετε και να δοκιμάσετε ένα καλύτερο DAC με ESP32: 5 βήματα
Πώς να φτιάξετε και να δοκιμάσετε ένα καλύτερο DAC με ESP32: 5 βήματα

Βίντεο: Πώς να φτιάξετε και να δοκιμάσετε ένα καλύτερο DAC με ESP32: 5 βήματα

Βίντεο: Πώς να φτιάξετε και να δοκιμάσετε ένα καλύτερο DAC με ESP32: 5 βήματα
Βίντεο: Πως Να Αυξήσετε Την Νοητική Λειτουργία Έως Τα 90; Τροφές ΚΑΤΑ Άνοιας, Αλτσχάιμερ, Κακή Μνήμη. 2024, Νοέμβριος
Anonim
Πώς να φτιάξετε και να δοκιμάσετε ένα καλύτερο DAC με το ESP32
Πώς να φτιάξετε και να δοκιμάσετε ένα καλύτερο DAC με το ESP32
Πώς να φτιάξετε και να δοκιμάσετε ένα καλύτερο DAC με ESP32
Πώς να φτιάξετε και να δοκιμάσετε ένα καλύτερο DAC με ESP32

Το ESP32 διαθέτει 2 ψηφιακούς σε αναλογικούς μετατροπείς 8-bit (DAC). Αυτά τα DAC μας επιτρέπουν να παράγουμε αυθαίρετες τάσεις μέσα σε ένα συγκεκριμένο εύρος (0-3,3V) με 8 bits ανάλυσης. Σε αυτό το Instructable, θα σας δείξω πώς να δημιουργήσετε ένα DAC και να χαρακτηρίσετε την απόδοσή του καθώς και να το συγκρίνετε με το ESP32 DAC. Οι δείκτες απόδοσης που θα εξετάσω περιλαμβάνουν

  • Επίπεδο θορύβου
  • εύρος ζώνης
  • Ολοκληρωτική μη γραμμικότητα
  • Διαφορική μη γραμμικότητα

Για να δοκιμάσω αυτούς τους δείκτες θα χρησιμοποιήσω το ADS1115.

Είναι σημαντικό να σημειωθεί ότι η εκτίμησή σας για όλους αυτούς τους δείκτες θα είναι εξίσου ακριβής με τη συσκευή αναφοράς σας (στην περίπτωση αυτή το ADS115). Για παράδειγμα, το ADS115 δεν έχει ακρίβεια 16 bit όταν πρόκειται για τη μετατόπιση και την αύξηση της τάσης του. Αυτά τα σφάλματα μπορεί να είναι έως και 0,1%. Για πολλά συστήματα, αυτά τα σφάλματα μπορούν να αγνοηθούν όταν η απόλυτη ακρίβεια είναι περιορισμένης ανησυχίας.

Προμήθειες

  • ADS1115
  • Πίνακας ESP32
  • σανίδα ψωμιού
  • καλώδια βραχυκυκλωτήρων
  • Αντίσταση 5 kOhm
  • 1 κεραμικός πυκνωτής micro-Farad

Βήμα 1: Τοποθέτηση του Breadboard

Τοποθέτηση του Breadboard
Τοποθέτηση του Breadboard

Συνδέστε τις ακόλουθες ακίδες

Μεταξύ του ESP32 και του ADS1115

3v3 VDD

GND GND

GPIO22 SCL

GPIO21 SDA

Στο ADS1115

ADDR GND (ADS115)

Κάνοντας το DAC

Υπάρχουν πολλοί τρόποι για να δημιουργήσετε ένα DAC. Το απλούστερο είναι να φιλτράρετε χαμηλής διέλευσης ένα σήμα PWM με αντίσταση και πυκνωτή. Θα μπορούσα να είχα προσθέσει ένα op-amp εδώ ως buffer, αλλά ήθελα να κρατήσω τα πράγματα απλά. Αυτός ο σχεδιασμός είναι απλός και φθηνός για εφαρμογή με οποιονδήποτε μικροελεγκτή που υποστηρίζει PWM. Δεν πρόκειται να περάσω από τη θεωρία του σχεδιασμού εδώ (google PWM DAC).

Απλώς συνδέστε GPIO255 KOhm αντίσταση 1 microFarad Capacitor gnd

Τώρα συνδέστε ένα καλώδιο βραχυκυκλωτήρα από το σημείο όπου η αντίσταση συναντά τον πυκνωτή στο A0 στο ADS115.

Βήμα 2: Αξιολόγηση σήματος σε επίπεδο θορύβου

Αξιολόγηση σήματος σε επίπεδο θορύβου
Αξιολόγηση σήματος σε επίπεδο θορύβου

Για να εκτιμήσετε το επίπεδο θορύβου, απλώς εκτελέστε το παρακάτω σενάριο. Για να το εκτιμήσουμε αυτό, αφήνουμε απλώς το DAC σε μια σταθερή τιμή και μετράμε πώς ταλαντεύεται η τάση με την πάροδο του χρόνου.

Λόγω του σχεδιασμού του DAC, ο θόρυβος θα είναι μεγαλύτερος όταν το σήμα PWM είναι σε κύκλο λειτουργίας 50%. Επομένως, εδώ θα το αξιολογήσουμε. Θα αξιολογήσουμε επίσης το ESP32 στο ίδιο επίπεδο σήματος. Θα φιλτράρουμε επίσης το ESP32 DAC με το ίδιο φίλτρο χαμηλής διέλευσης για να κάνουμε τη μέτρηση συγκρίσιμη.

Για μένα η έξοδος ήταν σαφής. Ο σχεδιασμός PWM είχε> 6dB καλύτερο SNR (δηλαδή 2 φορές καλύτερο). Ξεκάθαρη νίκη για τη νέα DAC. Ένα μικρό μπέρδεμα είναι ότι υπάρχουν φίλτρα ενσωματωμένα στο ADC που σίγουρα ενισχύουν το SNR. Έτσι, οι απόλυτες τιμές μπορεί να είναι δύσκολο να ερμηνευτούν. Αν είχα χρησιμοποιήσει φίλτρο δεύτερης τάξης αυτό δεν θα ίσχυε.

Εν πάση περιπτώσει, ο κωδικός είναι παρακάτω

#περιλαμβάνω

#συμπεριλάβετε διαφημίσεις Adafruit_ADS1115. // βιβλιοθήκη adafruit για adc int16_t adc0; // void setup (void) {Serial.begin (115200); // Έναρξη σειριακής διαφήμισης. SetGain (GAIN_TWO); // 2x κέρδος +/- 2.048V 1 bit = 0.0625mV ads.begin (); // Έναρξη adc float M = 0; // αρχικός μέσος όρος float Mp = 0; // previouos μέσο float S = 0; // αρχική μεταβλητότητα float Sp = 0; // προηγούμενη διακύμανση const int reps = 500; // αριθμός επαναλήψεων int n = 256; // αριθμός δειγμάτων ledcSetup (0, 25000, 8); // set pwm frequecny = 25000 Hz σε ανάλυση 8 bit ledcAttachPin (25, 0); // ορίστε το pwm στην ακίδα 25 ledcWrite (0, 128); // Ρυθμίστε το στο μισό κύκλο λειτουργίας (μεγαλύτερος θόρυβος) καθυστέρηση (3000). // περιμένετε για τον χρόνο τακτοποίησης float 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 δείγματα 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)); Μ = 0; Mp = 0; S = 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 ); }} void loop (void) {}

Βήμα 3: Ολοκληρωτική μη γραμμικότητα και διαφορική μη γραμμικότητα

Ολοκληρωτική μη γραμμικότητα και διαφορική μη γραμμικότητα
Ολοκληρωτική μη γραμμικότητα και διαφορική μη γραμμικότητα

Η ολοκληρωμένη μη γραμμικότητα είναι ένα μέτρο περίπου της απόκλισης μεταξύ της τάσης εξόδου DAC και μιας ευθείας γραμμής. Όσο μεγαλύτερο είναι τόσο χειρότερο είναι…

Η διαφορική μη γραμμικότητα είναι ένα μέτρο κατά προσέγγιση κατά πόσο η παρατηρούμενη μεταβολή της τάσης (από τον έναν κώδικα στον επόμενο) αποκλίνει από αυτό που αναμενόταν από μια ευθεία γραμμή.

Τα αποτελέσματα εδώ ήταν πραγματικά ενδιαφέροντα. Πρώτα απ 'όλα, και τα δύο έχουν λιγότερο από 0.5lsb σφάλμα (σε ανάλυση 8-bit) που είναι καλό, αλλά το PWM έχει πολύ καλύτερη ολοκληρωμένη γραμμικότητα. Και τα δύο έχουν συγκρίσιμη διαφορική μη γραμμικότητα, αλλά το ESP32 DAC έχει μερικές πολύ περίεργες αιχμές. Επιπλέον, η μέθοδος PWM έχει κάποια δομή στα σφάλματα. Ουσιαστικά ξεπερνά και υποβάλλει τη σωστή τάση με εναλλασσόμενο τρόπο.

Η υποψία μου είναι ότι πρόκειται για κάποιο περίεργο σφάλμα στρογγυλοποίησης στον τρόπο με τον οποίο παράγεται ένα σήμα PWM 8-bit στο ESP32.

Ένας τρόπος για να διορθωθεί αυτό είναι η ταχεία εναλλαγή μεταξύ δύο παρακείμενων κωδικών (π.χ. 128, 129) με το PWM. Με ένα αναλογικό φίλτρο χαμηλής διέλευσης, τα σφάλματα που προκύπτουν θα είναι κατά μέσο όρο στο μηδέν. Το προσομοίωσα στο λογισμικό και πράγματι όλα τα σφάλματα εξαφανίστηκαν. Τώρα η μέθοδος PWM έχει γραμμικότητα που είναι ακριβής στα 16-bit!

Οποιοσδήποτε ο κώδικας για τη δημιουργία των δεδομένων είναι παρακάτω. Η έξοδος θα είναι στη σειριακή οθόνη σε μορφή.csv. Απλώς αντιγράψτε το σε αρχείο κειμένου για περαιτέρω επεξεργασία.

#περιλαμβάνω

#συμπεριλάβετε διαφημίσεις Adafruit_ADS1115. / * Χρησιμοποιήστε αυτό για την έκδοση 16-bit */ int16_t adc0; void setup (void) {Serial.begin (115200); ads.setGain (GAIN_ONE); // 2x κέρδος +/- 2.048V 1 bit = 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); float αναμένεται = (i / 256.0 * 3.3) / 4.096 * 32767; Serial.print (αναμένεται) Serial.print (","); Serial.println (adc0); }} void loop (void) {}

Βήμα 4: Εύρος ζώνης

εύρος ζώνης
εύρος ζώνης

Θα ορίσω το εύρος ζώνης ως εδώ ως τη συχνότητα στην οποία η έξοδος του DAC μειώνεται κατά 3dB. Πρόκειται για μια σύμβαση και, ως ένα βαθμό, αυθαίρετη. Για παράδειγμα, στο σημείο 6dB, το DAC θα εξακολουθεί να βγάζει ένα σήμα που θα είναι απλώς am 50% πλάτος.

Για να το μετρήσουμε αυτό απλά περνάμε ημιτονοειδή κύματα σε αυξανόμενη συχνότητα από το DAC στο ADC και μετράμε την τυπική απόκλισή τους. Δεν αποτελεί έκπληξη το γεγονός ότι το σημείο 3dB είναι στα 30Hz (1/(2*pi*5000*1e-6)).

Το ESP32 μπορεί να κάνει 1 Mega δείγμα ανά δευτερόλεπτο. Αυτή είναι μια κερδοφόρα νίκη για το ESP32. Το πλάτος του δεν αποσυντίθεται καθόλου στην περιοχή δοκιμής εύρους ζώνης 100Hz.

Ο παρακάτω κώδικας μπορεί να δοκιμάσει το εύρος ζώνης PWM DAC.

#περιλαμβάνω

#συμπεριλάβετε διαφημίσεις Adafruit_ADS1115. / * Χρησιμοποιήστε αυτό για την έκδοση 16-bit */ int16_t adc0; int16_t adc1; void setup (void) {float M; float Mp = 0; float S = 0; float Sp = 0; Serial.begin (115200); ads.setGain (GAIN_ONE); // 1x κέρδος +/- 4.096V 1 bit = 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 (); ανυπόγραφο μακρύ Τ = millis (); Sp = 0; S = 0; Μ = 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 = millis (); k ++; } if (i == 1) {norm = sqrt (S / k); } Serial.print (i); Serial.print (","); Serial.println (sqrt (S / k) / norm, 3); k = 0; }} void loop (void) {}

Και αυτός ο κωδικός θα δοκιμάσει το εύρος ζώνης ESP32. Βεβαιωθείτε ότι έχετε αφαιρέσει τον πυκνωτή, διαφορετικά τα αποτελέσματα θα είναι τα ίδια και για τις δύο μεθόδους.

#περιλαμβάνω

#συμπεριλάβετε διαφημίσεις Adafruit_ADS1115. / * Χρησιμοποιήστε αυτό για την έκδοση 16-bit */ int16_t adc0; int16_t adc1; void setup (void) {float M; float Mp = 0; float S = 0; float Sp = 0; Serial.begin (115200); ads.setGain (GAIN_ONE); // 1x κέρδος +/- 4.096V 1 bit = 2mV 0.125mV ads.begin (); καθυστέρηση (5000)? Serial.println ("Συχνότητα, πλάτος"); για (int i = 1; i <100; i ++) {unsigned long start = millis (); ανυπόγραφο μακρύ Τ = millis (); Sp = 0; S = 0; Μ = 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 = millis (); k ++; } if (i == 1) {norm = sqrt (S / k); } Serial.print (i); Serial.print (","); Serial.println (sqrt (S / k) / norm, 3); k = 0; }} void loop (void) {}

Βήμα 5: Κλείσιμο σκέψεων

Ο νέος σχεδιασμός DAC κερδίζει με τη γραμμικότητα και τον θόρυβο, αλλά χάνει με το εύρος ζώνης. Ανάλογα με την εφαρμογή σας, ένας από αυτούς τους δείκτες μπορεί να είναι πιο σημαντικός από τον άλλο. Με αυτές τις διαδικασίες δοκιμής, θα πρέπει να μπορείτε να πάρετε αντικειμενικά αυτήν την απόφαση!

Επίσης, νομίζω ότι αξίζει να επισημανθεί εδώ ότι επειδή η έξοδος PWM είναι χαμηλού θορύβου, με εξαιρετική γραμμικότητα θα πρέπει να είναι δυνατή η κατασκευή ενός DAC πολύ υψηλότερης ανάλυσης με την έξοδο PWM (ίσως ακόμη και ακρίβεια 16 bit). Αυτό θα πάρει λίγη δουλειά. Μέχρι τότε, σας λέω μπράβο!

Συνιστάται: