Albero Robot di Carlo Villoresi – terza parte

In questo terzo articolo dedicato all’albero robot realizzato da Carlo leggerai come sono fatti gli sketch usati per i singoli microcontrollori.

Albero Robot montaggio 7

Negli articoli precedenti hai letto come Carlo ha realizzato sia la parte di assemblaggio meccanico sia la parte elettronica, ora esploriamo gli sketch.

Sketch dell’albero robot

Gli sketch sono 3 come i micro controllori presenti nel progetto ciascuno commentato direttamente nello sketch dall’autore.

Non ho voluto modificare gli sketch di Carlo per rispetto del progetto, ho solo rimosso i blocchi non utilizzati per ridurre la quantità di righe da leggere e non appesantire arduino confondendoti le idee.

Il primo sketch proposto è da caricare sull’arduino/genuino installato sul primo ripiano dell’albero robot

Albero Robot montaggio 3

ed ha come scopo il controllo dei motori e dei sensori in modo che l’albero robot possa andare in giro senza urtare contro mobili od altro:

/* *************************************************************** */
/* CHRISTMAS TREE BOT */

// Firenze, 17 dicembre 2015
/* Realizzazione di un albero di Natale robotico */
/* a cura di Carlo Villoresi */

/* *************************************************************** */

//SEZIONE SENSORI (TIPO AD ULTRASUONI SRF04)

/* Definizione delle costanti per i sensori e attribuzione pin Arduino */

// Sensore centrale 
#define ECHOPIN_CENTRALE 2  // ECHOPIN riceve l' impulso ad ultrasuoni
#define TRIGPIN_CENTRALE 4  // TRIGPIN emette l' impulso ad ultrasuoni

// Sensore di sinistra
#define ECHOPIN_SINISTRA 3  // come sopra
#define TRIGPIN_SINISTRA 5  // come sopra


//Sensore di destra
#define ECHOPIN_DESTRA 6    // come sopra
#define TRIGPIN_DESTRA 7    // come sopra


// Sensore posteriore
#define ECHOPIN_POSTERIORE 14  // il pin 14 equivale al pin A0
#define TRIGPIN_POSTERIORE 15  // il pin 15 equivale al pin A1


// Dichiaro le variabili di tipo int che conterranno i valori delle varie letture (4) dei sensori
int lettura_centrale = 0;    // lettura del sensore centrale
int lettura_sinistra = 0;    // lettura del sensore di sinistra
int lettura_destra = 0;      // lettura del sensore di destra
int lettura_posteriore = 0;  // lettura del sensore posteriore

// DICHIARAZIONE VARIABILI DINAMICHE PER SENSORI E MOVIMENTO
int letture_sensori[4];      // Dichiaro un array di lettura ( deve contenere 4 elementi in tutto) per le letture dei sensori
int presenza_ostacolo = 0;   // Dichiaro una variabile di tipo int per segnalare la presenza di un ostacolo (on/off) oppure (0/1)
int i;                       // Dichiaro una variabile di tipo int come contatore
// FINE DICHIARAZIONE VARIABILI DINAMICHE PER SENSORI E MOVIMENTO

/* SEZIONE MOTORIDUTTORI */

//Inizializzazione parametri motori

//motore A
int motorPinDirA = 8; //  pin polarità motore A
int motorPinDirB = 11; // pin polarità motore A
int motorPinA = 9;    //  pin velocità motore A


//motore B
int motorPinDirC = 12; // pin polarità motore B
int motorPinDirD = 13; // pin polarità motore B
int motorPinB = 10;    // pin velocità motore B

// FINE SEZIONE MOTORIDUTTORI 

void setup()
{
  /* SEZIONE SENSORI */
  
  /* associo ai vari pin la modalità I/0 */
  pinMode(ECHOPIN_CENTRALE, INPUT);     // Associo al pin ECHOPIN_CENTRALE la modalità INPUT)
  pinMode(TRIGPIN_CENTRALE, OUTPUT);    // Associo al pin ECHOPIN_CENTRALE la modalità OUTPUT)
  
  pinMode(ECHOPIN_SINISTRA, INPUT);     // Associo al pin ECHOPIN_SINISTRA la modalità INPUT)
  pinMode(TRIGPIN_SINISTRA, OUTPUT);    // Associo al pin ECHOPIN_SINISTRA la modalità OUTPUT)
  
  pinMode(ECHOPIN_DESTRA, INPUT);       // Associo al pin ECHOPIN_DESTRA la modalità INPUT)
  pinMode(TRIGPIN_DESTRA, OUTPUT);      // Associo al pin ECHOPIN_DESTRA la modalità OUTPUT)
  
  pinMode(ECHOPIN_POSTERIORE, INPUT);   // Associo al pin ECHOPIN_POSTERIORE la modalità INPUT)
  pinMode(TRIGPIN_POSTERIORE, OUTPUT);  // Associo al pin ECHOPIN_POSTERIORE la modalità OUTPUT)
  
  /* FINE SEZIONE SENSORI */
 
  /* SEZIONE MOTORI */
   
   //Inizializzazione pin motori
   
   // Motore A
   pinMode(motorPinDirA, OUTPUT);
   pinMode(motorPinDirB, OUTPUT);
   pinMode(motorPinA, OUTPUT);
  
   // Motore B
   pinMode(motorPinDirC, OUTPUT);
   pinMode(motorPinDirD, OUTPUT);
   pinMode(motorPinB, OUTPUT);
  
   // Fine inizializzazione pin motori
   
   
   //Inizializzazione pin velocità dei motori
   
   // Motore A
   analogWrite(motorPinA, 255);
   
   // Motore B
   analogWrite(motorPinB, 255);
   
   // Fine inizializzazione pin velocità motori

   /* velocità tramissione dati della seriale */
   Serial.begin(9600);
}

#define isdigit(n) (n >= '0' && n <= '9') // La funzione isdigit() verifica se il char in parentesi è un numero; in quel caso restituisce TRUE

void loop()
{
  
  /* LETTURA SENSORI SRF04 */
  
  // Lettura sensore centrale
  digitalWrite(TRIGPIN_CENTRALE, LOW);                   // Setta il pin trigger a low per 2uS
  delayMicroseconds(2);
  digitalWrite(TRIGPIN_CENTRALE, HIGH);                  // Spedisce al trigger un livello higs per 10uS
  delayMicroseconds(10);
  digitalWrite(TRIGPIN_CENTRALE, LOW);                   // Setta il pin a low nuovamente
  int lettura_centrale = pulseIn(ECHOPIN_CENTRALE, HIGH);// Legge gli intervalli di impulso
  lettura_centrale= lettura_centrale/58;                 // Calcola la distanza fra due impulsi
  Serial.print("sensore centrale: ");
  Serial.println(lettura_centrale);                     
  delay(500);                                            
  
  // Lettura sensore sinistra
  digitalWrite(TRIGPIN_SINISTRA, LOW);                    
  delayMicroseconds(2);
  digitalWrite(TRIGPIN_SINISTRA, HIGH);                  
  delayMicroseconds(10);
  digitalWrite(TRIGPIN_SINISTRA, LOW);                    
  int lettura_sinistra = pulseIn(ECHOPIN_SINISTRA, HIGH); 
  lettura_sinistra= lettura_sinistra/58;                  
  Serial.print("sensore sinistra: ");
  Serial.println(lettura_sinistra);                     
  delay(500);                    
  
  // Lettura sensore destra
  digitalWrite(TRIGPIN_DESTRA, LOW);                    
  delayMicroseconds(2);
  digitalWrite(TRIGPIN_DESTRA, HIGH);                   
  delayMicroseconds(10);
  digitalWrite(TRIGPIN_DESTRA, LOW);                    
  int lettura_destra = pulseIn(ECHOPIN_DESTRA, HIGH); 
  lettura_destra = lettura_destra/58;            
  Serial.print("sensore destra: ");
  Serial.println(lettura_destra);                     
  delay(500); 
  
  
  // Lettura sensore posteriore
  digitalWrite(TRIGPIN_POSTERIORE, LOW);                   
  delayMicroseconds(2);
  digitalWrite(TRIGPIN_POSTERIORE, HIGH);                  
  delayMicroseconds(10);
  digitalWrite(TRIGPIN_POSTERIORE, LOW);                   
  int lettura_posteriore = pulseIn(ECHOPIN_POSTERIORE, HIGH);      
  lettura_posteriore= lettura_posteriore/58;                 
  Serial.print("sensore posteriore: ");
  Serial.println(lettura_posteriore);                     
  delay(500);
  
  // FINE LETTURA SENSORI SRF04 */
  
  
  // SEZIONE UTILIZZO DELLE LETTURE SENSORI PER FAR MUOVERE IL ROBOT */
  
  // immagazzinamento letture sensori in un array
  letture_sensori[0] = lettura_centrale;
  letture_sensori[1] = lettura_sinistra;
  letture_sensori[2] = lettura_destra;
  letture_sensori[3] = lettura_posteriore;
  
  //Lettura dell' array da seriale. I valori letti corrispondono alle distanze rilevate dai sensori ( scommentare se si vuole analizzare tali letture )
  /*for (i = 0; i < 4; i = i + 1)
  {  
    Serial.print("sensore: ");
    Serial.print(i);
    Serial.print(" ");
    Serial.println(letture_sensori[i]);
    Serial.print(" ");
    delay(500);
    
  }*/
  Serial.print(" "); // stampa una riga vuota
  Serial.print(" "); // stampa una riga vuota
  Serial.print(" "); // stampa una riga vuota 
  
  
  //azione dei motori in presenza di ostacoli
  presenza_ostacolo = checkDistance(letture_sensori); // La funzione checkDistance restituisce un valore (0 oppure 1) a seconda della presenza di un ostacolo
  motori(presenza_ostacolo);                          // La funzione presenza_ostacolo() determina il moto del robot agendo sul comportamento dei motori
  
  Serial.print(presenza_ostacolo);                    // In seriale viene letta il valore della funzione checkDistance()
  Serial.print(" ");                                  // stampa una riga vuota
}

void motori(int presenza_ostacolo)
{
  if(presenza_ostacolo == 1)
  {
    Stop();
    delay(2000); // l' intervallo di tempo viene impostato in conseguenza della scelta precedente di commentare la 'Scelta del brano musicale' come intervallo di arresto del robot
    
    // azione motore successiva
    Indietro();   // viene eseguita la funzione Indietro()
    delay(6000);
    
    Sinistra();// azione motore successiva
    delay(3000);
  }
  else if(presenza_ostacolo == 0)
  {
    Avanti(); // azione motore
  }

}

// comanda il movimento dei motori in avanti
void Avanti()
{
  //impostazione direzione di rotazione motore A 
  digitalWrite(motorPinDirA, HIGH); // associo un valore HIGH al pin motorPinDirA 
  digitalWrite(motorPinDirB,LOW );  // associo un valore LOW al pin motorPinDirB

  //impostazione direzione di rotazione motore B
  digitalWrite(motorPinDirC, LOW);  // associo un valore LOW al pin motorPinDirC 
  digitalWrite(motorPinDirD, HIGH); // associo un valore HIGH al pin motorPinDirD 
}

// comanda il movimento dei motori indietro
void Indietro()
{

  //motore A 
  digitalWrite(motorPinDirA, LOW);  // associo un valore LOW al pin motorPinDirA 
  digitalWrite(motorPinDirB,HIGH ); // associo un valore HIGH al pin motorPinDirB 

  //motore B
  digitalWrite(motorPinDirC, HIGH); // associo un valore HIGH al pin motorPinDirC 
  digitalWrite(motorPinDirD, LOW);  // associo un valore LOW al pin motorPinDirD 

}  

// comanda il movimento dei motori a sinistra
void Sinistra()
{
  //motore A 
  digitalWrite(motorPinDirA, HIGH); // associo un valore HIGH al pin motorPinDirA 
  digitalWrite(motorPinDirB,LOW );  // associo un valore LOW al pin motorPinDirB 

  //motore B
  digitalWrite(motorPinDirC, HIGH); // associo un valore HIGH al pin motorPinDirC 
  digitalWrite(motorPinDirD, LOW);  // associo un valore LOW al pin motorPinDirD 

}

// comanda il movimento dei motori a destra
void Destra()
{
  //motore A 
  digitalWrite(motorPinDirA, LOW);  // associo un valore LOW al pin motorPinDirA 
  digitalWrite(motorPinDirB,HIGH ); // associo un valore HIGH al pin motorPinDirA 

  //motore B
  digitalWrite(motorPinDirC, LOW);  // associo un valore LOW al pin motorPinDirC 
  digitalWrite(motorPinDirD, HIGH); // associo un valore HIGH al pin motorPinDirD 

}

// comanda l' arresto dei motori
void Stop()
{
  digitalWrite(motorPinDirA, LOW);  // associo un valore LOW al pin motorPinDirA  
  digitalWrite(motorPinDirB, LOW);  // associo un valore LOW al pin motorPinDirA 

  digitalWrite(motorPinDirC, LOW);  // associo un valore LOW al pin motorPinDirC 
  digitalWrite(motorPinDirD, LOW);  // associo un valore LOW al pin motorPinDirD 


}

// Funzione che restituisce un valore (0 oppure 1) a seconda che ci si trovi davanti ad un ostacolo oppure no
int checkDistance(int lettura_sensori[])
{

  int esito = 0; // Dichiaro la variabile di tipo int che accoglie il valore finale della funzione
  int i;         // Dichiaro la variabile di tipo int i come indice dell' array contenente lettura_sensori[]

  //Lettura distanze sensori dall' array
  for (i = 0; i < 4; i = i + 1)
  {  
    if ((lettura_sensori[i] < 15)&& (lettura_sensori[i] > 0))  // impongo che l' ostacolo si debba trovare entro la distanza di 15 cm
    { 
      esito = 1; 
    }
  }
  
  // Stampa su seriale del valore di checkDistance() per analisi sensori
  Serial.print("checkDistance: ");
  Serial.println(esito);
  Serial.println(" ");
  Serial.println(" ");
  Serial.println(" ");
  return esito;  // restituisce il valore contenuto nella variabile esito

}

come hai letto il codice è scritto in modo chiaro ed ogni parte dello stesso è commentata a dovere.

Passa al secondo sketch, da caricare sull’arduino ( o genuino ) che hai installato sul secondo ripiano:

Albero Robot montaggio 5

/*
 Il programma consente la riproduzione di canzoni in formato mp3. Scaricare il programma
 in Arduino (la scheda situata al piano superiore 2) e scegliere la costante corretta da 
 inserire nello sketch per ottenere la sequenza di riproduzione voluta.
 */


// Elenco delle librerie necessarie
#include <SD.h>
#include <SPI.h>
#include <arduino.h>
#include <MusicPlayer.h>

void setup()
{
  Serial.begin(9600);
  player.begin();                      //inizializza l'hardware e definisce la modalità di default
  player.setPlayMode(PM_SHUFFLE_PLAY); //definisce la modalità di riproduzione dei brani come SHUFFLE (altrimenti PM_NORMAL_PLAY,PM_REPEAT_LIST,PM_REPEAT_ONE (vedere la libreria MusicPlayer.h)
  player.scanAndPlayAll();             //Se la playlist corrente è vuota saranno eseguite tutte le canzoni contenute nell cartella root della playlist.
}
void loop()
{
  player.play();
}

è decisamente più semplice del precedente ed il suo scopo ti è certamente già chiaro: controllare l’esecuzione dei brani musicali presenti nella SD Card che avrai inserito nella MusicShield.

Il lavoro è quasi totalmente affidato alla libreria che comunica con la shield ed esegue i brani.

L’ultimo sketch da caricare è quello che puoi caricare nella Adafruit Trinket 5V per la gestione delle luci dell’albero di natale:

int led1 = 4;
int led2 = 5;
int led3 = 6;
int led4 = 8;


void setup() 
{
  pinMode(led1,OUTPUT);
  pinMode(led2,OUTPUT);
  pinMode(led3,OUTPUT);
  pinMode(led4,OUTPUT);
  	
}
void loop()
{
  digitalWrite(led1,HIGH);
  digitalWrite(led2,LOW);
  digitalWrite(led3,LOW);
  digitalWrite(led4,LOW);
  delay(100);
  digitalWrite(led1,LOW);
  digitalWrite(led2,HIGH);
  digitalWrite(led3,LOW);
  digitalWrite(led4,LOW);
  delay(100);
  digitalWrite(led1,LOW);
  digitalWrite(led2,LOW);
  digitalWrite(led3,HIGH);
  digitalWrite(led4,LOW);
  delay(100);
  digitalWrite(led1,LOW);
  digitalWrite(led2,LOW);
  digitalWrite(led3,LOW);
  digitalWrite(led4,HIGH);
  delay(100);
}

anche questa parte del codice è molto semplice, tanto che Carlo non ha inserito dei commenti alle linee di controllo dei 5 led connessi alla scheda.

Il video dell’Albero Robot

Ecco il video realizzato dall’autore e condiviso su YouTube:

Prima di inserire un commento, per favore, leggi il regolamento

Permanent link to this article: http://www.mauroalfieri.it/elettronica/albero-robot-carlo-villoresi-terza-parte.html

3 comments

  1. Complimenti a Carlo per il bellissimo progetto da cui sto prendendo spunto, dopo l’uscita al cinema di “star wars”, per realizzare un piccolo R2-D2.
    Nella mia rielaborazione sto usando i sensori ad ultrasuoni in modo separato :
    Sensore di destra fa girare leggermente a sinistra, sensore di sinistra fa girare leggermente a destra, sensore anteriore fa andare indietro e girare a destra o sinistra dipendente dai sensori laterali, il sensore posteriore “dovrebbe” impedire di andare contro un ostacolo quando il robot fa retromarcia.
    Il problema è proprio sulla retromarcia perché i motori si muovono indietro per “x” millisecondi escludendo il sensore.
    Volevo chiedere se c’era un modo per ovviare a questo problema.
    Ti ringrazio
    Tiziano

    1. Ciao Tiziano,
      il modo per risolverlo è usare il comando millis() al posto del comando delay().
      Il primo non interrompe il ciclo ma necessita di una sintassi di programmazione un po’ più complessa.
      Il secondo è semplice da utilizzare ma impedisce qualunque operazione durante i movimenti.

      1. Grazie Mauro
        Ho trovato il tuo articolo “Tutorial: millis() contro delay()” con il link a Vittorio Zuccalà.
        Ci “studio” sopra e poi ti farò sapere.
        Ciao
        Tiziano

Lascia un commento

Your email address will not be published.

Questo sito usa Akismet per ridurre lo spam. Scopri come i tuoi dati vengono elaborati.