Telecomando con Arduino 1 e TOSP1738

Buongiorno a tutti...

so che ci sono molte discussioni e tutorial in rete riguardo l'uso di Arduino tramite telecomando e ricevitore TOSP1738, ma non ho trovato soluzione alla mio problema.
Tutti i tutorial che ho trovato però spiegano come accendere o spegnere un led tramite uno o l'altro tasto del telecomando.

Es:

  • premo tasto 6 (FFFF36 in formato HEX) e si accende;
  • premo tasto 4 (FFFF24 in formato HEX) e si sepegne;
#include <IRremote.h> // use the library
int receiver = 11; // pin 1 of IR receiver to Arduino digital pin 11
IRrecv irrecv(receiver); // create instance of 'irrecv'
decode_results results;

void setup()
{
  Serial.begin(9600); // for serial monitor output
  irrecv.enableIRIn(); // Start the receiver
  pinMode(9, OUTPUT); // Pin 9 output
}
void loop()
{
  if (irrecv.decode(&results)) // have we received an IR signal?
  {
    Serial.println(results.value, HEX); // display it on serial monitor in hexadecimal
    irrecv.resume();// receive the next value
  }
 
  if ( results.value == 0xFFFF36 ){ //tasto 6 sul telecomando
    digitalWrite(9, HIGH);   // set the LED on
  } 
 if ( results.value == 0xFFFF24 ){ //tasto 4 sul telecomando
    digitalWrite(9, LOW);   // set the LED 0ff
  }  
}

La mia domanda è:
come faccio ad accendere il led finchè il tasto 6 è premuto e si spenga quando rilascio il tasto?

Dipende dal telecomando.

Non tutti i tast trasmettono finche sono premuti.
Quelli del Volume é uno dei tasti che lo dovrebbero fare.

Controllalo con la telecamera del cellulare. Quella vede infrarosso.

Poi a secondo del codice di trasmissine che usano rimandano lo stesso codice del tasto e altri mandano un codice di ripetizione.

Ciao Uwe

uwefed:
Poi a secondo del codice di trasmissine che usano rimandano lo stesso codice del tasto e altri mandano un codice di ripetizione.

Quoto @uwe.
Se mantieni premuto lo stesso tasto, a me alcuni telecomandi spediscono di continuo lo stesso tasto, alcuni invece spediscono solo 1 volta il codice di quel tasto e poi di continuo 0xFFFFFF

Ho già verificato quello che stai dicendo tramite il comando Serial.print()

Ad esempio se premo il tasto 4 nel telecomado il codice HEX sarà FFFF24; Se invece tengo premuto il tasto 4 il codice HEX che uscirà sarà FFFFFF.

Quello che non riesco a far fare ad Arduino è che il led si accenda finchè viene trasmesso "FFFFFFF" e si spenga quando non viene più trasmesso nulla.

Sempre che si possa fare....

Ma almeno 1 volta viene spedito il codice giusto, poi sempre FFFFFF

Quindi devi fare come sempre, una istruzione switch (invece di tanti if) per verificare il tasto e poi lo memorizzi in modo da sapere il "precedente". Crea una variabile a inizio (globale) di nome precedente di tipo byte. E ci memorizzi un valore più facile da ricordare, esempio il numero del tasto come serigrafia, es. 4 o 6

void loop()
{ if (irrecv.decode(&results)) // have we received an IR signal?
  { Serial.println(results.value, HEX); // display it on serial monitor in hexadecimal
    switch(results.value)
    { case 0x406:
      case 0x10406:     //tasto 6 sul telecomando
        precedente=6;  
        break;
      case 0x404:
      case 0x10404:   //tasto 4 sul telecomando
        precedente=4;
        break;
      case 0xFFFFFF:  // tasto ripetuto
        if(precedente==6) digitalWrite(9,HIGH);
        //if(precedente==4) digitalWrite(8,HIGH);
        break;
    default: precedente=0;
    }  
    irrecv.resume();// receive the next value
  }
  digitalWrite(9,LOW);
  //digitalWrite(8,LOW);
}

P.S. Non l'ho provato.

Grazie per la risposta...ma non ti seguo:

A me non interessa sapere se è stato premuto il tasto 4 oppure il 6, mi interessa il codice del pulsante premuto a lungo (cioè 0xFFFFFF) e far sapere sapere ad arduino che deve accendere il led quando rileva quel codice;

Fin qui nessun problema:

 if ( results.value == 0xFFFFFF ){ //tasto 6 [b]"premuto a lungo"[/b] sul telecomando
    digitalWrite(9, HIGH);   // set the LED on

Se dopo 3 secondi che tengo premuto il pulsante 6 lo rilascio, come faccio a far spegnere il led? A dire che con nessun codice rilevato il led deve essere spento?

Non hai capito. Se un telecomando inviasse sempre FFFFFF per qualsiasi tasto se lo tieni premuto, come si potrebbe capire qual'è ?
Almeno i mie telecomandi fanno così:
Appena premi il tasto lui invia COMUNQUE una prima volta il codice giusto. POI tenendolo premuto invia di continuo FFFFFF

In tutti i casi, nella loop() devi mettere un digitalWrite(9,LOW); che spegne il led, in quanto non esiste un "evento" che dice "non premo più il pulsante"
Solo un else del primo if ti fa capire che non stai premendo tasti

if (irrecv.decode(&results))
{ tasto premuto
}
else
{ nessun tasto premuto
}

Ho capito che lo sketch che mi hai postato...ma quello che ho chiesto è un'altra cosa.

Facciamo che nel mio telecomando c'è solamente un pulsante che se premuto per 1ms oppure per 10s il codice sarà sempre 0xFFFFFF.

Premo il pulsante ed il led si accende; OK

Tolgo il dito dal pulsante (dopo 5s) e voglio che si spenga; come si fa?

Ho provato con questo codice, ma mentre tengo premuto si accende e spegne a caso.

#include <IRremote.h> // use the library
int receiver = 11; // pin 1 of IR receiver to Arduino digital pin 11
IRrecv irrecv(receiver); // create instance of 'irrecv'
decode_results results;

void setup()
{
  Serial.begin(9600); // for serial monitor output
  irrecv.enableIRIn(); // Start the receiver
  pinMode(13, OUTPUT); // Pin 9 output
}
void loop()
{
  if (irrecv.decode(&results)) // have we received an IR signal?
  {
    Serial.println(results.value, HEX); // display it on serial monitor in hexadecimal
    irrecv.resume();// receive the next value
  }
 
  if ( results.value == 0xFFFFFF ){ //tasto X sul telecomando
    digitalWrite(13, HIGH);   // set the LED on
 }
 else
    digitalWrite(13, LOW);   // set the LED 0ff
 }

In parole sarebbe: finchè ricevi segnale...led ON; quando non ricevi più segnale...led OFF.

Più facile dirsi...che a farsi :roll_eyes:

Come ti ho scritto al mio post 6, prova:

byte statoled=LOW; 
void loop()
{ 
  if (irrecv.decode(&results)) // have we received an IR signal?
  { Serial.println(results.value, HEX); // display it on serial monitor in hexadecimal
    if ( results.value == 0xFFFFFF )  // tasto X sul telecomando
    { statoled=HIGH;
    }
    else                                         // altro tasto, quindi spengo
    { statoled=LOW;
    }
    irrecv.resume();// receive the next value
  }
  else                // nessun tasto premuto, quindi spengo
  { statoled=LOW;
  }
  digitalWrite(13, statoled); 
}

L'idea non è sbagliata...però non va bene: il led, finché tengo premuto il pulsante lampeggia molto velocemente (non è stabile) perchè la trasmissione del segnale è un treno di impulsi ed avrà sempre una "parte OFF".

Sto provando ad implementare lo sketch con timer (millis) in modo che ogni volta che arrivano gli impulsi mi "resetti il conteggio" ed il led resta ON; se non viene resettato (cioè non arrivano più impulsi ed il pulsante non è più premuto) dopo 200ms il led va OFF.

Però non riesco...idee?

Scusate ma ragiono sempre con la logica del PLC a cui sono abituato, qui bisogna pensarla in altro modo...ma non è facile!

Grazie

Io non potevo provarlo dall'ufficio.
Se effettivamente tenendo premuto il tasto "lampeggia" allora non rimane che contare il tempo per cui non arriva più nulla (magari 500 ms) e solo allora porre statoLed = LOW

Ma se metti una Serial.println("non premuto"); nella ultima else che ti ho scritto, mentre tieni premuto di continuo, lui comunque ti stampa FFFFFF ma anche "non premuto" ?
Come se ci fossero dei momenti in cui la irrecv.decode() non "sente" nulla ?!?

Se premi un tasto del telecomando Ti arriva il codice del tasto esempio tasto 4 : 0x10404
Se tieni premuto a lungo un tasto Ti arriva il codice del tasto seguito dal codice di ripetizione:
tasto 4: 0x10404 0xFFFFFF 0xFFFFFF 0xFFFFFF 0xFFFFFF

Il 0xFFFFFF significa che hai premuto un tasto a lungo. quale tasto é lo sai dal codice spedito prima dei 0xFFFFFF.

Il lampeggio del LEd deriva dal fatto che il loop() gira piú veloce rispetto alla trasmissione del codice da parte del telecomando.

Numeri a caso:
Se il loop viene eseguito ogni 10 mS ma il telecomando manda il codice di ripetizione solo ogni 100mS allora in 9 di 10 cicli di loop() spegni il led per accenderlo il 10 ciclo.
Ci vuole un piccolo ritardo di spegnimento.

Leggo il codice tasto 4 0x10404 accendo il LED.
Leggo il codice IR che arriva; se entro 200mS non arriva un codice di ripetizione 0xFFFFFF spengo il led. Se arriva il codice di ripetizione 0xFFFFFF faccio ripartire il tempo di attesa. Il controllo del tempo trascorso lo fai con millis().

Ciao Uwe

uwefed:
Leggo il codice tasto 4 0x10404 accendo il LED.
Leggo il codice IR che arriva; se entro 200mS non arriva un codice di ripetizione 0xFFFFFF spengo il led. Se arriva il codice di ripetizione 0xFFFFFF faccio ripartire il tempo di attesa. Il controllo del tempo trascorso lo fai con millis().

Esatto...è proprio questo che bisogna fare. Ho provato qualche sketch usando appunto millis() ma non sono riuscito a venirne a capo.
Hai qualche esempio da mostrarmi?

Vedi l'esempio BlinkWithoutDelay. Crei come in quell'esempio 2 variabili unsigned long per avere la millis() corrente e quella vecchia (previousMillis e currentMillis) e mettile pure tutte e due tra le variabili globali.

Poi, facendo riferimento al codice del mio post #8, se premi un tasto (dentro la if di irrecv.decode) se il tasto è quello giusto, oltre a mettere statoLed a HIGH setti la previousMillis = mills();
Invece se il tasto non è quello (else) previousMillis = 0;

Ora nella parte else del "non premuto nulla" ovvero else della irrecv.decode non devi mettere sempre a LOW lo stato del led ma solo se è passato un certo tempo.
Quindi

...
  else   // nessun tasto premuto, quindi spengo
  { currentMillis = millis(); 
    if(currentMillis - previousMillis >= 400)  // 400 ms da provare
    { statoLed=LOW;
      previousMillis = millis(); 
    }
  }
  digitalWrite(9,statoLed);
}

Da provare. In pratica 1 evento attiva HIGH, tasto corretto, 2 eventi lo azzerano, tasto non corretto oppure troppo tempo passato senza premere nulla.
Se poi ci sono anche eventi di tasti "sporchi" bisognerà verificarli.