Kurs Arduino #20: I2C w zastosowaniach

Kurs Arduino #20: I2C w zastosowaniach

4. Przykładowy program #1: Skaner adresów I2C

Najprostszym program, który pomoże nam na samym początku jest skaner adresów I2C. Pozwala on na zwrócenie – jak sama nazwa wskazuje- głównego adresu urządzenia. Z pomocą tego prostego programu jesteśmy w stanie zweryfikować poprawność podłączenia układu, jak i sam fakt czy urządzenie działa.

i2c_ardu

Program jest stosunkowo prosty, ponieważ wszystko „kręci” się wokół zwracanych wartości przez funkcję endTransmission().  Na samym początku importujemy bibliotekę odpowiedzialną za I2C, oraz definiujemy trzy zmienne:

  • blad– do tej zmienne będą zapisywane zwracane wartości z funkcji endTransmission()
  • adres– tutaj będziemy zapisywać aktualnie badany adres
  • urzadzenia– ta zmienna będzie zawierać ilość znalezionych urządzeń

Następnie w funkcji początkowej uruchamiamy magistralę I2C oraz UART. Teraz w pętli głównej programu ustalmy początkową wartość urządzeń, czyli 0, a następnie przy pomocy funkcji for badamy czy jakieś urządzenie znajduje się pod adresem z zakresu 1 do 127 (bo 7bit, czyli 7 do drugiej potęgi daje nam 127). W tym celu po I2C wysyłana jest liczba o 1 większa od poprzedniej, zawartej w zmiennej adres. W międzyczasie przypisujemy do zmiennej blad funkcję endTransmission(), do której będą zapisywane zwracane wartości.

Następnie przy pomocy funkcji warunkowej switch…case, sprawdzamy jaka wartość została przypisana zmiennej blad.

Opis funkcji wielokrotnego wyboru switch...case
W tym momencie chciałbym opisać o co dokładnie chodzi z tą funkcją, żeby program został dobrze zrozumiany. Można powiedzieć, że funkcja warunkowa wielokrotnego wyboru switch…case jest bardzo podobna do funkcji warunkowej if, ale jednak jest nieco „słabsza”, ponieważ ona jest wykonywana tylko dla jednego, zdefiniowanego warunku. Ale ma też swoją zaletę jaką jest przejrzystość programu.

Składnia tej funkcji:

Jak widać nie jest ona trudna, a wręcz bardzo łatwa. Tylko jak wspomniałem wcześniej, może ona obsługiwać tylko jeden warunek zawarty w case, gdzie w funkcji warunkowej if możemy zawrzeć bardzo dużo informacji. No ale żeby te poradniki nie były  „takie same” to trzeba wprowadzać jakieś urozmaicenia :)

Ten program może być równie dobrze oparty o funkcje warunkowe if

Jeżeli wartość naszej zmiennej wynosi 0 to znaczy, że urządzenie slave zwróciło bit Ack, w związku z czym wystawi o nim informację „* Znaleziono urzadzenie o adresie 0x”, ale jeżeli adres jest mniejszy od 16 to wstawi przed ten adres jeszcze „0”, a na końcu sam adres, w postaci heksadecymalnej oraz inkrementuje wartość zmiennej urzadzania o 1. Natomiast jeżeli funkcja blad zwróci wartość 4 to znaczy że wystąpił jakiś błąd przy tym adresie, tzn. jakieś urządzenie może znajduje, ale jest problem z połączeniem, transmisją itp.

Na samym końcu programu -poza funkcją for- sprawdzane jest czy jakieś urządzenie zostało w ogóle wykryte. Jeżeli wartość zmiennej urzadzenia jest równa 0 to wtedy program wystawia informację na monitor portu szeregowego, że nie znaleziono żadnych urządzeń w tym zakresie adresów.

 

5. Przykładowy program #2: Obsługa układu MPU-6050 przy pomocy I2C

Jako podsumowanie tej części poradnika, stworzymy program obsługujący układ MPU-6050, przy pomocy I2C korzystając wyłącznie z rejestrów, a nie z gotowych bibliotek.

schemat-20-2

 

Program:

Na samym początku definiujemy adresy urządzenia oraz rejestru wewnętrznego, następnie tworzymy 16bitowe zmienne typu int, którym w dalszej części programu przypiszemy odczyty z żyroskopu oraz temperatury.

W pętli startowej programu uruchamiamy I2C oraz UART. Następnie rozpoczynamy transmisję adresu, oraz dwóch specjalnych adresów uruchamiających moduł

Ważnym, jest aby dokładnie zapoznać się z notą katalogową układu !

Na samym końcu zamykamy transmisję. Teraz nasz moduł jest uruchomiony i gotowy do działania, dzięki czemu możemy przejść do pętli głównej programu.

W pętli głównej, znowu odwołujemy się do adresu głównego naszego układu, a następnie wysyłamy adres rejestru wewnętrznego odpowiedzialnego za temperaturę i zamykamy transmisję. Następnie informujemy Arduino, że ma się spodziewać 8 bajtów danych.

Bajty:

  • 1-2 bajt wysoki i niski odczytanej temperatury
  • 3-4 bajt wysoki i niski odczytanej wartości żyroskopu dla osi X
  • 5-6 bajt wysoki i niski odczytanej wartości żyroskopu dla osi Y
  • 7-8 bajt wysoki i niski odczytanej wartości żyroskopu dla osi Z

 

Następnie wykonamy dwa działania:

  1. przesunięcia bitowego w lewo
  2. dodania bajtów

Żeby było łatwiej wytłumaczyć to stworzyliśmy taką animację:

temp

 

W pierwszej kolejności pobieramy pierwszy bajt z buforu, jakim jest w tym przypadku Temp_Out_H i „umieszczamy” go w zmiennej. Następnie „przesuwamy” go w lewo o 8 bitów, oraz pobieramy następny bajt z buforu (Temp_Out_L) i umieszczamy go w zmiennej. W taki sposób otrzymujemy wartość naszej temperatury.

Kiedy pobierzemy bajt z buforu to jest on usuwany, przez co nie ma problemów z odczytywaniem bajtów w poprawnej kolejności. Gdy mamy tą informację to możemy pobierać kolejny bajty z buforu i formować je w odpowiednie informacje. W naszym przypadku są to wartości żyroskopu dla osi X,Y,Z. Pamiętaj, że to co prezentuję będzie działać tylko i wyłącznie dla tego modułu. Sposób kontroli bitów jest przystosowany dla tego układu, ponieważ jak zerkniemy w notę katalogową tego układu:

register_mpa

to widzimy, że adresy odpowiedzialne za temperaturę i żyroskop X,Y,Z są ułożone po kolei. Gdybyś np. chciał odczytać wartości akcelerometru i żyroskopu, pomijając za razem temperaturę to najpierw byś musiał odwołać się adresu 0x3B i odczytać 6 bajtów, a następnie do adresu 0x43 i oczytać następne 6 bajtów.

Ale wracajmy do programu. Gdy już przebrnęliśmy przez odebranie danych z układu to teraz możemy, je wyświetlić na monitorze portu szeregowego. W przypadku temperatury to musimy jeszcze uformować odpowiednio otrzymane dane według wzoru z noty katalogowej.

W ten sposób dobrnęliśmy do końca naszego przykładu :)

Po wgraniu programu powinniśmy otrzymać taki efekt:

 

 

6. Podsumowanie

Po tej części kursu Arduino powinieneś wiedzieć:

  • Co to jest I2C
  • Na jakiej zasadzie działa
  • Podstawowe funkcje oraz ich implementacja w prostych programach

Staraliśmy się przedstawić zagadnienia w sposób przejrzysty i zrozumiały i mamy nadzieję, że od teraz obsługa magistrali I2C nie powinna sprawiać Ci większego problemu :)

Materiały do tej części kursu:

Download-icon

 

 

 


Jeżeli chcesz być informowany na bieżąco o nowych częściach kursu to kliknij ?Lubię to!? bądź subskrybuj naszą stronę, aby otrzymywać na adres e-mail nowości ze strony. Jeżeli masz jakieś pytania to śmiało zadawaj je na forum ; )