This is an extremely simple, yet visually very effective project that can serve as a gadget on your desktop or as an addition to an audio device.
Devices and components
Arduino-Nano
Capacitive touch sensor
capacitor 100nF 100V X7R 10% 0805 3k/reel (0805B104K101N3-Hitano)
Resistor 100k _1206
Resistor 4.7 kOhm 5% 1/16W 50V 0402 (RC0402JR-074K7L-Yageo)
8x32 LED matrix
Materials and tools
Soldering kit
Software and tools
Arduino IDE
Project description
1/*
2 Copyright (c) 2020 Janux
3
4 Permission is hereby granted, free of charge, to any person obtaining a copy
5 of this software and associated documentation files (the "Software"), to deal
6 in the Software without restriction, including without limitation the rights
7 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 copies of the Software, and to permit persons to whom the Software is
9 furnished to do so, subject to the following conditions:
10 The above copyright notice and this permission notice shall be included in all
11 copies or substantial portions of the Software.
12 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
13 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
14 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
15 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
16 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
17 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
18 SOFTWARE.
19
20 Based on an original project for the MAX72xx LED matrix and FFT lib made from Shajeeb.
21 Configuration settings section based on work of Ragnar Ranøyen Homb from Norvegian Creation.
22*/
23
24#define LIN_OUT 1 //FHT linear output magnitude
25#define FHT_N 128 //set SAMPLES for FHT, Must be a power of 2
26#include <FHT.h>
27
28#define xres 32 //Total number of columns in the display, must be <= SAMPLES/2
29#define yres 8 //Total number of rows in the display
30#define ledPIN 6 //out pint to control Leds
31#define NUM_LEDS (xres * yres) //total leds in Matrix
32#include <Adafruit_NeoPixel.h>
33#include <Adafruit_NeoMatrix.h>
34
35#define colorPIN 5 //pin to change ledcolor
36#define brightnessPIN 10 //pin to change brightness
37
38byte displaycolor = 0; //default color value
39byte brightness = 1; //default brightness level
40
41#include <EEPROM.h>
42#define CONFIG_START 32 //Memory start location
43#define CONFIG_VERSION "VER01" //Config version configuration
44
45typedef struct {
46 char version[6];
47 byte displaycolor;
48 byte brightness;
49} configuration_type;
50
51configuration_type CONFIGURATION = {
52 CONFIG_VERSION,
53 displaycolor,
54 brightness
55};
56
57byte yvalue;
58int peaks[xres];
59byte state = HIGH; // the current reading from the input pin
60byte previousState = LOW; // the previous reading from the input pin
61unsigned long lastDebounceTime = 0; // the last time the output pin was toggled
62unsigned long debounceDelay = 100; // the debounce time; increase if the output flickers
63
64byte data_avgs[xres]; //Array for samplig
65
66// Parameter 1 = number of leds in matrix
67// Parameter 2 = pin number
68// Parameter 3 = pixel type flags, add together as needed:
69// NEO_KHZ800 800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
70// NEO_KHZ400 400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
71// NEO_GRB Pixels are wired for GRB bitstream (most NeoPixel products)
72// NEO_RGB Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
73Adafruit_NeoPixel pixel = Adafruit_NeoPixel(NUM_LEDS, ledPIN, NEO_GRB + NEO_KHZ800);
74
75// EQ filter
76byte eq[32] = {
77 60, 65, 70, 75, 80, 85, 90, 95,
78 100, 100, 100, 100, 100, 100, 100, 100,
79 100, 100, 100, 100, 100, 100, 100, 100,
80 115, 125, 140, 160, 185, 200, 200, 200
81};
82
83bool EQ_ON = true; // set to false to disable eq
84
85//Define 5 set of colors for leds, 0 for single custom color
86byte colors[][8] = {
87 {170, 160, 150, 140, 130, 120, 1, 1},
88 {1, 5, 10, 15, 20, 25, 90, 90},
89 {90, 85, 80, 75, 70, 65, 1, 1},
90 {90, 90, 90, 30, 30, 30, 1, 1},
91 {170, 160, 150, 140, 130, 120, 110, 0}
92};
93
94//Define chars for display settings
95byte charBitmap[] = {
96 0x1C, 0x10, 0x10, 0x10, 0x10, 0x1C, 0x08, 0x18, 0x08, 0x08, 0x08, 0x1C,
97 0x0C, 0x12, 0x04, 0x08, 0x10, 0x1E, 0x0C, 0x12, 0x02, 0x06, 0x12, 0x0C,
98 0x10, 0x10, 0x10, 0x14, 0x1E, 0x04, 0x1E, 0x10, 0x1E, 0x02, 0x12, 0x0C,
99 0x1E, 0x10, 0x10, 0x1E, 0x12, 0x1E, 0x1E, 0x02, 0x04, 0x08, 0x08, 0x08,
100 0x0C, 0x12, 0x0C, 0x12, 0x12, 0x0C, 0x1C, 0x12, 0x1C, 0x12, 0x12, 0x1C
101};
102
103void setup() {
104
105 pixel.begin(); //initialize Led Matrix
106
107 //Begin FFT operations
108 ADCSRA = 0b11100101; // set ADC to free running mode and set pre-scaler to 32 (0xe5)
109 ADMUX = 0b00000000; // use pin A0 and external voltage reference
110
111 // Read config data from EEPROM
112 if (loadConfig()) {
113 displaycolor = CONFIGURATION.displaycolor;
114 brightness = CONFIGURATION.brightness;
115 }
116
117 //Set brightness loaded from EEPROM
118 pixel.setBrightness(brightness * 24 + 8);
119
120 //Show current config on start
121 //change true to false if you don't want this
122 showSettings(3, true);
123}
124
125void loop() {
126 while (1) { // reduces jitter
127 Sampling(); // FHT Library use only one data array
128 RearrangeFHT(); // re-arrange FHT result to match with no. of display columns
129 SendToDisplay(); // send to display according measured value
130 colorChange(); // check if button pressed to change color
131 brightnessChange(); // check if button pressed to change brightness
132 delay(10); // delay to reduce flickering (FHT is too fast :D)
133 }
134}
135
136void Sampling() {
137 for (int i = 0; i < FHT_N; i++) {
138 while (!(ADCSRA & 0x10)); // wait for ADC to complete current conversion ie ADIF bit set
139 ADCSRA = 0b11110101 ; // clear ADIF bit so that ADC can do next operation (0xf5)
140 //ADLAR bit is 0, so the 10 bits of ADC Data registers are right aligned
141 byte m = ADCL; // fetch adc data
142 byte j = ADCH;
143 int value = (j << 8) | m; // form into an int
144 value -= 0x0200; // form into a signed int
145 value <<= 6; // form into a 16b signed int
146 fht_input[i] = value / 8; // copy to fht input array after compressing
147 }
148 // ++ begin FHT data process -+-+--+-+--+-+--+-+--+-+--+-+--+-+-
149 fht_window(); // window the data for better frequency response
150 fht_reorder(); // reorder the data before doing the fht
151 fht_run(); // process the data in the fht
152 fht_mag_lin(); // take the output of the fht
153}
154
155void RearrangeFHT() {
156 // FHT return real value unsing only one array
157 // after fht_mag_lin() calling the samples value are in
158 // the first FHT_N/2 position of the array fht_lin_out[]
159 int step = (FHT_N / 2) / xres;
160 int c = 0;
161 for (int i = 0; i < (FHT_N / 2); i += step) {
162 data_avgs[c] = 0;
163 for (int k = 0 ; k < step ; k++) {
164 data_avgs[c] = data_avgs[c] + fht_lin_out[i + k]; // linear output magnitude
165 }
166 data_avgs[c] = data_avgs[c] / step ; // save avgs value
167 c++;
168 }
169}
170
171void SendToDisplay() {
172 for (int i = 0; i < xres; i++) {
173 if (EQ_ON)
174 data_avgs[i] = data_avgs[i] * (float)(eq[i]) / 100; // apply eq filter
175 data_avgs[i] = constrain(data_avgs[i], 0, 80); // set max & min values for buckets to 0-80
176 data_avgs[i] = map(data_avgs[i], 0, 80, 0, yres); // remap averaged values to yres 0-8
177 yvalue = data_avgs[i];
178 peaks[i] = peaks[i] - 1; // decay by one light
179 if (yvalue > peaks[i]) peaks[i] = yvalue; // save peak if > previuos peak
180 yvalue = peaks[i]; // pick peak to display
181 setColumn(i, yvalue); // draw columns
182 }
183 pixel.show(); // show column
184}
185
186// Light up leds of x column according to y value
187void setColumn(byte x, byte y) {
188 int led, i;
189
190 for (i = 0; i < yres; i++) {
191 led = GetLedFromMatrix(x, i); //retrieve current led by x,y coordinates
192 if (peaks[x] > i) {
193
194 switch (displaycolor) {
195 case 4:
196 if (colors[displaycolor][i] == 0) {
197 // show custom color with zero value in array
198 pixel.setPixelColor(led, 255, 255, 255); //withe
199 }
200 else {
201 // standard color defined in colors array
202 pixel.setPixelColor(led, Wheel(colors[displaycolor][i]));
203 }
204 break;
205
206 case 5:
207 //change color by column
208 pixel.setPixelColor(led, Wheel(x * 16));
209 break;
210
211 case 6:
212 //change color by row
213 pixel.setPixelColor(led, Wheel(i * y * 3));
214 break;
215
216 case 7:
217 //change color by... country :D
218
219 //Italy flagh
220 //if (x < 11) pixel.setPixelColor(led, 0, 255, 0);
221 //if (x > 10 && x < 21) pixel.setPixelColor(led, 255, 255, 255);
222 //if (x > 20) pixel.setPixelColor(led, 255, 0, 0);
223
224 //stars and stripes
225 if (i < yres - 2) {
226 if (x & 0x01) {
227 pixel.setPixelColor(led, 0, 0, 255);
228 }
229 else {
230 pixel.setPixelColor(led, 255, 0, 0);
231 }
232 }
233 else {
234 pixel.setPixelColor(led, 255, 255, 255);
235 }
236
237 break;
238
239 default:
240 //display colors defined in color array
241 pixel.setPixelColor(led, Wheel(colors[displaycolor][i]));
242 } //END SWITCH
243 }
244 else {
245 //Light off leds
246 pixel.setPixelColor(led, pixel.Color(0, 0, 0));
247 }
248 }
249}
250
251//================================================================
252// Calculate a led number by x,y coordinates
253// valid for WS2812B with serpentine layout placed in horizzontal
254// and zero led at bottom right (DIN connector on the right side)
255// input value: x= 0 to xres-1 , y= 0 to yres-1
256// return a led number from 0 to NUM_LED
257//================================================================
258int GetLedFromMatrix(byte x, byte y) {
259 int led;
260 x = xres - x - 1;
261 if (x & 0x01) {
262 //Odd columns increase backwards
263 led = ((x + 1) * yres - y - 1);
264 }
265 else {
266 //Even columns increase normally
267 led = ((x + 1) * yres - yres + y);
268 }
269 return constrain(led, 0, NUM_LEDS);
270}
271//================================================================
272
273void colorChange() {
274 int reading = digitalRead(colorPIN);
275 if (reading == HIGH && previousState == LOW && millis() - lastDebounceTime > debounceDelay) {
276 displaycolor++;
277 if (displaycolor > 7) displaycolor = 0;
278 showSettings(1, true); //set to false if you don't want this
279 saveConfig();
280 lastDebounceTime = millis();
281 }
282 previousState = reading;
283}
284
285void brightnessChange() {
286 int reading = digitalRead(brightnessPIN);
287 if (reading == HIGH && previousState == LOW && millis() - lastDebounceTime > debounceDelay) {
288 brightness++;
289 if (brightness > 7) brightness = 0;
290 pixel.setBrightness(brightness * 24 + 8);
291 showSettings(2, true); //set to false if you don't want this
292 saveConfig();
293 lastDebounceTime = millis();
294 }
295 previousState = reading;
296}
297
298// Utility from Adafruit Neopixel demo sketch
299// Input a value 0 to 255 to get a color value.
300// The colours are a transition R - G - B - back to R.
301unsigned long Wheel(byte WheelPos) {
302 WheelPos = 255 - WheelPos;
303 if (WheelPos < 85) {
304 return pixel.Color(255 - WheelPos * 3, 0, WheelPos * 3);
305 }
306 if (WheelPos < 170) {
307 WheelPos -= 85;
308 return pixel.Color(0, WheelPos * 3, 255 - WheelPos * 3);
309 }
310 WheelPos -= 170;
311 return pixel.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
312}
313
314// load whats in EEPROM in to the local CONFIGURATION if it is a valid setting
315int loadConfig() {
316 if (EEPROM.read(CONFIG_START + 0) == CONFIG_VERSION[0] &&
317 EEPROM.read(CONFIG_START + 1) == CONFIG_VERSION[1] &&
318 EEPROM.read(CONFIG_START + 2) == CONFIG_VERSION[2] &&
319 EEPROM.read(CONFIG_START + 3) == CONFIG_VERSION[3] &&
320 EEPROM.read(CONFIG_START + 4) == CONFIG_VERSION[4]) {
321
322 // load (overwrite) the local configuration struct
323 for (unsigned int i = 0; i < sizeof(CONFIGURATION); i++) {
324 *((char*)&CONFIGURATION + i) = EEPROM.read(CONFIG_START + i);
325 }
326 return 1; // return 1 if config loaded
327 }
328 return 0; // return 0 if config NOT loaded
329}
330
331// save the CONFIGURATION in to EEPROM
332void saveConfig() {
333 CONFIGURATION.displaycolor = displaycolor;
334 CONFIGURATION.brightness = brightness;
335 for (unsigned int i = 0; i < sizeof(CONFIGURATION); i++)
336 EEPROM.write(CONFIG_START + i, *((char*)&CONFIGURATION + i));
337}
338
339// 1 display color level, 2 display brightness level, 3 both
340void showSettings(byte num, bool show) {
341 if (show) {
342 pixel.clear();
343 if (num == 1 || num == 3) {
344 drawChar(0, 0);
345 drawChar(displaycolor + 1, 5);
346 }
347 if (num == 2 || num == 3) {
348 drawChar(9, xres - 9);
349 drawChar(brightness + 1, xres - 4);
350 }
351 delay(1000);
352 pixel.clear();
353 }
354}
355
356// Draw custom chars
357void drawChar(byte val, byte pos) {
358 for (int x = 4; x >= 0; x--) {
359 for (int y = 5; y >= 0; y--) {
360 if ((charBitmap[val * 6 + 5 - y] >> x) & 0x01) {
361 pixel.setPixelColor(GetLedFromMatrix(4 - x + pos, y + 1), Wheel((pos > 10) * 170));
362 pixel.show();
363 }
364 }
365 }
366}
367//by Janux®, Last version on 28/06/2020.
10khz code
1/*
2 Copyright (c) 2020 Janux
3
4 Permission is hereby granted, free of charge, to any person obtaining a copy
5 of this software and associated documentation files (the "Software"), to deal
6 in the Software without restriction, including without limitation the rights
7 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 copies of the Software, and to permit persons to whom the Software is
9 furnished to do so, subject to the following conditions:
10 The above copyright notice and this permission notice shall be included in all
11 copies or substantial portions of the Software.
12 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
13 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
14 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
15 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
16 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
17 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
18 SOFTWARE.
19
20 Based on an original project for the MAX72xx LED matrix and FFT lib made from Shajeeb.
21 Configuration settings section based on work of Ragnar Ranøyen Homb from Norvegian Creation.
22*/
23
24#define LIN_OUT 1 //FHT linear output magnitude
25#define FHT_N 128 //set SAMPLES for FHT, Must be a power of 2
26#include <FHT.h>
27
28#define xres 32 //Total number of columns in the display, must be <= SAMPLES/2
29#define yres 8 //Total number of rows in the display
30#define ledPIN 6 //out pint to control Leds
31#define NUM_LEDS (xres * yres) //total leds in Matrix
32#include <Adafruit_NeoPixel.h>
33#include <Adafruit_NeoMatrix.h>
34#include <Adafruit_GFX.h>
35
36#define colorPIN 5 //pin to change ledcolor
37#define brightnessPIN 10 //pin to change brightness
38
39byte displaycolor = 0; //default color value
40byte brightness = 1; //default brightness level
41
42#include <EEPROM.h>
43#define CONFIG_START 32 //Memory start location
44#define CONFIG_VERSION "VER01" //Config version configuration
45
46typedef struct {
47 char version[6];
48 byte displaycolor;
49 byte brightness;
50} configuration_type;
51
52configuration_type CONFIGURATION = {
53 CONFIG_VERSION,
54 displaycolor,
55 brightness
56};
57
58byte yvalue;
59int peaks[xres];
60byte state = HIGH; // the current reading from the input pin
61byte previousState = LOW; // the previous reading from the input pin
62unsigned long lastDebounceTime = 0; // the last time the output pin was toggled
63unsigned long debounceDelay = 100; // the debounce time; increase if the output flickers
64
65byte data_avgs[xres]; //Array for samplig
66
67// Parameter 1 = number of leds in matrix
68// Parameter 2 = pin number
69// Parameter 3 = pixel type flags, add together as needed:
70// NEO_KHZ800 800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
71// NEO_KHZ400 400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
72// NEO_GRB Pixels are wired for GRB bitstream (most NeoPixel products)
73// NEO_RGB Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
74Adafruit_NeoPixel pixel = Adafruit_NeoPixel(NUM_LEDS, ledPIN, NEO_GRB + NEO_KHZ800);
75
76// EQ filter
77byte eq[32] = {
78 60, 65, 70, 75, 80, 85, 90, 95,
79 100, 100, 100, 100, 100, 100, 100, 100,
80 100, 100, 100, 100, 100, 100, 100, 100,
81 115, 125, 140, 160, 185, 200, 200, 200
82};
83
84bool EQ_ON = true; // set to false to disable eq
85
86//Define 5 set of colors for leds, 0 for single custom color
87byte colors[][8] = {
88 {170, 160, 150, 140, 130, 120, 1, 1},
89 {1, 5, 10, 15, 20, 25, 90, 90},
90 {90, 85, 80, 75, 70, 65, 1, 1},
91 {90, 90, 90, 30, 30, 30, 1, 1},
92 {170, 160, 150, 140, 130, 120, 110, 0}
93};
94
95//Define chars for display settings
96byte charBitmap[] = {
97 0x1C, 0x10, 0x10, 0x10, 0x10, 0x1C, 0x08, 0x18, 0x08, 0x08, 0x08, 0x1C,
98 0x0C, 0x12, 0x04, 0x08, 0x10, 0x1E, 0x0C, 0x12, 0x02, 0x06, 0x12, 0x0C,
99 0x10, 0x10, 0x10, 0x14, 0x1E, 0x04, 0x1E, 0x10, 0x1E, 0x02, 0x12, 0x0C,
100 0x1E, 0x10, 0x10, 0x1E, 0x12, 0x1E, 0x1E, 0x02, 0x04, 0x08, 0x08, 0x08,
101 0x0C, 0x12, 0x0C, 0x12, 0x12, 0x0C, 0x1C, 0x12, 0x1C, 0x12, 0x12, 0x1C
102};
103
104void setup() {
105
106 pixel.begin(); //initialize Led Matrix
107
108 //Begin FFT operations
109 ADCSRA = 0b11100101; // set ADC to free running mode and set pre-scaler to 32 (0xe5)
110 ADMUX = 0b00000000; // use pin A0 and external voltage reference
111
112 // Read config data from EEPROM
113 if (loadConfig()) {
114 displaycolor = CONFIGURATION.displaycolor;
115 brightness = CONFIGURATION.brightness;
116 }
117
118 //Set brightness loaded from EEPROM
119 pixel.setBrightness(brightness * 24 + 8);
120
121 //Show current config on start
122 //change true to false if you don't want this
123 showSettings(3, true);
124}
125
126void loop() {
127 while (1) { // reduces jitter
128 Sampling(); // FHT Library use only one data array
129 RearrangeFHT(); // re-arrange FHT result to match with no. of display columns
130 SendToDisplay(); // send to display according measured value
131 colorChange(); // check if button pressed to change color
132 brightnessChange(); // check if button pressed to change brightness
133 delay(10); // delay to reduce flickering (FHT is too fast :D)
134 }
135}
136
137void Sampling() {
138 for (int i = 0; i < FHT_N; i++) {
139 while (!(ADCSRA & 0x10)); // wait for ADC to complete current conversion ie ADIF bit set
140 ADCSRA = 0xf6 ; // clear ADIF bit so that ADC can do next operation (0xf5)
141 //ADLAR bit is 0, so the 10 bits of ADC Data registers are right aligned
142 byte m = ADCL; // fetch adc data
143 byte j = ADCH;
144 int value = (j << 8) | m; // form into an int
145 value -= 0x0200; // form into a signed int
146 value <<= 6; // form into a 16b signed int
147 fht_input[i] = value / 8; // copy to fht input array after compressing
148 }
149 // ++ begin FHT data process -+-+--+-+--+-+--+-+--+-+--+-+--+-+-
150 fht_window(); // window the data for better frequency response
151 fht_reorder(); // reorder the data before doing the fht
152 fht_run(); // process the data in the fht
153 fht_mag_lin(); // take the output of the fht
154}
155
156void RearrangeFHT() {
157 // FHT return real value unsing only one array
158 // after fht_mag_lin() calling the samples value are in
159 // the first FHT_N/2 position of the array fht_lin_out[]
160 int step = (FHT_N / 2) / xres;
161 int c = 0;
162 for (int i = 0; i < (FHT_N / 2); i += step) {
163 data_avgs[c] = 0;
164 for (int k = 0 ; k < step ; k++) {
165 data_avgs[c] = data_avgs[c] + fht_lin_out[i + k]; // linear output magnitude
166 }
167 data_avgs[c] = data_avgs[c] / step ; // save avgs value
168 c++;
169 }
170}
171
172void SendToDisplay() {
173 for (int i = 0; i < xres; i++) {
174 if (EQ_ON)
175 data_avgs[i] = data_avgs[i] * (float)(eq[i]) / 100; // apply eq filter
176 data_avgs[i] = constrain(data_avgs[i], 0, 80); // set max & min values for buckets to 0-80
177 data_avgs[i] = map(data_avgs[i], 0, 80, 0, yres); // remap averaged values to yres 0-8
178 yvalue = data_avgs[i];
179 peaks[i] = peaks[i] - 1; // decay by one light
180 if (yvalue > peaks[i]) peaks[i] = yvalue; // save peak if > previuos peak
181 yvalue = peaks[i]; // pick peak to display
182 setColumn(i, yvalue); // draw columns
183 }
184 pixel.show(); // show column
185}
186
187// Light up leds of x column according to y value
188void setColumn(byte x, byte y) {
189 int led, i;
190
191 for (i = 0; i < yres; i++) {
192 led = GetLedFromMatrix(x, i); //retrieve current led by x,y coordinates
193 if (peaks[x] > i) {
194
195 switch (displaycolor) {
196 case 4:
197 if (colors[displaycolor][i] == 0) {
198 // show custom color with zero value in array
199 pixel.setPixelColor(led, 255, 255, 255); //withe
200 }
201 else {
202 // standard color defined in colors array
203 pixel.setPixelColor(led, Wheel(colors[displaycolor][i]));
204 }
205 break;
206
207 case 5:
208 //change color by column
209 pixel.setPixelColor(led, Wheel(x * 16));
210 break;
211
212 case 6:
213 //change color by row
214 pixel.setPixelColor(led, Wheel(i * y * 3));
215 break;
216
217 case 7:
218 //change color by... country :D
219
220 //Italy flagh
221 //if (x < 11) pixel.setPixelColor(led, 0, 255, 0);
222 //if (x > 10 && x < 21) pixel.setPixelColor(led, 255, 255, 255);
223 //if (x > 20) pixel.setPixelColor(led, 255, 0, 0);
224
225 //stars and stripes
226 if (i < yres - 2) {
227 if (x & 0x01) {
228 pixel.setPixelColor(led, 0, 0, 255);
229 }
230 else {
231 pixel.setPixelColor(led, 255, 0, 0);
232 }
233 }
234 else {
235 pixel.setPixelColor(led, 255, 255, 255);
236 }
237
238 break;
239
240 default:
241 //display colors defined in color array
242 pixel.setPixelColor(led, Wheel(colors[displaycolor][i]));
243 } //END SWITCH
244 }
245 else {
246 //Light off leds
247 pixel.setPixelColor(led, pixel.Color(0, 0, 0));
248 }
249 }
250}
251
252//================================================================
253// Calculate a led number by x,y coordinates
254// valid for WS2812B with serpentine layout placed in horizzontal
255// and zero led at bottom right (DIN connector on the right side)
256// input value: x= 0 to xres-1 , y= 0 to yres-1
257// return a led number from 0 to NUM_LED
258//================================================================
259int GetLedFromMatrix(byte x, byte y) {
260 int led;
261 x = xres - x - 1;
262 if (x & 0x01) {
263 //Odd columns increase backwards
264 led = ((x + 1) * yres - y - 1 );
265 }
266 else {
267 //Even columns increase normally
268 led = ((x + 1) * yres - yres + y);
269 }
270 return constrain(led, 0, NUM_LEDS);
271}
272//================================================================
273
274void colorChange() {
275 int reading = digitalRead(colorPIN);
276 if (reading == HIGH && previousState == LOW && millis() - lastDebounceTime > debounceDelay) {
277 displaycolor++;
278 if (displaycolor > 7) displaycolor = 0;
279 showSettings(1, true); //set to false if you don't want this
280 saveConfig();
281 lastDebounceTime = millis();
282 }
283 previousState = reading;
284}
285
286void brightnessChange() {
287 int reading = digitalRead(brightnessPIN);
288 if (reading == HIGH && previousState == LOW && millis() - lastDebounceTime > debounceDelay) {
289 brightness++;
290 if (brightness > 7) brightness = 0;
291 pixel.setBrightness(brightness * 24 + 8);
292 showSettings(2, true); //set to false if you don't want this
293 saveConfig();
294 lastDebounceTime = millis();
295 }
296 previousState = reading;
297}
298
299// Utility from Adafruit Neopixel demo sketch
300// Input a value 0 to 255 to get a color value.
301// The colours are a transition R - G - B - back to R.
302unsigned long Wheel(byte WheelPos) {
303 WheelPos = 255 - WheelPos;
304 if (WheelPos < 85) {
305 return pixel.Color(255 - WheelPos * 3, 0, WheelPos * 3);
306 }
307 if (WheelPos < 170) {
308 WheelPos -= 85;
309 return pixel.Color(0, WheelPos * 3, 255 - WheelPos * 3);
310 }
311 WheelPos -= 170;
312 return pixel.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
313}
314
315// load whats in EEPROM in to the local CONFIGURATION if it is a valid setting
316int loadConfig() {
317 if (EEPROM.read(CONFIG_START + 0) == CONFIG_VERSION[0] &&
318 EEPROM.read(CONFIG_START + 1) == CONFIG_VERSION[1] &&
319 EEPROM.read(CONFIG_START + 2) == CONFIG_VERSION[2] &&
320 EEPROM.read(CONFIG_START + 3) == CONFIG_VERSION[3] &&
321 EEPROM.read(CONFIG_START + 4) == CONFIG_VERSION[4]) {
322
323 // load (overwrite) the local configuration struct
324 for (unsigned int i = 0; i < sizeof(CONFIGURATION); i++) {
325 *((char*)&CONFIGURATION + i) = EEPROM.read(CONFIG_START + i);
326 }
327 return 1; // return 1 if config loaded
328 }
329 return 0; // return 0 if config NOT loaded
330}
331
332// save the CONFIGURATION in to EEPROM
333void saveConfig() {
334 CONFIGURATION.displaycolor = displaycolor;
335 CONFIGURATION.brightness = brightness;
336 for (unsigned int i = 0; i < sizeof(CONFIGURATION); i++)
337 EEPROM.write(CONFIG_START + i, *((char*)&CONFIGURATION + i));
338}
339
340// 1 display color level, 2 display brightness level, 3 both
341void showSettings(byte num, bool show) {
342 if (show) {
343 pixel.clear();
344 if (num == 1 || num == 3) {
345 drawChar(0, 0);
346 drawChar(displaycolor + 1, 5);
347 }
348 if (num == 2 || num == 3) {
349 drawChar(9, xres - 9);
350 drawChar(brightness + 1, xres - 4);
351 }
352 delay(1000);
353 pixel.clear();
354 }
355}
356
357// Draw custom chars
358void drawChar(byte val, byte pos) {
359 for (int x = 4; x >= 0; x--) {
360 for (int y = 5; y >= 0; y--) {
361 if ((charBitmap[val * 6 + 5 - y] >> x) & 0x01) {
362 pixel.setPixelColor(GetLedFromMatrix(4 - x + pos, y + 1), Wheel((pos > 10) * 170));
363 pixel.show();
364 }
365 }
366 }
367}
368//by Janux®, Last version on 28/06/2020.
Downloadable files
Schematic
Diagram.jpg
Note: Content and images are from: https://projecthub.arduino.cc/, with some modifications.
If you want it removed due to copyright reasons, please leave a comment. Thank you.
I want to share this article more widely so that everyone knows about Arduino and your project.