Some time ago I was doing some work on embedded systems firmware for a small control board using an 8-bit microcontroller. It had to control some motors and a laser, and had to send back sensor readings to a PC. I was looking for a simple peer-to-peer serial protocol that was robust against noise and other failures. Basically, I wanted an answer to a commonly-asked Stack Overflow question.
I didn’t want anything too complex and it all had to work in a tiny 8-bit ATmega AVR microcontroller (so there was no space for large packet buffers). I couldn’t find anything suitable so taking inspiration from CAN and LIN, I decided to roll something myself. I’ve called it MIN and uploaded a reference implementation to GitHub. MIN is pretty small and robust (about 200 lines of code) and in this post I want to help people quickly get a “hello world” program using MIN up and running.
I’ve built the test program using an Arduino Mega 2560 board (it runs a 16MHz ATmega2560 AVR 8-bit CPU) and wired it up to a bit of breadboard with a pushbutton, a serial-to-USB breakout board, and an LED. I’ve also used JTAG as the debugger connector to a Windows PC running Atmel Studio 6. Also running on the PC is a little Python-based test program that talks to the Arduino board.
Here’s the kit on my bench:
The Arduino board is the blue one. It’s plugged into USB for power (it’s not connected for anything else). TX0 and RX0 on the Arduino are wired to a serial-to-USB breakout board on the white breadboard. The serial board is a really neat little board that takes 5V (or 3.3V) level serial pins and converts to USB using the serial protocol (which means that the embedded board turns up on the PC as a COM port, COM4 in my case).
The Arduino board doesn’t have a JTAG connector so I wired the CPU’s pins with fly leads directly to the JTAG connector on the Dragon board. I’ve included a photo here so that anyone wanting to replicate this setup can do so easily:
The breadboard also contains a pushbutton that floats open until pushed, connecting PA6 on the Arduino to GND. The firmware sets this up with a pull-up resistor so that it reads ‘1’ until the button is pressed. The test program calls this a ‘deadbeef switch’ and sends a MIN message with payload 0xDEADBEEF to the other end when pressed. Every two seconds the test program also sends an ‘environment report’ message (containing hardwired values for temperature and humidity).
I also ran an output pin to my oscilloscope, toggled in the firmware every 8ms, that’s the first level of debugging to test if code is running. You can see the nice square wave here:
The test program on the PC end is written in Python (I used version 3.4) and has an interactive mode. Pressing ‘p’ sends a MIN frame that’s treated as a ‘ping’ request by the firmware – the application just sends the frame back. When ‘m’ is pressed a ‘motor request message’ is sent, which is interpreted by the firmware as an instruction to light an LED on the breadboard for 1 second (about as close to printing “hello world” as embedded software gets).
The test program also decodes and prints out MIN frames it receives from the Arduino (the deadbeef switch message, the environment report and the ping message):
I’ve used this for real where MIN is sending continuous sensor data and taking complex commands in a real embedded system that runs in a noisy environment. It’s worked well and I hope other people find it useful too.