Differenze tra le versioni di "RaspiRuga"
(Creata pagina con 'Raspiruga è un robottino ideato per sperimentare due cose: un primo abbozzo di chassis fatto con la stampante 3d e l'impiego di motori passo-passo per ottenere più precision...') |
|||
Riga 175: | Riga 175: | ||
stepper2.started = False | stepper2.started = False | ||
= Il video = | = Il video = | ||
− | [http://www.youtube.com/watch?v=IlGY5-Tbwzs&feature=youtu.be|Funzionamento base della Raspiruga] | + | [http://www.youtube.com/watch?v=IlGY5-Tbwzs&feature=youtu.be| Funzionamento base della Raspiruga] |
Versione attuale delle 17:07, 26 gen 2014
Raspiruga è un robottino ideato per sperimentare due cose: un primo abbozzo di chassis fatto con la stampante 3d e l'impiego di motori passo-passo per ottenere più precisione nel movimento.
Componenti
- Due motori passo-passo (attualmente usati i 28BYJ-48[1], sono poco potenti ma estremamente economici)
- Due driver ULN2003, per i motori passo-passo
- Un Raspberry Pi (al momento Mod. B, ma spero di passare al Mod. A al più presto) dotato di relativo modulo cam e adattatore Wi-Fi USB
- Un caricabatterie di emergenza a 4 pile AA/stilo, usato per alimentare il Raspberry Pi
- Una mucchia di Lego®
- Ruote, stampate 3d! E due sedi per i motori, compatibili con i Lego® che compongono il resto dello chassis, sempre stampati 3d!
- Un servo e una biro, per scrivere
Il nostro nuovo amico, il motore passo-passo
Il motore passo-passo è un tipo particolare di motore elettrico. Invece di muoversi continuamente, si sposta di una frazione di angolo alla volta grazie a dei magneti attivati in successione, risultando così estremamente preciso nel suo movimento. Per contro velocità troppo alte potrebbero far saltare un passo. Potete trovare online parecchia documentazione a riguardo soprattutto per Arduino [2] ma usarlo con Raspberry Pi è altrettanto semplice.
Sulla destra ci sono i collegamenti per l'alimentazione (5v e terra), in basso sette pin collegati al ULN2003, dei quali saranno utilizzati solo i primi quattro. A questi pin si possono collegare direttamente le uscite della GPIO del Raspberry Pi.
Per far girare un motore passo occorre alimentare un magnete alla volta. Per migliori risultati è meglio alimentare il magnete successivo prima di spegnere quello precedente. La sequenza è questa:
1, 1-2, 2, 2-3, 3, 3-4, 4, 4-1
1- 1 1 0 0 0 0 0 1 2- 0 1 1 1 0 0 0 0 3- 0 0 0 1 1 1 0 0 4- 0 0 0 0 0 1 1 1
Ovviamente per far girare il motore nell'altro senso occorre invertire la sequenza.
La velocità del motore è data dall'intervallo fra un passo della sequenza e l'altro. Il limite per non far saltare i passi (per la precisione di python) è circa 0,001 secondi.
Scrivere
Ora la Raspiruga scrive! Un servo, una biro inutilizzata, et voilà!
Il codice, pasticciato e brutto
Le librerie usate per questo robottino sono:
- wiringpi2 [1] derivata da WiringPi di Gordon "Drogon" [2]
- time per la gestione delle temporizzazioni
- threading per la gestione dei thread
- subprocess per call, utile per richiamare comandi bash da dentro python, nello specifico serve per dare i comandi a ServoBlaster [3] per muovere i servo. Sui servo potete trovare più informazioni qui Servo (radio control).
I thread sono indispensabili in questo caso perché i due motori devono muoversi contemporaneamente. Ricordatevi di farli terminare quando il programma finisce perché altrimenti rimarranno attivi.
Questo programmino chiede all'utente la velocità, la direzione e la durata del movimento. Un altro parametro del movimento, la variabile accel della classe movement, è fissa a 10. A cosa serve accel? È il numero di passi richiesti per raggiungere la velocità richiesta a partire da 0,1 secondi. In questo modo l'accelerazione sarà progressiva e i motori non saranno sottoposti a sforzi eccessivi. La direzione è data dai comandi "fd" (forward), "bk" (back), "lt" (left), "rt" (right), la velocità da un numero superiore a 0 (il risultato è 1/velocità, es. velocità 20 corrisponde a 0,05 secondi). I comandi "pu" (pen up) e "pd" (pen down) servono per comandare il servo con la penna. Il demone servod deve stare nella stessa cartella di questo codice (oppure dovrete segnare il path nella chiamata call(["sudo ./servod"],shell=True)). Inoltre, per comodità, ho disattivato tutti i pin comandati da ServoBlaster tranne uno, il pin P1-7 (che corrisponde al pin 7 wiringpi), in modo da avere gli altri pin disponibili per altri scopi. La lista di pin è modificabile nel sorgente servod.c alla riga 156.
#!/usr/bin/python #pin 11,10,6,5 motore 1 #pin 14,13,12,3 motore 2 import wiringpi2 as wiringpi import time import threading from subprocess import call class movement(threading.Thread): accel = 10 realspeed = 0.1 decremento = 0.1 go = False started = False avanti = False def run(self): while self.started: if self.go: self.decremento = (self.realspeed-speed)/self.accel wiringpi.digitalWrite(self.motor[self.ix],1) self.px = self.ix if self.avanti: self.ix +=1 else: self.ix -=1 if (self.ix == 4): self.ix = 0 if (self.ix == -1): self.ix = 3 time.sleep(self.realspeed) wiringpi.digitalWrite(self.motor[self.ix],1) time.sleep(self.realspeed) wiringpi.digitalWrite(self.motor[self.px],0) if self.realspeed > speed: self.realspeed -= self.decremento else: self.realspeed = speed else: for x in self.motor: wiringpi.digitalWrite(x,0) self.realspeed = 0.1 wiringpi.wiringPiSetup() wiringpi.pinMode(11,1) wiringpi.pinMode(10,1) wiringpi.pinMode(6,1) wiringpi.pinMode(5,1) wiringpi.pinMode(14,1) wiringpi.pinMode(13,1) wiringpi.pinMode(12,1) wiringpi.pinMode(3,1) stepper1 = movement() stepper2 = movement() stepper1.motor = [10,11,6,5] stepper2.motor = [14,13,12,3] stepper1.go = False stepper2.go = False stepper1.started = True stepper2.started = True stepper1.start() stepper2.start() direction ="" denominator = 1.0 call(["sudo killall servod"],shell=True) call(["sudo ./servod"],shell=True) while (direction !="quit"): for x in stepper1.motor: wiringpi.digitalWrite(x,0) for x in stepper2.motor: wiringpi.digitalWrite(x,0) direction = raw_input("action?(fd/bk/lt/rt/pu/pd/quit) ") if direction != "fd" and direction != "bk" and direction !="lt" and direction !="rt" and direction !="pu" and direction !="pd" and direction !="quit": print "only fd,bk,lt,rt,pu,pd,quit" continue if direction != "quit": if direction != "pu" and direction !="pd": try: denominator = input("speed?(number, 0 exit) ") except NameError: print "only numbers" continue try: duration = input("duration?(seconds) ") except NameError: print "only numbers" continue if direction == "bk": stepper1.avanti = True stepper2.avanti = True elif direction == "fd": stepper1.avanti = False stepper2.avanti = False elif direction == "lt": stepper1.avanti = True stepper2.avanti = False elif direction == "rt": stepper1.avanti = False stepper2.avanti = True elif direction == "pu": call(["echo 0=90 > /dev/servoblaster"],shell=True) duration = 0 elif direction == "pd": call(["echo 0=160 > /dev/servoblaster"],shell=True) duration = 0 speed = 1.0/denominator time.sleep (0.5) stepper1.ix = 0 stepper2.ix = 0 stepper1.px = 0 stepper2.px = 0 stepper1.go = True stepper2.go = True time.sleep(duration) stepper1.go = False stepper2.go = False else: print "exit" call(["sudo killall servod"],shell=True) stepper1.started = False stepper2.started = False