Introduction: Color Changing Larson Scanner

Video of scanner in action. Yes, I'm rotating through the colors manually.

Who doesn’t love KITT, the superhero car from Night Rider? The one with the Glowing Bouncing lights of a Larson Scanner up front. That scanner was so cool, they even filmed a remake of the TV Show featuring it. Don’t forget the Larson Scanner also made an appearance in Battelstar Glatica, Whooshing back and forth on the face of the Cylons.

On my version, for my car, I wanted the red glow from the TV car when showing it off, but I also wanted to be able to change to a color that would not be mistaken for an emergency vehicle while on public roads.

  • The Larson Scanner is named for Glen Larson, Producer of Knight Rider, and other shows. As I was writing up my build notes, I was sorry to read that Glen Larson passed away. The man clearly understood the appeal of blinking, whooshing, glowing lights.

Step 1: Tools and Materials

Materials used:

Arduino UnoR3

LED strip - Adafruit

Rotary Encoder - Sparkfun

Knob - Sparkfun

Encoder Break out Board - Sparkfun

Power Supply - Ebay 12v to 5v converter 3A $7.77

WS2811 chip - I Got mine from ebay (mounted on circuit board) but also available from Adafruit

Three 220 ohm 1/4 watt resistors

Header Pins - Adafruit

Proto board - I recommend using Arduino Shield protoboard board of some type

Connectors - I salvaged mine from old electronics

fuse holder - local auto supply store

fuse - local auto supply store

silicone glue/Waterproofing - local auto supply store

Main power Switch, Toggle switch for +12V - I salvaged mine from an old Printer

Tools used:

solderless Breadboard

power supply

PC

Soldering station

Jumper wires/test leads/temporary connectors

hand tools: screwdriver/knife/pliers/crescent wrench/

Useful references:

Adafruit Uberguide

Adafruit Larson Scanner

Bildr.org Blog - Rotary Encoder tutorial

Adafruit's NeoPixel library on GitHub

Step 2: Build Circuit and Load Code

Breadboard:

Breadboard up the circuit per the schematic and make sure everything works.
I had issues with my WS2811 boards from Ebay. The Data Out, and Data in were reversed on the silkscreen, also the RGB on the silkscreen had the R and G reversed. The circuit was fine, just the label on both of those were reversed.

.

Code Notes:

The chances are really good that you can write much better code than what I have cobbled together. My code runs, it does what I want it to do, and I am not turning it in to a Computer Science Instructor for a grade. I’ll polish it up in version 2.0
(This was my first time with an object oriented language and I am not one to start at the beginning, especially when there is sample code to start from). Shoulders of giants and all that.

To build the code below, I started with Adafruit’s Larson Scanner demo. It ran great right out of the box, but I was not happy with only having the color red.
I loaded the 'Read an Encoder' sample code from bldr.org and combined it with the Adafruit code, then I could read the encoder while the Scanner scanned.
I used those readings to change colors displayed by the LEDs.

Changing the Values in the look up table changes the displayed LED color. When you like the way it looks on the test bench, move the circuit to a permanent proto board and solder it up. It's probably a good idea to then give it another test before installing in your car.

Test Bench Video Yes, the color of the Rotary encoder does change hue to match the LED strip even though it does not necessarily appear that way in the video. I think I need some practice using the white balance on my camera.


Step 3: Code

//From bildr article: http://bildr.org/2012/08/rotary-encoder-arduino/
//and from Adafruit’s Larson Scanner https://learn.adafruit.com/larson-scanner-shades

//You will also need Adafruit’s NeoPixel library installed https://github.com/adafruit/Adafruit_NeoPixel

#include

#define N_LEDS 60

#define PIN 6

Adafruit_NeoPixel strip = Adafruit_NeoPixel(N_LEDS, PIN, NEO_GRB + NEO_KHZ800);

//these pins can not be changed 2/3 are special pins

int encoderPin1 = 2;

int encoderPin2 = 3;

volatile int lastEncoded = 0;

volatile int encoderValue = 0;

long lastencoderValue = 0;

int lastMSB = 0;

int lastLSB = 0;

void setup() {

strip.begin();

int pos = 1, dir = 1; // Position, direction of "eye"

Serial.begin (9600); // for testing encoder

pinMode(encoderPin1, INPUT);

pinMode(encoderPin2, INPUT);

digitalWrite(encoderPin1, HIGH); //turn pullup resistor on

digitalWrite(encoderPin2, HIGH); //turn pullup resistor on

//call updateEncoder() when any high/low changed seen

//on interrupt 0 (pin 2), or interrupt 1 (pin 3)

attachInterrupt(0, updateEncoder, CHANGE);

attachInterrupt(1, updateEncoder, CHANGE);

}

int pos = 1, dir = 1; // Position, direction of "eye"

void loop(){

int count =0;

count = (encoderValue / 4);

// Serial.println(encoderValue); //testing / debugging encoder

Serial.println(count); //testing / debugging encoder

int j;

long colorb = 0;

long colorg = 0;

long colorr =0;

// int count;

colorb = colorb + abs(encoderValue); // blue

colorg = colorb + 2*abs(encoderValue); //green

colorr = colorb + 4*abs(encoderValue); //red

//lookup table for color values 13 sets of 3 colors

int red [13] = { 255,255,255,255,128,0,0,0,0,0,127,255,255};

int red1[13] = { 128,128,204,204,102,0,0,0,0,0,102,204,204};

int red2[13] = { 32,16,153,153,76,0,0,0,0,0,76,153,153};

int green [13] = {255,0,0,0,0,0,127,255,255,255,255,255,127};

int green1[13] = { 128,0,0,0,0,0,102,64,204,128,204,204,102};

int green2[13] = { 32,0,0,0,0,0,76,32,153,16,153,153,76};

int blue [13] = { 255,0,127,255,255,255,255,255,0,0,0,0,0};

int blue1[13] = { 128,0,102,204,204,128,204,32,102,0,0,0,0};

int blue2[13] = { 32,0,76,153,153,16,153,32,76,0,0,0,0};

if (colorb > 255) colorg = colorg ++;

if (colorg >255) colorr = colorr++;

// Draw 5 pixels centered on pos. setPixelColor() will clip any

// pixels off the ends of the strip, we don't need to watch for that.

strip.setPixelColor(0,(red[count]),(green[count]),(blue[count])); // encoder LED (separate WS2811 chip)

strip.setPixelColor(pos - 2,(red2[count]),(green2[count]),(blue2[count])); // red2 green2 blue2 from lookup table

strip.setPixelColor(pos - 1, (red1[count]),(green1[count]),(blue1[count])); // red1 green1 blue1

strip.setPixelColor(pos , (red[count]),(green[count]),(blue[count])); // Center pixel is brightest

strip.setPixelColor(pos + 1, (red1[count]),(green1[count]),(blue1[count])); // red1 green1 blue1

strip.setPixelColor(pos + 2,(red2[count]),(green2[count]),(blue2[count])); // red2 green2 blue2

strip.show();

delay(30);

// Rather than being sneaky and erasing just the tail pixel,

// it's easier to erase it all and draw a new one next time.

for(j=-2; j<= 2; j++) strip.setPixelColor(pos+j, 0);

// Bounce off ends of strip

pos += dir;

if(pos < 2) {

pos = 3;

dir = -dir;

} else if(pos >= strip.numPixels()) {

pos = strip.numPixels() - 2;

dir = -dir;

}

}

void updateEncoder(){

int MSB = digitalRead(encoderPin1); //MSB = most significant bit

int LSB = digitalRead(encoderPin2); //LSB = least significant bit

int encoded = (MSB << 1) |LSB; //converting the 2 pin value to single number

int sum = (lastEncoded << 2) | encoded; //adding it to the previous encoded value

if(sum == 0b1101 || sum == 0b0100 || sum == 0b0010 || sum == 0b1011) encoderValue ++;

if(sum == 0b1110 || sum == 0b0111 || sum == 0b0001 || sum == 0b1000) encoderValue --;

if (encoderValue >55) encoderValue =0; // chaNGED 10-26-14

if (encoderValue <0) encoderValue =55;

lastEncoded = encoded; //store this value for next time

}

Step 4: Installation

In my case, the Scanner is going into a 2010 Ford Focus.
(The fact that this car parked in the driveway at exactly 50000.0 miles was an omen that this car wanted a shiny upgrade, and thought it was entitled to one.)

There was not too much work to the install once the circuit was built and tested on the bench. The LED strip went behind the grill and was secured with the silicone "glue", a dab on the open end sealed the LED strip from the weather. The positive battery terminal had a screw type connection just waiting for the wire to the fuse and power switch. The hardest part was running the wires through the firewall. I went through an existing grommet on the driver’s side, your millage may vary.

Currently everything is connected and working. The plastic dash still needs to be partially removed and the rotary encoder mounted on it, but the temperature has dropped to -11 degrees Fahrenheit. I think it would be a good idea to wait for warmer temperatures before prying and drilling on plastic. The scanner works great as it is anyway.

Step 5: Lessons Learned

  • Use real Arduino shield prototyping shield. The generic proto board just does not fit well, at least not the one I used.
  • Look closely at potential Ebay purchases. the Fifty WS2811 chips I bought were all mounted on one board that had no perforations.
  • Build on solderless proto board first (WS2811 chips were not exactly as marked on the silkscreen I had to reconfigure some connections)
  • In the future, look for parts with breadboard friendly 0.1” pin spacing.
  • Pull extra cable through the firewall for future use. Maybe even shielded twisted pair
  • A heated garage, clean enough to pull a car inside, is a worthy goal

Step 6: Going Further

  • There are 11 GPIO pins left over on this project. This leaves a lot of room for expansion. The downside is both interrupt pins are used for the rotary encoder, I’m sure one could free up at least one of these interrupts with a code rewrite.
  • I built a Larson Scanner page, linked from the Projects page on my website. This is a place I can post my improvements that are not quite ready for an instructable of their own, as well as a place to link to other people's comments / instructables.
  • More than one Row of lights, scanning together, might have more visual impact. One may want to consider airflow through the radiator though.
  • A PIR sensor to trigger the Larson Scanner from an off (or sleeping) state when someone walks by. That would be fun. Maybe trigger a camera at the same time.
  • Add the cool whooshing sound like was used in the TV show.
  • I expect the Instructables crowd to come up with ideas I would never have dreamed of for this project. Please, add yours.