Robot con arduino

Salve,ho costruito questo robot ma sto avendo dei problemi.
il robot è cosi fatto

i problemi che sto avendo sono:

  1. per provarlo ho attaccato la batteria mentre era collegato al pc cosi da caricare il programma e poi poterlo staccare dal computer per provarlo con la batteria, ma quando metto su on l interruttore della robotshield e quindi la batteria inizia ad alimentarlo incomincia a non rispondere al programma e gira in tondo a velocità elevata e non risponde al programma (siccome uso un telecomando del dvd per controllarlo ipoteticamente con il comando stop dovrebbe fermarsi)
    2)il robot non procede a dritto ma tende a girare a sinistra o a destra a seconda se va avanti o indietro(quando lo provo con l alimentazione solo del computer e spesso non legge bene i comandi del telecomando. Potrebbero essere le pile scariche per i comandi? potrebbe essere che fa semplicemente schifo il telecomando?(non è nuovissimo, avrà 10 anni circa).

Attendo suggerimenti con ansia in quanto avrei deciso di proporlo come tesina per la maturità ma dopo le ultime prove sono scoraggiato…
Il robot è composto da una scheda arduino uno, una robotshield, una motorshield , 1 motoriduttore doppio , un ricevitore infrarossi sulla robotshield e un sonar sulla robotshield, alimentato da un pacco batterie da 9vx4
il codice del programma è questo

#include <IRremote.h>
#include <IRremoteInt.h>

//carica libreria IR 
int RECV_PIN = 10;
IRrecv irrecv(RECV_PIN);//imposta il pin di ricezione dei dati
decode_results results;
unsigned long code; // memorizza il codice ricevuto

//ai codici ricevuti aggiungere 0x + codice
#define UP      0x11//comando marcia avanti
#define KEY_UP    0xE246AFCA  //codice del tasto freccia su
#define DOWN  0x22 //comando marcia indietro
#define KEY_DOWN  0x3AFB26D4  //codice del tasto freccia giu
#define LEFT 0x33 //comando gira a sinistra
#define KEY_SX 0x4D43596A //codice del tasto freccia sinistra
#define RIGHT 0x44 //comando gira a destra
#define KEY_DX 0xBB0EDD22 //codice del tasto freccia destra
#define STOP 0x55 //Comando stop
#define KEY_STOP 0xB520CEC //codice del tasto STOP

//variabili usate dal sonar
#define ECHO 12 //arduino pin D12 -SRF04 pin 4
#define TRIG 11 //arduino pin D11-SRF04 pin 3
unsigned long echo_time = 0;//tempo di ritorno dell echo sonar in us
#define DISTANCE_CM echo_time / 48  //calcola la distanza in cm
unsigned long go_sonar = 0; //timer per accensione a tempo 
boolean obstacle = 0 ; // memorizza se è stato avvicinato un ostacolo
unsigned long max_distance = 30 ; // distanza massima a cui può avvicinarsi il robot

//variabili usate dai motori 
#define PIN_PWMA 5 //arduino pin D3 PWM motore A
#define PIN_DIRA 2 //arduino pin D2 comando direzione motore A
#define PIN_PWMB 9 //arduino pin D3 PWM motore B
#define PIN_DIRB 8 //arduino pin D2 comando direzione motore B
int velo_A = 0 ; // imposta velocità motore A
int velo_B = 0; //imposta velocità motore B
int dir_A = LOW ; // imposta la direzione del motore A
int dir_B= LOW ; // imposta la direzione motore B

void setup() {
  // put your setup code here, to run once:
  irrecv.enableIRIn();//attiva il ricevitore 
  pinMode(ECHO, INPUT); //arduino attiva ingresso
  pinMode (TRIG, OUTPUT); //arduino attiva uscita
  pinMode (13, OUTPUT); // arduino attiva uscita pin D13 led L
  pinMode (PIN_PWMA, OUTPUT); //arduino attiva uscita motore A
  pinMode (PIN_PWMB, OUTPUT); //arduino attiva uscita motore B
  pinMode (PIN_DIRA, OUTPUT); //arduino attiva uscita direzione A
  pinMode (PIN_DIRB, OUTPUT); //arduino attivs uscita direzione B
  Serial.begin(9600); // attiva la comunicazione seriale-USB
}

void loop() {
 
  //ricevi i segnali dal telecomando 
  if (irrecv.decode(&results)) { // stato ricevuto un comando
    digitalWrite(13, HIGH);// accende il led L di arduino
    if (results.value == KEY_UP) code = UP; //se premuto freccia SU
    if(results.value == KEY_DOWN) code = DOWN; //se premuto freccia GIU
    if(results.value == KEY_SX) code = LEFT;//se premuto freccia SINISTRA
    if(results.value == KEY_DX) code = RIGHT;//se premuto freccia DESTRA  
    if(results.value == KEY_STOP) code = STOP;// se premuto tasto STOP
    Serial.print(results.value, HEX);//invia alla seriale -USB il codice ricevuto
    Serial.print("   "); // invia 3 spazi
    Serial.println(code, HEX); // invia alla seriale-USB il tasto premuto
    irrecv.resume();// riceve il prossimo codice
    delay (5); //aspetta 5 ms
    digitalWrite (13, LOW); // spegne il led L di arduino
  }

  // misura la distanza con il sonar 
  delay(1); //conta fino ad 1ms
  if(go_sonar++ >= 250) {//attiva il sonar ogni 250 cicli del loop
    digitalWrite(TRIG, HIGH);//attiva l emissione sonar
    delayMicroseconds(10); //aspetta 10 us
    digitalWrite(TRIG, LOW);//termina l emissione sonar
    echo_time =pulseIn(ECHO, HIGH);//misura la durata dell echo
    if(DISTANCE_CM <= max_distance) obstacle = 1; //si è troppo vicini all ostacolo
    else obstacle = 0; //non si è in presenza di ostacoli
    if(obstacle) Serial.print("obstacle "); //scrivi in presenza di un ostacolo
    Serial.print("  distance  ");
    Serial.println(DISTANCE_CM); //stampa la distanza in centimetri
    go_sonar = 0; // azzera il timer
  }
code == STOP;
  //comanda i motori
  if(!obstacle) {//se non ci sono ostacoli muove il robot
    //se DIR_A= LOW allora led A verde// se DIR_B =HIGH allora led B rosso
    if(code == UP) { 
      velo_A = 280; 
      velo_B = 230; 
      dir_A =LOW; 
      dir_B =HIGH;
    }

    else if(code == DOWN) {
      velo_A = 250; 
      velo_B = 240; 
      dir_A =HIGH; 
      dir_B =LOW;
    }
    else if(code == LEFT) {
      velo_A = 250; 
      velo_B = 250; 
      dir_A =HIGH; 
      dir_B =HIGH;
    }
    else if(code == RIGHT) {
      velo_A = 250; 
      velo_B = 125; 
      dir_A =LOW; 
      dir_B =LOW;
    }
    else if(code == STOP) {
      velo_A = 0; 
      velo_B = 0; 
      dir_A =LOW; 
      dir_B =LOW;
    }
  }
  //altrimenti ferma il robot finche è presente l ostacolo
  else { 
    velo_A = 0; 
    velo_B = 0; 
    dir_A = LOW; 
    dir_B = LOW;
  }
  analogWrite(PIN_PWMA, velo_A);//imposta la velocità del motore A
  analogWrite(PIN_PWMB, velo_B);//imposta la velocità del motore B
  digitalWrite(PIN_DIRA, dir_A);//imposta la direzione del motore A
  digitalWrite(PIN_DIRB, dir_B); //imposta la direzione del motore B
}

Prima cosa, cosa vuol dire " pacco batterie da 9vx4" ? Che motori usi, link al prodotto. Peso del robot e diametro delle ruote ? In tutti i casi senza disporre di encoder su i motori puoi scordarti di andre diritto ed eseguire manovre precise, puoi andare quasi storto e con larga imprecisione sulle manovre :)

ho sbagliato :D è un pacco batterie con 4 slot e batterie da 1.5 volt il link dei motori è questo : http://www.futurashop.it/double-gearbox-7300-dgearbox il peso del robot è di circa 460 g le ruote sono di diametro 36mm per la velocità ,siccome sono nabbo, un encoder me lo posso procurare oppure è in dotazione con i motori in genere? nel caso senza velocità posso provare modulando la velocità tramite programma e cercare di farlo andare il piu possibile dritto?

Quei motori sono abbastanza fiacchi, non puoi collegarci un encoder in quanto non sono predisposti, con il PWM puoi modulare la velocità dei motori e devi trovare empiricamente un fattore di correzione per far andare più o meno dritto il robot. Con il controllo in anello aperto i due motori non gireranno mai alla stessa velocità a parità di PWM.

ok, per il problema di quando attacco la batteria? grazie per l aiuto :)

ho provato ieri per un po e ho avuto qualche miglioramento

il problema di quando attacco la batteria rimane e se qualcuno potesse spiegarmi il perche gli sarei grato

i motori non so per quale motivo si comportano in maniera diversa a seconda della direzione… presumevo che trovata la combinazione giusta di pwm per l avanti funzionasse anche per la retromarcia ma invece sembra essere diversa.
per ora sono riuscito a farlo andare piu o meno avanti modificando cosi il codice

#include <IRremote.h>
#include <IRremoteInt.h>

//carica libreria IR 
int RECV_PIN = 10;
IRrecv irrecv(RECV_PIN);//imposta il pin di ricezione dei dati
decode_results results;
unsigned long code; // memorizza il codice ricevuto

//ai codici ricevuti aggiungere 0x + codice
#define UP      0x11//comando marcia avanti
#define KEY_UP    0xE246AFCA  //codice del tasto freccia su
#define DOWN  0x22 //comando marcia indietro
#define KEY_DOWN  0x3AFB26D4  //codice del tasto freccia giu
#define LEFT 0x33 //comando gira a sinistra
#define KEY_SX 0x4D43596A //codice del tasto freccia sinistra
#define RIGHT 0x44 //comando gira a destra
#define KEY_DX 0xBB0EDD22 //codice del tasto freccia destra
#define STOP 0x55 //Comando stop
#define KEY_STOP 0xB520CEC //codice del tasto STOP

//variabili usate dal sonar
#define ECHO 12 //arduino pin D12 -SRF04 pin 4
#define TRIG 11 //arduino pin D11-SRF04 pin 3
unsigned long echo_time = 0;//tempo di ritorno dell echo sonar in us
#define DISTANCE_CM echo_time / 48  //calcola la distanza in cm
unsigned long go_sonar = 0; //timer per accensione a tempo 
boolean obstacle = 0 ; // memorizza se è stato avvicinato un ostacolo
unsigned long max_distance = 30 ; // distanza massima a cui può avvicinarsi il robot

//variabili usate dai motori 
int pwm_a = 3;
int pwm_b =9;
int dir_a =2;
int dir_b =8;
int velo_A = 0 ; // imposta velocità motore A
int velo_B = 0; //imposta velocità motore B
int dir_A = LOW ; // imposta la direzione del motore A
int dir_B= LOW ; // imposta la direzione motore B

void setup() {
  // put your setup code here, to run once:
  irrecv.enableIRIn();//attiva il ricevitore 
  pinMode(ECHO, INPUT); //arduino attiva ingresso
  pinMode (TRIG, OUTPUT); //arduino attiva uscita
  pinMode (13, OUTPUT); // arduino attiva uscita pin D13 led L
pinMode(pwm_a, OUTPUT);
pinMode(pwm_b, OUTPUT);
pinMode(dir_a, OUTPUT);
pinMode(dir_b, OUTPUT); 
  Serial.begin(9600); // attiva la comunicazione seriale-USB
}

void loop() {
 
  //ricevi i segnali dal telecomando 
  if (irrecv.decode(&results)) { // stato ricevuto un comando
    digitalWrite(13, HIGH);// accende il led L di arduino
    if (results.value == KEY_UP) code = UP; //se premuto freccia SU
    if(results.value == KEY_DOWN) code = DOWN; //se premuto freccia GIU
    if(results.value == KEY_SX) code = LEFT;//se premuto freccia SINISTRA
    if(results.value == KEY_DX) code = RIGHT;//se premuto freccia DESTRA  
    if(results.value == KEY_STOP) code = STOP;// se premuto tasto STOP
    Serial.print(results.value, HEX);//invia alla seriale -USB il codice ricevuto
    Serial.print("   "); // invia 3 spazi
    Serial.println(code, HEX); // invia alla seriale-USB il tasto premuto
    irrecv.resume();// riceve il prossimo codice
    delay (5); //aspetta 5 ms
    digitalWrite (13, LOW); // spegne il led L di arduino
  }

  // misura la distanza con il sonar 
  delay(1); //conta fino ad 1ms
  if(go_sonar++ >= 250) {//attiva il sonar ogni 250 cicli del loop
    digitalWrite(TRIG, HIGH);//attiva l emissione sonar
    delayMicroseconds(10); //aspetta 10 us
    digitalWrite(TRIG, LOW);//termina l emissione sonar
    echo_time =pulseIn(ECHO, HIGH);//misura la durata dell echo
    if(DISTANCE_CM <= max_distance) obstacle = 1; //si è troppo vicini all ostacolo
    else obstacle = 0; //non si è in presenza di ostacoli
    if(obstacle) Serial.print("obstacle "); //scrivi in presenza di un ostacolo
    Serial.print("  distance  ");
    Serial.println(DISTANCE_CM); //stampa la distanza in centimetri
    go_sonar = 0; // azzera il timer
  }
code == STOP;
  //comanda i motori
  if(!obstacle) {//se non ci sono ostacoli muove il robot
    //se DIR_A= LOW allora led A verde// se DIR_B =HIGH allora led B rosso
    if(code == UP) { 
   digitalWrite(dir_a, HIGH); //motore A avanti
digitalWrite(dir_b, HIGH); // motore B avanti
analogWrite(pwm_a,145); //imposta la velocità a metà
analogWrite(pwm_b,250);     
    }

    else if(code == DOWN) {
        digitalWrite(dir_a, LOW); //motore A indietro
digitalWrite(dir_b, LOW); // motore B indietro
analogWrite(pwm_a, 250); // imposta la velocità a metà
analogWrite(pwm_b, 210);
    }
    else if(code == LEFT) {
      digitalWrite(dir_a, HIGH); //motore A indietro
digitalWrite(dir_b, LOW); // motore B indietro
analogWrite(pwm_a, 150); // imposta la velocità a metà
analogWrite(pwm_b, 100);
    }
    else if(code == RIGHT) {
      digitalWrite(dir_a, LOW); //motore A indietro
digitalWrite(dir_b, LOW); // motore B indietro
analogWrite(pwm_a, 150); // imposta la velocità a metà
analogWrite(pwm_b, 210);
    }
    else if(code == STOP) {
digitalWrite(dir_a, LOW); //motore A indietro
digitalWrite(dir_b, LOW); // motore B indietro
analogWrite(pwm_a, 0); // imposta la velocità a metà
analogWrite(pwm_b, 0);
    }
  }
  //altrimenti ferma il robot finche è presente l ostacolo
  else { 
   digitalWrite(dir_a, LOW); //motore A indietro
digitalWrite(dir_b, LOW); // motore B indietro
analogWrite(pwm_a, 0); // imposta la velocità a metà
analogWrite(pwm_b, 0);
  }

}

up

up

aiuto

Ma che problema ha la batteria? E comunque, dove la colleghi ?

Il problema della batteria è che quando faccio partire l alimentazione il robot comincia a andare a caso e non risponde al programma.

ho risolto con le batterie. ora il problema è che quando carico il programma il motore di sinistra non riceve tensione e di conseguenza non va. ho provato i motori indipendentemente (alimentandoli) e funzionano perfettamente. Poi ho provato con un programma indipendente dalla robotshield che sostanzialmente impone ai motori di andare avanti e indietro con un delay di 3 secondi e questi andavano.... in questo caso staccando la connessione con il computer e collegando le batterie i motori rispettavano i tempi di delay del programma e entrambi funzionavano. Quindi quando uso il programma con il ricevitore a infrarossi che deve muoversi rispondendo ai comandi del telecomando il motore di sinistra non va. Di conseguenza dovrebbe esserci un errore nel codice per cui il motore di sinistra non riceve alcun ordine dal telecomando, eppure io non vedo nessun errore.

Aiutatemi vi supplico sono disperato .... visto che tra 2 giorni devo presentarlo alla commissione e vorrei che funzionasse.... visto che ipoteticamente dovrebbe

aiuto aiuto aiuto aiuto aiutooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo

La libreria IRremote usa il timer2 del microcontrollore. Addio pwm sul pin digitale 3 dove c'è il motore