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-pr…ter/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[i][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[i][0] = int(colorData[i][0] * amplitude);
colors[i][1] = int(colorData[i][1] * amplitude);
colors[i][2] = int(colorData[i][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[i][0], colors[i][1], colors[i][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;
}[/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][i][i][i][i][i][i][i][i][i][i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][i][i][i][i][i][i][i][i][i][i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i]