Skip to content

Instantly share code, notes, and snippets.

@ungood
Created June 13, 2011 22:23
Show Gist options
  • Select an option

  • Save ungood/1023878 to your computer and use it in GitHub Desktop.

Select an option

Save ungood/1023878 to your computer and use it in GitHub Desktop.
Hoola Hoop Code
#include <Button.h>
// LEDs
const int numLedsInArray = 16;
const int numPinsPerLed = 3;
// Pattern Settings
const int patternIncrement = 16;
const int incrementDivider = 8;
const int patternRange = numLedsInArray * patternIncrement; //* incrementDivider;
// Input Settings
const unsigned int minSpeed = 1;
const unsigned int maxSpeed = 20;
const unsigned int minWidth = 1;
const unsigned int maxWidth = incrementDivider * 4;
// Input
const int modeButtonPin = 2;
Button modeButton = Button(modeButtonPin, PULLUP);
const int dirButtonPin = 4;
Button dirButton = Button(dirButtonPin, PULLUP);
const int potPin = 0;
//Setup
void setup() {
Serial.begin(9600);
pinMode(modeButtonPin, INPUT);
digitalWrite(modeButtonPin, HIGH);
pinMode(dirButtonPin, INPUT);
digitalWrite(dirButtonPin, HIGH);
setupLeds();
}
unsigned int state = 0;
unsigned int numStates = 2;
unsigned long changedTime = 0;
unsigned int step = 0;
int direction = 0;
unsigned int speed = (maxSpeed + minSpeed) / 2;
unsigned int bandwidth = incrementDivider;
void loop() {
readInput();
chaseLoop();
delay(speed);
}
void readInput() {
direction = dirButton.isPressed() ? 1 : -1;
if(modeButton.stateChanged())
changedTime = millis();
if(modeButton.isPressed()) {
unsigned long debounce = millis() - changedTime;
if(debounce > 200)
state = (state + 1) % numStates;
}
switch(state) {
case 0: // Change Speed
speed = readPot(speed, minSpeed, maxSpeed);
break;
case 1: // Change Band width
bandwidth = readPot(bandwidth, minWidth, maxWidth);
break;
}
}
void chaseLoop() {
step = step + direction;
int increment = patternIncrement * ((float)bandwidth / (incrementDivider * 2));
for(int led = 0; led < numLedsInArray; led++) {
unsigned int patternIndex = led * increment + step;
setColor(led, patternIndex);
}
}
int readPot(int prevVal, int min, int max) {
int mapped = map(analogRead(potPin), 0, 1023, min, max);
return smooth(mapped, .1, prevVal);
}
int smooth(int data, float filterVal, float smoothedVal) {
if (filterVal > 1){ // check to make sure param's are within range
filterVal = .99;
}
else if (filterVal <= 0){
filterVal = 0;
}
smoothedVal = (data * (1 - filterVal)) + (smoothedVal * filterVal);
return (int)smoothedVal;
}
enum {__RED, __GREEN, __BLUE};
int ledStates[numLedsInArray][numPinsPerLed];
int patternCache[patternRange][3];
#define __dataPin 9
#define __clockPin 10
#define __latchPin 11
#define __maxBrightness 100
#define __RELOAD_VAL 200
#define __delayMultiplier .5
#define __DATAPIN_PORT PORTB
#define __DATAPIN_BITMASK (1<<1)
#define __CLOCKPIN_PORT PORTB
#define __CLOCKPIN_BITMASK (1<<2)
#define __LATCHPIN_PORT PORTB
#define __LATCHPIN_BITMASK (1<<3)
#define __DATAPIN_SET_HIGH __DATAPIN_PORT |= __DATAPIN_BITMASK
#define __DATAPIN_SET_LOW __DATAPIN_PORT &= ~__DATAPIN_BITMASK
#define __CLOCKPIN_SET_HIGH __CLOCKPIN_PORT |= __CLOCKPIN_BITMASK
#define __CLOCKPIN_SET_LOW __CLOCKPIN_PORT &= ~__CLOCKPIN_BITMASK
#define __LATCHPIN_SET_HIGH __LATCHPIN_PORT |= __LATCHPIN_BITMASK
#define __LATCHPIN_SET_LOW __LATCHPIN_PORT &= ~__LATCHPIN_BITMASK
void getRainbowPattern(int& red, int& green, int& blue, float target, int numSteps);
int isrCount = 0;
void setColor(unsigned int led, unsigned int patternIndex) {
patternIndex %= patternRange;
ledStates[led][__RED] = patternCache[patternIndex][__RED];
ledStates[led][__GREEN] = patternCache[patternIndex][__GREEN];
ledStates[led][__BLUE] = patternCache[patternIndex][__BLUE];
}
ISR(TIMER2_OVF_vect)
{
TCNT2 = __RELOAD_VAL;
__LATCHPIN_SET_LOW;
for(int isr_ledNumber=numLedsInArray; isr_ledNumber >= 0; isr_ledNumber--)
{
for(int isr_loopCount=0; isr_loopCount < numPinsPerLed; isr_loopCount++)
{
if(ledStates[isr_ledNumber][isr_loopCount] <= isrCount)
{
__DATAPIN_SET_HIGH;
}
else
{
__DATAPIN_SET_LOW;
}
__CLOCKPIN_SET_HIGH;
__CLOCKPIN_SET_LOW;
}
}
__LATCHPIN_SET_HIGH;
isrCount++;
if(isrCount >= __maxBrightness)
{
isrCount=0;
}
}
void setupLeds() {
pinMode(__dataPin, OUTPUT);
pinMode(__clockPin, OUTPUT);
pinMode(__latchPin, OUTPUT);
unsigned int tcnt2;
TIMSK2 &= ~(1<<TOIE2);
TCCR2A &= ~((1<<WGM21) | (1<<WGM20));
TCCR2B &= ~(1<<WGM22);
ASSR &= ~(1<<AS2);
TIMSK2 &= ~(1<<OCIE2A);
TCCR2B |= (1<<CS22) | (1<<CS21) | (1<<CS20);
TCCR2B &= ~(1<<CS22);
TIMSK2 |= (1<<TOIE2);
for(int i = 0; i < patternRange; i++) {
int r, g, b;
getRainbowPattern(r, g, b, i, patternRange);
patternCache[i][__RED] = r;
patternCache[i][__GREEN] = g;
patternCache[i][__BLUE] = b;
}
}
void getRainbowPattern(int& red, int& green, int& blue, float target, int numSteps)
{
if(!numSteps)
{
numSteps=120;
}
while(target>=numSteps)
{
target -= (float) numSteps;
}
float sixthstep =(float) numSteps/6.000;
float seg0 = 0.00;
float seg1 = ((float)numSteps/6.00)+0;
float seg2 = seg1*2.00;
float seg3 = seg1*3.00;
float seg4 = seg1*4.00;
float seg5 = seg1*5.00;
float seg6 = seg1*6.00;
float lineSlope=(float)__maxBrightness/seg1;
float negLineSlope=-1*lineSlope;
if(target<=seg0)
{
red=__maxBrightness;
green=0;
blue=0;
}
else if(target<seg1 && target >= seg0)
{
red=__maxBrightness;
green=0;
blue=((target-seg0)*lineSlope);
}
else if(target<seg2 && target >= seg1)
{
red=__maxBrightness + ((target-seg1)*negLineSlope);
green=0;
blue=__maxBrightness;
}
else if(target<seg3 && target >= seg2)
{
red=0;
green=((target-seg2)*lineSlope);
blue=__maxBrightness;
}
else if(target<seg4 && target >= seg3)
{
red=0;
green=__maxBrightness;
blue=__maxBrightness + ((target-seg3)*negLineSlope);
}
else if(target<seg5 && target >= seg4)
{
red=((target-seg4)*lineSlope);
green=__maxBrightness;
blue=0;
}
else if(target<seg6 && target >= seg5)
{
red=__maxBrightness;
green=__maxBrightness + ((target-seg5)*negLineSlope);
blue=0;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment