Informatica

Programmazione, CoderDojo, configurazioni ecc

Elettronica

Arduino, Raspberry, stampanti 3D ecc

Fisica

Fisiclab, esperimenti, laboratori

Astronomia

Planetario, museo del cielo e della terra

Cucina

Ricette, esperimenti culinari, paciughi

Una macchina programmabile - prime prove

Eccoci al quarto post relativo al mio progetto con Arduino: una macchina programmabile.
Questi sono i link del primo, secondo e terzo post

Il telaio è pronto, la pulsantiera anche. Tutti i componenti sono montati.
Questo è il risultato finale:

Macchina programmabile finita Simone Bacciglieri
Si può vedere anche il dettaglio della posizione della batteria da 9V.
In questa foto invece si vede come il led si incastri perfettamente all'interno del buco del Lego.
Led Lego Brick

Ho fatto anche uno schema con Fritzing per far capire meglio come ho collegato il tutto. A questo però bisogna aggiungere lo schema della pulsantiera che ho inserito nel terzo post.

schema macchina programmabile Simone Bacciglieri

Questo è il programma che ho scritto:

/* Software per la macchina programmabile */
/* Simone Bacciglieri */

#include <Servo.h>

Servo servoleft;
Servo servoright;

//Array contenente tutte le istruzioni da eseguire.
//Nessuna istruzione = 0
//AVANTI = 1
//INDIETRO = 2
//DESTRA = 3
//SINISTRA = 4
int instructions[100];

int sLeft = 9;
int sRight = 8;

//Front left led
int flLed = 10;
//Front right led
int frLed = 11;
//Rear left led
int rlLed = 12;
//Rear right led
int rrLed = 13;

//Push button panel led
int bPanelLed = 7;

//Flag per sapere se sono in modalità inserimento comandi
int insertMode = 0;
//Posizione dell'ultima istruzione nell'array
int currentPosition = 0;

void setup() {
  Serial.begin(9600);

  pinMode(sLeft, OUTPUT);
  pinMode(sRight, OUTPUT);

  // Nei servo normali l'argomento del metodo write è la posizione angolare.
  // In quelli a rotazione continua invece
  // 0 vuol dire ruota avanti alla massima velocità
  // 180 vuol dire ruota indietro alla massima velocità
  // 90 vuol dire fermo
  servoleft.attach(sLeft);
  servoleft.write(90);
  servoright.attach(sRight);
  servoright.write(90);
 
  pinMode(flLed, OUTPUT);
  pinMode(frLed, OUTPUT);
  pinMode(rlLed, OUTPUT);
  pinMode(rrLed, OUTPUT);

  pinMode(bPanelLed, OUTPUT);

  //Abilito la resistenza interna di pullup sul pin A0
  pinMode(A0, INPUT_PULLUP);
  //Tutti i led spenti
  digitalWrite(flLed, LOW);
  digitalWrite(frLed, LOW);
  digitalWrite(rlLed, LOW); 
  digitalWrite(rrLed, LOW);

  digitalWrite(bPanelLed, LOW);
 
  Serial.println("Inizio");
}

void loop() {
  // Leggo il valore che mi arriva dalla pulsantiera
  int buttonsPanel = analogRead(A0);
  // Un po' di debug
  Serial.println(buttonsPanel);
  // Se il flag insertMode è a 0 eseguo immediatamente l'istruzione relativa al tasto premuto
  // Altrimenti la inserisco nell'array delle istruzioni
  switch (buttonsPanel) {
    case 15 ... 30:
      Serial.println("Bottone AVANTI premuto");
      delay(500);
      insertMode ? carSet(1) : fw();
      break;

    case 122 ... 142:
      Serial.println("Bottone INDIETRO spremuto");
      delay(500);
      insertMode ? carSet(2) : back();
      break;

    case 166 ... 175:
      Serial.println("Bottone SX spremuto");
      delay(500);
      insertMode ? carSet(4) : left();
      break;

    case 72 ... 82:
      Serial.println("Bottone DX spremuto");
      delay(500);
      insertMode ? carSet(3) : right();
      break;

    case 277 ... 284:
      Serial.println("Bottone STOP spremuto");
      delay(500);
      carStop();
      insertMode = 0;
      break;

    case 243 ... 251:
      //Hanno premuto SET quindi devo iniziare ad immagazzinare le istruzioni
      Serial.println("Bottone SET spremuto");
      delay(500);
      //Azzero l'array
      for (int i = 0; i < 100; i++) {
        instructions[i] = 0;
      }
      insertMode = 1;
      currentPosition = 0;
      break;

    case 207 ... 214:
      //Hanno premuto GO quindi devo eseguire tutte le istruzioni dell'array
      Serial.println("Bottone GO spremuto");
      delay(500);
      carGo();
      insertMode = 0;
      break;

    default:
      Serial.println("Nessun tasto spremuto");
      break;
  }
}

void ledBlink() {
  digitalWrite(bPanelLed,HIGH);
  delay(150);
  digitalWrite(bPanelLed,LOW);
  delay(150);
}

void fw() {
  Serial.println("Avanti");
  //Accendo i led anteriori e spengo quelli posteriori
  digitalWrite(flLed, HIGH);
  digitalWrite(frLed, HIGH);
  digitalWrite(rlLed, LOW);
  digitalWrite(rrLed, LOW);
  //I servo devono girare  in direzioni opposte per andare nello stesso verso
  //Sono montati in direzioni opposte
  servoleft.write(0);
  servoright.write(116);

  for(int i=0;i<8;i++) {

    ledBlink();
  }
  carStop();
}

void back() {
  Serial.println("Indietro");
 
  digitalWrite(flLed, LOW);
  digitalWrite(frLed, LOW);
  digitalWrite(rlLed, HIGH);
  digitalWrite(rrLed, HIGH);

  servoleft.write(180);
  servoright.write(60);

  for(int i=0;i<8;i++) {
    ledBlink();
  }
  carStop();
}

void left() {
  Serial.println("Sinistra");
 
  digitalWrite(flLed, HIGH);
  digitalWrite(frLed, LOW);
  digitalWrite(rlLed, HIGH);
  digitalWrite(rrLed, LOW);
  // Il servo sinistro è fermo mentre quello destro gira
  servoleft.write(90);
  servoright.write(180);

  for(int i=0;i<3;i++) {
    ledBlink();
  }
  carStop();
}

void right() {
  Serial.println("Destra");
  // Il servo sinistro gira mentre quello destro è fermo
  digitalWrite(flLed, LOW);
  digitalWrite(frLed, HIGH);
  digitalWrite(rlLed, LOW);
  digitalWrite(rrLed, HIGH);

  servoleft.write(0);
  servoright.write(90);

  for(int i=0;i<3;i++) {
    ledBlink();
  }
  carStop();
}

void carStop() {
  //Fermo la macchina e spengo tutto
  Serial.println("Ferma");
 
  digitalWrite(flLed, LOW);
  digitalWrite(frLed, LOW);
  digitalWrite(rlLed, LOW);
  digitalWrite(rrLed, LOW);

  servoleft.write(90);
  servoright.write(90);
}

void carGo() {
  Serial.println("Via");
  //Quando incontro il valore 0 vuol dire che sono finite le istruzioni
  for (int i = 0; i < 100; i++) {
   
    switch (instructions[i]) {
      case 0:
        //Fine istruzioni
        carStop();   
        break;
      case 1:
        //Avanti
        fw();
        break;
      case 2:
        //Indietro
        back();
        break;
      case 3:
        //Destra
        right();
        break;
      case 4:
        //Sinistra
        left();
        break;
    }
  }
}

void carSet(int instruction) {
  Serial.println("Set");
  // Inserisco nell'array l'istruzione relativa al pulsante premuto.
  // Se arrivo all'ultima istruzione segnalo facendo blinkare il led.
  if (currentPosition > 98) {
    Serial.println("Raggiunto il limite massimo di istruzioni");
    for(int i=0;i<14;i++) {
      ledBlink();
    }
  }
  instructions[currentPosition] = instruction;
  currentPosition++;
}



Ho iniziato a fare un po' di prove e ho notato subito un problema: i due servo motori non vanno alla stessa velocità. Ho provato a variare il parametro che passo alla funzione write ma, anche se la situazione è migliorata, non sono riuscito a farla andare perfettamente dritta.
Una volta risolto questo problema posso dire di aver raggiunto l'obiettivo che mi sono dato nel primo post e posso iniziare ad estendere il progetto: per prima cosa voglio mettere il sensore ad ultrasuoni perchè ho visto che i miei figli quando la usano la fanno sbattere da tutte le parti, quindi è bene che sappia fermarsi in tempo da sola. :)