1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

Blue Mood Blobs Effect - Wanna make it in C on ESP32

Discussion in 'Hyperion General' started by Braulio, 23 February 2020.

  1. Braulio

    Braulio Member

    Messages:
    38
    Hardware:
    RPi3
    Hello!

    I love the effect Blue Mood Blobs and I'd like to have this effect on ESP32 connected to a led strip. ESP32 uses C language and I got the blobs effect code from Hyperion and I am converting to C. I am using an emulator to code and test it with an Arduino (www.tinkercad.com) - See imagem attached.
    After long work I could convert the code but it's not working properly, current it just light the "blobs" in red only, but it is rolling through the strip, but only in red color, I believe something I converted wrong.
    Is anyone up to help me to figure out how to make it working correctly?
    The code is below.

    Here is the original code of the effect on Hyperion: https://github.com/hyperion-project/hyperion.ng/blob/master/effects/mood-blobs.py
    -------

    #include <Adafruit_NeoPixel.h>
    #include <stdio.h>
    #include <stdbool.h>
    #include <math.h>

    #define PIN 11
    #define NUMPIXELS 60

    Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);

    float rotationTime = 20;
    float hueChange = 60;
    float baseColorRangeLeft = 0; // Degree
    float baseColorRangeRight = 360; // Degree
    float baseColorChangeRate = 10; // Seconds for one Degree
    float baseColorChangeIncreaseValue;
    float hue;
    float sleepTime;
    float amplitudePhaseIncrement;
    float amplitudePhase;
    float baseHSVValue;
    float amplitude;
    float baseHsv[3];
    float rgb[3];

    int color[3] = {0,0,255};
    int blobs = int(5);
    int colorData[NUMPIXELS][3];
    int colorDataIncrement;
    int colors[NUMPIXELS][3];
    int baseColorChangeStepCount;
    float numberOfRotates;

    bool colorRandom = false;
    bool reverse = false;
    bool baseColorChange = false;
    bool fullColorWheelAvailable;
    bool rotateColors;

    void setColorLED();
    float *rgb_to_hsv(float r, float g, float b);
    float * hsv_to_rgb(float H, float S, float V);


    void setup() {
    // Get the parameters
    pixels.begin();

    // switch baseColor change off if left and right are too close together to see a difference in color
    if ((baseColorRangeRight > baseColorRangeLeft && (baseColorRangeRight - baseColorRangeLeft) < 10) || (baseColorRangeLeft > baseColorRangeRight && ((baseColorRangeRight + 360) - baseColorRangeLeft) < 10)) {
    baseColorChange = false;
    }

    // 360 -> 1
    fullColorWheelAvailable = fmod(baseColorRangeRight, 360) == fmod(baseColorRangeLeft, 360);
    baseColorChangeIncreaseValue = 1 / 360; // 1 degree
    hueChange /= 360.0;
    baseColorRangeLeft = (baseColorRangeLeft / 360.0);
    baseColorRangeRight = (baseColorRangeRight / 360.0);

    // Check parameters
    rotationTime = max(0.1, rotationTime);
    hueChange = max(0.0, min(abs(hueChange), .5));
    blobs = max(1, blobs);
    baseColorChangeRate = max(0, baseColorChangeRate); // > 0

    // Calculate the color data
    rgb_to_hsv(color[0]/255, color[1]/255, color[2]/255, baseHsv);
    if (colorRandom) {
    baseHsv[0] = random();
    baseHsv[1] = baseHsv[1];
    baseHsv[2] = baseHsv[2];
    }

    //colorData = bytearray();
    // for i in range(hyperion.ledCount):
    for (int i = 0; i < NUMPIXELS; i++) {
    hue = fmodf((baseHsv[0] + hueChange * sin(2 * M_PI * i / NUMPIXELS)),1);
    hsv_to_rgb(hue, baseHsv[1], baseHsv[2], rgb);
    colorData[0] = rgb[0]*255;
    colorData[1] = rgb[1]*255;
    colorData[2] = rgb[2]*255;
    }
    // Calculate the increments
    sleepTime = 0.1;
    amplitudePhaseIncrement = blobs * M_PI * sleepTime / rotationTime;
    colorDataIncrement = 3;
    baseColorChangeRate /= sleepTime;

    // Switch direction if needed
    if (reverse) {
    amplitudePhaseIncrement = -amplitudePhaseIncrement;
    colorDataIncrement = -colorDataIncrement;
    }

    // create a Array for the colors
    for (int i = 0; i < NUMPIXELS; i++) {
    colors[0] = 0;
    colors[1] = 0;
    colors[2] = 0;
    }

    // Start the write data loop
    amplitudePhase = 0.0;
    rotateColors = false;
    baseColorChangeStepCount = 0;
    baseHSVValue = baseHsv[0];
    numberOfRotates = 0;

    }

    void loop() {

    // move the basecolor
    if (baseColorChange) {
    // every baseColorChangeRate seconds
    if (baseColorChangeStepCount >= baseColorChangeRate) {
    baseColorChangeStepCount = 0;
    // cyclic increment when the full colorwheel is available, move up and down otherwise
    if (fullColorWheelAvailable) {
    baseHSVValue = fmod((baseHSVValue + baseColorChangeIncreaseValue), baseColorRangeRight);
    } else {
    // switch increment direction if baseHSV <= left or baseHSV >= right
    if (baseColorChangeIncreaseValue < 0 && baseHSVValue > baseColorRangeLeft && (baseHSVValue + baseColorChangeIncreaseValue) <= baseColorRangeLeft) {
    baseColorChangeIncreaseValue = abs(baseColorChangeIncreaseValue);
    } else {
    if (baseColorChangeIncreaseValue > 0 && baseHSVValue < baseColorRangeRight && (baseHSVValue + baseColorChangeIncreaseValue) >= baseColorRangeRight) {
    baseColorChangeIncreaseValue = -abs(baseColorChangeIncreaseValue);
    }
    }
    baseHSVValue = fmod((baseHSVValue + baseColorChangeIncreaseValue), 1);
    }
    // update color values
    //colorData = bytearray();
    for (int i = 0; i < NUMPIXELS; i++) {
    hue = fmod((baseHSVValue + hueChange * sin(2*M_PI * i / NUMPIXELS)), 1);
    hsv_to_rgb(hue, baseHsv[1], baseHsv[2], rgb);
    colorData[0] = rgb[0] * 255;
    colorData[1] = rgb[1] * 255;
    colorData[2] = rgb[2] * 255;
    }
    // set correct rotation after reinitialisation of the array
    //colorData = colorData[-colorDataIncrement*numberOfRotates:] + colorData[:-colorDataIncrement*numberOfRotates];
    //colorData = colorData[-colorDataIncrement*numberOfRotates] + colorData[-colorDataIncrement*numberOfRotates];
    }
    baseColorChangeStepCount += 1;
    }
    // Calculate new colors
    for (int i = 0; i < NUMPIXELS; i++) {
    amplitude = max(0.0, sin(-amplitudePhase + 2*M_PI * blobs * i / NUMPIXELS));
    colors[0] = int(colorData[0] * amplitude);
    colors[1] = int(colorData[1] * amplitude);
    colors[2] = int(colorData[2] * amplitude);
    }
    // set colors
    setColorLED();
    pixels.show();
    // increment the phase
    amplitudePhase = fmod((amplitudePhase + amplitudePhaseIncrement), (2*M_PI));

    if (rotateColors) {
    //colorData = colorData[-colorDataIncrement:] + colorData[:-colorDataIncrement]; //// NEED TO CHANGE, BUT I DIDN'T UNDERSTAND THIS LINE
    numberOfRotates = fmod((numberOfRotates + 1), NUMPIXELS);
    }
    rotateColors = not rotateColors;
    baseColorChange = not baseColorChange;
    // sleep for a while
    delay(sleepTime);
    }

    void setColorLED() {
    for (int i = 0; i < NUMPIXELS; i++) {
    pixels.setPixelColor(i, pixels.Color(colors[0], colors[1], colors[2]));
    }
    return;
    }

    void rgb_to_hsv(float r, float g, float b, float *base) {
    float min, max, delta;

    float hsv[3];
    float h, s, v;

    min = r < g ? r : g;
    min = min < b ? min : b;

    max = r > g ? r : g;
    max = max > b ? max : b;

    v = max; // v
    delta = max - min;
    if (delta < 0.00001)
    {
    s = 0;
    h = 0; // undefined, maybe nan?
    base[0] = h;
    base[1] = s;
    base[2] = v;
    //return hsv;
    }
    if( max > 0.0 ) { // NOTE: if Max is == 0, this divide would cause a crash
    s = (delta / max); // s
    } else {
    // if max is 0, then r = g = b = 0
    // s = 0, h is undefined
    s = 0.0;
    h = NAN; // its now undefined
    base[0] = h;
    base[1] = s;
    base[2] = v;
    //return hsv;
    }
    if( r >= max ) // > is bogus, just keeps compilor happy
    h = ( g - b ) / delta; // between yellow & magenta
    else
    if( g >= max )
    h = 2.0 + ( b - r ) / delta; // between cyan & yellow
    else
    h = 4.0 + ( r - g ) / delta; // between magenta & cyan

    h *= 60.0; // degrees

    if( h < 0.0 )
    h += 360.0;

    base[0] = h;
    base[1] = s;
    base[2] = v;
    //return hsv;
    return;
    }


    void hsv_to_rgb(float H, float S, float V, float *base) {
    float hh, p, q, t, ff;
    float i;
    float Rs, Gs, Bs;
    float nRgb[3];

    if(S <= 0.0) { // < is bogus, just shuts up warnings
    Rs = V;
    Gs = V;
    Bs = V;
    base[0] = Rs;
    base[1] = Gs;
    base[2] = Bs;
    return;
    }
    hh = H;
    if(hh >= 360.0) hh = 0.0;
    hh /= 60.0;
    i = (float)hh;
    ff = hh - i;
    p = V * (1.0 - S);
    q = V * (1.0 - (S * ff));
    t = V * (1.0 - (S * (1.0 - ff)));

    switch((int)i) {
    case 0:
    Rs = V;
    Gs = t;
    Bs = p;
    break;
    case 1:
    Rs = q;
    Gs = V;
    Bs = p;
    break;
    case 2:
    Rs = p;
    Gs = V;
    Bs = t;
    break;

    case 3:
    Rs = p;
    Gs = q;
    Bs = V;
    break;
    case 4:
    Rs = t;
    Gs = p;
    Bs = V;
    break;
    case 5:
    default:
    Rs = V;
    Gs = p;
    Bs = q;
    break;
    }

    base[0] = Rs;
    base[1] = Gs;
    base[2] = Bs;

    return;
    }
     

    Attached Files:

  2. TPmodding

    TPmodding Administrator Staff Member Administrator

    Messages:
    1,626
    Hardware:
    RPi1/Zero, RPi2, RPi3, +Arduino, +nodeMCU/ESP8266
    you can use also micropython on esp32
     
  3. Braulio

    Braulio Member

    Messages:
    38
    Hardware:
    RPi3
    Nice! I just had a look at it. I didn't know it is possible. I am just worried if I can later be able to back to the original firmware, but I will check it out.

    By the way, is there a code for the function below? I could not find it on github. For the C I have to adapt..
    hyperion.setColor(colors)

    Thanks a lot TPmodding!!!!
     
  4. TPmodding

    TPmodding Administrator Staff Member Administrator

    Messages:
    1,626
    Hardware:
    RPi1/Zero, RPi2, RPi3, +Arduino, +nodeMCU/ESP8266
    you can backup your "firmware" but only as binary, no as code...with avrdude
     
  5. Braulio

    Braulio Member

    Messages:
    38
    Hardware:
    RPi3
    Hi! I was searching for the firmware backup, I found using the ESPTOOL, I guess it does the same as avrdude (I will take a look too). Thanks for your tip!!!
     
  6. TPmodding

    TPmodding Administrator Staff Member Administrator

    Messages:
    1,626
    Hardware:
    RPi1/Zero, RPi2, RPi3, +Arduino, +nodeMCU/ESP8266
    should be yes, those are mostly other guis with the same tools in the background
     
    • Like Like x 1
  7. Braulio

    Braulio Member

    Messages:
    38
    Hardware:
    RPi3
    By the way, don't you know if the function code for hyperion.setColor(colors) is available? Otherwise I will have to find a way to programming similar one
     
  8. Braulio

    Braulio Member

    Messages:
    38
    Hardware:
    RPi3
    Just did it! :D
    See photo
     

    Attached Files:

  9. TPmodding

    TPmodding Administrator Staff Member Administrator

    Messages:
    1,626
    Hardware:
    RPi1/Zero, RPi2, RPi3, +Arduino, +nodeMCU/ESP8266
    You can also try WLED
     
    • Like Like x 1