Go Down

Topic: [4 x 4 LED RGB MATRIX] Sincronizzare frequenza PWM con loop (Read 930 times) previous topic - next topic

Elius94

Ciao ragazzi, sto realizzando un  firmware per pilotare via pwm, usando il metodo delle matrici, ad alta frequenza, 16 led rgb!

All'arduino sono collegati i 12 cavi che controllano il le singole file di anodi dei led, 4 file rosse, 4 file blu, e 4 verdi! per determinare quale dei 4 led venga acceso, le masse comuni a tutte le file (4 masse) vengono controllate tramite 4 transistor!

In sostanza, l'arduino accende i led, con il loro valore pwm, in ordine, da destra a sinistra, e una volta terminato fa la fila sotto.
In questo modo, ad altissime velocità (quella del ciclo dell'arduino stesso), i led risultano tutti accesi, con il relativo colore!
Finche non uso il pwm, ma uso solamente i 3 colori (r,G,B), quindi usando la funzione digitalWrite, funziona a meraviglia, e i led sembra che siano controllati singolarmente! senza sfarfallamenti ecc.

Quando invece utilizzo la funzione analorWrite, con le 12 uscite PWM dell'arduino mega, si crerano fastidiosi sfarfallamenti, e anche se i colori si vedono bene, "fa schifo" (sono pignolo) :)

Conosco la modulazione di larghezza dell'impulso (PWM), l'ho studiata bene, e quindi posso dedurre che si creano degli asincronismi fra il periodo di oscillazione del PWM, e quello di esecuzione del loop!

Come mi consigliereste di risolvere questo problema?

P.s, nel codice, uso un delayMicroseconds, per aspettare pochissimi microsecondi, prima che si spengano i led precedenti, in modo da dare tempo al led di accendersi del tutto, e questo ad alta velocità non crea problemi!

Ecco il codice :

Quote

int ledGND[] = {17,16,15,14};
int red[] = {2,3,4,5};
int green[] = {6,7,8,9};
int blue[] = {10,11,12,13};
int n = 0;
int n2 = 0;

byte REDvalue[4][4] = {
  {127,127,127,127},
  {127,127,127,127},
  {84,84,84,84},
  {0,0,0,0}
};

byte GREENvalue[4][4] = {
  {127,127,127,127},
  {0,0,0,0},
  {84,84,84,84},
  {127,127,127,127}
};
byte BLUEvalue[4][4] = {
  {0,0,0,0},
  {127,127,127,127},
  {84,84,84,84},
  {127,127,127,127}
};

void setup() {
  // initialize the digital pin as an output.
  for (int thisPin = 0; thisPin < 4; thisPin++)  {
    pinMode(ledGND[thisPin], OUTPUT); 
  }
  for (int thisPin = 0; thisPin < 4; thisPin++)  {
    pinMode(red[thisPin], OUTPUT);
  } 
    for (int thisPin = 0; thisPin < 4; thisPin++)  {
    pinMode(green[thisPin], OUTPUT);
  } 
    for (int thisPin = 0; thisPin < 4; thisPin++)  {
    pinMode(blue[thisPin], OUTPUT);
  } 
  Serial.begin(9600);
}


void loop() {
  for(n2=0; n2<4; n2++){
  digitalWrite(ledGND[n2], HIGH);
    for(n=0; n<4; n++) {
    analogWrite(red[n],REDvalue[n2][n]);
    analogWrite(green[n], GREENvalue[n2][n]);
    analogWrite(blue[n], BLUEvalue[n2][n]);
    //delayMicroseconds(200);
    //digitalWrite(green[n], LOW);
    }
  delayMicroseconds(995);
  digitalWrite(ledGND[n2], LOW);
  
  digitalWrite(red[0], LOW);
  digitalWrite(red[1], LOW);
  digitalWrite(red[2], LOW);
  digitalWrite(red[3], LOW);
  
  digitalWrite(green[0], LOW);
  digitalWrite(green[1], LOW);
  digitalWrite(green[2], LOW);
  digitalWrite(green[3], LOW);
  
  digitalWrite(blue[0], LOW);
  digitalWrite(blue[1], LOW);
  digitalWrite(blue[2], LOW);
  digitalWrite(blue[3], LOW);
  }
}



Grazie mille :D

Elius94

vedo che molta gente utilizza dell'hardware aggiuntivo, degli shift register, o dei pot digitali... però considerando che il mio arduino mega, ha più di 12 uscite PWM ed a me ne servono 12, dovrebbe bastare! anche perchè se accendo i led singolarmente, il pwm va benissimo, il problema è appunto nel farli "frullare " in un loop ;)

Qualche idea?

Elius94


uwefed

Lo sfarfalio deriva dalla frequenza di PWM che é 490Hz. Se fai il multiplexing in modo non sincronizzato con i PWM otterai dei tempi di accensione dei vari LED non dipendenti dal PWM.

Le 2 soluzioni sono:
* sincronizzare il multiplexing con il PWM
* aumentare la frequenza di PWM

Ciao Uwe

leo72

@Elius:
Immagino che per "frullare" tu intenda di farli accendere in sequenza.
Con il PWM puoi regolare la luminosità dei led poi devi farti una routine che alternativamente accende i led interessati.
Vedo tante soluzioni, se vuoi usare uno o più shift register potresti usare il PWM per pilotare gli anodi dei led e poi dare massa ai catodi con degli shift register.
Inizia a studiarti questa pagina:
http://arduino.cc/en/Tutorial/ShiftOut

Ovviamente per fare come ti ho detto devi mettere un transistor sull'alimentazione e pilotarlo col segnale PWM.
Così l'alimentazione è stabile ed i led si accendono solo quando vengono messi a massa.
Se vuoi usare elevate correnti per i led, ti consiglio di interporre degli Uln2803 fra gli shift register ed i catodi perché un 74HC595 mi pare lavori max a 100 mA e con 8 led a 20 mA l'uno lo friggi

Elius94



Le 2 soluzioni sono:
* sincronizzare il multiplexing con il PWM
* aumentare la frequenza di PWM



Ciao Uwe, la tua soluzione mi sembra la più rapida, come per sincronizzare il multiplexing con il pwm dovrei andare a tentativi, con il delay microseconds, oppure posso calcolarlo in qualche modo?

e invece è possibile aumentare la fequenza pwm?


@Elius:
Immagino che per "frullare" tu intenda di farli accendere in sequenza.
Con il PWM puoi regolare la luminosità dei led poi devi farti una routine che alternativamente accende i led interessati.
Vedo tante soluzioni, se vuoi usare uno o più shift register potresti usare il PWM per pilotare gli anodi dei led e poi dare massa ai catodi con degli shift register.
Inizia a studiarti questa pagina:
http://arduino.cc/en/Tutorial/ShiftOut

Ovviamente per fare come ti ho detto devi mettere un transistor sull'alimentazione e pilotarlo col segnale PWM.
Così l'alimentazione è stabile ed i led si accendono solo quando vengono messi a massa.
Se vuoi usare elevate correnti per i led, ti consiglio di interporre degli Uln2803 fra gli shift register ed i catodi perché un 74HC595 mi pare lavori max a 100 mA e con 8 led a 20 mA l'uno lo friggi


Grazie Leo, se non trovo altre soluz1ioni semplici, come quella di aumentare la frequenza pwm, seguirò le tue indicazioni :)

Elius94

Leo!!!!

Ho trovato una discussione in cui tu hai risposto ad un tipo che aveva il mio stesso problema, e gli hai consigliato la libreria PWM!

Ho provato ed ho fatto così:

Quote

#include <PWM.h>

int ledGND[] = {17,16,15,14};
int red[] = {2,3,4,5};
int green[] = {6,7,8,9};
int blue[] = {10,11,12,13};
int n = 0;
int n2 = 0;
int32_t frequency = 10000;

byte REDvalue[4][4] = {
  {127,127,127,0},
  {127,127,127,127},
  {84,84,84,84},
  {0,0,0,0}
};

byte GREENvalue[4][4] = {
  {127,127,127,255},
  {0,0,0,0},
  {84,84,84,84},
  {127,127,127,127}
};

byte BLUEvalue[4][4] = {
  {0,0,0,0}  ,
  {127,127,127,127},
  {84,84,84,84},
  {127,127,127,127}
};

void setup() {
  InitTimersSafe();
  // initialize the digital pin as an output.
  for (int thisPin = 0; thisPin < 4; thisPin++)  {
    pinMode(ledGND[thisPin], OUTPUT);
  }
  for (int thisPin = 0; thisPin < 4; thisPin++)  {
    pinMode(red[thisPin], OUTPUT);
    SetPinFrequencySafe(red[thisPin], frequency);
  } 
  for (int thisPin = 0; thisPin < 4; thisPin++)  {
    pinMode(green[thisPin], OUTPUT);
    SetPinFrequencySafe(green[thisPin], frequency);
  } 
  for (int thisPin = 0; thisPin < 4; thisPin++)  {
    pinMode(blue[thisPin], OUTPUT);
    SetPinFrequencySafe(blue[thisPin], frequency);
  } 
  Serial.begin(9600);
}


void loop() {
  for(n2=0; n2<4; n2++){
    digitalWrite(ledGND[n2], HIGH);
    for(n=0; n<4; n++) {
      pwmWrite(red[n],REDvalue[n2][n]);
      pwmWrite(green[n], GREENvalue[n2][n]);
      pwmWrite(blue[n], BLUEvalue[n2][n]);
      //delayMicroseconds(200);
      //digitalWrite(green[n], LOW);
    }
    delayMicroseconds(1000);
    digitalWrite(ledGND[n2], LOW);

    digitalWrite(red[0], LOW);
    digitalWrite(red[1], LOW);
    digitalWrite(red[2], LOW);
    digitalWrite(red[3], LOW);

    digitalWrite(green[0], LOW);
    digitalWrite(green[1], LOW);
    digitalWrite(green[2], LOW);
    digitalWrite(green[3], LOW);

    digitalWrite(blue[0], LOW);
    digitalWrite(blue[1], LOW);
    digitalWrite(blue[2], LOW);
    digitalWrite(blue[3], LOW);
  }
}




Ora non crea più problemi, però i colori li mette A CASO! e non seguendo gli array che gli ho impostato, li in alto:P ho sbagliato qualcosa?

Centra il fatto che il metodo FastPWM genera un onda a dente di sega?

leo72

Non mi ricordavo neanche che esisteva questa libreria PWM.h.  :smiley-sweat:
Comunque se i colori li regola giusti ma sono a caso forse o hai invertito dei collegamenti o hai dichiarato male i pin.

PaoloP

Per la cronaca la libreria è riferita a questo topic --> http://arduino.cc/forum/index.php/topic,117425.0.html
Code fast. Code easy. Codebender --> http://codebender.cc/?referrer=PaoloP

leo72

Eh... s'invecchia... non mi ricordo più una cippa  :smiley-yell:
Mi sa che la mia Flash ha raggiunto il max numero di riscritture  ;)

Go Up