Denis Lanfrit

Sito personale riguardante i miei progetti elettronici e non

Spectrum II

Ecco il secondo articolo dedicato a Spectrum, se non hai letto il primo ecco il link

Dopo aver scoperto l’esistenza di alcuni led “intelligenti” abbiamo deciso di semplificare in modo radicale il nostro progettino. Infatti viene praticamente eliminata tutta l’elettronica di controllo dei led costituita dai TLC5940.

WS2812B

Questo è il nome di questi particolari led RGB. Ma cosa hanno di speciale? Dall’esterno sembrano dei normali led smd 5050, in realtà all’interno integrano un controller in grado di ricevere dati in forma seriale e pilotare il led. Ogni led oltre all’alimentazione (5V) presenta due pin per i dati, un ingresso e un’uscita. In questo modo è possibile concatenare molti led e pilotarli tutti con un singolo pin di Arduino! In pratica è possibile controllare il colore di ogni singolo led presente nella catena.

ws2812

Il funzionamento è molto semplice, il microcontrollore (nel nostro caso Arduino) invia una sequenza di bit in forma seriale asincrona sbilanciata con protocollo NRZ. Per definire il colore di un led sono necessari 24 bit (8bit per colore, ovvero 16777216 combinazioni di colore). Quindi vengono inviati dei “pacchetti” da 24bit in modo sequenziale. Il primo led “legge” la sequenza in ingresso, cancella i primi 24 bit (a lui dedicati) e invia la sequenza al led succesivo che farà lo stesso. Inoltre il circuito interno “rigenera” il segnale, in questo modo la catena di led non è limitata dalla lunghezza della linea ma solo dal ritardo del segnale.

WS2812 timing

Ecco qua sopra uno schemino tratto dal datasheet.

Montaggio

I led in questione vengono venduti in striscie adesive come i comuni led per decoro. Il montaggio è risultato quindi molto semplice, ecco uno schemino che illustra la disposizione:

ws2812 disposizione

Software

Il software non è complesso. Per semplicità è stata utilizzata una libreria per la gestione dei led che si chiama FastLed. Quindi basta installare questa libreria nel proprio ambiente di sviluppo (Arduino IDE) e si è pronti.

Il codice di Spectrum è molto semplice:

Mostra il codice


/*
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 */

#include 

// numero totale di led
#define NUM_LEDS 56
#define COLONNE 7
#define RIGHE 8

// definizione dei pin
#define DATA_PIN 6 //pin per il collegamento della striscia led
#define STROBE_PIN 4 //pin strobe msgeq7
#define RESET_PIN 5  //pin reset msgeq7

//ALTRO
#define BRIGHTNESS  255    //luminosità
#define RUMORE 15          //soglia rumore

// definizione della matrice di led
CRGB leds[NUM_LEDS];

typedef struct ledrgb     //struct contenenti i parametri relativi ad un led
{
  int r;
  int g;
  int b;
  int hue;
  int sat;
  int val;
  int nled;
  boolean attivo;
} 
led;

led colori[COLONNE][RIGHE];  //matrice contenente il numero progressivo di ogni singolo led


//variabili globali
int destra[7];     //array contenente i dati relativi al canale destro
int sinistra[7];   //array contenente i dati relativi al canale sinistro
int medio[7];      //array contenente la media dei dati contenuti nei due array precedenti
int nlivello;      //indice del livello
int delta=130;     //valore che corrisponde ad un livello 128
int hue_arcobaleno=0; //variabile globale per l'hue variabile dell'arcobaleno
int long time_arcobaleno=0;
int long time_cambio=0;
int effetto=0;

//prototipi di funzione
void leggiMSGEQ7(void);     //riceve i dati dall'integrato MSGEQ7
void colonna_piena(void);   //visualizza i dati in colonne piene
void aggiornaRGB(void);     //funzione che trasmette i valori degli array agli integrati
void aggiornaHSV(void);     //funzione che trasmette i valori degli array agli integrati
void arcobaleno_a_colonne(void);      //colora le colonne di colori diversi
void arcobaleno_a_punti(void);      //colora i led di colori diversi
void colore_totale_hsv(int, int, int);  //colora tutti i led dello stesso colore hsv
void colore_totale_rgb(int, int, int);  //colora tutti i led dello stesso colore rgb

//////SETUP//////
void setup() {
  Serial.begin (9600);           //inizializza la seriale
  pinMode (DATA_PIN, OUTPUT);    //settaggio dei pin
  pinMode (STROBE_PIN, OUTPUT);
  pinMode (RESET_PIN, OUTPUT);
  
  int n=0;

  for(int i=0; i<7; i++){         //numera i led (dipende da come sono collegati)
    for(int j=0; j<8; j++){
      colori[i][j].nled=n;
      n++;
    }
  }


  FastLED.addLeds<WS2812B,DATA_PIN, RGB>(leds, NUM_LEDS).setCorrection( TypicalLEDStrip );
  FastLED.setBrightness( BRIGHTNESS );
  time_arcobaleno=millis();
  time_cambio=millis();
}


//////LOOP//////
void loop() {

  leggiMSGEQ7();
  
  if(millis()-time_cambio > 5000){       //codice che stabilisce ogni quanto cambiare effetto
    effetto++;
    if(effetto>3){
      effetto=0;
    }
    time_cambio=millis();
  }
  
  
  switch(effetto){
    case 0:
            arcobaleno_a_punti();
            colonna_piena();
            aggiornaHSV();
            break;
    case 1:
            if(millis()-time_arcobaleno > 15){
              arcobaleno_dinamico();
              time_arcobaleno=millis();
            }
            colonna_piena();
            aggiornaHSV();
            break;
    case 2: 
            if(millis()-time_arcobaleno > 15){
              arcobaleno_dinamico();
              time_arcobaleno=millis();
            }
            colonna_piena();
            if(destra[1]/delta > 5){
              colore_totale_rgb(255, 255, 255);
              aggiornaRGB();
            }else{
              aggiornaHSV();
            }
            break;
    case 3:
            colore_totale_hsv(255, 255, 255);
            colonna_piena();
            aggiornaHSV();
            break;
  }
    
 
  
  ////esempio settaggio colore:
  //leds[i] = CRGB( 50, 100, 150);
  //leds[i] = CRGB::Red;
  // La conversio a RGB è automatica.
  //leds[i] = CHSV( 160, 255, 255);
  //leds[i] = CRGB::Red;
  //FastLED.show();
  //FastLED.delay(1000 / FRAMES_PER_SECOND);

  delay(30);
}

/////FUNZIONI


// Funzione che legge le 7 bande del canale destro e sinistro.
void leggiMSGEQ7(void){

  digitalWrite(RESET_PIN, HIGH);
  digitalWrite(RESET_PIN, LOW);
  
  for(int banda=0; banda <COLONNE; banda++){
    digitalWrite(STROBE_PIN,LOW); // strobe, passa alla banda sucessiva 
    delayMicroseconds(30); //ritardo per rispettare le tempistiche dell'integrato (vedere datasheet) 
    destra[banda] = analogRead(0)-RUMORE; // salva la lettura della banda destra
    sinistra[banda] = analogRead(1)-RUMORE; // ... e di quella sinistra
    digitalWrite(STROBE_PIN,HIGH);
    medio[banda]= (destra[banda] + sinistra[banda])/2;  
    Serial.println (destra [banda], DEC);
  }

}

void aggiornaRGB(void){
  for(int i=0; i<7; i++){
    for(int j=0; j<8; j++){
      if(colori [i][j].attivo==1){
        leds[colori[i][j].nled] = CRGB(colori[i][j].r, colori[i][j].g, colori[i][j].b);
      }else{
        leds[colori[i][j].nled] = CRGB::Black;    
      }
      FastLED.show();  // è qui che i led effettivamente vengono aggiornati 
    }  
  }
}

void aggiornaHSV(void){
  for(int i=0; i<COLONNE; i++){
    for(int j=0; j<RIGHE; j++){
      if(colori[i][j].attivo==1){
        leds[colori[i][j].nled] = CHSV(colori[i][j].hue, colori[i][j].sat, colori[i][j].val);
      }else{
        leds[colori[i][j].nled] = CRGB::Black;    
      }
      
    }  
  }
FastLED.show();  // è qui che i led effettivamente vengono aggiornati 
}

void colonna_piena(void){
  
  nlivello=0;
  
  for(int i=0; i<COLONNE; i++){
    
    nlivello=destra[i]/delta;
    
    for(int j=0; j<RIGHE; j++){
      if(j <= nlivello){
        colori[i][j].attivo=1;}
      else{
        colori[i][j].attivo=0;}
    
    }
    //colori[i][picchi[i]].attivo=1;  
  }
}


void colore_totale_hsv(int h, int s, int v){

  for(int i=0; i<7; i++){
    for(int j=0; j<8; j++){
      colori[i][j].hue=h;
      colori[i][j].sat=s;
      colori[i][j].val=v;
    }
  }
  
}

void colore_totale_rgb(int r, int g, int b){

  for(int i=0; i<7; i++){
    for(int j=0; j<8; j++){
      colori[i][j].r=r;
      colori[i][j].g=g;
      colori[i][j].b=b;
    }
  }
  
}

void arcobaleno_a_colonne(void){
  int n=36;
  for(int i=0; i<7; i++){
    for(int j=0; j<8; j++){
      colori[i][j].hue=n;
      colori[i][j].sat=230;
      colori[i][j].val=240;
    }
    n+=36;
  }
}

void arcobaleno_a_punti(void){
  int n=36;
  for(int i=0; i<7; i++){
    for(int j=0; j<8; j++){
      colori[i][j].hue=n;
      colori[i][j].sat=230;
      colori[i][j].val=240;
      n+=5;
    }
  }
}

void arcobaleno_dinamico(void){

  for(int i=0; i<7; i++){
    for(int j=0; j<8; j++){
      colori[i][j].hue=hue_arcobaleno;
      colori[i][j].sat=230;
      colori[i][j].val=240;
    }
  }
  hue_arcobaleno++;
}

Next Post

Previous Post

8 Comments

  1. jose 21 Luglio 2018

    hi denis,,,, please send me the schemetic to conect spectrum shield … thanks

    • Denis Lanfrit 22 Luglio 2018 — Post Author

      Hi Jose, the connections are very simple: the led strip is connected to a 5v power supply and the data pin to Arduino digital pin n°6. The shield is simply inserted on Arduino Uno and pin n° 4 and 5 are used to select data from the shield, analog pin 0 and 1 are used to read data.
      This is an helpful link

  2. Amir 19 Ottobre 2018

    Hi Denis,
    thanx for sharing your idea and your code. I have a question. Do I have to copy both codes in a single Arduino file or are they two separate files? I can’t figure out how to use them.

    cheers

    • Denis Lanfrit 19 Ottobre 2018 — Post Author

      Hi Amir, It is indifferent, you can do it in both ways, for example you can copy the code in the same order as above into a single file and compile

  3. wensen 26 Novembre 2018

    hi…friend…
    how to make this Spectrum Analyzer with peak…?

  4. Mark 19 Maggio 2019

    Hi Denis
    Thanks for sharing this, I look forward to trying it out. Is this the most recent version?

  5. Aranng 30 Marzo 2020

    Appreciate all your work..thanks
    Maybe,more row colum looks better..

Leave a Reply

© 2022 Denis Lanfrit

Theme by Anders Norén