Neopixels kann nur 1 von 4 pins angesteuert werden

Hallo zusammen,
im rahmen meines techniker abschluss projektes binden wir einen arduino one an eine SPS mithilfe von Snap7 und einem shield an.

Die LED sind verdrahtet und und eine platine mit widerständen wurde gelötet. Das Problem ist, dass immer nur ein Pin angesteuert wird. Es ist hier immer der erste definierte pin der dann ein Signal weitergibt.
Die anderen 3 pins werden nicht angesteuert.
wenn ich die pins wechsel, dann leuchten die led, also jede einzelne verbindung funktioniert.

Ich frage mich ob das Programm mit der Snap 7 anbindung zu groß ist und wir auf einen Mega gehen müssen.
Hat damit vielleicht jemand erfahrung?

Hier das Programm, ist von der funktion noch nicht final.

#include <Ethernet.h>
#include "Settimino.h"
#include <Adafruit_NeoPixel.h>

// ---------- Netzwerk ----------
byte mac[] = { 0xA8, 0x61, 0x0A, 0xAE, 0x3A, 0xE2 };
IPAddress ipArduino(192,168,0,3);
IPAddress ipPLC(192,168,0,1);
IPAddress dns(0,0,0,0), gw(0,0,0,0), mask(255,255,255,0);
S7Client Client;

// ---------- LED-Hardware ----------
#define PIN_STRIP_1 2
#define PIN_STRIP_2 3
#define PIN_STRIP_3 4
#define PIN_STRIP_4 5

const uint8_t  STRIPS = 4;
// 134 LEDs aktiv + 1 LED Offset = 135 Puffer
const uint16_t NUM_LEDS_MAX = 135;

Adafruit_NeoPixel strip[STRIPS] = {
  Adafruit_NeoPixel(NUM_LEDS_MAX, PIN_STRIP_1, NEO_GRB + NEO_KHZ800),
  Adafruit_NeoPixel(NUM_LEDS_MAX, PIN_STRIP_2, NEO_GRB + NEO_KHZ800),
  Adafruit_NeoPixel(NUM_LEDS_MAX, PIN_STRIP_3, NEO_GRB + NEO_KHZ800),
  Adafruit_NeoPixel(NUM_LEDS_MAX, PIN_STRIP_4, NEO_GRB + NEO_KHZ800)
};

// reale Längen je Band
uint16_t activeLen[STRIPS] = { 134, 58, 58, 58 };

// erste physische LED (Index 0) bleibt unbenutzt
const uint8_t LED_OFFSET = 1;

// ---------- PLC Offsets ----------
const int DB_NUM = 10;

// SPS -> Arduino
const int OFF_SELECTED_MODE  = 2;   // BYTE
const int OFF_TEST_ENABLE_B  = 3;   // BYTE (Bit0 = Test)
const int OFF_TEST_STRIP     = 4;   // BYTE (0 = alle, 1..4 = Strip)
const int OFF_TEST_R         = 5;   // BYTE
const int OFF_TEST_G         = 6;   // BYTE
const int OFF_TEST_B         = 7;   // BYTE
const int OFF_TEST_BRIGHT    = 8;   // BYTE (0 = Default)

// Arduino -> SPS
const int OFF_STATE_BYTE20   = 20;  // BYTE (Bit0=Ready, Bit1=Error)
const int OFF_ERROR_CODE     = 22;  // INT
const int OFF_HEARTBEAT      = 24;  // WORD

// Bereich 0..18
const int BYTES_TO_READ = 19;

// ---------- Mode Bits ----------
#define SM_STOERUNG  0x01
#define SM_HAND      0x20
#define SM_AUTO      0x40

// ---------- Laufzeit ----------
uint32_t tAnim=0, tRead=0, tState=0;

uint8_t  selectedMode = 0;

bool     testEnable=false;
uint8_t  testStrip=0;
uint8_t  testR=255, testG=255, testB=255;
uint8_t  testBright=0;

bool     ardReady=false, ardError=false;
int16_t  ardErrCode=0;
uint16_t ardHeartbeat=0;

const uint8_t DEFAULT_BRIGHTNESS = 80;

// ---------- Helpers ----------
static inline uint32_t C(uint8_t r,uint8_t g,uint8_t b){
  return ((uint32_t)r<<16)|((uint32_t)g<<8)|b;
}

static inline void setPix(uint8_t s, uint16_t logicalIdx, uint32_t col){
  if(s>=STRIPS) return;
  if(logicalIdx>=activeLen[s]) return;

  uint16_t physIdx = logicalIdx + LED_OFFSET;
  if(physIdx>=NUM_LEDS_MAX) return;

  strip[s].setPixelColor(physIdx, col);
}

static void setAll(uint32_t col){
  for(uint8_t s=0;s<STRIPS;s++){
    for(uint16_t i=0;i<activeLen[s];i++) setPix(s,i,col);
  }
}

static float breathe01(uint32_t t,uint16_t per){
  float x=(t%per)/(float)per;
  return (sin(x*2*PI)+1.0f)*0.5f;
}

static float breatheScaled(uint32_t t,uint16_t per,float low,float high){
  float f=breathe01(t,per);
  return low + f*(high-low);
}

static void fillStripSolid(uint8_t s,uint32_t col){
  for(uint16_t i=0;i<activeLen[s];i++) setPix(s,i,col);
}

static void fillStripBreatheScaled(uint8_t s,uint32_t baseCol,uint32_t now){
  float f=breatheScaled(now,2000,0.40f,1.00f);
  uint8_t r=(uint8_t)(((baseCol>>16)&0xFF)*f);
  uint8_t g=(uint8_t)(((baseCol>>8 )&0xFF)*f);
  uint8_t b=(uint8_t)(( baseCol     &0xFF)*f);
  fillStripSolid(s,C(r,g,b));
}

static void fillStripChase(uint8_t s,uint32_t col,uint32_t now){
  if(activeLen[s]==0) return;
  uint8_t phase=(now/100)%activeLen[s];
  for(uint16_t i=0;i<activeLen[s];i++){
    bool on=((i+phase)%6)==0;
    setPix(s,i,on?col:0);
  }
}

// ---------- PLC Lesen ----------
uint8_t dbBuf[BYTES_TO_READ];

static void pollPLC(){
  if(!Client.Connected){
    Client.Disconnect();
    if(Client.ConnectTo(ipPLC,0,1)!=0){
      ardError=true; ardErrCode=11;
      return;
    }
  }

  int rc=Client.ReadArea(S7AreaDB, DB_NUM, 0, BYTES_TO_READ, S7WLByte, dbBuf);
  if(rc!=0){
    ardError=true; ardErrCode=12;
    return;
  }

  selectedMode = dbBuf[OFF_SELECTED_MODE];

  testEnable = (dbBuf[OFF_TEST_ENABLE_B] & 0x01)!=0;
  testStrip  = dbBuf[OFF_TEST_STRIP];
  testR      = dbBuf[OFF_TEST_R];
  testG      = dbBuf[OFF_TEST_G];
  testB      = dbBuf[OFF_TEST_B];
  testBright = dbBuf[OFF_TEST_BRIGHT];

  // Helligkeit
  uint8_t effB = (testBright > 0) ? testBright : DEFAULT_BRIGHTNESS;
  for(uint8_t s=0;s<STRIPS;s++) strip[s].setBrightness(effB);

  ardError=false;
  ardErrCode=0;
}

// ---------- PLC Schreiben ----------
static void pushStateToPLC(){
  uint8_t state=0;
  if(ardReady) state|=1<<0;
  if(ardError) state|=1<<1;
  Client.WriteArea(S7AreaDB,DB_NUM,OFF_STATE_BYTE20,1,S7WLByte,&state);

  uint8_t wb[2];
  S7.SetIntAt(wb,0,ardErrCode);
  Client.WriteArea(S7AreaDB,DB_NUM,OFF_ERROR_CODE,2,S7WLByte,wb);

  ardHeartbeat++;
  uint8_t hb[2];
  S7.SetWordAt(hb,0,ardHeartbeat);
  Client.WriteArea(S7AreaDB,DB_NUM,OFF_HEARTBEAT,2,S7WLByte,hb);
}

// ---------- Rendering: Test ----------
static void renderTEST(){
  uint32_t c=C(testR,testG,testB);

  if(testStrip==0){
    // alle Strips
    for(uint8_t s=0;s<STRIPS;s++){
      fillStripSolid(s,c);
    }
  } else if(testStrip>=1 && testStrip<=STRIPS){
    uint8_t s=testStrip-1;
    fillStripSolid(s,c);
  }
}

// ---------- Rendering: Auto ----------
static void renderAUTO(uint32_t now){
  for(uint8_t s=0;s<STRIPS;s++){
    // grünes Atmen
    fillStripBreatheScaled(s,C(0,200,0),now);
  }
}

// ---------- Rendering: Hand ----------
static void renderHAND(uint32_t now){
  for(uint8_t s=0;s<STRIPS;s++){
    // warmes Orange atmen
    fillStripBreatheScaled(s,C(255,180,40),now);
    // weißes Lauflicht
    fillStripChase(s,C(255,255,255),now);
  }
}

// ---------- Rendering: Störung ----------
static void renderFAULT(uint32_t now){
  uint8_t v = (uint8_t)(breatheScaled(now,900,0.1f,1.0f)*255);
  for(uint8_t s=0;s<STRIPS;s++){
    for(uint16_t i=0;i<activeLen[s];i++){
      setPix(s,i,C(v,0,0));
    }
  }
}

// ---------- Rendering: alles aus ----------
static void renderOFF(){
  setAll(0);
}

// ---------- Setup ----------
void setup(){
  Serial.begin(115200);
  while(!Serial){;}

  Ethernet.init(10);
  Ethernet.begin(mac,ipArduino,dns,gw,mask);
  delay(400);

  for(uint8_t s=0;s<STRIPS;s++){
    strip[s].begin();
    strip[s].setBrightness(DEFAULT_BRIGHTNESS);
    strip[s].setPixelColor(0,0); // erste LED sicher aus
    strip[s].show();
  }

  int cr=Client.ConnectTo(ipPLC,0,1);
  if(cr==0){
    ardReady=true;
    ardError=false;
  } else {
    ardReady=false;
    ardError=true;
    ardErrCode=10;
  }
}

// ---------- Loop ----------
void loop(){
  uint32_t now=millis();

  // PLC lesen
  if(now - tRead >= 100){
    tRead=now;
    pollPLC();
  }

  // LED-Animation
  if(now - tAnim >= 15){
    tAnim=now;

    if(testEnable){
      // Testmodus hat Vorrang
      setAll(0);
      renderTEST();
    } else {
      bool isStoer = (selectedMode & SM_STOERUNG)!=0;
      bool isHand  = (selectedMode & SM_HAND)!=0;
      bool isAuto  = (selectedMode & SM_AUTO)!=0;

      if(isStoer)        renderFAULT(now);
      else if(isHand)    renderHAND(now);
      else if(isAuto)    renderAUTO(now);
      else               renderOFF();
    }

    // erste physische LED immer AUS – verhindert Flackern
    for(uint8_t s=0;s<STRIPS;s++){
      strip[s].setPixelColor(0,0);
      strip[s].show();
    }
  }

  // Status zur SPS
  if(now - tState >= 500){
    tState=now;
    pushStateToPLC();
  }
}

tippe oder füge den Code hier ein

tippe oder füge den Code hier ein

Was ist ein Arduino one?

Grüße Uwe

was gibt der Compiler aus, wie viel Speicher wird verbraucht, was ist übrig. Kopier das mal rein.

das sind also 4 x 135 x 4 Byte die mal eben für deine Pixel benötigt werden ... hast du das zur Laufzeit noch über und bleibst du dann noch unter 50%?

mach mal ein Testprogram und steuere die 4 Streifen an. lass alles andere Weg, blinke nur jeweils einen Pixel je Strip.

Funktioniert das?

Das hört sich nach einem UNO an.

Damit bist Du mit den 4x135 Pixeln schon sehr weit.

Der Sketch verwendet 17756 Bytes (55%) des Programmspeicherplatzes. Das Maximum sind 32256 Bytes.
Globale Variablen verwenden 945 Bytes (46%) des dynamischen Speichers, 1103 Bytes für lokale Variablen verbleiben. Das Maximum sind 2048 Bytes.

Aber warum machst Du das:

Ich hab das mal umgeschrieben.

#include <Ethernet.h>
#include "Settimino.h"
#include <Adafruit_NeoPixel.h>

// ---------- Netzwerk ----------
byte mac[] = { 0xA8, 0x61, 0x0A, 0xAE, 0x3A, 0xE2 };
IPAddress ipArduino(192, 168, 0, 3);
IPAddress ipPLC(192, 168, 0, 1);
IPAddress dns(0, 0, 0, 0), gw(0, 0, 0, 0), mask(255, 255, 255, 0);
S7Client Client;

// ---------- LED-Hardware ----------
constexpr uint8_t PIN_STRIP_1 {2};
constexpr uint8_t PIN_STRIP_2 {3};
constexpr uint8_t PIN_STRIP_3 {4};
constexpr uint8_t PIN_STRIP_4 {5};

constexpr uint8_t STRIPS {4};
// 134 LEDs aktiv + 1 LED Offset = 135 Puffer

// reale Längen je Band
constexpr uint8_t activeLen[STRIPS] = { 134, 58, 58, 58 };

Adafruit_NeoPixel strip[STRIPS] =
{
  /*
    Adafruit_NeoPixel(NUM_LEDS_MAX, PIN_STRIP_1, NEO_GRB + NEO_KHZ800),
    Adafruit_NeoPixel(NUM_LEDS_MAX, PIN_STRIP_2, NEO_GRB + NEO_KHZ800),
    Adafruit_NeoPixel(NUM_LEDS_MAX, PIN_STRIP_3, NEO_GRB + NEO_KHZ800),
    Adafruit_NeoPixel(NUM_LEDS_MAX, PIN_STRIP_4, NEO_GRB + NEO_KHZ800)
  */

  Adafruit_NeoPixel(activeLen[0], PIN_STRIP_1, NEO_GRB + NEO_KHZ800),
  Adafruit_NeoPixel(activeLen[1], PIN_STRIP_2, NEO_GRB + NEO_KHZ800),
  Adafruit_NeoPixel(activeLen[2], PIN_STRIP_3, NEO_GRB + NEO_KHZ800),
  Adafruit_NeoPixel(activeLen[3], PIN_STRIP_4, NEO_GRB + NEO_KHZ800)

};

// erste physische LED (Index 0) bleibt unbenutzt
constexpr uint8_t LED_OFFSET {1};

// ---------- PLC Offsets ----------
constexpr uint8_t DB_NUM {10};

// SPS -> Arduino
const int OFF_SELECTED_MODE = 2;   // BYTE
const int OFF_TEST_ENABLE_B = 3;   // BYTE (Bit0 = Test)
const int OFF_TEST_STRIP = 4;   // BYTE (0 = alle, 1..4 = Strip)
const int OFF_TEST_R = 5;   // BYTE
const int OFF_TEST_G = 6;   // BYTE
const int OFF_TEST_B = 7;   // BYTE
const int OFF_TEST_BRIGHT = 8;   // BYTE (0 = Default)

// Arduino -> SPS
const int OFF_STATE_BYTE20 = 20;  // BYTE (Bit0=Ready, Bit1=Error)
const int OFF_ERROR_CODE = 22;  // INT
const int OFF_HEARTBEAT = 24;  // WORD

// Bereich 0..18
constexpr uint8_t BYTES_TO_READ {19};

// ---------- Mode Bits ----------
constexpr uint8_t SM_STOERUNG  {0x01};
constexpr uint8_t SM_HAND      {0x20};
constexpr uint8_t SM_AUTO      {0x40};

// ---------- Laufzeit ----------
uint32_t tAnim = 0, tRead = 0, tState = 0;

uint8_t selectedMode = 0;

bool testEnable = false;
uint8_t testStrip = 0;
uint8_t testR = 255, testG = 255, testB = 255;
uint8_t testBright = 0;

bool ardReady = false, ardError = false;
int16_t ardErrCode = 0;
uint16_t ardHeartbeat = 0;

const uint8_t DEFAULT_BRIGHTNESS = 80;

// ---------- Helpers ----------
static inline uint32_t C(uint8_t r, uint8_t g, uint8_t b)
{
  return ((uint32_t)r << 16) | ((uint32_t)g << 8) | b;
}

static inline void setPix(uint8_t s, uint16_t logicalIdx, uint32_t col)
{
  if (s >= STRIPS)
  {
    return;
  }

  if (logicalIdx >= activeLen[s])
  {
    return;
  }

  uint16_t physIdx = logicalIdx + LED_OFFSET;

  if (physIdx >= activeLen[s])
  {
    return;
  }

  strip[s].setPixelColor(physIdx, col);
}

static void setAll(uint32_t col)
{
  for (uint8_t s = 0; s < STRIPS; s++)
  {
    for (uint16_t i = 0; i < activeLen[s]; i++)
    {
      setPix(s, i, col);
    }
  }
}

static float breathe01(uint32_t t, uint16_t per)
{
  float x = (t % per) / (float)per;
  return (sin(x * 2 * PI) +1.0f) * 0.5f;
}

static float breatheScaled(uint32_t t, uint16_t per, float low, float high)
{
  float f = breathe01(t, per);
  return low + f * (high - low);
}

static void fillStripSolid(uint8_t s, uint32_t col)
{
  for (uint16_t i = 0; i < activeLen[s]; i++)
  {
    setPix(s, i, col);
  }
}

static void fillStripBreatheScaled(uint8_t s, uint32_t baseCol, uint32_t now)
{
  float f = breatheScaled(now, 2000, 0.40f, 1.00f);
  uint8_t r = (uint8_t)(((baseCol >> 16) & 0xFF) * f);
  uint8_t g = (uint8_t)(((baseCol >> 8 ) & 0xFF) * f);
  uint8_t b = (uint8_t)(( baseCol & 0xFF) * f);
  fillStripSolid(s, C(r, g, b));
}

static void fillStripChase(uint8_t s, uint32_t col, uint32_t now)
{
  if (activeLen[s] == 0)
  {
    return;
  }

  uint8_t phase = (now / 100) % activeLen[s];

  for (uint16_t i = 0; i < activeLen[s]; i++)
  {
    bool on = ((i + phase) % 6) == 0;
    setPix(s, i, on ? col : 0);
  }
}

// ---------- PLC Lesen ----------
uint8_t dbBuf[BYTES_TO_READ];

static void pollPLC()
{
  if (!Client.Connected)
  {
    Client.Disconnect();

    if (Client.ConnectTo(ipPLC, 0, 1) != 0)
    {
      ardError = true; ardErrCode = 11;
      return;
    }
  }

  int rc = Client.ReadArea(S7AreaDB, DB_NUM, 0, BYTES_TO_READ, S7WLByte, dbBuf);

  if (rc != 0)
  {
    ardError = true; ardErrCode = 12;
    return;
  }

  selectedMode = dbBuf[OFF_SELECTED_MODE];
  testEnable = (dbBuf[OFF_TEST_ENABLE_B] & 0x01) != 0;
  testStrip = dbBuf[OFF_TEST_STRIP];
  testR = dbBuf[OFF_TEST_R];
  testG = dbBuf[OFF_TEST_G];
  testB = dbBuf[OFF_TEST_B];
  testBright = dbBuf[OFF_TEST_BRIGHT];
  // Helligkeit
  uint8_t effB = (testBright > 0) ? testBright : DEFAULT_BRIGHTNESS;

  for (uint8_t s = 0; s < STRIPS; s++)
  {
    strip[s].setBrightness(effB);
  }

  ardError = false;
  ardErrCode = 0;
}

// ---------- PLC Schreiben ----------
static void pushStateToPLC()
{
  uint8_t state = 0;

  if (ardReady)
  {
    state |= 1 << 0;
  }

  if (ardError)
  {
    state |= 1 << 1;
  }

  Client.WriteArea(S7AreaDB, DB_NUM, OFF_STATE_BYTE20, 1, S7WLByte, &state);
  uint8_t wb[2];
  S7.SetIntAt(wb, 0, ardErrCode);
  Client.WriteArea(S7AreaDB, DB_NUM, OFF_ERROR_CODE, 2, S7WLByte, wb);
  ardHeartbeat++;
  uint8_t hb[2];
  S7.SetWordAt(hb, 0, ardHeartbeat);
  Client.WriteArea(S7AreaDB, DB_NUM, OFF_HEARTBEAT, 2, S7WLByte, hb);
}

// ---------- Rendering: Test ----------
static void renderTEST()
{
  uint32_t c = C(testR, testG, testB);

  if (testStrip == 0)
  {
    // alle Strips
    for (uint8_t s = 0; s < STRIPS; s++)
    {
      fillStripSolid(s, c);
    }
  }
  else if (testStrip < STRIPS)
  {
    uint8_t s = testStrip - 1;
    fillStripSolid(s, c);
  }
}

// ---------- Rendering: Auto ----------
static void renderAUTO(uint32_t now)
{
  for (uint8_t s = 0; s < STRIPS; s++)
  {
    // grünes Atmen
    fillStripBreatheScaled(s, C(0, 200, 0), now);
  }
}

// ---------- Rendering: Hand ----------
static void renderHAND(uint32_t now)
{
  for (uint8_t s = 0; s < STRIPS; s++)
  {
    // warmes Orange atmen
    fillStripBreatheScaled(s, C(255, 180, 40), now);
    // weißes Lauflicht
    fillStripChase(s, C(255, 255, 255), now);
  }
}

// ---------- Rendering: Störung ----------
static void renderFAULT(uint32_t now)
{
  uint8_t v = (uint8_t)(breatheScaled(now, 900, 0.1f, 1.0f) * 255);

  for (uint8_t s = 0; s < STRIPS; s++)
  {
    for (uint16_t i = 0; i < activeLen[s]; i++)
    {
      setPix(s, i, C(v, 0, 0));
    }
  }
}

// ---------- Rendering: alles aus ----------
static void renderOFF()
{
  setAll(0);
}

// ---------- Setup ----------
void setup()
{
  Serial.begin(115200);

  while (!Serial) {;}

  Ethernet.init(10);
  Ethernet.begin(mac, ipArduino, dns, gw, mask);
  delay(400);

  for (uint8_t s = 0; s < STRIPS; s++)
  {
    strip[s].begin();
    strip[s].setBrightness(DEFAULT_BRIGHTNESS);
    strip[s].setPixelColor(0, 0); // erste LED sicher aus
    strip[s].show();
  }

  int cr = Client.ConnectTo(ipPLC, 0, 1);

  if (cr == 0)
  {
    ardReady = true;
    ardError = false;
  }
  else
  {
    ardReady = false;
    ardError = true;
    ardErrCode = 10;
  }
}

// ---------- Loop ----------
void loop()
{
  uint32_t now = millis();

  // PLC lesen
  if (now - tRead >= 100)
  {
    tRead = now;
    pollPLC();
  }

  // LED-Animation
  if (now - tAnim >= 15)
  {
    tAnim = now;

    if (testEnable)
    {
      // Testmodus hat Vorrang
      setAll(0);
      renderTEST();
    }
    else
    {
      bool isStoer = (selectedMode & SM_STOERUNG) != 0;
      bool isHand = (selectedMode & SM_HAND) != 0;
      bool isAuto = (selectedMode & SM_AUTO) != 0;

      if (isStoer)
      {
        renderFAULT(now);
      }
      else if (isHand)
      {
        renderHAND(now);
      }
      else if (isAuto)
      {
        renderAUTO(now);
      }
      else
      {
        renderOFF();
      }
    }

    // erste physische LED immer AUS – verhindert Flackern
    for (uint8_t s = 0; s < STRIPS; s++)
    {
      strip[s].setPixelColor(0, 0);
      strip[s].show();
    }
  }

  // Status zur SPS
  if (now - tState >= 500)
  {
    tState = now;
    pushStateToPLC();
  }
}

Aehm...

Davon abgesehen, dass die 1. Bedingung immer eintritt, darf testStrip nur Werte von 0 ... 3 annehmen. In dem Fall ist auch 4 möglich und damit falsch.

Noch nicht fertig, aber ein Anfang.

Wieso 4 Byte pro Neopixel? Sind das nicht 3 Byte?
Auch bei 3 Byte sind das 135x3x4 = 1620 Byte. Da ist

Durch die Neopixel sind bereits der Großteil des RAMs belegt. Dazu noch das Ethernet Shiled. Da reicht das RAM nicht.

Also nochmal Welchen Arduino hast Du und welches Shield.

Grüße Uwe

hast recht, bei seinen GRB 3 Farben sinds also nur 3 Byte

  numBytes = n * ((wOffset == rOffset) ? 3 : 4);