From b3d5503aaa0deddccc58ddf114a6268eeed636fb Mon Sep 17 00:00:00 2001 From: Thomas Waldmann Date: Mon, 3 Feb 2020 22:15:08 +0100 Subject: [PATCH] add optional support for WS2812 RGB LED, fixes #106 specific indexes in the LED color time sequence are used for: - dark separator indicates "start of sequence" (also used for LED init and re-init) - color according to indications (3bits encoded via RGB color) (can be extended to show up to 32 indication bits) (dark if there is nothing to indicate) - white separator indicates "start of radiation display" (also works as LED test, white = R on + G on + B on) - color according to radiation (repeated, displayed most of the time) dark (unusually low / 0) green (normal) yellow (more than normal) red (much more than normal) --- multigeiger/multigeiger.ino | 5 ++ multigeiger/status_led.cpp | 107 ++++++++++++++++++++++++++++++ multigeiger/status_led.h | 15 +++++ multigeiger/userdefines-example.h | 3 + platformio-example.ini | 1 + 5 files changed, 131 insertions(+) create mode 100644 multigeiger/status_led.cpp create mode 100644 multigeiger/status_led.h diff --git a/multigeiger/multigeiger.ino b/multigeiger/multigeiger.ino index dd02af96..c6229fb5 100644 --- a/multigeiger/multigeiger.ino +++ b/multigeiger/multigeiger.ino @@ -83,6 +83,8 @@ #include #include +// for RGB LED +#include "status_led.h" // Check if a CPU (board) with LoRa is selected. If not, deactivate SEND2LORA. #if !((CPU==LORA) || (CPU==STICK)) @@ -553,6 +555,9 @@ void loop() { Dose_Rate = Count_Rate * GMC_factor_uSvph; // ... and dose rate + // indicate status on RGB LED (if any) + indicate(Dose_Rate, I_TEST); + // calculate the radiation over the complete time from start accumulated_Count_Rate = 0.0; if (accumulated_time != 0) { diff --git a/multigeiger/status_led.cpp b/multigeiger/status_led.cpp new file mode 100644 index 00000000..a1640d75 --- /dev/null +++ b/multigeiger/status_led.cpp @@ -0,0 +1,107 @@ +// show status indication via WS2812 RGB LED + +#include "userdefines.h" + +#if STATUS_LED==1 // we have a WS2812 RGB LED! + +#include + +#include "status_led.h" + +#define PIXEL_COUNT 1 +#define PIXEL_PIN 25 + +RgbColor red(255, 0, 0); +RgbColor green(0, 255, 0); +RgbColor blue(0, 0, 255); +RgbColor yellow(255, 255, 0); +RgbColor white(255, 255, 255); +RgbColor black(0, 0, 0); + +static NeoPixelBus LEDs(PIXEL_COUNT, PIXEL_PIN); + +static RgbColor last_col = black; + +static void set_LED(RgbColor col) { + if (col == last_col) + return; // nothing to change + + LEDs.SetPixelColor(0, col); // only 1 LED at index 0 + LEDs.Show(); + last_col = col; +} + +static void init_LED(void) { + LEDs.Begin(); // all LEDs off + LEDs.Show(); + last_col = black; // consistency sw state == hw state +} + +static void compute_color(unsigned int indication, + unsigned int mask_r, unsigned int mask_g, unsigned int mask_b, + RgbColor *color) { + // assign to *color depending on whether the r/g/b masked bits are set in the indication value + *color = RgbColor((indication & mask_r) ? 255 : 0, + (indication & mask_g) ? 255 : 0, + (indication & mask_b) ? 255 : 0) +} + +#define IDX_W 2 +#define CSL 30 + +void indicate(float radiation, unsigned int indication) { + // radiation [uSv/h] given to set the primary color R that is shown most of the time + // indication: 32 bit flags to indicate additional stuff, see status_led.h. + // + // this code will generate a time sequence of LED colors: + // index color + // ------------------------------------------------------ + // 0 dark (LED init) + // 1 indication color 1 + // ... reserved for more indications + // IDX_W white (LED test) + // ...+1 radiation color + // ... radiation color + // CSL-1 radiation color + + RgbColor col; + static int index = 0; // index counting modulo COLOR_SEQUENCE_LENGTH + + switch (index) { + case 0: // show a fixed dark separator after LED init + init_LED(); // (re-)init the LED + col = black; + break; + case 1: + // indication color 1: R G B + compute_color(indication, I_CONN_ERROR, I_TEST, I_HV_ERROR, &col); + break; + case IDX_W: // show a fixed white separator and LED test + col = white; + break; + default: // show radiation color + if (radiation > 1.0) { + col = red; + } else if (radiation > 0.2) { + col = yellow; + } else if (radiation > 0.01) { + col = green; + } else { + col = black; + } + } + + set_LED(col); + + if (++index == CSL) + index = 0; +} + +#else // no STATUS_LED + +void indicate(float radiation, unsigned int indication) { + // do nothing +} + +#endif // STATUS_LED + diff --git a/multigeiger/status_led.h b/multigeiger/status_led.h new file mode 100644 index 00000000..2a23f8bf --- /dev/null +++ b/multigeiger/status_led.h @@ -0,0 +1,15 @@ +// show status indication via WS2812 RGB LED + +// indication value used to reset indications to "all off" +#define I_RESET 0 +// indication value used to mask no bit, e.g. in compute_color +#define I_NONE 0 + +// indications, values are 32bit bit masks, valid values are 2^N +#define I_TEST 1 // reserved to test the indication code +#define I_HV_ERROR 2 // there is a problem with high voltage generation +#define I_CONN_ERROR 4 // there is a problem with the network connection + +// indicate radiation and special indications via a color time sequence. +// you should call this in regular time intervals [e.g. 1s]. +void indicate(float radiation, unsigned int indication); diff --git a/multigeiger/userdefines-example.h b/multigeiger/userdefines-example.h index 02d31e3e..485583fd 100644 --- a/multigeiger/userdefines-example.h +++ b/multigeiger/userdefines-example.h @@ -61,6 +61,9 @@ // Note: The TTN configuration needs to be done in lorawan.cpp (starting at line 65). #define SEND2LORA 0 +// 0: no RGB status LED, 1: WS2812B status LED +#define STATUS_LED 1 + // ********************************************************************************* // END of user changeable parameters. Do not edit beyond this point! // ********************************************************************************* diff --git a/platformio-example.ini b/platformio-example.ini index d4c42983..fd8fc460 100644 --- a/platformio-example.ini +++ b/platformio-example.ini @@ -44,4 +44,5 @@ lib_deps= Adafruit BME280 Library Adafruit Unified Sensor IotWebConf + NeoPixelBus