For a handful of travelers, especially Japanese, not only the island's scenic attractions prompt their visits but also the pleasure of Taiwanese foot massages.
Foot massage not only makes feet feel wonderful, but it also helps us entire body relax.
Most electronic massagers are excellent for general massage of the feet and for relaxation therapy.
We want to make a machine that you can set the path you want.
In the beginning, our plan was to make a “hair-milling machine” in delta mechanism but not parallel. The reason why we chose delta is that for the all 3 DoF machines, xyz mechanism tool point would always vertically point to the ground or plane of axes. But, for delta structures, the tool point can follow sphere surfaces within special coordinate which could let machine have bigger working area to mill your hair.
Simulation with real person.
Trying to simulate on Fusion 360. It seems fine but there was a big mistake that we did not draw tool platform. Unfortunately we did not figure it out something wrong until two weeks passed.
We simply calculated the frame size in reasonable range and figured out the length of rods cannot be too long.
After alculated the frame size , we have combined and modified linear stage material with 300 mm length from Jason Wang.
Then modified rods holders and platform from Rodstack by Johann Rocholl
The platform 3D design
The carriage 3D design
The rod_side 3D design
The magnet mount 3D design
3D printing for components
Combine two separate parts
We were testing and the rods were not in the right length in this picture. And when we built with platform, it was unstable with many degrees of freedom because we misunderstood that only rods intersecting at one point can limit the mechanism to one solution.
So we bought an 1 inch iron ball (used to bearing) and magnetic ball joints to limit the rods motion within one solution.
For the tool, we bought a nose hair trimmer which would have limited area and could engrave really nice shapes.
When we assembled all the components, the shape of pyramid just fixed and cannot move anyway! This disaster came from that the platform shape should be flexible in the mechanism and also have holder nose hair trimmer vertically pointing to the triangle.
Testing Gestalt
Making Fabnet
Following Getting Started With Gestalt Nodes, we successfully ran single node test.
It does not have to fuse or program the Gestalt nodes again.
Single gestalt node testing
And then testing with three nodes
Trying to identify each gestalt node.
But, the winter is coming again…
After this video, these three nodes cannot blink anymore….
In debug time, we found that the people from Fablab Leon faced same problem.
We tried to fuse and program these three Gestalt nodes with Arduino.
We were going to check the wires, but the programmer still cannot recognize
ATmega328P. So we removed the default crystal to burn them again.
It cannot work either.
However we have 4 Gestalt nodes and 3 of them cannot work, so we fused the rest
of workable one which can blink and identify by computer.
Boom! It worked!
Which means 3 of them might be totally broken with their ATmega328P.
While debugging, Kevin tried to write forward and reverse kinematics of hair milling
machine. Though it looks like delta machine, it’s not parallel mechanism at all. We
have to control the tool pointer and the position at the same time. So he modified the
Python code in machines.py and followed Delta Robot Kinematics by Steve Graves.
class kinematics(): # Bottom length = D # /\ A # / \ ^ x # / \ | # / \ | # / o \ o ---- > # / \ y # / \ # -------------- # C B #---Inherited from matrix class but not real matrix---- class deltaForwardTransform(matrix): '''Customized transform from axes input vector to delta hair-milling coordinate''' def __init__(self, L, r, rh, Lt, D): self.L = L #length of rod self.r = r #radius of iron ball self.rh = rh #diameter of your head self.Lt = Lt #length of tool-to-ball self.D = D #side length of bottom triangle self.Ax = math.sqrt(3)/3 * D self.Ay = 0 self.Bx = -math.sqrt(3)/6 * D self.By = 1/2 * D self.Cx = -math.sqrt(3)/6 * D self.Cy = -1/2 * D def transform(self, inputVector): if len(inputVector) != 3: #check to make sure that vectors match notice (self, 'vector length mismatch') return False Az = inputVector[0] Bz = inputVector[1] Cz = inputVector[2] P1 = numpy.array([self.Ax, self.Ay, Az]) P2 = numpy.array([self.Bx, self.By, Bz]) P3 = numpy.array([self.Cx, self.Cy, Cz]) ex = (P2 - P1)/(numpy.linalg.norm(P2 - P1)) i = numpy.dot(ex, P3 - P1) ey = (P3 - P1 - i*ex)/(numpy.linalg.norm(P3 - P1 - i*ex)) ez = numpy.cross(ex,ey) d = numpy.linalg.norm(P2 - P1) j = numpy.dot(ey, P3 - P1) xr = (pow((self.L+self.r),2) - pow((self.L+self.r),2) + pow(d,2))/(2*d) yr = ((pow((self.L+self.r),2) - pow((self.L+self.r),2) + pow(i,2) + pow(j, 2))/(2*j)) - ((i/j)*x) zr = numpy.sqrt(pow((self.L+self.r),2) - pow(x,2) - pow(y,2)) scale = self.rh / ( self.rh + self.Lt + self.r ) #scaling from iron ball to tool position x = scale * xr y = scale * yr z = scale * zr return [x,y] #---Inherited from matrix class but not real matrix---- class deltaReverseTransform(matrix): '''Customized transform from delta hair-milling coordinate to axes output vector''' def __init__(self, L, r, rh, Lt, D): self.L = L #length of rod self.r = r #radius of iron ball self.r = r #radius of iron ball self.rh = rh #radius of your head self.Lt = Lt #length of tool self.D = D #side length of bottom triangle self.Ax = math.sqrt(3)/3 * D self.Ay = 0 self.Bx = -math.sqrt(3)/6 * D self.By = 1/2 * D self.Cx = -math.sqrt(3)/6 * D self.Cy = -1/2 * D def transform(self, inputVector): # Only x,y allowed within inputVector if len(inputVector) != 2: #check to make sure that vectors match notice (self, 'vector length mismatch') return False x = inputVector[0] y = inputVector[1] z = math.sqrt(r**2 - x**2 - y**2) scale = ( self.rh + self.Lt + self.r ) / self.rh #scaling from tool position to iron ball position xr = scale * x yr = scale * y zr = scale * z Az = zr - math.sqrt( (self.L+self.r)**2 - (xr-self.Ax)**2 - (yrself. Ay)**2 ) Bz = zr - math.sqrt( (self.L+self.r)**2 - (xr-self.Bx)**2 - (yrself. By)**2 ) Cz = zr - math.sqrt( (self.L+self.r)**2 - (xr-self.Cx)**2 - (yrself. Cy)**2 ) return [Az, Bz, Cz] # Testing...... class hair_milling_delta(transform): def __init__(self, L, r, Lt, D): self.forwardMatrix = kinematics.deltaForwardTransform (L, r, rh, Lt, D) self.reverseMatrix = kinematics.deltaReverseTransform (L, r, rh, Lt, D)And added these to main file hair-milling.py
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(False)]) self.zAxis = elements.elementChain.forward ([elements.microstep.forward(4), elements.stepper.forward(1.8), elements.leadscrew.forward(8), elements.invert.forward(False)]) self.stageKinematics = kinematics.hair_milling_delta()When he was all set, we found out the 3 of Gestalt nodes were definitely broken and cannot fuse.