Komunikacja I2C pomiędzy Raspberry Pi a przetwornikiem analogowo-cyfrowym

Przykład wykorzystania interfejsu I2C do precyzyjnego pomiaru napięcia dokonywanego przez przetwornik MCP3434

O komunikacji I2C pisałem już wcześniej wykorzystując pyMCU. Tym razem Blis przygotował artykuł dotyczący komunikacji I2C w Raspberry Pi. W jego pracy z Raspberry Pi potrzebował bardzo precyzyjny miernik napięcia - przetwornik analogowo-cyfrowy. Taki układ scalony zamienia przyłożone napięcie na cyfrowy sygnał zero-jedynkowy zrozumiały dla komputera. Takie przetworniki mogą być bardzo precyzyjne dzięki czemu znajdują zastosowanie w aparaturze laboratoryjnej i różnych czujnikach.

Do wyboru są różne przetworniki. Możemy wybrać sam układ scalony i wykonać całe okablowanie i dodatkową elektronikę sami, możemy też skorzystać z gotowej płytki z przylutowanym przetwornikiem. Z gotowców do dyspozycji mamy np. płytkę Adafruit, czy płytkę Pridopii mogącej osiągać większą dokładność (16 bitowy przetwornik). W tym artykule Blis skorzysta z samego scalaka MCP3434.

Przetwornik analogowo cyfrowy MCP3434

Standard I2C określa sposób komunikacji między układami elektronicznymi. Do magistrali danych podłączony jest jeden układ sterujący (Master) oraz kilka urządzeń podrzędnych (Slave). Komunikacja odbywa się z wykorzystaniem 4 przewodów. Oprócz przewodu zasilającego (V+) oraz GND wymagana jest linia zegara (SCL) oraz linia przesyłu danych (SDC). W naszym przypadku Raspberry Pi będzie pełnił funkcję nadrzędną, a przetworniki analogowo cyfrowe będą urządzeniami typu Slave.

Układ I2C Master-Slave

Przetwornik analogowo cyfrowy MCP3434 wyposażony jest w 4 różnicowe wejścia analogowe pracujące w zakresie +/- 2.048V. Ponadto posiada wewnętrzny układ generowania napięcia odniesienia oraz programowany wzmacniacz mierzonego sygnału 1x, 2x, 4x lub 8x. Przetwornik można zaprogramować do pracy z różną dokładnością. Osiągnięcie większej rozdzielczość próbkowania musimy opłacić dłuższym czasem przetwarzania.

Podłączając więcej niż jeden układ MCP3424 do magistrali I2C, należy wybrać 1 z 9 dostępnych adresów. Aby tego dokonać należy podłączyć odpowiednie wyprowadzenia układu do V+, GND lub pozostawić niepodłączone (FLOAT). Układy MCP3424 dostępne są w bardzo małej obudowie, dlatego do ich wykorzystanie wymagana jest pewna umiejętność lutowania. Aby ułatwić sobie pracę można zaprojektować i wykonać płytkę drukowaną np. w darmowej wersji programu Eagle. Ponadto należy pamiętać o poziomach napięć akceptowanych zarówno przez port GPIO w Raspberry jak i przez urządzenia podłączane do magistrali I2C. W moim przypadku przetwornik MCP3424 pracuje w zakresie 2,5-5,5 V więc może być zasilany bezpośrednio z pinu GPIO + 3,3V. W związku z faktem, że port GPIO nie posiada żadnych zabezpieczeń należy uważać aby nie podać zbyt dużego napięcia które może skutecznie uszkodzić Raspberry. Na rysunku przedstawiłem widok przetwornika wlutowanego na płytce PCB wraz z dzielnikami umożliwiającymi pomiar napięcia w zwiększonym zakresie.

MCP3434 na własnoręcznie wykonanej płytce drukowanej

Po trudach związanych z budowaniem układu nadchodzi czas na jego testowanie. Jeśli mamy zainstalowanego Raspbiana to komunikacja I2C jest domyślnie wyłączona. Pierwszą rzeczą jest jej włączenie. Edytujemy /etc/modprobe.d/raspi-blacklist.conf i usuwamy wpis dla i2c-bcm270:

blacklist i2c-bcm2708

Kolejno trzeba dodać moduł jądra Linuxa odpowiedzialny za obsługę I2C. Do /etc/modules dodaj i2c-dev. Aby ułatwić sobie pracę z magistralą I2C możemy zainstalować pakiet i2c-tools oraz nadać uprawnienia użytkownikowi pi zezwalające na dostęp do I2C:

sudo apt-get install i2c-tools 
sudo adduser pi i2c
Na koniec pozostaje ponowne uruchomienie komputera. Po poprawnym zainstalowaniu pakietów i skonfigurowaniu systemu możemy spróbować wyszukać dostępne urządzenia poleceniem. W pozytywnym przypadku na ekranie naszego komputera zobaczymy adresy pod jakimi zostały one wykryte.
 pi@raspberrypi ~ $ i2cdetect -y 0 # 0 w przypadku Raspberry Pi Rev 1, 1 dla Rev 2. 
   0 1 2 3 4 5 6 7 8 9 a b c d e f 
00: – – – – – – – – – – – – – - - -
10: – – – – – – – – – – – – – – – – 
20: – – – – – – – – – – – – – – – – 
30: – – – – – – – – – – – – – – – – 
40: – – – – – – – – – – – – – – – – 
50: – – – – – – – – – – – – – – – – 
60: – – – – – – – – 68 – 6a – – – – 
70: – – – – – – – – - - - - - - - -
Wymiana danych z urządzeniami wymaga znajomości tych adresów. W prezentowanym artykule do komunikacji z przetwornikami wykorzystałem moduł quick2wire, który jest kompatybilny tylko z Pythonem 3. Dlatego też pozostałe czynności będą wykonywane z użyciem tej wersji Pythona.
import quick2wire.i2c as i2c

i2c_bus=i2c.I2CMaster(0) #otwarcie komunikacji

bajt_danych=0b01111000 #dane wysyłane do przetwornika
address=0x68 #adres pierwszego przetwornika

i2c_bus.transaction(i2c.writing_bytes(address,bajt_danych)) #wysłanie danych do przetwornika
p,d,c = i2c_bus.transaction(i2c.reading(address,3))[0] 
#odczytanie 3 bajtów danych p,d - pierwszy i drugi bit danych, c - bajt konfiguracyjny
Dokładny opis danych wysyłanych do przetwornika i odbieranych od niego znajduje się w specyfikacji dostarczonej przez producenta. W naszym przypadku wystarczy jeśli poznamy „jak zbudować” komunikat aby skonfigurować przetwornik. Komunikat wysyłany do przetwornika składa się z 8 bitów danych. Znaczenie tych bitów przedstawiono poniżej.
  • 7 - gotowość przetwornika, wpisanie 1 oznacza rozpoczęcie nowej konwersji, 0 - bez efektu
  • 6 i 5 - wybór kanału analogowego
  • 4 - tryb pracy, 1 - ciągły (domyślnie) / 0 - jedna konwersja
  • 3 i 2 -wybór szybkości próbkowania, a co za tym idzie rozdzielczości
  • 1 i 0 wybór wielkości wzmocnienia sygnału
Aby przeanalizować użyty komunikat wygodnie jest zgrupować bity w następujący sposób 0 11 1 10 00:
  • 0 - jeśli praca w trybie ciągłym nie wymaga wyzwalania nowej konwersji
  • 11 - wybieramy 4 kanał analogowy
  • 1 - praca w trybie ciągłym
  • 10 - wybór pracy z rozdzielczością 16 bitów (15 SPS)
  • 00 - wzmocnienie 1x
Odczytywanie danych uzależnione jest od dokładności konwersji. Jeśli pracujemy z 12, 14 lub 16 bitową rozdzielczością to do przesłania wyników wystarczą 2 bajty. Natomiast dla rozdzielczości 18 bit wymagane są 3 bajty danych. Odpowiedź przetwornika zawsze zaczyna się od 2 lub 3 bajtów danych po których odbierany jest bajt konfiguracyjny. W naszym przypadku dla 16 bitów rozdzielczości odczytujemy dwa bajty danych.
p,d,c = i2c_bus.transaction(i2c.reading(address,3))[0]
#p - pierwszy bajt danych (jako MSB zawiera znak)
#d - drugi bajt danych 
#c - bajt konfiguracyjny
wzmocnienie=1 #zaprogramowane wzmocnienie sygnału
mnoznik=2.048/2**15/wzmocnienie # 0 - 2.048V - 15 bitów bez znaku 
wynik_surowy=p<<3+d

if (h>>7)&1: #jeśli MSB==0 to wartość ujemna, jeśli MSB==1 to dodatnia.
   wynik=-wynik_surowy*mnoznik
else:
   wynik=wynik_surowy*mnoznik
print ("Napięcie wynosi %s [V]" % wynik)

W przedstawionym artykule zaprezentowałem sposób w jaki można połączyć minikomputer Raspberry Pi z przetwornikiem analogowo cyfrowym wykorzystując magistralę I2C. Użycie układu MCP3424 w prosty sposób pozwala zwiększyć funkcjonalność minikomputera o bardzo przydatne wejścia analogowe. Ponadto magistrala znajduje szerokie zastosowanie do komunikacji z innymi układami np. akcelerometrami, sterownikami wyświetlaczy LCD czy płytkami typu Arduino.

Autor: Blis

blog comments powered by Disqus

Kategorie

Strony