Programmable Headlights on an RC Car

Programmable Headlights on an RC Car

Experimenting with smart LEDs on an RC Car…

These are Adafruit Pixie Chainable Smart LEDs and an Arduino Uno.  On the car I replaced both channel’s servo cables with Y-harnesses.   Plugging one end of each harness back in to the servo/ESC, the other end is used to connect to Arduino PWM input pins.  Reading those values and using that information to  control the LEDs.  Adafruit Pixie LEDs are chained together but individually assignable to any color by the program.  This allows for making turn signals when turning the vehicle and also being able to do other things with the lights when the car is throttled or neutral.  I only have two LEDs in this example, but you could string more than that together.

Source code for the video demo:

/*
  This sketch is for two Smart LEDs on an RC car as programmable headlights.
     - Neutral position = "demon eye" red transition
     - Left turn        = left turn signal
     - Right turn       = right turn signal
     - Throttle         = blue, variable brightness
     - Full throttle    = white flashing

     Author:  John Reed  johnnycarlos@gmail.com
*/

#include "SoftwareSerial.h"
#include "Adafruit_Pixie.h"

#define NUMPIXELS 2 // Number of Pixies in the strip
#define PIXIEPIN  6 // Pin number for SoftwareSerial output
#define UP        1
#define DOWN      2
#define INCREMENT 2
#define OFF       0
#define LEFT_LED  0
#define RIGHT_LED 1
#define BRIGHTNESS     200
#define MAX_BRIGHTNESS 255
#define FLASH_DELAY    100

byte SERVOPIN    = 3;
byte THROTTLEPIN = 5;
int servoPWM;
int throttlePWM;


#define MAX_RED 254
#define MIN_RED 20
int currentRed = 0;

// Servo signal PWM values
int leftThreshold     = 1400;
int rightThreshold    = 1600;
int throttleThreshold = 1550;
int fadeDirection     = UP;

SoftwareSerial pixieSerial(-1, PIXIEPIN);
Adafruit_Pixie strip = Adafruit_Pixie(NUMPIXELS, &pixieSerial);

void setup() {

  pinMode(SERVOPIN,    INPUT);
  pinMode(THROTTLEPIN, INPUT);

  Serial.begin(9600);

  pixieSerial.begin(115200); // Pixie REQUIRES this baud rate

  // brightness is 0 to 255
  strip.setBrightness(BRIGHTNESS);

}

void loop() {

  // Measure servo values and then map them to the lights
  servoPWM    = pulseIn(SERVOPIN, HIGH);
  throttlePWM = pulseIn(THROTTLEPIN, HIGH);

  if(throttlePWM > throttleThreshold){
      whiteDoubleFlash();
  }
  
  if( servoPWM < leftThreshold ){ turnSignal(LEFT_LED); } else if( servoPWM > rightThreshold ){
      turnSignal(RIGHT_LED);
  }
  else{
      demonEyes();
  }
  
}

/*
 * Slow fading red.
 * 
 * Since this is a slow light sequence, I needed to make it interruptable
 * so there isn't a delay changing to another light sequence.  I did this by maintaining the
 * current light value.  Once per loop I inc/dec the current light value(depending on whater it's fading in or out) 
 * and display it.  This gives the loop a chance to decide to do something else.
 * The fade rate is entirely dependent on the speed of the main loop.  If the loop is very busy, for example, demonEyes  
 * wont refresh as often.  Thus, the INCREMENT value can be changed to compensate.
 */
void demonEyes(){
  
    if( fadeDirection == UP ){

        if( currentRed < MAX_RED ){ currentRed += INCREMENT; strip.setBrightness(currentRed); strip.setPixelColor(LEFT_LED, 255, 0, 0); strip.setPixelColor(RIGHT_LED, 255, 0, 0); strip.show(); } else{ fadeDirection = DOWN; } } else { if( currentRed > MIN_RED ){
            currentRed -= INCREMENT;
            strip.setBrightness(currentRed);
            strip.setPixelColor(LEFT_LED, 255, 0, 0);
            strip.setPixelColor(RIGHT_LED, 255, 0, 0);
            strip.show();

        }
        else{
          fadeDirection = UP;
        }
    }

}

/*
 * Flashes amber once.  Takes a NUMPIXELS(the LED number in the chain) that will flash.
 */
void turnSignal(int ledNum){

    int otherLed;
    if( ledNum == 0 ){
        otherLed = 1;
    }
    else{
        otherLed = 0;
    }

    strip.setBrightness(BRIGHTNESS);
    strip.setPixelColor(ledNum, 255, 125, 0);
    strip.setPixelColor(otherLed, 0, 0, 0);
    strip.show();
    delay(500);
    
    strip.setBrightness(OFF);
    strip.show();
    delay(300);
  
}

/*
 * Bright white double flash.
 */
void whiteDoubleFlash(){

    // Loop twice.  Two flashes
    for( int i = 0; i < 2; i++ ){
        strip.setBrightness(MAX_BRIGHTNESS);
        strip.setPixelColor(LEFT_LED, 255, 255, 255);
        strip.setPixelColor(RIGHT_LED, 255, 255, 255);
        strip.show();
        delay(FLASH_DELAY);

        strip.setBrightness(OFF);
        strip.show();
        delay(FLASH_DELAY);
    }
    
}

Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.