Pages: [1]   Go Down
Author Topic: [4 x 4 LED RGB MATRIX] Sincronizzare frequenza PWM con loop  (Read 569 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 45
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

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 smiley-grin
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 45
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Qualche idea?
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 45
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

NEssuno che mi riesca a dare un aiutino? smiley-razz
Logged

BZ (I)
Online Online
Brattain Member
*****
Karma: 234
Posts: 20193
+39 349 2158303
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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
Logged

Global Moderator
Italy
Online Online
Brattain Member
*****
Karma: 313
Posts: 21619
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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


Offline Offline
Newbie
*
Karma: 0
Posts: 45
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


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

Offline Offline
Newbie
*
Karma: 0
Posts: 45
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Global Moderator
Italy
Online Online
Brattain Member
*****
Karma: 313
Posts: 21619
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged


Cagliari, Italy
Offline Offline
Tesla Member
***
Karma: 103
Posts: 6572
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Code fast. Code easy. Codebender --> http://codebender.cc/?referrer=PaoloP

Global Moderator
Italy
Online Online
Brattain Member
*****
Karma: 313
Posts: 21619
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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


Pages: [1]   Go Up
Jump to: