Larson Scanner using Arduino

First, there are a lot of LED back-and-forth, running lights jobs out there.
A "Larson scanner" needs a trail of dimmer lights following the leading light.
Whether he was the inventor I'm not sure, but when Glen Larson did these for Battlestar Galactica (Cylons) and Knight Rider (KITT), he used light bulbs. The bulbs' incandescence made for the trailing effect.  But LEDs go on/off rapidly, there's no comparative incandescence when they go off, no gradual fade out.

So - how could that trailing tail be accomplished with LEDs?
Whip out your Arduino?  Good start, but still.
Use the PWM pins?  There are only six.
Charlieplex?  Stop already.
Glom some "library"?  Not me.
Off-board circuitry, something MAX-blah-blah?  Totally unnecessary.

I worked it out with 10 positions.
I didn't use any PWM pins as such, no libraries, or any of that - just a stock Arduino with 10 LEDs and 10 resistors.
I used a "lightbar" because it was handy, made for a small footprint.  T1 LEDs could fit within the confines of a small protoboard or a "proto-shield".

The Arduino paradigm focusses on digitalWrites, but that makes for a lot of flicker.  For speed, the key is "Port Manipulation", poking (POKE address, value - C64 BASIC) the PORTB and PORTD registers and getting the data out in parallel.  In this case, it's two POKEs, the PORTB chunk and the PORTD chunk.

I arranged an array of "frames" composed of 12 words each, bits 2 - 11 correspond to Digital pins.
In the following examples, "Frame 1" begins with the leading LED in bit 7 and in "Frame 2" it's in bit 8.

//                             11
//                             1098765432    
const word dimbits[] = { 0b0000000011111100, // frame 1
                         0b0000000011111000,
                         0b0000000011110000, 
                         0b0000000011100000, 
                         0b0000000011000000, 
                         0b0000000010000000, 
                         0b0000000010000000, 
                         0b0000000010000000, 
                         0b0000000000000000,
                         0b0000000000000000,
                         0b0000000000000000,
                         0b0000000000000000,
//                             1098765432                                 
                         0b0000000111111000, // frame 2
                         0b0000000111110000,
                         0b0000000111100000, 
                         0b0000000111000000, 
                         0b0000000110000000, 
                         0b0000000100000000, 
                         0b0000000100000000, 
                         0b0000000100000000, 
                         0b0000000000000000,
                         0b0000000000000000,
                         0b0000000000000000,
                         0b0000000000000000,

The brighter an LED is supposed to be, the greater the number of times it shows up in a frame's words.

In the sketch, each word gets read and split into two bytes that are written to ("POKEd" into) their respective port registers.  The sketch grabs each line at machine speed, it strafes.
The variable times_out sets the speed, it's the number of times that all 12 lines in the "frame" get read and outputted (put out?).
In the demo, times_out = 7500 makes for a leisurely procession, but 100 practically presents a solid bar and 100000 is agonisingly slow.

Sorry if it's a little blurry, but I think it's simple enough to get it together and put it together, upload the sketch and enjoy.



//
// PORTDB_larsen2ways
// 
// goes both ways: Back AND Forth  :)

// 
//                             11
//                             1098765432    
const word dimbits[] = { 0b0000000011111100, // frame 1
                         0b0000000011111000,
                         0b0000000011110000, 
                         0b0000000011100000, 
                         0b0000000011000000, 
                         0b0000000010000000, 
                         0b0000000010000000, 
                         0b0000000010000000, 
                         0b0000000000000000,
                         0b0000000000000000,
                         0b0000000000000000,
                         0b0000000000000000,
//                             1098765432                                 
                         0b0000000111111000, // frame 2
                         0b0000000111110000,
                         0b0000000111100000, 
                         0b0000000111000000, 
                         0b0000000110000000, 
                         0b0000000100000000, 
                         0b0000000100000000, 
                         0b0000000100000000, 
                         0b0000000000000000,
                         0b0000000000000000,
                         0b0000000000000000,
                         0b0000000000000000,
//                             1098765432                                 
                         0b0000001111110000, // frame 3
                         0b0000001111100000,
                         0b0000001111000000, 
                         0b0000001110000000, 
                         0b0000001100000000, 
                         0b0000001000000000, 
                         0b0000001000000000, 
                         0b0000001000000000, 
                         0b0000000000000000,
                         0b0000000000000000,
                         0b0000000000000000,
                         0b0000000000000000,
//                             1098765432                                 
                         0b0000011111100000, // frame 4
                         0b0000011111000000,
                         0b0000011110000000, 
                         0b0000011100000000, 
                         0b0000011000000000, 
                         0b0000010000000000, 
                         0b0000010000000000, 
                         0b0000010000000000, 
                         0b0000000000000000,
                         0b0000000000000000,
                         0b0000000000000000,
                         0b0000000000000000,
//                             1098765432                                 
                         0b0000111111000000, // frame 5 ****
                         0b0000111110000000,
                         0b0000111100000000, 
                         0b0000111000000000, 
                         0b0000110000000000, 
                         0b0000100000000000, 
                         0b0000100000000000, 
                         0b0000100000000000, 
                         0b0000000000000000,
                         0b0000000000000000,
                         0b0000000000000000,
                         0b0000000000000000,
//                             1098765432                                 
                         0b0000111110000000, // frame 6
                         0b0000111100000000,
                         0b0000111000000000, 
                         0b0000110000000000, 
                         0b0000110000000000, 
                         0b0000010000000000, 
                         0b0000010000000000, 
                         0b0000010000000000, 
                         0b0000000000000000,
                         0b0000000000000000,
                         0b0000000000000000,
                         0b0000000000000000,
//                             1098765432                                 
                         0b0000111100000000, // frame 7
                         0b0000111000000000,
                         0b0000111000000000, 
                         0b0000111000000000, 
                         0b0000011000000000, 
                         0b0000001000000000, 
                         0b0000001000000000, 
                         0b0000001000000000, 
                         0b0000000000000000,
                         0b0000000000000000,
                         0b0000000000000000,
                         0b0000000000000000,
//                             1098765432                                 
                         0b0000111100000000, // frame 8
                         0b0000111100000000,
                         0b0000111100000000, 
                         0b0000011100000000, 
                         0b0000001100000000, 
                         0b0000000100000000, 
                         0b0000000100000000, 
                         0b0000000100000000, 
                         0b0000000000000000,
                         0b0000000000000000,
                         0b0000000000000000,
                         0b0000000000000000,
//                             1098765432                                 
                         0b0000111110000000, // frame 9
                         0b0000111110000000,
                         0b0000011110000000, 
                         0b0000001110000000, 
                         0b0000000110000000, 
                         0b0000000010000000, 
                         0b0000000010000000, 
                         0b0000000010000000, 
                         0b0000000000000000,
                         0b0000000000000000,
                         0b0000000000000000,
                         0b0000000000000000,
//                             1098765432                                 
                         0b0000111111000000, // frame 10
                         0b0000011111000000,
                         0b0000001111000000, 
                         0b0000000111000000, 
                         0b0000000011000000, 
                         0b0000000001000000, 
                         0b0000000001000000, 
                         0b0000000001000000, 
                         0b0000000000000000,
                         0b0000000000000000,
                         0b0000000000000000,
                         0b0000000000000000,
//                             1098765432                                 
                         0b0000011111100000, // frame 11
                         0b0000001111100000,
                         0b0000000111100000, 
                         0b0000000011100000, 
                         0b0000000001100000, 
                         0b0000000000100000, 
                         0b0000000000100000, 
                         0b0000000000100000, 
                         0b0000000000000000,
                         0b0000000000000000,
                         0b0000000000000000,
                         0b0000000000000000,
//                             1098765432                              
                         0b0000001111110000, // frame 12
                         0b0000000111110000,
                         0b0000000011110000, 
                         0b0000000001110000, 
                         0b0000000000110000, 
                         0b0000000000010000, 
                         0b0000000000010000, 
                         0b0000000000010000, 
                         0b0000000000000000,
                         0b0000000000000000,
                         0b0000000000000000,
                         0b0000000000000000,
//                             1098765432                              
                         0b0000000111111000, // frame 13
                         0b0000000011111000,
                         0b0000000001111000, 
                         0b0000000000111000, 
                         0b0000000000011000, 
                         0b0000000000001000, 
                         0b0000000000001000, 
                         0b0000000000001000, 
                         0b0000000000000000,
                         0b0000000000000000,
                         0b0000000000000000,
                         0b0000000000000000,
//                             1098765432                              
                         0b0000000011111100, // frame 14 ***
                         0b0000000001111100,
                         0b0000000000111100, 
                         0b0000000000011100, 
                         0b0000000000001100, 
                         0b0000000000000100, 
                         0b0000000000000100, 
                         0b0000000000000100, 
                         0b0000000000000000,
                         0b0000000000000000,
                         0b0000000000000000,
                         0b0000000000000000, 
//                             1098765432                              
                         0b0000000001111100, // frame 15
                         0b0000000000111100,
                         0b0000000000011100, 
                         0b0000000000001100, 
                         0b0000000000001100, 
                         0b0000000000001100, 
                         0b0000000000001000, 
                         0b0000000000001000, 
                         0b0000000000000000,
                         0b0000000000000000,
                         0b0000000000000000,
                         0b0000000000000000, 
//                             1098765432                              
                         0b0000000000111100, // frame 16
                         0b0000000000011100,
                         0b0000000000011100, 
                         0b0000000000011100, 
                         0b0000000000011000, 
                         0b0000000000010000, 
                         0b0000000000010000, 
                         0b0000000000010000, 
                         0b0000000000000000,
                         0b0000000000000000,
                         0b0000000000000000,
                         0b0000000000000000,
//                             1098765432                              
                         0b0000000000111100, // frame 17
                         0b0000000000111100,
                         0b0000000000111100, 
                         0b0000000000111000, 
                         0b0000000000110000, 
                         0b0000000000100000, 
                         0b0000000000100000, 
                         0b0000000000100000, 
                         0b0000000000000000,
                         0b0000000000000000,
                         0b0000000000000000,
                         0b0000000000000000,
//                             1098765432                              
                         0b0000000001111100, // frame 18
                         0b0000000001111100,
                         0b0000000001111000, 
                         0b0000000001110000, 
                         0b0000000001100000, 
                         0b0000000001000000, 
                         0b0000000001000000, 
                         0b0000000001000000, 
                         0b0000000000000000,
                         0b0000000000000000,
                         0b0000000000000000,
                         0b0000000000000000};                         
                         
unsigned long duration = 0;
unsigned long times_out = 7500;  // frame's time out "speed"
                                 // 500 for way fast
                                 // 50000 for way slow
                        
int idx;
byte framepointer = 0;

void setup ()
{
  //pinMode(13,OUTPUT);
  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);
  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);
  pinMode(10, OUTPUT);
  pinMode(11, OUTPUT);
  //PORTD &= 0b00000011;
  
}
void loop ()
{
  for (framepointer = 0; framepointer < 216; framepointer = (framepointer + 12))
  // 0-11,12-33,24-35,36-47,48-59,60-71,72-83,84-95,96-107,
  // 108-119,120-131,132-143,144-155,156-167,168-179,
  // 180-191,192-203,204-215,216
  {
    for(duration=0; duration<times_out; duration++)
    // times_out is the number of
    // frame repetitions
    {
      for(idx = framepointer; idx < (framepointer + 12); idx++)
      {
        commitPORTs();
      }
    }
  }
  framepointer = 0;
  //delay(500);
}

void commitPORTs ()
{
  PORTD = dimbits[idx];
  PORTB = dimbits[idx]/256;
}
    
22 DEC 2014 -- Just a note that Glen Larson passed away, 14 NOV 2014. Thanks, Glen, for the inspiration.

No comments:

Post a Comment