Microcontroller Interconnect Network (MIN) version 1.0

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:

2015-02-18 15.02.16

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:

2015-02-18 15.02.52

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:

2015-02-18 15.03.31

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):

mincap

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.

Advertisements

10 thoughts on “Microcontroller Interconnect Network (MIN) version 1.0

  1. Nice comm protocol. I’ll check if it fulfils the requirements of my project. In case it doesn’t then it will be a great start point if I need to write my own.

    Keep coding and cheers!

  2. Glad you like it. If you do need to make changes then let me know: maybe we can roll them into MIN. I’m hoping to find the time to write a dissector for Wireshark to display not just MIN frames but also application-level signals contained within the frames.

  3. Hi Ken, thank you for open-sourcing your efforts! I know it is a bit offtopic, but is there any reason to use MIN on a board like STM Nucleo with a Cortex M MCU http://www.digikey.com/product-detail/en/ATMEGA2560-16AUR/ATMEGA2560-16AURTR-ND/2357022? It has CAN, I²C, IrDA, LIN, SPI, UART/USART. I’m not trying to say you’ve invented a wheel, as you’ve obviously made an analysis and decided to get some inspiration from CAN/LIN. But is it so important to keep using an 8bit MCU, which today is even more expensive than a 32-bit Cortex M0 http://www.digikey.com/product-detail/en/ATMEGA2560-16AUR/ATMEGA2560-16AURTR-ND/2357022?

    • Ha, I just ordered a Nucleo board an hour ago! Coincidence – or else you work for the NSA.

      For sure, MIN isn’t aimed at replacing CAN. It’s designed for a tiny MCU to talk to a host (either another MCU or a PC). And PCs don’t come with CAN controllers fitted (although you can get one). If your application lets you have a PC with a CAN controller, and the target MCU has a CAN controller, go for CAN.

      As for 8-bit MCUs being obsolete, that day will come (as it did for 4-bit micros). But I don’t think we’re there yet (compare an Atmel AVR with an Atmel SAMD10, for example). But for a dollar you can sure get some good MCUs now and if I were designing a non-volume product I’d put something much more powerful in. My latest project uses a SAM3X8E with 96K RAM and we’ve got a Wiznet W5100 chip on the board.

  4. Ganesh says:

    Stopped here in search of a simple protocol for communication between a micro and a Python. I needed a protocol where i send some request commands using the micro to the Python Gui to update the Sensors Data, and even send data from the Gui to update the Registers in the micro

    so Now, how can i change the payload size in your protocol, i wont be sure on how much data i would be sending in (updating all the Register values in the Gui which is sent from a Micro would require Higher payloads )

  5. I recently changed the max payload to 127 bytes because it was commonly required to have something bigger than 15 but not need an arbitrary length. The reason for 15 was to optimise the calculation of Fletcher’s checksum and to constrain the buffer sizes so that there would always be space. But it the applications I’ve worked on, there’s enough buffer space to pre-allocate fullsize buffers (if you don’t have enough space to do that then you’ll have to handle buffer overflow by discarding a message that’s too big).

    I’m going to update MIN with this larger message limit. I’ve got some improved Python handling too, with a baseclass for frames where an application can inherit and handle unpacking of frames into Python objects with attributes that came from the frame payload.

    You might see that I’ve been working on a JSON framework for describing sensor data and mapping to MIN frames. The goal is to autogenerate the MIN handling in embedded C and for the Python to inspect the JSON and automatically create the application-specific classes to pack and unpack sensor data into frames.

    Ooops, I forgot to say: if you want to hack the code now to raise the limit to higher than 15 bytes you need to revise the calculation of Fletcher’s checksum (WordPress is doing its best to corrupt pasted Python snippets, nice).

    One last point: you probably don’t want to put arbitrary payloads into a frame. The idea really is to have a fixed set of data associated with a given frame ID and then send multiple frames with different IDs at a rate that makes sense. For example, a temperature frame might have ID 0x12 and contain some temperature data and be sent every 1 second, whereas a speed frame might have an ID 0x25 and contain motor speeds and be sent every 100ms. Your GUI would display the latest value of each sensor in any frame it received. The unpacking of the frame is therefore dependent on the frame ID (so frame 0x25 in this example would always contain the same number of speed readings in a fixed place in the payload).

    • Ganesh says:

      Yah !! That’s a good idea of splitting the sensor data into different frames, I am actually dealing with a 32bit micro controller where the updates should be fast enough to the get the system running under a closed loop in real time … Thanks, ken !

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