Narzędzie typu i2c scanner pozwala szybko sprawdzić, które układy naprawdę odpowiadają na magistrali i czy problem leży w okablowaniu, adresie czy zasilaniu. W praktyce to jeden z pierwszych testów, który wykonuję przy czujnikach, wyświetlaczach i ekspanderach portów, bo oszczędza dużo zgadywania. W tym artykule pokazuję, jak działa skanowanie, jak odczytać wynik i jak odsiać typowe błędy, zanim zaczniesz wymieniać podzespoły.
Najważniejsze rzeczy, które warto wiedzieć przed skanem
- I2C używa dwóch linii: SDA i SCL, a każde urządzenie ma własny adres.
- Skaner sprawdza, czy układ odpowiada na adres, zwykle w zakresie 0x03-0x77 dla adresów 7-bitowych.
- Brak wyniku bardzo często oznacza problem z pull-upami, zasilaniem albo wyborem złego busa.
- Na Arduino zwykle używa się
Wire, w MicroPythoniei2c.scan(), a na Linuksiei2cdetect. - Sam skan nie mówi, jaki to układ, tylko czy ktoś odpowiada pod danym adresem.

Jak działa skanowanie magistrali I2C
W I2C wszystko kręci się wokół prostego założenia: jeden kontroler wysyła zapytanie, a urządzenie podrzędne odpowiada, jeśli rozpoznaje swój adres. Skanowanie polega więc na kolejnych próbach na różnych adresach i sprawdzeniu, gdzie pojawia się potwierdzenie odpowiedzi, czyli ACK. To nie jest „czytanie” zawartości czujnika, tylko test obecności urządzenia na magistrali.
Ja traktuję taki skan jako test graniczny. Jeśli wynik jest pusty, nie zaczynam od kodu aplikacji, tylko pytam: czy linie SDA i SCL są poprawnie podciągnięte, czy układ ma zasilanie, czy na pewno patrzę na właściwy bus i czy adres nie został zapisany w innej konwencji. Właśnie dlatego skaner tak dobrze sprawdza się na etapie uruchamiania prototypu.
Warto też pamiętać o dwóch ograniczeniach. Po pierwsze, skan zwykle obejmuje adresy 7-bitowe, a nie wszystkie narzędzia obsługują rzadziej spotykane adresowanie 10-bitowe. Po drugie, wynik mówi tylko tyle, że coś odpowiada pod danym adresem. Nie identyfikuje modelu układu, więc adres 0x76 może należeć do różnych rodzin sensorów i dopiero dokumentacja albo biblioteka powiedzą Ci, co naprawdę siedzi na płytce.
| Co sprawdza skaner | Co zobaczysz | Czego nie ustali sam wynik |
|---|---|---|
| Odpowiedź na adres | Lista adresów, na których ktoś odpowiada | Model układu i jego stan wewnętrzny |
| Obecność urządzenia na busie | Czy magistrala żyje elektrycznie | Czy aplikacja odczytuje poprawne rejestry |
| Konflikt adresów | Czasem brak pełnego obrazu albo niestabilne wyniki | Który z identycznych układów odpowiada |
Gdy rozumiesz już, co naprawdę mierzy skan, sensowniejsze staje się pytanie, jak uruchomić go na różnych platformach i nie wpaść w pułapki konkretnego środowiska.
Jak uruchomić skan na najczęstszych platformach
W praktyce najprościej podejść do tego platformami, a nie teorią. Na Arduino skanuje się magistralę przez bibliotekę Wire, w MicroPythonie wystarczy wywołanie i2c.scan(), a na Raspberry Pi i innych systemach Linux zwykle używa się narzędzia i2cdetect. Różnią się składnią, ale cel jest ten sam: dostać listę adresów, które odpowiedziały.
| Platforma | Najprostszy sposób | Na co zwracam uwagę |
|---|---|---|
| Arduino |
Wire lub Wire1 i pętla po adresach |
Trzeba trafić we właściwy bus; na części płytek nie każdy port nazywa się tak samo |
| MicroPython | i2c.scan() |
Hardware I2C jest szybki, ale ma ograniczenia pinów; SoftI2C daje większą swobodę kosztem wydajności |
| Raspberry Pi / Linux | i2cdetect -y 1 |
To aktywne sondowanie magistrali, więc używam go świadomie i bez zbędnego ryzyka dla wrażliwych układów |
Na Arduino zwykle startuję od domyślnego Wire, ale jeśli płytka ma kilka magistrali, trzeba wskazać tę właściwą, na przykład Wire1. To prosty detal, a potrafi zaoszczędzić pół godziny niepotrzebnego szukania błędu. W MicroPythonie sam zwrot z i2c.scan() jest wygodny, bo od razu dostajesz listę adresów w postaci liczb, bez dodatkowego parsowania. Na Linuksie z kolei przydaje się szybki podgląd tabeli, ale dobrze pamiętać, że samo narzędzie sonduje bus i może być zbyt agresywne, jeśli na magistrali siedzą specyficzne układy.
Warto też patrzeć na fizyczne szczegóły połączenia. MicroPython dokumentuje, że hardware I2C bywa ograniczony przez dostępne piny, a software I2C można uruchomić na dowolnych, ale jest mniej wydajny. To nie jest drobiazg teoretyczny. Na płytkach deweloperskich bardzo często to właśnie wybór pinu decyduje, czy skan w ogóle ruszy.
Skoro samo uruchomienie narzędzia mamy za sobą, trzeba jeszcze poprawnie zinterpretować wynik, bo tutaj najłatwiej o pozornie logiczny, ale błędny wniosek.
Jak czytać wynik i nie pomylić adresów
Najczęstszy błąd, jaki widzę, to mylenie adresowania 7-bitowego z 8-bitowym. Jeśli datasheet pokazuje 0x72, a biblioteka w kodzie oczekuje 0x39, to bardzo często chodzi o to samo urządzenie zapisane w dwóch różnych konwencjach. W praktyce 7-bitowy adres trzeba czasem przesunąć o jeden bit w lewo, dlatego 0x39 i 0x72 mogą opisywać tę samą kość.
| Wynik | Co zwykle oznacza | Jak ja to interpretuję |
|---|---|---|
0x76 lub 0x77
|
Urządzenie odpowiada pod adresem | Sprawdzam, czy kod używa tego samego adresu i tej samej konwencji zapisu |
-- lub pusty wynik |
Brak odpowiedzi na danym adresie | Wracam do zasilania, pull-upów, przewodów i wyboru właściwego busa |
UU na Linuksie |
Adres jest już zajęty przez sterownik | To nie zawsze błąd, ale znak, że układ jest obecny i obsługiwany przez system |
| Wiele adresów dla jednego modułu | Układ może mieć kilka wariantów adresowych | Sprawdzam zworki adresowe albo piny konfiguracji na płytce |
Adresy 0x00-0x07 i 0x78-0x7F są zarezerwowane, więc typowe narzędzia skanują zakres 0x03-0x77. To ważne, bo ktoś patrzący tylko na cyfrę „77” łatwo uzna, że narzędzie działa dziwnie, podczas gdy ono po prostu trzyma się standardowego zakresu. W dodatku niektóre czujniki potrafią mieć więcej niż jeden adres roboczy, więc pojedynczy wynik nie zawsze kończy temat, ale zwykle daje bardzo dobrą wskazówkę.
Jeśli wynik nadal wygląda podejrzanie, problem najczęściej nie leży w samym skanerze, tylko w warstwie elektrycznej albo w źle wybranym busie. I właśnie tam warto teraz zajrzeć.
Dlaczego skan niczego nie znajduje
Gdy skan zwraca pustą listę, zaczynam od najprostszych rzeczy: zasilania, wspólnej masy i rezystorów podciągających. I2C bez poprawnych pull-upów zachowuje się nieprzewidywalnie, a dokumentacja MicroPython przypomina, że typowe wartości mieszczą się w zakresie 1-10 kΩ. Adafruit z kolei zwraca uwagę, że część płytek ma te rezystory już na pokładzie, a część nie, więc nie zakładałbym niczego z góry.
Zasilanie, masa i pull-upy
Brak wspólnej masy to klasyczny powód, dla którego wszystko wygląda poprawnie „na papierze”, a na magistrali nic się nie pojawia. Podobnie jest z poziomami napięć: jeśli układ pracuje na 3,3 V, a linie są podciągnięte do 5 V, trzeba sprawdzić zgodność logiczną całego zestawu. Tu nie ma magii, jest po prostu elektronika.
Adres albo magistrala są inne niż myślisz
Drugie miejsce, w którym łatwo się pomylić, to wybór niewłaściwego busa. Na płytkach z wieloma interfejsami ten sam czujnik może siedzieć na innym porcie niż zakładasz, a narzędzie skanuje wtedy „dobry” protokół, ale zły przewód. Jeśli urządzenie ma zworę adresową, sprawdzam ją od razu, bo dwa identyczne układy z tym samym adresem potrafią skutecznie zamieszać w diagnozie. W takich przypadkach pomaga zmiana adresu albo użycie multipleksera I2C.
Przeczytaj również: Transponder RFID - jak działa i jak uniknąć błędów?
Gdy przewody są długie albo bus jest zbyt szybki
Przy krótkich przewodach test zwykle przechodzi bez problemu, ale przy dłuższych odcinkach pojemność linii zaczyna mieć znaczenie. Wtedy wynik bywa niestabilny: raz urządzenie widać, raz znika, a czasem pojawiają się losowe adresy. Ja wtedy obniżam częstotliwość, skracam połączenia i patrzę, czy problem znika. Jeśli tak, winny jest zwykle tor sygnałowy, nie biblioteka.
| Objaw | Najbardziej prawdopodobna przyczyna | Co sprawdzam najpierw |
|---|---|---|
| Pusta lista adresów | Brak pull-upów, brak zasilania, zły bus | SDA, SCL, GND, napięcie i konfigurację portu |
| Adres pojawia się i znika | Zła jakość połączeń albo zbyt duże obciążenie linii | Długość przewodów, lutowanie, rezystory podciągające |
| Widać adres, ale aplikacja nie działa | Problem z inicjalizacją lub rejestrami urządzenia | Dokumentację czujnika i kolejność wywołań w kodzie |
| Tylko jeden z dwóch identycznych modułów odpowiada | Konflikt adresów | Zwory adresowe albo multiplekser I2C |
Jeśli po takim przeglądzie skan nadal nie daje sensownej odpowiedzi, zazwyczaj zyskuję już bardzo mocne zawężenie problemu. Ostatni krok to krótka lista kontrolna, którą sam stosuję, zanim uznam magistralę za gotową do pracy.
Co sprawdzam, zanim uznam magistralę za gotową
Na koniec zawsze robię szybki przegląd w tej samej kolejności. Najpierw potwierdzam, jaki adres przewiduje dokumentacja układu, potem sprawdzam, czy linie SDA i SCL idą do właściwych pinów, a dopiero później uruchamiam skan. Taka kolejność jest nudna, ale skuteczna, bo nie miesza objawów z przyczynami.
- Sprawdzam, czy urządzenie ma własny, unikalny adres i czy nie koliduje z innym modułem na tej samej magistrali.
- Weryfikuję, czy zasilanie i poziomy logiczne pasują do konkretnego czujnika lub ekspandera.
- Upewniam się, że na busie są pull-upy i że nie zostały pomylone z innymi rezystorami na płytce.
- Uruchamiam skan na właściwej magistrali, a nie tylko na domyślnej, którą łatwo przyjąć „z rozpędu”.
- Porównuję wynik z dokumentacją i sprawdzam, czy problem nie wynika z różnicy między adresem 7-bitowym i 8-bitowym.
Jeśli skan działa, a układ nadal nie odpowiada tak, jak powinien, zwykle problem przenosi się już z warstwy fizycznej do protokołu: złej inicjalizacji, złych rejestrów albo błędnej biblioteki. I to jest dobra wiadomość, bo oznacza, że magistrala żyje, a diagnoza może iść dalej w konkretną stronę.