Ein kostengünstiger und mobiler I2C Scanner

Hallo und willkommen zu diesem Blog, in dem ich Ihnen einen mobilen I2C-Scanner vorstellen möchte. Auslöser war, dass ich für ein anderes Projekt dringend eine Bestimmung der I2C-Adresse eines Bausteines brauchte, jedoch nicht so einfach ein Datenblatt für diesen Baustein im Internet fand. 

Auf der folgenden Suche nach einem kostengünstigen Open Source I2C-Scanner waren die selbst auferlegten Vorgaben für diesen Scanner die folgenden:

  • Einfachheit: Kein Anschluss an einen PC benötigt. Für den Betrieb oder das Ablesen der I2C-Adressen ist kein PC nötig.
  • Minimalistisch: So kleine Bauteile wie möglich, um alles in einem kleinen Gehäuse unter zu bringen.
  • Kosteneffizienz: Keine unnötig teure Hardware.
  • Hardwareeffizienz: Keine "brachliegenden" Ressourcen der Hardware wie WLAN, Bluetooth etc.
  • Sparsam: Betrieb mit einem Akku-pack möglich.

Ein System, das alle die o.g. Kriterien für einen I2C-Scanner erfüllt, konnte ich jedoch nicht finden. Also hieß es: Selbst machen, und so ist dieser Blog entstanden.

Kommen wir zunächst zu einigen Überlegungen:

Das erste Ziel, ohne PC auszukommen, kann nur mit einem eigenen Display erreicht werden, auf dem die Daten direkt angezeigt werden. Durch die Vorgabe eines minimalistischen Designs, auf dem nur so wenig Platz wie möglich zur Verfügung steht, blieb nach Sondierung der Displays auf der AZ-Delivery Seite nur das OLED 128x64 Pixel in der engeren Auswahl. Dieses Display benötigt aber seinerseits schon einen I2C-Bus um zu funktionieren. Was nun?

Micro Controller mit 2 parallelen I2C-Bussen "on Board", wie sie die Boards mit dem ESP32 haben, fielen aber aufgrund der überzogenen Hardware (Bluetooth, WLAN, großer Speicher) für dieses Projekt durch. Ebenso aus gleichem Grunde der ESP8266 (Kosteneffizienz und Hardwareeffizienz). Blieb also nur der Arduino Nano für das Projekt übrig, den wir mit einem kleinen "Trick" auch nutzen können: Wir emulieren per Software einen weiteren I2C Port, der für das Scannen benutzt wird, im folgenden Software-I2C genannt. Denn der Hardware-I2C-Bus wird für die Ansteuerung des OLED-Displays genutzt.

Glücklicherweise gibt es bereits eine fertige Bibliothek, um einen I2C-Bus in Software zu emulieren. Diese heißt „Soft Wire“ und ist von Steve Marple.

Die Bibliothek kann von hier heruntergeladen werden:

https://github.com/stevemarple/SoftWire

Weitere Informationen zu dieser Bibliothek finden sich auch auf der Seite https://www.arduinolibraries.info/libraries/soft-wire  

Benötigte Hardware 

Bevor also mit unserem heutigen Projekt begonnen werden kann, müssen zuerst die Bibliotheken (siehe Sketch) in bekannter Weise installiert werden. Für den I2C-Scanner aus dem heutigen Blog benötigen Sie darüber hinaus noch folgende Teile aus dem Shop:

Anzahl Bauteil Anmerkung
1 Arduino Nano
1 0,91 Zoll OLED I2C Display 128 x 32 Pixel
2 4,7 KOhm Widerstände


Danach kann die Hardware gemäß folgender Fritzing-Zeichnung aufgebaut werden:


Bitte beachten Sie die 4,7 KOhm Pull-up-Widerstände für die Software I2C Schnittstelle. Diese werden für die Funktion benötigt. Aufgebaut auf einem Breadboard und in Betrieb sieht das Ganze nun so aus: 

 


Nach dem Aufbau kann folgender Code hochgeladen werden:

 // Tobias Kuch 2020 GPL 3.0 tobias.kuch@googlemail.com
// https://github.com/kuchto

/*
Dieser kurze Sketch durchsucht den I2C-Bus nach Geräten.
Wenn ein Gerät gefunden wird, wird es auf einem OLED Display
mit seiner Adresse in den Zahlensystemen Binär, Hexadezimal und Dezimal angezeigt.
*/

#include <Wire.h>
#include <SoftWire.h>
#include <AsyncDelay.h>
#include "SSD1306Ascii.h"
#include "SSD1306AsciiWire.h"

#define oLed_I2C_ADDRESS 0x3C
#define SoftSDA 4
#define SoftSCL 5

const uint8_t firstAddr = 1;
const uint8_t lastAddr = 0x7F;

SSD1306AsciiWire oled;
SoftWire sw(SoftSDA, SoftSCL);

//------------------------------------------------------------------------------

uint8_t I2C_Device_found_at_Address= 0;
uint16_t Round = 0;
bool AlreadyScan = false;

void setup()
{
Wire.begin();
Wire.setClock(400000L);
sw.setTimeout_ms(200); // Set how long we are willing to wait for a device to respond
oled.begin(&Adafruit128x64, oLed_I2C_ADDRESS); // Set display size
oled.setFont(Adafruit5x7);
oled.clear();
oled.set1X();
oled.clear();
oled.setCursor(0, 0);
oled.print("Scanning I2C Bus...");
oled.setCursor(0, 1);
oled.print("Initital Scan.");
}
//------------------------------------------------------------------------------

bool scanI2C()
{
bool detected=false;
for (uint8_t addr = firstAddr; addr <= lastAddr; addr++)
{
delayMicroseconds(50);
uint8_t startResult = sw.llStart((addr << 1) + 1); // Signal a read
sw.stop();
if ((startResult==0) & (I2C_Device_found_at_Address != addr)) // New I2C Device found
{
Round = 0;
detected=true;
I2C_Device_found_at_Address = addr;
AlreadyScan = false;
oled.set1X();
oled.setCursor(0,0);
// oled.clear();
oled.print("I2C Device found at: ");
oled.setCursor(0,1);
oled.set2X();
oled.setCursor(0,1);
oled.print("-");
oled.print(addr,BIN);
oled.print("-b ");
oled.set1X();
oled.setCursor(0,3);
oled.print("0x");
if(addr<16) oled.print("0");
oled.print(addr,HEX);
oled.print(" HEX -- ");
if(addr<10) oled.print("0");
oled.print(addr,DEC);
oled.print(" DEC ");
delay(100);
break;
} // Device Found END
} // Scan Round END

if (!detected)
{
I2C_Device_found_at_Address = 0;
Round++;
}
return detected;
} // Function END

void loop()
{
if ((!scanI2C()) && (Round > 2))
{
if (!AlreadyScan)
{
AlreadyScan = true;
oled.clear();
oled.setCursor(0, 0);
oled.print("Scanning I2C Bus...");
}
Round = 0;
I2C_Device_found_at_Address = 0;
}
delay(200);
}


Sollten Sie Probleme beim Hochladen des Sketches haben, kontrollieren Sie bitte im Menüpunkt Tools die Einstellungen für Board, Prozessor und (USB-) Port. Ggf. müssen Sie den Prozessor in ATmega328P (Old Bootloader) ändern.


Sobald nun ein I2C adressierbarer und funktionsfähiger Baustein an den Port 5 (SCL) und Port 4 (SDA) angeschlossen wird, wird dessen Adresse umgehend im OLED- Display in den verschiedenen Zahlensystemen Binär, Dezimal und Hexadezimal angezeigt. Ich wünsche Ihnen viel Spaß beim Bauen und beim Verwenden des I2C-Scanners. Alle Projekte und Informationen meiner Blogs finden Sie auch unter https://github.com/kuchto.  

MuestraPara arduinoProyectos para principiantes

15 comentarios

H. Eichhorn

H. Eichhorn

@W.Parschfeld
Das muss nicht falsch sein und auch nicht unbedingt ein Fehler in der Library
sein. Ich habe mein Projekt mit einem leeren ATmega168 fertig. Das Display
verwendet die u8g2 lib und den dort implementierten SW I2C. Der HW I2C
wird für die zu erkennenden Adressen genutzt.
Beim DS3231 werden auch zwei Adressen erkannt: 0×57 und 0×68. Und das ist
richtig! Der EEprom wird über eine zweite Adresse angesprochen. Deshalb hat das
Modul zwei Adressen.

H. Eichhorn

H. Eichhorn

@Harald
Ich kann Dir leider nicht sagen ob dieses Shield damit funktioniert. Allerdings
vermute ich, dass es gehen sollte. Vermutlich werden die Anzeigen dort nicht
per I2C gesteuert. Dann könnte man den HW I2C für den Scan verwenden.
Du musst eben schauen wie die Anzeige angesteuert wird.

Andreas

Andreas

Ein schönes Beispiel, das die Verwendung von SoftWire und das Ansprechen des OLED-Displays demonstriert.
Um die Anforderungen zu erfüllen, würde ich allerdings eher ein nur geringfügig teureres TFT-Display mit einer Auflösung von 128×160 verwenden, das die noch freie SPI-Schnittstelle verwendet.
Oder vielleicht noch minimalistischer, jedoch mit WLAN ein ESP8266-01 Modul: Da kann der I2C-Bus auf die Tx und Rx-Leitungen gelegt werden und im SoftAP-Modus kann man die Messergebnisse für ein beliebiges Smartphone bereitstellen und spart damit auch noch das Display-Modul ein.11

Harald

Harald

Ich möchte den Multi-Function-Shield (MFS)
http://cool-web.de/arduino/multi-function-shield-einrichtung.htm
mit einem Uno benutzen als I2C-Scanner; der MFS kostet ungefähr €4. Kennst du den? Ob es damit funktioniert? Mir genügt eine Anzeige der HEX-Adresse auf den Siebensegmentanzeigen.
Gruß Harald

H. Eichhorn

H. Eichhorn

@Michael
Es sieht in der Tat komisch aus mit den 6 Stellen der binären Darstellung.
Führende 0er sind zwar nutzlos, machen die Darstellung aber optisch runder.
Wobei man doch meist eh die Hex Version für seinen Code verwendet. Aus
meiner Sicht ist das deshalb die wichtigste Info.
Natürlich kann man die Darstellung anpassen wenn man dies möchte. Allerdings
wird dies von print mit BIN nicht unterstützt. da muss man selbst tätig werden.

W.Parschfeld

W.Parschfeld

… übrigens mit dem Beispiel “ListDevices” aus der SoftWir-Library tritt der gleich Effekt auf! —> also scheint die Ursache dort zu liegen …

W.Parschfeld

W.Parschfeld

Leiderergab der Nachbau folgenden Fehler: Bei Anschluss von EEPROMS 24(L) C256 müsst die Adresse 0×50... 0×57 RICHTIG sein. Leider findet das Programm auch zusätzlich die Adresse 0×18x (0×18...0×1F) – FALSCH. Bei mehreren Modulen mit unterschiedlichen Adressen werden die 0×5?-Adfessen gar nicht mehr angeziegt. Bei Anschluss von RTC-Modulen gleiches Verhalten: zwei Adressen … :-(

Michael

Michael

Es verwirrt etwas, dass im Beispielbild der OLED-Ausgabe nur 6 Bits binär angezeigt werden. Evtl. könnte man führende Nullen mit anzeigen?

R. Edmaier

R. Edmaier

Funktioniert prima!
In Code Zeile 36 muss es &Adafruit128x32 heißen, statt &Adafruit128x64, dann erfolgt auch die Darstellung auf dem Display korrekt und nicht vertikal gestaucht.

H. Eichhorn

H. Eichhorn

Sehr nettes Projekt, allerdings aus meiner Sicht noch zu “dick” und die Problematik der
3,3V I2C Komponenten wird nicht berücksichtigt. Nicht alle Module oder Komponenten
sind 5V tolerant.
Das Projekt hat mich nun zum Aufbau einer speziellen Platinemit einem nackten Atmega168 inspiriert. Die Schaltung wird mit 5V per USB versorgt. Über einen
Jumper kann auf 3,3V gewechselt werden (Spannungsregler). Der Atmega und das Display
kommen mit beidem zurecht. Das erspart den Levelshifter und erlaubt beide Varianten.

Tobias

Tobias

Hallo Herr Parschfeld,

Das gezeigte Projekt ist für 5 Volt Logik Bausteine, NICHT für 3,3V-I²C-Bausteine.
Viele Grüße

Tobias

Tobias

Hallo zusammen,
Genau So wie derri es beschrieben hat ist es auch. (Vielen Dank für deine perfekte Erklärung) Das EEPROM 25CL256 im Fritzing dient als Testobjekt, im Foto ist ein I2C Adapter für LCD-Textdisplays das Testobjekt. Für den Scanner selbst werden nur die in der Stückliste aufgeführten Bauteile benötigt. (2 Wiederstände)

derri

derri

@Pit Gutzmann
Die offensichtlichen Unterschiede zwischen Foto und Zeichnung haben mich auch irritiert. Nach genauerer Betrachtung ist die Sache klarer:
Das EEPROM 25CL256 im Fritzing dient als Testobjekt, genau im Foto wie das anonyme Bauteil, das m.E. ein I2C Adapter für LCD-Textdisplays ist.
Das eigentliche Projekt benötigt nur die zwei Widerstände der Stückliste. Der dritte Widerstand im Fritzing dient dazu, den Schreibschutz-Eingang des EEPROM (Pin WP im Datenblatt) an VCC zu legen und damit ein ungewolltes Beschreiben des IC’s zu verhindern.
Gespeist werden die Testobjekte des Testaufbaus, wie Du richtig beobachtet hast, indirekt über die Pins 27 (5 V) und 29 (GND bzw. Masse) des Arduino Nano aus dem USB-Anschluss. Beim fertigen Gerät wird an den Pins 27 (+) und 29 (-) dann eventuell der Akku angeschlossen. Es gibt aber auch spezielle Lademodule für Lipo-Akkus mit 3,7 V. welche stabilisierte 5 V an einem USB-Stecker für die Verbraucher zur Verfügung stellen. Siehe zum Beispiel https://www.az-delivery.de/products/tp5400-usb-powerbank-modul?pos=5&_sid=65dd8aa57&ss=r . Damit kann dann die Speisung des Arduino wieder per USB- Schnittstelle erfolgen.

Pit Gutzmann

Pit Gutzmann

Sicher eine tolle Sache, so ein mobiler einfacher I2C-Scanner. Was mir bei diesen BLOGs immer wieder Sorgen bereitet, sind die Ungereimtheiten zwischen Einkaufsliste, Frizzing-Bild und Foto. In der Liste stehen 2 Widerstände, im Frizzing sind es 3. Im Frizzing taucht ein seltsamer Baustein namens 241 C 256 auf, der nirgends sonst erwähnt wird, und im Foto gibt es ein (wahrscheinlich zu testendes???) I2C-Bauteil, was wiederum ohne den im Frizzing dargestellten 3. Widerstand angeschlossen wurde. Außerdem sollte das Gerät doch eigentlich mit Akku betrieben werden, während hier ein USB-Kabel benutzt wurde? Für mich als relativen Anfänger sind solche Diskrepanzen sehr verwirrend.

W. Parschfeld

W. Parschfeld

Hi, interessantes Projekt – beschäftige mich gerade auch mit der I²C-Problematik. Allerding fehlt mir im vorgestellten Ansatz die Differenzierung der 5V- und 3,3V-I²C-Bausteine und der Einsatz eines Level-Shifters (habe damit gerade einen D1 mini per I²C mit einem Arduino Mega gekoppelt).

Deja un comentario

Todos los comentarios son moderados antes de ser publicados

Artículos de blog

  1. Ahora instalamos el esp32 a través de la administración.
  2. Lüftersteuerung Raspberry Pi
  3. Arduino IDE - Programmieren für Einsteiger - Teil 1
  4. ESP32 - das Multitalent
  5. Transporte Aéreo - programación de ESP mediante redes locales inalámbricas