problema visualizzazione minuti su adafruit neopixel16x

ciao a tutti, ho un problema nel visualizzare i minuti con il neopixel ring
16x, ogni led integra un circuito che regola il colore(RGB) di ogni singolo led
e utilizza un solo pin di arduino per comandarli.
per visualizzare l'ora ho risolto con un switch/case per ogni singola ora, il
problema si presenta con i minuti visto che ogni led mi deve visualizzare
quando sono passati 3min e 45sec e fare accendere quello successivo quando
ne passano altri 3min e 45sec e così via.... non ho troppe idee a riguardo, speriamo
che riuscite a darmi una mano ma sicuramente sarà cosi XD vi posto il codice e una
che vi può chiarire le idee https://db.tt/EEWc5PBD

#include <Wire.h>
#include "RTClib.h"
#include <Adafruit_NeoPixel.h>

#define PIN 6
byte prev_second=0;
int pin_ledSec = 15;

RTC_DS1307 rtc;
Adafruit_NeoPixel strip = Adafruit_NeoPixel(16, PIN, NEO_GRB + NEO_KHZ800);

void setup () {
  
  Wire.begin();
  rtc.begin();
  strip.begin();
  strip.show(); 
  
}

void loop () {
    DateTime now = rtc.now();
    strip.setBrightness(128);
    set_ora();
    set_sec();
    
    }
    
    void set_ora(){
      DateTime now = rtc.now();
       switch(now.hour()) 
    {
      case 0:
        strip.setPixelColor(15, 0, 0, 200);  // il 15 è il num del pin , il resto sono i valori dell'RGB
        strip.setPixelColor(0, 0, 0, 200);
        strip.show();
        break;
        case 1:
        strip.setPixelColor(14, 0, 0, 200);
        strip.show();
        break;
        case 2:
        strip.setPixelColor(13, 0, 0, 200);
        strip.show();
        break;
        case 3:
        strip.setPixelColor(12, 0, 0, 200);
        strip.setPixelColor(11, 0, 0, 200);
        strip.show();
        break;
        case 4:
        strip.setPixelColor(10, 0, 0, 200);
        strip.show();
        break;
        case 5:
        strip.setPixelColor(9, 0, 0, 200);
        strip.show();
        break;
        case 6:
        strip.setPixelColor(8, 0, 0, 200);
        strip.setPixelColor(7, 0, 0, 200);
        strip.show();
        break;
        case 7:
        strip.setPixelColor(6, 0, 0, 200);
        strip.show();
        break;
        case 8:
        strip.setPixelColor(5, 0, 0, 200);
        strip.show();
        break;
        case 9:
        strip.setPixelColor(4, 0, 0, 200);
        strip.setPixelColor(3, 0, 0, 200);
        strip.show();
        break;
        case 10:
        strip.setPixelColor(2, 0, 0, 200);
        strip.show();
        break;
        case 11:
        strip.setPixelColor(1, 0, 0, 200);
        strip.show();
        break;
        case 12:
        strip.setPixelColor(15, 0, 0, 200);
        strip.setPixelColor(0, 0, 0, 200);
        strip.show();
        break;
        case 13:
        strip.setPixelColor(14, 0, 0, 200);
        strip.show();
        break;
        case 14:
        strip.setPixelColor(13, 0, 0, 200);
        strip.show();
        break;
        case 15:
        strip.setPixelColor(12, 0, 0, 200);
        strip.setPixelColor(11, 0, 0, 200);
        strip.show();
        break;
        case 16:
        strip.setPixelColor(10, 0, 0, 200);
        strip.show();
        break;
        case 17:
        strip.setPixelColor(9, 0, 0, 200);
        strip.show();
        break;
        case 18:
        strip.setPixelColor(8, 0, 0, 200);
        strip.setPixelColor(7, 0, 0, 200);
        strip.show();
        break;
        case 19:
        strip.setPixelColor(6, 0, 0, 200);
        strip.show();
        break;
        case 20:
        strip.setPixelColor(5, 0, 0, 200);
        strip.show();
        break;
        case 21:
        strip.setPixelColor(4, 0, 0, 200);
        strip.setPixelColor(3, 0, 0, 200);
        strip.show();
        break;
        case 22:
        strip.setPixelColor(2, 0, 0, 200);
        strip.show();
        break;
        case 23:
        strip.setPixelColor(1, 0, 0, 200);
        strip.show();
        break;
      }
    }

void set_sec(){
    DateTime now = rtc.now(); 
   
    if(pin_ledSec == -1){pin_ledSec =15;} // questo if serve per far riprendere il ciclo orario del led
    if(now.second() != prev_second){
      prev_second = now.second();

        strip.setPixelColor(pin_ledSec, 0, 200, 0);
        strip.show();
        delay(999);
        strip.setPixelColor(pin_ledSec, 0, 0, 0);
        strip.show();
        if(pin_ledSec < 16){pin_ledSec = pin_ledSec-1;}
        
      }
}

http://arduino.cc/en/Reference/Map
LEDminuti = map(minuti+costante, 0,59, 0 ,15);
aggiungi ai miunti un valore per avere un risultato uniforma.
Per le ore fai la stessa cosa ma visto che usi 2 LED fai 2 map e aggiungi per ogni map un numero diverso in modo che quando hai un numero tra 2 led ti si illumniano 2 LED.

Ciao Uwe

Ciao biohazard91,
ultimamente mi sono divertito a fare un po' di questi orologi con i neoPixel ... oggetti molto simpatici, ne ho fatti con il ring a 12 LED, con quello a 24 LED e con i quello a 60 LED (4 semicerchi da 15 LED ... QUESTI).

Per evitare i problemi che stai incontrando tu e poter fare una cosa generica (ho fatto un unico stampato con ATtiny85 e un DS1307) indipendente da quale dei tre tipi di ring usi, la cosa più semplice NON è lavorare come fai tu in ore, minuti e secondi, ma sempre e solo in secondi ... anzi, meglio, per avere un aggiornamento più corretto del ring, in decimi di secondo.

In questo modo hai sempre numeri interi con cui giocare e puoi facilmente fare una formula che ti identifica quale led accendere :wink:

Per chiarezza ti faccio un esempio semplice, preso dalla prima versione del mio programma, che era nata solo per il neoPixel a 24 LED ... poi l'ho resa generica, ma è un po' più complessa e meno adatta ad una spiegazione ... :grin:

Come ti dicevo io ho una variabile "unsigned long int" che mi conta i decimi di secondo e che riparte da 0 a mezzanotte. Ti servono poi tre variabili che ti indicheranno quale LED devi accendere delle per le ore, per i minuti e per i secondi ...
... tTime è la varibile che contiene i decimi di secondo, ssLED, mmLED, hhLED, indicano il numero di LED da accendere ...

ssLED = (tTime / 25) % 24;              // On 24 LEDs, 1 LED = 2,5 secs  =   25 tenths
mmLED = (tTime / 1500) % 24;            // On 24 LEDs, 1 LED = 2,5 mins  =  150 secs = 1500 tenths
hhLED = (tTime / 18000) % 24;           // On 24 LEDs, 1 LED = 1/2 hour  = 1800 secs = 18000  tenths

I commenti parlano da soli ... come vedi molto semplice e decine di volte più compatta di quella serie di IF che ... hai dovuto fare tu XD XD XD

Certo comunque che come ring, per fare un orologio, hai scelto il peggiore (... per numero di LED) ... :roll_eyes:

Guglielmo

uwefed:
http://arduino.cc/en/Reference/Map
LEDminuti = map(minuti+costante, 0,59, 0 ,15);
aggiungi ai miunti un valore per avere un risultato uniforma.
Per le ore fai la stessa cosa ma visto che usi 2 LED fai 2 map e aggiungi per ogni map un numero diverso in modo che quando hai un numero tra 2 led ti si illumniano 2 LED.

Ciao Uwe

ciao, grazie per la risposta ma non ho capito il motivo per cui debba sommarli una costante("per avere un risultato uniforma"), e poi mi sono dimenticato di specificare che l'ordine dei led è antiorario, in questo nodo https://db.tt/XnGvCmo4

gpb01:
Ciao biohazard91,
ultimamente mi sono divertito a fare un po' di questi orologi con i neoPixel ... oggetti molto simpatici, ne ho fatti con il ring a 12 LED, con quello a 24 LED e con i quello a 60 LED (4 semicerchi da 15 LED ... QUESTI).

Per evitare i problemi che stai incontrando tu e poter fare una cosa generica (ho fatto un unico stampato con ATtiny85 e un DS1307) indipendente da quale dei tre tipi di ring usi, la cosa più semplice NON è lavorare come fai tu in ore, minuti e secondi, ma sempre e solo in secondi ... anzi, meglio, per avere un aggiornamento più corretto del ring, in decimi di secondo.

In questo modo hai sempre numeri interi con cui giocare e puoi facilmente fare una formula che ti identifica quale led accendere :wink:

Per chiarezza ti faccio un esempio semplice, preso dalla prima versione del mio programma, che era nata solo per il neoPixel a 24 LED ... poi l'ho resa generica, ma è un po' più complessa e meno adatta ad una spiegazione ... :grin:

Come ti dicevo io ho una variabile "unsigned long int" che mi conta i decimi di secondo e che riparte da 0 a mezzanotte. Ti servono poi tre variabili che ti indicheranno quale LED devi accendere delle per le ore, per i minuti e per i secondi ...
... tTime è la varibile che contiene i decimi di secondo, ssLED, mmLED, hhLED, indicano il numero di LED da accendere ...

ssLED = (tTime / 25) % 24;              // On 24 LEDs, 1 LED = 2,5 secs  =   25 tenths

mmLED = (tTime / 1500) % 24;            // On 24 LEDs, 1 LED = 2,5 mins  =  150 secs = 1500 tenths
hhLED = (tTime / 18000) % 24;           // On 24 LEDs, 1 LED = 1/2 hour  = 1800 secs = 18000  tenths




I commenti parlano da soli ... come vedi molto semplice e decine di volte più compatta di quella serie di IF che ... hai dovuto fare tu XD XD XD

Certo comunque che come ring, per fare un orologio, hai scelto il peggiore (*... per numero di LED*) ... :roll_eyes:

Guglielmo

ahaha, effetivamente non sono il massimo il numero di led ma avevo solo quella in casa inutilizzata =)
quindi, se ho capito bene.... con l'RTC faccio un IF che quando arriva a 00:00:00 fa in modo che mi resetti la variabile tTime
e quel % 24 lo sostituisco con il 16 che è il numero dei pin del ring...

biohazard91:
quindi, se ho capito bene.... con l'RTC faccio un IF che quando arriva a 00:00:00 fa in modo che mi resetti la variabile tTime

NO, in realtà io uso il DS1307 solo per "rimettere" ogni X minuti (es. una volta l'ora) il mio contatore di decimi di secondo che però è del tutto indipendente dal DS1307.

Per un oggetto banale come questo, rimettendo l'orario ogni X minuti/ore, la precisione della millis() è più che sufficiente ... ti do un estratto dal codice :

void loop() {
  ...
  // Update the clock variable
  if ((millis() - lastMillis) >= 100) {
    lastMillis = millis();
    tTime++;
    if (tTime >= 432000) tTime = 0;   // IF 12 hours, reset from 0
    showTIME();                       // Update the neoPiexel Array
  }
  ...
}

... come vedi, in realtà, lavoro sempre a 12 ore, tanto ... non hai la visualizzazione del valore numerico e considerare solo 12 ore è più semplice.

biohazard91:
... quel % 24 lo sostituisco con il 16 che è il numero dei pin del ring...

Non basta ... devi calcolarti anche i valori delle divisioni :wink: Quelli sono validi per 24 LED ... guarda i commenti ...

Guglielmo

ok, ho capito il procedimento con i decimi di secondo però ogni led del ring equivale a 3,45 m(207secondi), secondo te se gli facessi fare il cambio led contando semplicemente i secondi con l'rtc? cioè, ogni 207sec cambia led... per i secondi mi piace di più che continuano a girare :smiley: :smiley: tra l'altro con la funzione strip.getPixelColor(15) puoi "interrogare" il led e quindi quando il led che conta i secondi ci passa sopra gli posso dire che se era spento allora lo accendi di verde e basta oppure se era di un colore gli faccio combinare i due colori assieme. dimmi te cosa ne pensi XD

... penso che ti piace complicarti la vita :grin: XD :grin:

Una volta che sai esattamente quale LED deve essere acceso (... e LO SAI se hai calcolato ssLED, mmLED, hhLED come ti ho detto) basta un volgare FOR per accendere e spegnere quelli che ti interessano. Io inoltre illumino con il blu al minimo (intensità 2) tutti i LED (... anche quelli che devono essere spenti, per dare l'idea dell'orologio) e con il rosso al minimo (intensità 2) i LED dei quarti (15, 30, 45) :wink:

Banale e veloce ... ecco il codice per i 24 LED ... ovviamente lo devi modificare per i tuoi 16 ...

for (i = 0; i < 24; i++) {
    if ((i % 6) == 0) {
      strip.setPixelColor(i, ((hhLED == i) ? 255 : 2), ((ssLED == i) ? 255 : 0), ((mmLED == i) ? 255 : 0));
    }
    else {
      strip.setPixelColor(i, ((hhLED == i) ? 255 : 0), ((ssLED == i) ? 255 : 0), ((mmLED == i) ? 255 : 2));
    }
}
strip.show();

Guglielmo

P.S. : Come vedi, il trucco è nel fare uso dell'operatore condizionale "? :" ... :wink:

....ciao a tutti, chi è così gentile da indicarmi dove poter prendere il codice per realizzare un orologio con 60 led neopixel e DS1307
grazie.

anatol:
....ciao a tutti, chi è così gentile da indicarmi dove poter prendere il codice per realizzare un orologio con 60 led neopixel e DS1307
grazie.

... ho idea che te lo devi scrivere da solo ... e noi ti aiutiamo a correggerlo ... :wink:

Fai un po' di ricerche qui sul forum e vedi come gestire il DS1307, il resto ... lo trovi in piccoli pezzi anche in questo therad :slight_smile:

Guglielmo