eye2see - Tiny Symbolic Debugger for all Arduinos*

* "Tiny Symbolic Debugger for all Arduinos" applies if your project uses an I2C bus or has an available I2C port

Similar projects worth following
Frustratingly, most Arduino debugging is done with "Serial.print()". What if I told you you can have a symbolic debugger, with breakpoints, using just an I2C bus and a few C/C++ pre-processor tricks? And what if this works on all Arduinos, even tiny ones like ATTiny85s, and often without requiring any dedicated pins? Well, you can do it with eye2see :-)

The idea of eye2see is to add a slave I2C device to your project's I2C bus, and send debug output from your program to an eye2see device ("probe"). The eye2see probe can be another Arduino, or the eye2see hardware described in this project. Also provided is an Arduino function (just a few lines of code) that you add to your code and call when you want to output debug information. The eye2See device talks to your PC over USB, and the eye2see Python GUI running on your PC will display variable names, values, line numbers and even filename! Symbolic debugging with your Arduino!

Why eye2see ?

For decades professional embedded tools have included sophisticated debuggers, typically ones that provide debug data using information from the source code ("symbolic debuggers"). The Arduino universe has enabled millions of people to develop amazing embedded projects, but has never offered robust debugging capabilities (this is changing with some of the newer hardware and IDE versions). But since so many folks are happily using legacy, small, low cost and low performance Arduino-based platforms, we're left without good debug tools!

eye2see (a play on words ;-) ) was developed by me as a way to get debug info out of Arduino projects that were very limited, in terms of pins, memory and ports (like the ATTiny85). Many of my projects (most?) have an I2C bus connecting displays and sensors, or have a free I2C port. So, why not output debug information over those wires?? ZERO additional pins used if you're already using I2C! 

Once I started sending debug info out the I2C port, I realized I could use C/C++ macros to get actual symbolic information at run-time (!), and format data for display on a PC. I used an Arduino as an I2C to serial-over-USB bridge, but soon added functionality to this "probe" (hardware and software). eye2see was now a light weight, sophisticated symbolic debugger (with a couple of small limitations).

I've used eye2see for a couple of years, and it's now indispensable for all my projects. It's far superior to using "Serial.print()" debugging, and it frees up the serial port for other duties! I typically add a Qwiic/StemmaQT connector to all my PCBs so connecting the eye2see probe is plug-and-play. Where eye2see is particularly helpful is debugging results of type conversions (different sized integers, signed/unsigned, overflows etc.) as it can display variable values in different bases and formats.

eye2see - Overview

Once you have the eye2see system set up (more on this below), using eye2see is extremely easy! Any time you want to see the value of a variable in your running program, all you need to do is insert a line to call eye2see, with the variable name in the function call:


When you upload your program to the target and it starts running, and the line of code you inserted executes, you will see a display like this on the eye2see PC graphical user interface:

ey2see displays a timestamp (each time the variable is updated), the file name of the Arduino source file (aka Arduino IDE tab), the line number of the added line of code, the variable name and the variable value - which can be displayed in user-selectable signed decimal, unsigned decimal, hex or binary formats!

eye2see can also display text strings (like using Serial.print()):

e2cslog("Hello world");

Will display : 

You can use eye2see to watch multiple variables, with the most-recently updated value being highlighted in red.

Break Points

In addition to watching variable values, eye2see can also stop execution on the target when a variable is updated ("Break Points"). A red dot indicates the execution has hit a "break", and a "Resume" button allows the target code to resume running:

Break points can be enabled and disabled from the eye2see GUI, and can also be set using the following function call in your code:


eye2see - Limitations

The main limitation of eye2see is that it slows down target execution (a lot).  This is due to handshaking that occurs between the eye2see components (running on target, eye2see Probe and the PC).

For many debug cases this is not a big problem (for example, when developing user interfaces etc.). In some cases it doesn't impact programs that interact with the real world (for example, reading a sensor), but in some cases it will impact operation of the target (for example, motor control). In some cases it's possible to record variable values to global variables in...

Read more »

  • eye2See - Preprocessor Magic

    Mark Henderson08/07/2023 at 18:22 0 comments

    eye2see - C/C++ Preprocessor Magic

    The C/C++ preprocessor is a very powerful tool, and a couple of its features are used by eye2see to perform "magic" - namely obtaining key debugging information at run-time: file name, line number, variable size, value and memory location.

    These are preprocessor features used (the last 2 are actually native C/C++ features):

    __FILE__         //makes file name available to C/C++ macros 
    __LINE__         //makes file line number available
    #varName         //makes variable name available as a string
    sizeof(varName)  //makes byte size of variable available
    &varName         //makes memory location of variable available

     By coding the eye2see user functions as macros, and using these features, we can access runtime values and pass them over I2C to the eye2see Probe and then on to the PC GUI via USB for display.

    #define e2clog(v,b) E2Clog(__NAME__,#v,b,sizeof(v),v,&v, __LINE__)

    Another eye2see macro called __NAME__ takes the file name returned by __FILE__ and strips off the PATH to reduce the display line length.

  • eye2see - the Probe

    Mark Henderson08/07/2023 at 17:51 0 comments

    eye2see Probe Hardware

    The first dedicated eye2see Probe hardware is shown below. 

    This uses a simple 2 layer PCB (fabricated here by OSHPark, I also use PCBWay and both give excellent service and quality). The PCB forms the bottom of the enclosure.  The Seeed Xiao RP2040 is soldered to the PCB, along with the FPC connector for the 132x32 LCD, Qwiic/StemmaQT connector and 3pin 0.1" male header (both connectors carry ground, SDA and SCL for attaching to the target). Captive nuts fit in 4 holes in the corners of the PCB.

    The enclosure "chassis"  was designed using OpenSCAD and is FDM 3D printed in PLA (on my Monoprice MiniDelta II), holds the LCD securely, and provides clearance for the FPC cable, connectors and components on the PCB.

    Finally, the enclosure top is laser cut from 1mm black acrylic, and bolts through the chassis to the captive nuts in the PCB.

    This stack makes a rugged, compact and inexpensive enclosure.

View all 2 project logs

Enjoy this project?



Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates