Pages: [1]   Go Down
Author Topic: Problema con funzione  (Read 669 times)
0 Members and 1 Guest are viewing this topic.
Marche
Offline Offline
Edison Member
*
Karma: 32
Posts: 2263
azioni semplici per risultati complessi
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Salve a tutti, avrei bisogno di capire cosa non va nello sketch che ho fatto. In pratica ho fatto uno script che abilita un'uscita per un tot di millisecondi usando la funzione millis e fin qui spero mi sia spiegato bene; se lo script lo inserisco direttamente nel void loop così come è scritto, funziona correttamente ma se vado ad inserirlo in una funzione noto che l'uscita è sempre alta. Posto gli script, il primo è quello funzionante e se volete provarlo non occorre collegare niente all'arduino in quanto uso per comodità il pin digitale 13:
Quote
const int ledPin =  13; // led sul pin 13
long millisPrec = 0;
int timeSet = 1500;     // durata uscita high
int var = 0;            // variabile per far partire il timer

void setup()
{
  Serial.begin(9600);
  pinMode(ledPin, OUTPUT);  // setto il pin come uscita
  var = 1;                  // all'inizio la variabile è 1 e fa partire il timer nel loop
  delay(2000);              // aspetto 2 secondi
}

void loop()
{
  if (var == 1)                              // se la variabile è 1
  {
    millisPrec = millis();                
    while(millis() <= millisPrec + timeSet)  // finchè millis non raggiunge
    {                                        // il tempo impostato
      digitalWrite(ledPin, HIGH);            // l'uscita è alta
    }
    digitalWrite(ledPin, LOW);               // al termine l'uscita torna bassa
    var = 0;                                 // e la variabile di controllo va a 0
  }                                          // in modo che il timer non riparte
}
Nello script sottostante invece ho messo il codice in una funzione per comodità ma il led del pin 13 rimane sempre acceso:
Quote
const int ledPin =  13; // led sul pin 13
long millisPrec = 0;
int timeSet = 1500;     // durata uscita high
int var = 0;            // variabile per far partire il timer

void setup()
{
  Serial.begin(9600);
  pinMode(ledPin, OUTPUT);
  var = 1;                
  delay(2000);
}

void loop()
{
  timer(var, timeSet, ledPin);                                      
}

void timer(int varControllo, int durata, int pin)
{
  if (varControllo == 1)
  {
    millisPrec = millis();
    while(millis() <= millisPrec + durata)
    {
      digitalWrite(pin, HIGH);
    }
    digitalWrite(pin, LOW);
    varControllo = 0;  
   }
}
Non è un problema enorme in quanto potrei omettere la funzione e lasciare tutto come nel primo sketch ma vorrei capire perchè si comporta in questo modo almeno in futuro so come comportarmi.
Saluti a tutti.
Logged

0
Offline Offline
Edison Member
*
Karma: 20
Posts: 2227
Have you mooed today?
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ciao,
temo che la chiamata alla funzione timer (che avviene in loop) avvenga molto più velocemente dell'intervallo da te settato per lo spegnimento del led.
Quindi, all'avvio dell'Arduino, la loop chiama la tua funzione timer di fatto accendendo il led (pin HIGH).
Usando una millis, il ciclo non si ferma ma continua, percui la loop richiama nuovamente la tua funzione timer, risettando il pin HIGH (anche se sinceramente, non ho idea se usando una delay la cosa potrebbe cambiare).

Mi sa che rischi anche di saturare la memoria dell'Arduino.

Se ho detto una castronata, mi correggerete!
« Last Edit: June 20, 2010, 09:53:31 am by pictux » Logged

Marche
Offline Offline
Edison Member
*
Karma: 32
Posts: 2263
azioni semplici per risultati complessi
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ciao, grazie per avermi risposto. Mi sembra molto strano il fatto che il codice che sta dentro la funzione è identico a quello del primo sketch che funziona correttamente, forse è la funzione di per sè che gli crea qualche problema. Se come dici tu millis non ferma il ciclo e lo fa proseguire, allora dovrebbe spegnere il led ed impostare la variabile di controllo (varControllo) a 0 non facendo verificare la prima condizione e di conseguenza il led non si riaccenderebbe al prossimo ciclo, ho detto una fesseria?
Logged

0
Offline Offline
Edison Member
*
Karma: 20
Posts: 2227
Have you mooed today?
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ciao,
forse non mi sono spiegato bene.
Nel primo sketch che hai messo, il controllo che fa accendere/spegnere il led è nel loop, percui viene eseguito - oltretutto solo una volta, ovvero:
accende il led perchè VAR ==1, VAR viene quindi settato a 0, di conseguenza il flusso non "rientra"  nellla condizione che ti fa accendere il led.

"Esportando" questo codice in una funzione esterna, questa viene richiamata continuamente dal loop.
Solo che, in questo caso, tu hai una variabile globale VAR che rimane sempre settata a 1 - infatti nella tua funzione tu setti a 0 la variabile di funzione varControllo - ecco la differenza sostanziale rispetto al primo sketch!

Di conseguenza, ogni qualvolta la loop richiama la funzione timer,  il led viene acceso - ma essendo la frequenza di esecuzione di certo maggiore rispetto al valore della variabile timeSet, il led rimane sempre acceso.

Spero di essermi spiegato meglio di prima..
Ciao
M
« Last Edit: June 20, 2010, 10:46:34 am by pictux » Logged

Marche
Offline Offline
Edison Member
*
Karma: 32
Posts: 2263
azioni semplici per risultati complessi
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ora ho capito dove stava l'errore, grazie infinite!
Logged

0
Offline Offline
Full Member
***
Karma: 0
Posts: 181
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

accidenti mi avete superato di un soffio, effettivamente la var esterna resta sempre a 1, mentre commuta varcontrollo da 0 a 1
prova cosi a mettere la funzione int cosi devi avere un ritorno di qualcosa e quel calcosa è 0. Per capirci:
Code:
const int ledPin =  13; // led sul pin 13
long millisPrec = 0;
int timeSet = 1500;     // durata uscita high
int var = 0;            // variabile per far partire il timer

void setup()
{
  Serial.begin(9600);
  pinMode(ledPin, OUTPUT);
  var = 1;                
  delay(2000);
}

void loop()
{
  var=timer(var, timeSet, ledPin);   //la variabile var riceve il risultato della funzione
}

int timer(int varControllo, int durata, int pin)
{
  if (varControllo == 1)
  {
    millisPrec = millis();
    while(millis() <= millisPrec + durata)
    {
      digitalWrite(pin, HIGH);
    }
    digitalWrite(pin, LOW);
   }
   return(0); //restituisce 0
}
Logged

kokiua
Guest
 Bigger Bigger  Smaller Smaller  Reset Reset

Per ottenere delle frequenze con tempi certi non dovete usare le funzioni di tempo date da Arduino, bensì studiarvi gli interrupt del processore, perchè solo con gli interrupt controllati dai timer interni è possibile avere la certezza di una generazione ininterrotta e pulita!
Logged

0
Offline Offline
Full Member
***
Karma: 0
Posts: 181
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

scusami, dove trovo questi interupt? un link
Logged

Marche
Offline Offline
Edison Member
*
Karma: 32
Posts: 2263
azioni semplici per risultati complessi
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

@milionario:
bella trovata cambiare la funzione da void ad integer, mi piace proprio questa soluzione così elegante; in questo modo la variabile globale si aggiorna facilmente senza stravolgere il codice
@kokiua:
fortunatamente non mi serve molta precisione, l'applicazione tollera un secondo come margine d'errore difatti l'uscita deve essere alta per un periodo di tempo superiore a un secondo ma inferiore a 3 secondi, qualche millesimo in più o in meno non mi causa nessun problema. Comunque sia vedrò ugualmente la faccenda dei timer interni, uno sguardo sicuramente non guasta.
Logged

kokiua
Guest
 Bigger Bigger  Smaller Smaller  Reset Reset

@milionario: Per capire cosa sono gli interrupt e come usarli inizia a fare un pochino di ricerche sul forum...
Ad esempio qui ci sono dei miei interventi che ti possono tornare utili:
http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1274956236/45
ed in particolare questo dopo il mio intervento
http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1273390219/0
« Last Edit: June 20, 2010, 01:57:52 pm by kokiua » Logged

Pages: [1]   Go Up
Jump to: