PortManipulation zur Steuerung von Neopixel Stripes oder gibt es was besseres?

Guten Tag,
der im Anhang befindliche Sketch funktioniert sehr gut, aber die Steuerung kann nur über PIN 1 erfolgen. Ich möchte aber 7 Neo Pixel Stripes (1m 60 LED - zum testen habe ich 1m 30 LED) parallel ansteuern, also eigentlich dann PIN 1 bis PIN 7. Nun habe ich was von PortManipulation beim Arduino UNO gelesen, und das die Eingabe von

// alle Bits von Port D auf Ausgang
DDRD = B11111111;

PIN 0 bis PIN 7 parallel auf Ausgang schalten kann.

Geht das überhaupt in dem Sketch, ich habe keine Ahnung, weil ja PIN 1 fest eingegeben werden muß.

Wäre mein Anliegen eventuell auch mit einem 75HC595 lösbar? So ein Schieberegister kann doch auch 7 Ausgänge parallel ansteuern. Aber da wüßte ich jetzt auch nicht, wie ich das in den Sketch reinzaubern sollte.

Oder gibt es noch eine bessere Lösung, auf die ich mit meinem gefährlichen Halbwissen noch garnicht gekommen bin?

#include "FastLED.h"
#define NUM_LEDS 30 
CRGB leds[NUM_LEDS];
#define PIN 1 

void setup()
{
  FastLED.addLeds<WS2811, PIN, GRB>(leds, NUM_LEDS).setCorrection( TypicalLEDStrip );
}

// *** REPLACE FROM HERE ***
void loop() {
  BouncingBalls(0xff,0,0, 1);
}

void BouncingBalls(byte red, byte green, byte blue, int BallCount) {
  float Gravity = -9.81;
  int StartHeight = 1;
  
  float Height[BallCount];
  float ImpactVelocityStart = sqrt( -2 * Gravity * StartHeight );
  float ImpactVelocity[BallCount];
  float TimeSinceLastBounce[BallCount];
  int   Position[BallCount];
  long  ClockTimeSinceLastBounce[BallCount];
  float Dampening[BallCount];
  
  for (int i = 0 ; i < BallCount ; i++) {   
    ClockTimeSinceLastBounce[i] = millis();
    Height[i] = StartHeight;
    Position[i] = 0; 
    ImpactVelocity[i] = ImpactVelocityStart;
    TimeSinceLastBounce[i] = 0;
    Dampening[i] = 0.90 - float(i)/pow(BallCount,2); 
  }

  while (true) {
    for (int i = 0 ; i < BallCount ; i++) {
      TimeSinceLastBounce[i] =  millis() - ClockTimeSinceLastBounce[i];
      Height[i] = 0.5 * Gravity * pow( TimeSinceLastBounce[i]/1000 , 2.0 ) + ImpactVelocity[i] * TimeSinceLastBounce[i]/1000;
  
      if ( Height[i] < 0 ) {                      
        Height[i] = 0;
        ImpactVelocity[i] = Dampening[i] * ImpactVelocity[i];
        ClockTimeSinceLastBounce[i] = millis();
  
        if ( ImpactVelocity[i] < 0.01 ) {
          ImpactVelocity[i] = ImpactVelocityStart;
        }
      }
      Position[i] = round( Height[i] * (NUM_LEDS - 1) / StartHeight);
    }
  
    for (int i = 0 ; i < BallCount ; i++) {
      setPixel(Position[i],red,green,blue);
    }
    
    showStrip();
    setAll(0,0,0);
  }
}
// *** REPLACE TO HERE ***

void showStrip() {
 #ifdef ADAFRUIT_NEOPIXEL_H 
   // NeoPixel
   strip.show();
 #endif
 #ifndef ADAFRUIT_NEOPIXEL_H
   // FastLED
   FastLED.show();
 #endif
}

void setPixel(int Pixel, byte red, byte green, byte blue) {
 #ifdef ADAFRUIT_NEOPIXEL_H 
   // NeoPixel
   strip.setPixelColor(Pixel, strip.Color(red, green, blue));
 #endif
 #ifndef ADAFRUIT_NEOPIXEL_H 
   // FastLED
   leds[Pixel].r = red;
   leds[Pixel].g = green;
   leds[Pixel].b = blue;
 #endif
}

void setAll(byte red, byte green, byte blue) {
  for(int i = 0; i < NUM_LEDS; i++ ) {
    setPixel(i, red, green, blue); 
  }
  showStrip();
}

Setze Deinen Code bitte direkt ins Forum. Benutze dazu Codetags (</>-Button oben links im Forumseditor oder [code] davor und [/code] dahinter ohne *).
Dann ist er auch auf mobilen Geräten besser lesbar.
Das kannst Du auch noch nachträglich ändern.

Gruß Tommy

PortManipulation

Natürlich geht sowas...
Denn letztlich verwenden fast alle libs dieses Verfahren (mit 1 Ausgang)

Aber natürlich lassen sich auch 8 Stripes gleichzeitig bedienen.

RAM Mangel macht dann allerdings fix einen Strich durch die Rechnung.
Und sowieso ist das Timing bei den Strips nicht ohne.
Es lässt keine/kaum Berechnungen während der Ausgabe zu.
Auf den kleinen AVRs bedeutet das dann, dass die Datenmengen fertig vorbereitet da liegen müssen.
(APA102 o.ä. wäre einfacher)

Anders bei µC mit DMA, oder 2 Kernen
Dort können Berechnungen parallel zur Ausgabe stattfinden
Auch haben diese meist mehr Speicher.

dobroino:
Oder gibt es noch eine bessere Lösung, ...

Ja, siehe Beispiel in diesem Thema.

#define DATA_PIN1    2
#define DATA_PIN2    3
...
CRGB leds1[NUM_LEDS];
CRGB leds2[NUM_LEDS];
...
  FastLED.addLeds<LED_TYPE, DATA_PIN1, COLOR_ORDER>(leds1, NUM_LEDS).setCorrection(TypicalLEDStrip); // initializes LED strip
  FastLED.addLeds<LED_TYPE, DATA_PIN2, COLOR_ORDER>(leds2, NUM_LEDS).setCorrection(TypicalLEDStrip); // initializes LED strip
...

@noiasca
Ich habe/hatte kein Problem das hardwaremäßig zu lösen, ich hatte bei dem Sketch bzw. bei der Umsetzung meiner Idee eine Blockade.

@agmue
Vielen Dank. Das war der entscheidende Hinweis. Im Anhang der angepasste, funktionierende Sketch mit 7 parallel laufenden Neopixel Stripes. Es gibt auch keine Geschwindigkeitseinbußen, da bin ich überrascht. Da der Sketch noch um weitere Effekte erweitert wird, muß das ganze natürlich auf einen Mega, es sind jetzt beim Uno schon 39% Speicher besetzt.

Danke das mir hier geholfen wurde.

#include "FastLED.h"
#define NUM_LEDS 30
#define DATA_PIN1    2
#define DATA_PIN2    3
#define DATA_PIN3    4
#define DATA_PIN4    5
#define DATA_PIN5    6
#define DATA_PIN6    7
#define DATA_PIN7    8
#define LED_TYPE    WS2812B
#define COLOR_ORDER GRB

CRGB leds1[NUM_LEDS];
CRGB leds2[NUM_LEDS];
CRGB leds3[NUM_LEDS];
CRGB leds4[NUM_LEDS];
CRGB leds5[NUM_LEDS];
CRGB leds6[NUM_LEDS];
CRGB leds7[NUM_LEDS];




void setup()
{
FastLED.addLeds<LED_TYPE, DATA_PIN1, COLOR_ORDER>(leds1, NUM_LEDS).setCorrection(TypicalLEDStrip); // initializes LED strip
FastLED.addLeds<LED_TYPE, DATA_PIN2, COLOR_ORDER>(leds2, NUM_LEDS).setCorrection(TypicalLEDStrip); // initializes LED strip
FastLED.addLeds<LED_TYPE, DATA_PIN3, COLOR_ORDER>(leds3, NUM_LEDS).setCorrection(TypicalLEDStrip); // initializes LED strip
FastLED.addLeds<LED_TYPE, DATA_PIN4, COLOR_ORDER>(leds4, NUM_LEDS).setCorrection(TypicalLEDStrip); // initializes LED strip
FastLED.addLeds<LED_TYPE, DATA_PIN5, COLOR_ORDER>(leds5, NUM_LEDS).setCorrection(TypicalLEDStrip); // initializes LED strip
FastLED.addLeds<LED_TYPE, DATA_PIN6, COLOR_ORDER>(leds6, NUM_LEDS).setCorrection(TypicalLEDStrip); // initializes LED strip
FastLED.addLeds<LED_TYPE, DATA_PIN7, COLOR_ORDER>(leds7, NUM_LEDS).setCorrection(TypicalLEDStrip); // initializes LED strip
    
}

// *** REPLACE FROM HERE ***
void loop() {
  BouncingBalls(0xff,0,0, 1);
}

void BouncingBalls(byte red, byte green, byte blue, int BallCount) {
  float Gravity = -9.81;
  int StartHeight = 1;
  
  float Height[BallCount];
  float ImpactVelocityStart = sqrt( -2 * Gravity * StartHeight );
  float ImpactVelocity[BallCount];
  float TimeSinceLastBounce[BallCount];
  int   Position[BallCount];
  long  ClockTimeSinceLastBounce[BallCount];
  float Dampening[BallCount];
  
  for (int i = 0 ; i < BallCount ; i++) {  
    ClockTimeSinceLastBounce[i] = millis();
    Height[i] = StartHeight;
    Position[i] = 0;
    ImpactVelocity[i] = ImpactVelocityStart;
    TimeSinceLastBounce[i] = 0;
    Dampening[i] = 0.90 - float(i)/pow(BallCount,2);
  }

  while (true) {
    for (int i = 0 ; i < BallCount ; i++) {
      TimeSinceLastBounce[i] =  millis() - ClockTimeSinceLastBounce[i];
      Height[i] = 0.5 * Gravity * pow( TimeSinceLastBounce[i]/1000 , 2.0 ) + ImpactVelocity[i] * TimeSinceLastBounce[i]/1000;
  
      if ( Height[i] < 0 ) {                      
        Height[i] = 0;
        ImpactVelocity[i] = Dampening[i] * ImpactVelocity[i];
        ClockTimeSinceLastBounce[i] = millis();
  
        if ( ImpactVelocity[i] < 0.01 ) {
          ImpactVelocity[i] = ImpactVelocityStart;
        }
      }
      Position[i] = round( Height[i] * (NUM_LEDS - 1) / StartHeight);
    }
  
    for (int i = 0 ; i < BallCount ; i++) {
      setPixel(Position[i],red,green,blue);
    }
    
    showStrip();
    setAll(0,0,0);
  }
}
// *** REPLACE TO HERE ***

void showStrip() {
 #ifdef ADAFRUIT_NEOPIXEL_H
   // NeoPixel
   strip.show();
 #endif
 #ifndef ADAFRUIT_NEOPIXEL_H
   // FastLED
   FastLED.show();
 #endif
}

void setPixel(int Pixel, byte red, byte green, byte blue) {
 #ifdef ADAFRUIT_NEOPIXEL_H
   // NeoPixel
   strip.setPixelColor(Pixel, strip.Color(red, green, blue));
 #endif
 #ifndef ADAFRUIT_NEOPIXEL_H
   // FastLED
   leds1[Pixel].r = red;
   leds1[Pixel].g = green;
   leds1[Pixel].b = blue;
   leds2[Pixel].r = red;
   leds2[Pixel].g = green;
   leds2[Pixel].b = blue;
   leds3[Pixel].r = red;
   leds3[Pixel].g = green;
   leds3[Pixel].b = blue;
   leds4[Pixel].r = red;
   leds4[Pixel].g = green;
   leds4[Pixel].b = blue;
   leds5[Pixel].r = red;
   leds5[Pixel].g = green;
   leds5[Pixel].b = blue;
   leds6[Pixel].r = red;
   leds6[Pixel].g = green;
   leds6[Pixel].b = blue;
   leds7[Pixel].r = red;
   leds7[Pixel].g = green;
   leds7[Pixel].b = blue;
   
   
 #endif
}

void setAll(byte red, byte green, byte blue) {
  for(int i = 0; i < NUM_LEDS; i++ ) {
    setPixel(i, red, green, blue);
  }
  showStrip();
}

dobroino:
Im Anhang der angepasste, funktionierende Sketch mit 7 parallel laufenden Neopixel Stripes.

Danke, dann können andere sich was abschauen!

dobroino:
Danke das mir hier geholfen wurde.

Bitte gerne :slight_smile: