FABLAB TRIVANDRUM

We are a bunch of enthusiastic engineers who are curious about technology and are passionate about making them.

Fab Arm

Fab Arm is a desktop version of a robotic arm capable of doing a multitude of things. From Drawing images to laser cutting, it can be programmed to do almost everything its industrial cousin can.

Next

Why we did this ?

Man's pursuit has always been to imitate nature. Human hands are highly dexterous, capable of doing multiple tasks. We wanted to try and bring the same functionality with robotics. A platform which can be programmed to do almost anything.

Next

Fabrication of FabArm in our FabLab fabricated by

Ideation

The people in our lab are from varied backgrounds, some Mechanical engineers, some Electronics engineers and some Computer Science Engineers ans since its the first time we are doing a big project like this, all of decided to join together and form a single team.

Initially we were confused about what to make. Our group brain stormed for many project ideas this week. Some of the ideas we discussed about where

  • > Digital Embroidery Sewing Machine
  • > Vertical plotter
  • > Hang 3D printer
  • > Wireless White board Drawing robot
  • > Foam cutting machine
  • > CNC Desktop Coil winding machine.
  • > Sand Sculpting Machine

Finally we decided to make the robotic arm and also add a linear guide rail system to it.

The initial sketch of the proposed plan. It has a Robotic arm mounted on a linear guide rail assembly. When finished this robot will have the capability of picking an placing objects, X-Y plotting, laser cutting etc. Certain modification need to be made to the original U arm design to fit our needs.

Fab Arm is based on U arm an open source multipurpose desktop robotic hand. We chose the U arm because of the simplicity of its design, there are no motors in the arm, all the electronics are contained in the base itself. This makes the arm even more responsive and simpler in construction.

We did not want to start from scratch when a lot of people have already worked on many designs. Hence taking into consideration the amount of time we have, we decided to take an existing design and augment it. We will make a fab version of the U arm with some modification and extra functionalities like a linear rail system for the arm to move about.

Delegation of work

Once the project was finalized the next step is to divide the work. Since a lot of us are from varied backgrounds we discussed With each other and everyone was allocated parts of the work which they were most comfortable with.

Proof of Concept

As a proof of concept we decided to make a prototype version of the arm to see if we can build it with all the parts available in our lab. The original design required for a large set of unique parts. These are going to be difficult to find, hence we planned to modify the design and make the parts which we could not acquire.

For our first try, we decided to make the design on Cardboard to really understand how the different parts come together and understand the whole assembly.

The cardboard model was good to understand how all the pieces come together but it was too flimsy to be considered a prototype. We need to test the joints to understand how to make parts for them, for that we need to make the arm in something much more rigid. We decided to go with wood the next time.

Finding Parts

We went through our local shops to identify the parts which we needed, we were able to acquire most of the Standard screws(M4,M3,M2) which we needed.

Designing spacers for the joints

There are a lot of moving joints in the fab arm and each joint is supposed to have a bearing to allow for friction less movement.

We require a total of 24 Nos of Flange Bearing MF84ZZ. This is a small flange bearing and is not available locally, So replacement to that we planned a spacer of dimension of 4.2mm inner diameter and 8.7mm outer diameter. Designed the spacers in Rhino and printed using ultimaker.

The next part which we could not find is the Brass standoffs.

Design of Standoffs

A standoff is a threaded separator of defined length used to raise one assembly above another. They are usually round or hex (for wrench tightening), often made of aluminum, brass, or nylon, and come in male-female or female-female forms. In our project we require M4 and M3 Standoffs of different sizes. The total requirement of standoffs for our project are summarized below.

Standoff requirement for FAB-ARM

  1. * Stand-offs M4X10mm - 4Nos
  2. * Stand-offs M4X15mm- 1No
  3. * Stand-offs M4X22mm- 4Nos
  4. * Stand-offs M4X55mm- 2Nos
  5. * Stand-offs M4X65mm- 1No
  6. * Stand-offs M3X8mm- 2Nos
We have searched the standoff availability in local shops but we didn't get the brass standoffs. So we planned to design and 3D print it on 3D printer with plastic as the replacement for brass standoffs.

The hexagonal shaped standoffs were designed using Rhinoceros software. Sufficient width was given the to walls to get enough strength in the standoffs.

The 3mm standoffs were made for holding the control board and all other arm parts needs 4mm Standoffs. The picture shown below is the assembly diagram of the arm in that we can clearly understand the use of standoffs.

Challenges Faced

The requirement for the stand off was 4mm, so the first test pieces was designed with dimension of 4mm and fabricated in ultimaker. When we tested the 3D printed part on a M4 cheese head screw we found that the piece was really tight.

Since the screw has threads on it we wanted the hole to be tight enough so that the threads will hold but loose nough so that we can turn it easily.

So we changed the dimension to 4.1mm, 3D printed again and this time it worked.

Corrected design print on Ultimaker 3D printer, print was given in batches. The image shown below is the printing of 10mm standoffs in ultimaker.

Making a prototype of Arm

Since we will be designing and fabricating most of the parts for the arm we decided to make a prototype of the arm on scrap pieces of wood to make sure all the dimensions are correct and figure out how the joints are going to come together and what all parts do we need to make.

We laser cut all the parts for the arm in scrap pieces of wood.

Now that we have all the screws,the spacers and the stand offs we are ready to put the arm together.

Assembling the Prototype Arm

After cutting the parts, we started assembling it with the screws and other fasteners by referring the assembly instructions form the uarm documentation page. Assembling the servos into the side plates was the difficult part of the build since, it is having a lots of parts and fasteners with different sizes. It's taken almost 6 hours to complete the assembly. The selfie with Fab-arm was awesome ,because we have finished it in morning 2:15 am.

Servo Trouble shooting and Load Testing

We require 3 Servos to control the arm. This week the assignment is to build a machine and move it mechanically ,but we planned to move the arm electronically by driving the servos using the arduino. Renjith was incharge of load testing, he started testing servos individually, while testing individual servos it was observed that one of them is not working and while connecting to arduino the arduino is getting some errors.

In order to figure it out the error we checked the servo and found that the VCC and GND line were shorted in servo. So the servo was removed and done some passive measurements were done. It was found that in the control board one SMD capacitor is short, for time being we kept it aside for further analysis.

Load testing

Load testing is performed to determine the maximum torque of the motor under different load conditions. We have Hobbyking HK15138 standard analog servo which is having a torque of 4.3Kg at 6V, first we have to test it with our arm before integrating it to the arm.

After completing the arm assembly the servo motor was integrated on the arm and we have done load testing, used Neodymium magnet as the load . Placed equal quantity of magnets on the two sides of the arm on the M4 screws and done the test.

We found that at 5V the arm is capable to a maximum load of 60 grams and the craft wood arm parts weighed around 59 grams . So in total it taken maximum 110gm of load at 5V.

In our case we don't have any higher torque servos available in our lab . So we planned to use this for the first version prototype and to procure new servos or to replace with stepper with higher torque for our final prototype.

Servo programming and calibration

After doing the interconnections, we tested the servos individually using arduino and identified the electrical limits of the motor, for this we used three 10K resistors and using the potentiometer the angular rotation of the servos are controlled. The potentiometers were connected to the power supply of +5V , Arduino is having 10 bit ADC with the signal range between 0-5V. The mechanical limits of each servo motors will be different and we need to calibrate it before using it. Here is the code we are worked to calibrate the servo motors. Servo calibration using potentiometers /add servo library #include < Servo.h> //define our servos Servo servo1; Servo servo2; Servo servo3; int i=100; //variable to read the values from the analog pin (potentiometers) int valPot1; int valPot2; int valPot3; char inByte; int a=5; void setup() { Serial.begin(9600); //attaches our servos on pins PWM 9,10,11 to the servos servo1.attach(9); servo1.write(150); //define servo1 start position servo2.attach(10); servo2.write(90); //define servo2 start position servo3.attach(11); servo3.write(90); //define servo3 start position } void loop() { valPot1=100; servo1.write(valPot1); i=i+a; valPot2 =i; servo2.write(valPot2); valPot3=45;; servo3.write(valPot3); delay(100); if(i==145) a=-5; if(i==100) a=5; } After doing the above calibration we are able to find different points manually and next we planned to change the potentiometers and instead to put the positional values directly to the servo motors in order to move the fab arm in a particular direction. The below showed programm doing the same. The points were given in such a way to move the arm to draw circular shapes. /add servo library #include < Servo.h> //define our servos Servo servo1; Servo servo2; Servo servo3; Servo servo4; int i=100; //variable to read the values from the analog pin (potentiometers) int valPot1[]={100,100,100,100,102,102,102,118,128,138,145,152,152,157,157,157,157,157,157,157}; int valPot2[]={139,137, 113, 88, 71, 71, 71,71, 71, 71, 71, 71,71, 71, 88, 100, 108, 118, 117, 118}; int valPot3[]={45, 45, 45, 45, 45, 86, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 56, 48, 45}; char inByte; int a=1; void setup() { Serial.begin(9600); //attaches our servos on pins PWM 3-5-6-9 to the servos servo1.attach(9); servo1.write(150); //define servo1 start position servo2.attach(10); servo2.write(90); //define servo2 start position servo3.attach(11); servo3.write(90); //define servo3 start position } void loop() { for(int i=1;i<=19;i++) { servo1.write(valPot1[i]); //set the servo position according to the scaled value servo2.write(valPot2[i]); servo3.write(valPot3[i]); delay(500); } for(int i=19;i>=1;i--) { servo1.write(valPot1[i]); //set the servo position according to the scaled value servo2.write(valPot2[i]); servo3.write(valPot3[i]); delay(500); } } In the above code you can see the default pot values i.e for each potentiometers pot1,pot2 & pot3. After flashing the program the arm started moving in circular movement. But we feel oscillations were there on the arms . We connected a pen to the end effector and it started drawing the circular shapes on the notebook.

Designing various End Effectors

Pen holder
We planned this arm to be used for multipurpose use like pick and place,plotter etc. So we designed a pen holder for it as an end effector in Rhinoceros. It is having two parts one is a 2D base part to fix into the head of the arm which made using craft wood and the second part is a 3D printed pen holder. The design and 3D printed parts are shown below.

After the design the base part was exported in .dxf format and cut using laser cutter. The 3d design of penholder was printed on Dimension SST1200es printer on ABS plastic both parts are shown below.

We had done some basic testing of the arm in three axis with the arduino board. we did the programming for moving each servos in particular angles, our main aim was to move the arm in all three directions simultaneously.

Since we did not yet have the bearing for the base, we temporarily fixed the arm on the base by fixing a servo horn on the base and putting the arm on top of it. We require a bearing to mount the base to solve this issue, we have ordered for the bearing and expecting the earliest delivery . Mounted the Mini sharpie over the end effector and moved the arms and sketched some lines with the arm. The hero shot of our arm with the pen holder end effector is shown below.

Object picker clamp
This is another end effector we made. This end effector consists of two jaws one of that can be fitted on to the main arm and the other can be used to open and close the clamp. First we used fusion360 to make the designs from a drawing and later the parts where 3d printed. The following images show the making.

Finally after assembling the fabarm and the end effector,

Object Holder
We did another end effector which we intend to use it for holding objects. The designs were obtained from the u-arm designs. It laser cut the parts needed and assembled them with a small servo motor.

Making the actual Fab Arm

After making a prototype of the arm, we figured out all the problems with it and which all parts we need to modify to make the arm with the parts we have. The design changes was handled by Jim and we started making the final arm after redesigning and making all the spare parts for it.

We found a replacement for the flange shafts, which we did not have during the earlier prototype, using Aluminum rod which we took apart from an old printer. We had to cut the rod based on our design for which we used the driller and attached the aluminum rod to the drill head. We then used a saw blade to cut when the driller is activated. The rod started heating up during the process, we used a small wooden piece from making direct contact with the rod.

We started with laser cutting the Fab Arm parts in 4mm craft plywood. In the actual design the bearing used are of internal diameter of 35mm and outer dia of 42mm and this was replaced by the ball bearing of 37mm internal dia and 52mm outer dia.

Ganadev and Syed completed the rest of the assembly,

We measured the dimensions for the locally sourced bearing and revised the bearing support base for the assembly.

Rahul and Jim started designing a linear rail for giving the horizontal movement of the entire arm.

Design of the Linear guide rails

Jim designed a Linear guide rail carriage for our robotic arm, on Fusion 360. The images shown below are the screen shots of Rail design. The intention was to make all the parts using the machines available in our lab. So as to eliminate to buy any parts to be bought for the rails. So the first design was to cut the rails, rollers everything in acryllic, and to have a stepper motor drive integrated to a moving carriage supported on rollers. This design is illustrated in the below images and CAD model.

But later, we found that having this many moving parts is not a very good idea considering the precise movement expected from our machine. So we explored various other ideas, and during one of the weekly lecture sessions Neil mentioned about fabricatable-machines. We explored the gantry design on github, and found that to be simple and robust for our operation.

The Gantry rail that we finally based our design on (source : github)

Making a Linear Guide Rail

We decided to make the simple gantry mechanism designed by Jens Dyvik. You can find it onGithub . Since we don't have the bird beak bit required to cut v-rails on both sides at the same time. we decided to switch over to the chamfer rails.

The next problem is the availability of materials. The High density plastic which we require for cutting the rails is not easily accessible in our region. And the cost is significantly higher. Hence for our first try we chose to stick to the fab inventory and go with 6mm acrylic. Now this poses another set of challenges.

Jens's design was for material thicker than 10mm. Hence we are going to try a really hands on approach and bolt together two pieces of acrylic.

Test cutting Acrylic

In our lab we have never cut acrylic using shopbot hence we had to start from scratch and figure out the machine settings. we began test cutting the acrylic with different settings based from the original bit settings. Acrylic is denser than wood and hence we reduced the feedrate, plungerate, etc.

Cutting out acrylic is a bit tricky, if the feed is high it might melt and deposit on the bit. Start with a really low speed and progress up. We started with less than half the feedrate of wood and proceeded to find the optimal value.

The shopbot bed has to be perfectly level when cutting the chamfer rail. Well the sacrificial layer in our shopbot has seen better days, there are some variations in certain places. But we found a good place and decided to fit the sheet there.

You have to be really careful when fixing acrylic to the bed. If you screw it in with large force then the sheet will crack.

Cutting the Glide block.

The glide block is designed to slide on the chamfer rails. Jens original design requires a material thickness of 10mm or above. We only have 6mm acrylic. Hence we scaled it down to fit the 6mm acrylic.

The reason we have to use the shopbot and not the laser cutter is because we have to cut a 45deg chamfer on one side of the rail. the chamfer serves the purpose of aligning the glide blocks on the rails. Hence it is a requirement.

Cutting the Chamfer Rail

The chamfer rails were made from the modified design of Jens and we decided to make a test rail in acrylic.

The design was imported into Vcarve and the tool paths were set.

The sequence is to first cut the chamfer, then Drill the holes and then cut the teeth.For cutting the chamfer we have a 90Deg V-bit, which we use for engraving. I cut the chamfer with the V-bit after changing the machine setting to cut acrylic.

The main purpose of this test cut was to see if it was possible to make the chamfer rails out of 6mm acrylic. We removed some of the additional features of the rail for simplicity. The next step is to cut the final rail.

Cutting the Pinion

The pinions were cut in the laser because we did not have small enough end mills to make it in shop bot.

We test cut multiple sizes to get a pinion that will press fit with the stepper shaft.

Rahul was called up in this weeks review and he explained to Neil what our plan was, Neil suggested that acrylic is too fragile a material to serve as the rail and told us to look for other possible materials like POM or Delrin.

Making the Chamfer Rail in PVC foam board

We found some scrap foam board and decided to make the rail with that.Since this is a new material we had to test cut it to make sure figure out the machine parameters.

The rail is 60cm long and 18mm thick, The ecoboard is holding it shape nicely, but if you apply pressure at a sharp corner, you will deform the material. Its not the idea material for making a mechanical structure.

The next step was to make the guide blocks. We made some modifications to the guide block so that we can make it in this material.

We attached to stepper motor using the motor plate to the final gantry system.

Next we had to figure out how to attach the arm on the gantry system. We decided to make a base which rests on top of the stepper motor. For securing it properly, we made a piece which will press fit with the stepper and then the base can be attached on top of it.

Once the base is secured then the arm can be fixed on top it.

FABNET Bridge board fabrication and Gestalt node Testing

We have gone through the gestalt node documentation from thearchives and the documentation by Nadia.

The configuration of gestalt with stepper motors is shown in the below figure.

FABNET Bridge Board

Fabnet Bridge board is the interface board between the PC and individual gestalt nodes called fab nets. Individual Fabnet contains an RS-485 bus with a few additional signals. FTDI cable is used for communicating with the fab nets using fabnet bridge board. The FTDI cable provided is a little different than the other FTDI cables we've been using; it is an RS-485 version. Here's its pinout for reference:

We need to create a bridge board, the files are already available from the link. The design files were opened in eagle software and exported it to png files and processed using modela CNC.

The Pcb is simple one to split the FTDI lines to gestalt node. It is having two 604 ohm resistors which is not in the inventory part and we got it as the part of gestalt node.The pcb milling and cutout files are given below.

The pcb is milled and soldered two resistors and the FTDI cable as per the layout diagram and final board is shown below.

Electrical configuration

Fab Arm is having 3 servos for basic movements and one stepper mounted to drive the linear rails. After the assembly, 3 servos are mounted on the fab arm and we planned to start testing the servo motors. An electrical interconnection plan for the project in draw.io and is shown below.

The servos and stepper that are setup on our fab arm.

Ganadev used the fabnet to test the gestalt boards and worked towards integrating multiple stepper motors via gestalt.





We used the stepper motor to drive the fabarm through the guide rail that Rahul did using Jen's design,





Ganadev continued with the arduino code shown earlier to control the fabarm and worked on implementing serial communication.

Serial Communication is handled with the following characters 'a', 'b', 'c', 'e', 'f' with each character having different functions. 'a' and 'd' control one servo motor to go on either directions. Same goes for the rest 'b' & 'e', 'c' & 'f'. Character 's' is to just for logging the values for debugging purpose.

//add servo library #include < Servo.h> //define our servos Servo servo1; Servo servo2; Servo servo3; //Servo servo4; //define our potentiometers //int pot1 = A0; //int pot2 = A1; //int pot3 = A2; //int pot4 = A3; //variable to read the values from the analog pin (potentiometers) int valPot1 = 120; int valPot2 = 90; int valPot3 = 90; //int valPot4; char inByte; void setup() { Serial.begin(9600); //attaches our servos on pins PWM 3-5-6-9 to the servos servo1.attach(9); servo1.write(valPot1); //define servo1 start position servo2.attach(10); servo2.write(valPot2); //define servo2 start position servo3.attach(11); servo3.write(valPot3); //define servo3 start position // servo4.attach(6); // servo4.write(70); //define servo4 start position } void loop() { //reads the value of potentiometers (value between 0 and 1023) // while (1); // valPot1 = analogRead(pot1); // valPot1 = map (valPot1, 0, 1023, 100, 180); //scale it to use it with the servo (value between 0 and 180) // servo1.write(valPot1); //set the servo position according to the scaled value ////------------------------------------------------------------- // valPot2 = analogRead(pot2); // valPot2 = map (valPot2, 0, 1023, 0, 180); // servo2.write(valPot2); // //----------------------------------------------------------------- // valPot3 = analogRead(pot3); // valPot3 = map (valPot3, 0, 1023, 45, 130); // servo3.write(valPot3); // // valPot4 = analogRead(pot4); // valPot4 = map (valPot4, 0, 1023, 70, 150); // servo4.write(valPot4); if (Serial.available()) { inByte = Serial.read(); switch (inByte) { case 'a': Serial.print("a"); valPot1 += 1; servo1.write(valPot1); Serial.println(" "); break; case 'b': Serial.print("b"); valPot2 += 1; servo2.write(valPot2); Serial.println(" "); break; case 'c': Serial.print("c"); valPot3 += 1; servo3.write(valPot3); Serial.println(" "); break; case 'd': Serial.print("d"); valPot1 -= 1; servo1.write(valPot1); Serial.println(" "); break; case 'e': Serial.print("e"); valPot2 -= 1; servo2.write(valPot2); Serial.println(" "); break; case 'f': Serial.print("f"); valPot3 -= 1; servo3.write(valPot3); Serial.println(" "); break; case 's': Serial.print(byte(valPot1)); Serial.print(" "); Serial.print(byte(valPot2)); Serial.print(" "); Serial.print(byte(valPot3)); Serial.println(" "); break; case '\n': break; default: Serial.print("Wrong Input"); Serial.println(" "); } } } We used the arduino code to do a cleaning like action,



Along the same timeline, Ganadev worked on the GUI based on kivy.

from kivy.uix.popup import Popup from kivy.app import App from kivy.uix.gridlayout import GridLayout from kivy.uix.label import Label from kivy.uix.textinput import TextInput from kivy.uix.button import Button from kivy.uix.boxlayout import BoxLayout from kivy.uix.stacklayout import StackLayout from kivy.uix.slider import Slider from kivy.config import Config Config.set('modules', 'serial', '') # Forked from DFUnitVM Oct 2013 # set portname # set location of hex file for bootloader # #------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 import time import io import threading import serial #------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/tty.usbserial-FT0METG6')) def initControllers(self): self.xAxisNode = nodes.networkedGestaltNode('X Axis', self.fabnet, filename = '086-005a.py', persistence = self.persistence) self.xNode = nodes.compoundNode(self.xAxisNode) def initCoordinates(self): self.position = state.coordinate(['mm']) def initKinematics(self): self.xAxis = elements.elementChain.forward([elements.microstep.forward(4), elements.stepper.forward(1.8), elements.leadscrew.forward(6.096), elements.invert.forward(True)]) self.stageKinematics = kinematics.direct(1) #direct drive on all axes def initFunctions(self): self.move = functions.move(virtualMachine = self, virtualNode = self.xNode, axes = [self.xAxis], 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.xyzNode.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 class FabControl(GridLayout): def __init__(self, **kwargs): super(FabControl, self).__init__(**kwargs) self.cols = 3 self.row = 3 global serialcom, tempmotor1, tempmotor2, tempmotor3 tempmotor1 = 120 tempmotor2 = 90 tempmotor3 = 90 serialcom = serial.Serial() serialcom.braudrate = 115200 serialcom.port = "/dev/tty.usbmodem1421" serialcom.open() self.add_widget(Label(text='Motor1 [ 0 to 120 ] ')) self.motor1 = Slider(min=-30, max=120, value=120) self.motor1.bind(value=self.Motor1Change) self.add_widget(self.motor1) self.motor1value = Label(text=str(self.motor1.value)) self.add_widget(self.motor1value) self.add_widget(Label(text='Motor2 [ 0 to 180 ] ')) self.motor2 = Slider(min=0, max=180, value=90) self.motor2.bind(value=self.Motor2Change) self.add_widget(self.motor2) self.motor2value = Label(text=str(self.motor2.value)) self.add_widget(self.motor2value) self.add_widget(Label(text='Motor3 [ 45 to 130 ] ')) self.motor3 = Slider(min=45, max=130, value=90) self.motor3.bind(value=self.Motor3Change) self.add_widget(self.motor3) self.motor3value = Label(text=str(self.motor3.value)) self.add_widget(self.motor3value) self.add_widget(Label(text='Motor4 [ -100 to 100 ] ')) self.motor4 = Slider(min=-100, max=100, value=0) self.motor4.bind(value=self.Motor4Change) self.add_widget(self.motor4) self.motor4value = Label(text=str(self.motor4.value)) self.add_widget(self.motor4value) self.move = Button(text="Move") self.add_widget(self.move) self.move.bind(on_press=self.initiatemove) self.startrec = Button(text="Start Record") self.add_widget(self.startrec) self.stoprec = Button(text="Stop Record") self.add_widget(self.stoprec) self.play = Button(text="Play") self.add_widget(self.play) def Motor4Change(self, instance, value): self.motor4value.text = str(value) def Motor1Change(self, instance, value): self.motor1value.text = str(value) threading.Thread(target=self.movemotor1).start() def Motor2Change(self, instance, value): self.motor2value.text = str(value) threading.Thread(target=self.movemotor2).start() def Motor3Change(self, instance, value): self.motor3value.text = str(value) threading.Thread(target=self.movemotor3).start() def initiatemove(self,instance): # time.sleep(5) threading.Thread(target=self.movemotor4).start() threading.Thread(target=self.movemotor1).start() threading.Thread(target=self.movemotor2).start() threading.Thread(target=self.movemotor3).start() def movemotor4(self): print "movemotor4 called" global stage # print stage # print self.motor4.value # print self.motor1.value # print self.motor2.value # print self.motor3.value # movemotor4 = int(self.motor4.value) supercoords = [[movemotor4]] for coords in supercoords: stage.move(coords, 0) status = stage.xAxisNode.spinStatusRequest() while status['stepsRemaining'] > 0: time.sleep(0.001) status = stage.xAxisNode.spinStatusRequest() # ser = serial.Serial() # ser.braudrate = 115200 # ser.port = "/dev/tty.usbmodem1411" # ser.open() def movemotor1(self): print "movemotor1called" global serialcom, tempmotor1 movemotor1 = self.motor1.value - tempmotor1 tempmotor1 = self.motor1.value print movemotor1 # print movemotor2 # print movemotor3 if serialcom.isOpen(): print("serialcomial is open!") # serialcom.write('a\n') if movemotor1 > 0: for i in range(int(movemotor1)): print 'sending a' serialcom.write('a\n') # time.sleep(.5) # print serialcom.read() print serialcom.readline() else: for i in range(abs(int(movemotor1))): serialcom.write('d\n') # time.sleep(.5) # print serialcom.read() print serialcom.readline() # serialcom.close() def movemotor2(self): print "movemotor2called" global serialcom, tempmotor2 movemotor2 = self.motor2.value - tempmotor2 tempmotor2 = self.motor2.value print movemotor2 if serialcom.isOpen(): print("serialcomial is open!") # serialcom.write('a\n') if movemotor2 > 0: for i in range(int(movemotor2)): print 'sending b' serialcom.write('b\n') # time.sleep(.5) # print serialcom.read() print serialcom.readline() else: for i in range(abs(int(movemotor2))): serialcom.write('e\n') # time.sleep(.5) # print serialcom.read() print serialcom.readline() def movemotor3(self): print "movemotor3called" global serialcom, tempmotor3 movemotor3 = self.motor3.value - tempmotor3 tempmotor3 = self.motor3.value print movemotor3 if serialcom.isOpen(): print("serialcomial is open!") # serialcom.write('a\n') if movemotor3 > 0: for i in range(int(movemotor3)): print 'sending c' serialcom.write('c\n') # time.sleep(.5) # print serialcom.read() print serialcom.readline() else: for i in range(abs(int(movemotor3))): serialcom.write('f\n') # time.sleep(.5) # print serialcom.read() print serialcom.readline() class FabApp(App): def build(self): global stage stage = virtualMachine() # print dir(stage.xNode) #stage.xNode.loadProgram('../../../086-005/086-005a.hex') #stage.xNode.setMotorCurrent(1) stage.xNode.setVelocityRequest(8) return FabControl() if __name__ == '__main__': FabApp().run()

To run the python kivy program, kivy fabarmkivy.py



Screenshot of the UI,



it wasn't quite working as intended by the code, it was too jittery and random, sometimes it moves correct sometimes doesn't



Finally figure it was due to some loose connections and we replaced the servos as well during debugging,

Controlling via GUI