Pages: [1]   Go Down
Author Topic: Problema con PWM  (Read 974 times)
0 Members and 1 Guest are viewing this topic.
Ivrea
Offline Offline
Jr. Member
**
Karma: 0
Posts: 50
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ciao a tutti, volevo controllare per esercitarmi l'intensità di luce di un led leggendo il valore attraverso porta seriale, ho scritto questo codice:
Code:
const int led = 9;  //Pin del led (PWM OK)
int valore_letto = 0;   //Variabile che memorizza il valore letto    

void setup()
{
  Serial.begin(9600);  //Impostazione del baud-rate
}

void loop()
{
  valore_letto = Serial.read(); //Legge un valore dalla seriale e lo memorizza in valore_letto
  analogWrite(led, valore_letto);  //Accende il led secondo il valore          
  Serial.print("\t output = ");    //Restituisce in uscita la scritta  
  Serial.println(valore_letto);    //Restituisce in uscita il valore
}

peccato che non funzioni, tramite il serial monitor visualizzo sempre il valore -1 in valore_letto, il led rimane acceso e per qualsiasi numero che do in input sempre attraverso il serial monitor (fino a 255) valore_letto incrementa fino a 49 per un secondo e il led lampeggia
Logged

Milano
Offline Offline
Sr. Member
****
Karma: 0
Posts: 362
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

devi usare Serial.available()

Code:
void loop() {

      // send data only when you receive data:
      if (Serial.available() > 0) {
            // read the incoming byte:
            incomingByte = Serial.read();

            // say what you got:
            Serial.print("I received: ");
            Serial.println(incomingByte, DEC);
      }
}
Logged

BZ (I)
Offline Offline
Brattain Member
*****
Karma: 258
Posts: 21494
+39 349 2158303
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

ciao Matti157
comunque sappi che Serial read prende solo un carattere; se vuoi ricevere dei valori fino a 255 devi fare diversamente:

Code:

char Data[4];
int PWM =0;
int i =0;

...


do {      // aspetta di leggere 3 Byte e li mettere nella stringa Data.
     if (Serial.available()) {
       Data[i] = Serial.read();
     i++;
     }
   } while (i<3);  
  
Data[i] = 0;    // aggiunge un zero finale per chiudere la stringa
i=0;
  
PWM = atof(Data);  // trasforma la stringa in un numero

....


Ciao Uwe
« Last Edit: July 25, 2010, 04:21:15 am by uwefed » Logged

Roma / Benevento
Offline Offline
Full Member
***
Karma: 0
Posts: 183
Guardava al futuro con l'inguaribile ottimismo di un dodo...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Come già ti hanno detto SerialRead legge un solo byte che comunque può valere al massimo 128 a meno che da parte del computer non usi un sistema diverso dal SerialMonitor che tratta solo caratteri ascii. Da parte dell'Arduino il dato andrebbe letto come unsigned char per arrivare a 255.
Quel "-1" che leggi significa "non ci sono dati" e questo succede perché il computer dovrebbe mandare il byte proprio mentre l'Arduino esegue il SerialRead... alquanto difficile.
Per ovviare devi mettere l'Arduino a fare un "polling" della seriale con la funzione SerialAvailable... che semplicemente restituisce true quando in ingresso c'è un dato diverso da "-1".
La tua applicazione è semplice e non ci sono problemi a farlo, ma per applicazioni più complesse il polling è un vero problema perché il processore deve starsene ad ascoltare la seriale senza fare nient'altro, in questi casi si dovrebbe assegnare un interrupt alla porta ma sull'Arduino non so ancora come si fa, probabilmente bisogna ricorrere all'AVR-C o all'asm... boh!
ciao
Logged

Linux User #503422 | Linux Machine #414597-8 | Ubuntu User #30132

Milano
Offline Offline
Sr. Member
****
Karma: 0
Posts: 362
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

@MGuruDC
per gli interrupt http://www.arduino.cc/en/Reference/AttachInterrupt
Logged

BZ (I)
Offline Offline
Brattain Member
*****
Karma: 258
Posts: 21494
+39 349 2158303
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ragazzi non complicarsi la vita sparando in alto;
Pe il momento la soluzione da me proposta va bene per il problema di  matti157 . Se ci fossero altre esigenze cambierá il codice.
Ciao Uwe
Logged

Ivrea
Offline Offline
Jr. Member
**
Karma: 0
Posts: 50
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

grazie a tutti per le risposte molto precise  smiley-wink
sono rimasto molto contento di Arduino e del vostro forum che leggo quotidianamente e ne approfitto magari per fare una proposta:
si dovrebbe aprire un thread ufficiale di Arduino sui maggiori forum di informatica (tipo hwupgrade) per farlo conoscere un po' di più, io ci ho già messo del mio!

domani poi proverò il codice, comunque ora i valori li invio via serial monitor e poi tramite un'interfaccia in visual basic semplice da fare.
Logged

Ivrea
Offline Offline
Jr. Member
**
Karma: 0
Posts: 50
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

ok ho provato il codice:
Code:
char Data[4];
int pwm =0;
int i =0;
const int led = 9;  //Pin del led (PWM OK)

void setup()
{
  Serial.begin(9600);  //Impostazione del baud-rate
}

void loop()
{
  do {      // aspetta di leggere 3 Byte e li mettere nella stringa Data.
     if (Serial.available()) {
       Data[i] = Serial.read();
     i++;
     }
   }
   while (i<3);
  {
    Data[i] = 0;    // aggiunge un zero finale per chiudere la stringa
    i=0;
  }
  
 pwm = atof(Data);  // trasforma la stringa in un numero


  analogWrite(led, pwm);           //Accende il led secondo il valore          
  Serial.print("\t output = ");    //Restituisce in uscita la scritta  
  Serial.println(pwm);    //Restituisce in uscita il valore
}

solo che ci sono problemi:
-apro il serial monitor, digito 20 per fare accendere il led in modo lieve, a questo punto succede che la prima volta che do il numero non cambia nulla, il led rimane spento e non si visualizza il messaggio di risposta da arduino, la seconda volta il valore viene letto ma viene interpretato come un 202, facendo accendere così il led ad una forte intensità, la terza volta che do il 20 in input funziona tutto bene

-provo con 50, la prima volta mi viene restituito valore di 305, la seconda niente, la terza un 505 e la quarta finalmente 50

-PER FARE ANDARE I NUMERI A 3 CIFRE HO MODIFICATO IL TUO CODICE METTENDO 2 PARENTESI GRAFFE DOPO IL CICLO WHILE, SPERO DI AVER FATTO GIUSTO, ALTRIMENTI AI NUM. DI 3 CIFRE VENIVA TRONCATA L'ULTIMA CIFRA

(scusate il maiuscolo)
« Last Edit: July 26, 2010, 03:54:15 pm by matti157 » Logged

BZ (I)
Offline Offline
Brattain Member
*****
Karma: 258
Posts: 21494
+39 349 2158303
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

devi scrivere 020 e 050; devi sempre trasmettere 3 numeri
Ciao Uwe
Logged

Ivrea
Offline Offline
Jr. Member
**
Karma: 0
Posts: 50
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

ok grazie! non ci arrivavo mica  :-[
Logged

Roma / Benevento
Offline Offline
Full Member
***
Karma: 0
Posts: 183
Guardava al futuro con l'inguaribile ottimismo di un dodo...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Grazie, conosco attach e detach interrupt, ma queste funzioni assegnano interupt a un pin, mica a una porta!
Il problema è far partire l'interrupt quando la porta segna !=-1... boh
Logged

Linux User #503422 | Linux Machine #414597-8 | Ubuntu User #30132

Roma / Benevento
Offline Offline
Full Member
***
Karma: 0
Posts: 183
Guardava al futuro con l'inguaribile ottimismo di un dodo...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
solo che ci sono problemi:
-apro il serial monitor, digito 20 per fare accendere il led in modo lieve, a questo punto succede che la prima volta che do il numero non cambia nulla, il led rimane spento e non si visualizza il messaggio di risposta da arduino, la seconda volta il valore viene letto ma viene interpretato come un 202, facendo accendere così il led ad una forte intensità, la terza volta che do il 20 in input funziona tutto bene

-provo con 50, la prima volta mi viene restituito valore di 305, la seconda niente, la terza un 505 e la quarta finalmente 50

-PER FARE ANDARE I NUMERI A 3 CIFRE HO MODIFICATO IL TUO CODICE METTENDO 2 PARENTESI GRAFFE DOPO IL CICLO WHILE, SPERO DI AVER FATTO GIUSTO, ALTRIMENTI AI NUM. DI 3 CIFRE VENIVA TRONCATA L'ULTIMA CIFRA

Io uso questa funzione che mi permette di leggere numeri anche senza mandare gli zeri prima.

Code:
void acquis(){
  for(i = 0; i < 10; i ++) {  //pulisce il buffer
    buf[i] = 0;
  }
  for(i = 0; Serial.available() > 0; i ++) {  //in caso di errore segnala e esce dalla funzione
    if (i > 10) {
      Serial.println("Errore");
      Serial.flush();
      return;
    }
    buf[i] = Serial.read();  //memorizza nel buffer i dati in arrivo
  }
  if (i > 0){
    T = 0;
    i --;
    for (esp = 0; i >= 0; i --) {  //converte i caratteri del buffer in un numero intero
      T += (buf[i] - 48)*pow(10, esp);
      esp++;
    }
  }  

L'ultimo ciclo for può essere sostituito con la funzione atoi(quando ho scritto questo codice non sapevo della sua esistenza).
I problemi che avevi in pratica sono legati al fatto che non pulivi il buffer prima si usarlo e al fatto che non ti affidavi alla velocità della porta per scrivere il buffer.
ciao
Logged

Linux User #503422 | Linux Machine #414597-8 | Ubuntu User #30132

Pages: [1]   Go Up
Jump to: