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);
}
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
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"
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 ...
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.