Ciao a tutti, vi scrivo per sottoporre alla vostra attenzione due problemi che sto riscontrando con un progetto arduino.
Ho costruito un robot car utilizzando i seguenti componenti:
-scocca con 4 motori duttori completi di ruote gommate con diametro 65 mm.
-Telecomando ir con ricevitore VS1838..
-driver l298 per i motori delle ruote.
-Arduino 1 compatibile.
-scheda sensor shield per arduino.
-2 motori servo SG90 con supporto pan tilt.
-scheda sensore ad ultrasuoni HC-SR04
-modulo led rgb
-buzzer.
Il programma che ho scritto è composto sostanzialmente di 6 funzioni attivabili con il telecomando ir. Nello sketch vi sono altre funzioni utili al sensore ultrasuono che calcola la distanza ed un’altra relativa al ricevitore ir.
Con il telecomando posso mandare il robot avanti, indietro, a destra, a sinistra, posso fermare i motori, ed in fine posso attivare la guida autonoma in cui il robot naviga evitando gli ostacoli.
Nello sketch è presente una funzione chiamata Telecomandata dove sono presenti varie if che attivano le varie funzioni alla pressione dei tasti del telecomando. Qui troverete dei numeri lunghissimi che sono quelli restituiti sul monitor seriale dal ricevitore alla pressione dei singoli tasti. Ho mappato tutto il telecomando tasto per tasto, vedrete che ad ogni pulsante ho impostato nella sua relativa if due numeri lunghi, questo perchè in fase di mappatura dei pulsanti restituiva un doppio valore in modo alternato.
Nel loop richiamo la funzione Telecomandata.
Fatte tutte queste doverose premesse vengo ai due problemi riscontrati.
Faccio presente che non ho problemi di compilazione, il software viene digerito bene dall’ide.
Problema 1:
Se nel setup inserisco un suono di avvio con la seguente scrittura, quando premo i pulsanti del telecomando il robot non fa nulla.
“tone(buzzer,300,200); delay(400); tone(buzzer,300,200); delay(400); noTone(buzzer);”
Con questa scrittura il robot suona all’avvio facendo due beep alla fine dell’inizializzazione del setup, ma poi non riceve più comandi.
Non riesco a risolvere in nessun modo e non capisco dove possa esser il problema, stupidamente ho tentato anche di cambiare il pin del buzzer ma non è cambiato nulla, prinma era sul pin 2 ed ora l’ho messo sul pin 17 utilizzando un pin analogico come digitale.
Problema 2:
Non utilizzando il buzzer che crea l’anomalia, il robot funziona perfettamente tranne per una situazione specifica.
Come dicevo sopra, nel loop ho la funzione Telecomandata che mi permette di attivare i vari programmi. Bene essi funzionano tutti tranne la funzione di guida autonoma. Quando premo il pulsante 2, il robot entra in modalità guida autonoma accedendo alla funzione chiamata automatica.
Non appena rileva un ostacolo il sensore ruota a destra e sinistra per trovare la via di fuga ma invece di fare le manovre per evitare l’ostacolo esce dalla funzione e si blocca.
Attenzione, faccio presente che la funzione automatica è ben programmata, per testarla ho fatto questa prova:
Sono entrato nel loop ed ho rimosso la chiamata alla funzione Telecomandata ed ho chiamato la funzione Automatica, questo per bypassare il telecomando. Bene, ricaricando lo sketch su arduino, il robot gira per casa evitando tutti gli ostacoli e non si blocca mai.
Non riesco proprio a capire perchè entrando nella funzione con il telecomando si blocca al rilevamento ostacoli mentre direttamente funziona in maniera perfetta.
La questione del buzzer mi lascia anch’essa perplesso, il compilatore non da errore, che vi sia qualche conflitto software tra il ricevitore ir ed un semplicissimo altoparlantino?
Accetto suggerimenti d’ogni tipo.
Grazie mille…
lo sketch:
/*
appunti assemblaggio:
Il sensore ultrasuono è connesso con la porta triger al pin a4 e la echo al pin a5, ma sto usando queste porte analogiche come digitali.
I motori delle ruote sono collegati a coppia ai pin digitali pwm, rispettivamente ai pin 11, 10 per le ruote di sinistra e, 6 e 5 per le ruote di destra.
(attenzione! se aziono contemporaneamente motorPin1 e motorPin3 il robot va in avanti, se invece attivo motorPin2 e motorPin4 va indietro. *
Il motore servo che fa il movimento pan è connesso al pin digitale 9, mentre quelllo che fa il movimento tilt è al pin digitale 3.
il ricevitore ir del telecomando è un VS1838 ed è connesso al pin digitale 4. Il ricevitore l'ho connesso con una resistenza da 100 ohm sulla linea del positivo ed una resistenza di pull up da 10 kohm tra il pin dati e quello dell'alimentazione.
(la libreria ir necessita di un pin pwm nel caso in cui il ricevitore dovesse trasmettere. ).
*/
#include <IRremote.h>
//librerie ricevitore ir
#include <Servo.h>
//libreria servo motore
int triggerPort = 18;
int echoPort = 19;
// pin ai quali sono connessi il sensore ultrasuono.
int RECV_PIN = 4;
IRrecv irrecv(RECV_PIN);
decode_results results;
//pin del sensore ir e variabili.
int ledblu = 13;
int ledred = 12;
int ledgreen = 8;
// modulo rgb
int velocitamotore = 255;
//assegno alla variabile velocitamotore il valore pwm delle ruote motrici che regoleranno appunto la velocità delle stesse.
Servo myservo;
// assegno il nome myservo al motore servo che fa il movimento pan.
Servo servotilt;
// assegno il nome al motore servo che fa il movimento tilt.
const int motorPin1 = 11;
const int motorPin2 = 10;
//Ruote motrici di sinistra.
const int motorPin3 = 6;
const int motorPin4 = 5;
// Ruote motrici di destra.
int buzzer = 17;
void setup() {
Serial.begin(9600);
irrecv.enableIRIn();
pinMode( triggerPort, OUTPUT );
pinMode( echoPort, INPUT );
pinMode(ledblu, OUTPUT);
pinMode(ledred, OUTPUT);
pinMode(ledgreen, OUTPUT);
pinMode(buzzer, OUTPUT);
// inizializzo la porta seriale a 9600 baud e avvio il ricevitore ir. Dichiaro la modalità dei pin.
myservo.attach(9);
myservo.write(99);
// dichiaro il pin al quale è connesso il motore servo pan e lo posiziono a 99 grad che è la posizione centrale.
servotilt.attach(3);
servotilt.write(60);
// dichiaro il pin al quale è connesso il motore servo che fa il movimenti tilt e lo posiziono a 60 gradi che è la posizione in cui è dritto davanti perpendicolare alla linea di terra..
rgbavviosetup();
//richiamo la funzione rgb di avvio
} void loop() {
if (irrecv.decode(&results)) {
Serial.println(results.value, DEC); dump(&results);
irrecv.resume(); // Receive the next value
delay(200);
}
/* richiamo la funzione telecomandata che permette di guidare il robot con le frecce direzionali e che fa fermare i motori con il tasto ok. Se premo il tasto 2 passo alla modalità guida autonoma. */
Telecomandata();
}
// creo la funzione che ferma le ruote motrici.
void Stop() {
analogWrite(motorPin1, 0);
analogWrite(motorPin2, 0);
analogWrite(motorPin3, 0);
analogWrite(motorPin4, 0);
}
// creo la funzione che manda avanti le ruote motrici.
void Avanti() {
analogWrite(motorPin1, velocitamotore);
analogWrite(motorPin2, 0);
analogWrite(motorPin3, velocitamotore);
analogWrite(motorPin4, 0);
}
// creo la funzione che manda le ruote motrici indietro.
void Indietro() {
analogWrite(motorPin1, 0);
analogWrite(motorPin2, velocitamotore);
analogWrite(motorPin3, 0);
analogWrite(motorPin4, velocitamotore);
}
// creo la funzione che fa girare il robot a destra quando è in modalità guida autonoma.
void Destra() {
analogWrite(motorPin1, velocitamotore);
analogWrite(motorPin2, 0);
analogWrite(motorPin3, 0);
analogWrite(motorPin4, velocitamotore);
delay(300);
Avanti();
}
// creo la funzione che fa girare il robot a sinistra quando è in modalità guida autonoma.
void Sinistra() {
analogWrite(motorPin1, 0);
analogWrite(motorPin2, velocitamotore);
analogWrite(motorPin3, velocitamotore);
analogWrite(motorPin4, 0);
delay(300);
Avanti();
}
// creo la funzione che fa girare il robot a destra in modalità telecomandata.
void Destratelecomandata() {
analogWrite(motorPin1, velocitamotore);
analogWrite(motorPin2, 0);
analogWrite(motorPin3, 0);
analogWrite(motorPin4, velocitamotore);
}
// creo la funzione che fa girare il robot a sinistra in modalità telecomandata.
void Sinistratelecomandata() {
analogWrite(motorPin1, 0);
analogWrite(motorPin2, velocitamotore);
analogWrite(motorPin3, velocitamotore);
analogWrite(motorPin4, 0);
}
//Creo la funzione che manda avanti il robot in maniera che se rileva un ostacolo nella guida manuale ferma automaticamente i motori
void Avantiprotetta() {
myservo.write(99);
digitalWrite( triggerPort, LOW );
//invia un impulso di 10microsec su trigger
digitalWrite( triggerPort, HIGH );
delayMicroseconds( 10 );
digitalWrite( triggerPort, LOW );
long duration = pulseIn( echoPort, HIGH );
long r = 0.034 * duration / 2;
if (r <= 30) {
Stop();
}
else Avanti();
}
// creo la funzione misura che rileva la distanza dell'ostacolo.
int misura() {
digitalWrite( triggerPort, LOW );
//invia un impulso di 10microsec su trigger
digitalWrite( triggerPort, HIGH );
delayMicroseconds( 10 );
digitalWrite( triggerPort, LOW );
long duration = pulseIn( echoPort, HIGH );
long r = 0.034 * duration / 2;
}
// creo la funzione che fa ruotare verso destra il motore servo pan e misura la distanza dell'eventuale ostacolo restituendo il valore della misurazione.
int guardadestra()
{
myservo.write(30);
delay(200);
int distanza = misura();
delay(100);
myservo.write(99);
return distanza;
}
// creo la funzione che fa ruotare verso sinistra il motore servo pan e misura la distanza dell'eventuale ostacolo restituendo il valore della misurazione.
int guardasinistra()
{
myservo.write(150);
delay(200);
int distanza = misura();
delay(100);
myservo.write(99);
return distanza;
delay(100);
}
// creo la funzione che fa andare in automatico il robot.
void Automatica ( ) {
// creo due variabili per la distanza di ostacoli a destra ed a sinistra assegnando temporaneamente il valore 0.
int distanzadestra = 0;
int distanzasinistra = 0;
//porta bassa l'uscita del trigger
digitalWrite( triggerPort, LOW );
//invia un impulso di 10microsec su trigger
digitalWrite( triggerPort, HIGH );
delayMicroseconds( 10 );
digitalWrite( triggerPort, LOW );
long duration = pulseIn( echoPort, HIGH );
long r = 0.034 * duration / 2;
// calcoli per rilevare la distanza con il sensore ultrasuoni hcsr04.
if (r <= 30)
{
Stop();
delay(100);
Indietro();
delay(300);
Stop();
delay(200);
distanzadestra = guardadestra();
delay(200);
distanzasinistra = guardasinistra();
delay(200);
// Ho assegnato alle due variabili le rispoettive funzioni che fanno rilevare gli ostacoli a destra ed a sinistra.
if (distanzadestra >= distanzasinistra)
{
Destra();
Stop();
}
else
{
Sinistra();
Stop();
}
} else
{
Avanti();
}
}
//creo la funzione che permette di telecomandare il robot.
void Telecomandata ( ) {
int debauncingtelecomando = 200;
if (results.value == 16718055 or results.value == 1033561079) {
Avantiprotetta();
delay(debauncingtelecomando);
}
else if (results.value == 1217346747 or results.value == 16726215) {
Stop();
delay(debauncingtelecomando);
}
else if (results.value == 71952287 or results.value == 16734885) {
Destratelecomandata();
delay(debauncingtelecomando);
}
else if (results.value == 3431610115 or results.value == 16716015) {
Sinistratelecomandata();
delay(debauncingtelecomando);
}
else if (results.value == 465573243 or results.value == 16730805) {
Indietro();
delay(debauncingtelecomando);
}
// se premo il tasto 2 del telecomando attiva la funzione automatica.
else if (results.value == 16736925 or results.value == 5316027) {
Automatica();
delay(debauncingtelecomando);
}
}
void rgbavviosetup () {
digitalWrite(ledblu, HIGH); delay(1000); digitalWrite(ledblu, LOW);
digitalWrite(ledred, HIGH); delay(1000); digitalWrite(ledred, LOW);
digitalWrite(ledgreen, HIGH); delay(1000); digitalWrite(ledgreen, LOW); delay(1000);
}
// funzione ricevitore ir
//Dumps the result and prints the numeric received dada and type of remote
void dump(decode_results *results) {
// Dumps out the decode_results structure.
// Call this after IRrecv::decode()
int count = results->rawlen;
if (results->decode_type == UNKNOWN) {
Serial.print("Unknown encoding: ");
}
else if (results->decode_type == NEC) {
Serial.print("Decoded NEC: ");
}
else if (results->decode_type == SONY) {
Serial.print("Decoded SONY: ");
}
else if (results->decode_type == RC5) {
Serial.print("Decoded RC5: ");
}
else if (results->decode_type == RC6) {
Serial.print("Decoded RC6: ");
}
else if (results->decode_type == PANASONIC) {
Serial.print("Decoded PANASONIC - Address: ");
Serial.print(results->address, HEX);
Serial.print(" Value: ");
}
else if (results->decode_type == LG) {
Serial.print("Decoded LG: ");
}
else if (results->decode_type == JVC) {
Serial.print("Decoded JVC: ");
}
else if (results->decode_type == WHYNTER) {
Serial.print("Decoded Whynter: ");
}
Serial.print(results->value, HEX);
Serial.print(" (");
Serial.print(results->bits, DEC);
Serial.println(" bits)");
Serial.print("Raw (");
Serial.print(count, DEC);
Serial.print("): ");
for (int i = 1; i < count; i++) {
if (i & 1) {
Serial.print(results->rawbuf[i]*USECPERTICK, DEC);
}
else {
Serial.write('-');
Serial.print((unsigned long) results->rawbuf[i]*USECPERTICK, DEC);
}
Serial.print(" ");
}
Serial.println();
}