I am using a stepper motor for FabInABox. Characteristics of stepper motors are
A stepper motor works by alternating electromagnets to create attractions in the direction of rotation. Teeth are pulled one step to a lower energy state based on the state of the electromagnets. Switching the energy of the electromagnets again will cause a different teeth to be pulled to a lower energy state.
Current motors on FabInABox are 4209M-02P stepper motors from Lin Engineering. Specs:
Professor Ian Hunter probably showed the best example of a stepper motor with a demo he built in his BioInstrumentation Lab. Four cutler-hammers are used to allow current to flow to a specific lead. By "playing" the hammers in the correct order, you can create attractions to pull the teeth in the right direction.
There is an example code for xy_plotter for the use of gestalt for modular axis. I used that to create xyz_plotter and add an extra degree of freedom to see if I could control FabInABox this way. Hard coded the word "FAB". Came out better than I expected. Also had to create a z-check.py to check the vertical distance of the marker. Wherever the pen is is the 0,0,0, but I did not like the big circle left when I moved the pen with the arrow keys to get it to the start position. Instead, z-check.py runs down a few mm, and I adjust the height of the bed until the marker barely touches the stickers.
#------IMPORTS------- from gestalt import nodes from gestalt import interfaces from gestalt import machines from gestalt import functions from gestalt.machines import elements from gestalt.machines import kinematics from gestalt.machines import state from gestalt.utilities import notice from gestalt.publish import rpc #remote procedure call dispatcher import time import io #------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 = 'COM3')) #'/dev/ttyUSB0')) def initControllers(self): self.xAxisNode = nodes.networkedGestaltNode('X Axis', self.fabnet, filename = '086-005a.py', persistence = self.persistence) self.yAxisNode = nodes.networkedGestaltNode('Y Axis', self.fabnet, filename = '086-005a.py', persistence = self.persistence) self.zAxisNode = nodes.networkedGestaltNode('Z Axis', self.fabnet, filename = '086-005a.py', persistence = self.persistence) self.xyzNode = nodes.compoundNode(self.xAxisNode, self.yAxisNode, self.zAxisNode) def initCoordinates(self): self.position = state.coordinate(['mm','mm','mm']) #X,Y,Z def initKinematics(self): self.xAxis = elements.elementChain.forward([elements.microstep.forward(4), elements.stepper.forward(1.8), elements.leadscrew.forward(8), elements.invert.forward(True)]) 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(2), elements.invert.forward(False)]) self.stageKinematics = kinematics.direct(3) #direct drive on all three axes
Then I hard coded the x,y,z coordinates to draw out "FAB"
stages.xyzNode.setVelocityRequest(8) moves = [[10,50,-26],[10,50,-30],[0,50,-30],[0,30,-30],[0,30,-26].... ] for move in moves: stages.move(move, 0) status = stages.xAxisNode.spinStatusRequest() # This checks to see if the move is done. while status['stepsRemaining'] > 0: time.sleep(0.001) status = stages.xAxisNode.spinStatusRequest()
Finally, I was able to set up a manual mode to control the three axes. It used wxPython, a gui widget for python. Credit goes to Nadya for make_png_mmtmdraw, which I used as a starting point.