-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathAubsProg
More file actions
284 lines (232 loc) · 7.95 KB
/
Copy pathAubsProg
File metadata and controls
284 lines (232 loc) · 7.95 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
#include <FastLED.h>
#define NUM_LEDS 84
#define DATA_PIN 3
#define WAVELENGTH 400 // # of steps peak-to-peak
#define MAX_BRIGHTNESS 255.0 // max brightness 0-255
#define CYCLE_TIME 150 // delay before updating colors, in ms
#define FLASH_TIME 50 // delay before rewriting outputs (Useful for fading)
#define SCALING_FACTOR 20 //The phase distance in waveform between the each LED
#define FADE_DURATION 1200 //The time it takes to fade between on and off
#define BUTTON_PIN 8 // the number of the pushbutton pin
class ButtCheck {
public: // Access specifier
unsigned long buttonStartTime = 0; //Start time since the button has been high, with debounce control
unsigned long lastTimeCheck = 0;
int debCount; //debounce buffer counter. zero = button is off
const int debBufferMax = 6; //button has to be low for at least 50 ms to be registered as off
const int timeCheckInterval = 1; //
int myButtonPinNum; //what button pin number is it that I'm watching
ButtCheck(int tempButt) { // Constructor
myButtonPinNum = tempButt;
}
int timeButtPush() {
unsigned long currTimeCheck = millis(); //temp var to get current time
//if sufficient time has passed since the last time check
if (currTimeCheck - lastTimeCheck >= timeCheckInterval) {
lastTimeCheck = currTimeCheck;
//if button is pushed
if (digitalRead(myButtonPinNum)) { //if reads button as high
if (debCount == 0) { //first signal that the button has been pushed. So, set the start time as now
buttonStartTime = currTimeCheck;
}
debCount = debCount + 2;
if (debCount > debBufferMax) {
debCount = debBufferMax;
}
} else { //if reads button as low
debCount = debCount - 1;
}
}
if (debCount <= 0) {//debounce buffer has run out, so assume button was actually released
debCount = 0;
return 0;
}
int tempInt = currTimeCheck - buttonStartTime;
return tempInt;
}
};
/*
we're going to use a triangle wave that's truncated below 0, like so:
MAX |\ /\
| \ / \
| \ / \
| \ / \
0___|____\__________/________\_
|
but then overlay 3 of these, one each for R, G, B:
R G B R G
MAX |\ /\ /\ oops /\ /\
| \ / \ / \ / \ /
| X X \ / X
| / \ / \ \ / / \
0___|/___\/___\____\/____/___\_
|
so really we want to cut off half of the negative (zero) part of the cycle:
MAX |\ /\
| \ / \
| \ / \
| \ / \
0___|____\_____/________\_
|
for this pattern:
R G B R G B
MAX |\ /\ /\ /\ /\ /\
| \ / \ / \ / \ / \ /
| X X X X X
| / \ / \ / \ / \ / \
0___|/___\/___\/___\/___\/___\/_
|
so, using WAVELENGTH and MAXBRIGHT, we precalculate an array of values sampled
from the conceptual (dis)continuous function, then shift along those at each
step, with a different offset for each color
*/
CRGB leds[NUM_LEDS];
int Ridx;
int Gidx;
int Bidx;
int tempRidx;
int tempGidx;
int tempBidx;
int brightness = 255;
unsigned long cyclePrevTime = 0;
unsigned long flashPrevTime = 0;
ButtCheck myTouchSense(BUTTON_PIN);
bool lightsOn = 1; //default on
bool lightOnModeLatch = 0; //For tracking if the lighton has already been switched
bool redMode = 0; //default off
bool redModeLatch = 0; //For tracking if the redmode has already been switched
int lastButtonTime;
bool fadingToBlack = 0;
bool fadingToLight = 1;
int fadeStartTime = 0;
int fadeScale = 255;
byte waveform[WAVELENGTH];
void setup() {
pinMode(BUTTON_PIN, INPUT);
//Serial.begin(9600);
//Serial.println("Hi");
FastLED.addLeds<WS2811, DATA_PIN>(leds, NUM_LEDS);
// TODO: delete most of this code by using the FastLED triwave8() func
// also look into other provided funcs
// (maybe beatsin8 would be even better?)
/*
start moving upward from the wave minimum, so we're going to generate this:
MAX | /\
| / \
0___|___/____\_
*/
double slope = (double) (1) / (WAVELENGTH / 3);
double val = -1;
//Serial.print("slope = "); Serial.println(slope);
for (int i=0; i < WAVELENGTH; i++) {
// TODO: probably going to be some errors in here
// wrt int -> double -> int conversion
// clamp to 0 while val is negative
if (val >= 0) {
waveform[i] = floor(pow(val,2) * 255.0);
} else {
waveform[i] = 1;
}
val = val + slope;
// once we hit max, start going down
if (val >= 1) {
val = 1;
slope *= -1;
}
//Serial.print("i: "); Serial.print(i); Serial.print(" = "); Serial.println(waveform[i]);
}
// these offsets will make the cycle start at 100% red,
// as in the diagram above
Ridx = (2 * WAVELENGTH) / 3;
Gidx = WAVELENGTH / 3;
Bidx = 0;
fadeStartTime = millis(); //DELETE ME maybe
}
void loop() {
//int currentButtonTime = myTouchSense.timeButtPush(); //This is zero if the button is released
//Serial.print("last: "); Serial.print(lastButtonTime); Serial.print(", now: "); Serial.println(currentButtonTime);
if (fadingToLight) {
fadeToLight();
}
if (fadingToBlack) {
fadeToBlack();
}
if (lightsOn) {
lightsCycle();
}
if (myTouchSense.timeButtPush() > 1000 && redModeLatch == 0) { //switch modes if released for longer than 3 secs
redMode = !redMode;
redModeLatch = 1;
} else if (myTouchSense.timeButtPush() > 2000 && lightOnModeLatch == 0) { //power off if released for between .1 and 5 secs
lightsOn = !lightsOn;
lightOnModeLatch = 1;
redMode = 0;
if (lightsOn) { //turn lights on
fadingToLight = 1;
fadeStartTime = millis();
fadeScale = 0;
} else { //turn lights off
fadeScale = 0;
FastLED.setBrightness(fadeScale);
FastLED.show();
}
}
if (myTouchSense.timeButtPush() == 0) { //Button low
redModeLatch = 0;
lightOnModeLatch = 0;
}
}
void fadeToBlack() {
float temp = (float) (millis() - fadeStartTime) / FADE_DURATION;
if (temp > 1.0) {
temp = 1.0;
fadingToBlack = 0;
}
temp = 1.0 - temp;
temp = pow(temp, 4.0);
fadeScale = temp * MAX_BRIGHTNESS;
}
void fadeToLight() {
float temp = (float) (millis() - fadeStartTime) / FADE_DURATION;
if (temp > 1.0) { //Fully faded
temp = 1.0;
fadingToLight = 0;
}
temp = pow(temp, 2.0);
fadeScale = temp * MAX_BRIGHTNESS;
}
void lightsCycle() {
unsigned long currTime = millis();
if (currTime - cyclePrevTime > CYCLE_TIME) { //Only do the lightcycle if enough time has passed
cyclePrevTime = currTime;
for(int n=0; n < NUM_LEDS; n++) {
// scan through the full waveform to assign a different value
// to each LED, looping back to the start as necessary, separating them out by the scaling factor
tempRidx = (Ridx + n*SCALING_FACTOR) % WAVELENGTH;
tempGidx = (Gidx + n*SCALING_FACTOR) % WAVELENGTH;
tempBidx = (Bidx + n*SCALING_FACTOR) % WAVELENGTH;
//led.r is actually blue, g is actually red, and b is actually green
if (redMode) {
leds[n].r = 0;
leds[n].b = waveform[tempGidx] * 0.4;
if (waveform[tempBidx] > waveform[tempRidx]) {
leds[n].g = waveform[tempBidx];
} else {
leds[n].g = waveform[tempRidx];
}
} else {
leds[n].r = waveform[tempBidx];
leds[n].b = waveform[tempGidx];
leds[n].g = waveform[tempRidx];
}
}
Ridx = (Ridx + 1) % WAVELENGTH;
Gidx = (Gidx + 1) % WAVELENGTH;
Bidx = (Bidx + 1) % WAVELENGTH;
}
if (currTime - flashPrevTime > FLASH_TIME) { //Only do the flash if enough time has passed
flashPrevTime = currTime;
FastLED.setBrightness(fadeScale);
FastLED.show();
}
}