Arduino I2C sniffer

[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.

Comments

  1. kernelcode says:

    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)

  2. Agent420 says:

    I’m not sure why you would capture raw data instead of just monitoring the bus and reporting the commands and data?

  3. kernelcode says:

    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.

  4. Johngineer says:

    @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.

  5. Tim says:

    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

  6. Anonymous says:

    http://www.qsl.net/zl2wrw/projects/AN6311%20exp/AN6311%20exp.html

    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.

  7. Agent420 says:

    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.

    http://en.wikipedia.org/wiki/I%C2%B2C#Example_of_bit-banging_the_I2C_Master_protocol

  8. John says:

    @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.

  9. Spork says:

    BusPirate is also super clean for this if you have one handy.

  10. Joe says:

    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!

    • John says:

      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.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 96,659 other followers