Spisu treści:

Jak zrobić i przetestować lepszy przetwornik cyfrowo-analogowy z ESP32: 5 kroków
Jak zrobić i przetestować lepszy przetwornik cyfrowo-analogowy z ESP32: 5 kroków

Wideo: Jak zrobić i przetestować lepszy przetwornik cyfrowo-analogowy z ESP32: 5 kroków

Wideo: Jak zrobić i przetestować lepszy przetwornik cyfrowo-analogowy z ESP32: 5 kroków
Wideo: Jak podłączyć odtwarzacz do wzmacniacza stereo - cyfra vs analog | Poradnik 2024, Lipiec
Anonim
Jak zrobić i przetestować lepszy przetwornik cyfrowo-analogowy z ESP32?
Jak zrobić i przetestować lepszy przetwornik cyfrowo-analogowy z ESP32?
Jak zrobić i przetestować lepszy przetwornik cyfrowo-analogowy z ESP32?
Jak zrobić i przetestować lepszy przetwornik cyfrowo-analogowy z ESP32?

ESP32 ma 2 8-bitowe przetworniki cyfrowo-analogowe (DAC). Te przetworniki cyfrowo-analogowe pozwalają nam wytwarzać dowolne napięcia w pewnym zakresie (0-3,3 V) z 8-bitową rozdzielczością. W tej instrukcji pokażę, jak zbudować przetwornik cyfrowo-analogowy i scharakteryzować jego wydajność, a także porównać go z przetwornikiem cyfrowo-analogowym ESP32. Wskaźniki wydajności, na które będę patrzeć, obejmują

  • Poziom hałasu
  • Przepustowość łącza
  • Nieliniowość całkowa
  • Nieliniowość różniczkowa

Do przetestowania tych indeksów użyję ADS1115.

Należy pamiętać, że Twoja ocena wszystkich tych wskaźników będzie tylko tak dokładna, jak Twoje urządzenie referencyjne (w tym przypadku ADS115). Na przykład ADS115 nie ma 16-bitowej precyzji, jeśli chodzi o przesunięcie napięcia i wzmocnienie. Błędy te mogą sięgać nawet 0,1%. W przypadku wielu systemów błędy te można zignorować, gdy absolutna dokładność ma ograniczone znaczenie.

Kieszonkowe dzieci

  • ADS1115
  • Płyta ESP32
  • płytka do krojenia chleba
  • przewody połączeniowe
  • Rezystor 5 kΩ
  • 1 kondensator ceramiczny micro-Farad

Krok 1: Układanie deski do krojenia chleba

Układanie deski do krojenia chleba
Układanie deski do krojenia chleba

Podłącz następujące szpilki

Między ESP32 a ADS1115

3v3 VDD

GND GND

GPIO22 SCL

GPIO21 SDA

W ADS1115

ADDR GND (ADS115)

Dokonywanie DAC

Istnieje wiele sposobów na zrobienie DAC-a. Najprostszym jest filtrowanie dolnoprzepustowe sygnału PWM za pomocą rezystora i kondensatora. Mogłem dodać tutaj wzmacniacz operacyjny jako bufor, ale chciałem, aby wszystko było proste. Ten projekt jest prosty i tani w realizacji z dowolnym mikrokontrolerem obsługującym PWM. Nie będę tutaj przechodził przez teorię projektu (google PWM DAC).

Wystarczy podłączyć rezystor GPIO255 KOhm 1 microFarad kondensator gnd

Teraz podłącz przewód połączeniowy od punktu, w którym rezystor styka się z kondensatorem, do A0 na ADS115.

Krok 2: Oceń sygnał do poziomu hałasu

Oceń sygnał do poziomu hałasu
Oceń sygnał do poziomu hałasu

Aby ocenić poziom hałasu, po prostu uruchom poniższy skrypt. Aby to ocenić, po prostu pozostawiamy DAC na stałej wartości i mierzymy, jak napięcie oscyluje w czasie.

Ze względu na konstrukcję przetwornika cyfrowo-analogowego hałas będzie największy, gdy sygnał PWM będzie miał 50% cyklu pracy. Dlatego tutaj to ocenimy. Na tym samym poziomie sygnału ocenimy również ESP32. Będziemy również filtrować DAC ESP32 tym samym filtrem dolnoprzepustowym, aby pomiar był porównywalny.

Dla mnie wyjście było jasne. Projekt PWM miał >6dB lepszy SNR (to 2 razy lepszy). Wyraźne zwycięstwo nowego DAC-a. Jedyną drobną przeszkodą jest to, że w ADC są wbudowane filtry, które zdecydowanie zwiększają SNR. Dlatego wartości bezwzględne mogą być trudne do interpretacji. Gdybym użył filtra drugiego rzędu, tak by nie było.

W każdym razie kod jest poniżej

#włączać

#dołącz reklamy Adafruit_ADS1115; // biblioteka adafruit dla adc int16_t adc0; // void setup(void) { Serial.begin(115200); // Uruchom serial ads.setGain(GAIN_TWO); // 2x wzmocnienie +/- 2,048V 1 bit =0,0625mV ads.begin(); // rozpocznij adc float M = 0; // początkowa średnia float Mp = 0; // poprzednie średnia float S = 0; // początkowa wariancja float Sp = 0; // poprzednia wariancja const int reps = 500; // liczba powtórzeń int n = 256; // liczba próbek ledcSetup(0, 25000, 8); // ustaw częstotliwość pwm =25000 Hz przy rozdzielczości 8 bitów ledcAttachPin(25, 0); // ustaw pwm na pinie 25 ledcWrite(0, 128); // ustaw go na połowę cyklu pracy (największy szum) delay(3000); // czekaj na czas rozliczenia float snrPWM[reps]; // tablica snrs dla PWM float snrDAC[reps]; // tablica snrs dla DAC for (int i = 0; i < powtórzeń; i++) { // pętla po powtórzeniach for (int k = 1; k < (n + 1); k++) { // pętla nad próbkami adc0 = ads.readADC_SingleEnded(0); // uzyskaj odczyt M = Mp + (adc0 - Mp) / k; // oblicz średnią kroczącą Mp = M; // ustaw poprzednią średnią S = Sp + (adc0 - Mp) * (adc0 - M); // oblicz wariancję kroczącą Sp = S; // ustaw poprzednią wariancję } // snr w dB snrPWM = 20 * log10(3,3 / (sqrt(S / n) *.0625 *.001)); //resetuj wartości M = 0; Mp = 0; S = 0; Sp = 0; } ledcDetachPin(25); // odłącz PWM od pinu 25 dacWrite(25, 128); // zapis do DAC delay(3000); // czekaj na zadowolenie (int i = 0; i < reps; i++) { // to samo co pętla PWM for (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; } // wykreśl SNR na jednym wykresie dla (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) { }

Krok 3: Nieliniowość całkowa i nieliniowość różniczkowa

Nieliniowość całkowa i nieliniowość różniczkowa
Nieliniowość całkowa i nieliniowość różniczkowa

Całkowa nieliniowość jest miarą w przybliżeniu tego, jak duże jest odchylenie między napięciem wyjściowym przetwornika DAC a linią prostą. Im większe, tym gorzej…

Nieliniowość różnicowa jest przybliżoną miarą tego, jak bardzo obserwowana zmiana napięcia (od jednego kodu do następnego) odbiega od tego, czego można by oczekiwać od linii prostej.

Wyniki tutaj były naprawdę interesujące. Przede wszystkim oba mają błąd mniejszy niż 0,5 lsb (przy rozdzielczości 8-bitowej), co jest dobre, ale PWM ma znacznie lepszą liniowość całkowania. Oba mają porównywalną nieliniowość różnicową, ale DAC ESP32 ma kilka bardzo dziwnych skoków. Co więcej, metoda PWM ma pewną strukturę błędów. Zasadniczo przereguluje i zaniża prawidłowe napięcie w sposób naprzemienny.

Podejrzewam, że jest to jakiś dziwny błąd zaokrąglenia w sposobie wytwarzania 8-bitowego sygnału PWM na ESP32.

Jednym ze sposobów skorygowania tego jest szybkie przełączanie się między dwoma sąsiednimi kodami (np. 128, 129) za pomocą PWM. W przypadku analogowego filtra dolnoprzepustowego wynikowe błędy będą uśredniane do zera. Symulowałem to w oprogramowaniu i rzeczywiście wszystkie błędy zniknęły. Teraz metoda PWM ma liniowość z dokładnością do 16 bitów!

Każdy kod do generowania danych znajduje się poniżej. Dane wyjściowe będą wyświetlane na monitorze szeregowym w formacie.csv. Wystarczy skopiować go do pliku tekstowego w celu dalszego przetwarzania.

#włączać

#dołącz reklamy Adafruit_ADS1115; /* Użyj tego dla wersji 16-bitowej */ int16_t adc0; void setup(void) { Serial.begin(115200); ads.setGain(GAIN_ONE); // 2x wzmocnienie +/- 2,048V 1 bit = 1mV 0,0625mV ads.begin(); ledcSetup (0, 25000, 8); ledcAttachPin(25, 0); Serial.println("Oczekiwany, obserwowany"); ledcWrite(0, 2); opóźnienie(3000); for (int i = 2; i < 255; i++) { ledcWrite(0, i); opóźnienie (100); adc0 = ads.readADC_SingleEnded(0); oczekiwana liczba zmiennoprzecinkowa = (i / 256,0 * 3,3) / 4,096 * 32767; Serial.print(oczekiwany); Serial.print(", "); Serial.println(adc0); } } void loop(void) { }

Krok 4: Przepustowość

Przepustowość łącza
Przepustowość łącza

Mam zamiar zdefiniować szerokość pasma tak jak tutaj jako częstotliwość, przy której wyjście DAC spada o 3dB. To konwencja i do pewnego stopnia arbitralna. Na przykład w punkcie 6 dB przetwornik cyfrowo-analogowy nadal będzie wysyłał sygnał o amplitudzie ~50%.

Aby to zmierzyć, po prostu przekazujemy fale sinusoidalne o rosnącej częstotliwości z DAC do ADC i mierzymy ich odchylenie standardowe. Nic dziwnego, że punkt 3dB jest przy 30 Hz (1/(2*pi*5000*1e-6)).

ESP32 może wykonać 1 Mega próbkę na sekundę. To bezwzględna wygrana dla ESP32. Jego amplituda nie zanika w ogóle w obszarze testowym pasma 100 Hz.

Poniższy kod może przetestować przepustowość PWM DAC.

#włączać

#dołącz reklamy Adafruit_ADS1115; /* Użyj tego dla wersji 16-bitowej */ int16_t adc0; int16_t adc1; void setup(void) { float M; pływak Mp = 0; pływak S = 0; pływak Sp = 0; Serial.początek(115200); ads.setGain(GAIN_ONE); // 1x wzmocnienie +/- 4,096V 1 bit = 2mV 0,125mV ads.begin(); ledcSetup (0, 25000, 8); ledcAttachPin(25, 0); opóźnienie(5000); Serial.println("Częstotliwość, Amplituda "); for (int i = 1; i < 100; i++) { unsigned long start = millis(); unsigned long T = millis(); Sp = 0; S = 0; M = 0; Mp = 0; int k = 1; norma pływaka; while ((T - start) < 1000) { int out = 24 * sin(2 * PI * i * (T - start) / 1000,0) + 128; ledcWrite(0, nie); adc0 = ads.readADC_SingleEnded(0); M = Mp + (adc0 - Mp) / k; MP = M; S = Sp + (adc0 - Mp) * (adc0 - M); Sp = S; T = mili(); k++; } if (i == 1) { norma = sqrt(S / k); } Serial.print(i); Serial.print(", "); Serial.println(sqrt(S / k) / norma, 3); k = 0; } } void loop(void) { }

A ten kod przetestuje przepustowość ESP32. Pamiętaj, aby usunąć kondensator, w przeciwnym razie wyniki będą takie same dla obu metod.

#włączać

#dołącz reklamy Adafruit_ADS1115; /* Użyj tego dla wersji 16-bitowej */ int16_t adc0; int16_t adc1; void setup(void) { float M; pływak Mp = 0; pływak S = 0; pływak Sp = 0; Serial.początek(115200); ads.setGain(GAIN_ONE); // 1x wzmocnienie +/- 4,096V 1 bit = 2mV 0,125mV ads.begin(); opóźnienie(5000); Serial.println("Częstotliwość, Amplituda "); for (int i = 1; i < 100; i++) { unsigned long start = millis(); unsigned long T = millis(); Sp = 0; S = 0; M = 0; Mp = 0; int k = 1; norma pływaka; while ((T - start) < 1000) { int out = 24 * sin(2 * PI * i * (T - start) / 1000,0) + 128; dacWrite(25, wyj.); adc0 = ads.readADC_SingleEnded(0); M = Mp + (adc0 - Mp) / k; MP = M; S = Sp + (adc0 - Mp) * (adc0 - M); Sp = S; T = mili(); k++; } if (i == 1) { norma = sqrt(S / k); } Serial.print(i); Serial.print(", "); Serial.println(sqrt(S / k) / norma, 3); k = 0; } } void loop(void) { }

Krok 5: Myśli zamykające

Nowa konstrukcja przetwornika cyfrowo-analogowego wygrywa pod względem liniowości i szumu, ale traci na przepustowości. W zależności od aplikacji jeden z tych wskaźników może być ważniejszy od drugiego. Dzięki tym procedurom testowym powinieneś być w stanie obiektywnie podjąć tę decyzję!

Myślę też, że warto tutaj zaznaczyć, że ponieważ wyjście PWM jest niskoszumowe, z wyjątkową liniowością powinno być możliwe skonstruowanie przetwornika cyfrowo-analogowego o znacznie wyższej rozdzielczości z wyjściem PWM (może nawet 16-bitowa precyzja). To zajmie trochę pracy. Do tego czasu pozdrawiam Cię!

Zalecana: