[Risolto] Problema con telecomando IR + servomotori

Salve a tutti,
è la prima volta che scrivo, perché ho sempre trovato risposte a problemi facendo ricerche sul forum o su internet, ma questa volta non riesco a venirne a capo. Dopo questa breve premessa ecco il problema:

Sto utilizzando da un po' di giorni una Robot shield (quella per Bipe, Filippo e Spiderin) sul mio Arduino Yun. Ho modificato lo schield non collegando il pin Vin, dato che lo Yun non ha regolatore di tensione. Le due schede sono alimentate separatamente. Sulla schield ho collegato 2 servomotori (a 360°) che possono compiere rotazione continua (come fossero due motorini DC). Sulla stessa schield è presente un ricevitore IR. Con un telecomando IR piloto i servomotori, mi capita però che dopo aver premuto un tasto per mettere in movimento un servo, quest'ultimo continua a girare ininterrotamente fino alla pressione un'altro tasto, se non è uno di quelli programmati finalmente il servo si ferma, altrimenti fa quello per cui è programmato azionando per es l'altro servo. Vorrei che non premendo nessun tasto sul telecomando i servo si fermassero. Spero di essere stato abbastanza chiaro, di seguito il codice che sto utilizzando.

#include <IRremote.h>
#include <Bridge.h>       
#include <Servo.h>

int RECV_PIN = 10;        // pin del sensore IR su Robot_shield

IRrecv irrecv(RECV_PIN);  // metodi della libreria
decode_results results;   // IRremote per decodifica

Servo servoDX;
Servo servoSX;

int comando;      // variabile per il codice IR in DEC
int rotServoDX;
int rotServoSX;
int delayServo;

void setup() {
  
  Bridge.begin();

  irrecv.enableIRIn(); // Start the receiver
  
  servoDX.attach(2);  // collegato su Robot shield a S1
  servoSX.attach(4);  // collegato su Robot shield a S3
  
  delayServo = 10;
}

void loop() {
  
  // controlla se è stato ricevuto un comando
  if (irrecv.decode(&results)) {
    storeCode(&results);
    Console.println(comando); // per visualizzare la variabile ricevuta dal telecomando
    irrecv.resume(); // resume receiver
  }
  else {
    rotServoDX = 91;
    rotServoSX = 91;
    muovi();
  }
  
  // i codici dei case sono i valori della decodifica 
  // in decimale del telecomando che si sta utilizzando
  switch (comando) {
    case 528:  // indietreggia
      rotServoDX = 135;
      rotServoSX = 45;
      muovi();
      break;
    case 2064: // avanza
      rotServoDX = 45;
      rotServoSX = 135;
      muovi();
      break;
    case 16: // avanza verso destra
      rotServoDX = 91;
      rotServoSX = 135;
      muovi();
      break;
    case 1040: // avanza verso sinistra
      rotServoDX = 45;
      rotServoSX = 91;
      muovi();
      break;
    case 2576: // indietreggia verso sinistra
      rotServoDX = 135;
      rotServoSX = 91;
      muovi();
      break;
    case 3088: // indietreggia verso destra
      rotServoDX = 91;
      rotServoSX = 45;
      muovi();
      break;
    default:
      rotServoDX = 91;
      rotServoSX = 91;
      muovi();
      break;
  }
  
}

// decodifica
void storeCode(decode_results *results) {

    comando = (results->value);

}

// routine di movimento
void muovi() {
  servoDX.write(rotServoDX);
  delay(delayServo);
  servoSX.write(rotServoSX);
  delay(delayServo);
}

Grazie in anticipo per l'aiuto

Ti invitiamo a presentarti qui: Re: Presentazioni nuovi iscritti, fatevi conoscere da tutti! (Part 1) - Generale - Arduino Forum
e a leggere il regolamento: [REGOLAMENTO] Come usare questa sezione del forum - Italiano - Arduino Forum

Grazie per i link, uno di quelli mi era sfuggito (quello dei link utili). Potrebbero esserci diverse cose interessanti.

Fai un po' di ricerche qui sul forum per "IRremote" e "Servo" perché ...
... ricordo problemi di incompatibilità tra le due librerie ... :roll_eyes:

Guglielmo

Ciao gpb01, mmm...
ho trovato (su un tuo post tra l'altro) che al libreria IR usa:

  • Timer 2 : controlla il PWM dei pin 3 e 11, ma i miei servo sono sui pin 2 e 4
    la libreria servo usa:
  • Timer 1 : controlla il PWM dei pin 9 e 10
    Il ricevitore IR sulla shield è (fisso) sul pin 10, potrebbe essere quello il problema?
    Non so, continuo a cercare

Ripeto, purtroppo ho solo un vago ricordo di qualcuno che aveva problemi ... altro ... non mi viene in mente ... :frowning:

Guglielmo

Fossi in te farei un pò di debug mandando sul Serial Monitor un pò di messaggi nei vari passaggi del codice.
Metterei dei Console.println("stop"); soprattutto dove stoppi i motori.
E anche dentro la void muovi()

Ciao nid69ita,
non ti ho risosto subito ieri perché stavo testando un'altro codice. Ho seguito il tuo consiglio, facendo un po' di debug ho scoperto il mio banalissimo errore.
Non premendo nessun tasto sul telecomando nella variabile comando restava memorizzato l'ultimo valore assegnato, ma come ho fatto a non pensarci !!! Dunque è stato sufficiente nella struttura di controllo if - else assegnare alla variabile un valore che non corrisponde a nessuno dei case dello switch. Ecco il codice corretto:

#include <IRremote.h>      
#include <Servo.h>

int RECV_PIN = 10;        // pin del sensore IR su Robot_shield

IRrecv irrecv(RECV_PIN);  // metodi della libreria
decode_results results;   // IRremote per decodifica

Servo servoDX;
Servo servoSX;

int comando;      // variabile per il codice IR in DEC
int rotServoDX;
int rotServoSX;
int delayServo;

void setup() {
  
  Bridge.begin();

  irrecv.enableIRIn(); // Start the receiver
  
  servoDX.attach(2);  // collegato su Robot shield a S1
  servoSX.attach(4);  // collegato su Robot shield a S3
  
  delayServo = 30;
}

void loop() {
  
  // controlla se è stato ricevuto un comando
  if (irrecv.decode(&results)) {
    storeCode(&results);
    irrecv.resume(); // resume receiver
  }
  else {
    comando = 0;  // se non è stato premuto nessun tasto assegna 0 alla variabile
  }
  
  // i codici dei case sono i valori della decodifica 
  // in decimale del telecomando che si sta utilizzando

  switch (comando) {
    case 528:  // indietreggia
      rotServoDX = 135;
      rotServoSX = 45;
      muovi();
      break;
    case 2064: // avanza
      rotServoDX = 45;
      rotServoSX = 135;
      muovi();
      break;
    case 16: // avanza verso destra
      rotServoDX = 91;
      rotServoSX = 135;
      muovi();
      break;
    case 1040: // avanza verso sinistra
      rotServoDX = 45;
      rotServoSX = 91;
      muovi();
      break;
    case 2576: // indietreggia verso sinistra
      rotServoDX = 135;
      rotServoSX = 91;
      muovi();
      break;
    case 3088: // indietreggia verso destra
      rotServoDX = 91;
      rotServoSX = 45;
      muovi();
      break;
    default:  // se non corrisponde nessun altro comando stop servo
      rotServoDX = 91;
      rotServoSX = 91;
      muovi();
      break;
  }  
}

// decodifica
void storeCode(decode_results *results) {
  
  comando = (results->value);

}

// routine di movimento
void muovi() {
  
  servoDX.write(rotServoDX);
  delay(delayServo);
  servoSX.write(rotServoSX);
  delay(delayServo);
  
}

Ciao, avevo sospettato un problema di logica, ma capisci che non potendolo prove era difficile da vedere.
Bene che hai risolto da solo. Buon "Festa dal lavoro" :smiley:

Grazie, buona festa anche a te. XD

Daigo:
non ti ho risosto subito ieri perché stavo testando un'altro codice. Ho seguito il tuo consiglio, facendo un po' di debug ho scoperto il mio banalissimo errore.

Ottimo, quindi confermi di non aver trovato incompatibilità tra le due librerie (IRremote e Servo) ? ... perché penso sia un'informazione utile da ricordare ... :grin:

Guglielmo

Ciao gpb01.
Credo che non ci sia problema di compatibilità, anche se tu mi hai messo una pulce nell'orecchio.
La libreria servo usa il Timer 1 che controlla i pin 9 e 10, nelle mia configurazione ho il ricevitore IR sul pin 10 gestito dalla libreria IRremote e tutto funziona correttamente.