Category Archives: Microcontroller

LED light strip LPD6803 code

Wow, it’s been a crazy few months. I am taking some courses for my masters, started a few contracting gigs and went to China with DangerousPrototypes Hacker Camp. There is so much to write about and I’ve been dropping the ball on Protological. Time to change that. Time for some cool LED stuff!

While in China I picked up a 5 meter “5050” 12V LED strip with 30 LEDs per meter for 90RMB which is $14.50 USD. I didn’t buy the controller because I wanted to control it with a microcontroller of course! The controller chip is a knockoff LPD6803 LED driver chip that listens for clocked data. The only datasheet I could find was from Adafruit here and the english is really, really bad. I didn’t know ‘grey’ == ‘color’?! After some playing around I figured out the protocol for how the data is sent. The commands are 16-bit and shifted out MSB first, the clock is idle low and the data is latched in on the high transition of the clock. The MSB is always 1 to indicate that the value is data and the 3 colors are 5 bits each; allowing for 31 steps in brightness.

1000 0000 0000 0000
D|Col1||Col2||Col3|

One would think that the colors are Red, Green and Blue, however some testing showed they are Green, Red and Blue.

1000 0000 0000 0000
D|Grn ||Red ||Blue|

So if you want to turn on an LED with 1 step of RGB the byte value is 1 00001 00001 00001 = 1000 0100 0010 0001 = 0x8421;

These strips can be chained together, so to ‘reset’ the strip pixel ID and have it listen for a new set of colors you send 32 0’s which is 8 bytes of 0x00. Once I got the protocol figured out it was really easy to hook up a micro and control the strip.

I used an LPC1768 Mbed microcontroller (because it’s super easy) and made a demo program with some simple animations. The strip is 30 LEDs per meter, 5 meters long. Each LED ‘pixel’ is a group of 3 RGB LEDs and they all show the same color. So there are 50 groups of 3 in my 5 meter strip. The way I drive the LEDs is I make a uint16_t array in RAM for the 50 pixels, then create a timer to run through the array and send it out to the strip using the SPI hardware. With 8 bytes of reset, 100 bytes of data, at 500KHz I was able to address the whole strip in about 4ms. I set my timer to update the strip at 10ms, giving me a 100Hz refresh rate.

The rest of the application just writes the data array in memory and lets the timer clock it out to the strip. I included the code here with 4 demos. This will build in the Mbed compiler and uses the P5 & P6 SPI pins on the LPC1768 for data and clock. It should be pretty straight forward to port to an Arduino or other microcontroller, just setup a timer and update the SPI config and write functions.

Here is a video of the demos in action:

And the source file: ledstrip_mbed_demo.cpp

Enjoy, Drew

Impressions on the Arduino Yun

Arduino Yun

As I mentioned before I haven’t worked with the Arduino family much since I tend to be working on different processors than 8-bit ATMega chips. Recently I have been playing around with an Arduino Yun for a client and had a chance to explore the features of this microcontroller + Linux SOC board.

First I want to say that I think pairing a microcontroller with a Linux SOC is a great idea. The micro allows for very fast and accurate data sampling and GPIO control while the Linux SOC deals with all the networking and file system stuff using the Linux OS. So far I think the Yun is pretty good but there are a few things that are really frustrating.

First, the Arduino IDE and toolchain. I don’t like the fact everything is hidden and you MUST use the Arduino IDE (yes, even for command line compilation). You can’t use Makefiles and the gcc stuff is all tucked away so you can’t see it, and thus can’t modify it easily. Also each ‘sketch’ must be an *.ino file which is a pain in the rear if you are using a C editor like Eclipse. This isn’t so much a Yun issue as a limitation with the Arduino way of doing things. Personally I find a raw gcc binary and a USB programmer to be much better, but that’s what I learned on.

The other thing I dislike is the way the networked “Console” is implemented in the Yun. The Console is a way of sending text out to a PC, similar to the USB serial port on other Arduinos. The issue with the Yun, is to get the text you have to SSH into the device and then do a telnet to a locahost port. Honestly I can’t really think of a better way to get debug information out wirelessly, but it’s really clunky. I am going to be looking into using the USB serial port rather than the Console because it’s much simpler.

My final issue is that it takes >60seconds to get the Linux part of the Yun up and running. Why!? I have a RaspberryPi that boots in <10seconds, how can a 16M Linux install with only about 30 entries in the ‘ps’ output possibly take 60 seconds to boot? I’d also like to know what happens to the Linux system when you pull the power, hopefully I don’t run into some kind of config file truncation due to power loss in the middle of a flash write (Yes, I have dealt with that before).

I’m not a total hater. I do like the fact that you can write a file on the Linux part of the Yun without writing an entire file system for the ATMega. The project I am working on reads lots of values and logs them to files which are then post processed. Having gigs of space on a SD card is great for logging lots of data over time. Also, since the Yun uses SSH, you can SCP and SFTP files off the Arduino wirelessly which is a really nice way to collect all that data.

It’s also worth noting that you can update the firmware via WiFi right from the Arduino IDE. This is a really nice feature for once a system is deployed since it might be in a really difficult to access location. The issue with the WiFi update is that is seems really slow, on my limited tests it takes over 60 seconds to program which can really slow down my code-test-update cycle. I would recommend programming via USB for development and WiFi if you need it for production.

The summary is that while the interface and access is a little clunky, the Yun is pretty good little platform if you need a networked microcontroller to collect lots of information.

Arduino execution time analysis

Recently I was asked to take a look at some code for the Arduino Yun that was developed as a proof of concept for a medical device. The company developing the device was “running out of room” and couldn’t get the Arduino to sample all the ADC inputs in the time period they wanted. I suspect they mean they are running out of processing time to sample/control multiple outputs within their processing window. I have always worked a level down from the Arduino wiring framework and honestly have not worked with the Arduino family much, but when a contract job comes up, you take it. The first thing I noticed in the code was heavy use of floating point values as parameters and returns for lots of functions. Anyone who is embedded knows that floating point operations take WAY more time than integer math, but I was curious as to how much longer. I didn’t find any good online resources that say “floating point divides take XXX instructions”, so I decided to get that information myself.

While I don’t have a Yun, I do have an Arduino Uno which uses the ATMega328, an 8-bit micro with most instructions running at 1 instruction per clock using a 16MHz crystal. I decided to look at each basic math operation for unsigned integer types and floating point types. All input and output variables were created as volatile so the compiler wouldn’t optimize, each operation was performed 1000 times and the results are the average. The method of recording the times was the micros() function which has an accuracy of 4us and does include an unsigned long shift, adding a uint8_t and a multiply by a uint16 literal value. Here are the results on the Uno:

Starting test, looping 1000 times
Control 10ms loop: time 10009 us
Float div: 34 us ~544 instructions, 29/ms
Float mul: 12 us ~192 instructions, 83/ms
Float add: 11 us ~176 instructions, 90/ms
Float sub: 11 us ~176 instructions, 90/ms
uint8 div: 8 us ~128 instructions, 125/ms
uint8 mul: 3 us ~48 instructions, 333/ms
uint8 add: 3 us ~48 instructions, 333/ms
uint8 sub: 3 us ~48 instructions, 333/ms
uint16 div: 16 us ~256 instructions, 62/ms
uint16 mul: 4 us ~64 instructions, 250/ms
uint16 add: 3 us ~48 instructions, 333/ms
uint16 sub: 3 us ~48 instructions, 333/ms
uint32 div: 41 us, ~656 instructions, 24/ms
uint32 mul: 9 us, ~144 instructions, 111/ms
uint32 add: 4 us, ~64 instructions, 250/ms
uint32 sub: 4 us, ~64 instructions, 250/ms

What is interesting is that a uint32_t divide takes more time than a floating point divide! Overall it is clear to see that as the integer gets larger the processing time increases. Floating point operations are 3-4 times as long as integer operations (except for uint32_t divides). I estimated the number of instructions per operation based on 16MHz and how many of each operation could be performed in 1ms.

The next step is to get these values for the Yun and look for performance improvement areas.

Here is the code I used to get these values: http://protological.com/browser/files/timer_sketch.ino.
(Here is the same code but with a macro function, it’s a little cleaner to look at)

Microcontroller parameter parsing with AWK

I needed to get all the information on every 16bit Microchip PIC microcontroller into one header file for use in a library. Microchip supplies a pic.h header for processors but it doesn’t have the information I needed including end address of the flash and EEPROM. If you poke around on the Microchip parametric search site, you can select all 16-bit microcontrollers and download a CSV with all the parameters. A little bit of AWK magic and you can get a nice header with whatever data you want.

awk -f process.awk all-microcontrollers.csv > pic.h

AWK script and example output header

microchip microcontroller parameteric search