RaspiRuga

Da raspibo.

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


Indice

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

Strumenti personali
Namespace

Varianti
Azioni
Navigazione
Strumenti