Skip to content

Instantly share code, notes, and snippets.

@tlorens
Created January 29, 2017 19:43
Show Gist options
  • Save tlorens/ad41a61dc885c2112fea987a98e10d31 to your computer and use it in GitHub Desktop.
Save tlorens/ad41a61dc885c2112fea987a98e10d31 to your computer and use it in GitHub Desktop.
Arduino Code for "Larson Scan" Aka "Knight Rider" turn signals.
/**
* Author: Timothy Lorens <tlorens@cyberdyne.org>
* Date: Jan 2016
* Larson scan turn signal code for Arduino
*
*/
#include <Adafruit_NeoPixel.h>
#define LeftSignal A5
#define RightSignal A4
#define PIN 8
#define BRIGHTNESS 255
#define NUM_PIXELS 24
Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_PIXELS, PIN, NEO_GRB + NEO_KHZ800);
int LeftBlinkerState = 0;
int RightBlinkerState = 0;
int runLightState = 0;
int AMBER = strip.Color(255, 130, 0);
int OFF = strip.Color(0, 0, 0);
/**
* Setup pins and do fancy start-up sequence.
* Red/White/Blue Larson scanner.
*/
void setup() {
pinMode(LeftSignal, INPUT);
pinMode(RightSignal, INPUT);
strip.begin();
strip.setBrightness(BRIGHTNESS);
strip.show();
knightRider(1, 16, 2, 0xFF0000);
knightRider(1, 16, 2, 0xFFFFFF);
knightRider(1, 16, 2, 0x0000FF);
}
/**
* Main loop
*/
void loop() {
// Read the state of the left turn-signal voltage
LeftBlinkerState = analogRead(LeftSignal);
float LeftVoltage = LeftBlinkerState * (5.0 / 1023.0);
// Read the state of the right turn-signal voltage
RightBlinkerState = analogRead(RightSignal);
float RightVoltage = RightBlinkerState * (5.0 / 1023.0);
// If we have voltage clear the strip from 'run light state'
// and start Larson scan to the left.
if (LeftVoltage > 4.99) {
runLightState = 0;
clearStrip();
leftTurn();
delay(10);
}
// If we have voltage clear the strip from 'run light state'
// and start Larson scan to the right.
if (RightVoltage > 4.99 ) {
runLightState = 0;
clearStrip();
rightTurn();
delay(10);
}
// If there's < 3v (capasitor drain) revert to run light state.
if (RightVoltage < 3.0 && LeftVoltage < 3.0) {
runLight();
}
delay(200);
}
// Larson scan for right turn.
void rightTurn() {
strip.setBrightness(BRIGHTNESS);
for(uint16_t i = NUM_PIXELS / 2; i < NUM_PIXELS; i++) {
strip.setPixelColor(i, AMBER);
strip.show();
delay(10);
}
delay(300);
for(uint16_t i = NUM_PIXELS / 2; i < NUM_PIXELS; i++) {
strip.setPixelColor(i, OFF);
strip.show();
delay(10);
}
delay(150);
}
// Larson scan for left turn.
void leftTurn() {
strip.setBrightness(BRIGHTNESS);
for(int16_t i = (NUM_PIXELS-1) /2 ; i > -1; i--) {
strip.setPixelColor(i, AMBER);
strip.show();
delay(10);
}
delay(300);
for(int16_t i = NUM_PIXELS / 2; i > -1; i--) {
strip.setPixelColor(i, OFF);
strip.show();
delay(10);
}
delay(150);
}
// Helper function to make all LEDs color (c)
void all(uint32_t c) {
for(uint16_t i=0; i < strip.numPixels(); i++) {
strip.setPixelColor(i, c);
}
strip.show();
}
// Dim red, run-light state.
void runLight()
{
if (runLightState == 0) {
strip.setBrightness(BRIGHTNESS / 12);
spread(15, 0xFF0000);
runLightState = 1;
all(0xFF0000);
strip.show();
}
}
// Function for larson scan.
void knightRider(uint16_t cycles, uint16_t speed, uint8_t width, uint32_t color) {
uint32_t old_val[NUM_PIXELS]; // up to 256 lights!
for(int i = 0; i < cycles; i++){
for (int count = 1; count < NUM_PIXELS; count++) {
strip.setPixelColor(count, color);
old_val[count] = color;
for(int x = count; x>0; x--) {
old_val[x-1] = dimColor(old_val[x-1], width);
strip.setPixelColor(x-1, old_val[x-1]);
}
strip.show();
delay(speed);
}
for (int count = NUM_PIXELS-1; count>=0; count--) {
strip.setPixelColor(count, color);
old_val[count] = color;
for(int x = count; x<=NUM_PIXELS ;x++) {
old_val[x-1] = dimColor(old_val[x-1], width);
strip.setPixelColor(x+1, old_val[x+1]);
}
strip.show();
delay(speed);
}
}
}
// Set all LEDs to off/black.
void clearStrip() {
for( int i = 0; i<NUM_PIXELS; i++){
strip.setPixelColor(i, 0x000000);
strip.show();
}
}
// Dim a color across a width of leds.
uint32_t dimColor(uint32_t color, uint8_t width) {
return (((color&0xFF0000)/width)&0xFF0000) + (((color&0x00FF00)/width)&0x00FF00) + (((color&0x0000FF)/width)&0x0000FF);
}
// Function to light LEDS from the center one at a time (spreading).
void spread(uint16_t speed, uint32_t color) {
clearStrip();
delay(300);
int center = NUM_PIXELS / 2;
for(int x = 0; x < center; x++) {
strip.setPixelColor(center + x, color);
strip.setPixelColor(center + (x*-1), color);
strip.show();
delay(speed);
}
}
@Mitesh80000
Copy link

An error is coming

@OmarRayes
Copy link

hello,
I have updated your code to be used with 2 e.a independent ws2812b strips.
i did not have the chance to test it.
is my update ok or need more
thank you
Omar

/**

#include <Adafruit_NeoPixel.h>

#define LeftSignal 1
#define RightSignal 2
#define BRIGHTNESS 255
#define NUM_PIXELS 32

Adafruit_NeoPixel strip_R = Adafruit_NeoPixel(32, 3, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel strip_L = Adafruit_NeoPixel(32, 4, NEO_GRB + NEO_KHZ800);

int LeftBlinkerState = 0;
int RightBlinkerState = 0;
int runLightState = 0;
int AMBER_L = strip_L.Color(255, 130, 0);
int OFF_L = strip_L.Color(0, 0, 0);
int AMBER_R = strip_R.Color(255, 130, 0);
int OFF_R = strip_R.Color(0, 0, 0);
/**

  • Setup pins and do fancy start-up sequence.
  • Red/White/Blue Larson scanner.
    */
    void setup() {
    pinMode(LeftSignal, INPUT);
    pinMode(RightSignal, INPUT);
    strip_L.begin();
    strip_L.setBrightness(BRIGHTNESS);
    strip_L.show();
    strip_R.begin();
    strip_R.setBrightness(BRIGHTNESS);
    strip_R.show();
    knightRider(1, 16, 2, 0xFF0000);
    knightRider(1, 16, 2, 0xFFFFFF);
    knightRider(1, 16, 2, 0x0000FF);
    }

/**

  • Main loop
    */
    void loop() {
    // Read the state of the left turn-signal voltage
    LeftBlinkerState = analogRead(LeftSignal);
    float LeftVoltage = LeftBlinkerState * (5.0 / 1023.0);

// Read the state of the right turn-signal voltage
RightBlinkerState = analogRead(RightSignal);
float RightVoltage = RightBlinkerState * (5.0 / 1023.0);

// If we have voltage clear the strip from 'run light state'
// and start Larson scan to the left.
if (LeftVoltage > 4 ) {
runLightState = 0;
clearStrip_L();
leftTurn();
delay(10);
}

// If we have voltage clear the strip from 'run light state'
// and start Larson scan to the right.
if (RightVoltage > 4 ) {
runLightState = 0;
clearStrip_R();
rightTurn();
delay(10);
}

// If there's < 2.0 v (capasitor drain) revert to run light state.
if (RightVoltage < 2.0 && LeftVoltage < 2.0) {
runLight();
}
delay(200);
}

// Larson scan for right turn.
void rightTurn() {
strip_R.setBrightness(BRIGHTNESS);
for(uint16_t i = NUM_PIXELS/33 ; i < NUM_PIXELS; i++) {
strip_R.setPixelColor(i, AMBER_R);
strip_R.show();
delay(10);
}

delay(10);

for(uint16_t i = NUM_PIXELS/33 ; i < NUM_PIXELS; i++) {
strip_R.setPixelColor(i, OFF_R);
strip_R.show();
delay(10);
}
delay(10);
}

// Larson scan for left turn.
void leftTurn() {
strip_L.setBrightness(BRIGHTNESS);
for(int16_t i = NUM_PIXELS ; i < NUM_PIXELS ; i++) {
strip_L.setPixelColor(i, AMBER_L);
strip_L.show();
delay(10);
}

delay(10);

for(int16_t i = NUM_PIXELS ; i < NUM_PIXELS ; i++) {
strip_L.setPixelColor(i, OFF_L);
strip_L.show();
delay(10);
}
delay(10);
}

// Helper function to make all LEDs color (c)
void all(uint32_t c) {
for(uint16_t i=0; i < strip_L.numPixels(); i++) {
strip_L.setPixelColor(i, c);
}
strip_L.show();
}
void all_L(uint32_t c) {
for(uint16_t i=0; i < strip_R.numPixels(); i++) {
strip_R.setPixelColor(i, c);
}
strip_R.show();
}

// Dim red, run-light state.
void runLight()
{
if (runLightState == 0) {
strip_L.setBrightness(BRIGHTNESS / 2);
spread(15, 0xFF0000);
runLightState = 1;
all(0xFF0000);
strip_L.show();
}
}
void runLight_R()
{
if (runLightState == 0) {
strip_R.setBrightness(BRIGHTNESS / 2);
spread(15, 0xFF0000);
runLightState = 1;
all(0xFF0000);
strip_R.show();
}
}

// Function for larson scan.
void knightRider(uint16_t cycles, uint16_t speed, uint8_t width, uint32_t color) {
uint32_t old_val[NUM_PIXELS]; // up to 256 lights!

for(int i = 0; i < cycles; i++){
for (int count = 1; count < NUM_PIXELS; count++) {
strip_L.setPixelColor(count, color);
old_val[count] = color;
for(int x = count; x>0; x--) {
old_val[x-1] = dimColor_L(old_val[x-1], width);
strip_L.setPixelColor(x-1, old_val[x-1]);
}
strip_L.show();
delay(speed);
}

for (int count = NUM_PIXELS-1; count>=0; count--) {
  strip_L.setPixelColor(count, color);
  old_val[count] = color;
  for(int x = count; x<=NUM_PIXELS ;x++) {
    old_val[x-1] = dimColor_L(old_val[x-1], width);
    strip_L.setPixelColor(x+1, old_val[x+1]);
  }
  strip_L.show();
  delay(speed);
}

}
}

void knightRider_R(uint16_t cycles, uint16_t speed, uint8_t width, uint32_t color) {
uint32_t old_val[NUM_PIXELS]; // up to 256 lights!

for(int i = 0; i < cycles; i++){
for (int count = 1; count < NUM_PIXELS; count++) {
strip_R.setPixelColor(count, color);
old_val[count] = color;
for(int x = count; x>0; x--) {
old_val[x-1] = dimColor_L(old_val[x-1], width);
strip_R.setPixelColor(x-1, old_val[x-1]);
}
strip_R.show();
delay(speed);
}

for (int count = NUM_PIXELS-1; count>=0; count--) {
  strip_R.setPixelColor(count, color);
  old_val[count] = color;
  for(int x = count; x<=NUM_PIXELS ;x++) {
    old_val[x-1] = dimColor_R(old_val[x-1], width);
    strip_R.setPixelColor(x+1, old_val[x+1]);
  }
  strip_R.show();
  delay(speed);
}

}
}
// Set all LEDs to off/black.
void clearStrip_L() {
for( int i = 0; i<NUM_PIXELS; i++){
strip_L.setPixelColor(i, 0x000000);
strip_L.show();
}
}

void clearStrip_R() {
for( int i = 0; i<NUM_PIXELS; i++){
strip_R.setPixelColor(i, 0x000000);
strip_R.show();
}
}

// Dim a color across a width of leds.
uint32_t dimColor_L(uint32_t color, uint8_t width) {
return (((color&0xFF0000)/width)&0xFF0000) + (((color&0x00FF00)/width)&0x00FF00) + (((color&0x0000FF)/width)&0x0000FF);
}

// Function to light LEDS from the center one at a time (spreading).
void spread(uint16_t speed, uint32_t color) {
clearStrip_L();
delay(300);
int center = NUM_PIXELS ;
for(int x = 0; x < center; x++) {
strip_L.setPixelColor(center + x, color);
strip_L.setPixelColor(center + (x*-1), color);
strip_L.show();
delay(speed);
}
}

uint32_t dimColor_R(uint32_t color, uint8_t width) {
return (((color&0xFF0000)/width)&0xFF0000) + (((color&0x00FF00)/width)&0x00FF00) + (((color&0x0000FF)/width)&0x0000FF);
}

// Function to light LEDS from the center one at a time (spreading).
void spread_R(uint16_t speed, uint32_t color) {
clearStrip_R();
delay(300);
int center = NUM_PIXELS / 33 ;
for(int x = 0; x < center; x++) {
strip_R.setPixelColor(center + x, color);
strip_R.setPixelColor(center + (x*-1), color);
strip_R.show();
delay(speed);
}
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment