Sometimes there’s just no substitute for the right diagnostic tool. [Ankit] was trying to port some I2C code from an Arduino platform to an ARM chip. When the latter code wasn’t working, he got clever and wrote a small sketch for the Arduino which would echo each byte that came across I2C out to the serial line. The bytes all looked right, yet the OLED still wasn’t working.
Time to bring out the right tool for the job: a logic analyzer or oscilloscope. Once he did that, the problem was obvious (see banner image — Arduino on top, ARM on bottom): he misunderstood what the ARM code was doing and was accidentally sending an I2C stop/start signal between two bytes. With that figured, he was on the right track in no time.
We just ran an epic post on troubleshooting I2C, and we’ll absolutely attest to the utility of having a scope or logic analyzer on hand when debugging communications. If you suspect that the bits aren’t going where they’re supposed to, there’s one way to find out. It’s conceivable that [Ankit] could have dug his way through the AVR’s hardware I2C peripheral documentation and managed to find the status codes that would have also given him the same insight, but it’s often the case that putting a scope on it is the quick and easy way out.
This is funny. I am just sitting down to troubleshoot an i2c issue. I turned on my scope and then checked my email to find this. I call an oscilloscope a time microscope — which is most certainly what it is. Almost the equivalent of “put a printf in the code and let it tell you what it is doing” is “hook up the scope and see what is really going on”.
Now that you mention the printf, there is a trick I learned a long time ago. Let’s say you want to debug a state machine. You can use an unused DAC (or even connect one) in your uP and output a different voltage for every state. Then on the scope is obvious what your program is doing. This has saved me a lot of time debugging embedded circuits.
Wow! That’s a pretty ingenious idea. Never thought of that. I’ve done something similar in using a few extra GPIOs as state flags with some encoding register states and some which step it was on, but was limited by number of pins. Combining the two gives me a much greater flexibility.
Slight variation:
Output the debug data to whatever (serial) peripheral your’re not using uart, i2c, spi, etc and catch it with a logic analyser. Much more accurate and you can search through your data.
Years ago I wore some macro’s for AVR to do this at a random pin and I was amazed how usefull this was.
/*===========================================================================
User definitions for: Debugging.
Copyright 2014 Paul vd Hoeven. Released unther the GPL V2.
===========================================================================*/
/* Simple and low impact debugging lib.
It’s main use is to output some values to a logic anaylzer to trace back which
parts of your code are exectuded and the timing between marked points.
1). Define “DEBUG_PORT”, “DEBUG_DDR”, and “DEBUG_BIT” macro’s for the
debug output and include this header file in each .c(pp) file you want
to use it for debugging. Copy/paste the example:
//#define DEBUG_PORT PORTD // This define adds/removes the debug code.
#define DEBUG_DDR DDRD
#define DEBUG_BIT (1<<7)
#include "debug.h"
2). It's possible this way to use a different debug pin for each source file.
3). Call the DEBUG_OUTPUT_ENABLE macro once to enable the output.
4). DEBUG(X) can now be used to trace the execution path through your software
with a logic analyzer.
5). Output format is serial, 7N1 with a baudrate of 50% of F_CPU.
6). Commenting out "DEBUG_PORT" & recompile will completely disable debugging.
7). If optimisation level is higher than -O1 timing gets messed up.
8). For an overview of the meaning of your debug numbers you can comment
the debug lines and then do a grep on that file. See example below.
Bug: Enchancement, Use hardware SPI, U(S)ART or whatever is available.
– Variables can be send.
– Even lower inpact on program timing.
– Less flexibility in output pins.
– needs more i/o pins.
– This debug can use different pins for each source code file.
*/
#ifdef DEBUG_PORT
// Just to make sure the user knows the debug code is inserted.
// Higher optimisation levels disrupts the timing for debugging.
#warning Debug code inserted. Use optimisation level: -O1.
// Use this macro to enable the debug output pin.
#define DEBUG_OUTPUT_ENABLE _SET, (DEBUG_DDR |= DEBUG_BIT)
// 3 little Macro's for internal use only.
#define _SET (DEBUG_PORT |= DEBUG_BIT)
#define _CLEAR (DEBUG_PORT &= ~DEBUG_BIT)
#define _BIT(X,Y) ((X) &(0x01 << (Y)) ? (_SET) : (_CLEAR))
// Startbit, a bunch of data bits and a stop bit.
#define DEBUG(X) (_CLEAR,\
_BIT(X,0), _BIT(X,1), _BIT(X,2),_BIT(X,3),\
_BIT(X,4), _BIT(X,5), _BIT(X,6), \
_SET)
#else
// Preprocessor removes debug statements.
#define DEBUG_OUTPUT_ENABLE
#define DEBUG(x)
#endif
The stuff on my website is getting pretty old unfortunately…
I’ve debugged JTAG breakpoint code with an oscilloscope and put rising edges on unused pins at points in the code to trigger. It really can be simplest way to figure out what’s wrong at the software level.
I hope the readers are all smart enough to know the difference between the two devices mentioned and the voltage limitations involved with one of them….
That said, having a logic analyzer, I would have pulled it out and used it for I2C, as it’s going to have some protocol analysis available so I can see what’s going on without having to decipher the bits to be sure.
Short of having the logic analyzer, a ‘scope will work, but it’s more work to get an actual value out of your display, unless you have a more expensive scope that can do communication protocols as well.
But using a “LOGIC” logic analyzer that is limited to TTL and trying to read real, full level RS232 is going to bite someone if they don’t know better.
A scope would cover it, but having a headline like this and then talking about a completely different piece of gear is kind of weird.
But you are the only one talking about a logic analyzer.
Oops, I stand corrected – yes the title is misleading. I find logic analyzers a pain in the rear to set up, but invaluable when you have lots of channels and only care about logic states. An oscilloscope on the other hand is usually quick and easy to clip onto a single signal and of course shows you the full range of voltage levels. I just invested in a Rigol DS1054Z and could not be more delighted. My old Tektronix 7603 won’t be seeing much use.
That’s a Saleae logic analyzer’s output in the pic, isn’t it? Good stuff, those, and a better UI than any other logic analyzer I’ve used. The newer devices with analog channels can even be a passable substitute for an oscilloscope, so long as you’re working with fairly low frequencies like I2C.
Regarding the Saleae logic analyzer, a few years ago I’ve bought the 1st version (8bit and digital only). It is a wonderful device that has helped me out many many times. In combination with the protocol analyzers it is really practical. It is just so much easier then counting edges on the signals of an oscilloscope screen.
But what is the greatest of all is the infinite depth, you can sample for very long, minutes on 24MHz is you have to. Which is great if you do not know when your problem is going to happen or to which event it is related.
It is a shame that there are cheap clones/copies out there that pretend to be the real device and therefore use the same software. So if you want a versatile but cheap analyser, go for the Saleae one, support the designers not the pirates that make the clones.
Or you can use sigrok with the “clones”. They have fully open source firmware and driver for them and sigrok/pulseview are open source as well. Support open source, not over charging corporations.
If you are implying that Saleae is an “over charging corporation” you are dead wrong. The owners are makers like all of us that are making a living by creating a fantastically well-designed product at a very reasonable price. I have bought several logic analyzers from them and are among the finest measurement devices I have ever had. My Kudos to them and Jii not everyone that sales something is a crook, somehow people has to make a living and employ other people. I’m sure Saleae creates a lot of direct and indirect employment.
Well sorry, but charging over a hundred for 8 bit 24 Mhz Logic analyser for 3,3V logic (as, if i remember correctly, the original does not have a buffer or is the wrong kind, it can overload 5V pins, just like in some clones) made from 2 dollar MCU and the whole thing isn’t their design, as i’ve understood, pretty much brings them to a over charging corporation in my book.
If it actually was reasonably priced, i’d have no problem. There is no way to be able to beat the chinese, if you keep over valuing your brand. You pay 15 dollars or 150 dollars. Well, maybe i’m wrong, look where Apple is.
If you have $100 to spend on a logic analyzer, look into the DSLogic. HaD even has a review and sell that in their store. It has 16 channels with 16MB buffer and can sample to 100MS/s or 200MS/s for 4-bit. Software is a bit crude and it locks up once in a while, but it does it job.
Oops. It can go up to 400MS/s for 4 inputs. The probes are passive probes with a voltage divider and to reduce loading for high speed signals and it is a micro coax cable. Most of your your usual DIY or those 24MHz toys just feed the signal with a short loose wire into a chip or a buffer. There is a bit of engineering for that price.
Absolutely love Saleae’s products and support. Recently upgraded my Logic16 to a Logic16 Pro (which has some useful analog functionality). The software sells their product IMO
Unfortunately, no USB LA is a substitute for a physical one, for the simple reason that it’s triggered. Physical ones can be left to roll, which means you get to see the glitches that happen when you don’t expect, and the infrequent ones too.
Once you know they’re there, by all means use a USB one, but there are many bugs I’ve caught in the past just by having the ‘scope on roll, and seeing something ‘odd’ that I wouldn’t have captured otherwise.
Quite a strange article in my opinion… The arduino code is really trivial and there is certainly already something like this on the internet – or to quote some other comments: Where’s the hack? Using an AVR with internal I2C hardware to receive I2C isn’t one.
Ok, let’s say something more useful… For those like me that need to debug an I2C (or other) bus with a scope that doesn’t has protocol decoders (like the famous DS1052E): It’s quite easy to export the data from the scope, convert it and feed it to the I2C analyzer of the Open Logic Sniffer software or some other software (protocol decoders or other stuff). I did this once using a USB flash drive, it’s works but saving 1M points in csv is reaaaaaally slow (and even if the native Rigol format has been reverse-engineered it’s to complicate for a quick thing). I plan to connect the scope to the computer and automate the entire thing using Perl. It’s quite easy to talk to the scope and the commands are documented entirely by Rigol – have fun!
(For those like me that don’t have a logic analyzer but only a scope…)
If you have a device or a master that pulls down the clock or data line line out of turn, then all you can see on the logic analyzer are corrupted data.
If you have a scope, you can at least put a small series resistor in the 100 ohms range on the device and try to observe the voltage drop across it to determine if who is acting funny pulling the signal down. The current shows up as a small I*R drop and can be seen in a scope.
Ideally, you want to have both – one for timing and one for looking at the signal level and signal quality.
i had a simular issue with driving an I2C OLED from arm when the exact same code worked well on an arduino.
after some datasheet diving i ended up changing slew rate and drive strength on the i2c gpio ( PORT_PCR_DSE_MASK and PORT_PCR_SRE_MASK) and then it just worked ;)
In my day, oscilloscopes were often affectionately referred to as “Truth Meters”. A well applied scope really is hard to beat! I often use mine as a quick replacement even for a voltmeter.