Autopilotaggio di un rover...

Ciao, ho riscritto lo sketch per la gestione del rover da remoto (tramite un modulo bloetooth). Le funzioni sono 2:

  • Controllo remoto tramite gamepad o tastiera (ricordo che uno una interfaccia scritta da me in Visual C#).
  • Avvio dell'autopilota, in pratica il rover si muovi in avanti e tramite un sensore a ultrasuoni Parallax rileva eventuali ostacoli.

PROBLEMA: Nella gestione dell'autopilota, quando eseguo una lettura dal sensore, occorre dare un piccolo ritardo in modo che il controller interpreti il dato prima di passare all'istruzione successiva, ciò fa si che il rover proceda a scatti, dato che quando il controller elabora il dato, i motori si fermano.

Posto il codice:

#include  // Inclusione della classe Servo.h per la gestione del servomotore

// Variabili per il controllo dei motori
int E1 = 5; // Velocità motori a sinistra
int E2 = 6; // Velocità motori a destra
int M1 = 4; // Direzione motori a sinistra
int M2 = 7; // Direzione motori e destra

// Gestione servo
Servo servo; // Il servo lavora sul pin 9

const int pingPin = 7; // Settaggio del PIN a cui è connesso il sensore a ultrasuoni
long distanza;

void fermi(void) // Fermo il rover
{
  digitalWrite(E1,LOW); // Motori a sinistra fermi
  digitalWrite(E2,LOW); // Motori a destra fermi
}

void indietro(char a, char b) // Mando il rover indietro
{
  analogWrite(E1,a); // Muovo i motori di sinistra passndo la velocità "a"
  digitalWrite(M1,HIGH); // La direzione dei motori di sinistra è "avanti"
  analogWrite(E2,b); // Muovo i motori di destra passando la velocità "b"
  digitalWrite(M2,HIGH); // La direzione dei motori di destra è "avanti"
}

void avanti(char a, char b) //Mando il rover avanti
{
  analogWrite(E1,a); // Muovo i motori di sinistra passndo la velocità "a"
  digitalWrite(M1,LOW); // La direzione dei motori di sinistra è "indietro"
  analogWrite(E2,b); // Muovo i motori di destra passando la velocità "b"
  digitalWrite(M2,LOW); // La direzione dei motori di destra è "indietro"
}

void sinistra(char a, char b) // Mando il rover a sinistra
{
  analogWrite(E1,a); // Muovo i motori di sinistra passndo la velocità "a"
  digitalWrite(M1,LOW); // La direzione dei motori di sinistra è "indietro"
  analogWrite(E2,b); // Muovo i motori di destra passando la velocità "b"
  digitalWrite(M2,HIGH); // La direzione dei motori di destra è "avanti"
}

void destra(char a, char b) // Mando il rover a destra
{
  analogWrite(E1,a); // Muovo i motori di sinistra passndo la velocità "a"
  digitalWrite(M1,HIGH); // La direzione dei motori di sinistra è "avanti"
  analogWrite(E2,b); // Muovo i motori di destra passando la velocità "b"
  digitalWrite(M2,LOW); // La direzione dei motori di destra è "indietro"
} 

long RilevaDistanza () // Rilevazione della distanza in cm
{
  long durata, distanzaCm;
  
  // Rilevazione della distanza
  pinMode(pingPin, OUTPUT);
  digitalWrite(pingPin, LOW);
  delayMicroseconds(2);
  digitalWrite(pingPin, HIGH);
  delayMicroseconds(5);
  digitalWrite(pingPin, LOW);
  
  pinMode(pingPin, INPUT);
  durata = pulseIn(pingPin, HIGH);
  
  // Calcolo della distanza
  distanzaCm = durata / 29 / 2;
  
  return distanzaCm;
}

void setup(void)
{
  Serial.begin(9600); // Avvio la comunicazione seriale 19200
  
  // Configuro i pin: 4, 5, 6 e 7 in output
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);
  
  // Configurazione del servo
  servo.attach(9);
  
  servo.write(90);
}

void loop()
{
  if (Serial.available()) // Controllo se ci sono dati sulla porta seriale
  {
    char valore = Serial.read(); // Leggo il valore passato
    if (valore != -1)
    {
      switch (valore) // Controllo il valore letto e mi comporto di conseguenza
      {
        // Controllo remoto
        case 'a': // Avanti
          avanti (255, 255); 
        break;
        case 'i': // Indietro
          indietro (255, 255);
        break;
        case 's': // Sinistra
          sinistra (255, 255);
        break;
        case 'd': // Destra
          destra (255, 255);
        break;
        case 'f': // Fermo i motori
          fermi();
        break;
        //----------------------------------------
        // Autopilota
        case 'y': // Avvio dell'autopilota
          while (valore != 'n')
          {
            distanza = RilevaDistanza();
            delay(100);
            if (distanza < 25)
            {
              fermi();
            }
            else
            {
              avanti (255, 255);
            }
          }  
        break;
      }  
    }  
    else
       fermi(); // Fermo i motori   
  }
  Serial.flush(); // Pulisco il buffer della porta seriale
}

La parte che riguarda l'autopilota è la seguente:

// Autopilota
        case 'y': // Avvio dell'autopilota
          while (valore != 'n')
          {
            distanza = RilevaDistanza();
            delay(100);
            if (distanza < 25)
            {
              fermi();
            }
            else
            {
              avanti (255, 255);
            }
          }  
        break;

Suggerimenti? Grazie!

Devi togliere il delay che blocca il codice e sostituirlo con un controllo basato su millis.

Apparentemente sembra un problema legato alla distanza rilevata dal sensore. Aumentando o eliminando del tutto il ritardo, ad un certo punto viene rilevato un oggetto anche se questo non è presente...

Il codice implementato è il seguente:

// Autopilota
        case 'y': // Avvio dell'autopilota
          while (valore != 'n')
          {
            valore = Serial.read(); // Leggo dalla porta seriale
            
            distanza = RilevaDistanza(); // Rilevo la distanza
                        
            if (distanza > 25) 
            {
              avanti(255, 255);            
            }   
            else
            {
              fermi();
            }
            
            //Serial.flush(); // Pulisco il buffer della porta seriale
          }  
        break;

Quello relativo alla lettura del sensore è questo:

long RilevaDistanza () // Rilevazione della distanza in cm
{
  long durata, distanzaCm;
  
  // Rilevazione della distanza
  pinMode(pingPin, OUTPUT);
  digitalWrite(pingPin, LOW);
  delayMicroseconds(2); 
  digitalWrite(pingPin, HIGH);
  delayMicroseconds(5); 
  digitalWrite(pingPin, LOW);
  
  pinMode(pingPin, INPUT);
  durata = pulseIn(pingPin, HIGH);
  
  // Calcolo della distanza
  distanzaCm = durata / 29 / 2;
   
  return distanzaCm;
}

Sto cercando di capire per quale motivo il sensore restituisca un valore non corretto. Lo ho testato con un altro programma fatto da me e funziona...

Su come può operare il tuo sensore non so aiutarti

Se il sensore é un SRF05 http://communityofrobots.com/tutorial/kawal/srf05-ultrasonic-sensor-and-arduino Ciao Uwe

A quanto pare il problema era hardware. In pratica il sensore è connesso sul pin come un servo (sig, vcc, gnd), ad un certo punto ho avuto il sospetto che non avesse una alimentazione adeguata e per questo motivo certe letture non andavano a buon fine, il valore restituito era 0 e quindi il rover di fermava. Così, ho connesso un’altra batteria (da 9v) all’alimentazione destinata ai servi e a quel punto il funzionamento è stato corretto.

Come detto in passato, il mio campo è la programmazione, devo fare la mano su tutti i problemi legati all’hw…