compiliert aber nicht getestet
Verwendet uintX_t für klare Datenbreite anstelle von char, byte, int, long (einfach durch den passenden Datentyp ersetzen wenn der Compiler meckert)
Beinhaltet Glitches wegen integerRechnung, Rundungsfehler und hat bestimmt Optimierungspotential
Aber zumindest logisch sollte es funktionieren, habe nur gerade keine NeoPixel und kein Arduino zur Hand zum testen
Sollte als Grundlage aber erstmal reichen
Code:
#define PIN 6
#define NUMPIXELS 10
typedef enum
{
anim_off,
anim_fade_dn,
anim_fade_up,
anim_oscil_up,
anim_oscil_dn,
anim_cnt_dn,
anim_cnt_up,
anim_on
}animationMode_e;
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
uint8_t selectedColor[3] = {0,0,0};
uint8_t activeColor[3] = {0,0,0};
uint16_t timerTop = 0; //change to whatever fade or oscillation time required, depends on how frequent handleLEDs is called
uint16_t timer = 0;
animationMode_e anim_mode = anim_off;
void setupLEDs()
{
anim_mode = anim_off;
timer = 0;
memset(selectedColor,15,sizeof(activeColor)}; //low white value for possible LED check
pixels.begin();
}
void handleLEDs()
{
uint8_t i;
for(i=0;i<NUMPIXELS;i++)
{
switch(anim_mode)
{
case(anim_on):
if(i==0) memcpy(activeColor,selectedColor;, sizeof(activeColor));
break;
case(anim_fade_dn): // Intended fallthrough
case(anim_oscil_dn):
if(i==0) //always only once per cycle or timer gets confus
{
if(timer == 0)
{
if(anim_mode == anim_oscil_dn) anim_mode = anim_oscil_up;
else anim_mode = anim_off;
}
else
{
activeColor[0] = ((uint32_t)timer * (uint32_t)selectedColor[0]) / (uint32_t)timerTop;
activeColor[1] = ((uint32_t)timer * (uint32_t)selectedColor[1]) / (uint32_t)timerTop;
activeColor[2] = ((uint32_t)timer * (uint32_t)selectedColor[2]) / (uint32_t)timerTop;
timer--;
}
}
break;
case(anim_fade_up): // Intended fallthrough
case(anim_oscil_up):
if(i==0) //always only once per cycle or timer gets confus
{
if(timer == timerTop)
{
if(anim_mode == anim_oscil_up) anim_mode = anim_oscil_dn;
else anim_mode = anim_on;
}
else
{
activeColor[0] = ((uint32_t)timer * (uint32_t)selectedColor[0]) / (uint32_t)timerTop;
activeColor[1] = ((uint32_t)timer * (uint32_t)selectedColor[1]) / (uint32_t)timerTop;
activeColor[2] = ((uint32_t)timer * (uint32_t)selectedColor[2]) / (uint32_t)timerTop;
timer++;
}
}
break;
case(anim_cnt_dn):
if(((NUMPIXELS*timer)/timerTOP) > i)
{
memset(activeColor,0,sizeof(activeColor)};
}
else if(((NUMPIXELS*timer)/timerTOP) == i)
{
uint16_t t_per = timerTop/NUMPIXELS; // periode time, kann man als MACRO machen für weniger RAM verbrauch
uint16_t t_dut = timer - (t_per * i)); // duty time, kann man als MACRO machen für weniger RAM verbrauch
activeColor[0] = ((uint32_t)selectedColor[0] * (uint32_t)t_dut) / (uint32_t)t_per;
}
else
{
memcpy(activeColor,selectedColor, sizeof(activeColor));
}
if(i==0) //always only once per cycle or timer gets confus
{
if(timer > 0) timer--;
else anim_mode = anim_off;
}
break;
case(anim_cnt_up):
if(((NUMPIXELS*timer)/timerTOP) > i)
{
memcpy(activeColor,selectedColor, sizeof(activeColor));
}
else if(((NUMPIXELS*timer)/timerTOP) == i)
{
uint16_t t_per = timerTop/NUMPIXELS; // periode time, kann man als MACRO machen für weniger RAM verbrauch
uint16_t t_dut = timer-(t_per * i); // duty time, kann man als MACRO machen für weniger RAM verbrauch
activeColor[0] = ((uint32_t)selectedColor[0] * (uint32_t)t_dut) / (uint32_t)t_per;
}
else
{
memset(activeColor,0,sizeof(activeColor)};
}
if(i==0) //always only once per cycle or timer gets confus
{
if(timer > timerTop) timer++;
else anim_mode = anim_on;
}
break;
case(anim_off): // Intended fallthrough
default:
memset(activeColor,0,sizeof(activeColor)};
break;
}
pixels.setPixelColor(i, pixels.Color(activeColor[0],activeColor[1],activeColor[2])); // Moderately bright green color.
}
pixels.show(); // This sends the updated pixel color to the hardware.
}
du musst nur den Animations_mode und einen Timerwert angeben, setupLEDs ein einziges mal und dann handleLEDs in einem festen Zyklus aufrufen
fade up und dn machen nur einen einzelnen fade und münden dann in on oder off zustand
oscil up und dn laufen als schleife bis du den mode zu etwas anderem wechselst
cnt up und dn sind dann deine ring animation und enden ebenfalls mit on bzw. off
Lesezeichen