Multiplexare dei LED... sfarfallio!!

Ciao ragazzi, ho 4 pezzi di striscia led che volevo pilotare mediante l'arduino...
I 4 spezzoni hanno i pin R,G,B in comune, quindi le multiplexo alimentanto singolarmente ogni striscia

Il problema è che ho un odioso sfarfallio quando le comando in PWM!!
Se utilizzo questo codice NON ho problemi:

void loop() {

digitalWrite(A2, LOW);// Tolgo il positivo alla striscia 1
** digitalWrite(9, 0);// Spengo il Verde**
** digitalWrite(10, 1);// Accendo il Rosso**
digitalWrite(A0, HIGH);// Collego il positivo della striscia 0

delay(4);

digitalWrite(A0, LOW);// Tolgo il positivo alla striscia 0
** digitalWrite(10, 0);// Spengo il rosso**
** digitalWrite(9, 1); //Accendo il verde**
digitalWrite(A2, HIGH);// Collego il positivo della striscia 1
delay(4);
}

Se al posto del "digitalWrite(pin, 1)" metto "analogWrite(pin, 255)" ottengo ugualmente il flicker!!

void loop() {

digitalWrite(A2, LOW);// Tolgo il positivo alla striscia 1
** analogWrite(9, 0);// Spengo il Verde**
** analogWrite(10, 255);// Accendo il Rosso**
digitalWrite(A0, HIGH);// Collego il positivo della striscia 0

delay(4);

digitalWrite(A0, LOW);// Tolgo il positivo alla striscia 0
** analogWrite(10, 0);// Spengo il rosso**
** analogWrite(9, 255); //Accendo il verde**
digitalWrite(A2, HIGH);// Collego il positivo della striscia 1
delay(4);
}

Com'è possibile!?

Le strip led sono collegate così: ImageShack - Best place for all of your image hosting and image sharing needs

Probabilmente perché la funzione analogWrite esegue altre cose prima di scrivere materialmente lo stato sul pin, come controllare se su quel pin c'è un PWM e se sì, lo stacca.

Questo introduce un allungamento dei tempi di risposta della funzione, che diminuiscono la frequenza di lampeggio arrivando a valori precepibili dall'occhio umano.
Quando usi analogWrite prova diminuendo l'intervallo specificato dal delay.

Sto provando a velocizzare tutto usando le PORT... ma sto modificando dei tutorial su internet con scarsi risultati!! Addirittura molti degli esempi proposti se caricati non funzionano >.<

Ad esempio con questo codice:
PORTB &= ~( ( 1 << 1 ) | ( 1 << 2 ) );
Non dovrebbe portare il pin 1 e 2 della PORTB (quindi pin 9-10) ad high?

Grazie mille Leo per la risposta!

]:smiley: manca il delay tra l'accensione e lo spegnimento

Guglio:
Ad esempio con questo codice:
PORTB &= ~( ( 1 << 1 ) | ( 1 << 2 ) );
Non dovrebbe portare il pin 1 e 2 della PORTB (quindi pin 9-10) ad high?

No, fa l'opposto. Li porta a LOW.
Il segno di complemento "~" inverte lo stato dei pin, poi viene fatto un AND bit a bit con il valore della porta col risultato che spenge solo i pin 1 e 2.

Leggi questo:
http://www.leonardomiliani.com/2013/manipoliamo-direttamente-le-porte-logiche-di-una-mcu/

gingardu:
]:smiley: manca il delay tra l'accensione e lo spegnimento

Veramente c'è.

Ho provato a mettere un delay(1) fra i due analogWrite.. in effetti funziona... il problema è che le funzione è troppo lenta e come provo a collegare tutte e 4 le strisce flickera un casino... e poi con tutti quei delay si illuminano meno...

Al momento ho risolto così

#define BINARY(a,b,c,d,e,f,g,h)  (a<<7|b<<6|c<<5|d<<4|e<<3|f<<2|g<<1|h)

void setup() {        
 /** Blabla */
}

// Struttura Array:

////           S1       S2    S3    S4
/// Rosso
/// Verde
/// Blu

int r[4] = {
  1, 0, 1, 1};
int g[4] = {
  1, 1, 0, 0};
int b[4] = {
  0, 1, 0, 1};

unsigned long timer = 0;
int strip = 14;// i positivi sono sui pin 14, 15, 16, 17
int wait = 4000;

void loop() {
  if ((micros()-timer) > wait){
    //    PORTC = 0x00;// Spegne tutti gli analog
    PORTC = 1 << (strip-14);//spegne tutti gli analog accendendo solo il pin desiderato
    PORTB = BINARY(0,0,0,0,b[(17-strip)],r[(17-strip)],g[(17-strip)],0);//Accende e spegne i pin dell'rgb
    timer = micros();
    strip++;
    if (strip>17){
      strip = 14;
    }
  }
}

Il codice funziona... solo che come vedete non posso usare l'rgb... si riesce ad implementare il PWM così via software agendo sulle porte?

Il PWM altro non è che un segnale generato da un timer interno. Puoi attivare il PWM su un pin con una determinata frequenza e poi scegliere tu il duty cycle semplicemente modificando il registro OCR del timer interessato. Non devi per forza passare dalla funzioni dell'Arduino.

Ciao Leo! Sto facendo qualche prova con i timer del PWM, a quanto mi consigli di mettere la frequenza? E' meglio alta o bassa per il lavoro che devo fare io?
Ad esempio ho provato a mettere il divisore a 1, ottenendo 31250hz e l'alimentatore fischiava come se non ci fosse un domani!

Grazie mille per l'aiuto

L'Arduino regola il PWM a ~490 Hz per il timer 1 e 2 e ~980 Hz per il timer 0. Usa questi valori, tanto a te non serve una frequenza eccessiva.

Ciao Leo, pilotando le strip led senza multiplexarle sui 490Hz non ho problemi...
Invece se le utilizzo accendendole una per volta per cambiare il colore molto velocemente non funziona! Ho dovuto impostare gli Hz massimi a 31250 altrimenti sfarfallava tutto...

Al momento anche se con un lieve sfarfallio funziona tutto tranne la libreria VirtualWire!!
Come provo a modificare i registri OCR per impostare il PWM questa smette di funzionare!!
idee?

Il codice è questo se può servire!!

Grazie mille per l'aiuto!

#include <VirtualWire.h>
#define BINARY(a,b,c,d,e,f,g,h)  (a<<7|b<<6|c<<5|d<<4|e<<3|f<<2|g<<1|h)

boolean SettingMinTime = false;
int mintimeon = 100;
void setup()
{
  TCCR1A = _BV(COM2A1) | _BV(COM2B1) | _BV(WGM21) | _BV(WGM20);
  TCCR1B = _BV(CS22);

  TCCR2A = _BV(COM2A1) | _BV(COM2B1) | _BV(WGM21) | _BV(WGM20);
  TCCR2B = _BV(CS22);

  TCCR1A = TCCR1A & 0b11111000 | 0x01;//3
  TCCR2A = TCCR1A & 0b11111000 | 0x01;//4
  TCCR1B = TCCR1B & 0b11111000 | 0x01;//3
  
  Serial.begin(115200);	// Debugging only
  Serial.println("setup");
  

  // Controllo Spezzoni  
  pinMode(A3, OUTPUT);
  pinMode(A2, OUTPUT);
  pinMode(A1, OUTPUT);
  pinMode(A0, OUTPUT);
  // RGB
  pinMode(9, OUTPUT);//Verde
  pinMode(10, OUTPUT);//Rosso
  pinMode(11, OUTPUT);//Blu
  pinMode(12, OUTPUT);//Relè
  pinMode(13, OUTPUT);//Debug
  pinMode(A5, INPUT);//Sensore FLash
  digitalWrite(A3, 0);
  digitalWrite(A2, 0);
  digitalWrite(A1, 0);
  digitalWrite(A0, 0);
  
  
  vw_set_ptt_inverted(true); // Required for DR3100
  vw_setup(2000);	 // Bits per sec
  vw_set_rx_pin(7);
  vw_set_tx_pin(8);
  vw_rx_start();       // Start the receiver PLL running
}

int r[4] = {
  1, 1, 1, 1};
int g[4] = {
  1, 1, 1, 1};
int b[4] = {
  1, 1, 1, 1};

unsigned long timer = 0;
unsigned long timer1 = 0;
int strip = 14;// 14, 15, 16, 17
int wait = 5000;


void loop()
{
  
  
  if ((micros()-timer) > wait){
    //PORTC = 0x00;// Spegne tutti gli analog
    PORTB = BINARY(0,0,0,0,b[(17-strip)],r[(17-strip)],g[(17-strip)],0);//Accende e spegne i pin dell'rgb
    //OCR1B = r[(17-strip)];// 10 rosso   Usando queste 3 funzioni non va la virtualwire!
    //OCR1A = g[(17-strip)];// 9 verde
    //OCR2A = b[(17-strip)];// 11 blu
    PORTC = 1 << (strip-14);//spegne tutti gli analog accendendo solo il pin desiderato

    timer = micros();
    strip++;
    if (strip>17){
      strip = 14;
    }
  }
///*** Gestione dati in ingresso con VW ***/
}

leo72:

Guglio:
Ad esempio con questo codice:
PORTB &= ~( ( 1 << 1 ) | ( 1 << 2 ) );
Non dovrebbe portare il pin 1 e 2 della PORTB (quindi pin 9-10) ad high?

No, fa l'opposto. Li porta a LOW.
Il segno di complemento "~" inverte lo stato dei pin, poi viene fatto un AND bit a bit con il valore della porta col risultato che spenge solo i pin 1 e 2.

Leggi questo:
http://www.leonardomiliani.com/2013/manipoliamo-direttamente-le-porte-logiche-di-una-mcu/

OT

leo se provo a vedere la tua guida nod32 segnala cavallo di troia
errore?

lucaleo:
...
leo se provo a vedere la tua guida nod32 segnala cavallo di troia
errore?

Confermo Leo ... anche a me segnala : "http://www.leonardomiliani.com/2013/manipoliamo-direttamente-le-porte-logiche-di-una-mcu - JS/Kryptik.AOC trojan" ... falso positivo o ... server violato ???

Guglielmo

gpb01:
falso positivo o ... server violato ???

Più probabile la seconda.... è un calvario... :cold_sweat:

Uh... ho addirittura trovato una bellissima backdoor russa. Il KGB mi sta spiando :stuck_out_tongue_closed_eyes: :stuck_out_tongue_closed_eyes:

/******************************************************************************************************/
/*
/*                                     #    #        #    #                             
/*                                     #   #          #   #
/*                                    #    #          #    #
/*                                    #   ##   ####   ##   #
/*                                   ##   ##  ######  ##   ##
/*                                   ##   ##  ######  ##   ##
/*                                   ##   ##   ####   ##   ##
/*                                   ###   ############   ###
/*                                   ########################
/*                                        ##############
/*                                 ######## ########## #######
/*                                ###   ##  ##########  ##   ###
/*                                ###   ##  ##########  ##   ###
/*                                 ###   #  ##########  #   ###
/*                                 ###   ##  ########  ##   ###
/*                                  ##    #   ######   #    ##
/*                                   ##   #    ####   #    ##
/*                                     ##                 ##
/*
/*
/*
/*  r57shell.php - ?????? ?? ??? ??????????? ??? ????????? ???? ???????  ?? ??????? ????? ???????
/*  ?? ?????? ??????? ????? ?????? ?? ????? ?????: http://rst.void.ru
/*  ??????: 1.24 (New Year Edition)
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
/*  (c)oded by 1dt.w0lf
/*  RST/GHC http://rst.void.ru , http://ghc.ru
/*  ANY MODIFIED REPUBLISHING IS RESTRICTED
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
/*  ????????? ????????????? ?? ?????? ? ????: blf, virus, NorD ? ???? ?????? ?? RST/GHC. 
/******************************************************************************************************/
/* ~~~ ????????? | Options  ~~~ */

leo72:
Uh... ho addirittura trovato una bellissima backdoor russa. Il KGB mi sta spiando ....

... ti tengono sotto controllo ...

Guglielmo

Ho ripulito quella backdoor.
Non ho altri malware (dopo scansione): a questo punto dovrebbero essere falsi positivi, se ce ne sono ancora.

ora va :wink:

Invece di ripulirla e basta, avresti dovuto sfruttarla per "restituirgli" un pacchetto di virus distruttivi ... ah, come mi sento buono ... :stuck_out_tongue: XD XD XD

Sì, poi mi mandavano un paio di missili intercontinentali sul server.... e visto che il mio host è americano... scatenavo la III G.M. no, grazie :sweat_smile: