Created
January 29, 2017 19:43
-
-
Save tlorens/ad41a61dc885c2112fea987a98e10d31 to your computer and use it in GitHub Desktop.
Arduino Code for "Larson Scan" Aka "Knight Rider" turn signals.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Author: Timothy Lorens <[email protected]> | |
* 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); | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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);
/**
*/
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);
}
/**
*/
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);
}
}
}
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);
}
}
}
// 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);
}
}