Pages: [1] 2 3   Go Down
Author Topic: Problema a me incomprensibile di programmazione  (Read 1186 times)
0 Members and 1 Guest are viewing this topic.
Livorno
Offline Offline
Jr. Member
**
Karma: 0
Posts: 77
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Sto facendo una funzioncina per fare il debounce ai tasti (non potendo usare la libreria già fatta, perchè i tasti sono collegati al PCF8574AP con relativa libreria).
Il punto è che il codice che ho fatto funziona, ma smette di funzionare nel momento in cui provo a convertire il codice in funzione.

Questo è il codice semplice:
Code:
#include <Wire.h>
#include <IOexp.h>

IOexp tastiera(0x39);
boolean tasto;
unsigned long tempo;

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

void loop()
{
  tasto = tastiera.read(P0);
  if (tasto == true && (millis() >= (tempo + 300)))
  {
    Serial.println("Tasto destro");
    tempo = millis();
  }
}

Questo è lo stesso codice convertito in modo da poter essere richiamato come funzione la dove serve (in questo caso la stessa funzione serve per 3 diversi tasti):
Code:
#include <Wire.h>
#include <IOexp.h>

#define DX 1 //Tasto sul pin 4 del PCF, corrispondente a P0
#define SX 2 //Tasto sul pin 5 del PCF, corrispondente a P1
#define Dec 4 //Tasto sul pin 6 del PCF, corrispondente a P2

IOexp tastiera(0x39);

unsigned long tempo;

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

void loop()
{
if (LeggiTasto(SX)) //Leggo il tasto già con i controlli di debounce
{ //Se la funzione ritorna true, faccio l'azione
Serial.println("Tasto sinistro");
}
if (LeggiTasto(DX)) //Leggo il tasto già con i controlli di debounce
{ //Se la funzione ritorna true, faccio l'azione
Serial.println("Tasto destro");
}
if (LeggiTasto(Dec)) //Leggo il tasto già con i controlli di debounce
{ //Se la funzione ritorna true, faccio l'azione
Serial.println("Tasto decremento");
}
}

boolean LeggiTasto(byte tasto)
{
if (tastiera.read(tasto) && (millis() >= (tempo + 300)))
{
tempo = millis();
return true;
}
}

Non ho spiegato che problema mi da: apparentemente funziona esattamente come il codice sopra, in realtà dopo esattamente 65535 millisecondi premendo un qualunque tasto, questo risponde a raffica anzichè col debounce.
Sicuramente il fatto che il problema si manifesta esattamente dopo 65535 la dice lunga, questo mi fa pensare a problemi di conversioni di variabili o cose simili, ma dato che l'unica variabile che è implicata nel tempo è "tempo" ed è infatti dichiarata come unsigned long, non riesco a capire dove sia il problema.
Inoltre sottolineo che lo stesso codice, se utilizzato come codice e non come funzione, si comporta correttamente!!  smiley-eek
Logged

0
Offline Offline
Shannon Member
****
Karma: 117
Posts: 10106
:(){:|:&};: TOX id: fcb8e918bef08581e23f6ddf9d4dba77697c25b217bf372736ed959a95fde36df5b8c5b90fbb
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

dopo il 300 nel while scrivi LU, in pratica lo forzi ad essere un unsigned long:
Quote
if (tasto == true && (millis() >= (tempo + 300LU)))
Logged

my Arduino code: https://github.com/lestofante/arduinoSketch
sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

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

dopo il 300 nel while scrivi LU, in pratica lo forzi ad essere un unsigned long:
Quote
if (tasto == true && (millis() >= (tempo + 300LU)))
Avevo già provato una cosa simile mettendo (unsigned long)300 ma non aveva funzionato. E comunque non mi spiego come la stessa riga se usata "come codice" funziona, se la metto dentro una funzione invece no.

Comunque faccio una prova e ti faccio sapere,
grazie.

ciao
Logged

0
Offline Offline
Shannon Member
****
Karma: 117
Posts: 10106
:(){:|:&};: TOX id: fcb8e918bef08581e23f6ddf9d4dba77697c25b217bf372736ed959a95fde36df5b8c5b90fbb
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

ma scusa il codice ti compila? perchè la funzione non ha il return false (forse è implicito?)..

eppoi scusami, ma se leggi 3 tasti ogni tasto deve avere il tuo time, altrimenti poi succedono casini (ma mi sembra starno che accadano in modo deterministico)
Logged

my Arduino code: https://github.com/lestofante/arduinoSketch
sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

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

Si, il codice si compila correttamente. Il resturn false direi che è implicito dal momento che normalmente funziona.
Si in effetti il tempo "in comune" non è il massimo, ma per adesso non mi sono addentrato troppo in questa problematica dato che c'è quest altro problema a monte. (comunque grazie del suggerimento)

Ho provato "if (tasto == true && (millis() >= (tempo + 300LU)))" ma si comporta esattamente allo stesso modo.
« Last Edit: April 22, 2011, 10:02:32 am by mechrekt » Logged

0
Offline Offline
Shannon Member
****
Karma: 117
Posts: 10106
:(){:|:&};: TOX id: fcb8e918bef08581e23f6ddf9d4dba77697c25b217bf372736ed959a95fde36df5b8c5b90fbb
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

metti il return false, e prova a usare il codice solo con un tasto
Logged

my Arduino code: https://github.com/lestofante/arduinoSketch
sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

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

ok
Logged

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

Cavolo sembra funzionare!!!
Logged

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

Qualche suggerimento per mettere la variabile "tempo" distinta per ogni tasto?
Banalmente potrei passare alla funzione la variabile tempo oltre che il tasto in questione, ma poi come faccio a far tornare indietro il risultato in 2 variabili? La mia conoscenza limitata di programmazione si ferma a una funzione dove puoi dargli in pasto quante variabili vuoi, ma ne ritorna indietro sempre una. Nel caso specifico la funzione è dichiarata come boolean e infatti ritorna true o false. Io avrei bisogno che mi restituisse anche "a che punto è" la variabile tempo relativa ad un tasto specifico per poi ridargliela in pasto al loop successivo o quando mi serve lavorare su quel tasto.

Ad ogni modo usare una variabile "tempo" globale o usarne una per ciascun tasto non è che impedisce la lettura contemporanea di più tasti (qualora per assurdo uno ne tenesse premuti 2 insieme), infatti in entrambi i casi ottengo risultati random perchè nel loop comunque leggo tutti i tasti e prima o poi viene eseguita l'azione relativa a ciascun tasto.
Logged

0
Offline Offline
Shannon Member
****
Karma: 117
Posts: 10106
:(){:|:&};: TOX id: fcb8e918bef08581e23f6ddf9d4dba77697c25b217bf372736ed959a95fde36df5b8c5b90fbb
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

secondo me l'ideale sarebbe avere una struttura Tasto che contenga l'unsigned long tempo, byte pin ed eventuali altre info che ti interessano. poi crei un'array di queste strutture(una cella per ogni tasto), che nel setup() inizializzi inserendo il valore del pin e inizializzi tempo a 0 o ai millis() attuali.
poi ogni loop() hai una funzione che scorre l'array di strutture, e per ogni struttura esegua la funzione desiderata.

se non sai cos'è una struttura (lascia stare per ora la parte sulle liste se non sai cos'è un puntatore) http://cprogramminglanguage.net/c-structure.aspx
Logged

my Arduino code: https://github.com/lestofante/arduinoSketch
sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

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

1) devi usare una variabile del tempo per ogni pulsante
2) 300 ms sono troppi, ne bastano 10 e in questo caso puoi anche fare un delay(10); leggi il tasto, asetti 10 ms e rileggi. Se é ancora HIGH é schiacciato.
3) se la variabile la definisci globale (fuori dalla funzione come l' hai fatto nel esempio) é a disposizione in tutte le funzioni
4) il Tuo programma ha piú errori concettuali:
Code:
unsigned long tempo;
....
boolean LeggiTasto(byte tasto)
{
if (tastiera.read(tasto) && (millis() >= (tempo + 300)))
{
tempo = millis();
return true;
}
}
*La prima volta che chiami la funzione Leggi Tasto la cariabile tempo non ha valore. ( adesso non so che valore da se uno casuale o semicasuale).
Oltre questo solo quando la condizione é vera (pulsante schiacciato e millis() maggiore di un x piú 300) caricherai la variabile tempo con un valore.
* da un True ogni 300ms se il tasto rimane schiacciato perché non controlli se era giá schiacciato. Qua sta a Te se vuoi eseguire l' azione solo la prima volta che schiacci il tasto o di continuo finche il tasto viene mollato; presuppongo la prima opzione.  

2 soluzioni:
*1) usare un semplice delay di 10 ms
Code:
boolean LeggiTasto(byte tasto)
{
if (tastiera.read(tasto)&& StatoTasto [tasto]==0) // lege la prima volta il tasto schiacciato
{
        delay(10);
        if (tastiera.read(tasto)) // lege la seconda volta il tasto schiacciato
      {
               StatoTasto [tasto]++;
               return true;
      }
               else
               {
               return false;
               }
        }
       if (tastiera.read(tasto)&& StatoTasto [tasto]==1) // lege la seconda volta il tasto schiacciato
       {
        return false;
        }  
      
        if (!tastiera.read(tasto)&& StatoTasto [tasto]==1) // lege la prima volta il tasto rilasciato
{
        delay(10);
        if (!tastiera.read(tasto)) // lege la seconda volta il tasto rilasciato
      {
               StatoTasto [tasto]=0;    //Dopo il tempo di debounce il tasto é ancora mollato
               return false;
               }
               else
               {
               return false;    // Dopo il tempo di debounce il tasto é schiacciato; serve un ulteriore controllo al prossimo giro.
               }
        }
}
}

*2) usare una variabile di stato millis().

le cose devono essere sequenziali:
   * tasto schiacciato e StatoTasto== 0 -> StatoTasto=1 e memorizza tempo return false;
   * tasto schiacciato, StatoTasto== 1 e tempo passato -> StatoTasto=2 return true;
   * tasto mollato e StatoTasto== 2 -> StatoTasto=3 e memorizza tempo return false;
   * tasto mollato, StatoTasto== 3 e tempo passato -> StatoTasto=0 return false;
definisci le seguenti variabili all inizio: una per ogni entrata
Code:
unsigned long tempo[8];  // ritardo per ogni tastio
StatoTasto[8] ;  // stato di ogni tasto

Non ho compilato il codice percui potrebbero essere errori di battitura.

Ciao Uwe
Logged

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

secondo me l'ideale sarebbe avere una struttura Tasto che contenga l'unsigned long tempo, byte pin ed eventuali altre info che ti interessano. poi crei un'array di queste strutture(una cella per ogni tasto), che nel setup() inizializzi inserendo il valore del pin e inizializzi tempo a 0 o ai millis() attuali.
poi ogni loop() hai una funzione che scorre l'array di strutture, e per ogni struttura esegua la funzione desiderata.

se non sai cos'è una struttura (lascia stare per ora la parte sulle liste se non sai cos'è un puntatore) http://cprogramminglanguage.net/c-structure.aspx
Interessante, mi piacerebbe approfondire questo aspetto. Ho letto il link e più o meno ho capito come potrei creare la struttura, ma non ho capito come questa cosa potrebbe risolvere il problema di dare in pasto ad una funzione quante variabili vuoi (o una struttura di esse) se poi posso ritornare indietro sempre e solo una variabile.
Logged

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

Mit globalen Variablen hast Du das Problem nicht.
Grüße Uwe

Con variabili globali non c'hai quel problema
Ciao Uwe
« Last Edit: April 22, 2011, 03:49:43 pm by uwefed » Logged

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

2) 300 ms sono troppi, ne bastano 10 e in questo caso puoi anche fare un delay(10); leggi il tasto, asetti 10 ms e rileggi. Se é ancora HIGH é schiacciato.
La funzione per come l'avevo intesa io mi fa sia da debounce che da delay per un tasto premuto. La funzione nella sua semplicità utilizza i 300ms impostati in modo che faccia da debounce, evitando doppie o più letture e nello stesso tempo mi fa da "hold" così che se uno tiene premuto un tasto non fa input a raffica ma ogni 300ms, così ad esempio posso usare la funzione per scorrere le voci di un menù. Capisco che la funzione così concepita è un compromesso tra semplicità e funzionalità (poco flessibile).

*La prima volta che chiami la funzione Leggi Tasto la cariabile tempo non ha valore. ( adesso non so che valore da se uno casuale o semicasuale).
Oltre questo solo quando la condizione é vera (pulsante schiacciato e millis() maggiore di un x piú 300) caricherai la variabile tempo con un valore.
La variabile tempo all'inizio direi che ha valore zero infatti non mi ha mai dato problemi

* da un True ogni 300ms se il tasto rimane schiacciato perché non controlli se era giá schiacciato. Qua sta a Te se vuoi eseguire l' azione solo la prima volta che schiacci il tasto o di continuo finche il tasto viene mollato; presuppongo la prima opzione.  
La seconda, come dicevo sopra

*1) usare un semplice delay di 10 ms
Non vorrei immetere delay all'interno del programma.

Non ho capito la soluzione 2 ma penso sia quelle che eventualmente vorrei intraprendere dato che usa millis.
Logged

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

Mit globalen Variablen hast Du das Problem nicht.
Grüße Uwe


Cosa vuol dire? Buona notte a domani?  smiley-lol
Logged

Pages: [1] 2 3   Go Up
Jump to: