Questo progetto mostra le potenzialità di Arduino. Esso è stato presentato come tesina d’esame al mio esame di maturità.

Materiali utilizzati

Elettronica:

Struttura:

  • Barre metallo 12x12mm, foro 10x10mm
  • Lastre plexiglas spessore 2mm
  • Stampe 3D (PLA) con la stampante Prusa i3
  • Jumper e cavi
  • Viteria varia

Realizzazione

Meccanica

Dal punto di vista della meccanica il rover è stato progettato affinché possa superare ostacoli proporzionali alla propria grandezza (5 centimetri se inclinazione ostacolo 100%) al fine di esplorare agevolmente su diversi tipi di terreno. Il corpo è rialzato e il sistema di sospensioni è il rocker bogie.

Il corpo del rover è stato pensato per essere semplice e rappresentare l’idea dell’ ‘’open source’’, Vi è infatti un telaio metallico atto a garantire rigidità, mentre la carrozzeria è trasparente in modo da dare la possibilità di osservare i componenti elettronici. Sul corpo è collegato con un piccolo asse il bilanciere che garantisce equilibrio al corpo in relazione all’inclinazione delle sospensioni.

Il sistema rocker bogie impone l’uso di un motore elettrico per ruota per garantire la trazione integrale poiché risulterebbe più dispendioso avere assi di trasmissione e differenziali distributori di coppia lungo i bracci del rocker bogie dunque per il movimento sono utilizzati 6 motori elettrici DC, in particolare Motoriduttore L149.12.90

Per lo sterzo è stata garantita la possibilità che il rover si muova agevolmente con raggio di sterzo tendente a zero; infatti sono stati utilizzati 4 servo motori HS-422 Deluxe Standard Servo che garantiscono lo sterzo alle 2 ruote anteriori ed alle 2 posteriori. Esse ruotando di circa 45 gradi ed utilizzando marcia inversa tra quelle di destra e quelle di sinistra garantiscono uno sterzo circolare, con il corpo che rimane al centro della circonferenza descritta dalle 4 ruote ai vertici. Tutto il sistema è controllato elettronicamente dal processore dell’Arduino Mega il quale consente inoltre di regolare la traiettoria del mezzo in marcia.

Le ruote hanno un battistrada di 55 millimetri, tale larghezza offre ampia superficie di appoggio ed evita affondamenti su suoli sabbiosi poiché distribuisce il peso esercitando meno pressione su un singolo punto (Pressione = F/S), inoltre sono dotate di sistema di smaltimento di materiale sabbioso (materiale largamente presente sul suolo del pianeta rosso), favorito dalla conformazione elicoidale dei raggi delle ruote la quale tende a far defluire il materiale depositato nella ruota sempre nello stesso senso, ciò comporta la fuoriuscita del materiale sabbioso dai fori sopracitati.

La testa del rover garantisce la possibilità di visualizzare il territorio con invio di immagini e visualizzazione video da monitor in tempo reale di ciò che si presenta intorno al rover nelle sue esplorazioni. La testa è costituita da due alloggiamenti che garantiscono due gradi di libertà, nel primo vi è collocato il servo motore che garantisce il movimento della telecamera trasversale al terreno, nel secondo è collocata la telecamera. I due gradi di libertà sono garantiti da due servo motori TowerPro SG90 Servo, uno posto al di sotto della superficie del corpo centrale, l’altro posto su una delle due parti che compongono la testa vera e propria.

Informatica ed elettronica

Il modello presentato monta tecnologie ispirate a quelle realmente montate sui rover:

  • Telecamera wireless con ricevitore AV esterno, ad emulazione della Pancam. Il movimento della camera è affidato a due microservo, i quali consentono una visione a 360° dell’ambiente circostante. La telecamera trasmette in tempo reale.
  • Sensori di prossimità (HB-SR04) (2x) nella parte anteriore ad emulazione dell’Hazcam anteriore. Il funzionamento di tali sensori è però differente: sfruttano gli ultrasuoni per poter rilevare gli ostacoli. Sono stati inseriti per sviluppare un primitivo sistema di autoguida (WIP).
  • Servomotori (4x) ad emulazione del sistema di sterzata.
  • Motoriduttori (6x) per consentire il movimento.

I due modelli di Arduino impiegati sono connessi tramite protocollo I2C con un rapporto di master (Mega) e slave (Uno). L’I2C è un protocollo che mette in comunicazione le due schede di programmazione mediante 3 jumper (cavi): un ground (GND) comune, il pin A4 (SDA) di Uno con il pin SDA di Mega ed il pin A5 (SCL) di Uno con il pin SCL di Mega. Il pin SDA (Serial DAta) serve a scambiare dati tra le due schede, mentre il pin SCL (Serial CLock) per sincronizzarne i clock. Funziona tramite la libreria Wire.h tramite comandi quali “read()” e “write()” e riesce a trasmettere e ricevere fino ad 8 bit a pacchetto (128 diverse combinazioni di numeri). Tale connessione è risultata necessaria per via dell’esigenza di controllare 6 motori in modo indipendente, ma non esiste alcuna motor shield in grado di gestirne tanti.

I comandi di input vengono invece impartiti al master attraverso il Onesheeld, uno shield bluetooth in grado di comunicare con il proprio smartphone attraverso l’apposita app. Di tale app viene sfruttata la scheda “gamepad”, attraverso la quale vengono impartiti gli ordini ai servomotori e ai motoriduttori.

Codice

E’ possibile scaricare i programmi del progetto direttamente dalla mia cartella Onedrive:

MASTER

//Sviluppa if(2 pulsanti premuti) > switch tra autopilot e comandi

/*
   Up;     #7     Motori
   Right;  #6
   Down;   #5
   Left;   #4

   Yellow; #10    Camera
   Red;    #9
   Green;  #8
   Blue;   #2

   ????;   #1

   Stop;   #0
*/

#define CUSTOM_SETTINGS
#define INCLUDE_GAMEPAD_SHIELD

#include <Wire.h>
#include <Servo.h>
#include <OneSheeld.h>

Servo servoAntSx;
Servo servoAntDx;
Servo servoPostSx;
Servo servoPostDx;


int pwmA = 3;
int dirA = 12;

int pwmB = 11;
int dirB = 13;

byte x;

void setup()
{
  Wire.begin(); // join i2c bus (address optional for master)
  Serial.begin(9600);

  pinMode(10, INPUT);
  pinMode(9, INPUT);
  pinMode(8, INPUT);
  pinMode(7, INPUT);
  pinMode(6, INPUT);
  pinMode(5, INPUT);
  pinMode(4, INPUT);
  pinMode(2, INPUT);

  pinMode(pwmA, OUTPUT);
  pinMode(dirA, OUTPUT);

  pinMode(pwmB, OUTPUT);
  pinMode(dirB, OUTPUT);

  servoAntSx.attach(23);
  servoAntDx.attach(25);
  servoPostSx.attach(27);
  servoPostDx.attach(29);

  servoAntSx.write(90);
  servoAntDx.write(90);
  servoPostSx.write(90);
  servoPostDx.write(90);

  delay(200);
}

void loop()
{
  //MOTORI
  if (digitalRead(4))          // Left
  {
    left();
  }
  else if (digitalRead(6))        // Right
  {
    right();
  }
  else if (digitalRead(7))      // Up
  {
    up();
  }
  else if (digitalRead(5))    // Down
  {
    down();
  }

  //      CAMERA
  else if (digitalRead(9)) // Red (Right)
  {
    x = 9;
  }
  else if (digitalRead(2)) // Blue (Left)
  {
    x = 2;
  }
  else if (digitalRead(8)) // Green(down)
  {
    x = 8;
  }
  else if (digitalRead(10)) // Yellow(up)
  {
    x = 10;
  }
  else
  {
    stopMotor();
  }


  Wire.beginTransmission(4); // transmit to device #4
  Wire.write(x);              // sends one byte
  Wire.endTransmission();    // stop transmitting

  Serial.println(x);
  delay(500);
}

//VOID SINGOLI
//MOTORI
void left()
{
  x = 4;
  servoAntSx.write(45);
  servoAntDx.write(135);
  servoPostSx.write(135);
  servoPostDx.write(45);

  digitalWrite(dirA, HIGH);
  analogWrite(pwmA, 1023);

  digitalWrite(dirB, HIGH);
  analogWrite(pwmB, 1023);
}

void right()
{
  x = 6;

  servoAntSx.write(45);
  servoAntDx.write(135);
  servoPostSx.write(135);
  servoPostDx.write(45);

  digitalWrite(dirA, LOW);
  analogWrite(pwmA, 1023);

  digitalWrite(dirB, LOW);
  analogWrite(pwmB, 1023);
}

void up()
{
  x = 7;

  servoAntSx.write(90);
  servoAntDx.write(90);
  servoPostSx.write(90);
  servoPostDx.write(90);

  digitalWrite(dirA, HIGH);
  analogWrite(pwmA, 1023);

  digitalWrite(dirB, LOW);
  analogWrite(pwmB, 1023);
}

void down()
{
  x = 5;

  servoAntSx.write(90);
  servoAntDx.write(90);
  servoPostSx.write(90);
  servoPostDx.write(90);

  digitalWrite(dirA, LOW);
  analogWrite(pwmA, 1023);

  digitalWrite(dirB, HIGH);
  analogWrite(pwmB, 1023);
}

void stopMotor()
{
  x = 0;                // Stop

  servoAntSx.write(90);
  servoAntDx.write(90);
  servoPostSx.write(90);
  servoPostDx.write(90);

  digitalWrite(dirA, HIGH);
  analogWrite(pwmA, 0);

  digitalWrite(dirB, HIGH);
  analogWrite(pwmB, 0);
}

SLAVE

//SLAVE

#include <Wire.h>
#include <Servo.h>
#include <Adafruit_MotorShield.h>
#include "utility/Adafruit_PWMServoDriver.h"

Adafruit_MotorShield AFMS = Adafruit_MotorShield();

Adafruit_DCMotor *M1 = AFMS.getMotor(1);
Adafruit_DCMotor *M2 = AFMS.getMotor(2);
Adafruit_DCMotor *M3 = AFMS.getMotor(3);
Adafruit_DCMotor *M4 = AFMS.getMotor(4);

Servo servoUp;    //attacca al pin 9
Servo servoDown;  //attacca al pin 10

int asseX = 90;
int asseY = 90;

int x;

int timer = 1;
int spaziatura = 5;

void setup()
{
  AFMS.begin();

  M1->setSpeed(1023);
  M1->run(RELEASE);

  M2->setSpeed(1023);
  M2->run(RELEASE);

  M3->setSpeed(1023);
  M3->run(RELEASE);

  M4->setSpeed(1023);
  M4->run(RELEASE);

  servoUp.attach(3);
  servoDown.attach(2);

  servoUp.write(asseY);
  servoDown.write(asseX);

  Wire.begin(4);                // join i2c bus with address #8
  Wire.onReceive(receiveEvent); // register event

  Serial.begin(9600);
}

void receiveEvent(int howMany)
{
  while (0 < Wire.available()) { x = Wire.read(); // receive byte as an integer } } void loop() { if (x == 4) //Left { left(); } else if (x == 6) //Right { right(); } else if (x == 7) //Up { up(); } else if (x == 5) //Down { down(); } else if (x == 9) // Red (Right) { red(); } else if (x == 2) // Blue (Left) { blue(); } else if (x == 8) // Green(down) { green(); } else if (x == 10) // Yellow(up) { yellow(); } else if (x == 0) //Stop { servoUp.write(asseY); servoDown.write(asseX); stopMotor(); } Serial.println(x); delay(500); } //VOID SINGOLI //MOTORI void left() { M1->run(FORWARD);
  M2->run(BACKWARD);
  M3->run(FORWARD);
  M4->run(BACKWARD);

  delay(50);
}

void right()
{
  M1->run(BACKWARD);
  M2->run(FORWARD);
  M3->run(BACKWARD);
  M4->run(FORWARD);

  delay(50);
}

void up()
{
  M1->run(BACKWARD);
  M2->run(BACKWARD);
  M3->run(FORWARD);
  M4->run(FORWARD);

  delay(50);
}

void down()
{
  M1->run(FORWARD);
  M2->run(FORWARD);
  M3->run(BACKWARD);
  M4->run(BACKWARD);

  delay(50);
}

void stopMotor()
{
  M1->run(RELEASE);
  M2->run(RELEASE);
  M3->run(RELEASE);
  M4->run(RELEASE);

  delay(50);
}




//CAMERA
void red()
{
  if (asseX > 0);
  {
    asseX = asseX + spaziatura;
    servoDown.write(asseX);
    delay(100);
  }
}

void blue()
{
  if (asseX < 180); { asseX = asseX - spaziatura; servoDown.write(asseX); delay(100); } } void green() { if (asseY > 0);
  {
    asseY = asseY + spaziatura;
    servoUp.write(asseY);
    delay(100);
  }
}

void yellow()
{
  if (asseY > 0);
  {
    asseY = asseY - spaziatura;
    servoUp.write(asseY);
    delay(100);
  }
}

void stopCam()
{
  servoUp.write(asseY);   //Stopcam
  servoDown.write(asseX);
  delay(100);
}

/*void frontCamera()
  {
  servoUp.write(45);
  servoDown.write(90);
  delay(100);
  }*/

Questo è il progetto ultimato e funzionante in un video dimostrativo. I sensori di prossimità verranno implementati con successivi aggiornamenti per lo sviluppo del sistema di autoguida.