Skip to content

Instantly share code, notes, and snippets.

@AkBKukU
Created May 7, 2016 01:33
Show Gist options
  • Select an option

  • Save AkBKukU/d5d3cab8a250296e186b16a975a79b96 to your computer and use it in GitHub Desktop.

Select an option

Save AkBKukU/d5d3cab8a250296e186b16a975a79b96 to your computer and use it in GitHub Desktop.
MultiLEDPWN
/* -------------- MultiLEDPWM -------------- *\
| By: Shelby Jueden |
| Date: 2016-05-06 |
| |
| Description: This is a software PWM Library |
| that has 4 animations and a cycling mode. |
| It's designed to be used with a line of |
| LEDs. |
\*-------------------------------------------*/
/* ---------- Basic Configuration ---------- */
//Mode switch button input
#define MODE_SWITCH_PIN 2
// Number of outputs
#define PIN_COUNT 8
// Outputs pins for each channel
int outputPins[PIN_COUNT] = {
12,11,10,9,8,7,6,5};
// Outout inverting for different BJTs
boolean invertOutput = false;
// Cycle animation delay
#define CYC_DELAY 5000
/* -------- Advanced Configuration --------- */
// Mode switching variables
#define MODE_DELAY 1000
double modeTime = 0;
boolean inModeSwitch = false;
// Input debouncing
#define DEBOUNCE 200
double debounceTime = 0;
// LED PWM Settings and variables
#define RESOLUTION 256
int output[PIN_COUNT];
int outputCounter = 0;
double outputTime = 0;
// LED fade decay speed
#define DEFAULT_DECAY 0.88
float decayRate = DEFAULT_DECAY;
// Fixed update settings
#define REFRESH_RATE 60
int refDelay = 0;
// Mode settigns and variables
#define MODE_COUNT 5
// Cylon
#define MODE_CYLON 0
int cylLightPos = 0;
int cylLightDir = 1;
#define CYL_LIGHT_MOVE_SPEED 120
double cylTime = 0;
// Center
#define MODE_TO_CENTER 1
int tcnLightPos = 0;
#define TCN_LIGHT_MOVE_SPEED 250
double tcnTime = 0;
#define TCN_DECAY 0.88
// Rain
#define MODE_RAIN 2
int raiLightPos = 0;
int raiLightDis = 0;
#define RAI_LIGHT_NEXT_DROP 1200
#define RAI_LIGHT_MOVE_SPEED 200
double raiTimeMove = 0;
double raiTimeDrop = 0;
#define RAI_DECAY 0.90
#define RAI_AMP 1.7
// Corrupt
#define MODE_CORRUPT 3
// Cycle
#define MODE_CYCLE 4
int cycleMode = 0;
double cycTime = 0;
int currentMode = MODE_CYLON;
void setup()
{
// Configure Input
pinMode(MODE_SWITCH_PIN,INPUT);
// Configure Outputs
int i = 0;
for (i = 0; i < PIN_COUNT;i++)
{
pinMode(outputPins[i],OUTPUT);
}
// Get milliseconds for refresh rate
refDelay = 1000 / REFRESH_RATE;
// Initilize all LEDs
clearLEDs();
}
void loop()
{
// Call for running loop with refresh rate
fixedLoopCalc();
// Input Checking
modeSwitch();
}
// Loop function that runs at the REFRESH_RATE frequency
void fixedLoop()
{
// Check that not in switch Mode
if(!inModeSwitch)
{
// Run update function for current mode
switch(currentMode)
{
case MODE_CYLON:
decayRate = DEFAULT_DECAY;
cylonUpdate();
break;
case MODE_TO_CENTER:
decayRate = TCN_DECAY;
toCenterUpdate();
break;
case MODE_RAIN:
decayRate = RAI_DECAY;
rainUpdate();
break;
case MODE_CORRUPT:
curruptUpdate();
break;
case MODE_CYCLE:
cycleUpdate();
break;
}
}
}
// Check for input to change mode
void modeSwitch()
{
// Check for input and not debouncing
if(
digitalRead(MODE_SWITCH_PIN)
&& millis() > debounceTime
){
// Reset Timer
debounceTime = millis() + DEBOUNCE;
clearLEDs();
// Start mode select timeout
modeTime = millis() + MODE_DELAY;
// Check if already in mode select mode
if(inModeSwitch)
{
// Change mode
currentMode++;
// Wrap currentMode to MODE_COUNT
if(currentMode > MODE_COUNT - 1 )
currentMode = 0;
}
else
{
// Start mode change mode
inModeSwitch = true;
}
// Indicate selected mode
output[currentMode] = RESOLUTION -1;
}
// Check for mode timeout
if(
inModeSwitch
&& millis() > modeTime
){
// Exit mode select
inModeSwitch = false;
clearLEDs();
}
}
// Cylon Animation logic
void cylonUpdate()
{
// Check for next animation time
if(millis() > cylTime)
{
// Reset Timer
cylTime = millis() + CYL_LIGHT_MOVE_SPEED;
// Set current position to max brightness
output[cylLightPos] = RESOLUTION -1;
// Change position based on direction
cylLightPos = cylLightPos + cylLightDir;
// Bounds check posistion and change direction
if(cylLightPos > PIN_COUNT - 1)
{
cylLightDir = -1;
cylLightPos = cylLightPos + cylLightDir;
}
else if(cylLightPos < 0)
{
cylLightDir = 1;
cylLightPos = cylLightPos + cylLightDir;
}
}
// Fade out lights
outputDecay();
}
// Center Animation logic
void toCenterUpdate()
{
// Check for next animation time
if(millis() > tcnTime)
{
// Reset Timer
tcnTime = millis() + TCN_LIGHT_MOVE_SPEED;
// Set posistions to max brightness
output[tcnLightPos] = RESOLUTION -1;
output[PIN_COUNT - 1 - tcnLightPos] = RESOLUTION -1;
// Move to next position
tcnLightPos++;
// Wrap position at center
if(tcnLightPos > (PIN_COUNT/2)-1)
{
tcnLightPos = 0;
}
}
// Fade out lights
outputDecay();
}
// Rain Animation logic
void rainUpdate()
{
// Check for next spread animation
if(millis() > raiTimeMove)
{
// Reset Timer
raiTimeMove = millis() + RAI_LIGHT_MOVE_SPEED;
// Move spread point
raiLightDis++;
// Bounds check spread and set to max brightness
if(raiLightPos + raiLightDis < PIN_COUNT)
output[raiLightPos+raiLightDis] = output[raiLightPos+raiLightDis] + output[raiLightPos+raiLightDis-1] * RAI_AMP;
if(raiLightPos - raiLightDis >= 0)
output[raiLightPos-raiLightDis] = output[raiLightPos-raiLightDis] + output[raiLightPos-raiLightDis+1] * RAI_AMP;
// Check for next drop animation
if(millis() > raiTimeDrop)
{
// Reset Timer
raiTimeDrop = millis() + RAI_LIGHT_NEXT_DROP;
// Get random drop position
raiLightPos = random(PIN_COUNT);
// Set posisiton to max brightness
output[raiLightPos] = RESOLUTION -1;
// Reset spread
raiLightDis=0;
}
}
// Fade out lights
outputDecay();
}
// Corrupt Animation logic
void curruptUpdate()
{
// Pick random position and value
output[random(PIN_COUNT)] = random(RESOLUTION-1);
}
// Cycle Mode logic
void cycleUpdate()
{
// Run update for current cycle mode
switch(cycleMode)
{
case MODE_CYLON:
decayRate = DEFAULT_DECAY;
cylonUpdate();
break;
case MODE_TO_CENTER:
decayRate = TCN_DECAY;
toCenterUpdate();
break;
case MODE_RAIN:
decayRate = RAI_DECAY;
rainUpdate();
break;
case MODE_CORRUPT:
curruptUpdate();
break;
}
// Check for time to cycle
if(millis() > cycTime)
{
// Reset Timer
cycTime = millis() + CYC_DELAY;
// Move to next mode
cycleMode++;
// Wrap currentMode to MODE_COUNT
if(cycleMode > MODE_COUNT - 2 )
cycleMode = 0;
}
}
// Fade out all LEDs by set amount
void outputDecay()
{
// Go through all LEDs
for (int i = 0; i < PIN_COUNT;i++)
{
// Check if value needs lowered
if(output[i] > 1)
{
output[i] = output[i] * decayRate;
}
else
{
// Set to off
output[i] = 0;
}
}
}
// Calculates when to run the LED update and fixed loop based on the refresh rate
void fixedLoopCalc()
{
// Check if it's time to run the frequency restricted logic
if(millis() > outputTime)
{
// Reset Timer
outputTime = millis() + refDelay;
// Run fixedLoop
fixedLoop();
// PWM LEDs
updateLEDs();
}
}
// Set all LEDs to off
void clearLEDs()
{
for (int i = 0; i < PIN_COUNT;i++)
{
output[i] = 0;
}
}
// Go through each LED
// LED PWM control code.
void updateLEDs()
{
// Go through each brightness level
for (outputCounter = 0; outputCounter < RESOLUTION;outputCounter++)
{
// Go through each LED
for (int i = 0; i < PIN_COUNT;i++)
{
// Set LED state for level based on brightness level inverted option
if(outputCounter < output[i])
{
if(invertOutput)
digitalWrite(outputPins[i],LOW);
else
digitalWrite(outputPins[i],HIGH);
}
else
{
if(invertOutput)
digitalWrite(outputPins[i],HIGH);
else
digitalWrite(outputPins[i],LOW);
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment