diff --git a/multigeiger/multigeiger.ino b/multigeiger/multigeiger.ino index 4de753b..b55f5a3 100644 --- a/multigeiger/multigeiger.ino +++ b/multigeiger/multigeiger.ino @@ -18,6 +18,7 @@ #include "ble.h" #include "chkhardware.h" #include "clock.h" +#include "status_led.h" // Measurement interval (default 2.5min) [sec] #define MEASUREMENT_INTERVAL 150 @@ -42,6 +43,7 @@ static Switches switches; void setup() { bool isLoraBoard = init_hwtest(); setup_log(DEFAULT_LOG_LEVEL); + setup_status_LED(); setup_display(isLoraBoard); setup_switches(isLoraBoard); switches = read_switches(); // only read DIP switches once at boot time @@ -138,6 +140,9 @@ void publish(unsigned long current_ms, unsigned long current_counts, unsigned lo float Count_Rate = (dt != 0) ? (float)counts * 1000.0 / (float)dt : 0.0; float Dose_Rate = Count_Rate * GMC_factor_uSvph; + // indicate status on RGB LED (if any) + indicate(Dose_Rate, I_TEST); + // calculate the count rate and dose rate over the complete time from start accumulated_Count_Rate = (accumulated_time != 0) ? (float)accumulated_GMC_counts * 1000.0 / (float)accumulated_time : 0.0; accumulated_Dose_Rate = accumulated_Count_Rate * GMC_factor_uSvph; diff --git a/multigeiger/status_led.cpp b/multigeiger/status_led.cpp new file mode 100644 index 0000000..892756c --- /dev/null +++ b/multigeiger/status_led.cpp @@ -0,0 +1,98 @@ +// show status indication via WS2812 RGB LED + +#include "userdefines.h" + +#include + +#include "log.h" +#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; + +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; +} + +void setup_status_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 + + log(INFO, "LED index: %d, radiation: %f", index, radiation); + + switch (index) { + case 0: // show a fixed dark separator after LED init + 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; +} diff --git a/multigeiger/status_led.h b/multigeiger/status_led.h new file mode 100644 index 0000000..22d6eb5 --- /dev/null +++ b/multigeiger/status_led.h @@ -0,0 +1,17 @@ +// 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); + +void setup_status_LED(void); diff --git a/platformio-example.ini b/platformio-example.ini index d7e5963..9d08704 100644 --- a/platformio-example.ini +++ b/platformio-example.ini @@ -31,3 +31,4 @@ lib_deps= IotWebConf MCCI LoRaWAN LMIC library h2zero/NimBLE-Arduino + NeoPixelBus@>=2.6.0,!=2.6.2,<3.0.0