OttoBot

Da raspibo.

OttoBot è il risultato di un tentativo di usare un ATmega8 al posto di una board Arduino.

Indice

Le specifiche tecniche

L'ATmega8, prodotto da Atmel, è piuttosto modesto.

  • Ha 8KB di memoria flash. Se usate il bootloader di Arduino allora ve ne rimarranno solo 7.
  • Il clock è massimo 16Mhz usando un risuonatore esterno. Quello interno va a 8Mhz (ma vi risparmiate un bel po' di circuiteria). Per usare il risuonatore interno occorre cambiare un fuse.
  • 23 pin programmabili.
  • 2 interrupt.
  • Porte SPI, I²C e seriale (ma non è possibile usare seriali software, presenti nella libreria di Arduino).
  • Costa una bazzecola.

Per essere acceso ha bisogno da 2,7 a 5,5 Volt. Il prezzo oscilla attorno all'euro.

Prime versioni

8bot.jpg

Come potete vedere, la dimensione è proprio mini. Si comanda tramite bluetooth. Ruote e chassis sono stampate 3d.

8bots.JPG

Da sinistra a destra, l'evoluzione di 8bot!

Modificare l'ATmega8 affinché sembri un Arduino

Per approfondire questo argomento leggete anche Programmazione dei microcontrollori.

Per ottenere questo occorre fare tre cose:

  • Trovare un programmatore (potete usare la porta parallela oppure acquistarne uno, ma anche un normalissimo Arduino può essere usato come programmatore)
  • Settare i fuses
  • Caricare il bootloader
  • Aggiungere l'ATmega8 nel file boards.txt di Arduino

Una volta fatti questi passi, potrete usare l'IDE come per qualsiasi altra board.

Di guide su come usare i programmatori ne trovate a bizzeffe su internet, noi ci concentreremo sull'utilizzo di Arduino come ISP, che è la procedura che ho usato io.

Arduino as ISP

Negli sketch di esempio nella IDE di Arduino c'è "Arduino as ISP" (In-System Programmer). Caricatelo su un Arduino di vostra scelta con l'accortezza di controllare i pin da usare: sui Mega sono diversi. Dovrete usare la porta SPI e in genere avete: 10 reset, 11 MOSI, 12 MISO e 13 clock (SCK). Sui Mega le porte sono rispettivamente 53, 51, 50 e 52. Trovate tutto nei commenti dello sketch. Altri pin, opzionali, sono il 9 (heartbeat, mostra se il programma sta girando), 8 (error, si accende se c'è un problema), 7 (programming, si accende durante le comunicazioni).

La porta SPI va così collegata, MISO con MISO, MOSI con MOSI, SCK con SCK e reset con reset. Il datasheet lo trovate qui [1]

Atmega8 arduinopinout.png

I pin che vedete sono quelli come da IDE di Arduino. Se lo programmate con altri sistemi (come Eclipse) i riferimenti possono essere diversi. Se il vostro ATmega8 è settato per avere un risuonatore esterno, dovrete collegarlo con un pin XTAL1 e l'altro su XTAL2. Entrambi i pin XTAL1 e XTAL2 vanno poi collegati a terra con un condensatore da 22 picofarad. Ne avrete bisogno se volete raggiungere frequenze superiori agli 8 Mhz o se avete bisogno di maggiore stabilità (il risuonatore interno non è molto preciso). Per contro, il risuonatore interno non ha bisogno di collegare nulla. Per approfondire guardate questa guida [2]

avrdude

Per interagire con l'ATmega8 dovrete usare avrdude, questa è una riga di esempio:

avrdude -p m8 -c arduino -P /dev/ttyACM1 -U flash:w:{bootloader}.hex -U hfuse:w:0xd9:m -U lfuse:w:0xe3:m -b 19200

Per saperne di più [3]

-p m8 

dice che abbiamo a che fare con un ATmega8

-c arduino

segnala che stiamo usando un Arduino come programmatore, nelle nuove versioni della IDE, con il nuovo sketch ArduinoISP probabilmente il protocollo da usare è stk500v1

-P /dev/(porta)

è la porta dove avete collegato il programmatore, di solito per gli Arduino è ttyACMx o ttyUSBx; per conoscerla ci sono due modi: guardare nella IDE di Arduino le porte disponibili o collegare l'Arduino e guardare gli ultimi messaggi in dmesg

-U flash:w:{bootloader}.hex

scrive il bootloader, vedi sotto

-U hfuse:w:0xd9:m -U lfuse:w:0xe3:m 

modifica i fuse, vedi sotto

-b 19200

la velocità di comunicazione in baud

Caricare il bootloader

Se volete usarlo come Arduino dovreste caricare il bootloader. Potete farne anche a meno e risparmiare 1Kb (su 8, non è poco). In teoria potreste farne a meno e continuare a caricare gli sketch sull'ATmega8 l'Arduino come programmatore. Fatto sta che l'ho caricato una volta e non ho mai provato a toglierlo (del resto: if ain't broke, don't fix it). I bootloader li trovate in {cartella di Arduino}/hardware/arduino/avr/bootloaders. Se non li avete li trovate qua [4]

Settare i fuse

Molte opzioni dell'ATmega8 sono settabili tramite dei fuse. I fuse sono dei bit su una memoria EEPROM che dicono al microcontrollore come deve comportarsi. Tramite i fuses è possibile settare il clock, se usare un oscillatore esterno o interno, quanto deve aspettare durante il boot per una nuova programmazione, etc. Qui trovate due calcolatori di fuse, questo è più semplice da usare avrfuse questo è più completo Engbedded AVR Fuse Calculator.

Aggiungere le opzioni alla IDE di Arduino

Se siete affezionati alla IDE dovrete aggiungere al menu delle board l'ATmega8.

In teoria, nel menu Tools/boards, c'è già "Arduino NG or older" che ha, fra le varie opzioni, anche la possibilità di usare l'ATmega8, ma io ho avuto una serie di problemi a usarla e alla fine non ho provato a capire perché non funzionasse.

Andate in {cartella di Arduino}/hardware/arduino/avr e aprite il file boards.txt (se avete paura di fare dei danni, fate una copia di questo file prima, per precauzione).

Per aggiungere l'ATmega8 basta aggiungere queste opzioni alla fine [5].

In alternativa

Copiate i files dal repository https://github.com/chuckb/atmega, cartellle incluse, nella directory hardware degli sketches arduino, per esempio (nel mio caso):

ls ~/arduino-sketches/hardware/atmega/avr/
boards.txt  platform.txt


Se caricate uno sketch sul microcontrollore con un clock sbagliato accadranno risultati imprevedibili, ad es. caricate dalla IDE usando ATmega8 a 4Mhz con i fuses settati in modo che vada a 8Mhz scoprirete che tutto andrà al doppio della velocità. I secondi diventano mezzi secondi, 9600 baud diventano 19200 e così via. Non una gran cosa se state cercando di programmare, però può sfuggirvi perché non segnala nessun errore.

Una volta editato boards.txt riavviate la IDE se l'avevate aperta e vedrete comparire nel menu Tools/board una nuova voce, quella dell'ATmega8.

Caricare uno sketch

Collegate il programmatore (nei nostri esempi, l'Arduino) all'ATmega8 alla seriale (se avete caricato il bootloader) o alla SPI, collegate il reset (di default su Arduino as ISP è il pin 10), il +5v e la terra, andate sotto Sketch e usate "Upload Using Programmer". Alternativamente potete cliccare shift+pulsante del caricamento dello sketch. Se tutto è andato come dovrebbe vedrete lampeggiare i LED della seriale dell'Arduino per qualche secondo fino a che l'IDE non ci comunicherà "done". Se invece non volete usare la IDE, potete compilare il vostro sketch con avr-gcc e uploadarlo direttamente con avrdude (ma di questo non tratteremo qui).

Problemi più frequenti: cavetti non collegati bene, cavetti invertiti, alimentazione non sufficiente, oscillatore esterno previsto ma mancante.

Altri metodi

Potete usare, ad esempio, la SPI del Raspberry Pi, guardate la pagina Programmazione_dei_microcontrollori.

Lo schema elettrico

È estremamente banale. Collegate le batterie a modulo Bluetooth, integrato e motori, in parallelo, collegate i fili del segnale dei servo a un pin libero dell'ATmega8, collegate RX dell'integrato a TX del modulo Bluetooth. Se volete un feedback dall'integrato allora collegate anche il TX dell'integrato al RX del modulo Bluetooth.

8botschema.png

In sintesi:

  • il + delle batterie va collegato a: vcc del modulo Bluetooth, vcc dell'ATmega8, + del servo 1 e 2
  • il - delle batterie va collegato a: gnd del modulo Bluetooth, due gnd dell'ATmega8, - del servo 1 e 2
  • TX del modulo Bluetooth va collegato a RX dell'ATmega8
  • RX del modulo Bluetooth va collegato a TX dell'ATmega8
  • i segnali dei servi vanno collegati a due pin liberi (nel nostro caso 14 e 15 ma potete benissimo sceglierne degli altri)

Lo sketch

Lo trovate sul repository: [6]

Vediamo un po' i punti più strani.

#include <Servo.h>
#include <EEPROM.h>

Servo dx_servo;
Servo sx_servo;

const int dx_pin = 8;
const int sx_pin = 9;
int fd_spd_dx = 180; //initial values
int bk_spd_dx = 0;   //180 is full forward, 0 full backward
int fd_spd_sx = 0;   //stop is somewhere in the middle 
int bk_spd_sx = 180; //but the motors keep running

Per far funzionare il nostro robottino servirà la libreria Servo. La EEPROM ci servirà per mantenere la calibrazione da spento. Ci sono due costanti, i pin a cui sono collegati il segnale dei servi, e i valori che passeremo al metodo write degli oggetti dx_servo e sx_servo. Nei servo continui 0 è antiorario e 180 orario, lo stato fermo è più o meno 90. In questo caso però li staccheremo con detach così da non mantenerli in tensione. Se il vostro progetto non ha bisogno che il servo faccia resistenza (ad es. deve tenere un peso) allora è meglio staccarlo. Non è solo una questione di risparmio energetico: i piccoli servo e quelli di scarsa qualità quando sono in tensione tendono a scaldare. Le quattro variabili sono rispettivamente il valore avanti e indietro del motore a destra e il valore avanti e indietro del motore a sinistra.

void setup() {
  Serial.begin(9600);
  Serial.println("READY");
  if (EEPROM.read(4) == 1) {
    fd_spd_dx = EEPROM.read(0);//reserve 4 bytes 
    bk_spd_dx = EEPROM.read(1);//for saved calibration
    fd_spd_sx = EEPROM.read(2);
    bk_spd_sx = EEPROM.read(3);
  }
}

Accende la seriale e si legge la EEPROM. La memoria non scritta ha come valore 255 quindi serve un quinto elemento che comunichi se la calibrazione è stata fatta o meno. Scrivere e aggiornare la EEPROM è facilissimo. Vi consiglio di leggere la guida ufficiale [7]. Ricordate che l'ATmega8 ha 512 bytes a disposizione nella EEPROM.

void loop() {
  if(Serial.available()){
    char command = Serial.read(); //every command is a char
    if (command == 's') {         //it is possible to write to  the bot
      turnOnServo();              //using a keyboard
      dx_servo.write(fd_spd_dx);
      sx_servo.write(fd_spd_sx);
 } else if (command == 'd') {
 [...]

Ogni comando ricevuto dalla seriale è un char. Si potrebbe eventualmente mandare un byte, ma così è più comodo soprattutto quando ancora non avevo pronta la app e dovevo pilotare il piccolo bot con la tastiera. Si può ancora fare: i tasti sono wasd. Sulla funzione turnOnServo() torneremo dopo.

 [...]
 } else if (command == 'h') {
      if (fd_spd_dx > 90) {
        fd_spd_dx --;        
 }
 [...]

Altri comandi servono per la calibrazione. Purtroppo nella app la calibrazione è ancora molto confusionaria. Ogni variabile può diventare da 0 a 90 e da 91 a 180.

   [...]
   } else if (command == 'z') { //save calibration into eeprom
     EEPROM.update(0,fd_spd_dx);
     EEPROM.update(1,bk_spd_dx); 
     EEPROM.update(2,fd_spd_sx);
     EEPROM.update(3,bk_spd_sx);
     EEPROM.update(4,1);
     Serial.println("OK");
   } else {
     stopServo(); //if the serial is empty, stop the motors
   }

Infine, ecco dove la EEPROM viene scritta, incluso l'indirizzo 4 che diventa 1 e segnala al prossimo riavvio di leggersi i valori che avevamo salvato. Se non arriva nessun comando i servo vengono staccati.

void turnOnServo() {
  dx_servo.attach(dx_pin);
  sx_servo.attach(sx_pin);
}
void stopServo() {
  dx_servo.detach();
  sx_servo.detach();
}

Ogni volta che arriva un comando vengono riattaccati. In questo modo non rimarranno sotto tensione.

Il bluetooth

Il collegamento fra l'Ottobot e il vostro smartphone o il vostro computer avverrà tramite il modulo HC-05 o HC-06. Il modulo è molto semplice da usare: ha una porta seriale fisica dove legge e scrive tutto ciò che arriva via il servizio di porta seriale via Bluetooth. Nel nostro caso sarà attaccato direttamente ai pin RX e TX del nostro ATmega8 e farà come da ponte fra il nostro dispositivo e il microcontrollore. Potete leggere più informazioni su come giocare con questo tipo di moduli nella pagina HC-05 e HC-06.

L'app

Potete scaricarla, guardarla e modificarla all'indirizzo di App Inventor (serve account Google) qua.

L'app è stata scritta con il MIT App Inventor 2. È un tool molto potente utile per chi, come me, è ancora fermo a cercare di fare un "Hello World" decente su Android. Non è la soluzione più efficace, ma nell'attesa di imparare qualcosa di migliore, è la più semplice.

L'App Inventor è basato sul popolare linguaggio educativo Scratch. Permette di inserire pulsanti, grafica e di interagire con i sensori e, nel nostro caso, con dispositivi Bluetooth. Permette di collegarsi a un dispositivo Android (anche emulato) per fare dei test in real-time e fare correzioni al volo. Quando avrete finito potrete creare un .apk da installare così non avrete più bisogno dell'App Inventor per usarla.

Tutte le informazioni su come utilizzarlo le trovate nel sito ufficiale [8].

Nel repository c'è il sorgente in formato .aia, che potete caricare sull'App Inventor con Import.

Per prima cosa ho creato, nello Screen 1, una lista che si carica con la lista dei dispositivi Bluetooth che sono nel range del nostro tablet o telefono. Nella schermata c'è solo una lista e un componente "Bluetooth Client" chiamato BluetoothClient1.

Initbt.png

AfterPicking, ovvero dopo aver scelto un dispositivo, andrà nello screen "Controls" portandosi dietro il nome del dispositivo a cui ci vogliamo connettere.

Andiamo ora nella schermata "Controls".

Controls 8bot.png

Ci sono i pulsanti per le direzioni, un pulsante per connettersi a un altro dispositivo (che non fa altro che tornare a Screen1), e i pulsanti per la taratura (ancora in beta). Anche qui c'è BluetoothClient1. Appena arriva in questa schermata l'app si fermerà per permettere di fare l'accoppiamento tramite Bluetooth. Il pin è di solito 1234.

Initcontr.png

Se non riesce a connettersi o se clicchiamo "Connect" tornerà nella schermata di selezione precedente.

Controlscomm.png

I controlli sono molto semplici: ogni tasto invia un carattere. Quando viene rilasciato manda un carattere che spegne i servo. Non è ancora perfetto perché se perde la connessione i motori rimangono accesi, in futuro questo problema sarà corretto.

Trim8bot.png

Infine il codice per la calibrazione. A seconda se il robot sta andando avanti oppure indietro saranno calibrati i valori che vengono usati per muovere i motori. Purtroppo questa parte non è ancora scritta in modo efficace (ad es. il motore che va avanti in senso antiorario va più veloce con un valore INFERIORE, quindi per farlo andare più veloce occorre premere il tasto MENO). Quando la calibrazione è soddisfacente, con il tasto "Write" la si memorizza nella EEPROM dell'ATmega8.

I motori

L'8bot ha bisogno di due servo motori 9g continui, detti anche servo a 360°. Se volete risparmiare ulteriormente potete acquistare dei normalissimi servo a 180° e fare qualche modifica per trasformarli in 360°. Per effettuare la modifica seguite questa guida.

Lo chassis

Tutti gli .stl di 8bot li trovate su git [9]

Le ruote

Per le ruote ci sono due modelli, uno è della dimensione delle gomme delle mini4wd Tamiya[10]:

8bot4wd.png

mentre l'altro è della dimensione di un o-ring[11]:

8botoring.png

entrambe si incastrano sul pignone del servo senza bisogno di viti o altro (ma se volete metterne una, male non fa).

Il telaio

Il telaio è una piccola piattaforma con due fessure per inserire un'aletta del servi e un foro per la casterball. Recentemente ho aggiunto altre due alette per tenere fermo il portabatterie[12].

Chass.png

Corso di costruzione Ottobot

Nell'autunno 2016 a Raspibo un gruppo di makers si e' riunito specificamente per costruire Ottobot e programmarli sotto la guida paziente di Oloturia, creatore del progetto.

Materiale

Il materiale e' stato procurato dallo stesso Oloturia da vari fornitori durante l'estate con un occhio particolare ai costi per permettera tutti di realizzare un piccolo robot didattico.

Alcune parti progettate appositamente, sono state stampate in 3D.

Ad ogni partecipante del corso e' stato fornito un kit, oltre a questo ogni partecipante ha portato un po' di attrezzi ed un pc.

Il kit completo del corso ottobot

Preparazione dei motori

Nel kit i due servo possono essere sia a rotazione continua quindi gia' pronti oppure standard.

Per i motori standard e' neccessario procedere ad una modifica vedi Modifica_servo_rc_per_rotazione_continua

Assemblaggio del robot

Montare le ruote sul microservo modificato per rotazione continua
Le ruote vanno montate sull'asse con una vite che si trova nel sacchetto degli accessori del servo. Il tutto va poi incastrato sulla base. Se la stampa e' perfetta i motori si incastrano perfettamete sulla base altrimenti ci si puo' aiutare con colla, viti o nastro biadesivo.
Fissare la ball caster
Come terzo appoggio utilizziamo una ballcaster che consente liberta' di movimento e di sterzata. Inserire il pezzo nel foro centrale e fissarlo con tre viti, oppure colla.
Strumenti personali
Namespace

Varianti
Azioni
Navigazione
Strumenti