Cesarino

Da raspibo.

Cesarino è un robot che cerca la luce. Se non ne trova abbastanza continuerà a girare all'infinito, o almeno fino a che non finiscono le batterie. Il cuore e lo chassis di Cesarino è OttoBot. Anzi: sono proprio lo stesso robot con due sistemi di guida differenti. Per saperne di più sulla programmazione dell'ATmega8, usato per la logica di Cesarino, vi rimando alla pagina di OttoBot. In questa guida faremo come se si stesse usando un qualsiasi Arduino.

Cesarino 1ver.JPG La prima versione, quasi funzionante

Indice

Componenti

Cesarino è stato assemblato con:

  • Un ATmega8 con il bootloader di Arduino (potete usare qualsiasi Arduino-like)
  • Un HC-SR04, sensore a ultrasuoni (per evitare gli ostacoli, su Ardubottino ne trovate uno simile)
  • Due motori DC (con ruote)
  • Una fotoresistenza
  • Una resistenza da 1K
  • Il ponte a H L298, lo stesso usato in Ardubottino al quale vi rimando per sapere come funziona
  • Batterie: nel dettaglio una 9V per i motori e 4 AA per l'ATmega8 e il resto della logica.
  • Uno chassis, stampato malamente in 3D!

La fotoresistenza, questa sconosciuta

In realtà non c'è molto da sapere. È una resistenza che cambia il suo valore a seconda di quanta luce riceve. Il rapporto luce/resistenza è inversamente proporzionale ovvero più luce riceve, meno resistenza oppone. Per contro, più luce riceve, più corrente lascia passare. La fotoresistenza ha 2 pin, uno va messo a +5V, l'altro in un'entrata analogica dell'Arduino. L'entrata analogica va poi messa a terra (usando un'opportuna resistenza) in modo da fare un divisore di voltaggio.

FotoresCes.JPG

Il resto della roba, come funziona?

La trovate tutta su Ardubottino. L'unica differenza è che l'HC-SR04 non ha la possibilità di usare il trigger dell'ultrasuono e l'echo sullo stesso filo. Ha bisogno di due fili (questo significa che lo sketch di esempio dell'IDE di Arduino ha bisogno di essere modificato).

Cesarino Schema.png

E ora il codice!

const int fw1 = 5;
const int bk1 = 6;
const int fw2 = 7;
const int bk2 = 8;
const int am1 = 9;
const int am2 = 10; //motor pins, fw=forward, bk=back, am=enable
const int lightSensor = A0; //pin for light sensor
const int lightThreshold = 60;
const int pingPin = 4;
const int trigPin = 3 ;
int changeDir = 0; 

void setup() {
  Serial.begin(19200);
  Serial.println("Ready");
  pinMode(fw1,OUTPUT);
  pinMode(bk1,OUTPUT);
  pinMode(fw2,OUTPUT);
  pinMode(bk2,OUTPUT);
  pinMode(am1,OUTPUT);
  pinMode(am2,OUTPUT);
  pinMode(pingPin, INPUT);
  pinMode(trigPin, OUTPUT);
}

void motorAction(int fwm, int bkm,int anm,int motspeed) { //requires fd pin, bk pin, en pin and speed (PWM)
      if (motspeed > 0 ) {             //going forward
        digitalWrite(fwm,HIGH);
        digitalWrite(bkm,LOW);
      } else if (motspeed < 0) {       //reverse
        digitalWrite(fwm,LOW);
        digitalWrite(bkm,HIGH);
      } else {                         //stop
        digitalWrite(fwm,LOW);
        digitalWrite(bkm,LOW);
      }
      analogWrite(anm,abs(motspeed));
}

void straight(int spd) {          //all of these functions must be rewritten if
  motorAction(fw1,bk1,am1,spd);   //a different kind of motors (stepper, servo..)
  motorAction(fw2,bk2,am2,spd);   //are used
}
  
void right(int spd) {
  motorAction(fw1,bk1,am1,spd);
  motorAction(fw2,bk2,am2,0);
} 

void left(int spd) {
  motorAction(fw1,bk1,am1,0);
  motorAction(fw2,bk2,am2,spd);  
}

void halt() {
  motorAction(fw1,bk1,am1,0);
  motorAction(fw1,bk1,am2,0);
}

bool proximity(){
  long duration;
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(5);
  digitalWrite(trigPin, LOW);
  duration = pulseIn(pingPin, HIGH);
  if (duration/29/2 < 10) {         //avoids obstacles 10 cm away
    return true;
  } else {
    return false;
  }
} 

void loop(){
  if (analogRead(lightSensor) < lightThreshold) { //if the light is not enough go FORWARD
    Serial.println("FORWARD");                    //serial output for debugging reasons (plug the motors off and see how it works)
    straight(100);
    changeDir ++;
    if (changeDir > 1000) {                       //sometimes it changes direction; it's just for not letting the robot to follow
      right(150);                                 //a straight line, anyway the path is quite predictable
      left(-150);
      delay(500);
      changeDir = 0;
    }
  } else {
    Serial.println("HALT");                       //it found enough light, so it stays still
    halt();
  }
  while(proximity()) {
    Serial.println("PROXIMITY");                  //found an obstacle
    right(-150);
    left(150);
  }
}

Non ho testato bene il codice. Si può fare di meglio ma non ho avuto molto tempo. Ci guarderò con calma nelle prossime settimane. In particolare non ho testato i delay (avevo usato delayMicroseconds al posto di delay, ma ho scoperto che accetta solo interi) e il sistema per far cambiare direzione è pratico ma brutale. Ad ogni modo Cesarino è andato in giro per la mia cucina, sbattendo qua e là e correndo come un pazzo, fino a che non si è messo sotto la finestra. Lì si è fermato.

Cesarino last.JPG

Sst! Non disturbatelo!

Strumenti personali
Namespace

Varianti
Azioni
Navigazione
Strumenti