WEEK ASSIGNMENT:
Mechanical Design and Machine Design
Make a machine, including the end effector, build the passive parts and operate it manually, automate your machine, document the group project and your individual contribution.
For this week activity we make a machine and automate the machine, so we decide to make a Styrofoam cutting machine.
The machine was design by Aristarco Cortes and Itan Fuentes, and Huber's contribution was automate the machine.
The Styrofoam cutting machine have 4 stepper motors: one on "X" and one in a 360° that move the base, and two in "Z" that move the tool: hot wire.
Mechanical design
We recycled an old base as it can be tell by the two guides on the x axle. I designed the Z axle posts and laser cut it. You can find the dxf file by clicking HERE. And the machine circular base by clicking HERE.
There is a mistake on the Z axis design regarding to the size of the motor. I did not consider in the design the material's width, so what we did was to manually cut the assembly "teeth" and glue it to the Z post.
X motor and 360° base
Z1 and Z2 motors
Electronic
To control the Stepper motors we use 4 gestalt nodes, FabNet adapter and a USB adapter
Control Software: Python Aplication
To control the Stepper motors we write a Python application for Ubuntu, based in the Single_Node and XY_Plotter from the gestalt demo codes.
This Python application read a txt file with instructions to place each stepper motor, this code read the instructions for motor x, motorz1, motor z2 and final to 360° motor.
/////////CODE://///////
# FabLab Puebla - Huber Giron Nieto
#------IMPORTS-------
from pygestalt import nodes
from pygestalt import interfaces
from pygestalt import machines
from pygestalt import functions
from pygestalt.machines import elements
from pygestalt.machines import kinematics
from pygestalt.machines import state
from pygestalt.utilities import notice
from pygestalt.publish import rpc #remote procedure call dispatcher
from Tkinter import *
import time
import io
motores = 'Motor1', 'Motor2', 'Motor3', 'Motor4',
r1=0
r2=0
r3=0
r4=0
cha = [0,0,0,0]
outx="En espera...x"
#------VIRTUAL MACHINE------
class virtualMachine(machines.virtualMachine):
def initInterfaces(self):
if self.providedInterface: self.fabnet = self.providedInterface #providedInterface is defined in the virtualMachine class.
else: self.fabnet = interfaces.gestaltInterface('FABNET', interfaces.serialInterface(baudRate = 115200, interfaceType = 'ftdi', portName = '/dev/ttyUSB0'))
def initControllers(self):
self.xAxisNode = nodes.networkedGestaltNode('Motor 1', self.fabnet, filename = '086-005a.py', persistence = self.persistence)
self.yAxisNode = nodes.networkedGestaltNode('Motor 2', self.fabnet, filename = '086-005a.py', persistence = self.persistence)
self.zAxisNode = nodes.networkedGestaltNode('Motor 3', self.fabnet, filename = '086-005a.py', persistence = self.persistence)
self.wAxisNode = nodes.networkedGestaltNode('Motor 4', self.fabnet, filename = '086-005a.py', persistence = self.persistence)
self.hNode = nodes.compoundNode(self.xAxisNode, self.yAxisNode, self.zAxisNode, self.wAxisNode)
def initCoordinates(self):
self.position = state.coordinate(['mm', 'mm', 'mm', 'mm'])
def initKinematics(self):
self.xAxis = elements.elementChain.forward([elements.microstep.forward(4), elements.stepper.forward(1.8), elements.leadscrew.forward(8), elements.invert.forward(False)])
self.yAxis = elements.elementChain.forward([elements.microstep.forward(4), elements.stepper.forward(1.8), elements.leadscrew.forward(8), elements.invert.forward(True)])
self.zAxis = elements.elementChain.forward([elements.microstep.forward(4), elements.stepper.forward(1.8), elements.leadscrew.forward(8), elements.invert.forward(False)])
self.wAxis = elements.elementChain.forward([elements.microstep.forward(4), elements.stepper.forward(1.8), elements.leadscrew.forward(256), elements.invert.forward(False)])
self.stageKinematics = kinematics.direct(4) #direct drive on all axes
def initFunctions(self):
self.move = functions.move(virtualMachine = self, virtualNode = self.hNode, axes = [self.xAxis, self.yAxis, self.zAxis, self.wAxis], kinematics = self.stageKinematics, machinePosition = self.position,planner = 'null')
self.jog = functions.jog(self.move) #an incremental wrapper for the move function
pass
def initLast(self):
# self.machineControl.setMotorCurrents(aCurrent = 0.8, bCurrent = 0.8, cCurrent = 0.8)
# self.hNode.setVelocityRequest(0) #clear velocity on nodes. Eventually this will be put in the motion planner on initialization to match state.
pass
def publish(self):
# self.publisher.addNodes(self.machineControl)
pass
def getPosition(self):
return {'position':self.position.future()}
def setPosition(self, position = [None]):
self.position.future.set(position)
def setSpindleSpeed(self, speedFraction):
# self.machineControl.pwmRequest(speedFraction)
pass
#CODIGO INTERFAZ GRAFICA
def fetch(entries):
aza=1
for entry in entries:
motorx = entry[0]
paxo = int(entry[1].get())
print('%s: "%d"' % (motorx, paxo))
if aza==1:
r1=paxo
elif aza==2:
r2=paxo
elif aza==3:
r3=paxo
elif aza==4:
r4=paxo
aza=aza+1
supercoords = [[r1,r2,r3,r4]]
for coords in supercoords:
stage.move(coords, 0)
status = stage.xAxisNode.spinStatusRequest()
while status['stepsRemaining'] > 0:
time.sleep(0.001)
status = stage.xAxisNode.spinStatusRequest()
def makeform(root, motores):
entries = []
for motorx in motores:
row = Frame(root)
lab = Label(row, width=15, text=motorx, anchor='w')
ent = Entry(row)
row.pack(side=TOP, fill=X, padx=5, pady=5)
lab.pack(side=LEFT)
ent.pack(side=RIGHT, expand=YES, fill=X)
ent.insert (10,0)
entries.append((motorx, ent))
return entries
# CODIGO PARA LEER UN TXT
def decodifica():
numerocuenta=0
to=0
ls=0
ps=0
ry1=0
ry2=0
ry3=0
ry4=0
print ("Decodificando....")
po = caja1.get()
print("%s" % po)
while(not((po[numerocuenta]=='\n') and (po[numerocuenta+1]=='\n'))):
if(po[numerocuenta]!=',' and po[numerocuenta]!='\n'):
cha[ls]=(int(po[numerocuenta]))
ls= ls + 1
elif(po[numerocuenta]==','):
to= (cha[0]*(10**(ls-1)))+(cha[1]*(10**(ls-2)))+(cha[2]*(10**(ls-3)))
print("%d:" % to)
ps=ps+1
if (ps==1):
ry1=to
elif (ps==2):
ry2=to
elif (ps==3):
ry3=to
cha[0]=0
cha[1]=0
cha[2]=0
cha[3]=0
to=0
ls=0
if(po[numerocuenta+1]=='\n'):
to= (cha[0]*(10**(ls-1)))+(cha[1]*(10**(ls-2)))+(cha[2]*(10**(ls-3)))
print("%d:" % to)
ry4=to
muevete(ry1,ry2,ry3,ry4)
cha[0]=0
cha[1]=0
cha[2]=0
cha[3]=0
to=0
ls=0
ps=0
numerocuenta=numerocuenta+1
def muevete(hx1,hx2,hx3,hx4):
r1=hx1
r2=hx2
r3=hx3
r4=hx4
print("Motor1: %d" % r1)
print("Motor2: %d" % r2)
print("Motor3: %d" % r3)
print("Motor4: %d" % r4)
supercoords = [[r1,r2,r3,r4]]
outx= ("%d , %d , %d , % d" %(r1, r2, r3, r4))
var.set(outx)
root.update_idletasks()
for coords in supercoords:
stage.move(coords, 0)
status = stage.xAxisNode.spinStatusRequest()
while status['stepsRemaining'] > 0:
time.sleep(0.001)
status = stage.xAxisNode.spinStatusRequest()
#
# CODIGO PARA ir a CERO
def ZERO():
muevete(0,0,0,0)
#
#------IF RUN DIRECTLY FROM TERMINAL------
if __name__ == '__main__':
stage = virtualMachine(persistenceFile = "test.vmp")
stage.hNode.setVelocityRequest(4)
root = Tk()
root.title('FabLab Puebla - CNC Machine')
root.geometry("700x170+0+0")
var = StringVar()
# nuevo codigo
caja1= Entry(root)
caja1.pack(side=LEFT, padx=5, pady=5)
b2 = Button(root, text='Cortar', bg='red', command=(lambda : decodifica()))
b2.pack(side=LEFT, )
labZX= Label(root, width=15, textvariable=var)
labZX.pack(side=LEFT, padx=5, pady=0)
var.set(outx)
#
ents = makeform(root, motores)
root.bind('<Return>', (lambda event, e=ents: fetch(e)))
b1 = Button(root, text='Avanza', bg='green',
command=(lambda e=ents: fetch(e)))
b1.pack(side=LEFT, padx=55, pady=5)
b2 = Button(root, text='Zero', bg='green',
command=(lambda : ZERO()))
b2.pack(side=LEFT, padx=5, pady=5)
root.mainloop()
Each participant made a different code
Aristarco
/////////CODE:///////// PIRULI
0,0,0,0
0,180,180,0
0,150,150,0
150,150,150,0
150,180,180,0
0,180,180,0
30,180,180,0
30,150,150,0
30,0,0,64
0,0,0,64
0,150,150,64
30,150,150,64
30,0,0,128
0,0,128
0,150,150,128
30,150,150,128
30,0,0,192
0,0,0,192
0,150,150,192
30,150,150,192
30,0,0,256
0,0,0,256
Huber's
/////////CODE:///////// Waffle
0,0,0,0
0,32,32,0
16,55,55,0
33,42,42,0
49,55,55,0
66,42,42,0
82,55,55,0
100,42,42,0
130,42,42,0
130,22,22,0
130,22,22,64
100,22,22,64
82,45,45,64
66,22,22,64
49,45,45,64
33,22,22,64
16,45,45,64
0,22,22,64
Itan's
////////CODE:///////// COPA
5,0,0,0
5,10,10,0
30,10,10,0
30,40,40,0
0,70,70,0
0,100,100,0
90,100,100,0
90,70,70,0
60,40,40,0
60,10,10,0
90,10,10,0
90,0,0,0
110,0,0,0
110,0,0,43
90,0,0,43
90,10,10,43
60,10,10,43
60,40,40,43
90,70,70,43
90,100,100,43
0,100,100,43
0,70,70,43
30,40,40,43
30,10,10,43
0,10,10,43
0,0,0,43
0,0,0,86
5,0,0,86
5,10,10,86
30,10,10,86
30,40,40,86
0,70,70,86
0,100,100,86
90,100,100,86
90,70,70,86
60,40,40,86
60,10,10,86
90,10,10,86
90,0,0,86
110,0,0,86
110,0,0,129
90,0,0,129
90,10,10,129
60,10,10,129
60,40,40,129
90,70,70,129
90,100,100,129
0,100,100,129
0,70,70,129
30,40,40,129
30,10,10,129
0,10,10,129
0,0,0,129
0,0,0,172
5,0,0,172
5,10,10,172
30,10,10,172
30,40,40,172
0,70,70,172
0,100,100,172
90,100,100,172
90,70,70,172
60,40,40,172
60,10,10,172
90,10,10,172
90,0,0,172
110,0,0,172
110,0,0,215