Next large robot



  • I didn't have to deal with that. There are a few sellers of these that have a warehouse in Oakland that they hold product in, and I live an hour from there in San Jose, so it was delivered with a lift-gate truck to my door as part of the $2500 price. I was expecting "75% completed kit" but it was pretty much plug & play. I've been happy with it.
  • I went and ordered the Boss Laser Cutter today. I ordered the LS1620 model but they upgraded me to the LS1630 model for the same price as the other unit. It seems they are phasing these out but haven't updated their website. They don't want to bring in any more of these so I agreed to take one. Now its a 2-4 week wait for delivery. In the meantime I have to figure out where to set this up in the basement and clear out a spot.

    Bob Sweeney
  • Unless you need to laser something bigger than 12" x 9", you can buy a 40W laser on ebay for $365, free shipping.

    A 100W laser can't cut any more materials that a 40W laser can. To laser all the plywood for my R/C airplane only takes an hour. I imagine then that a 100W laser would do it in 24 minutes. I did have to align the mirrors etc, but everything went smoothly.

    I hope for whatever you're spending, that at least it doesn't have stepper motors.
    I am the Master, and technology my slave.
  • The_Master wrote: »
    Unless you need to laser something bigger than 12" x 9", you can buy a 40W laser on ebay for $365, free shipping.

    A 100W laser can't cut any more materials that a 40W laser can. To laser all the plywood for my R/C airplane only takes an hour. I imagine then that a 100W laser would do it in 24 minutes. I did have to align the mirrors etc, but everything went smoothly.

    I hope for whatever you're spending, that at least it doesn't have stepper motors.
    This is a commercial laser and 100 watts may not cut/etch any more materials than a 40watt but it gives enough power to easily and quickly cut through fairly thick wood and plastics. I have several hobbies besides robotics that I plan on using the laser for making parts along with a few other side ventures I am exploring. It is probably over kill for what I will be using it for and expensive for hobby use but since you can't take it with you, might as well have fun along the way! Besides, think of all the new design robot bodies that can come out of this!

    I have been able to spend several hours working on coding the hexapod. I decided to experiment with the PID loop for the coxa by re-writing a new PID routine and making it even simpler. I got rid of the existing speed control code and only used the inherent ramping on the PID. Actually its a PI loop right now, I haven't added a derivative process yet. The proportional code was easy to integrate as it is simply the constant (kp) times the error (kp*error). I determined the kp value by simply incrementing it by 1 and then commanding a move. The larger the value the faster the leg moved until I got a value where the leg had significant overshoot. Then I backed the value back down to the previous value.

    The Integral portion is trickier but it improves the response rate as its output is added to the output of the Proportional code. The Integral value is based on the change in error over time, since the code time interval was essentially constant, I did not use any code to determine time. This simplifies the code to accumulating the error (errorsum = error + error sum) and then multiplying it by a constant (ki) (ki * errorsum). This value can grow pretty quickly so I put limits on its growth to prevent it going too far. Initial tuning of the Integral portion didn't go well as I was using integers for ki which cause the motor speed to accelerate much too rapidly and caused wide overshoots. That's when I figured out the ki value should be less than 1. Since I can't use floating point math (no cogs available to run the code), I set ki = 5 and then divided the integral result by 10. This produced a controllable leg movement that did not have any overshoot.

    A byproduct of this testing was that the encoder value at the end of one motor command now closely matched the last encoder value for the previous command. As I stated a few days ago I ran into issues where although the stop motor command was sent at the right time, the motor inertia caused enough additional movement that the leg would end up further away from the desired position.

    At this time I don't think I need to add the derivative portion of the control, I still have more testing to perform and I want to try a variety of integral constants to see what value gives the best response.
  • The re-write of the Coxa PID loop was successful so the Tibia and Femur loops were also updated using the new routine. This greatly simplified the movement routines, the troubleshooting text output is a significant part of the code now. With this last change I eliminated the 'S-curve' speed control as the PID now controls the motor speed. The ADC control was also removed, however I will need the ADC eventually for the leg impact sensors. Here is an example of the code used for the Coxa PID routine:
    pub CoxaPID | error, speed, actualADC, oldADC, endspeed, dir, currentAngle, kp, ki, errsum, output
      'PID motor controller routine for Coxa
      ' repeat until inside of deadband
      'monitors CoxaTarget value continuously
        kp := 3                                                                       'tested to value 4 causes oscillations
        ki := 1
        CoxaColor := Green
        CoxaMagEncoder := CoxaEncoder
        error := CoxaMagEncoder - CoxaTarget                                               'error based on mag encoder, CoxaTarget is desired position
        'allow for calibration and keep motor stopped inside deadzone
        if ||error < 2 AND coxaCal == 0
          speed := 1500
          dc.set(2, speed, 0)                                                       'stop motor
        endspeed := 0
        ' if CoxaAngle = 0 then running calibration check
        repeat while (CoxaDone == 1) 
          CoxaMagEncoder := CoxaEncoder  
          error := CoxaTarget - CoxaMagEncoder                                              'error based on mag encoder
          errsum := error + errSum                                          'get Integral value, limit it to 500 (motor pwm stop =1500, so 
    1500-500 = 1000 and 1500+500 - 2000; the limit of HB-25 controller output
          if errsum > 500
            errsum := 500
          if errsum < -500
            errsum := -500
          output := (kp * error) + (ki * errSum)/10                                 'main PID output value - divide by 10 to use integral math
          if error > 0
            dir := 1
            speed := 1500 - (output)                                               'use output to determine motor speed - limit speed to max value
            if speed < 1100
              speed := 1100            
            CoxaColor := Blue
            dir := 0
            speed := 1500 + ||(output)
            if speed > 1900
              speed  := 1900
            CoxaColor := Orange
          if (||error < 1)                                           'stop if in deadzone
            speed := 1500
            dc.set(2, speed, 0)                                                       'stop motor
            coxaColor := Green
            coxaDone := 0
            errSum := 0
            CoxaMagEncoder := CoxaEncoder  
            if CoxaTest == 1                                 'output text if in testing mode
              currentAngle := CoxaMaxAngle-(((CoxaMagEncoder - CoxaMaxMag) * 1000)/ cSlope)      'calc current angle for troubleshooting                              
              io.str(0,String(13, "Coxa Done - Stop, motor inside deadband: "))
              io.str(0,String("     Encoder: "))
              io.str(0,String("   -CoxaAngle: "))
              io.tx(0, CR)
          'set variable speed code here using the speedcmd value (10-100)
          endspeed := SetCoxaSpeed(speed)
          dc.set(2, endspeed, 0)                                                     'start motor at speed
          CoxaMagEncoder := CoxaEncoder  
          if CoxaTest == 1
            currentAngle := CoxaMaxAngle-(((CoxaMagEncoder - CoxaMaxMag) * 1000)/ cSlope)      'calc current angle for troubleshooting                              
            io.str(0,String(13, "Coxa Angle: "))
            io.str(0,String("  -Encoder: "))
            io.str(0,String( "  -CoxaTarget: "))
            io.str(0,String( "  -Error: "))
            io.str(0,String( "  -Speed: "))
            io.str(0,String("  -dir: "))
            io.str(0,String("  -errsum: "))
            io.str(0,String("  -ki: "))
            pauseMSec(20)                                                       'required pause when not outputing debug info
          ActualADC := CoxaMagEncoder                                                     'based on encoder input
          if CoxaCounter == 1                                                        'check if encoder not changing
            oldADC := CoxaMagEncoder                                                      'reset check encoder value
          if CoxaStopError(oldADC, CoxaMagEncoder)                                        'error if encoder not changing
            speed := 1500
            dc.set(2, speed, 0)
            coxaColor := Red
            coxaDone := 0
            errSum := 0
            if CoxaTest == 1
              io.str(0,String(13, "Coxa Done 4 - Encoder value not changing: "))
              io.str(0,String("     Encoder: "))
              io.tx(0, CR)
        coxaColor := Green
    pub SetCoxaSpeed(speed)
    ' modify speed based on input value speedcmd (5-100%)
      if speed > 1500                                                               'formula differs for each motor direction
        result := 1500 + (((speed - 1500) * cSpeed) / 100)
        result := result #> 1552                                                    'set minimum speed
      elseif speed < 1500
        result := 1500 - (((1500 - speed) * cSpeed) / 100)
        result := result <# 1448
    pub CoxaStopError(iADC, aADC)
      CoxaCounter := CoxaCounter + 1                                                                    'count to 10
      result := false
      if CoxaCounter == 1                                                                     'at start get encoder value
        iADC := aADC
      if CoxaCounter == 10                                                                     'max count 10
        CoxaCounter := 0
        if iADC == aADC                                                             'error, encoder not changing
          Result := true
    I left in the code to set overall motor speed and determine if the motor is not moving.

    I am putting together a short video of the PID tuning process that I should be able to post shortly.

    The next step is to re-introduce the master computer into the mix and run the leg computer via commands from the master. Then I can visit the gait control algorithms again and start getting those working.

    Its slow but progress is still being made, thanks for joining me on this long, long journey!
  • Such a fun journey this has been! I book marked this thread at the very begining!
  • I finally got Adobe Premier Elements to cooperate and was able to patch together a short video of the PID tuning process for the coxa motor. Hopefully there is enough information in there for you to see the process I used. Setting the PID variables is time consuming but the end result is worth it.

  • Got the laser cutter installed in the basement and took the first cuts today. It works great and I even was able to transfer CAD files to the laser software and cut out a cover for the Magnetic Encoder housing. It even fits! I see a lot of uses for this machine in the future.
  • Cool!
  • Summer is winding down, the boat is getting ready for its winter rest, Michigan is getting colder (wetter, windy) so bike riding is slowing down and only diving every couple of weeks, so I have more time to get back on the robot! Unfortunately I've only spent a handful of days playing with the code so I end up spending a lot of time re-familiarizing myself with where I left off the previous time.

    I spent a day working on just tuning the 3 PID loops, so far the leg motor output looks good when I manually input commands even with 0.1 degree movements. The Coxa encoder mechanical setup is still not the best, I see some 'sticking' of the encoder while the motor is moving which throws the position off. I want to return to the mechanical attachments and see how those can be improved.
    I put the individual leg controller in its 'Automatic' mode but was unable to get any movement when running the master computer. Since it was already late I quit before I messed any code up. Later I realized that I had changed the leg ID from 6 to 1 (don't remember why) so most likely that was the problem. I also spent a day reviewing the Inverse Kinematics math for leg movement. I had to watch my own video on Inverse Kinematics to help me refresh my mind on how I programmed that into the master controller. I think I've got that all straight again so the next stage is to code some simple movements and see if I can get this leg to move in a straight line! Then I can think about how the leg formulas need to change for the leg moving in a straight line but at different angles.
  • Now I'm completely Blown away. What a project to undertake.
  • RS_JimRS_Jim Posts: 1,074
    edited October 25 Vote Up0Vote Down
    ASKME wrote: »
    Now I'm completely Blown away. What a project to undertake.

    What a fun project! I have been watching since this thread started back in 2015. Am anxiously awaiting its first steps. I guess that Bob will early on have to teach it to climb stairs!
  • The problem with communications between the master computer and leg controller was due to the changed leg number. Once I changed the master program to output to leg 1, they started talking to each other.
    I started testing with a simple move, take the leg to a default position. Then I told it to move to a specific location using the Inverse Kinematics (IK) equations. This was successful but the movement of the coxa puts the leg tip (the tip is where the leg would normally be touching the ground) describing an arc movement since each axis motor's speed impacts the leg tip movement differently. This means that the femur and tibia motors may finish their movements while the coxa is still moving into position. This is bad because that represents a sliding movement for the leg tip on the ground and this robot isn't designed to slide (smaller hexapod leg tips can slide some but I'm dealing with quite a bit more weight!). To reduce the amount of the arc the motion is broken down into a series of segments.
    The output of the IK is the new angle for the 3 axis of the leg that describes the final position of the leg tip. The change in angle to get to this point is calculated for each axis (start angle minus the IK angle). This value is then divided into segments (still testing to determine the best value but the value of 30 was giving good results). The master outputs a request to leg axis for the current axis angle plus the value of the change angle/30. This is a relatively small movement where the differences in axis movement speeds is minimized so tendencies for the leg tip to slide are absorbed due to inherent mechanical 'slop' (there may be a better word to describe this but I can't think of one) in the leg.
    That describes the coding for leg movement but in practice what I observed today is that the femur and tibia movements are smooth but the coxa has a tendency to jerk the leg and overshoot the position. I did not observe this jerk when working with the leg controller and tuning the coxa axis. There are a couple of possible explanations that I came up with. First, the coxa tuning is too aggressive and needs to be backed off. The speed that the master inputs the movement commands is much faster/frequent than I can manually input from the keyboard, this might put the PID loop into a condition where it overshoots the target. The other possibility is that the mechanical setup for moving the coxa encoder shaft sticks with very small coxa movements and when it does move a large PID error is introduced. It may even be a combination of both items.
    I've done enough for today but tomorrow I will 'detune' the coxa PID loop so that it responds slower and see how that affects leg movement. Re designing the encoder mounting is something I hope I don't have to do!

  • Yesterday was a bust for working on the robot, my wife tasked me with helping her figure out how to use the software for her computerized quilting machine. It took a lot longer than I expected but she is happy again. I have figured out that retirement means I just have one less boss!
    Before I got into the programming again today I put together a cheat sheet for myself for the IK equations and assumptions that went into the design. I thought I'd post it here also for anyone wanting to create their own hexapod using this leg design.
  • Good Job DiverBob, a happy wife makes for a happy life.
  • I've been tweaking the PID tuning values for the Coxa for a while and I believe I'm getting some good output travel from the coxa. It is not jerking anymore and responds smoothly. I put a ruler on the floor and input a destination value for the leg and use the ruler to see how close to a straight line the leg tip travels. With the coxa moving smoothly I found the tibia is making a large move at the beginning of the leg swing and comes to the correct location by the time the leg completes the swing. Checking the requested position data from the master to the leg controller shows the expected output but the tibia reacts too quickly initially but is in the correct location by the end. At first I thought the tibia motor speed was too high as compared to the coxa but experiments with the tibia speed gave similar results. Working with the tibia PID directly allowed me to manually input a sequence of tibia angle changes that matched the input from the master. I was seeing correct responses to the input and the corresponding leg moves. So this is a puzzle to figure out.
    As I wrote up the description of the issue out above I suddenly thought of a possible cause. Each motor PID loop is designed to respond to an input angle. Even if the PID is still moving to a requested angle a new angle command can be input and update the error response before the leg completes the previous move. This response is desired otherwise if I waited for each motor to complete their movement it would result in a jerky leg movement as each motor starts and stops (since a leg movement from the start to the end position is broken up into 30 segments this is a lot of starting and stopping). If the master is outputting the position commands too rapidly to the leg controller, the tibia could be reacting more quickly than the coxa causing the leg to swing outward. Then the last position command from the master would be the only thing both motors are responding to at the end which would explain why the leg still ended up in the correct end position. I will add some long pauses in the loop from the master and see if that straightens the response out. Then I can slowly reduce the pause time until I get to the point where the command input and motor response timing are the same.
    Some days it seems for every problem I solve two new ones crop up..... I need to video some of this testing but the video editing software I use (Adobe Premier Elements Version 14) has been way too slow ever since I upgraded to v14. I'm ready to move over to a new video editor but don't know which one to use. Any suggestions for a decent video editor that does HD and won't break the bank?

    Bob Sweeney
  • The issue I discussed in yesterdays post was not specifically caused by the item I wrote up by itself. There is another factor that I didn't take account of that became clearer when I increased the interval between moves to 750 milliseconds. I saw the tibia move outward a much greater distance than expected during the first portion of the leg move. The primary cause ends up being an assumption that I made that if I know the initial and final leg motor angle positions I could evenly divide the amount of movement by a value; (final position angle - initial position angle)/20. This results in each motor axis moving equal amounts needed to reach the final position. What I didn't take into account was that for the leg tip to move along a straight line path the angular change is different along the path. For example if you draw a straight line and then draw a point a couple of inches off to the side of the line and around midpoint of the line. Now using the point as a pivot point, take a pencil or pen and hold one end on the pivot point. Rotate the pencil so that it is 90 degrees to the line. Observe the point where the pencil touches the line and rotate the pencil one inch. Observe the distance that the line moved relative to the pencil shaft. Now do the same 1 inch movement but further down the line. You should be able to see that the distance that line moves relative to the shaft is much greater than it was initially. What this boils down to is that I can not use the same angular movement as initially the angle change is small and slowly rises as the leg tip moves further away.
    To solve this problem I still divide the movement into discrete distances for each motor but now I run those X, Y, and Z through the Inverse Kinematics routine to get the correct angle for each location. I wrote the coding for that and got a much straighter movement. I also implemented a short delay into the routine as that gave the motors more time to react before the next command showed up. The speed of spin may become an issue later as I add more legs into the master controller, but I should be able to reduce/remove the delay as more legs are added.
    So far the majority of leg movements have been just changing the Z axis and leaving the X and Y values alone. I want to start implementing X values which mean the leg will move at an angle relative to the pivot point. I have done a little testing with that but haven't used a wide variety of values. That capability is essential as the plan is that the robot doesn't have a front or back so I need it capable of moving any direction without turning.

    I took some video on my iphone of some of the tests but I want to combine it into a single file before I post it. I'm looking at video editors and Pinnacle Studio Plus seems interesting from what I've read so far. Anyone familiar with it?
  • It turns out that I didn’t have to write any special code for leg movements where the Z axis isn’t zero. With the new updates, the code already takes into account those differences. So on to the next task, turning the movement into a step.

    I ran into some issues testing the coding where the leg would just take off in unexpected directions. As I tested and wrote code to fix a problem another problem would crop up requiring more coding workarounds. Finally I got to a point where the leg stopped working reliably and was not responding as expected.The code was a mess and almost unreadable at this point.

    After a nights sleep I tried again but first put down pseudo spin code on paper to better visualize the movement and what information would be needed. I wrote a new leg movement routine using that as a guide that surprisingly worked correctly the first time. However after that success the calibration of the tibia went out of whack. I found that the connecting rod from the encoder to the leg got bent which changed the calibration. Even with re-calibration it would not hold accurately since the bent connecting rod could rotate, changing the encoder angle. The rod got bent in the first place since the slot that the rod came out of the housing was not long enough for all possible motions. This is an older design for the encoder housing that I hadn’t replaced yet as it had been working well in the past.

    So I decided to machine a new encoder housing using the new design. It took a lot longer than expected as I kept making basic machining mistakes. Apparently I haven’t been using the CNC mill enough lately and was trying to rely on my memory for all the steps needed to prep the stock material for cutting and other steps in the process that weren’t in the CNC programming. Luckily none of these mistakes were catastrophic so eventually I got the housing created. I did document the process for making the housing so hopefully the next time will be quicker and I don’t have to try to rely on memory for all the necessary machining operations.

    I still need to unsolder the encoder from the old housing and swap in the new housing. Then reassemble the unit with a new connecting rod, calibrate, and hopefully continue with the gait coding.


    (Still looking for a video editor. Also, how do I post a video on this thread without having to reference a YouTube video? Can I just reference a video on my C: drive? I have several short iPhone videos of the testing to show)
  • Is there a way to post videos without going through YouTube? I have several very short videos taken with my iPhone that I would like to post but I don’t want to compile them together and put on YouTube.
  • Camtasia Studio?
    I am just another Code Monkey.
    A determined coder can write COBOL programs in any language. -- Author unknown.
    Press any key to continue, any other key to quit

    The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this post are to be interpreted as described in RFC 2119.
  • I installed the new encoder housing and used the laser to create covers for the housing. The slot for the connecting rod from the encoder to the tibia is much longer so I shouldn’t have any issues with the rod bending due to over-travel like the previous housing design.
    Calibration of the tibia went smoothly and the initial manual testing had it moving in 0.30 degree inputs.
    I put the master computer back in the loop and started moving the leg along a straight line path of 5 inches. The leg followed the expected path very nicely. The next step added code to raise the leg, return it to the origin and then lower the leg. After a few bumps in the road, I got the code to perform more or less as expected. An issue now is that when the leg lifts, the code for returning the leg to the starting point starts moving the leg before the leg has finished moving up. I added a short delay after the leg lift but what is happening is that the motor done flag from the leg controller is not being updated to the master computer.
    The code for the motor done flag update is embedded in the main leg controller loop and doesn’t execute until there is some type of input from the master computer and even then it just executes that one time. I tried a dedicated line from the the leg controller to the master computer with mixed results. Now that I have a spare cog in the leg controller I want to try out creating a continually running routine that outputs the motor status information to the master either via another serial link or by toggling a couple of I/O pins. That will be the objective for todays coding.


    I checked out the website for Camtasia Studio. It looks promising, I may have to download the free trial and see how easy it is to use. I’m still leaning toward Pinnicle Studio, mainly due to the price. Most of the video that I make is relatively simple and I don’t need 90% of the bells and whistles most video editors have.
    I still haven’t figured out how to directly embed a video from my computer into this forum if I don’t want to use YouTube.
Sign In or Register to comment.