PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Suche WS2812b/Arduino-Miniprogramm benötigt



Andree-HB
09.05.2018, 06:28
Guten Morgen,
ich benötige für ein Gerät eine Zusatzfunktion, dazu ein kleines Programm (für einen kleinen Arduino):



um einen Starttaster herum ist ein RGB-LED Ring (Neopixel) angeordnet, z.b. mit 8 LED`s
es wird wird durch eine permanente, kleine Animation/blinken zum drücken das Tasters aufgefordert
nach dem Drücken des Tasters werden alle LED`s auf eine Farbe gesetzt (z.B. rot)
als "Countdown" werden die nun alle nacheinander kreisförmig abgeschaltet
ein Ausgang wird nun als Triggersignal gesetzt
mit etwas Verzögerung wird wieder auf die Startanimation geführt


Hat jemand Lust und Zeit ? :-)

Ceos
09.05.2018, 08:28
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 :)



#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

Andree-HB
11.05.2018, 09:24
...danke Dir schonmal !

Leider bekomme ich hier schon einen Fehler beim kompilieren:
public typedef enum

Ceos
11.05.2018, 13:29
oh ähm ja sorry, das public war ein schnitzer :P ich jag das gleich nochmal durch mein studio und mach es ordentlich, hatte ich völlig vergessen

Ceos
12.05.2018, 08:51
habe den Code im Post oben repariert :D

sollte soweit gehen, wenn er die datentypen nicht erkennt, einfach durch die passend breite datentypen ersetzen