Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
co2ampel
ampel-firmware
Commits
443cf3bf
Commit
443cf3bf
authored
May 07, 2021
by
Eric Duminil
Browse files
led_effects: Allowing choice between 12 & 16 LEDs
parent
b13b1a6c
Changes
2
Hide whitespace changes
Inline
Side-by-side
ampel-firmware/config.public.h
View file @
443cf3bf
...
...
@@ -64,6 +64,8 @@
// MIN_BRIGHTNESS, if defined, should be between 0 and MAX_BRIGHTNESS - 1
// If MIN_BRIGHTNESS is not set, or if it is set to MAX_BRIGHTNESS, breathing is disabled.
# define MIN_BRIGHTNESS 60
// How many LEDs in the ring? 12 and 16 are currently supported. If undefined, 12 is used as default.
# define LED_COUNT 12
/**
* WEB SERVER
...
...
ampel-firmware/led_effects.cpp
View file @
443cf3bf
...
...
@@ -12,8 +12,28 @@ namespace config {
const
uint8_t
brightness_amplitude
=
config
::
max_brightness
-
config
::
min_brightness
;
const
int
kitt_tail
=
3
;
// How many dimmer LEDs follow in K.I.T.T. wheel
const
uint16_t
poor_air_quality_ppm
=
1600
;
// Above this threshold, LED breathing effect is faster.
//NOTE: Use a class instead? NightMode could then be another state.
bool
night_mode
=
false
;
bool
night_mode
=
false
;
//NOTE: Use a class instead? NightMode could then be another state.
#if !defined(LED_COUNT)
# define LED_COUNT 12
#endif
const
uint16_t
led_count
=
LED_COUNT
;
#if LED_COUNT == 12
//NOTE: One value has been prepended, to make calculations easier and avoid out of bounds index.
const
uint16_t
co2_ticks
[
led_count
+
1
]
=
{
0
,
500
,
600
,
700
,
800
,
900
,
1000
,
1200
,
1400
,
1600
,
1800
,
2000
,
2200
};
// [ppm]
// For a given LED, which color should be displayed? First LED will be pure green (hue angle 120°),
// last 4 LEDs will be pure red (hue angle 0°), LEDs in-between will be yellowish.
const
uint16_t
led_hues
[
led_count
]
=
{
21845U
,
19114U
,
16383U
,
13653U
,
10922U
,
8191U
,
5461U
,
2730U
,
0
,
0
,
0
,
0
};
// [hue angle]
#elif LED_COUNT == 16
const
uint16_t
co2_ticks
[
led_count
+
1
]
=
{
0
,
400
,
500
,
600
,
700
,
800
,
900
,
1000
,
1100
,
1200
,
1300
,
1400
,
1500
,
1600
,
1800
,
2000
,
2200
};
// [ppm]
const
uint16_t
led_hues
[
led_count
]
=
{
21845U
,
20024U
,
18204U
,
16383U
,
14563U
,
12742U
,
10922U
,
9102U
,
7281U
,
5461U
,
3640U
,
1820U
,
0
,
0
,
0
,
0
};
// [hue angle]
#else
# error "Only 12 and 16 LEDs rings are currently supported."
#endif
}
#if defined(ESP8266)
...
...
@@ -24,20 +44,7 @@ const int NEOPIXELS_PIN = 5;
const
int
NEOPIXELS_PIN
=
23
;
#endif
const
int
NUMPIXELS
=
12
;
//NOTE: One value has been prepended, to make calculations easier and avoid out of bounds index.
const
uint16_t
CO2_TICKS
[
NUMPIXELS
+
1
]
=
{
0
,
500
,
600
,
700
,
800
,
900
,
1000
,
1200
,
1400
,
1600
,
1800
,
2000
,
2200
};
// [ppm]
// const uint16_t CO2_TICKS[NUMPIXELS + 1] = { 0, 400, 500, 600, 700, 800, 900, 1000, 1100, 1200, 1300, 1400, 1500, 1600, 1800, 2000, 2200 }; // [ppm]
// For a given LED, which color should be displayed? First LED will be pure green (hue angle 120°),
// last 4 LEDs will be pure red (hue angle 0°), LEDs in-between will be yellowish.
// For reference, this python code can be used to generate the array
// NUMPIXELS = 12
// RED_LEDS = 4
// hues = [ (2**16-1) // 3 * max(NUMPIXELS - RED_LEDS - i, 0) // (NUMPIXELS - RED_LEDS) for i in range(NUMPIXELS) ]
// '{' + ', '.join([str(hue) + ('U' if hue else '') for hue in hues]) + '}; // [hue angle]'
const
uint16_t
LED_HUES
[
NUMPIXELS
]
=
{
21845U
,
19114U
,
16383U
,
13653U
,
10922U
,
8191U
,
5461U
,
2730U
,
0
,
0
,
0
,
0
};
// [hue angle]
// const uint16_t LED_HUES[NUMPIXELS] = { 21845U, 20024U, 18204U, 16383U, 14563U, 12742U, 10922U, 9102U, 7281U, 5461U, 3640U, 1820U, 0, 0, 0, 0 }; // [hue angle]
Adafruit_NeoPixel
pixels
(
NUMPIXELS
,
NEOPIXELS_PIN
,
NEO_GRB
+
NEO_KHZ800
);
Adafruit_NeoPixel
pixels
(
config
::
led_count
,
NEOPIXELS_PIN
,
NEO_GRB
+
NEO_KHZ800
);
namespace
led_effects
{
//On-board LED on D4, aka GPIO02
...
...
@@ -97,14 +104,15 @@ namespace led_effects {
//NOTE: basically one iteration of KITT wheel
void
showWaitingLED
(
uint32_t
color
)
{
using
namespace
config
;
delay
(
80
);
if
(
config
::
night_mode
)
{
if
(
night_mode
)
{
return
;
}
static
uint16_t
kitt_offset
=
0
;
pixels
.
clear
();
for
(
int
j
=
config
::
kitt_tail
;
j
>=
0
;
j
--
)
{
int
ledNumber
=
abs
((
kitt_offset
-
j
+
NUMPIXELS
)
%
(
2
*
NUMPIXELS
)
-
NUMPIXELS
)
%
NUMPIXELS
;
// Triangular function
for
(
int
j
=
kitt_tail
;
j
>=
0
;
j
--
)
{
int
ledNumber
=
abs
((
kitt_offset
-
j
+
led_count
)
%
(
2
*
led_count
)
-
led_count
)
%
led_count
;
// Triangular function
pixels
.
setPixelColor
(
ledNumber
,
color
*
pixels
.
gamma8
(
255
-
j
*
76
)
/
255
);
}
pixels
.
show
();
...
...
@@ -116,7 +124,7 @@ namespace led_effects {
// Takes approximately 1s for each direction.
void
showKITTWheel
(
uint32_t
color
,
uint16_t
duration_s
)
{
pixels
.
setBrightness
(
config
::
max_brightness
);
for
(
int
i
=
0
;
i
<
duration_s
*
NUMPIXELS
;
++
i
)
{
for
(
int
i
=
0
;
i
<
duration_s
*
config
::
led_count
;
++
i
)
{
showWaitingLED
(
color
);
}
}
...
...
@@ -126,10 +134,10 @@ namespace led_effects {
* For example, for 1500ppm, every LED between 0 and 7 (500 -> 1400ppm) should be on, LED at 8 (1600ppm) should be half-on.
*/
uint8_t
getLedBrightness
(
uint16_t
co2
,
int
ledId
)
{
if
(
co2
>=
CO2_TICKS
[
ledId
+
1
])
{
if
(
co2
>=
config
::
co2_ticks
[
ledId
+
1
])
{
return
255
;
}
else
{
if
(
2
*
co2
>=
CO2_TICKS
[
ledId
]
+
CO2_TICKS
[
ledId
+
1
])
{
if
(
2
*
co2
>=
config
::
co2_ticks
[
ledId
]
+
config
::
co2_ticks
[
ledId
+
1
])
{
// Show partial LED if co2 more than halfway between ticks.
return
27
;
// Brightness isn't linear, so 27 / 255 looks much brighter than 10%
}
else
{
...
...
@@ -158,9 +166,9 @@ namespace led_effects {
return
;
}
pixels
.
setBrightness
(
config
::
max_brightness
);
for
(
int
ledId
=
0
;
ledId
<
NUMPIXELS
;
++
ledId
)
{
for
(
int
ledId
=
0
;
ledId
<
config
::
led_count
;
++
ledId
)
{
uint8_t
brightness
=
getLedBrightness
(
co2
,
ledId
);
pixels
.
setPixelColor
(
ledId
,
pixels
.
ColorHSV
(
LED_HUES
[
ledId
],
255
,
brightness
));
pixels
.
setPixelColor
(
ledId
,
pixels
.
ColorHSV
(
config
::
led_hues
[
ledId
],
255
,
brightness
));
}
pixels
.
show
();
if
(
config
::
brightness_amplitude
>
0
)
{
...
...
@@ -177,8 +185,8 @@ namespace led_effects {
unsigned
long
t0
=
millis
();
pixels
.
setBrightness
(
config
::
max_brightness
);
while
(
millis
()
-
t0
<
duration_ms
)
{
for
(
int
i
=
0
;
i
<
NUMPIXELS
;
i
++
)
{
pixels
.
setPixelColor
(
i
,
pixels
.
ColorHSV
(
i
*
65535
/
NUMPIXELS
+
wheel_offset
));
for
(
int
i
=
0
;
i
<
config
::
led_count
;
i
++
)
{
pixels
.
setPixelColor
(
i
,
pixels
.
ColorHSV
(
i
*
65535
/
config
::
led_count
+
wheel_offset
));
wheel_offset
+=
(
pixels
.
sine8
(
sine_offset
++
/
50
)
-
127
)
/
2
;
}
pixels
.
show
();
...
...
@@ -215,7 +223,7 @@ namespace led_effects {
pixels
.
fill
(
color
::
blue
);
pixels
.
show
();
int
countdown
;
for
(
countdown
=
NUMPIXELS
;
countdown
>=
0
&&
!
digitalRead
(
0
);
countdown
--
)
{
for
(
countdown
=
config
::
led_count
;
countdown
>=
0
&&
!
digitalRead
(
0
);
countdown
--
)
{
pixels
.
setPixelColor
(
countdown
,
color
::
black
);
pixels
.
show
();
Serial
.
println
(
countdown
);
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment