Our Biomaker Challenge: Designing for Code-Free LCD Menu Generation
By Matthew Hamer, Winter Challenge 2018-2019 participant
I’m a hardware designer and embedded systems programmer based outside Boston, MA, and I was an early independent contributor to the XOD project. I come from a background and education more rooted in art and design, sound engineering, and analog circuit design for audio equipment, than software development/code hacking and seem to be more of a “visual thinker,” so the idea of being able to rapidly prototype microprocessor systems with a metaphor like wiring modules together really appealed to me. And I was glad to see that Cambridge chose to use this environment as an educational aid. I think it will be a unique tool for science and engineering students, even with limited programming ability, to build fairly complex microprocessor-based hardware vital to the success of projects in their own fields, and simultaneously teach how to design and think like an engineer.
Prior to being invited to participate in the Biomaker design challenge, I had been thinking about some of my own microcontroller projects that have been increasing in complexity as I become more experienced writing embedded software. For any kind of widget that has to operate stand-alone, some type of user interface is going to be required. Simple projects can get by with buttons, switches, LEDs etc., but rapidly require some kind of display and organized menu structure to navigate through all the settings and functions.
I felt this could be a really useful feature to have available for other Biomakers to use in the XOD environment for their own projects, but I knew immediately the idea would be too complex to implement in the XOD environment directly using prefab nodes from the core library. Fortunately, XOD makes it easy to implement custom nodes using C++. While it’s often thought that C++ is an inappropriate language to use for microcontrollers, in my experience, that’s not true at all – thoughtful use of C++ features like template metaprogramming and runtime polymorphism/virtual functions bring a lot to the table, and the AVR compiler used for the Arduino processor is very good at using efficient code and supports many recent language features up to the C++11 standard.
I’ve been working with the XOD environment since soon after its release, so I’ve become pretty familiar with its capabilities and current limitations (it’s still a project under continual development and improvement). But implementing any new set of features/nodes for the platform, particularly when using C++ code (and where ironically the whole point of the exercise is so users won’t have to use much code!) and interfacing between hardware like an LCD display and software running on the device requires some careful planning – and a lot of debugging!
Debugging complex programs on a “bare-metal” embedded platform like Arduino, as compared to a desktop platform like Windows or Linux or mobile platform like Android, is a challenge at the best of times. The way I try to keep my sanity on that front is to do as much of the development work as I can, in testable small sections, using portable C++...on a PC! Since the GCC compiler for AVR is a branch of the usual GCC compiler that comes with Linux, if my code passes tests there, then I can usually “port” it to the Arduino with few problems after making the couple of Arduino-specific changes required to get it to run in that environment.
One example of a design issue I had to solve was to make menu navigation more tractable by writing extensions of some of the native XOD C++ classes that work with strings and lists so that lists could be browsed bi-directionally, and traversed up and down, as if between main menus and sub menus. I had to figure out a way to allow a variable number of sub-menus to be connected to the menu they branch off from in the “menu tree” depending on how the designer wants it. Fortunately, recent versions of XOD allow nodes to be “variadic” - accept an arbitrary number of inputs, say for comparing arbitrary numbers of variables and producing a single output, and I figured out a way to leverage that to allow the menu graph to gather information about its own state on program startup and determine what’s connected to what. And since the AVR 8-bit-based Arduino has a pretty limited amount of RAM and program memory storage, I had to try very hard to keep that overhead down. I feel I did pretty well having each menu screen in a sketch only consume a couple dozen bytes of RAM, but with only 2k on the ATMega328 included with the Biomaker designer’s kit, this is still an area for improvement and more work is required.
It’s my hope that this work will be useful for the summer Biomaker Challenge teams in their own work, and I’ve begun working on a second revision to this XOD library with some changes that I hope will make it as user-friendly and stable/bug free as possible by that time!