/*
This program is to control multiple LEDs, to bring some fancy effects to a Imperial Raider
The core idea is:
BlinkLed 1 - 3: run a fiber optic to these leds, and connect these to the sides of the raider, to allow these lights to twinkle/fade
SolidLed1: this is for a cockpit LED, can either be a sold "on" led, or can use a flicker LED to make this animated
LaserLed1: connect fiberoptics from here to each gun, this will have a tripple fire effect on button press
FadeLed: this is for the engines, and will cause the engines to fade on and off
Use 100 (2.0v forward) - 130 (2.2v forward) ohm resistors with this setup to avoid burning out the LEDs
*/
// Pin Definitions
const uint8_t blinkLed1 = 3;
const uint8_t blinkLed2 = 5;
const uint8_t blinkLed3 = 6;
const uint8_t solidLed1 = 8;
const uint8_t laserLed1 = 9;
const uint8_t throbPin1 = 10;
const uint8_t throbPin2 = 11;
// PWM Pins Overview Comment
// Note: Almost all PWM pins are in use (3, 5, 6, 9, 10, 11).
// Three vias are available for engine lights to allow up to 4 engines to be lit.
// Due to the 40mA limit on PWM pins, pins 10 and 11 are set to mirror each other
// to maximize the number of available engine LEDs.
// Brightness Variables
uint8_t brightnessLaser = constrain(brightnessLaser, 0, 255);
uint8_t brightnessBlinkLed1 = constrain(brightnessBlinkLed1, 0, 255);
uint8_t brightnessBlinkLed2 = constrain(brightnessBlinkLed2, 0, 255);
uint8_t brightnessBlinkLed3 = constrain(brightnessBlinkLed3, 0, 255);
uint8_t maxBrightnessLaser = 255;
// Fade Speeds
float laserFade = 0.90;
uint8_t blinkFade = 5;
uint8_t randomWidth = 100;
uint8_t switchChance = 3; // Probability of twinkle LEDs switching from fading to brightening (%).
// Button Counter
const uint8_t buttonPin = 2;
uint8_t buttonCounter = 0;
byte buttonState = LOW;
byte lastButtonState = LOW;
unsigned long nextReadMillis = 0;
// LED Variables
byte blinkLed1Value = 1;
byte blinkLed2Value = 1;
byte blinkLed3Value = 1;
// Debounce Time
#define debounceTime 200
// Sine Wave Generator for Engine Throb
float timeStep = 0;
uint8_t throbValue = 0;
void setup() {
// Debugging Statment
Serial.begin(115200); // used for debugging, comment out
// LED setup
pinMode(solidLed1, OUTPUT); // pin "solidLed1" is output
pinMode(laserLed1, OUTPUT); // pin "laserLed1" is output
randomSeed(analogRead(0)); // makes the Random() function truly random
// Button Setup
pinMode(buttonPin, INPUT); // Initialize the button pin as a input:
// twinkleLeds Setup
pinMode(blinkLed1, OUTPUT); // Pin "blinkLed1" is output
pinMode(blinkLed2, OUTPUT); // Pin "blinkLed2" is output
pinMode(blinkLed3, OUTPUT); // Pin "blinkLed3" is output
// this is for the sine wave engine throb
pinMode(10, OUTPUT);
pinMode(11, OUTPUT);
// Turns on solid LED, sets cockpit LED to on. Use a flickering LED here
digitalWrite(solidLed1, HIGH);
}
void loop() {
Serial.println(brightnessBlinkLed1); // for debugging
// Control functions
turboLaser();
twinkleLED(brightnessBlinkLed1, blinkLed1, blinkFade, blinkLed1Value); // Controls first twinkle LED
twinkleLED(brightnessBlinkLed2, blinkLed2, blinkFade, blinkLed2Value); // Controls second twinkle LED
twinkleLED(brightnessBlinkLed3, blinkLed3, blinkFade, blinkLed3Value); // Controls third twinkle LED
throbber(timeStep, throbValue); // This is for the sine wave engine throb.
delay(30); // 30ms cycle
}
void throbber(float &time, uint8_t &throb){ // engine throb function. Produces a sine wave
throb = 127 * sin( 2 * PI * time) + 127; // sine equation, sine * Tau + 127 to avoid negitive numbers
timeStep += 0.01; // used to determine how quickly engines throb, default 0.01 for 3 second pulse.
// Writes throb to engines
analogWrite(throbPin1, throb);
analogWrite(throbPin2, throb);
}
void twinkleLED(uint8_t &brightness, uint8_t blinkLed, uint8_t fade, byte &value){ //twinkling Side LEDs funtion
uint8_t blinkLedRandom = 0; // Random Value for LED
blinkLedRandom = random(randomWidth); // Sets blinkLedRandom to a value between 0 & 199
if (blinkLedRandom <= switchChance){ // if random number is < switch chance, go negitive
value = LOW;
} else if (blinkLedRandom >= randomWidth - switchChance){ // if random number is higher than switch chance, go postiive. if between, maintain direction
value = HIGH;
}
brightness = (value == HIGH && brightness < 250) ? brightness + fade : // randomly increases and decreases the brightness
(value == LOW && brightness > 100) ? brightness - fade :
(value == LOW && brightness <= 100) ? 0 : brightness;
analogWrite(blinkLed, brightness);
}
void turboLaser() {
// Laser firing logic
buttonPress();
if (buttonCounter == 0) { // If button not pressed, do nothing
brightnessLaser = 0;
} else if (buttonCounter <= 79) {// if count is <80, and devisible by 20, then laser max. if not devisible by 20, the reduce laser
brightnessLaser = (buttonCounter % 20 == 0) ? maxBrightnessLaser : brightnessLaser * laserFade;
buttonCounter++;
} else { // if buttoncount is 80, then reset and wait for next button press
brightnessLaser = 0;
buttonCounter = 0;
}
analogWrite(laserLed1, brightnessLaser);
}
void buttonPress(){
unsigned long newMillis = millis();
// Button debounce counter
if (newMillis >= nextReadMillis) {
// Compare the buttonState to its previous state
buttonState = digitalRead(buttonPin);
if (buttonState != lastButtonState) {
// If the state has changed, increment the counter
if (buttonState == HIGH) {
// If the current state is HIGH, the button went from off to on
nextReadMillis = newMillis + debounceTime;
buttonCounter++;
}
lastButtonState = buttonState; // Save the current state as the last state
}
}
}