Arduino e pulsante

Ciao , ho un problema con Arduino ,devo intercettare quando viene premuto un pulsante , direte voi e che ci vuole semplice , lo pensavo anche io ma dato che il codice che ho scritto non funziona a dovere ve lo chiedo .
il mio problema è che riesco a leggere il valore del pin e se il pulsante è premuto è a 1 , il problema capita spesso che quando premo il pulsante l Arduino non sta leggendo lo stato del pin e dunque perdo l azione che è stato premuto il pulsante , mi funziona solo se lo tengo premuto per 1 o 2 secondi il tempo che gira il codice e fa la lettura del pin.
Ora chiedevo ma esiste un qualcosa ad eventi ? ho provato ad usare i task ma non credo di averlo fatto a dovere perché comunque la lettura funziona solo tenendo premuto il pulsante .
avete qualche idea ???
grazie mille

Ci fai vedere il codice che usi? Scommetto che contiene dei lunghi delay()...

inserisco la parte di codice di loop , i Delay non ci sono lunghi , ho usato i task per vedere se funziona ...ma è la stessa cosa ...

void bt12Callback();
//
Task b12task(10, TASK_FOREVER, &bt12Callback);


void bt12Callback() {
  valb1=digitalRead(button1PIN);
  if(valb1)
  {
    piumenol=2;
    }
  //delay(5);
  valb2=digitalRead(button2PIN);
  if(valb1)
  {
    piumenol=-2;
    }
  if((valb1) && (valb2))
  {
    piumenol=0;
    motorminl=0;
    }
}

void loop() {
  //
  runner.execute();
  delay(10);
  //
  valtrimlr = analogRead(trimlrPIN);
  strim.setValue(map(valtrimlr,rangmintrim,rangmaxtrim,100,0));
  valtrimlr = map(valtrimlr, rangmintrim,rangmaxtrim,minValueMotor,maxValueMotor);
  valStickThrottle = analogRead(throttlePIN);
  pbarthrottle.setValue(map(valStickThrottle,rangminjoythr,rangmaxjoythr,0,100));
  itoa(map(valStickThrottle,rangminjoythr,rangmaxjoythr,0,100), sbuffer, 10);
  tthrottle.setText(sbuffer); //map(valStickThrottle,rangminjoythr,rangmaxjoythr,0,100));
  valStickThrottle = map(valStickThrottle, rangminjoythr,rangmaxjoythr,minValueMotor,maxValueMotor);
  valStickYaw = analogRead(yawPIN);
  pbaryaw.setValue(map(valStickYaw,rangminjoyyaw,rangmaxjoyyaw,100,0));
  itoa(map(valStickYaw,rangminjoyyaw,rangmaxjoyyaw,0,100), sbuffer, 10);
  tyaw.setText(sbuffer);
  valStickYaw = map(valStickYaw, rangminjoyyaw, rangmaxjoyyaw, minValueMotor, maxValueMotor);
  //
  motorminl=motorminl+piumenol;
  motorminr=motorminr+piumenor;
  piumenol=0;
  piumenor=0;
  //
  pbarmotl.setValue(motorminl);
  pbarmotr.setValue(motorminr);
  itoa(motorminl, sbuffer, 10);
  lmot.setText(sbuffer);
  itoa(motorminr, sbuffer, 10);
  rmot.setText(sbuffer);
  //
  commands="";
  commands=String(valStickThrottle)+"|"+String(valStickYaw)+"|"+String(valtrimlr)+"|"
          + String(valb1)+"|"+String(valb2)+"|"+String(valb3)+"|"+String(valb4)
          + "|"+String(motorminl)+"|"+String(motorminr)+"|";
  serialRadio.println(commands);
  Serial.println(commands);
  commands.toCharArray(sbuffer,100);
  txtlog.setText(sbuffer);
  delay(10);
  //
}

Non conosco "i task" e non mi posso esprimere.

Quei delay(), per quanto non causa del problema, mi pare siano completamente inutili e servano solo a rallentare il programma.

Un consiglio per la leggibilità e manutenibilità: quei map(...) che usi più volte, falli una volta sola memorizzando il risultato in una variabile, e poi usa questa.

per verificare (a spanne) quanto dura un ciclo di loop
inserisci come prima istruzione del loop

unsigned long inizio=micros();

e come ultime istruzioni

unsigned long fine= micros();
Serial.println(fine - inizio);
delay(1000);   //pausa di un secondo tra 2 cicli di loop

ovviamente devi attivare la seriale nel setup...

se il loop ti dura veramente 1-2 secondi.... hai dei problemi e devi trovare cos'è che blocca il programma per così tanto tempo

SukkoPera:
Non conosco "i task" e non mi posso esprimere.

Quei delay(), per quanto non causa del problema, mi pare siano completamente inutili e servano solo a rallentare il programma.

Un consiglio per la leggibilità e manutenibilità: quei map(...) che usi più volte, falli una volta sola memorizzando il risultato in una variabile, e poi usa questa.

ma I map che effettua sono tutti diversi , non ha senso memorizzarli , non li riuso .....

ho provato altre strade una fra queste quella degli interrupts , solo che nella scheda pro-mini che uso sono solo due i pin a cui sono associati gli interrupts e il mio joystick ne ha 4 ....
soluzioni ???

potresti utilizzare 4 diodi sui pulsanti e un solo pin di interrupt, ai tempi che utilizzavo i pic per un telecomando con diversi pulsanti utilizzavo appunto un piccolo diodo per svegliare il pic dallo sleep con uno qualsiasi dei pulsanti premuti.

matteogiovagnini:
ho provato altre strade una fra queste quella degli interrupts , solo che nella scheda pro-mini che uso sono solo due i pin a cui sono associati gli interrupts ...

... mai sentito parlare dei "pin-change interrupts"? Dato che non sono esattamente banali da applicare, ti consiglio l'uso dell'ottima libreria EnableInterrupt che gestisce tutti i tipi di interrupt. Il relativo WiKi QUI.

Guglielmo

Accodandomi ai precedenti validi consigli, mi chiedevo che senso abbia la seconda if() ossia se per caso non debba essere "if(valb2)" e non "if(valb1)", perché mi sfugge la logica:

void bt12Callback() {
  valb1=digitalRead(button1PIN);
  if(valb1)
  {
    piumenol=2;
    }
  //delay(5);
  valb2=digitalRead(button2PIN);
  // ----------------
  // QUESTO!!
  if(valb1)
  {
    piumenol=-2;
    }
  // ----------------
  if((valb1) && (valb2))
  {
    piumenol=0;
    motorminl=0;
    }
}

Ossia se è premuto il pulsante 1 imposti piumenol a 2, poi vedi se è premuto il pulsante 2 ma se è premuto il primo imposti piumenol a -2 (!), ed infine se sono premuti entrambi lo metti a zero...
Insomma, io avrei fatto una cosa del genere:

void bt12Callback() {
  valb1=digitalRead(button1PIN);
  valb2=digitalRead(button2PIN);
  if( (valb1) && !(valb2) ) // Pulsante 1 premuto e 2 non premuto, incremento
    piumenol=2;
  else if(!(valb1) && (valb2) ) // Pulsante 1 non premuto e 2 premuto, decremento
    piumenol=-2;
  else if((valb1) && (valb2))  // Entrambi premuti, fermo
  {
    piumenol=0;
    motorminl=0;
    }
}

Infine una nota, scusami, tutta sta sparata di istruzioni tutte attaccate senza uno straccio di commento:

  valtrimlr = analogRead(trimlrPIN);
  strim.setValue(map(valtrimlr,rangmintrim,rangmaxtrim,100,0));
  valtrimlr = map(valtrimlr, rangmintrim,rangmaxtrim,minValueMotor,maxValueMotor);
  valStickThrottle = analogRead(throttlePIN);
  pbarthrottle.setValue(map(valStickThrottle,rangminjoythr,rangmaxjoythr,0,100));
  itoa(map(valStickThrottle,rangminjoythr,rangmaxjoythr,0,100), sbuffer, 10);
  tthrottle.setText(sbuffer); //map(valStickThrottle,rangminjoythr,rangmaxjoythr,0,100));
  valStickThrottle = map(valStickThrottle, rangminjoythr,rangmaxjoythr,minValueMotor,maxValueMotor);
  valStickYaw = analogRead(yawPIN);
...eccetera eccetera...

non è il massimo, non solo per te (se tra un anno o due devi riprendere in mano il codice, sicuro di ricordare come funziona e perché?) ma anche per chi (come noi) magari vorrebbe cercare di aiutarti... :wink:

Scusate ma mi intrometto un attimo:

piumeno1=2*letturap1-2*letturap2;
altravariabile=altravariabile*!(letturap1*letturap2);

Se é premuto solo p1
Piumeno=21-20=2
Altravariabile=se stessa*!(10)= sestessa!0=sestessa*1=sestessa
Viceversa l'altro

E se tutti e due
Piumeno=2-2=0
Altra=sestessa*0=0

Any fool can write code that a computer can understand. Good programmers write code that humans can understand. — Martin Fowler

Programs should be written for people to read, and only incidentally for machines to execute. — Abelson and Sussman

Ok, forse mi son fatto prendere un po la mano con sta roba dello "accorcia e restringi"

Forse.

:smiley: :smiley:

Grazie mille dei consigli , il codice era abbozzato al volo per provare i pulsanti .....
Il mio problema sono gli interrupt, usando ardui no pro mini non posso applicare la soluzione di Guglielmo xche mi sembra di aver capito che non è supportata dalla mia scheda , credo che userò il metodo descritto da Zef ...

Minimatte77:
Il mio problema sono gli interrupt, usando ardui no pro mini non posso applicare la soluzione di Guglielmo xche mi sembra di aver capito che non è supportata dalla mia scheda

:o :o :o ... ma non hai una Pro Mini? ... e non è basata su ATmega328P?

Guglielmo

... un altra cosa ... non avevi l'account "matteogiovagnini"? ... REGOLAMENTO, punto 16.12 ... che debbo fare?

Guglielmo

gpb01:
... un altra cosa ... non avevi l'account "matteogiovagnini"? ... REGOLAMENTO, punto 16.12 ... che debbo fare?

Guglielmo

Era una vita che non mi ricollegavo e non riuscivo a trovare la password e le mail associata all account ...

... e quindi, quale account devo eliminare (e con lui tutti i post/thread)? ? ? Il REGOLAMENTO parla chiaro !

Guglielmo