RaspiRuga

Da raspibo.
Jump to navigation Jump to search
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

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.

Raspiruga.jpg


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.

Passopassopiccolo.jpg 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à!

Raspiruga writer1.jpg

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

Il video

Funzionamento base della Raspiruga