Go Down

Topic: [4 x 4 LED RGB MATRIX] Sincronizzare frequenza PWM con loop (Read 1 time) 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?


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

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
 


Please enter a valid email to subscribe

Confirm your email address

We need to confirm your email address.
To complete the subscription, please click the link in the email we just sent you.

Thank you for subscribing!

Arduino
via Egeo 16
Torino, 10131
Italy