Powrót

Wokół Arduino. Dokładność pomiaru napięcia

Już wcześniej zasygnalizowałem, że korzystając ze skądinąd przyjaznego Arduino, można też natknąć się na różne, czasem przykre niespodzianki. Aby takich niespodzianek było jak najmniej, potrzebna jest wiedza i doświadczenie. Będziemy je zdobywać stopniowo. W tym artykule zajmiemy się niektórymi „aspektami analogowymi” płytki Arduino: omówimy kwestie precyzji i dokładności pomiarów analogowych.

Na początek trzeba podkreślić, że prawie wszystkie książki dotyczące Arduino koncentrują się na kwestiach programowych, a nie na sprzętowych. Autorzy zakładają, że czytelnik nie ma pojęcia o elektronice (w większości sami autorzy nie są elektronikami i też mają mizerne pojęcie o właściwościach sprzętu). I oni, i nieprzygotowany czytelnik traktują płytkę Arduino jak czarną skrzynkę o mocno tajemniczych, ale niewątpliwie cudownych właściwościach.

Jedną z takich cudownych właściwości Arduino jest możliwość pomiaru napięcia za pomocą sześciu wejść analogowych A0…A5.

W książkach o Arduino stosuje się następujące rozumowanie: maksymalny odczyt z 10-bitowego przetwornika ADC to 1023 i odpowiada to napięciu (zasilania) 5V, więc jeśli z przetwornika odczytamy liczbę X w zakresie 0…1023, możemy łatwo obliczyć napięcie z zależności:

Ux = X * 5V / 1023

Jeżeli do takich obliczeń wykorzystamy zmienne typu float, czyli liczby zmiennoprzecinkowe (32-bitowe), obliczenia przeprowadzone zostaną z dokładnością do 6…7 miejsc po przecinku (kropce). Przykładowo u mnie prosty program, z tego listingu:

#include <LiquidCrystal.h>
LiquidCrystal wysw(2, 3, 4, 5, 6, 7); float u; //zmienna typu float
void setup() { wysw.begin(16, 2); Serial.begin(9600); }
void loop() { 
u = (float)analogRead(A0) * 5 / 1023;
wysw.clear(); wysw.print("Nap. zasilania:"); wysw.setCursor(0, 1);
wysw.print(u, 10); wysw.print('V'); Serial.print("Nap. zasilania = ");
Serial.print(u, 10); Serial.println('V'); delay(1000); }

zmierzył napięcie zasilania (przy zwarciu pinów A0 i VCC) i dał wynik, pokazany na rysunku 1 i fotografii 2.

Rysunek 1

Fotografia 2

Wynik pomiaru prezentowany jest z rozdzielczością dziesięciu miejsc po przecinku, co oczywiście z kilku powodów nie ma sensu.
Przecież przetwornik w kostce ATmega328P jest 10-bitowy, czyli rozróżnia 1024 poziomy – schodki. Jeden „schodek” (1LSB) to 1/1024 = 0,0009765625 całości, czyli nieco mniej niż 0,1%. Przy napięciu odniesienia 5V jeden 0,1-procentowy „schodek” odpowiada więc wartości około 5mV, co sugeruje precyzję pomiarów 5mV.
Taki wniosek mogą też sugerować rysunek 1 i fotografia 2. Osoby nieco bardziej zapoznane z techniką cyfrową mogą zapytać: czy rzeczywiście zmierzyliśmy tu napięcie zasilania naszej płytki Arduino z dokładnością 0,1%?

Nie! Nie! Nie!

Co zmierzyliśmy?

Nasza płytka Arduino podczas testów zasilana jest przez kabel USB. Domyślnie napięciem odniesienia dla przetwornika ADC jest właśnie napięcie zasilania. W katalogu procesora ATmega328P znajdziemy wzór, pokazany na rysunku 3.

Rysunek 3

Jak widzimy, liczba uzyskiwana z przetwornika ADC nie jest bezwzględną miarą napięcia, tylko miarą stosunku napięcia wejściowego VIN i napięcia odniesienia VREF, którym standardowo jest napięcie zasilania płytki. Czyli napięcie z portu USB.

Rysunek 4 pokazuje wymagania „energetyczne” dotyczące portu USB. Jak widzimy, dopuszczalny zakres wyjściowych napięć zasilania na złączu USB to w najgorszym przypadku 4,4V…5,25V, czyli 5V z tolerancją –12% +5%.

Rysunek 4

Po pierwsze w naszym pomiarze mamy „masło maślane”, bo to samo napięcie ma być mierzone i jednocześnie ma być napięciem odniesienia. Taki pomiar niewątpliwie jest zabiegiem mało sensownym.

Jednak przy zasilaniu przez kabel USB, nawet przy pomiarze „obcych napięć”, nasze „pseudoprecyzyjne” pomiary mogą być obarczone błędem w zakresie –12%… +5%!

Rozdzielczość pomiarów niezmiennie wynosi około 0,1% i jest wyznaczona przez liczbę bitów przetwornika.

Natomiast dokładność, zależnie od właściwości użytego napięcia odniesienia, może być dramatycznie mała i wynosić –12%…+5%.

Źródła napięcia odniesienia

Rozdzielczość przetwornika ADC wynosi 0,1%, ale dokładności 0,1% na pewno uzyskać się nie da, nawet i innymi, lepszymi źródłami napięcia odniesienia. Omówmy kilka możliwości.

NCP1117

Jeżeli płytka Arduino zasilana jest nie przez kabel USB, tylko zewnętrznym napięciem wyższym niż 5V, podanym na gniazdo wtykowe (albo na pin oznaczony VIN) i jeśli pracuje stabilizator NCP1117ST50T3G, to dokładność pomiarów może być lepsza. Rysunek 5 pokazuje fragmenty karty katalogowej NCP1117 OnSemi. Niebieskimi podkładkami wyróżnione są parametry „dobre”, a różowymi te, które budzą czujność.

Rysunek 5

Napięcie wyjściowe ma tolerancję ±1%, ale odchyłkę można zmierzyć dokładnym woltomierzem i skalibrować programowo.  Problemem jest stabilność długoczasowa (typowo 0,3%) i wpływ temperatury (typowo 0,5%). Ale przede wszystkim napięcie wyjściowe może zmieniać się pod wpływem prądu obciążenia, a grzanie kostki powoduje wzrost temperatury (jej typowy wpływ pokazuje też rysunek 6). Wniosek jest prosty: aby napięcie wyjściowe było stabilne, należy minimalizować zmiany prądu obciążenia.

Rysunek 6

Pobór prądu przez system Arduino zależy od szeregu czynników, w wielu przypadkach dużo prościej będzie wykorzystać wbudowany stabilizator LDO 3,3V. Jest to kostka LP2985.

LP2985
Jak pokazuje rysunek 7, mamy dwie wersje: o tolerancji 1% i 1,5%. Tu też należy się liczyć z rozrzutami i zmianą wartości napięcia wyjściowego. Jednak jeśli prąd wyjściowy nie będzie się zmieniał, odchyłki napięcia można skalibrować programowo.

Rysunek 7

Rysunek 8 pochodzący ze starszej wersji katalogu pokazuje wpływ temperatury. Jak widać, przy zmianie temperatury o 50 stopni napięcie wyjściowe typowo może zmienić się o 0,4%. Karta katalogowa nie zawiera dokładniejszych informacji. W każdym razie nieobciążona kostka LP2985 może być sensownym źródłem napięcia odniesienia, jeśli zmiany prądu obciążenia i temperatury będą małe.

Rysunek 8

Internal reference

Trzeba też pamiętać, że procesor ma również wbudowane wewnętrzne źródło napięcia odniesienia dla przetwornika ADC. Typowo jego napięcie ma wynosić 1,1V, ale producent przewiduje zaskakująco dużą tolerancję 1,0…1,2V, czyli około 10%. Ale tolerancja nie jest problemem! Rozrzut między egzemplarzami może być bardzo duży, ale stabilność tego napięcia w konkretnym egzemplarzu jest dość dobra. Jak wskazuje rysunek 9, w całym zakresie temperatur pracy napięcie odniesienia zmieni się o mniej niż 1%. Przy wzroście temperatury procesora z +25°C do +85°C, napięcie zmaleje typowo o około 0,5%. Znów kłania się sprawa zmian temperatury struktury, a to zależne jest m.in. od prądu obciążenia wyjść.

Rysunek 9

Precision external reference

Może się wydawać, że dokładność równą rozdzielczości (0,1%) można uzyskać przez podanie na wyprowadzenie AREF stabilnego zewnętrznego napięcia odniesienia (które może mieć wartość powyżej 1V, ale nie większą niż napięcie zasilania VCC). Scalonych układów źródeł odniesienia (voltage reference) jest mnóstwo. Wejście AREF ma rezystancję 30kΩ…50kΩ, więc nie będzie znaczącym obciążeniem dla takiego źródła.

Owszem, jak najbardziej można wykorzystać zewnętrzne, bardzo precyzyjne źródło napięcia odniesienia.

Ale to jest znaczący kłopot i koszt, a na dodatek też nie pozwoli na uzyskanie bezwzględnej dokładności 0,1%. Dlatego w praktyce wystarczą opisane wcześniej proste, łatwo dostępne możliwości.

Nieliniowość przetwornika

Nawet zastosowanie najbardziej precyzyjnego źródła napięcia odniesienia nie pozwoli uzyskać dokładności 0,1% z uwagi na nieliniowość przetwornika ADC i inne „wewnętrzne” błędy. Jak podaje karta katalogowa procesora (rysunek 10), absolutna dokładność przetwornika to ±2LSB, czyli plus/minus dwa „schodki”. Maksymalna dokładność z idealnym nawet źródłem napięcia odniesienia nie będzie więc lepsza niż ±0,2%. I nie pomoże tu żadne uśrednianie czy „oversampling”, które mogą zwiększyć tylko rozdzielczość, ale nie dokładność.

Rysunek 10

Problem masy

Układy wykorzystujące Arduino często są realizowane w sposób urągający elementarnym zasadom montażu układów elektronicznych. Tymczasem montaż, a konkretnie prowadzenie masy, może mieć bardzo duży wpływ w układach, gdzie wymagana jest jak największa dokładność.

Mówiąc najprościej, chodzi o spadki napięć na rezystancjach tworzących obwód masy.

Warto pamiętać, że przy wykorzystaniu wewnętrznego źródła napięcia odniesienia o wartości około 1,1V, jeden „schodek” (1LSB) to tylko około 1mV.

Jeżeli przykładowo obwód masy będzie miał rezystancję tylko dwóch setnych oma (0,02Ω) i popłynie tam prąd o wartości pół ampera (0,5A), to spadek napięcia na tym obwodzie wyniesie:

U = 0,5A*0,02 Ω = 0,01V = 10mV

Spadek napięcia 10mV to około 10 „schodków” przetwornika ADC. Wynik przetwarzania może być sfałszowany o 10. Może, nie musi, zależnie od tego, jak poszczególne elementy są dołączone do obwodu masy. Temat jest szeroki i wykracza poza ramy serii „Wokół Arduino”.

Podsumowanie

Przedstawione informacje pokazują, że przy pomiarach napięcia mamy trzy główne źródła błędów i niepewności, na które mamy mniejszy lub większy wpływ:

  1. Wahania temperatury, powodujące zmiany napięcia odniesienia przetwornika ADC. Możemy je minimalizować, redukując zmiany prądu obciążenia źródła napięcia odniesienia.
  2. Wahania prądu obciążenia zmieniają moc wydzielanych strat, a tym samym są związane ze zmianami temperatury. Minimalizujemy je, zmniejszając prądy obciążenia wyjść Arduino.
  3. Spadki napięć w obwodzie masy minimalizujemy przez redukcję rezystancji obwodów masy i płynących tam prądów.

Niemniej uzyskanie wiarygodnych  wyników z przetwornika ADC jest możliwe. Unikając opisanych pułapek i prawidłowo projektując układy wykorzystujące Arduino, możemy osiągnąć dokładność pomiaru ADC rzędu ±0,2%…±0,5%, co należy uznać za wartość jak najbardziej  satysfakcjonującą. A jeśli wymagania są większe, trzeba zastosować zewnętrzny, precyzyjny przetwornik ADC.

 Piotr Górecki