Skip to content

Commit be57a54

Browse files
committed
Add example that can work with 256 LEDs
1 parent f42f10b commit be57a54

File tree

10 files changed

+415
-0
lines changed

10 files changed

+415
-0
lines changed

examples/LotsOfLeds/BlinkyTape.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#ifndef BLINKY_TAPE_H
2+
#define BLINKY_TAPE_H
3+
4+
#include <FastLED.h>
5+
6+
#define LED_COUNT 255 // Number of LEDs connected to the board. This is also the maximum number of LEDs that can be controlled via serial
7+
8+
#define LED_OUT 13
9+
#define BUTTON_IN 10
10+
#define ANALOG_INPUT A9
11+
#define EXTRA_PIN_A 7
12+
#define EXTRA_PIN_B 11
13+
14+
class Pattern {
15+
public:
16+
virtual void draw(CRGB * leds);
17+
virtual void reset();
18+
};
19+
20+
#endif

examples/LotsOfLeds/ColorLoop.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#include "ColorLoop.h"
2+
#include "BlinkyTape.h"
3+
4+
#include <Arduino.h>
5+
6+
7+
ColorLoop::ColorLoop(float newRBal, float newGBal, float newBBal) :
8+
rBal(newRBal),
9+
gBal(newGBal),
10+
bBal(newBBal) {
11+
}
12+
13+
void ColorLoop::reset() {
14+
j = 0;
15+
f = 0;
16+
k = 0;
17+
}
18+
19+
void ColorLoop::draw(CRGB* leds) {
20+
for (uint16_t i = 0; i < LED_COUNT; i++) {
21+
leds[i].r = 64*(1+sin(i/2.0 + j/4.0 )) * rBal;
22+
leds[i].g = 64*(1+sin(i/1.0 + f/9.0 + 2.1)) * gBal;
23+
leds[i].b = 64*(1+sin(i/3.0 + k/14.0 + 4.2)) * bBal;
24+
}
25+
26+
j = j + 1;
27+
f = f + 1;
28+
k = k + 2;
29+
}

examples/LotsOfLeds/ColorLoop.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#ifndef COLOR_LOOP_H
2+
#define COLOR_LOOP_H
3+
4+
#include <FastLED.h>
5+
#include "BlinkyTape.h"
6+
7+
class ColorLoop : public Pattern {
8+
private:
9+
float rBal;
10+
float gBal;
11+
float bBal;
12+
13+
int j;
14+
int f;
15+
int k;
16+
int count;
17+
18+
public:
19+
ColorLoop(float newRBal, float newGBal, float newBBal);
20+
void reset();
21+
void draw(CRGB * leds);
22+
};
23+
24+
#endif

examples/LotsOfLeds/Flashlight.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#include "Flashlight.h"
2+
#include "BlinkyTape.h"
3+
4+
#include <Arduino.h>
5+
6+
Flashlight::Flashlight(CRGB newColor) :
7+
color(newColor) {
8+
}
9+
10+
void Flashlight::draw(CRGB* leds) {
11+
for (uint16_t i = 0; i < LED_COUNT; i++) {
12+
leds[i] = color;
13+
}
14+
}

examples/LotsOfLeds/Flashlight.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#ifndef FLASHLIGHT_H
2+
#define FLASHLIGHT_H
3+
4+
#include <FastLED.h>
5+
#include "BlinkyTape.h"
6+
7+
class Flashlight : public Pattern {
8+
private:
9+
CRGB color;
10+
11+
public:
12+
Flashlight(CRGB newColor);
13+
void reset() {};
14+
void draw(CRGB * leds);
15+
};
16+
17+
#endif

examples/LotsOfLeds/LotsOfLeds.ino

Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
#include <EEPROM.h>
2+
3+
#include <FastLED.h>
4+
#include <Animation.h>
5+
6+
#include "BlinkyTape.h"
7+
#include "ColorLoop.h"
8+
#include "SerialLoop.h"
9+
#include "Scanner.h"
10+
#include "Flashlight.h"
11+
12+
struct CRGB leds[LED_COUNT];
13+
14+
#define BRIGHT_STEP_COUNT 8
15+
#define STARTING_BRIGHTNESS 4
16+
volatile uint8_t brightnesSteps[BRIGHT_STEP_COUNT] = {5,15,40,70,93, 70, 40, 15};
17+
18+
uint8_t brightness = 4;
19+
uint8_t lastBrightness = 4;
20+
21+
22+
// For fading in a new sketch
23+
long lastTime;
24+
25+
float fadeIndex;
26+
#define FADE_STEPS 50
27+
28+
// Button interrupt variables and Interrupt Service Routine
29+
uint8_t buttonState = 0;
30+
bool buttonDebounced;
31+
long buttonDownTime = 0;
32+
long buttonPressTime = 0;
33+
34+
#define BUTTON_BRIGHTNESS_SWITCH_TIME 1 // Time to hold the button down to switch brightness
35+
#define BUTTON_PATTERN_SWITCH_TIME 1000 // Time to hold the button down to switch patterns
36+
37+
38+
#define EEPROM_START_ADDRESS 0
39+
#define EEPROM_MAGIG_BYTE_0 0x12
40+
#define EEPROM_MAGIC_BYTE_1 0x34
41+
#define PATTERN_EEPROM_ADDRESS EEPROM_START_ADDRESS + 2
42+
43+
uint8_t currentPattern = 0;
44+
uint8_t patternCount = 0;
45+
#define MAX_PATTERNS 10
46+
Pattern* patterns[MAX_PATTERNS];
47+
48+
49+
// Register a pattern
50+
void registerPattern(Pattern* newPattern) {
51+
// If there is space for this pattern
52+
if(MAX_PATTERNS <= patternCount) {
53+
return;
54+
}
55+
56+
patterns[patternCount] = newPattern;
57+
patternCount++;
58+
}
59+
60+
// Change the current pattern
61+
void initializePattern(uint8_t newPattern) {
62+
// Check if this is a valid pattern
63+
if(newPattern >= MAX_PATTERNS) {
64+
return;
65+
}
66+
67+
EEPROM.write(PATTERN_EEPROM_ADDRESS, newPattern);
68+
69+
currentPattern = newPattern;
70+
patterns[currentPattern]->reset();
71+
72+
lastTime = millis();
73+
fadeIndex = 0;
74+
}
75+
76+
// Run one step of the current pattern
77+
void runPattern() {
78+
patterns[currentPattern]->draw(leds);
79+
}
80+
81+
82+
// Called when the button is both pressed and released.
83+
ISR(PCINT0_vect){
84+
buttonState = !(PINB & (1 << PINB6)); // Reading state of the PB6 (remember that HIGH == released)
85+
86+
if(buttonState) {
87+
// On button down, record the time so we can convert this into a gesture later
88+
buttonDownTime = millis();
89+
buttonDebounced = false;
90+
91+
// And configure and start timer4 interrupt.
92+
TCCR4B = 0x0F; // Slowest prescaler
93+
TCCR4D = _BV(WGM41) | _BV(WGM40); // Fast PWM mode
94+
OCR4C = 0x10; // some random percentage of the clock
95+
TCNT4 = 0; // Reset the counter
96+
TIMSK4 = _BV(TOV4); // turn on the interrupt
97+
98+
}
99+
else {
100+
TIMSK4 = 0; // turn off the interrupt
101+
}
102+
}
103+
104+
// This is called every xx ms while the button is being held down; it counts down then displays a
105+
// visual cue and changes the pattern.
106+
ISR(TIMER4_OVF_vect) {
107+
// If the user is still holding down the button after the first cycle, they were serious about it.
108+
if(buttonDebounced == false) {
109+
buttonDebounced = true;
110+
lastBrightness = brightness;
111+
brightness = (brightness + 1) % BRIGHT_STEP_COUNT;
112+
LEDS.setBrightness(brightnesSteps[brightness]);
113+
}
114+
115+
// If we've waited long enough, switch the pattern
116+
// TODO: visual indicator
117+
buttonPressTime = millis() - buttonDownTime;
118+
if(buttonPressTime > BUTTON_PATTERN_SWITCH_TIME) {
119+
// first unroll the brightness!
120+
brightness = lastBrightness;
121+
LEDS.setBrightness(brightnesSteps[brightness]);
122+
123+
initializePattern((currentPattern+1)%patternCount);
124+
125+
// Finally, reset the button down time, so we don't advance again too quickly
126+
buttonDownTime = millis();
127+
}
128+
}
129+
130+
ColorLoop originalRainbow(1,1,1);
131+
ColorLoop blueRainbow(.2,1,1);
132+
Scanner scanner(4, CRGB(255,0,0));
133+
Flashlight flashlight(CRGB(255,255,255));
134+
135+
void setup()
136+
{
137+
Serial.begin(57600);
138+
139+
LEDS.addLeds<WS2811, LED_OUT, GRB>(leds, LED_COUNT);
140+
brightness = STARTING_BRIGHTNESS;
141+
LEDS.setBrightness(brightnesSteps[brightness]);
142+
LEDS.show();
143+
144+
pinMode(BUTTON_IN, INPUT_PULLUP);
145+
pinMode(ANALOG_INPUT, INPUT_PULLUP);
146+
pinMode(EXTRA_PIN_A, INPUT_PULLUP);
147+
pinMode(EXTRA_PIN_B, INPUT_PULLUP);
148+
149+
// Interrupt set-up; see Atmega32u4 datasheet section 11
150+
PCIFR |= (1 << PCIF0); // Just in case, clear interrupt flag
151+
PCMSK0 |= (1 << PCINT6); // Set interrupt mask to the button pin (PCINT6)
152+
PCICR |= (1 << PCIE0); // Enable interrupt
153+
154+
registerPattern(&originalRainbow);
155+
registerPattern(&blueRainbow);
156+
registerPattern(&scanner);
157+
registerPattern(&flashlight);
158+
159+
160+
// Attempt to read in the last used pattern; if it's an invalid
161+
// number, initialize it to 0 instead.
162+
if((EEPROM.read(EEPROM_START_ADDRESS) == EEPROM_MAGIG_BYTE_0)
163+
&& (EEPROM.read(EEPROM_START_ADDRESS + 1) == EEPROM_MAGIC_BYTE_1)) {
164+
currentPattern = EEPROM.read(PATTERN_EEPROM_ADDRESS);
165+
if(currentPattern >= patternCount) {
166+
currentPattern = 0;
167+
}
168+
}
169+
else {
170+
EEPROM.write(EEPROM_START_ADDRESS, EEPROM_MAGIG_BYTE_0);
171+
EEPROM.write(EEPROM_START_ADDRESS, EEPROM_MAGIC_BYTE_1);
172+
currentPattern = 0;
173+
}
174+
175+
176+
initializePattern(currentPattern);
177+
}
178+
179+
void loop()
180+
{
181+
// If'n we get some data, switch to passthrough mode
182+
if(Serial.available() > 0) {
183+
serialLoop(leds);
184+
}
185+
186+
// Draw the current pattern
187+
runPattern();
188+
189+
if((millis() - lastTime > 15) && fadeIndex < FADE_STEPS) {
190+
lastTime = millis();
191+
fadeIndex++;
192+
193+
LEDS.setBrightness(brightnesSteps[brightness]*(fadeIndex/FADE_STEPS));
194+
}
195+
196+
197+
LEDS.show();
198+
}
199+

examples/LotsOfLeds/Scanner.cpp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
#include "Scanner.h"
2+
#include "BlinkyTape.h"
3+
4+
#include <Arduino.h>
5+
6+
Scanner::Scanner(uint16_t newScanWidth, CRGB newColor) :
7+
scanWidth(newScanWidth),
8+
color(newColor) {
9+
}
10+
11+
void Scanner::reset() {
12+
position = 2;
13+
direction = 1;
14+
}
15+
16+
void Scanner::draw(CRGB* leds) {
17+
for (uint16_t i = 0; i < LED_COUNT; i++) {
18+
if((i >= position) && (i < position + scanWidth)) {
19+
leds[i] = color;
20+
}
21+
else {
22+
leds[i] = CRGB(0);
23+
}
24+
}
25+
26+
if(direction == 0) {
27+
position += 1;
28+
29+
}
30+
else {
31+
position -= 1;
32+
}
33+
34+
if(position > LED_COUNT - scanWidth) {
35+
direction = 1;
36+
}
37+
else if(position == 0) {
38+
direction = 0;
39+
}
40+
41+
delay(30); // TODO: Don't place me here
42+
}

examples/LotsOfLeds/Scanner.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#ifndef SCANNER_H
2+
#define SCANNER_H
3+
4+
#include <FastLED.h>
5+
#include "BlinkyTape.h"
6+
7+
class Scanner : public Pattern {
8+
private:
9+
uint16_t scanWidth;
10+
CRGB color;
11+
12+
uint16_t position;
13+
uint8_t direction; // 0 is positive, 1 is negative
14+
15+
public:
16+
Scanner(uint16_t newScanWidth, CRGB newColor);
17+
void reset();
18+
void draw(CRGB * leds);
19+
};
20+
21+
#endif

0 commit comments

Comments
 (0)