From 100b1f99dc6559993b8b594cc8d14efebf742397 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) - white separator indicates "start of radiation display" - 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 | 8 +++ multigeiger/status_led.cpp | 105 ++++++++++++++++++++++++++++++ multigeiger/status_led.h | 16 +++++ multigeiger/userdefines-example.h | 3 + 4 files changed, 132 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 160bcc0b..a36ae10f 100644 --- a/multigeiger/multigeiger.ino +++ b/multigeiger/multigeiger.ino @@ -84,6 +84,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)) @@ -356,6 +358,9 @@ void setup() // OLED-Display u8x8.begin(); + // init RGB LED + indicate(0.0, I_RESET); + // set IO-Pins pinMode (LED_BUILTIN, OUTPUT); pinMode (PIN_HV_FET_OUTPUT, OUTPUT); @@ -532,6 +537,9 @@ void loop() Dose_Rate = Count_Rate *GMC_factor_uSvph; // ... and dose rate + // indicate status on RGB LED (if any) + indicate(Dose_Rate, I_RESET | 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..85f0ff11 --- /dev/null +++ b/multigeiger/status_led.cpp @@ -0,0 +1,105 @@ +// 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); + +NeoPixelBus LEDs(PIXEL_COUNT, PIXEL_PIN); + +static RgbColor last_col = black; + +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; +} + +void init_LED(void) { + LEDs.Begin(); // all LEDs off + LEDs.Show(); + last_col = black; // consistency sw state == hw state +} + +#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; + int r, g, b; + 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: + r = indication & I_CONN_ERROR; + g = indication & I_TEST; + b = indication & I_HV_ERROR; + col = RgbColor(r ? 255 : 0, g ? 255 : 0, b ? 255 : 0); + 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..afee0b4e --- /dev/null +++ b/multigeiger/status_led.h @@ -0,0 +1,16 @@ +// show status indication via WS2812 RGB LED + +// indication value used to reset indications to "all off" +#define I_RESET 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 once from setup() like this: +// indicate(0.0, I_RESET) +// you should call this in regular time intervals [e.g. 1s] from loop() like this: +// indicate(radiation_uSvh, indication) +void indicate(float radiation, unsigned int indication); diff --git a/multigeiger/userdefines-example.h b/multigeiger/userdefines-example.h index b9264f00..82a0fefe 100644 --- a/multigeiger/userdefines-example.h +++ b/multigeiger/userdefines-example.h @@ -57,6 +57,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! // *********************************************************************************