[PROJEKT] KAmodRPI 10b ADC/DAC – ekspander z przetwornikiem ADC dla komputerów Raspberry Pi – Przykład w C++
Moduł KAmodRPI 10b ADC/DAC to ekspander rozszerzający możliwości komputera Raspberry PI o przetwarzanie sygnałów cyfrowych na postać analogową oraz dyskretyzację sygnału analogowego. Ekspander został oparty na dwóch niezależnych przetwornikach A/C i C/A. W module zastosowano 10 bitowy przetwornik ADC MCP3021 i 10-bitowy przetwornik DAC MCP4716 firmy Microchip. Moduł jest kompatybilny z komputerami Raspberry Pi 3, Raspberry Pi 2, Raspberry Pi+ i Raspberry Pi. Komunikacja z przetwornikami odbywa się za pośrednictwem magistrali I2C. Przetwornik analogowo-cyfrowy pozwala na konwersję z częstotliwością do 22,3 kHz. Zakres napięcia wejściowego to 0…+3,3V/0…+5V/0…+10V (w zależności od wybranego współczynnika podziału). Przetwornik zawiera wbudowany układ próbkująco-pamiętający (Sample & Hold). W tym przykładzie pokażę jak w prosty sposób można zrealizować pomiar napięcia wejściowego, z poziomu programu w C++, oraz z wykorzystaniem modułu KAmodRPI 10b ADC/DAC.
Program został napisany i skompilowany na komputerze Raspberry PI Model B z poziomu systemu Raspbian Jessie (wersja z: 27.05.2016).
Pierwszą czynnością po uruchomieniu systemu będzie utworzenie katalogu, gdzie będziemy przechowywali nasz program wraz z skompilowaną wersją. W moim przypadku jest to katalog „KAmodRPI_10b_ADC_DAC” w folderze domowym użytkownika.
Kolejnym krokiem jest utworzenie pliku *.cpp, z przykładowym programem, w nowo utworzonym katalogu. Kod programu przedstawiam poniżej.
#include <iostream> #include <errno.h> #include <wiringPiI2C.h> #include <unistd.h> #include <iomanip> #include <stdint.h> #include <stdio.h> using namespace std; int main() { int fd; uint8_t tmp; uint16_t measureValueRAW = 0; double measureValue = 0.0; fd = wiringPiI2CSetup(0x4D); cout << "Init result: " << fd << endl; while(1) { measureValueRAW = wiringPiI2CReadReg16(fd, 0x4B); printf("%.4X >> RAW\n", measureValueRAW); tmp = measureValueRAW; measureValueRAW = (measureValueRAW >> 8) | (tmp << 8); measureValueRAW = (measureValueRAW >> 2); measureValueRAW &= 0x3FF; measureValue = (measureValueRAW / 1024.0) * 3.3; printf("%.2X >> %Lf \n", measureValueRAW, measureValue); usleep(1000000); } return 0; }
W powyższym programie korzystamy z biblioteki wiringPiI2C.h. Umożliwia ona w prosty sposób realizować komunikację z układem za pośrednictwem interfejsu I2C.
W programie tworzymy cztery zmienne:
- fd – zmienna przechowuje status konfiguracji i inicjalizacji połączenia z wykorzystaniem I2C;
- tmp – zmienna tymczasowa do przechowywania 8 starszych bitów wyniku pomiaru;
- measureValueRaw – zmienna przechowuje zawartość dwóch rejestrów składających się na całkowity pomiar
- measureValue – zmienna przechowująca ostateczny obliczony wynik pomiaru
funkcja wiringPiI2CSetup() pozwala na konfigurację i ustanowienie połączenia pomiędzy procesorem a układem ADC z ekspandera. Adres układu zapisany w postaci szesnastkowej to 0x4D.
Główna pętla programu rozpoczyna się od odczytania dwóch rejestrów układu zawierających młodszy i starszy bajt wyniku pomiaru. Odczyt odbywa się po uprzednim wysłaniu do układu informacji o konieczności wykonania pomiaru napięcia na wejściu. W tym celu stosujemy funkcję wiringPiI2CReadReg16().
Kolejna linijka odpowiada za wyświetlenie odczytanej wartości w konsoli.
Do poprawnego przeliczenia surowej wartości konieczne jest zamienienie miejscami dwóch bajtów. Pobranie wartości za pomocą wyżej wymienionej funkcji powoduje to, że 8 starszych bitów to tak naprawdę 8 bitów mniej znaczących całego pomiaru. Zamiany dokonujemy z wykorzystaniem zmiennej pomocniczej tmp, do której przypisujemy starszy bajt zmiennej measureValueRAW. Kolejnym krokiem jest przesunięcie bitowe o 8 miejsc w prawo bitów zmiennej measureValueRAW oraz dopisanie do zmiennej na właściwym miejscu, zawartości zmiennej tmp.
Przetwornik ADC zastosowany w KAmodRPI 10b ADC/DAC ma rozdzielczość 10 bitów. Oznacza to że wynik pomiaru napięcia wejściowego zawarty jest jedynie w 10 bitach, a nie w pełnych 16. Wynik zawarty jest między 2 a 11 bitem zmiennej measureValueRAW. Aby poprawnie odczytać interesującą nas wartość należy zawartość zmiennej przesunąć bitowo o dwa miejsca w prawo, a następnie dokonać operacji koniunkcji bitowej lub bardziej znanej pod nazwą BIT-AND z maską 0x3FF. Pozwoli to na wyłuskanie ostatecznego wyniku.
Ostatnią czynnością jest przeliczenie otrzymanej wartości mierzonej wielkości na wartość napięcia. W tym celu dzielimy wartość zmiennej measureValueRAW na 1024 i wynik dzielenia mnożymy przez wartość napięcia odniesienia. W naszym przypadku jest to 3,3V.
Obliczoną wartość przechowujemy w ostatniej zmiennej measureValue oraz na koniec wyświetlamy ją na ekranie w konsoli.
Program kompilujemy za pomocą kompilatora g++, z poziomu terminala systemu operacyjnego. Kompilację przeprowadzamy wykonując polecenie:
g++ example_kamodrpi_10b_ADC_DAC.cpp -l wiringPi -o example_kamodrpi_10b_ADC_DAC
Polecenie wykonujemy będąc w katalogu, w którym znajduje się plik *.cpp z naszym programem.
Program uruchamiamy z poziomu terminala poleceniem:
sudo ./example_kamodrpi_10b_ADC_DAC
Wynik działania programu prezentuje poniższy zrzut ekranu gdzie widać jak zmieniała się wartość pomiaru wraz z regulacją napięcia na zasilaczu laboratoryjnym.
Ekspander wyposażony jest w zworki umożliwiające zmianę progu wartości napięcia mierzonego. Realizowane jest to przez użycie przy pomocy zworki jednego z dwóch dzielników napięcia. W celu skorzystania z tej funkcjonalności należy w programie uwzględnić odpowiedni mnożnik dla ostatecznego wyniku pomiaru.