Rejestrator parametrów – U, I, T

Przod_1

W końcu udało mi się ukończyć projekt, który rozpocząłem rok temu! Jest to rejestrator parametrów – U,I,T. Głównym celem wykonania urządzenia, była możliwość monitorowania zmian napięcia, prądu i temperatury w badanym układzie wraz z zapisem na kartę SD. Urządzenie to będzie mi umożliwiało łatwą diagnozę problemów z wykonanymi układami – bo przeważnie następuje jakaś zmiana, gdy się odejdzie od miernika na przysłowiową sekundę. Dużej dokładności rejestrator może i nie ma, ale będę wiedział gdzie w pewnym zakresie napięć i prądu, a także czasu mam szukać problemu. Dodatkowo potrzebowałem też urządzenia przenośnego do pomiaru i rejestracji temperatury w danym pomieszczeniu.

Założenia i koncepcja zmieniła się nieznacznie w stosunku do tego co pisałem w temacie związanym z realizacją tego układu. Dla przypomnienia przedstawię je jeszcze raz, ale już w formie ostatecznej (uaktualnionej):

Założenia ogólne:

  • Zapis danych na kartę SD;
  • Pomiar napięcia do 13VDC;
  • Pomiar prądu, do 0,5A;
  • Pomiar temperatury z wykorzystaniem DS18B20
  • Zasilanie bateryjne, bądź z zasilacza 12VDC;
  • Podłączenie przejściówki RS232, modułu bluetooth – złącze RJ45 6P;
  • Interfejs użytkownika w postaci wyświetlacza i 4 przycisków;
  • Wyświetlanie pomiaru napięcia, prądu i temperatury na wyświetlaczu;
  • Diody sygnalizujące wykonywany pomiar, oraz zapis na kartę SD;
  • 2 złącza 2 pinowe do pomiaru napięcia i prądu;
  • Czujnik temperatury podłączany poprzez złącze jack;
  • Pozostałe kanały wyprowadzone na złącze RJ46 8P;
  • Mała, przenośna obudowa.

Założenia programistyczne:

  • Możliwość zmiany nazw zapisywanych plików z poziomu UI;
  • Zmiana czasu dokonywania pomiarów (próbkowania);
  • Włączenie/wyłączenia odpowiednich kanałów pomiarowych;
  • Dane konfiguracyjne zapisywane w pamięci EEPROM;

Czytając powyższe założenia, można sobie wyobrazić ogrom pracy, jaki był, podczas wykonywania rejestratora. Gdy zabrałem się za wykonywanie projektu, myślałem że nie uda mi się wszystkich założeń wykonać tak jak planuję. Jednak udało mi się i jestem z tego efektu bardzo zadowolony.

Zapraszam do zapoznania się z opisem urządzenia – budowa oraz działanie.


Najpierw wspomnę o złączach jack, oraz RJ45.

W projekcie tym zastosowałem dwa typy złącz, którym odpowiednim pinom przypisałem konkretne zadanie. Dzięki temu będę mógł je wykorzystywać również w kolejnych projektach jako swoje standardy złączek. Są to złącza jack oraz modułowe RJ – pierwszy z nich będzie miał zastosowanie w podłączeniu czujników komunikujących się po 1-wire. Natomiast złącze modułowe RJ z 6 pinami będzie zastosowane między innymi do komunikacji po RS232 a także RS485 (RS485 w chwili obecnej nie wykorzystuję – jest to pomysł na przyszłość). W projektach będę wykorzystywał różnego rodzaju złącza modułowe RJ, w których dwa piny będą miały zawsze tą samą polaryzację (1 jako VCC, ostatni jako GND).

Zastosowanie powyższych złączek umożliwia pewne i sprawne podłączanie i odłączanie danych modułów z wykonanego urządzenia. Gorąco polecam tworzenie swoich „standardów” złączek.


W wykonanym urządzeniu napięciem pracy jest 3.3V, więc zastosowanie typowego wyświetlacza z sterownikiem HD44780 może skutkować tym, że napisy mogą nie być prawidłowo wyświetlane z powodu zbyt małego napięcia kontrastu. Postanowiłem więc zastosować przetwornicę napięcia ujemnego i wykonać moduł do tych wyświetlaczy. Dodatkowo taki moduł wyposażyłem w złączki które ułatwią mi podłączanie tego wyświetlacza do docelowego układu. Moduł ten został opisany w poprzednim wpisie. Zachęcam do zapoznania się z nim: Uniwersalny moduł wyświetlacza.

Rejestrator U I T - schemat ideowy
Rejestrator U I T – schemat ideowy

Rejestrator może być zasilany z dwóch źródeł – z baterii (na chwilę obecną jest to bateria 9V – nie nadają się one jednak do takiego zastosowania bo mają zbyt małą pojemność), bądź z zasilacza zewnętrznego. Napięcie jakie panuje w wykonanym układzie jak już wcześniej wspomniałem wynosi 3.3V, jest ono zapewniane przez stabilizator LM1117DT-3.3. Zastosowanie napięcie 3.3V umożliwiło bezpośrednie podłączenie karty SD do mikrokontrolera bez stosowania dodatkowych układów do translacji napięcia. Komunikacja po RS232 jak i obsługa czujnika DALLAS DS18B20 jest również możliwa przy zastosowanym napięciu. Jak już pisałem we wcześniejszym akapicie – wyświetlacz LCD posiada moduł wraz z przetwornicą napięcia ujemnego dzięki czemu nie ma również problemu z wyświetlaniem komunikatów. Jedyny problem – raczej niedogodność – dotyczy pomiaru różnicowego napięcia oraz prądu, a dokładnie maksymalnego napięcia wyjściowego w zastosowanym wzmacniaczu operacyjnym. Według noty katalogowej LM358 napięcie wyjściowe wzmacniacza operacyjnego może wynieść maksymalnie V+1,5V (V+ napięcie zasilające), czyli w moim przypadku dla napięcia zasilającego 3.3V maksymalne napięcie wyjściowe wyniesie 1,8V (po pomiarach w rzeczywistości maksymalne napięcie wyjściowe wynosi 2V). Znając ten parametr musiałem tak dobrać wzmocnienie każdego wzmacniacza aby przy maksymalnej mierzonej wartości nie przekroczyć tego napięcia.

Pomiar różnicowy prądu oraz napięcia
Pomiar różnicowy prądu oraz napięcia

Urządzenie umożliwia pomiar napięcia na 7 kanałach, oraz pojedynczy pomiar prądu. W tych 7 kanałach do pomiaru napięcia znajduje się 6 kanałów nieskonfigurowanych (nieposiadających żadnego pomiaru różnicowego – napięcie podawane jest bezpośrednio do układu scalonego i nie może ono przekroczyć napięcia 2,56V), oraz jeden kanał umożliwiający pomiar napięcia do 13V. Do pomiaru napięcia jak i prądu wykorzystałem układ różnicowy z wzmacniaczem operacyjnym. Układ ten umożliwia pomiar spadku napięcia na danym elemencie. Poprzez odpowiedni dobór rezystorów możliwe jest uzyskanie wzmocnienia w dużym zakresie – większe jak i mniejsze od 1. Jedyny największy minus tego rozwiązania to niska rezystancja wejść wzmacniacza, co może powodować zakłócenia w badanym układzie. Dlatego starałem się zastosować rezystancje jak największe, aby wpływ ten był jak najmniejszy (im większa rezystancja to tym mniejszy prąd płynący przez rezystory w układzie różnicowym – prąd który jest „pobierany” z badanego układu). Wzmocnienie w tym układzie wynosi k=7 (wartość wzmocnienia obliczonego na podstawie rezystancji wynosi 6.67, natomiast podałem wartość wzmocnienia „rzeczywistego” – rezystancja ścieżek, dokładność 5% rezystorów i lutów w tym przypadku odegrała znaczącą rolę).

W pomiarze prądu został zastosowany rezystor, tzw. bocznik. Pomiar spadku napięcia na tym rezystorze umożliwia obliczenie z prawa Ohma prądu jaki przez ten rezystor płynie. Zastosowany rezystor posiada rezystancję 0.1ohma. Natomiast rezystory w układzie różnicowym definiują wzmocnienie o wartości k=41 (zastosowałem rezystory o dokładności 1%). Upraszczając – spadek napięcia jest wprost proporcjonalny do prądu płynącego przez rezystor w proporcjach 1 do 4.

Próbkowanie można ustalić na jednym z następujących poziomów (czas podany w sekundach):

0,1; 0,2; 0,3; 0,4; 0,6; 0,8; 1; 2; 3; 4; 5; 6; 7; 8; 9; 10; 11; 12; 13; 14; 15; 20; 25; 30; 40; 60; 90; 120; 150; 180

Zostały również wykonane test układu, w celu sprawdzenia czy najmniejszy czas próbkowania nie powoduje jakichś błędów, lub nieprawidłowości w działaniu całego programu jak i urządzenia. Testy wykonałem przy włączonych wszystkich kanałach pomiarowych, oraz temperatury (czyli wykonywanych było 9 pomiarów). Aktywny był zapis na kartę SD (maksymalna ilość zapisywanych danych do pliku, czyli 100), oraz przesyłanie pomiarów przez RS232. Czas pomiaru wyniósł około 4 minut (plus opóźnienie z włączeniem i wyłączeniem pomiarów). Wyniki testów przedstawiają się następująco:

  • ilość plików – 25;
  • ilość próbek – 2463;
  • czas wykonywania pomiarów według ilości próbek – 4 minuty i 6,3 sekundy.

Poniżej przedstawiam krótki algorytm z działania całego programu – jest to algorytm ogólny, gdyby zaszła taka potrzeba mogę wykonać kolejne algorytmy, ale to w zależności czy ktoś będzie zainteresowany (proszę o umieszczanie tego w komentarzach do tego wpisu).

Algorytm główny działania programu

Natomiast kod pętli głównej jest następujący:

while(1){
	backlight();
	return_screen();
	button_service();
	DISPLAY_EVENT(1);
	wdt_reset();
	pomiary();
	ADC_EVENT();
	zapisz_dane();
	UART_EVENT(uart_bufor);
	sygnalizacja_led();
	wdt_reset();
}

 Jak można zauważyć, również i w poprzednich wpisach, główne pętle programów staram się pisać w ten sposób aby były przedstawione w jak najprostszy sposób, tzn zawierały funkcje i zajmowały jak najmniej miejsca. Ma to na celu lepsze analizowanie kodu w przyszłości. Każda czynność ma przypisaną swoją funkcję, dzięki czemu łatwo mogę odnaleźć ją i dokonać ewentualnej modyfikacji. Ułatwia również to dodawanie nowych funkcjonalności, szczególnie tych, które muszą zostać wykonane po konkretnej czynności. Ten program również cechuje się brakiem blokujących funkcji (pomijam minimalny wpływ opóźnień wynikających z obsługi magistrali 1-wire).

Wykorzystanie zasobów mikrokontrolera ATmega32 przedstawia się następująco:

  • FLASH – 27,848 kb tj. 85%
  • RAM – 1,372kb tj. 67%
  • EEPROM – 24b tj. 2,3%

Mikrokontroler taktowany jest kwarcem o częstotliwości 16MHz.

Na potrzeby projektu, stworzyłem własne biblioteki do obsługi przycisków jak i menu. Na razie przedstawię tylko najciekawsze fragmenty biblioteki do obsługi przycisków. W przyszłości, jak zajdzie taka potrzeba, w nowym wpisie przedstawię swoją bibliotekę wraz z opisem działania.

Rejestrację nowych przycisków dokonuje się poprzez wywołanie odpowiedniej funkcji. Wygląda to w ten sposób:

//rejestracja klawiszy
button_register(&SW_UP, &(PIN(BUTTON_PORT)), (1<<BUTTON_UP),1,20,up_menu_button,NULL);         //1
button_register(&SW_DWN, &(PIN(BUTTON_PORT)), (1<<BUTTON_DWN),1,20,down_menu_button,NULL);      //4
button_register(&SW_OK, &(PIN(BUTTON_PORT)), (1<<BUTTON_OK),2,200,ok_menu_button, start_button);   //2
button_register(&SW_EXIT, &(PIN(BUTTON_PORT)), (1<<BUTTON_EXIT),2,2,exit_menu_button, NULL);      //3

Natomiast zdarzenie/procedura obsługująca przyciski ma postać:

//obsługa przycisków
void button_service(void){

   uint8_t i=0;         //i - numer obsługiwanego przycisku,
   enum b_st state=none;      // state stan dla danego przycisku

   for(i=0 ; i < MAX_BUTTON ; i++){
      if(button_tab[i]) {
         state = ds_button_serv(i);

         if(state == procedure)
            continue;

         if(state == button_short){
            if(button_tab[i]-&short_push)         //jeżeli została przydzielona funkcja
               button_tab[i]-&short_push();
            break;
         }
         else if(state == button_long){
            if(button_tab[i]-&long_push)         //jeżeli została przydzielona funkcja
               button_tab[i]-&long_push();
            break;
         }
      }
   }
}

Struktura, która przechowuje informację o przyciskach wygląda następująco:

typedef struct {
    volatile uint8_t *PORT;      //port do którego podłączony jest klawisz, np. PINB
    uint8_t button_mask_pin;      //pin/maska pinu do którego podłączony jest przycisk, np. (1<<PB0)
    uint8_t repeat_wait_s;      //czas oczekiwania na identyfikację długiego wcisniecia      w s
    uint8_t repeat_time_ms;      //czas pomiędzy powtórzeniami   w 10ms
    void (*short_push)(void);      //funkcja obsługująca krótkie wcisnienie
    void (*long_push)(void);      //funkcja obslugująca długie wcisnięcie
} DS_BUTTON;

Komunikacja z komputerem odbywa się poprzez interfejs RS232, natomiast obsługę wykonuje się poprzez komendy AT z wykorzystaniem terminala. Poprzez komendy AT możliwa jest ta sama zmiana i konfiguracja parametrów co poprzez UI. Jedynie kalibracja wyświetlanych wartości napięcia i prądu na wyświetlaczu LCD, jest możliwa poprzez komendy AT (polecenie AT+CAL) – nie ma takiej możliwości z poziomu menu na wyświetlaczu. Dodatkowo do mikrokontrolera jest wgrany bootloader, który umożliwia wgranie nowego programu poprzez RS232 bez podłączania zewnętrznego programatora. Poniżej przedstawiam screeny z działania komunikacji przez RS232.

W ostatniej kolumnie znajduje się pomiar temperatury. Pierwsza wartość jest tak duża z tego względu, że czujnik temperatury po inicjalizacji pierwszego pomiaru musi mieć pewien czas aby dokonać konwersji tej temperatury. Zostawiłem ten odczyt bez opóźnienia, z tego względu, żeby można było określić czy inicjalizacja przebiegła pomyślnie.

Wyniki odczytu napięcia i prądu są podawane jako czyste wartości ADC (również w takiej formie są zapisywane na karcie pamięci). Nie stosowałem konwersji wartości pomiarowych, aby zaoszczędzić na czasie podczas zapisu danych na kartę SD. Jedynie napięcie i prąd przedstawiane na wyświetlaczu są na bieżąco przeliczane.

Wykonane pomiary zapisywane są również na karcie SD. Przed wykonywaniem pomiarów możliwa jest zmiana nazwy pliku do jakiego będą zapisywane dane, znak oddzielający kolumny, oraz ilość próbek zapisanych w pliku. Maksymalna ilość plików wynosi 99. Po przerwaniu pomiarów, a następnie rozpoczęciu nowej serii, nowe dane pomiarowe będą zapisywane do kolejnego numeru pliku.

W plikach nie jest zapisywany czas pomiaru. Odstęp pomiędzy pomiarami jest ustawiany wcześniej, więc znane jest próbkowanie – pominąłem ten parametr, aby nie tracić dodatkowe czasu podczas samego zapisu danych na kartę SD.

W projekcie użyłem bibliotek FatFS do obsługi kart SD.

Przed przystąpieniem do pisania programu określiłem kolejność pisania kodu. Plan kodowania wygląda następująco:

  • Obsługa LCD
  • Menu i obsługa przycisków
  • Obsługa czujnika temperatury
  • Komunikacja poprzez RS232
  • Obsługa karty SD
  • Konfiguracja poprzez UI
  • Konfiguracja poprzez komendy AT
  • Obsługa ADC
  • Bootloader

Tak się przedstawia w całości wykonany układ:

Podczas wykonywania projektu przychodziły mi nowe pomysły oraz rozwiązania, które zastosuje w następnej wersji tego urządzenia. Pomimo tych pomysłów i koncepcji które mi przyszły do głowy, postanowiłem dokończyć ten projekt głównie dlatego, aby przypomnieć sobie, oraz podszkolić się z programowania AVR, a także w celu poprawy umiejętności w obróbce obudowy (pomijam oczywiście najważniejszy powód – nie lubię zostawiać niedokończonych projektów).

Zapraszam do oceniania i komentowania!

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *