Portal dla pasjonatów motoryzacji

Woltomierz AC na arduino. woltomierz bluetooth oparty na arduino

Czy zdarza się, że chcesz sprawdzić napięcie lub jakiś punkt w obwodzie, ale nie masz pod ręką woltomierza ani multimetru? Biegać kupić? Jest długi i drogi. Zanim to zrobisz, co powiesz na zrobienie własnego woltomierza? W rzeczywistości, dzięki prostym komponentom, możesz zrobić to sam.

Krok 1: Przygotowanie składników

  • W tutorialu wykorzystaliśmy płytkę kompatybilną z Arduino - SunFounder Uno / Mars (http://bit.ly/2tkaMba)
  • Kabel USB do transmisji danych
  • 2 potencjometry (50k)
  • LCD1602 - http://bit.ly/2ubNEfi
  • Płyta prototypowa - http://bit.ly/2slvfrB
  • Wiele zworek

Zanim się połączymy, najpierw zrozummy, jak to działa.

Użyj płyty SunFounder Uno do głównej części przetwarzania danych woltomierza, LCD1602 jako ekranu, potencjometru do regulacji kontrastu LCD, a drugiej do podziału napięcia.

Kiedy obracasz potencjometr podłączony do płyty Uno, zmienia się rezystor potencjometru, zmieniając w ten sposób napięcie na nim. Sygnał napięciowy zostanie wysłany do płyty Uno przez pin A0, a Uno przekształci odebrany sygnał analogowy na postać cyfrową i zapisze na wyświetlaczu LCD. Możesz więc zobaczyć wartość napięcia przy aktualnej rezystancji pojemności.

LCD1602 posiada dwa tryby pracy: 4-bitowy i 8-bitowy. Gdy IO MCU jest niewystarczające, możesz wybrać tryb 4-bitowy, który wykorzystuje tylko piny D4 ~ D7.

Postępuj zgodnie z tabelą, aby je połączyć.

Krok 4: podłącz potencjometr do LCD1602

Podłącz środkowy pin potencjometru do pinu Vo na LCD1602, a pozostałe piny do GND.

Podłącz środkowy pin potencjometru do pinu A0 SunFounder Uno i jeden z pozostałych do 5V, a drugi do GND.

Krok 6: Przesyłanie kodu

Kod taki jak ten:

#włączać /*********************************************** ***** *****/ const int analogIn = A0;//potencjometr podłącz do A0 LiquidCrystal lcd(4, 6, 10, 11, 12, 13);//lcd(RS,E,D4,D5 ,D6.D7) float val = 0;// zdefiniuj zmienną jako wartość=0 /******************************* ***** *****************/ void setup() ( Serial.begin(9600);//Zainicjuj serial lcd.begin(16, 2);/ / ustaw pozycję znaków na wyświetlaczu LCD jako wiersz 2, kolumna 16 lcd.print("Voltage Value:");//print "Voltage Value:" ) /************ ***** ************************************/ void loop() ( val = analogRead (A0);//Odczytaj wartość potencjometru do val val = val/1024*5.0;// Przekształć dane na odpowiednią wartość napięcia w sposób matematyczny Serial.print(val);//Wydrukuj liczbę val na monitorze szeregowym Serial.print („V”); // wypisz jednostkę jako V, skrót napięcia na monitorze szeregowym lcd. setCursor(6,1); // umieść kursor w wierszu 1, kolumnie 6. Z tutaj znaki mają być wyświetlane lcd.print(val);//Wydrukuj numer val na LCD lcd.print("V");//Następnie wypisz jednostkę jako V, skrót od napięcia na wyświetlaczu LCD delay( 200); //Poczekaj 200ms )

Obróć potencjometr, aby sprawdzić napięcie na LCD1602 w czasie rzeczywistym.

Oto trudna sprawa. Po uruchomieniu kodu na wyświetlaczu LCD pojawiły się symbole. Następnie wyregulowałem kontrast ekranu (stopniowa zmiana z czarnego na biały) obracając potencjometr w prawo lub w lewo, aż na ekranie będą wyświetlane wyraźnie znaki.

Weź dwie baterie do pomiaru ich napięcia: 1,5 V i 3,7 V. Odepnij podłączenie drugiego potencjometru od pinu A0 i GND, co oznacza wyjęcie potencjometru z obwodu. Zamocuj koniec przewodu A0 do anody akumulatora, a obwód GND do katody. NIE podłączaj ich ponownie, ponieważ spowoduje to zwarcie baterii. Wartość 0V to połączenie odwrotne.

Tak więc napięcie baterii jest wyświetlane na wyświetlaczu LCD. Może występować błąd między wartością a wartością nominalną, ponieważ akumulator nie jest w pełni naładowany. I dlatego muszę zmierzyć napięcie, aby zrozumieć, czy mogę korzystać z baterii, czy nie.

PS: Jeśli masz problemy z wyświetlaniem, zapoznaj się z często zadawanymi pytaniami dotyczącymi wyświetlaczy LCD — http://wiki.sunfounder.cc/index.php?title=LCD1602/I2C_LCD1602_FAQ.

Pomysł

Pomysł urządzenia do pomiaru napięcia, prądu, pojemności, rozładowania, a może i ładunku powstały dawno temu i nie tylko u mnie. Możesz znaleźć sporo zabawek o nazwie Tester USB (Doktor) do testowania różnych urządzeń USB. Interesuje mnie nieco bardziej uniwersalne urządzenie, niezależne od interfejsu, ale po prostu zaprojektowane dla określonych napięć i prądów. Na przykład 0 - 20,00 V, 0 - 5,00 a, 0 - 99,99 Ah. Jeśli chodzi o funkcje, to widzę to tak

  • Wyświetlanie aktualnego napięcia i prądu, czyli woltoamperomierz. W zasadzie możesz natychmiast odzwierciedlić moc.
  • Obliczanie i wyświetlanie skumulowanej pojemności. W amperogodzinach i najprawdopodobniej w watogodzinach.
  • Wyświetlacz czasu procesu
  • I najprawdopodobniej konfigurowalne dolne i górne progi wyłączania napięcia (limity rozładowania i ładowania)

Rozwój

Do realizacji obliczeń i pomiarów potrzebujemy kontrolera. Przypomniałem sobie ten pomysł w ramach znajomości z Arduino, więc prosty popularny Atmega328 będzie kontrolerem i będzie programowany w środowisku Arduino. Z inżynierskiego punktu widzenia wybór chyba nie najlepszy - kontroler do zadania trochę za gruby, a jego ADC nie można nazwać pomiarowym, ale... spróbujemy.

  • W tym projekcie nie będziemy dużo lutować. Jako podstawę weźmiemy gotowy moduł Arduino Pro Mini, ponieważ Chińczycy są gotowi dostarczyć je za 1,5 USD w sprzedaży detalicznej.
  • Urządzeniem wyświetlającym będzie wyświetlacz 1602 – 1,5 USD więcej. Mam opcję z modułem interfejsu I2C, ale w tym projekcie nie jest to bardzo potrzebne (0,7 USD).
  • Do rozwoju potrzebujemy deski do krojenia chleba. W moim przypadku jest to mały BreadBoard za 1 USD.
  • Oczywiście potrzebne będą przewody i szereg rezystorów o różnych wartościach znamionowych. W przypadku wyświetlacza 1602 bez I2C potrzebny jest również wybór kontrastu - odbywa się to za pomocą zmiennego rezystora 2 - 20 kOhm.
  • Aby zaimplementować amperomierz, potrzebujesz bocznika. W pierwszym przybliżeniu może to być rezystor 0,1 oma, 5 watów.
  • Aby wdrożyć automatyczne wyłączanie, potrzebny jest przekaźnik ze stykami zaprojektowanymi na maksymalny prąd urządzenia i napięcie równe napięciu zasilania. Do sterowania przekaźnikiem potrzebny jest tranzystor npn i dioda zabezpieczająca.
  • Urządzenie będzie zasilane zewnętrznym zasilaczem, oczywiście co najmniej 5V. Jeśli zasilanie jest bardzo zróżnicowane, wymagany będzie również zintegrowany stabilizator typu 7805 - określi on napięcie przekaźnika.
  • Gdy Arduino Pro Mini będzie wymagać konwertera USB-TTL do flashowania oprogramowania układowego.
  • Do ustawienia potrzebny będzie multimetr.

Woltomierz

Wdrażam prosty woltomierz z jednym zakresem około 0 - 20 V. Ta uwaga jest ważna, ponieważ ADC naszego kontrolera ma pojemność 10 bitów (1024 wartości dyskretnych), więc błąd wyniesie co najmniej 0,02 V (20/1024). Do implementacji sprzętowej potrzebujemy wejścia analogowego kontrolera, dzielnika z pary rezystorów i jakiegoś wyjścia (wyświetlacz jest w gotowej wersji, port szeregowy można wykorzystać do debugowania).

Zasada pomiaru ADC polega na porównaniu napięcia na wejściu analogowym z napięciem odniesienia VRef. Wyjście ADC jest zawsze liczbą całkowitą - 0 odpowiada 0 V, 1023 odpowiada napięciu VRef. Pomiar realizowany jest poprzez serię kolejnych odczytów napięcia i uśrednianie w okresie pomiędzy aktualizacjami wartości na ekranie. Wybór napięcia odniesienia jest ważny, ponieważ domyślnie jest to napięcie zasilania, które może nie być stabilne. To nam w ogóle nie odpowiada - jako podstawę przyjmiemy stabilne wewnętrzne źródło odniesienia o napięciu 1,1 V, inicjując je wywołaniem analogReference(INTERNAL). Następnie skalibrujemy jego wartość zgodnie z odczytami multimetru.

Na schemacie po lewej - wariant z bezpośrednim sterowaniem wyświetlaczem (jest to po prostu sterowane - patrz standardowy szkic LiquidCrystal\HelloWorld). Po prawej stronie jest opcja I2C, z której będę dalej korzystał. I2C pozwala zaoszczędzić na przewodach (których w zwykłej wersji jest 10, nie licząc podświetlenia). Wymaga to jednak dodatkowego modułu i bardziej złożonej inicjalizacji. W każdym przypadku należy najpierw sprawdzić wyświetlanie symboli na module i wyregulować kontrast - w tym celu wystarczy wyświetlić dowolny tekst po inicjalizacji. Kontrast jest regulowany przez rezystor R1 lub podobny rezystor modułu I2C.

Wejście to dzielnik 1:19, który przy Vref = 1,1 pozwala na uzyskanie maksymalnego napięcia około 20V (zwykle kondensator + dioda zenera jest kładziona równolegle z wejściem dla zabezpieczenia, ale nie ma to dla nas znaczenia już). Rezystory mają rozpiętość, referencyjne Vref sterownika też, więc po złożeniu należy zmierzyć napięcie (przynajmniej zasilanie) równolegle z naszym urządzeniem i multimetrem referencyjnym i wybrać w kodzie Vref, aż odczyty będą się zgadzać. Warto również zauważyć, że każdy ADC ma napięcie przesunięcia zera (co psuje odczyty na początku zakresu), ale nie będziemy się jeszcze w to zagłębiać.

Istotne będzie również odseparowanie „masy” zasilającej i pomiarowej. Nasz ADC ma rozdzielczość nieco gorszą niż 1 mV, co może być problematyczne, jeśli zostanie nieprawidłowo podłączone, zwłaszcza na płytce stykowej. Ponieważ okablowanie płytki modułu zostało już wykonane i pozostaje nam wybór pinów. Moduł posiada kilka pinów "masa", więc musimy upewnić się, że zasilanie modułu dochodzi przez jedną "masę", a pomiary przez drugą. W rzeczywistości do zmian zawsze używam pinu uziemienia znajdującego się najbliżej wejść analogowych.

Do sterowania I2C używany jest wariant biblioteki LiquidCrystal_I2C - w moim przypadku wskazany jest konkretny pinout modułu I2C (Chińczycy produkują moduły z różnymi kontrolkami). Zaznaczam też, że I2C w Arduino wiąże się z wykorzystaniem pinów A4, A5 - na płytce Pro Mini nie ma ich na krawędzi, co jest niewygodne przy prototypowaniu na BreadBoard.

Źródło

#włączać #włączać // Prosty woltomierz z wyświetlaczem i2c 1602. V 16.11 // Ustawienia wyświetlacza i2c 1602 z niestandardowym pinoutem #define LCD_I2C_ADDR 0x27 #define BACKLIGHT 3 #define LCD_EN 2 #define LCD_RW 1 #define LCD_RS 0 #define LCD_D4 4 #define LCD_D5 5 # zdefiniuj LCD_D6 6 #define LCD_D7 7 LiquidCrystal_I2C lcd(LCD_I2C_ADDR,LCD_EN,LCD_RW,LCD_RS,LCD_D4,LCD_D5,LCD_D6,LCD_D7); // Czas odświeżania, ms (200-2000) #define REFRESH_TIME 330 // Wejście analogowe #define PIN_VOLT A0 // Wewnętrzne napięcie odniesienia (select) const float VRef = 1.10; // Współczynnik dzielnika rezystancji wejściowej (Rh + Rl) / Rl. W<-[ Rh ]--(analogInPin)--[ Rl ]--|GND const float VoltMult = (180.0 + 10.0) / 10.0; float InVolt, Volt; void setup() { analogReference(INTERNAL); // Инициализация дисплея lcd.begin (16, 2); lcd.setBacklightPin(BACKLIGHT, POSITIVE); lcd.setBacklight(HIGH); // включить подсветку lcd.clear(); // очистить дисплей lcd.print("Voltage"); } void loop() { unsigned long CalcStart = millis(); int ReadCnt = 0; InVolt = 0; // Чтение из порта с усреднением while ((millis() - CalcStart) < REFRESH_TIME) { InVolt += analogRead(PIN_VOLT); ReadCnt++; } InVolt = InVolt / ReadCnt; // Смещение 0 для конкретного ADC (подобрать или отключить) if (InVolt >0,2) InVolt += 3; // Przelicz na wolty (Wartość: 0..1023 -> (0..VRef) przeskalowane przez Mult) Volt = InVolt * VoltMult * VRef / 1023; // Wyświetl dane lcd.setCursor(0, 1); lcd.print(Volt); lcd.print("V"); )

Schemat ideowy domowego woltomierza bipolarnego na Arduino Uno iz wyświetlaczem 1602A. W artykule „Podwójny woltomierz na ARDUINO UNO” (L.1) autor zaproponował opis woltomierza oraz program do jednoczesnego pomiaru i wskazania dwóch stałych napięć. Jest to bardzo wygodne, jeśli chcesz zmierzyć dwa stałe napięcia w tym samym czasie i porównać je.

Może to być wymagane na przykład podczas naprawy lub ustawiania stabilizatora napięcia stałego w celu pomiaru napięcia na jego wejściu i wyjściu lub w innych przypadkach.

Istnieją jednak obwody z mocą bipolarną, w których napięcie w pewnym punkcie obwodu względem wspólnego „zera” może być dodatnie lub ujemne.

Schemat obwodu

Opisuje, jak zmodyfikować obwód i program, aby urządzenie mogło mierzyć i wskazywać zarówno napięcie dodatnie, jak i ujemne.

Na początek mierzone napięcia podawane są na dwa wejścia analogowe A1 i A2. W sumie jest sześć wejść analogowych, - A0-A5, można wybrać dowolne dwa z nich. W tym przypadku wybrane są A1 i A2. Napięcie na portach analogowych może być tylko dodatnie i tylko w zakresie od zera do napięcia zasilania mikrokontrolera, czyli nominalnie do 5V.

Wyjście portu analogowego jest konwertowane przez ADC mikrokontrolera na postać cyfrową. Aby uzyskać wynik w jednostkach woltów, należy go pomnożyć przez 5 (przez napięcie odniesienia, czyli przez napięcie zasilania mikrokontrolera) i podzielić przez 1024.

Ryż. 1. Schemat ideowy woltomierza bipolarnego na Arduino Uno i 1602A.

Aby móc zmierzyć napięcie większe niż 5V, a raczej większe niż napięcie zasilania mikrokontrolera, ponieważ rzeczywiste napięcie na wyjściu 5-woltowego regulatora na płytce ARDUINO UNO może różnić się od 5V, oraz zwykle trochę niżej, trzeba na wejściu zastosować zwykłe dzielniki rezystancyjne.

Tutaj są to dzielniki napięcia na rezystorach R1, R3 i R2, R4. Ale co, jeśli napięcie musi być zmierzone poniżej zera? W takim przypadku wyjście jest tylko jedno - jest to podniesienie wejściowego poziomu zerowego. Idealnie potrzebujesz połowy napięcia zasilania, czyli do 2,5 V. W tym samym czasie do napięcia wejściowego zostaną dodane dane 2,5 V.

Następnie programowo to napięcie jest po prostu odejmowane od zmierzonego. Będzie to jednak wymagało dodatkowego źródła tego napięcia. Zasadniczo nie jest to trudne, ale istnieje łatwiejsze rozwiązanie.

Płytka ARDUINO UNO oprócz regulatora napięcia 5V posiada również źródło napięcia 3,3V. Tutaj może być używany jako „wirtualne zero” do wprowadzania.

Zmiany w obwodzie widoczne są na rysunku 1. W porównaniu z pierwszą opcją wejście „zero” jest po prostu przestawiane ze wspólnego zera na źródło +3,3V. Dlatego gdy napięcie wejściowe jest dodatnie, to na wejściu jest większe niż 3,3 V (ale nie większe niż 5 V – jest to górna granica pomiaru), a gdy jest ujemne – mniejsze niż 3,3 V (ale nie mniejsze niż OV - jest to dolna granica pomiaru).

Zwiększenie granic pomiarowych (modulo) uzyskuje się przez dzielnik rezystancyjny, a wskazanie rzeczywistego napięcia wejściowego podawanego na X2 i X3 przez programowe odjęcie wartości 3,3V od napięcia na wejściach mikrokontrolera.

Program przedstawiono w tabeli 1. Można to zobaczyć w wierszach:

volt=(vout*5.0/1024.0-3.3)/0.048 ;

wolt=(woltl*5,0/1024,0-3,3)/0,048;

Liczba 3,3 to po prostu podane napięcie „wirtualnego zera” wejścia.

W tych liniach liczba 5.0 to napięcie na wyjściu stabilizatora płyty ARDUINO UNO. Idealnie powinno być 5V, ale dla dokładnego działania woltomierza należy najpierw zmierzyć to napięcie. Podłącz zasilanie i zmierz wystarczająco dokładnym woltomierzem napięcie +5V na złączu POWER płytki.

Co by się nie działo to wpisz w te kreski zamiast 5,0.To samo tyczy się napięcia +3,3V - trzeba je zmierzyć na złączu płytki, bo w rzeczywistości może się nieznacznie różnić od 3,3V. Na przykład, jeśli „5 V” to w rzeczywistości 4,85 V, a „3,3 V” to w rzeczywistości 3,32 V, linie będą wyglądać następująco:

wolt=(vwyj*4,85/1024,0-3,32)/0,048;

wolt=(woltl*4,85/1024,0-3,32)/0,048;

W następnym etapie konieczne będzie zmierzenie rzeczywistych rezystancji rezystorów R1-R4 i określenie współczynników K (wskazano 0,048) dla tych linii za pomocą wzorów:

K1 = R3 / (R1+R3) i K2 = R4 / (R2+R4)

Powiedzmy, że K1 = 0,046, a K2 = 0,051, więc piszemy:

wolt=(vwyj*4,85/1024,0-3,32)/0,046;

wolt=(woltl*4,85/1024,0-3,32)/0,051;

Dlatego tekst programu musi zostać poprawiony zgodnie z rzeczywistym napięciem na wyjściu stabilizatorów 5-woltowych i 3,3-woltowych płyty ARDUINO UNO oraz zgodnie z rzeczywistymi współczynnikami podziału dzielników rezystancyjnych.

Wtedy urządzenie będzie działać dokładnie i nie będzie wymagało żadnej regulacji ani kalibracji. Podczas pomiaru napięcia ujemnego na wyświetlaczu LCD w odpowiedniej linii przed wartością napięcia pojawi się znak minus. Podczas pomiaru napięcia dodatniego nie ma znaku.

Zmieniając współczynniki podziału dzielników rezystancyjnych (i odpowiednio współczynniki „K”) można wprowadzić inne granice pomiarowe, niekoniecznie takie same dla obu wejść.

Przypominam, że do portów cyfrowych D2-D7 płytki ARDUINO UNO podłączony jest moduł wyświetlacza ciekłokrystalicznego typu 1602A typu H1. Wskaźnik LCD jest zasilany przez regulator napięcia 5V, który jest dostępny na płytce regulatora napięcia 5V.

Aby wskaźnik mógł współpracować z ARDUINO UNO, musisz załadować podprogram do programu, aby go kontrolować. Takie procedury nazywane są „bibliotekami”, aw pakiecie oprogramowania dla ARDUINO UNO istnieje wiele różnych „bibliotek”. Wyświetlacz LCD oparty na HD44780 wymaga biblioteki LiquidCrystal. Dlatego program (Tabela 1) rozpoczyna się od załadowania tej biblioteki:

Ta linia nakazuje załadowanie tej biblioteki do ARDUINO UNO. Następnie musisz przypisać porty ARDUINO UNO, które będą współpracować ze wskaźnikiem LCD. Wybrałem porty od D2 do D7. Możesz wybrać inne. Te porty są przypisane przez ciąg:

dioda ciekłokrystaliczna (2, 3, 4, 5, 6, 7);

Następnie program przechodzi do właściwej pracy woltomierza.

Karavkin V. RK-06-17.

Literatura: 1. Karavkin V. - Podwójny woltomierz na ARDUINO UNO. RK-01-17.

Wejścia analogowe płytki Arduino.

Płytka Arduino UNO zawiera 6 wejść analogowych do pomiaru sygnałów napięciowych. Bardziej poprawne byłoby stwierdzenie, że 6 wyjść płytki może pracować zarówno w trybie wyjść dyskretnych, jak i wejść analogowych.

Piny te są ponumerowane od 14 do 19. Są one początkowo skonfigurowane jako wejścia analogowe i mogą być określane jako A0-A5. W dowolnym momencie można je skonfigurować do pracy w trybie wyjść dyskretnych.

tryb pin(A3, WYJŚCIE); // ustawienie trybu wyjścia dyskretnego dla A3
digitalWrite(A3, LOW); // ustawienie wyjścia A3 na stan niski

Aby powrócić do trybu wejścia analogowego:

tryb pin(A3, WEJŚCIE); // ustawienie trybu wejścia analogowego dla A3

Wejścia analogowe i rezystory podciągające.

Rezystory podciągające są podłączone do pinów wejść analogowych, a także do pinów cyfrowych. Włączenie tych rezystorów odbywa się za pomocą polecenia

zapis cyfrowy(A3, WYSOKI); // włącz rezystor podciągający do wejścia A3

Komenda musi być zastosowana do wyjścia skonfigurowanego w trybie wejściowym.

Należy pamiętać, że rezystor może wpływać na poziom wejściowego sygnału analogowego. Prąd z zasilacza 5V, przepływający przez rezystor podciągający, spowoduje spadek napięcia na rezystancji wewnętrznej źródła sygnału. Dlatego lepiej wyłączyć rezystor.

Płytka konwertera analogowo-cyfrowego Arduino.

Właściwy pomiar napięcia na wejściach realizowany jest przez przetwornik analogowo-cyfrowy (ADC) z przełącznikiem dla 6 kanałów. ADC ma rozdzielczość 10 bitów, co odpowiada kodowi wyjściowemu przetwornika 0...1023. Błąd pomiaru wynosi nie więcej niż 2 jednostki najmniej znaczącej cyfry.

Aby zachować maksymalną dokładność (10 cyfr), konieczne jest, aby rezystancja wewnętrzna źródła sygnału nie przekraczała 10 kΩ. Wymóg ten jest szczególnie ważny w przypadku stosowania dzielników rezystorowych podłączonych do wejść analogowych płytki. Rezystancja rezystorów dzielnika nie może być zbyt duża.

Funkcje oprogramowania wejść analogowych.

int odczyt analogowy (port)

Odczytuje wartość napięcia na określonym wejściu analogowym. Napięcie wejściowe w zakresie od 0 do poziomu napięcia odniesienia (często 5 V) jest konwertowane na kod od 0 do 1023.

Przy napięciu odniesienia 5 V rozdzielczość wynosi 5 V / 1024 = 4,88 mV.

Konwersja zajmuje około 100 µs.

int kod wejściowy; // kod napięcia wejściowego
wejście pływakoweNapięcie; // napięcie wejściowe w V

inputCod=analogRead(A3); // odczytać napięcie na wejściu A3
inputVoltage= ((float) inputcod * 5. / 1024.); // kod konwersji na napięcie (V)

void analogReference(typ)

Ustawia napięcie odniesienia dla przetwornika ADC. Określa maksymalne analogowe napięcie wejściowe, które przetwornik ADC może poprawnie przekonwertować. Wartość napięcia odniesienia określa również współczynnik konwersji kodu na napięcie:

Napięcie wejściowe = kod ADC * napięcie odniesienia / 1024.

Argument typu może przyjmować następujące wartości:

  • DOMYŚLNE - napięcie odniesienia jest równe napięciu zasilania sterownika (5 V lub 3,3 V). Dla Arduino UNO R3 - 5 V.
  • WEWNĘTRZNE - wewnętrzne napięcie odniesienia 1,1 V dla płyt ze sterownikami ATmega168 i ATmega328, dla ATmega8 - 2,56 V.
  • INTERNAL1V1 - Wewnętrzne napięcie odniesienia 1,1 V dla kontrolerów Arduino Mega.
  • INTERNAL2V56 - wewnętrzne napięcie odniesienia 2,56 V dla kontrolerów Arduino Mega.
  • ZEWNĘTRZNE – zewnętrzne źródło napięcia odniesienia, podłączone do wejścia AREF.

Odniesienie analogowe(WEWNĘTRZNE); // napięcie odniesienia wynosi 1,1 V

Dwukanałowy woltomierz na Arduino.

Jako przykład wykorzystania funkcji wejść analogowych stwórzmy prosty projekt woltomierza cyfrowego na Arduino. Urządzenie musi mierzyć napięcia na dwóch wejściach analogowych płytki i przesyłać zmierzone wartości do komputera przez port szeregowy. Na przykładzie tego projektu pokażę zasady tworzenia prostych systemów do pomiaru i zbierania informacji.

Postanawiamy, że woltomierz powinien mierzyć napięcie w zakresie co najmniej 0...20 V i opracować obwód do podłączenia wejść woltomierza do płytki Arduino UNO.

Jeżeli ustawimy napięcie odniesienia na 5 V, to wejścia analogowe płytki zmierzą napięcie w zakresie 0...5 V. A potrzebujemy co najmniej 0...20 V. Musimy więc zastosować dzielnik napięcia.

Napięcie na wejściu i wyjściu dzielnika są powiązane zależnością:

Uwy = (Uwe / (R1 + R2)) * R2

Współczynnik transmisji:

K = Uwyjście / Uwejście = R2 / (R1 + R2)

Potrzebujemy wzmocnienia 1/4 (20V * 1/4 = 5V).

Aby zachować maksymalną dokładność (10 cyfr), konieczne jest, aby rezystancja wewnętrzna źródła sygnału nie przekraczała 10 kΩ. Dlatego wybieramy rezystor R2 równy 4,22 kOhm. Obliczamy rezystancję rezystora R1.

0,25 = 4,22 / (R1 + 4,22)
R1 \u003d 4,22 / 0,25 - 4,22 \u003d 12,66 kOhm

Znalazłem rezystory o rezystancji 15 kOhm z najbliższą wartością znamionową. Z rezystorami R1 = 15 kΩ i R2 = 4,22:

5 / (4,22 / (15 + 4,22)) = 22,77 V.

Obwód woltomierza oparty na Arduino będzie wyglądał następująco.

Do wejść analogowych A0 i A1 podłączone są dwa dzielniki napięcia. Kondensatory C1 i C2 wraz z dzielnikami tworzą filtry dolnoprzepustowe, które usuwają szumy o wysokiej częstotliwości z sygnałów.

Zmontowałem ten obwód na płytce stykowej.

Pierwsze wejście woltomierza podłączyłem do zasilacza stabilizowanego, a drugie do zasilania 3,3 V płytki Arduino. Aby kontrolować napięcie, podłączyłem woltomierz do pierwszego wejścia. Pozostaje napisać program.

Program do pomiaru napięcia z wykorzystaniem płytki Arduino.

Algorytm jest prosty. Niezbędny:

  • odczytywać kod ADC dwa razy na sekundę;
  • przekonwertować go na napięcie;
  • przesłać zmierzone wartości przez port szeregowy do komputera;
  • Program monitorujący port Arduino IDE wyświetla uzyskane wartości napięć na ekranie komputera.

Podam zarys programu w całości.

// program do pomiaru napięcia
// na wejściach analogowych A0 i A1

#włączać

czas okresu pomiarowego
#definiuj R1 15. // rezystor R1
#definiuj R2 4.22 // rezystor R2


pływak u1, u2; // zmierzone napięcia

anuluj konfigurację()(
Serial.begin(9600); //

MsTimer2::start(); // włączyć przerwanie
}

pusta pętla() (

// okres 500 ms
if (licznik czasu >= MEASURE_PERIOD) (
licznik czasu=0;

//

// odczytywanie kodu kanału 2 i konwersja na napięcie
u2= ((float)analogRead(A1)) * 5. / 1024. / R2 * (R1 + R2);

// transfer danych przez port szeregowy
Serial.print("U1 = "); Wydruk seryjny(u1, 2);
Serial.print(" U2 = "); Serial.println(u2, 2);
}
}

// przetwarzanie przerwań 1 ms
unieważnienie timeraInterupt() (
licznik czasu++;
}

Pozwól, że wyjaśnię linię, w której kod ADC jest konwertowany na napięcie:

// odczytywanie kodu kanału 1 i konwersja na napięcie
u1= ((float)analogRead(A0)) * 5. / 1024. / R2 * (R1 + R2);

  • Odczytywany jest kod ADC: analogRead(A0) .
  • Jawnie przekonwertowany na format zmiennoprzecinkowy: (float) .
  • Przeliczone na napięcie na wejściu analogowym: * 5. / 1024. Kropka na końcu cyfr oznacza, że ​​jest to liczba zmiennoprzecinkowa.
  • Uwzględniany jest współczynnik dzielnika: / R2 * (R1 + R2) .

Załadujmy program na płytkę, uruchommy monitor portu szeregowego.

Dwie biegnące kreski pokazują wartości mierzonych napięć. Wszystko działa.

Pomiar średniej wartości sygnału.

Podłączmy pierwszy kanał naszego woltomierza do źródła napięcia o wysokim poziomie tętnienia. Taki obraz zobaczymy na monitorze.

Wartości napięć pierwszego kanału na ekranie monitora cały czas drgają i skaczą. A odczyty woltomierza kontrolnego są dość stabilne. Dzieje się tak, ponieważ woltomierz wzorcowy mierzy średnią wartość sygnału, podczas gdy płytka Arduino odczytuje poszczególne próbki co 500ms. Naturalnie moment odczytu ADC przypada na różne punkty sygnału. A przy wysokim poziomie pulsacji amplituda w tych punktach jest inna.

Ponadto, jeśli sygnał jest odczytywany w oddzielnych rzadkich próbkach, wówczas każdy szum impulsowy może wprowadzić znaczny błąd do pomiaru.

Rozwiązaniem jest pobieranie kilku częstych próbek i uśrednianie zmierzonej wartości. Dla tego:

  • w procedurze obsługi przerwania odczytujemy kod ADC i sumujemy go z poprzednimi próbkami;
  • policzyć czas uśredniania (liczbę uśrednionych próbek);
  • po osiągnięciu określonej liczby próbek zapisujemy całkowitą wartość kodów ADC;
  • aby otrzymać wartość średnią dzielimy sumę kodów ADC przez liczbę próbek uśredniających.

Zadanie z podręcznika do matematyki klasa 8. Oto szkic programu, dwukanałowego woltomierza wartości średniej.

// program do pomiaru średniego napięcia
// na wejściach analogowych A0 i A1

#włączać

#define MEASURE_PERIOD 500 // czas okresu pomiarowego
#definiuj R1 15. // rezystor R1
#definiuj R2 4.22 // rezystor R2

int licznik czasu; // licznik czasu
długa sumaU1, sumaU2; // zmienne do sumowania kodów ADC
długa dostępnośćU1, dostępnośćU2; // suma kodów ADC (średnia * 500)
flaga logicznaGotowe; // znak gotowości danych pomiarowych

anuluj konfigurację()(
Serial.begin(9600); // zainicjuj port, prędkość 9600
MsTimer2::set(1, timerInterupt); // przerwania timera, okres 1 ms
MsTimer2::start(); // włączyć przerwanie
}

pusta pętla() (

if (flagReady == true) (
flagGotowy=false;
// konwersja na napięcie i przesłanie do komputera
Serial.print("U1 = ");
Serial.print((float)avarageU1 / 500. * 5. / 1024. / R2 * (R1 + R2), 2);
Serial.print(" U2 = ");
Serial.println((float)avarageU2 / 500. * 5. / 1024. / R2 * (R1 + R2), 2);
}
}

// przetwarzanie przerwań 1 ms
unieważnienie timeraInterupt() (

licznik czasu++; // +1 uśredniający licznik próbek
sumU1+=odczyt analogowy(A0); // sumowanie kodów ADC
sumU2+=odczyt analogowy(A1); // sumowanie kodów ADC

// sprawdzanie liczby próbek uśredniających
if (licznik czasu >= MEASURE_PERIOD) (
licznik czasu=0;
dostępnośćU1=sumaU1; // przeciążenie wartością średnią
średniaU2=sumaU2; // przeciążenie wartością średnią
suma U1= 0;
sumaU2=0;
FlagReady=true; // znak wynik pomiaru jest gotowy
}
}

Do wzoru na konwersję kodu ADC na napięcie dodano liczbę /500 próbek. Załaduj, uruchom monitor portu (Cntr + Shift + M).

Teraz, nawet przy znacznym poziomie tętnienia, odczyty zmieniają się o setne części. Dzieje się tak tylko dlatego, że napięcie nie jest stabilizowane.

Liczbę próbek należy wybrać biorąc pod uwagę:

  • liczba próbek determinuje czas pomiaru;
  • im większa liczba próbek, tym mniejszy będzie wpływ interferencji.

Głównym źródłem zakłóceń w sygnałach analogowych jest sieć 50 Hz. Dlatego pożądane jest wybranie czasu uśredniania będącego wielokrotnością 10 ms - czasu półcyklu sieci o częstotliwości 50 Hz.

Optymalizacja obliczeń.

Obliczenia zmiennoprzecinkowe po prostu pochłaniają zasoby 8-bitowego mikrokontrolera. Każda operacja zmiennoprzecinkowa wymaga denormalizacji mantysy, operacji stałoprzecinkowej, normalizacji mantysy, korekty wykładniczej... I wszystkich operacji na liczbach 32-bitowych. Dlatego konieczne jest zminimalizowanie stosowania obliczeń zmiennoprzecinkowych. Powiem ci, jak to zrobić w następnych lekcjach, ale przynajmniej zoptymalizujmy nasze obliczenia. Efekt będzie znaczący.

W naszym programie konwersja kodu ADC na napięcie jest zapisana w następujący sposób:

(zmiennoprzecinkowa)średniaU1 / 500. * 5. / 1024. / R2 * (R1 + R2)

Ile jest obliczeń i wszystkie są zmiennoprzecinkowe. Ale większość obliczeń to operacje ze stałymi. Część liniowa:

/ 500. * 5. / 1024. / R2 * (R1 + R2)

(zmiennoprzecinkowa)średniaU1 * 0,00004447756

Inteligentne kompilatory same rozpoznają obliczenia ze stałymi i obliczają je w czasie kompilacji. Miałem pytanie, jak inteligentny jest kompilator Andruino. Postanowiłem sprawdzić.

Napisałem krótki program. Wykonuje cykl 10 000 przejść, a następnie przekazuje do komputera czas wykonania tych 10 000 cykli. Te. pozwala zobaczyć czas wykonania operacji umieszczonych w ciele pętli.

// sprawdzenie optymalizacji obliczeń

intx= 876;
pływak y;
liczba int bez znaku;
unsigned long timeCurrent, timePrev;

anuluj konfigurację()(
Serial.begin(9600);
}

pusta pętla() (
liczyć++;
// y= (liczba zmiennoprzecinkowa)x / 500. * 5. / 1024. / 4,22 * (15. + 4,22);
// y= (liczba zmiennoprzecinkowa)x * 0.00004447756 ;

jeśli (liczba >= 10000) (
liczba=0;
czasCurrent=milis();
Serial.println(czasBieżący - czasPoprzedni);
czasPoprzedni=czasBieżący;
}
}

W pierwszym wariancie, gdy operacje zmiennoprzecinkowe są komentowane i nie są wykonywane w pętli, program dał wynik 34 ms.

Te. 10 000 pustych cykli wykonuje się w ciągu 34 ms.

Następnie otworzyłem linię:

y= (liczba zmiennoprzecinkowa)x / 500. * 5. / 1024. / 4,22 * (15. + 4,22);

powtarza nasze obliczenia. Wynik 10 000 przebiegów w ciągu 922 ms lub

(922 - 34) / 10 000 = 88,8 µs.

Te. wykonanie tej linii obliczeń zmiennoprzecinkowych zajmuje 89 µs. Myślałem, że będzie więcej.

Teraz zamknąłem tę linię komentarzem i otworzyłem następną, pomnożoną przez wstępnie obliczoną stałą:

y= (liczba zmiennoprzecinkowa)x * 0,00004447756 ;

Wynik 10 000 przebiegów w ciągu 166 ms lub

(166 - 34) / 10 000 = 13,2 µs.

Niesamowity wynik. Zaoszczędziliśmy 75,6 µs na linię. Ukończono go prawie 7 razy szybciej. Mamy 2 takie linie, ale w programie może być ich znacznie więcej.

Wniosek - obliczenia ze stałymi należy wykonać samodzielnie na kalkulatorze i wykorzystać w programach jako gotowe współczynniki. Kompilator Arduino nie obliczy ich na etapie kompilacji. W naszym przypadku powinniśmy zrobić tak:

# zdefiniuj ADC_U_COEFF 0.00004447756 // Kod ADC na współczynnik konwersji napięcia

Serial.print((float)avarageU1 * ADC_U_COEFF, 2);

Optymalną opcją prędkości jest przesłanie kodu ADC do komputera, a wraz z nim wszystkich obliczeń zmiennoprzecinkowych. W takim przypadku wyspecjalizowany program powinien odbierać dane na komputerze. Monitor portu z Arduino IDE nie będzie działać.

W razie potrzeby omówię inne sposoby optymalizacji programów Arduino na przyszłych lekcjach. Ale bez rozwiązania tego problemu niemożliwe jest tworzenie złożonych programów na 8-bitowym mikrokontrolerze.

Na stronie () pojawiła się kolejna lekcja poświęcona pomiarom sygnałów analogowych. Zajmuje się pracą ADC w tle.

W następnej lekcji nauczymy się, jak pracować z wewnętrzną pamięcią EEPROM, porozmawiajmy o kontroli integralności danych.

Kategoria: . Możesz dodać do zakładek.

W tym artykule pokazano, jak połączyć Arduino z komputerem i przesłać dane z ADC do komputera. Program Windows został napisany przy użyciu Visual C++ 2008 Express. Program woltomierza jest bardzo prosty i ma wiele do zrobienia. Jego głównym celem było pokazanie pracy z portem COM oraz wymiany danych pomiędzy komputerem a Arduino.

Komunikacja między Arduino a komputerem:

  • Pobieranie odczytów z ADC rozpoczyna się, gdy komputer wysyła polecenia 0xAC i 0x1y do Arduino. Na– numer kanału ADC (0-2);
  • Odczyt zatrzymuje się po otrzymaniu przez Arduino poleceń 0xAC i 0x00;
  • Podczas odczytu Arduino co 50 ms wysyła do komputera komendy 0xAB 0xaa 0xbb, gdzie aa i bb to pomiary maksymalne i minimalne.

Program dla Arduino

Możesz przeczytać więcej o komunikacji szeregowej na arduino.cc. Program jest dość prosty, większość działa z portem równoległym. Po zakończeniu odczytu danych z ADC otrzymujemy 10-bitową wartość napięcia (0x0000 - 0x0400) w postaci 16-bitowych zmiennych (INT). Port szeregowy (RS-232) umożliwia przesyłanie danych w pakietach po 8 bitów. Konieczne jest podzielenie zmiennych 16-bitowych na 2 części po 8 bitów.

Serial.print(napięcie>>8,BAJT);

Serial.print(napięcie%256,BYTE);

Przesuwamy bajty zmiennej o 8 bitów w prawo, a następnie dzielimy przez 256 i wysyłamy wynik do komputera.

Możesz pobrać pełny kod źródłowy oprogramowania Arduino.

Visual C++

Zakładam, że masz już podstawową wiedzę na temat programowania w C++ dla Windows, jeśli nie, skorzystaj z Google. Internet jest pełen tutoriali dla początkujących.

Pierwszą rzeczą do zrobienia jest dodanie portu szeregowego z paska narzędzi do dolnego formularza. Umożliwi to zmianę kilku ważnych parametrów portu szeregowego: nazwy portu, szybkości transmisji, szybkości transmisji. Jest to przydatne do dodawania kontrolek do okna aplikacji, do zmiany tych ustawień w dowolnym momencie, bez ponownej kompilacji programu. Użyłem tylko opcji wyboru portu.

Po wyszukaniu dostępnych portów szeregowych domyślnie wybierany jest pierwszy port. Jak to jest zrobione:

szyk< String ^>^serialPorts=nullptr;

serialPorts = serialPort1->GetPortNames();

this->comboBox1->Elementy->AddRange(serialPorts);

this->comboBox1->SelectedIndex=0;

Port szeregowy w komputerze PC może być używany tylko przez jedną aplikację na raz, dlatego port musi być otwarty przed użyciem i nie może być zamknięty. Proste polecenia do tego:

SerialPort1->Otwórz();

serialPort1->Zamknij();

Aby poprawnie odczytać dane z portu szeregowego, należy użyć zdarzeń (w naszym przypadku przerwania). Wybierz typ wydarzenia:

Lista rozwijana po dwukrotnym kliknięciu „DataReceived”.

Kod zdarzenia jest generowany automatycznie:

Jeśli pierwszym bajtem, który dotarł do portu szeregowego, jest 0xAB, oznacza to, że pozostałe bajty przenoszą dane dotyczące napięcia.

prywatny: System::Void serialPort1_DataReceived(System::Object^ nadawca, System::IO::Ports::SerialDataReceivedEventArgs^ e) (

znak bez znaku dane0, dane1;

if (serialPort1->ReadByte()==0xAB) (

data0=serialPort1->ReadByte();

data1=serialPort1->ReadByte();

napięcie=Math::Round((float(dane0*256+dane1)/1024*5,00),2);

liczba_danych++;

SerialPort1->ReadByte();

Zapisywanie i odczytywanie danych portu szeregowego

Dla mnie małym problemem było przesyłanie heksadecymalnych danych RAW przez port szeregowy. Użyto polecenia Write(); ale z trzema argumentami: tablica, numer początkowego bajtu, liczba bajtów do zapisania.

prywatny: System::Void button2_Click_1(System::Object^ nadawca, System::EventArgs^ e) (

kanał znaków bez znaku = 0;

kanał=to->listBox1->WybranyIndeks;

tablica^start =(0xAC,(0x10+kanał));

tablica^stop =(0xAC,0x00);

port szeregowy1->Zapisz(początek,0,2);

this->button2->Text="Stop";

) w przeciwnym razie (

SerialPort1->Zapisz(stop,0,2);

this->button2->Text="Start";

To wszystko!

Oryginalny artykuł w języku angielskim (tłumaczenie: Aleksander Kasjanow dla witryny cxem.net)