Pi Wars week -29: Blinkin' Lights

So, you remember how last time I said I'd be talking about threads and/or level shifters in the next blog entry? That's because I'd procured some Neopixels to fulfil the "flashy LED" requirement which had brought their own requirements.

Problem 1: Multitasking

A problem most roboticists will run into eventually: you want your code to be doing more than one time-sensitive thing at once. In my case, it isn't pat its head and rub its tummy; I want my robot to be able to drive around, checking the R/C controller or its environmental sensors multiple times per second, and also flash some LEDs, because flashy flashy flash. Interleaving the code to do both would be a chore, so the usual solution is threads. Write a function to turn the LED on, wait 0.4 seconds, turn it off, wait, repeat, and then run that function in a thread so your main code can focus on driving into walls more effectively and the LED flashing code runs in the background.

Problem 2: Voltage

The Raspberry Pi is a 3.3V device; the GPIO pins can output between 0 - 3.3V. A lot of hobby electronics kit is 5V, and this includes Neopixels - the Pi isn't capable of outputting the specified voltage to control a Neopixel's data pin. (See below) The usual solution to this mismatch is a level shifter chip: feed in 3.3V on a number of input pins and get 5V out for driving 5V electronics. Nice and simple apart from the fact that I don't own one.

Two birds, one stone

arduino My knight in shining Ard-mour

While once again cursing my lack of preparedness in not checking whether the Pi could drive Neopixels, I realised an Arduino

  • Is a convenient source of 5V GPIO pins
  • Can sit and run some simple code to flash LEDs on and off at a command
  • Can use the FastLED library with a single #include statement

The Arduino Nano is more than capable of outputting a few light patterns, so it just needs to be told what to do by the Pi. USB serial is an easy way to achieve this: plug an Arduino into a USB port on the Pi and it will appears as /dev/ttyUSB0. A couple of lines of Python can write out short commands to this device, and an equally simple loop in the Arduino sketch reads the commands and switches to the desired mode.

Python:

import serial
ser = serial.Serial('/dev/ttyUSB0',9600)
ser.write("1")

Arduino:

.#include <FastLED.h>

if (Serial.available() > 0)
{
  mode = Serial.parseInt();
}

Put it all together and what have you got?

Now I just have to find somewhere to squeeze the Nano into my increasingly crowded robot.
Teaser for next time: I just finished assembling the 3d printed scale model of my robot shell (which was the last job to do before submitting an application)

spoilers

- PKM


  • Technically they specify the control voltage should be more than 0.7 times the power supply voltage, because of something to do with pesky analog physics, which means either giving it 3.5V for a 5V supply, or dropping the supply voltage via some creative use of diodes. I'd rather just use 5V for power and 5V for the control signal. Opinion is divided on whether you can drive a Neopixel straight from a Pi GPIO pin, but that's the kind of marginal behaviour I'd rather avoid for the sake of reliability.