//rc Lighting Controller
//For use with ws2812 and bright high powered leds.
//jkw feb 16 2018
//ch1 = throttle from rc radio via splitter cable.
//ch2 = steering from rc radio via splitter cable.
//ch3 = right side button, for lights on / off.
#include <Breathe.h>
Breathe Breathe;
#include <Adafruit_NeoPixel.h>
#include "WS2812_Definitions.h"
#define LIBRARYUNDERTEST "PinChangeInt"
#include <PinChangeInt.h>
#define BAT_VOLTS_SCALE 0.00385 // 0.00785
#define AVG_NUM 8
#define PIN 7 // yellow wire
#define LED_COUNT 4
int LightsOn = 0;
int FlasherOn = 0;
int led1 = 6; // orange wire - Brakelights - PWM
int led2 = 8; // brown wire Tail Headlights - non pwm
int led3 = 9; // blue wire - left pwm
int led4 = 10; // purple wire Right pwm
int ch1 = 4;
int ch2 = 3; //pin assignment input
int ch3 = 5; //pin assignment input
int batV = A0; // Battery measurement disabled.. voltage divider needs to be tuned.
volatile int THROTTLE_IN_PIN = 3;
uint32_t ulThrottleStart;
uint32_t ulBrakeStart;
long ulBrake;
long ulBrakeOld;
int dbt; //throttle
int dbtH;
int dbtL;
int dbs; //steering deadband center
int dbsH;
int dbsL;
int dbb; //button
int taps = 0;
int radio;
long braketime = 0;
Adafruit_NeoPixel leds = Adafruit_NeoPixel(LED_COUNT, PIN, NEO_GRB + NEO_KHZ800);
volatile uint16_t unThrottleInShared;
void setup() { //not much to see here, run once and go away...
Serial.begin (9600);
pinMode (PIN, OUTPUT);
dbt = pulseIn (ch2, HIGH);
dbtL = (dbt * .93); //if the center position isn't wide enough try adjusting
dbtH = (dbt * 1.03); // these constants to .9 and 1.1
dbs = pulseIn (ch1, HIGH);
dbsL = (dbs * .93); //if the center position isn't wide enough try adjusting
dbsH = (dbs * 1.03); // these constants to .9 and 1.1
leds.begin(); // Call this to start up the LED leds.
PCintPort::attachInterrupt(THROTTLE_IN_PIN, calcThrottle,CHANGE);
pinMode(led1, OUTPUT);
pinMode(led2, OUTPUT);
pinMode(led3, OUTPUT);
pinMode(led4, OUTPUT);
digitalWrite(led2, LOW);
}
void loop() {
readradio();
directionDetection();
Detectreverse();
output();
}
void calcThrottle()
{
taps = taps + 1;
if (taps > 2) {
taps = 2;
}
if(digitalRead(THROTTLE_IN_PIN) == HIGH)
{
ulThrottleStart = micros();
}
else
{
dbt = (uint16_t)(micros() - ulThrottleStart);
}
}
void Detectreverse() {
if (radio != 0 && dbt <= 1410) { //wev'e gone below count up taps
ulBrakeStart = millis();
}
else if (radio != 0 && dbt >= 1420) { //weve gone over count down
ulBrake = (ulBrake + ((uint16_t)(millis() - ulBrakeStart)));
braketime = (ulBrake + ulBrakeOld);
ulBrakeOld = ulBrake;
ulBrake = 0;
}
}
void directionDetection() {
if ( radio == 0) {
Serial.println("sleeping");
dbs = 1500;
dbt = 1500;
dbb = 0;
breathAll();
}
if (radio != 0 && dbt <= dbtL) {
if (taps >= 2 && braketime < 2000) {
if (dbs >= dbsH) { // blink while moving forward.
Blink(2,3,255,215,0,50);
Serial.println("Backing Right ");
}
if (dbs <= dbsL) {
Blink(0,1,255,215,0,50);
Serial.println("Backing Left ");
}
Serial.println("Reversing");
analogWrite(led1, 255);
leds.setPixelColor(0,255,0,0);
leds.setPixelColor(3,255,0,0);
leds.show();
}
else if ( taps <= 1 || braketime > 2000) {
if (dbs >= dbsH) { // blink while moving forward.
Blink(2,3,255,215,0,50);
Serial.println("Braking Right ");
}
if (dbs <= dbsL) {
Blink(0,1,255,215,0,50);
Serial.println("Braking Left ");
}
taps = taps -1;
Serial.println("Braking ");
analogWrite(led1, 255);
leds.setPixelColor(0,255,0,0);
leds.setPixelColor(3,255,0,0);
leds.show();
}
}
//if (radio != 0 && dbt >= 1570 && LightsOn == 0) {
if (radio != 0 && dbt >= 1570) {
int color = map(dbt, 1570, 2000, 0, 255);
Serial.println("Driving ");
if (LightsOn == 1) {
analogWrite(led1, 30);
}
else if (LightsOn == 0) {
analogWrite(led1, 0);
}
leds.setPixelColor(1,color+15,0,color);
leds.setPixelColor(2,color+15,0,color);
if (dbs >= dbsH) { // blink while moving forward.
Blink(2,3,255,211,0,50);
blinkright();
Serial.println("Driving Right ");
}
if (dbs <= dbsL) {
Blink(0,1,255,211,0,50);
blinkleft();
Serial.println("Driving Left ");
}
leds.show();
}
if (radio != 0 && dbs >= dbsH) { // blinkers
if ( dbb > 1600 && FlasherOn == 0) {
LightsOn = 1;
}
else if (dbb < 1400) {
LightsOn = 0;
}
Blink(2,3,255,211,0,50);
Serial.println("Right ");
}
if (radio != 0 && dbs <= dbsL) {
if ( dbb > 1600 && LightsOn == 0) {
FlasherOn = 1;
}
else if (dbb < 1400) {
FlasherOn = 0;
}
Blink(0,1,255,211,0,50);
Serial.println("Left ");
}
if (dbb >1600) { // aux button,,, here come the cops!
if (LightsOn == 1 ) {
digitalWrite(led2, HIGH);
analogWrite(led1, 30);
analogWrite(led3, 30);
analogWrite(led4, 30);
leds.setPixelColor(1,255,255,255);
leds.setPixelColor(2,255,255,255);
leds.setPixelColor(0,60,0,0);
leds.setPixelColor(3,60,0,0);
leds.show();
}
if (FlasherOn == 1) {
Sparkle(0, 0, 255, 25);
delay(3);
Sparkle(255, 0, 0, 25);
}
}
if (radio != 0 && dbt > dbtL && dbt < dbtH && dbs < dbsH && dbs > dbsL ) {
if ( LightsOn == 0 ) {
digitalWrite(led2, LOW);
analogWrite(led1, 0);
analogWrite(led3, 0);
analogWrite(led4, 0);
leds.setPixelColor(0,0,0,0);
leds.setPixelColor(1,0,0,0);
leds.setPixelColor(2,0,0,0);
leds.setPixelColor(3,0,0,0);
}
Serial.println("Stop ");
leds.setPixelColor(0,0,0,0);
leds.setPixelColor(3,0,0,0);
leds.show();
}
if ( dbb < 1410 ) { // aux button off,,, ts cool now!
LightsOn = 0;
FlasherOn = 0;
}
}
void readradio() {
radio = (pulseIn (3, HIGH, 50000)); // if new packet received from radio in 50 ms 25 was too fast for the mini.
//Serial.println(radio);
if ( radio != 0)
{
dbs = pulseIn (ch1, HIGH);
calcThrottle();
dbb = pulseIn (ch3, HIGH);
delay(500);
}
}
void Sparkle(byte red, byte green, byte blue, int SpeedDelay) {
int Pixel = random(LED_COUNT);
leds.setPixelColor(Pixel,red,green,blue);
leds.show();
delay(SpeedDelay);
leds.setPixelColor(Pixel,0,0,0);
leds.show();
}
void Blink(int Pixel, byte red, byte green, byte blue, int SpeedDelay) {
leds.setPixelColor(Pixel,red,green,blue);
leds.show();
delay(SpeedDelay);
leds.setPixelColor(Pixel,0,0,0);
leds.show();
}
void output() {
Serial.print("dbs ");
Serial.println(dbs);
Serial.print("dbt ");
Serial.println(dbt);
Serial.print("dbb ");
Serial.println(dbb);
}
void blinkleft() {
analogWrite(led3, 255);
delay(250);
Serial.println("Left ");
if (LightsOn == 1 ) {
analogWrite(led3, 30);
}
else
analogWrite(led3, 0);
}
void blinkright() {
analogWrite(led4, 255);
delay(250);
Serial.println("Right ");
if (LightsOn == 1 ) {
analogWrite(led4, 30);
}
else
analogWrite(led4, 0);
}
void Blink(int Pixel1, int Pixel2, byte red, byte green, byte blue, int SpeedDelay) {
leds.setPixelColor(Pixel1,red,green,blue);
leds.setPixelColor(Pixel2,red,green,blue);
leds.show();
delay(SpeedDelay);
leds.setPixelColor(Pixel1,0,0,0);
leds.setPixelColor(Pixel2,0,0,0);
leds.show();
}
// Sets all LEDs to off, but DOES NOT update the display;
// call leds.show() to actually turn them off after this.
void clearLEDs()
{
for (int i=0; i<LED_COUNT; i++)
{
leds.setPixelColor(i, 0);
}
}
int read_adc(int channel) {
int sum = 0;
int temp;
int i;
for (i = 0; i < AVG_NUM; i++) { // loop through reading raw adc values AVG_NUM number of times
temp = analogRead(channel); // read the input pin
sum += temp; // store sum for averaging
delayMicroseconds(50); // pauses for 50 microseconds
}
return (sum / AVG_NUM); // divide sum by AVG_NUM to get average and return it
}
void breathAll() {
for (int i; i < 225 ; i++) {
for(int j=0; j<leds.numPixels(); j++) {
leds.setPixelColor(j, leds.Color(i+15,i,0)); // yellow with a little extra red to make it warmer
}
leds.show();
delay(2);
}
for (int i = 225; i > 0; i--) {
for(int j=0; j<leds.numPixels(); j++) {
leds.setPixelColor(j, leds.Color(i+15,i,0));
}
leds.show();
delay(4);
}
}
Comments