There are several good I2C scanners available for the Arduino.
However I missed the feature to scan if a device is reachable at different speeds.
So time to roll my own ...
(I2C EEPROM 24LC256 attached to I2C bus)
when
#define PRINTALL false
the output looks like
Multispeed - I2C Scanner - V0.1 -
ADDR ADDR 10 50 100 200 400 [KHz]
-----------------------------------------------------------------------
80 0x50 V V V V V
done...
when
#define PRINTALL true
the output looks like
Multispeed - I2C Scanner - V0.1 -
ADDR ADDR 10 50 100 200 400 [KHz]
-----------------------------------------------------------------------
0 0x0 . . . . .
1 0x1 . . . . .
2 0x2 . . . . .
3 0x3 . . . . .
4 0x4 . . . . .
5 0x5 . . . . .
6 0x6 . . . . .
7 0x7 . . . . .
8 0x8 . . . . .
9 0x9 . . . . .
10 0xA . . . . .
11 0xB . . . . .
12 0xC . . . . .
13 0xD . . . . .
14 0xE . . . . .
15 0xF . . . . .
16 0x10 . . . . .
17 0x11 . . . . .
18 0x12 . . . . .
19 0x13 . . . . .
20 0x14 . . . . .
21 0x15 . . . . .
22 0x16 . . . . .
23 0x17 . . . . .
24 0x18 . . . . .
25 0x19 . . . . .
26 0x1A . . . . .
27 0x1B . . . . .
28 0x1C . . . . .
29 0x1D . . . . .
30 0x1E . . . . .
31 0x1F . . . . .
32 0x20 . . . . .
33 0x21 . . . . .
34 0x22 . . . . .
35 0x23 . . . . .
36 0x24 . . . . .
37 0x25 . . . . .
38 0x26 . . . . .
39 0x27 . . . . .
40 0x28 . . . . .
41 0x29 . . . . .
42 0x2A . . . . .
43 0x2B . . . . .
44 0x2C . . . . .
45 0x2D . . . . .
46 0x2E . . . . .
47 0x2F . . . . .
48 0x30 . . . . .
49 0x31 . . . . .
50 0x32 . . . . .
51 0x33 . . . . .
52 0x34 . . . . .
53 0x35 . . . . .
54 0x36 . . . . .
55 0x37 . . . . .
56 0x38 . . . . .
57 0x39 . . . . .
58 0x3A . . . . .
59 0x3B . . . . .
60 0x3C . . . . .
61 0x3D . . . . .
62 0x3E . . . . .
63 0x3F . . . . .
64 0x40 . . . . .
65 0x41 . . . . .
66 0x42 . . . . .
67 0x43 . . . . .
68 0x44 . . . . .
69 0x45 . . . . .
70 0x46 . . . . .
71 0x47 . . . . .
72 0x48 . . . . .
73 0x49 . . . . .
74 0x4A . . . . .
75 0x4B . . . . .
76 0x4C . . . . .
77 0x4D . . . . .
78 0x4E . . . . .
79 0x4F . . . . .
80 0x50 V V V V V
81 0x51 . . . . .
82 0x52 . . . . .
83 0x53 . . . . .
84 0x54 . . . . .
85 0x55 . . . . .
86 0x56 . . . . .
87 0x57 . . . . .
88 0x58 . . . . .
89 0x59 . . . . .
90 0x5A . . . . .
91 0x5B . . . . .
92 0x5C . . . . .
93 0x5D . . . . .
94 0x5E . . . . .
95 0x5F . . . . .
96 0x60 . . . . .
97 0x61 . . . . .
98 0x62 . . . . .
99 0x63 . . . . .
100 0x64 . . . . .
101 0x65 . . . . .
102 0x66 . . . . .
103 0x67 . . . . .
104 0x68 . . . . .
105 0x69 . . . . .
106 0x6A . . . . .
107 0x6B . . . . .
108 0x6C . . . . .
109 0x6D . . . . .
110 0x6E . . . . .
111 0x6F . . . . .
112 0x70 . . . . .
113 0x71 . . . . .
114 0x72 . . . . .
115 0x73 . . . . .
116 0x74 . . . . .
117 0x75 . . . . .
118 0x76 . . . . .
119 0x77 . . . . .
120 0x78 . . . . .
121 0x79 . . . . .
122 0x7A . . . . .
123 0x7B . . . . .
124 0x7C . . . . .
125 0x7D . . . . .
126 0x7E . . . . .
127 0x7F . . . . .
done...
I'm thinking about adding a few more features and make it menu driven , so one can do different tests without reloading.
as always, remarks and comments are welcome
latest code - Arduino/sketches/MultiSpeedI2CScanner at master · RobTillaart/Arduino · GitHub -
//
// FILE: MultiSpeedI2CScanner.ino
// AUTHOR: Rob Tillaart
// VERSION: 0.1.04
// PURPOSE: I2C scanner @different speeds
// DATE: 2013-11-05
// URL: http://forum.arduino.cc/index.php?topic=197360
//
// Released to the public domain
//
#include <Wire.h>
#include <Arduino.h>
// scans devices from 50 to 800KHz I2C speeds.
// lower than 50 is not possible
// DS3231 RTC works on 800 KHz. TWBR = 2; (?)
long speed[] = {
50, 100, 200, 250, 400, 500, 800 };
const int speeds = sizeof(speed)/sizeof(speed[0]);
// DELAY BETWEEN TESTS
#define RESTORE_LATENCY 5 // for delay between tests of found devices.
bool delayFlag = false;
// MINIMIZE OUTPUT
bool printAll = true;
bool header = true;
// STATE MACHINE
enum states {
STOP, ONCE, CONT, HELP };
states state = STOP;
uint32_t startScan;
uint32_t stopScan;
void setup()
{
Serial.begin(115200);
Wire.begin();
displayHelp();
}
void loop()
{
switch (getCommand())
{
case 's':
state = ONCE;
break;
case 'c':
state = CONT;
break;
case 'd':
delayFlag = !delayFlag;
Serial.print(F("<delay="));
Serial.println(delayFlag?F("5>"):F("0>"));
break;
case 'e':
// eeprom test TODO
break;
case 'h':
header = !header;
Serial.print(F("<header="));
Serial.println(header?F("yes>"):F("no>"));
break;
case '?':
state = HELP;
break;
case 'p':
printAll = !printAll;
Serial.print(F("<print="));
Serial.println(printAll?F("all>"):F("found>"));
break;
case 'q':
state = HELP;
break;
default:
break;
}
switch(state)
{
case ONCE:
I2Cscan();
state = HELP;
break;
case CONT:
I2Cscan();
delay(1000);
break;
case HELP:
displayHelp();
state = STOP;
break;
case STOP:
break;
default: // ignore all non commands
break;
}
}
char getCommand()
{
char c = '\0';
if (Serial.available())
{
c = Serial.read();
}
return c;
}
void displayHelp()
{
Serial.println(F("\nArduino I2C Scanner - 0.1.03\n"));
Serial.println(F("\ts = single scan"));
Serial.println(F("\tc = continuous scan - 1 second delay"));
Serial.println(F("\tq = quit continuous scan"));
Serial.println(F("\td = toggle latency delay between successful tests."));
Serial.println(F("\tp = toggle printAll - printFound."));
Serial.println(F("\th = toggle header - noHeader."));
Serial.println(F("\t? = help - this page"));
Serial.println();
}
void I2Cscan()
{
startScan = millis();
uint8_t count = 0;
if (header)
{
Serial.print(F("TIME\tDEC\tHEX\t"));
for (uint8_t s = 0; s < speeds; s++)
{
Serial.print(F("\t"));
Serial.print(speed[s]);
}
Serial.println(F("\t[KHz]"));
for (uint8_t s = 0; s < speeds + 5; s++)
{
Serial.print(F("--------"));
}
Serial.println();
}
// TEST
// 0.1.04: tests only address range 8..120
// --------------------------------------------
// Address R/W Bit Description
// 0000 000 0 General call address
// 0000 000 1 START byte
// 0000 001 X CBUS address
// 0000 010 X reserved - different bus format
// 0000 011 X reserved - future purposes
// 0000 1XX X High Speed master code
// 1111 1XX X reserved - future purposes
// 1111 0XX X 10-bit slave addressing
for (uint8_t address = 8; address < 120; address++)
{
bool printLine = printAll;
bool found[speeds];
bool fnd = false;
for (uint8_t s = 0; s < speeds ; s++)
{
TWBR = (F_CPU/(speed[s]*1000) - 16)/2;
Wire.beginTransmission (address);
found[s] = (Wire.endTransmission () == 0);
fnd |= found[s];
// give device 5 millis
if (fnd && delayFlag) delay(RESTORE_LATENCY);
}
if (fnd) count++;
printLine |= fnd;
if (printLine)
{
Serial.print(millis());
Serial.print(F("\t"));
Serial.print(address, DEC);
Serial.print(F("\t0x"));
Serial.print(address, HEX);
Serial.print(F("\t"));
for (uint8_t s = 0; s < speeds ; s++)
{
Serial.print(F("\t"));
Serial.print(found[s]? F("V"):F("."));
}
Serial.println();
}
}
stopScan = millis();
if (header)
{
Serial.println();
Serial.print(count);
Serial.print(F(" devices found in "));
Serial.print(stopScan - startScan);
Serial.println(F(" milliseconds."));
}
}