Striscia led WS2812b con Attiny85 si accendono solo 110 led

Buongiorno ragazzi.
Sto cercando di dare un tocco di classe al mio home studio di registrazione con l’inserimento di qualche striscia led.
Come da titolo, ho una striscia led di circa 250 led di tipo WS2812b, alimentata con un alimentatore da 60W. Il microcontrollore che sto usando è un Attiny85, che per le sue dimensioni è perfetto per l’uso che devo farne. I led si dovrebbero accendere grazie ad un rilevatore di distanza ad ultrasuoni, se passo la mano a meno di 30 cm dal sensore i led si accendono.
Sto facendo funzionare il tutto con la libreria Adafruit_NeoPixels.h. Ecco il mio codice:

#include <Adafruit_NeoPixel.h>

#define NUM_LEDS 110

const int trigger = 1;
const int echo = 2;
const int maxDistance = 30;
bool on = false;

Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUM_LEDS, 0, NEO_GRB + NEO_KHZ800);

void setup(){
  pixels.begin();
  pinMode(trigger, OUTPUT);
  pinMode(echo, INPUT);
  digitalWrite(trigger, LOW);
  light(true);
}

void loop(){
  if(dist() < maxDistance){
    on = !on;
    light(on);

   delay(1000);
       
    while(true){
      if(dist() > maxDistance){
        break;
      }
    }
  } 
}

void light(bool on){
  if(on){
    for(int i=0;i<NUM_LEDS;i++){
      pixels.setPixelColor(i, pixels.Color(0, 255, 0));
      pixels.show();
    }
  }else{
    for(int i=0;i<NUM_LEDS;i++){
      pixels.setPixelColor(i, pixels.Color(0, 0, 0));
      pixels.show();
    }
  }
}

long dist(){
  digitalWrite(trigger, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigger, LOW);

  long durata = pulseIn(echo, HIGH);
  long distanza = 0.034 * durata / 2;

  return distanza;
}

Il problema è questo: se come numero totale dei led indico circa 110 led allora tutto funziona alla perfezione, se ne indico di più, smette di funzionare e non se ne accende neanche uno. Come può essere?
Grazie in anticipo!

Tiro ad indovinare, finita la memoria del tiny? Considera che ogni pixel richiede 3 byte il tiny85 ne ha un totale di 512, anche a volerla usare tutta puoi usaren un massimo di 169 (in realtà meno perché nella SRAM ci vanno anche le altre variabili e cose necessarie all’esecuzione del programma)

Empty imported post

In questi casi, Guglielmo docet: APA102!
Con i WS2812b devi mandare i dati in rapida sequenza rispettando le tempistiche imposte dal cip.
Con gli APA102, hai un clock per temporizzare il passaggio dei dati.
Che significa? Che con i WS2812b devi tirarti tutti i dati in memoria e poi trasferirli, altrimenti non riesci a rispettare le tempistiche, con gli APA102 puoi passare i dati a rate appoggiandoti anche a strutture di memoria più lente per memorizzare le sequenze o facendo elaborazioni nel mezzo, ad es. ripetendo la sequenza ogni tot led senza il rischio di sballare la trasmissione dati.

Maurizio

Insomma dovrei comprare un'altra striscia. Vabbè al limite userò l'atmega328

Io proverei anche a usare il metodo clear e fill della libreria anzichè i for per assegnare i colori al singolo pixel dovrebbe essere più performante perché se non ricordo male la loro libreria è scritta in assembler per essere efficiente al massimo

>militandri: ... perché il post #2 è vuoto? ? ? :o

Guglielmo

Indipendentemente dal tipo di interfaccia, se a un pin o due la memoria necessaria per memorizzare i dati colore di un pin restano invariati ovvero 3 Byte per LED.
Se vuoi pilotare 250 LED servono 750Byte RAM.

Ciao Uwe

In alternativa, potresti usare soltanto 100 led e giocare anche sui colori.

uwefed:
Indipendentemente dal tipo di interfaccia, se a un pin o due la memoria necessaria per memorizzare i dati colore di un pin restano invariati ovvero 3 Byte per LED.
Se vuoi pilotare 250 LED servono 750Byte RAM.

Ciao Uwe

Se la sequenza la generi tramite funzione matematica e puoi inviare il risultato direttamente alla striscia senza memorizzarlo prima, quanto dici non è più vero!

Ora, se devi rispettare dei timing fissi, la cosa diventa molto più complicata (per i WS2812b dovresti scrivere la comunicazione senza usare le librerie già pronte che si salvano prima tutto e poi trasmettono) se non impossibile, se il timing lo decidi tu fornendo il clock, non hai vincoli, se non quelli della durata complessiva di tutto un giro che potrebbe rendere sgradevole l'effetto.

Maurizio

Comunque, per continuare ad utilizzare la striscia WS2812b e l'Attiny85, un'alternativa potrebbe essere quella di dividere la striscia in 3 segmenti da pilotare singolarmente e alternativamente.

Altra possibilità ancora, se l'effetto desiderato è ripetitivo, si potrebbe anche pilotare vari spezzoni, opportunamente dimensionati, in parallelo.
Ad es. se si creano sequenze ripetute da 50 led, si potrebbero collegare in parallelo i segnali di comando di 5 spezzoni così da pilotarli tutti contemporaneamente con un singolo segnale che riproduce lo stesso effetto su tutti e 5 gli spezzoni contemporaneamente.

Dipende tanto dal genere di effetti che si desidera produrre e dalle possibilità di cablaggio.

Maurizio

Per inciso ... molto tempo fa ci fu un thread in cui l'utente bitbank propse una interessante soluzione che NON richiede il buffer dei singoli LED ... la discussione cominciò QUI e proseguì nelle pagine successive.

L'idea è buona e bitbank ha anche rilasciato un codice funzionante su github, QUI ... chi è interessato può provare a studiarlo ed ad applicarlo.

Guglielmo

La dimostrazione a quello che affermavo io, senza dover perdere tempo a dimostrarlo io stesso… questa si che è vita! :stuck_out_tongue:
Ma poi gli avete offerto questo caffè?

Grazie, comunque per la segnalazione.

Maurizio