gestione OUTPUT PWM

lollo1100:

PaoloP:
non mi riferivo ad una funzione specifica ma ad una variabile generica. L'avrei potuta chiamare anche pippo = Tfinale - Tiniziale.

si ok ...l'avevo capito un attimo dopo che avevo risposto :* ho fatto un mezzo sketch solo che non funziona in maniera appropriatissima :frowning:

Pubblicalo, per capire dov'è l'errore.

ok il problema credo sia un discorso di anti rimbalzo ora lo pubblico x vedere cosa può essere
lo sketch mi restituisce il tempo tra due pressioni di pulsante

/* TIMER
 * UTILIZZO DI millis()
 * TIMER : VISUALIZZA INTERVALLO DI TEMPO TRA 2 PUSH CONSECUTIVI DI BUTTON 1° START TIMER 2° STOP TIMER
 * CONFIGURAZIONE ELETTRONICA: INTERRUTTORE COLLEGATO AL PIN 4 
 */

#define BUTTON 4                    //  BOTTONE SU PIN 4

int statoBottone;                   //  VARIABILE PER MEMORIZZARE LO STATO DEL BOTTONE
int ultimoStatoBottone = HIGH;      //  VARIABILE PER MEMORIZZARE L'ULTIMO STATO DEL BOTTONE LO IMPOSTO ALTO DI DEFAULT
boolean timer = false;              //  CONDIZIONE PER INIZIO/FINE TIMER
unsigned long tempoInizio;          //  ISTANTE DI START
unsigned long tempoTrascorso;       //  TEMPO TRASCORSO
int frazioneSecondi;                //  VARIABILE UTILIZZATA PER LE FRAZIONI DI TEMPO

void setup()
{
  Serial.begin(9600);

  pinMode(BUTTON, INPUT);           //  IMPOSTA BUTTON COME INPUT
  digitalWrite(BUTTON, HIGH);       //  IMPOSTA ALTA LA RESISTENZA DI PULLUP

}

void loop()
{
  //  VERIFICA LA PRESSIONE DEL BOTTONE

  statoBottone = digitalRead(BUTTON);                     //  LEGGI LO STATO DEL BOTTONE E MEMORIZZALO

  if (statoBottone == LOW && ultimoStatoBottone == HIGH  &&  timer == false){     

    //  VERIFICA LA PRESENZA DI TRANSIZIONE DA ALTO A  BASSO SUL BOTTONE
    //  SE è VERO MENTRE NON SI è VERIFICATA UNA NUOVA PRESSIONE DI BOTTONE E IL TIMER NON è IN ESECUZIONE AVVIA IL TIMER

    tempoInizio = millis();                                 //  MEMORIZZA IL TEMPO DI INIZIO
    timer = true;                                           //  ATTIVA IL TIMER
    delay(5);                                               //  BREVE RITARDO PER ANTIRIMBALZO SUL BOTTONE
    ultimoStatoBottone = statoBottone;                      //  MEMORIZZA LO SATO DEL BOTTONE NELL'ULTIMO STATO DEL BOTTONE PER SUCCESSIVO CONFRONTO
    
  }
  else if (statoBottone == LOW && ultimoStatoBottone == HIGH && timer == true){   

    //  VERIFICA LA PRESENZA DI TRANSIZIONE DA ALTO A  BASSO
    //  SE è STATO DI NUOVO PREMUTO IL BOTTONE FERMARE IL TIMER E PREPARARE LA STAMPA DEL TEMPO TRASCORSO

    tempoTrascorso =   millis() - tempoInizio;              //  MEMORIZZA IL TEMPO TRASCORSO
    timer = false;                                          //  SPEGNI IL TIMER PER PASSARE A SCRIVERE IL TEMPO TRASCORSO
    ultimoStatoBottone = statoBottone;                      //  MEMORIZZA LO SATO DEL BOTTONE NELL'ULTIMO STATO DEL BOTTONE PER SUCCESSIVO CONFRONTO

    //  DI SEGUITO ROUTINE PER SEGNALARE IL TEMPO TRASCORSO 

    Serial.print("IL TEMPO TRASCORSO TRA I 2 PUSH DI BUTTON E' : ");
    Serial.print( (int)(tempoTrascorso / 1000L));           //  DIVIDI PER MILLE PER CONVERTIRE IN SECONDI E PREPARA LA STAMPA SULLA COM  
    Serial.print(".");                                      //  STAMPA IL PUNTO DECIMALE

    //  UTILIZZARE L'OPERATORE MODULO PER OTTENERE LA PARTE FRAZIONARIA DEL TEMPO TRASCORSO
    frazioneSecondi = (int)(tempoTrascorso % 1000L);

    //  STAMPARE GLI ZERO INIZIALI NON SAREBBE CARINO 

    if (frazioneSecondi == 0)
      Serial.print("000");                                  //  AGGIUNGI TRE ZERO
        else if (frazioneSecondi < 10)                      //  SE LA PARTE FRAZIONARIA è MINORE DI 10 LO 0 VIENE IGNORATO DANDO UN TEMPO ERRATO IN MODO DI AGGIUNGERE GLI ALTRI ZER0
          Serial.print("00");                               //  AGGIUNGI DUE ZERO
            else if (frazioneSecondi < 100)
              Serial.print("0");                            //  AGGIUNGI UNO ZERO
              Serial.print(frazioneSecondi);                //  STAMPA LA PARTE FRAZIONARIA DEL TEMPO
              Serial.println(" SECONDI");                   //  STAMPA SECONDI
  }
  else{
    ultimoStatoBottone = statoBottone;                      //  MEMORIZZA LO SATO DEL BOTTONE NELL'ULTIMO STATO DEL BOTTONE PER SUCCESSIVO CONFRONTO
  }
}

forse ci sono arrivato da solo :slight_smile: devo fare alcuni test ritiro quello che ho scritto :slight_smile: non va anzi va peggio

Ho trovato questo --> http://www.instructables.com/id/Arduino-Button-Tutorial/?ALLSTEPS

Nel diagramma non c'è resistenza perché usa la pull-up interna è la pressione manda in LOW il pin.

Trovata anche una libreria interessante --> Google Code Archive - Long-term storage for Google Code Project Hosting.

per inviare ogni 200 ms una cosa non ha senso fare delay ??? è un'eresia ? :grin: Grazie dovrei far si che dentro un if ogni 200 ms venga collegata l'ethernet e inviato un byte

lollo1100:
per inviare ogni 200 ms una cosa non ha senso fare delay ??? è un'eresia ? :grin: Grazie dovrei far si che dentro un if ogni 200 ms venga collegata l'ethernet e inviato un byte

Il delay non è il "male". A volte è utile, se si usa consci del fatto che ferma l'esecuzione del codice. Ma se serve proprio attendere un certo lasso di tempo, perché non usare un delay?

In pratica io vorrei fare una cosa dentro a un if x un certo tempo (in cui non devo lasciare il pulsante) quindi utilizzo un while e farlo x ogni 200 ms

scusate ho questo codice ancora forse non ho capito bene la differenza tra int e byte

vorrei fare un codice che mentre arriva 80 mi incrementa di 80 fino a che non arriva a 255

int valore1 = 0;
int valore = 0;
int valore2 = 0;
int i = 0;

void convertiHEX(){

  int val1 = 0;
  int val2 = 0;
  int valore = 0;

//NEL LOOP c'è questo

  if ( CMD[2] >= 'A' && CMD[2] <= 'F' )    
    val1 = CMD[2] - 55;
  else 
    if ( CMD[2] >= '0' && CMD[2] <= '9' )
    val1 = CMD[2] - 48;

  if ( CMD[3] >= 'A' && CMD[3] <= 'F' )    
    val2 = CMD[3] - 55;
  else 
    if ( CMD[3] >= '0' && CMD[3] <= '9' )
    val2 = CMD[3] - 48;

  valore = (val1*16) + val2;
  
  for ( int i = 7; i > -1; i-- ){
    MSK[i] = bitRead(valore,i);
  }
  int val3 = 0;
  int val4 = 0;
  
  
  if ( CMD[4] >= 'A' && CMD[4] <= 'F' )    
    val3 = CMD[4] - 55;
  else 
    if ( CMD[4] >= '0' && CMD[4] <= '9' )
    val3 = CMD[4] - 48;

  if ( CMD[5] >= 'A' && CMD[5] <= 'F' )    
    val4 = CMD[5] - 55;
  else 
    if ( CMD[5] >= '0' && CMD[5] <= '9' )
    val4 = CMD[5] - 48;
  valore1 = (val3*16) + val4;
  if (valore1 == 80 && valore2 <= 255){
    
    valore2 += (80*i);
    i++;
  Serial.println(valore);
  }
  else
    if(valore1 == 0 || valore1 == 255){
      valore2 = valore1;
      Serial.println(valore2);
    }
}

a parte che se gli arriva 50 come CMD[4] = '5' e CMD[5] = '0' valore1 = 80 a parte questo se faccio così sulla seriale mi stampa 89 169 249 io invece vorrei 80 160 240 a dire la verità vorrei 50 100 150 200 xò x fare questo dovrei cambiare quelle due formule x la conversione da chars a intero decimale. Il problema che non riesco a capire xk ci mette 9 in +
Il +9 è stato risolto era un errore mio su la variabile i ok adesso gli ho cambiato nome e non fa + il + 9 i problemi ora sono 2 il primo come modificare la formula quella del -55 e -48 quando magari mando 50 e mi da 80 e poi perchè sull'if con valore2 <= 255 va oltre ugualmente come posso vincolare l'incremento di valore2 fino a 255?

il discorso dell'80 ok xk in pratica 80 è la conversione decimale del numero HEX 50 ok capito

lollo1100:
scusate ho questo codice ancora forse non ho capito bene la differenza tra int e byte

Un int è un dato che occupa 2 byte in memoria e può contenere un numero che va da -32768 a +32767.
Un unsigned int è un dato che occupa sempre 2 byte in memoria ma che non gestisce il segno, per cui i suoi valori (solo positivi) possono andare da 0 a 65535.
Un byte è un unsigned char, un tipo di dati che occupa 1 solo byte in memoria (da qui il nome) ed i cui valori vanno da 0 a 255.

vorrei fare un codice che mentre arriva 80 mi incrementa di 80 fino a che non arriva a 255

Ricordati che con un tipo "byte", quando passi il valore di 255 la variabile riparte da 0. Quindi se hai 240 e sommi ancora 80, dopo hai 64: 240+80-(2^8)

Ciao a tutti dovrei far si che il mio client a cui sono collegati i bottoni abbia uno sketch che consenta di inviare dei comandi dopo che il bottone è premuto x + di 1 secondo a gap di 500 ms ogni volta deve inviare un comando x accendere gradualmente un led posto su un pin pwm
Il mio codice è il seguente non so se si può fare meglio ? :slight_smile:

#include <SPI.h>                                              //  IMPORTA LIBRERIA SPI
#include <Ethernet.h>                                         //  IMPORTA LIBRERIA ETHERNET

#define BUTTONAON 4                   //  BOTTONE ON SU PIN 5
#define BUTTONAOFF 5                  //  BOTTONE OFF SU PIN 4

int ts1st = HIGH;                     //  VARIABILE PER MEMORIZZARE LO STATO DEL BOTTONE
int stato1 = HIGH;                    //  VARIABILE PER MEMORIZZARE L'ULTIMO STATO DEL BOTTONE LO IMPOSTO ALTO DI DEFAULT
int ts2st = HIGH;                     //  VARIABILE PER MEMORIZZARE LO STATO DEL BOTTONE
int stato2 = HIGH;                    //  VARIABILE PER MEMORIZZARE L'ULTIMO STATO DEL BOTTONE LO IMPOSTO ALTO DI DEFAULT
boolean timer1 = false;               //  CONDIZIONE PER INIZIO/FINE TIMER IMPOSTATO FALSE DI DEFAULT
boolean timer2 = false;               //  CONDIZIONE PER INIZIO/FINE TIMER IMPOSTATO FALSE DI DEFAULT
unsigned long tempoInizio1;           //  ISTANTE DI START
unsigned long tempoTrascorso1;        //  TEMPO TRASCORSO
int frazioneSecondi1;                 //  VARIABILE UTILIZZATA PER LE FRAZIONI DI TEMPO
unsigned long tempoInizio2;           //  ISTANTE DI START
unsigned long tempoTrascorso2;        //  TEMPO TRASCORSO
int frazioneSecondi2;                 //  VARIABILE UTILIZZATA PER LE FRAZIONI DI TEMPO
int flagPWMA = 1;
int byteA = 0;
int i = 0;
int maskA1 = 5;
int maskA2 = 9;


EthernetClient client = 0;
EthernetServer server = EthernetServer(23);       //  TELNET PORTA 23

void setup() {
  Serial.begin(9600);
  Ethernet.begin( mac, ip, gateway, gateway, subnet );         //  INIZIALIZZA ETHERNET
  pinMode(BUTTONAON, INPUT);                                   //  IMPOSTA BUTTON COME INPUT
  pinMode(BUTTONAOFF, INPUT);                                  //  IMPOSTA BUTTON COME INPUT
  digitalWrite(BUTTONAON, HIGH);                               //  IMPOSTA ALTA LA RESISTENZA DI PULLUP
  digitalWrite(BUTTONAOFF, HIGH);                              //  IMPOSTA ALTA LA RESISTENZA DI PULLUP
  client.stop();
}

void loop() {
  //  VERIFICA LA PRESSIONE DEL BOTTONE
  client = server.available();
  ts1st = digitalRead(BUTTONAON);                              //  LEGGI LO STATO DEL BOTTONE E MEMORIZZALO
  ts2st = digitalRead(BUTTONAOFF);                             //  LEGGI LO STATO DEL BOTTONE E MEMORIZZALO
  
  if (ts1st == LOW && stato1 == HIGH  &&  timer1 == false){     
    
    tempoInizio1 = millis();                                   //  MEMORIZZA IL TEMPO DI INIZIO
    timer1 = true;                                             //  ATTIVA IL TIMER
    delay(5);                                                  //  BREVE RITARDO PER ANTIRIMBALZO SUL BOTTONE
    stato1 = ts1st;                                            //  MEMORIZZA LO SATO DEL BOTTONE NELL'ULTIMO STATO DEL BOTTONE PER SUCCESSIVO CONFRONTO
  }
  else 
    if (ts1st == HIGH && stato1 == HIGH && timer1 == true && millis() - tempoInizio1 < 1000 && flagPWMA){   
      
    tempoTrascorso1 =   millis() - tempoInizio1;               //  MEMORIZZA IL TEMPO TRASCORSO
    timer1 = false;                                            //  SPEGNI IL TIMER PER PASSARE A SCRIVERE IL TEMPO TRASCORSO
    stato1 = ts1st;                                            //  MEMORIZZA LO SATO DEL BOTTONE NELL'ULTIMO STATO DEL BOTTONE PER SUCCESSIVO CONFRONTO
    byteA = 255;
    
    if (client.connect(serverA, 23)){        
        client.print('@');
        client.print('1');
        client.print(maskA1,HEX);
        client.print(maskA2,HEX);
        client.println(byteA,HEX);
        client.stop();
    }
}
else
if(ts1st == LOW  && timer1 == true && millis() - tempoInizio1 > 1000 && flagPWMA){
   timer1 = false;
  while (ts1st == LOW) {
    ts1st = digitalRead(BUTTONAON);                                  
    delay(400);
    if (client.connect(serverA, 23)){
        byteA = 33;      
        i+=400;
        client.print('@');
        client.print('1');
        client.print(maskA1,HEX);
        client.print(maskA2,HEX);
        client.println(byteA);
        client.stop();
        Serial.print(maskA1,HEX);
        Serial.print(maskA2,HEX);
        Serial.println(byteA);
    }
    }                 
  }
else{
      stato1 = ts1st;                                               //  MEMORIZZA LO SATO DEL BOTTONE NELL'ULTIMO STATO DEL BOTTONE                                                                  //  PER UN CONFRONTO SUCCESSIVO
    }
  
      if (ts2st == LOW && stato2 == HIGH  &&  timer2 == false){     
      
      tempoInizio2 = millis();                                 //  MEMORIZZA IL TEMPO DI INIZIO
      timer2 = true;                                           //  ATTIVA IL TIMER
      delay(5);                                               //  BREVE RITARDO PER ANTIRIMBALZO SUL BOTTONE
      stato2 = ts2st;                                         //  MEMORIZZA LO SATO DEL BOTTONE NELL'ULTIMO STATO DEL BOTTONE PER SUCCESSIVO CONFRONTO
    }
    else 
      if (ts2st == HIGH && stato2 == HIGH && timer2 == true && millis() - tempoInizio2 < 1000 && flagPWMA){   
        
      tempoTrascorso2 =   millis() - tempoInizio2;              //  MEMORIZZA IL TEMPO TRASCORSO
      timer2 = false;                                          //  SPEGNI IL TIMER PER PASSARE A SCRIVERE IL TEMPO TRASCORSO
      stato2 = ts2st;                                         //  MEMORIZZA LO SATO DEL BOTTONE NELL'ULTIMO STATO DEL BOTTONE PER SUCCESSIVO CONFRONTO
      byteA = 0;
      
    if (client.connect(serverA, 23)){        
        client.print('@');
        client.print('1');
        client.print(maskA1,HEX);
        client.print(maskA2,HEX);
        client.println(byteA);
        client.stop();
    }
  }
    else{
      stato2 = ts2st;                                               //  MEMORIZZA LO SATO DEL BOTTONE NELL'ULTIMO STATO DEL BOTTONE                                                                  //  PER UN CONFRONTO SUCCESSIVO
      i = 0;  
  }
if(ts2st == LOW  && timer2 == true && millis() - tempoInizio2 > 1000 && flagPWMA){
   timer2 = false;
  while (ts2st == LOW) {
    ts2st = digitalRead(BUTTONAOFF);                                  
    delay(400);
    if (client.connect(serverA, 23)){
        byteA = 34;      
        i+=400;
        client.print('@');
        client.print('1');
        client.print(maskA1,HEX);
        client.print(maskA2,HEX);
        client.println(byteA);
        client.stop();
        Serial.print(maskA1,HEX);
        Serial.print(maskA2,HEX);
        Serial.println(byteA);
    }
    }                 
  }
else{
      stato2 = ts2st;                                               //  MEMORIZZA LO SATO DEL BOTTONE NELL'ULTIMO STATO DEL BOTTONE                                                                  //  PER UN CONFRONTO SUCCESSIVO
    }
    
  
}

scusate una cosa ma AnalogWrite accende anche i pin non pwm basta che duty cycle sia >= 128 giusto??? in pratica x vedere tutto il led acceso basta mattere 128 dovrei distinguere l'accensione dei pin pwm da quelli normali digitali ??? come posso fare ...penso basti toccare il duty cycle ??? Giusto ? Grazie

mi sono risposto da solo si accendono anche l'altre perchè ricevono il comando 255 che è di accensione FF in HEX ok come non detto

Il problema persiste ho questa situazione invio una maschera di comando di un bottone in cui accendo magari N LED X di questi sono PWM e Y sono digitali normali il problema è il seguente
cerco di accenderli in modalità PWM con analogwrite solo che quando supero 128 mi si continuano accendere quelli dimmer ma mi si accendono completamente anche quelli digitali come si può ovviare a ciò? ovviamente stanno accesi a palla quando duty cycle = 255 in DEC o FF in HEX però non vorrei che mi si accendono anche quelli digitali quando tento di accendere quelli dimmer nè prima che mando 128 come duty nè dopo dato che il problema si presenta quando arriva un duty >= 128

In pratica AnalogWrite (pin,value) = ON se 128 < value < 255 io invece vorrei che non mi accendesse i pin digitali x valori compresi tra 128 e 255 come dovrei fare? grazie vorrei che accendesse solo i pin pwm x quei valori di ON tra 128 e 255 come posso fare?

lollo1100:
vorrei che non mi accendesse i pin digitali

Basta che metti un if e gli dici di saltare i pin digitali.
Crei un array dei pin PWM e se non è tra quelli lo salta.

Il codice dell'AnalogWrite è questo:

void analogWrite(uint8_t pin, int val)
{
	// We need to make sure the PWM output is enabled for those pins
	// that support it, as we turn it off when digitally reading or
	// writing with them.  Also, make sure the pin is in output mode
	// for consistenty with Wiring, which doesn't require a pinMode
	// call for the analog output pins.
	pinMode(pin, OUTPUT);
	if (val == 0)
	{
		digitalWrite(pin, LOW);
	}
	else if (val == 255)
	{
		digitalWrite(pin, HIGH);
	}
	else
	{
		switch(digitalPinToTimer(pin))
		{
			...........................
                        // OMISSIS
                        ...........................

			case NOT_ON_TIMER:
			default:
				if (val < 128) {
					digitalWrite(pin, LOW);
				} else {
					digitalWrite(pin, HIGH);
				}
		}
	}
}

PaoloP:

lollo1100:
vorrei che non mi accendesse i pin digitali

Basta che metti un if e gli dici di saltare i pin digitali.
Crei un array dei pin PWM e se non è tra quelli lo salta.

Il codice dell'AnalogWrite è questo:

void analogWrite(uint8_t pin, int val)

{
// We need to make sure the PWM output is enabled for those pins
// that support it, as we turn it off when digitally reading or
// writing with them.  Also, make sure the pin is in output mode
// for consistenty with Wiring, which doesn't require a pinMode
// call for the analog output pins.
pinMode(pin, OUTPUT);
if (val == 0)
{
digitalWrite(pin, LOW);
}
else if (val == 255)
{
digitalWrite(pin, HIGH);
}
else
{
switch(digitalPinToTimer(pin))
{
...........................
                       // OMISSIS
                       ...........................

		case NOT_ON_TIMER:
		default:
			if (val < 128) {
				digitalWrite(pin, LOW);
			} else {
				digitalWrite(pin, HIGH);
			}
	}
}

}

guarda ti scrivo il codice di come faccio io

  for ( int j = 0; j < 8; j++ ){
    if ( MSK[j] == 1 && CMD[6] == 0x0d )
      analogWrite( LED[j], valore2 );
  }

questo sta dentro il loop. MSK [j] va da 0 a 7 e i gli indici che sono pwm sono j == 0 j==4 j==6 valore2 viene incrementato di 5 da 0 a 255 quando legge 130 mi si accende giustamente per come è fatto analogwrite così come mi si spegne quando legge 125 i pin digitali

come posso fare a evitare di accendere i pin digitali in modalità dimmer ovvero non fargli vedere duty cycle maggiori 128 o minori di 128 in fase di spegnimento ???

poi se volessi inserire la password sulla connessione telnet e far si che si colleghi solo con la password corretta ??

lollo1100:
come posso fare a evitare di accendere i pin digitali in modalità dimmer ovvero non fargli vedere duty cycle maggiori 128 o minori di 128 in fase di spegnimento ???

Non ho capito.... un pin digitale accetta o 1 o 0, 1 per High e 0 per Low.
Non ha stati intermedi, quelli puoi averli solo sui pin PWM pilotati con analogWrite.

leo72:

lollo1100:
come posso fare a evitare di accendere i pin digitali in modalità dimmer ovvero non fargli vedere duty cycle maggiori 128 o minori di 128 in fase di spegnimento ???

Non ho capito.... un pin digitale accetta o 1 o 0, 1 per High e 0 per Low.
Non ha stati intermedi, quelli puoi averli solo sui pin PWM pilotati con analogWrite.

leo anche io pensavo ciò solo che quando gli arriva un valore maggiore uguale a 128 il digitale si accende e considera come se gli avessi mandato 255 xk come posso fare
il pin digitale si accende non va bene cioè va bene fino ad un certo punto appena vede 130 come duty si accende

Qualunque valore che non sia 0 viene interpretato come 1.
Questo è il codice della digitalWrite interessato all'analisi del valore passato:

	if (val == LOW) {
		*out &= ~bit;
	} else {
		*out |= bit;
	}

leo72:
Qualunque valore che non sia 0 viene interpretato come 1.
Questo è il codice della digitalWrite interessato all'analisi del valore passato:

	if (val == LOW) {
	*out &= ~bit;
} else {
	*out |= bit;
}

Leo io faccio AnalogWrite(pin,value) se value >= 128 per un pin digitale quello è ON altrimenti se <128 è OFF capisci che intendo?

Ah, ok. Ma il succo non cambia.
Ecco cosa fa l'analogWrite:

case NOT_ON_TIMER:
			default:
				if (val < 128) {
					digitalWrite(pin, LOW);
				} else {
					digitalWrite(pin, HIGH);
				}

Tutto ciò che uguale o sopra a 128 diventa HIGH.