diff --git a/include/ColorUtil.h b/include/ColorUtil.h new file mode 100644 index 0000000..ebdac16 --- /dev/null +++ b/include/ColorUtil.h @@ -0,0 +1,45 @@ +/** + * @brief ColorUtil collection + * @file ColorUtil.h + * + */ + +#ifndef COLOR_UTIL +#define COLOR_UTIL + +#include +#ifndef UNIT_TEST +#include + +typedef enum dir_t { + FORWARD = 0, + BACKWARD +} Direction; + + +void RainbowCycle (Adafruit_NeoPixel* pix, uint8_t *pIndex); +#endif + +/** + * @brief Extract color form a given string + * possible values are: + * - red + * - green + * - blue + * - white + * - black + * - off + * - #RRGGBB (red, green blue as hex values: 0-F (uppercase)) + * - #rrggbb (red, green blue as hex values: 0-f (lowercase)) + * @param text The text with the color information + * @param length The amount of characters in the given text + * @return uint32_t 32-bit color value. Most significant byte is white (for RGBW + pixels) or ignored (for RGB pixels), next is red, then green, + and least significant byte is blue. + */ +uint32_t extractColor(const char *text, int length); + + +uint32_t Color(uint8_t r, uint8_t g, uint8_t b); + +#endif /* COLOR_UTIL */ \ No newline at end of file diff --git a/include/controller.h b/include/controller.h index 250f84d..ea2c033 100644 --- a/include/controller.h +++ b/include/controller.h @@ -16,10 +16,10 @@ #define GPIO_DS18B20 D2 /**< One-Wire used for Dallas temperature sensor */ -#define WS2812SINGLE_GPIO_PIN D5 +#define WS2812SINGLE_GPIO_PIN D3 #define WS2812SINGLE_LEDS 3 -#define WS2812STRIP_GPIO_PIN D3 +#define WS2812STRIP_GPIO_PIN D5 #define WS2812STRIP_LEDS 13 #endif /* End FANLEDCTL_PINS */ \ No newline at end of file diff --git a/src/ColorUtil.cpp b/src/ColorUtil.cpp new file mode 100644 index 0000000..b878ac3 --- /dev/null +++ b/src/ColorUtil.cpp @@ -0,0 +1,147 @@ +/** + * @brief ColorUtil collection + * @file ColorUtil.c + * + * See: + * https://learn.adafruit.com/multi-tasking-the-arduino-part-3/utility-functions + */ +#include "ColorUtil.h" +#include "string.h" +#include + +#define MIN(a, b) ((a) > (b) ? b : a) +#define COMPARE_STR(text,length, staticText) strncmp(text, staticText, MIN(length, (int) strlen(staticText))) + +#ifdef UNIT_TEST +#include "test_helper.h" +#else +#include + + +/*! + @brief Convert separate red, green and blue values into a single + "packed" 32-bit RGB color. + @param r Red brightness, 0 to 255. + @param g Green brightness, 0 to 255. + @param b Blue brightness, 0 to 255. + + Copied from Adafruit_NeoPixel.h + + @return 32-bit packed RGB value, which can then be assigned to a + variable for later use or passed to the setPixelColor() + function. Packed RGB format is predictable, regardless of + LED strand color order. + */ +uint32_t Color(uint8_t r, uint8_t g, uint8_t b) { + return ((uint32_t)r << 16) | ((uint32_t)g << 8) | b; +} + +/** + * @brief + * + * @param WheelPos + * + * The colours are a transition r - g - b - back to r + * + * @return uint32_t + */ +uint32_t Wheel(uint8_t WheelPos) +{ + WheelPos = 255 - WheelPos; + if(WheelPos < 85) + { + return Color(255 - WheelPos * 3, 0, WheelPos * 3); + } + else if(WheelPos < 170) + { + WheelPos -= 85; + return Color(0, WheelPos * 3, 255 - WheelPos * 3); + } + else + { + WheelPos -= 170; + return Color(WheelPos * 3, 255 - WheelPos * 3, 0); + } +} + +void RainbowCycle (Adafruit_NeoPixel* pix, uint8_t *pIndex) +{ + uint8_t Index = (*pIndex); + for(int i=0; i< pix->numPixels(); i++) + { + pix->setPixelColor(i, Wheel(((i * 256 / pix->numPixels()) + Index) & 255)); + } + (*pIndex) = Index + 1; + pix->show(); +} +#endif + +uint32_t extractColor(const char *text, int length) { + int parsed = 0; + + /* invalid values are returned as black */ + if ((length <= 0) || + (text == NULL) || + (strlen(text) < (unsigned int) length)){ + return 0xFFFFFFFF; + } + if ( (COMPARE_STR(text, length, "off") == 0) || (COMPARE_STR(text, length, "OFF") == 0) || + (COMPARE_STR(text, length, "black") == 0) || (COMPARE_STR(text, length, "BLACK") == 0) ) { + return 0; + } else if ( (COMPARE_STR(text, length, "red") == 0) || (COMPARE_STR(text, length, "RED") == 0) ) { + return 0x00FF0000; + } else if ( (COMPARE_STR(text, length, "green") == 0) || (COMPARE_STR(text, length, "GREEN") == 0) ) { + return 0x0000FF00; + } else if ( (COMPARE_STR(text, length, "blue") == 0) || (COMPARE_STR(text, length, "BLUE") == 0) ) { + return 0x000000FF; + } else if ((COMPARE_STR(text, length, "white") == 0) || (COMPARE_STR(text, length, "WHITE") == 0) ) { + return 0x00FFFFFF; + } else if (text[0] == '#' && length == 7) { /* parse #rrggbb or #RRGGBB */ + int red, green, blue = 0; + parsed = sscanf(text, "#%2X%2X%2X", &red, &green, &blue); + if (parsed == 3) { + uint32_t c = blue; + c |= (green << 8); + c |= (red << 16); +#ifdef UNIT_TEST + printf("rrggbb %s = %x\n", text, c); +#endif + return c; + } else { + /* try to parse lower case hex values */ + parsed = sscanf(text, "#%2x%2x%2x", &red, &green, &blue); + if (parsed == 3) { + uint32_t c = blue; + c |= (green << 8); + c |= (red << 16); +#ifdef UNIT_TEST + printf("RRGGBB %s = %x\n", text, c); +#endif + return c; + } else { + return 0; + } + } + } else { + int hue; /* OpenHAB hue (0-360°) */ + int satu; /* OpenHAB saturation (0-100%) */ + int bright; /* brightness (0-100%) */ + + parsed = sscanf(text, "%d,%d,%d", &hue, &satu, &bright); + if (parsed == 3) { +#ifndef UNIT_TEST + return Adafruit_NeoPixel::ColorHSV(65535 * hue / 360, + 255 * satu / 100, + 255 * bright / 100); +#else + return replacementColorHSV(65535 * hue / 360, + 255 * satu / 100, + 255 * bright / 100); +#endif + } else { + return 0xFFFFFFFF; /* wrong format */ + } + } + + return 0xFFFFFFFF; +} \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index e61e948..a337ca0 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3,9 +3,10 @@ #include #include #include +#include "ColorUtil.h" #include "controller.h" /****************************************************************************** - * MAKROS + * MACROS ******************************************************************************/ @@ -24,8 +25,8 @@ /****************************************************************************** * LOCAL VARIABLES ******************************************************************************/ -Adafruit_NeoPixel pixels(WS2812STRIP_LEDS, WS2812STRIP_GPIO_PIN, NEO_RBG + NEO_KHZ400); -Adafruit_NeoPixel singleLed(WS2812SINGLE_LEDS, WS2812SINGLE_GPIO_PIN, NEO_RBG + NEO_KHZ400); +Adafruit_NeoPixel* pixels; +Adafruit_NeoPixel* singleLed; OneWire oneWire(GPIO_DS18B20); DallasTemperature sensors(&oneWire); @@ -35,6 +36,8 @@ DallasTemperature sensors(&oneWire); * Initialize hardware pins */ void setup() { + pixels = new Adafruit_NeoPixel(WS2812STRIP_LEDS, WS2812STRIP_GPIO_PIN, NEO_GRB + NEO_KHZ400); + singleLed = new Adafruit_NeoPixel(WS2812SINGLE_LEDS, WS2812SINGLE_GPIO_PIN, NEO_GRB + NEO_KHZ400); Serial.begin(115200); WiFi.mode(WIFI_OFF); @@ -42,17 +45,19 @@ void setup() { { Serial.println(F("\nWifi mode is WIFI_OFF")); } - +#ifdef FAN_ENABLED /* Setup FAN Control */ pinMode(FAN_PIN, OUTPUT); pinMode(SIGNAL_PIN, INPUT); +#else + Serial.println(F("\nFAN NOT enabled")); +#endif - - pixels.begin(); - pixels.clear(); - pixels.setBrightness(100); - pixels.fill(pixels.Color(255,0,0)); - pixels.show(); + pixels->begin(); + pixels->clear(); + pixels->setBrightness(100); + pixels->fill(Color(255,0,0)); + pixels->show(); /* Initialize Temperature sensor */ @@ -64,18 +69,18 @@ void setup() { Serial.println("Reset 1-Wire Bus"); } - pixels.fill(pixels.Color(0,255,0)); - pixels.setBrightness(50); - pixels.show(); + pixels->fill(Color(0,255,0)); + pixels->setBrightness(50); + pixels->show(); /* prepare LED strip pin */ - singleLed.begin(); - singleLed.clear(); - singleLed.setBrightness(100); - singleLed.fill(singleLed.Color(255,0,0)); - singleLed.show(); + singleLed->begin(); + singleLed->clear(); + singleLed->setBrightness(100); + singleLed->fill(Color(255,0,0)); + singleLed->show(); } - +#ifdef FAN_ENABLED /** * @brief Get the Fan Speed in round per minutes * @@ -102,6 +107,8 @@ void setFanSpeedPercent(int p) { analogWrite(FAN_PIN, value); } +#endif + float readTemperature(void) { int sensorCount = sensors.getDeviceCount(); @@ -122,12 +129,14 @@ float readTemperature(void) * @brief Endless loop * (is called as fast as possible) */ -void loop() { - float temp = readTemperature(); +void loop() +{ + float temp = readTemperature(); + Serial.print(temp); Serial.print(";"); - int fanSpeedPercent, actualFanSpeedRpm; + int fanSpeedPercent, actualFanSpeedRpm = 0; if (temp < MIN_TEMP) { fanSpeedPercent = 0; @@ -137,23 +146,33 @@ void loop() { fanSpeedPercent = (100 - MIN_FAN_SPEED_PERCENT) * (temp - MIN_TEMP) / (MAX_TEMP - MIN_TEMP) + MIN_FAN_SPEED_PERCENT; } +#ifdef FAN_ENABLED actualFanSpeedRpm = getFanSpeedRpm(); - - pixels.fill(pixels.Color(255, 0,0)); - pixels.setBrightness(fanSpeedPercent); - pixels.show(); + pixels->fill(pixels.Color(255, 0,0)); + pixels->setBrightness(actualFanSpeedRpm); +#else + uint8_t index = (uint8_t) ((actualFanSpeedRpm + 1) % 256); + RainbowCycle(pixels, &index); +#endif + pixels->show(); +#ifdef FAN_ENABLED Serial.print(fanSpeedPercent); Serial.print("%;"); setFanSpeedPercent(fanSpeedPercent); Serial.print(actualFanSpeedRpm); Serial.println("RPM"); +#else + Serial.println(""); +#endif - singleLed.fill(singleLed.Color(0,128,128)); - singleLed.setBrightness(255 - (actualFanSpeedRpm / 10)); - singleLed.show(); - + singleLed->fill(Color(0,128,128)); + singleLed->setBrightness(fanSpeedPercent); + singleLed->show(); + +#ifdef FAN_ENABLED delay(DELAY_TIME); +#endif }