[4 x 4 LED RGB MATRIX] Sincronizzare frequenza PWM con loop

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) :slight_smile:

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 :

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 :smiley:

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 :wink:

Qualche idea?

NEssuno che mi riesca a dare un aiutino? :stuck_out_tongue:

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

@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:

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

uwefed:
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?

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

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

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ì:

#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?

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

Per la cronaca la libreria è riferita a questo topic --> http://arduino.cc/forum/index.php/topic,117425.0.html

Eh... s'invecchia... non mi ricordo più una cippa :stuck_out_tongue_closed_eyes:
Mi sa che la mia Flash ha raggiunto il max numero di riscritture :wink: