[Johngineer] found himself in need of an I2C sniffer, but didn’t have one available. Necessity is the mother of invention, so he put together this I2C sniffer sketch for Arduino. The arduino will record what is going on for a set time interval, then dump the data via serial as a .csv. You then have to plot it to see what is going on. [Johngineer] recommends Livegraph, since it is portable and easy. As you can see in the code, the time interval is adjustable, but you have the physical limitations of the RAM on the board to consider. This seems like a pretty handy piece of code stored around, effectively giving you a passable I2C sniffer in a pinch.
11 thoughts on “Arduino I2C Sniffer”
Nice and handy for folk with Arduinos
I think a good way to get around RAM limitations would be set up an interrupt on the pin you’re monitoring and a timer which counts the time between edges. That way, you only need to store a byte (or two) for each edge which should give you plenty of space.
(Up to 2000 edges with 2K I suppose)
I’m not sure why you would capture raw data instead of just monitoring the bus and reporting the commands and data?
Then you have to teach the micro to ‘speak’ i2c.
I’m not really familiar with Arduino libraries, but I think the i2c library is fairly regimented in its implementation (i.e. you can’t just monitor the bus).
Plus the way he did it doesn’t limit him to just i2c – he can monitor any digital signal.
@agent420: I was working on implementing an i2c slave in software, so I needed to see the raw data on the lines so that I could get the timing right.
I wrote some I2C sniffer code for a silabs C8051F340 MCU one time. On that MCU, it has specialized I2C hardware, so you only have to peek/poke certain registers to make the I2C bus do what you want.
What I did was set the I2C hardware to slave mode, so an interrupt fires when it detects activity on the bus. Normally what would happen now is the ISR would compare the received device address to the one you programmed the MCU to respond to, and send an ACK if they match. Instead, my ISR sends an ACK for EVERY device address received (I have to send an ACK instead of just being passive on the bus because of they way the I2C hardware on this device works, if I do not ACK the first byte received the hardware will ignore all further bytes received and not fire I2C interrupts until the next START). Then, it just sits passively on the bus (NOT sending an ACK, or ever transmitting data), reading every byte is sees on the bus until a STOP is detected, and adding each byte to a buffer.
Then, once the stop is detected, I pull the received data off of the buffer, package it into a “packet” (basically just add the byte count as the first byte of the packet), then add each packet to a large circular buffer so I can pull the data off vis USB
This page has some similar code (pllsnoop on the page) to spy on a radio’s PLL comms. Granted, it’s not specific for Arduino, but, I personally, have “adapted” it. If I recall correctly, only required some pin changes in the code.
I’m not saying it’s not an intertesting way to go about it, but it seems to me that there isn’t a lot of timing to account for… you are simply monitoring pin states.
Wiki’s I2C entry has a decent psuedocode bitbanging example.
@agent420: ‘timing’ was not the word I should have used — ‘signalling’ is more accurate. the problem i was having was that my slave was not ACKing after receiving a byte of data.
by showing me the sequence of events, the sniffer helped me figure out why: specifically the slave wasn’t asserting a low state on the SDA line fast enough to run through a master-driven clock pulse (a standard ACK). SDA was in fact going low about 2/3rds of the way through said pulse.
the problem was in the code, which i was able to re-arrange and optimize so that it forced SDA low earlier, while at the same time releasing SCL later. sniffing packet content alone wouldn’t have told me anything, i needed to look at the physical layer.
BusPirate is also super clean for this if you have one handy.
Would a sound card and paired MOSFET-based sampling amps work? Or would there be more to it? I just wonder if there’s a good circuit for recording the signals of an EEPROM (~10Kb/s) using a standard stereo line in jack. I recommend some kind of amplifier because of noise immunity. You don’t want a whole lot of signals going from the PC’s electronics into the other machine, not to mention ground faults!
A sound card would probably not work for I2C. Most sound cards can sample at a rates up to around 96kHz. I2C typically signals around 100kHz, so you’d need a sample rate of 200kHz to capture the I2C data, which is far beyond most audio cards.
Please be kind and respectful to help make the comments section excellent. (Comment Policy)