Hallo erstmal,
ich bin schon länger in dem Forum am lesen und Informationen zusammen zu suchen für mein Projekt. Leider bin ich absoluter Anfänger in den ganzen Sachen und versuche mich direkt ein einem etwas komplexeren Projekt.
Zunächst, das Projekt soll nicht von heute auf morgen stehen, sondern mit der Zeit wachsen.
Es handelt sich hierbei um zwei getrennte WS2812B Streifen an jeweils einem Digitalen Ausgang mit einmal 117 und 30 LEDs. Für ein Netzteil mit 18 Ampere ist gesorgt, da in Zukunft noch weitere LEDs geplant sind, aber die können ruhig mit der Zeit folgen.
Angeschlossen ist es einem einem Arduino Uno.
Beide sind jeweils mit einem 470 Ohm Widerstand ausgestattet und in allen Test, die ich mit folgenden Script bisher versucht habe, lief auch alles technisch einwandfrei. Auch, wenn ich das Script auf meine Bedürfnisse hin angepasst habe.
#include "FastLED.h"
// This sketch shows one way to define a 'timed playlist'
// of animations that automatically rotate on a custom schedule.
//
// A "ResetPlaylist" method is provided so that the playlist can be
// restarted from a custom external trigger, e.g., a button or event.
// For demonstration purposes, the playlist is reset if the
// sketch receives a letter "r" on the serial port.
//
// -Mark Kriegsman, January 2015
#define DATA_PIN 6
#define DATA_PIN2 3
#define LED_TYPE WS2812B
#define COLOR_ORDER GRB
#define NUM_LEDS 117
#define NUM_LEDS2 30
CRGB leds[NUM_LEDS];
CRGB leds2[NUM_LEDS2];
#define BRIGHTNESS 96
#define FRAMES_PER_SECOND 120
void setup() {
delay(3000); // 3 second delay for recovery
FastLED.addLeds<LED_TYPE,DATA_PIN,COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);
FastLED.addLeds<LED_TYPE, DATA_PIN2, COLOR_ORDER>(leds2, NUM_LEDS2).setCorrection(TypicalLEDStrip);
FastLED.setBrightness(BRIGHTNESS);
RestartPlaylist();
Serial.begin(57600);
}
// List of patterns to cycle through. Each is defined as a separate function below.
typedef void (*SimplePattern)();
typedef SimplePattern SimplePatternList[];
typedef struct { SimplePattern mPattern; uint16_t mTime; } PatternAndTime;
typedef PatternAndTime PatternAndTimeList[];
uint32_t previousMillis = 0, intervall = 500;
// These times are in seconds, but could be changed to milliseconds if desired;
const PatternAndTimeList gPlaylist = {
{ black, 1 },
{ sign1_L, 10 },
{ sign, 50 },
{ rainbowM, 20 },
{ bpm, 5 },
{ sign, 5 },
{ applause, 1 },
{ fadeToBlack, 3 }
};
// If you want the playlist to loop forever, set this to true.
// If you want the playlist to play once, and then stay on the final pattern
// until the playlist is reset, set this to false.
bool gLoopPlaylist = true;
uint8_t gCurrentTrackNumber = 0; // Index number of which pattern is current
uint8_t gHue = 0;
uint8_t farbe = 0;
uint8_t zeit = 0;
bool gRestartPlaylistFlag = false;
void loop()
{
// Call the current pattern function once, updating the 'leds' array
gPlaylist[gCurrentTrackNumber].mPattern();
// send the 'leds' array out to the actual LED strip
FastLED.show();
// insert a delay to keep the framerate modest
FastLED.delay(1000/FRAMES_PER_SECOND);
// For demo purposes, restart the playlist any time we read
// the letter "r" character from the serial port.
if( Serial.read() == 'r') RestartPlaylist();
EVERY_N_MILLISECONDS( 20 ) { gHue++; }
// Here's where we do two things: switch patterns, and also set the
// 'virtual timer' for how long until the NEXT pattern switch.
//
// Instead of EVERY_N_SECONDS(10) { nextPattern(); }, we use a special
// variation that allows us to get at the pattern timer object itself,
// and change the timer period every time we change the pattern.
//
// You could also do this with EVERY_N_MILLISECONDS_I and have the
// times be expressed in milliseconds instead of seconds.
{
EVERY_N_SECONDS_I(patternTimer,gPlaylist[gCurrentTrackNumber].mTime) {
nextPattern();
patternTimer.setPeriod( gPlaylist[gCurrentTrackNumber].mTime);
}
// Here's where we handle restarting the playlist if the 'reset' flag
// has been set. There are a few steps:
if( gRestartPlaylistFlag ) {
// Set the 'current pattern number' back to zero
gCurrentTrackNumber = 0;
// Set the playback duration for this patter to it's correct time
patternTimer.setPeriod( gPlaylist[gCurrentTrackNumber].mTime);
// Reset the pattern timer so that we start marking time from right now
patternTimer.reset();
// Finally, clear the gRestartPlaylistFlag flag
gRestartPlaylistFlag = false;
}
}
}
#define ARRAY_SIZE(A) (sizeof(A) / sizeof((A)[0]))
void nextPattern()
{
// add one to the current pattern number
gCurrentTrackNumber = gCurrentTrackNumber + 1;
// If we've come to the end of the playlist, we can either
// automatically restart it at the beginning, or just stay at the end.
if( gCurrentTrackNumber == ARRAY_SIZE( gPlaylist) ) {
if( gLoopPlaylist == true) {
// restart at beginning
gCurrentTrackNumber = 0;
} else {
// stay on the last track
gCurrentTrackNumber--;
}
}
}
void RestartPlaylist()
{
gRestartPlaylistFlag = true;
}
void blackS(int zeit) {
fadeToBlackBy( leds, NUM_LEDS, zeit);
}
void blackM( int zeit) {
fadeToBlackBy( leds2, NUM_LEDS2, zeit);
}
void sign() {
black();
uint8_t BeatsPerMinute = 42;
uint8_t beat = beatsin8( BeatsPerMinute, 64, 255);
uint8_t helligkeit = beat;
sign1(0, 192);
sign2(160, helligkeit);
sign3(0, 192);
sign4(160, helligkeit);
}
void sign1( fract8 farbe, fract8 helligkeit) {
for ( int i = 0; i < 26; i++) { //9948
leds[i] = CHSV(farbe, 255, helligkeit);
}
}
void sign2( fract8 farbe, fract8 helligkeit) {
for ( int i = 26; i < 36; i++) { //9948
leds[i] = CHSV(farbe, 255, helligkeit);
}
}
void sign3( fract8 farbe, fract8 helligkeit) {
for ( int i = 36; i < 63; i++) { //9948
leds[i] = CHSV(farbe, 255, helligkeit);
}
}
void sign4( fract8 farbe, fract8 helligkeit) {
for ( int i = 63; i < 73; i++) { //9948
leds[i] = CHSV(farbe, 255, helligkeit);
}
}
Folgendes versuche ich nun umzusetzen und frage mich, ob ich mit dem "theoretischen" auf dem richtigen Weg bin.
Ich möchte, dass der kürzere der beiden Streifen durchgehend unterschiedliche Animationen von einer Playlist abspielt, so als Default Modus.
Über C# und der seriellen Schnittstelle soll ein Array oder String gesendet werden, mit welchem der Arduino arbeiten und eine andere kurze Animationen aus einer Playlist auf beiden Stripes abspielen soll. Dabei soll er den den Default modus unterbrechen und wenn und falls möglich in die anderen Animationen faden.
Sobald die Playlist durchgelaufen ist, soll er wieder zurück zu default und auf das nächste Ereignis warten.
In Zukunft soll auch eine automatische Musiksteuerung erfolgen, die ich allerdings auch über C# umsetzten möchte. Der Arduino soll nur als Empfänger und Umsetzer dienen.
Somit kommen schon einmal einige Daten die ich an den Arduino mitteilen möchte. Sachen wie Modus, BPM, Danceability (0 - 1), Vocals (0 - 1).
Gedacht habe ich an einen Case Switch, ich weiß aber nicht ob es das Sinnvollste ist, was ich tun kann, zumal ich keine Ahnung habe, wie ich all die Werte übergeben soll. Sowohl die Werte von der Seriellen Schnittstelle als auch an die LEDs mit den Playlisten.
Immer wieder lese ich etwas von den Arrays die per Serial gelesen werden und interpretiert werden, aber alle haben da ihre eigenen Anforderungen, sodass ich nur schwer den Bespielen folgen kann, um sowas für mich um zusetzten.
Alternativ dachte ich, dass ich jede einzelne Animation in einen Case Switch setze und per C# und der seriellen Schnittstelle immer den jeweiligen Code (ala Wert 0 = aus; 1 = default ; 2 = eine farbe leuchten ; 3 = farbverlauf; ...; 66 = Im Takt wechsel) übermitteln lasse. Dazu kämen dann aber die Werte wie BPM, die nicht in jeden Case Switch hineingehören.
Also viel Text, noch mehr hab ich hier und in diversen anderen Foren gelesen und muss nochmals erwähnen, dass ich zwar vieles umgesetzt bekomme, aber es braucht Zeit und die richtigen Informationen, mit denen ich mich schwer tue.
Vielleicht hat ja jemand der Leser, hierfür eine bessere Idee und/oder Ratschläge um mein LED Projekt voran zu bringen.
Ich danke schon mal fürs lesen.
Viele Grüße