Today will be a programming day, the first in quite a while. I like to start out with something easy and fun to get myself back into the swing of working with SPIN again. I think I'll start by setting up routines for the RGB lights first. I searched the OBEX and found a nice looking setup for serially sequencing the lights so it's time to wire one up and experiment. If that goes well then I'll play with the radio transmitter and reciever and see if I can control the lights that way. Should be a good way to enjoy a cold, snowy day!
I still have to finish some soldering on the wiring harnesses but I have enough done to get at least two legs up and running for initial calibrations and testing.
I did discover one issue I need to work through, the multi-turn pots I'm using have shafts that are just a bit too short for a reliable connection to the spur gear on the swing gear reduction. I either have to find pots with longer shafts or design some type of extension. More on that later
They seem to have a long shaft, if you want I can send some to test out.
Thanks for the offer! I went online to check out some 10 turn, 10K shaft driven pots and got a serious case of sticker shock. I saw prices on Digikey ranging from $8+ to $175. The pots I'm using we're surplus and considerably less!
I think I'll first see about machining a shaft extension and use a set screw or roll pin to hold the extension and gear in place. This doesn't have to be fancy since I'm only using a nylon spur gear, no power transmission or other forces on the shaft so it can be lightweight. There is plenty of space available for it in the housing area. If that doesn't work then I might take you up on your offer!
I did get the RGB lights going, set up a couple of simple routines to push specific colors and flash a light if needed. It should look nice in the end. I didn't do the XBee wireless setup as I read some where that you shouldn't run it without an antenna so I ordered one of those for testing. I'll play with the motor controllers tonight, run some of the setup routines I've used previously to validate the wiring down to the motor level. Then I can start calibrations on the motors.
Tough week so far. I've been having problems getting the HB25 motor controllers to cooperate. I have power going in to them and I'm using code that worked on the test leg but not now. Today I'll tear things apart to validate the power wiring and just power up a single controller.
All the other tests have gone well so far, ADC circuitry and code, RGB lighting and some other general use routines. I'm confused as to why I can't get any output from the motor controllers. I have all day today to figure this one out. It's snowing hard outside and inside seems to be the best place to hang out!
Tough week so far. I've been having problems getting the HB25 motor controllers to cooperate. I have power going in to them and I'm using code that worked on the test leg but not now. Today I'll tear things apart to validate the power wiring and just power up a single controller.
All the other tests have gone well so far, ADC circuitry and code, RGB lighting and some other general use routines. I'm confused as to why I can't get any output from the motor controllers. I have all day today to figure this one out. It's snowing hard outside and inside seems to be the best place to hang out!
Bob
Hi
The following is what I did to get my HB25's to initialize.
That was where my problems happened.
I use a relay to turn on the HB25 Power supply.
I'm using , for now, a BS1.
Startup:
HIGH BatVolt 'Turn on 12V motor power relay
IF PIN2 = 0 THEN Startup 'Wait for HB-25 Power Up
Let DIRS = %00001110 'Set Pin2 and Pin3 and Pin1 to Output
LOW HB25 'Make Pin2 Low
Pause 5 'Wait for HB-25 to Initialize
PULSOUT HB25, 150 'Stop Motor1
PAUSE 1
PULSOUT HB25, 150 'Stop Motor2
PAUSE 20 'Wait 20ms
Pause 5000 'Wait for the HB25s to warm up.
I realize that you are using Propeller, but just thought this might help you out.
Before using this initializing sequence, I could not get the HB25s to cooperate.
Aparantly, the HB25 is pretty particular in how they are initialized.
Thanks for the info but I figured out what I was doing wrong. After checking each wire I finally realized I hadn't initialized the pin to the HB25 as an output! It's always the simple things that really make you tear your hair out!
Anyway, I like your approach to setting up the HB25, it is particular about the order in which power is applied and a programmatic solution would be easiest to implement. I'll try your version out in the morning.
I was able to run all my calibration routines on the lift (tibia) motor. The final test was the routine where I was able to enter an angle in the Propellor serial terminal (PST) and the tibia moved to the location repeatibly. I need to repeat this for the tibia and Coxa motors tomorrow. Then I will work on the Inverse Kinematics routine and see how that turns out. It's nice to finally get back into the programming side again, I've been away too long! You may have noticed I haven't discussed the impact sensor, leg down sensor or the limit switches in the program. That's because I haven't installed them yet. I decided that I will add these sensors later once I get a program built that these can be added then.
I will post some photos and a video later when I get some time to put it together.
Ran into a snag today. Started testing the tibia motor and found that the feedback potentiometer wasn't reading any values for the first 3/4 inches of travel. I took the actuator apart, played with it a while and started to think maybe it has a bad pot. So I pulled the actuator from another leg and got the same results. A few more tests and it seems the ADC circuit isn't reading the lower voltage values. I posted a question on the prop forum, maybe someone else has seen this before.
It's not a good idea to keep on working on this now, I'm sure I'll do something I'll regret later! I have a tendency to want to start tearing things apart to figure out the problem when sometimes I just missed a simple clue. Better to try tomorrow when fully rested.
Bob I saw your thread in the Prop forum and tried Jon's code with the 10k pot on the PPBD and even though the pot is a little dirty it reads ok using this code only to read channel 1.
Good news, the ADC read issue has been solved. It turned out to be a problem with the mcp3208 object which the author recognized and fixed the listing in the OBEX. Now both the femur and tibia motors are acting correctly. Calibrations are complete on both actuators. Next is to perform the same work on the Coxa. This requires me to come up with a better way to hold the nylon spur gear on the multi-turn pot as it is just a bit 1/4" to short. I will try to create an extension on the lathe and see how well that works first as that would be the simplest fix.
I got the Coxa motor working and calibrated. All 3 motors are operational on one leg now. I'll use this first leg to create and test the routines I'll need for movement before I install the other legs. I have found out a couple of immediate items that need worked on first.
I figured out that I need a better ramp up and down routine, I keep overshooting the intended target position. An example is entering 90 degrees which might have a ADC target value of 2500. The ramp I'm using is basically 2 speeds, it slows down when the actual ADC value minus the target ADC value is less than 50. I may end up with a final ADC value of 2550 when everything stops moving. Now if I enter 92 degrees it is possible that the leg moves the wrong direction since it is already over the new target value.
For this ramping routine I'm going to determine the best ramp for increasing and lowering speed. Once I know the time needed for a ramp up to full speed and back down again, I'll have to figure out how to handle situations where it doesn't have time to ramp all the way up and down again.
The calibration shows that the linkages on the production legs are much tighter than the test leg in that I'm getting the same ADC values no matter which direction the leg is moving. As a bonus, when I plotted the ADC values they are very linear.
I'm going to use this information to greatly simplify the calibration process by storing the ADC values for each extreme as constants and calculating the target ADC value using the slope of the plotted values. This removes the table of ADC values that I've been using.
So I've got my next programming challenges laid out. Now, back to the shop!
Long day programming. I've got the basic ramp structure complete and changed the code for determining what ADC value corresponds to a requested angle. I had to dig the internet math sites to remember how to calculate the slope of a line and from that algebraically determining a point on the x axis. That portion of the code is working pretty good now, still troubleshooting a couple of anomalies in the ramp code. I also added a 'dead zone' into the routine to prevent oscillation of the motor.
I got tired of swapping screens from the spin compiler to the serial terminal. I located an old LCD screen I haven't been using and will get a dual screen video card from Best Buy tomorrow. That will speed up the troubleshooting as I write to the PST information I need for troubleshooting.
I got a wider monitor but it came with another VGA cable, need to get a DVI cable instead. At least the monitor is wide enough to display the PST and Spin app side by side now, makes for easier debugging.
Since my last posting I'm now on version 4 of the motor control routine. They all worked except for little issues that couldn't be resolved easily. The current version is the best one yet but it has its own quirks that I'm trying to work thru. The biggest issue was overshooting the desired position but I got that down to a much lower value by stopping earlier than the target rather than wait until I reached the target. It makes sense now but it took some work to get here.
The current and hopefully last issue is the fact that the ADC shows smooth movement towards the goal and the final ADC value is within 10-15 increments of the target. However if I use the same input angle value that got to this point (should be no movement as it's the same angle and the actual ADC should be with the dead zone of +/- 20), but the new starting ADC value comes up 100-150 points either higher or lower depending on the direction. So entering the same angle has the motor moving first one way and then the other. I believe the problem is that the motor is still moving after I send the stop command as it coasts down. I am going to come up with a 'fudge factor' I can add to account for this extra movement.
This has taken longer than expected, I was planning on doing some IK stuff but this needs to be fixed first. Can't have the legs coming up with their own positions arbitrarily. I have some video and will post that and the code once it gets closer to a reliably working product.
It's been a few days since the last update so here's what's happening.
I finished up the femur and tibia motor routines that incorporates some 'dead zone' to account for the extra motor movement. This seems to have helped quite a bit. The Coxa motor routine needs a bit more work, it uses a similar motor routine but it seems to be a bit pickier than the other two.
I was able to start work on the Inverse Kinematics calculations finally and have spent several days puzzling over the formulas. Paul Krasinski, the same person who developed the Q4 digital transmitter I'm using, is helping me understand the way he coded has hexapod. I finally figured out today that one of the reasons I was having so much difficulty in understanding his code and why mine wouldn't return good data was that we were using different frame references for our , Y and Z values. Once that was figured out my formulas started working. I've only got a simple gait installed on a single leg, the femur and Tibia seem to be responding as expected but the Coxa motor routine issues reared back up. Once I get that solved I'll make a video and post it here.
Happy New Year, Bob! Great to see your continued enthusiasm and dedication to this giant project. I'm sure 2014 will see rapid progress to your bot. Just go easy in testing and I'm sure your bot will walk circles around Grant Imahara's hexapod! I think I hear Grant whisper an F-bomb in the video before he yells "phew". http://forums.parallax.com/showthread.php/151632-Spike-the-Spider-Robot?p=1231331&viewfull=1#post1231331
Happy New Year, Bob! Great to see your continued enthusiasm and dedication to this giant project. I'm sure 2014 will see rapid progress to your bot. Just go easy in testing and I'm sure your bot will walk circles around Grant Imahara's hexapod! I think I hear Grant whisper an F-bomb in the video before he yells "phew". http://forums.parallax.com/showthread.php/151632-Spike-the-Spider-Robot?p=1231331&viewfull=1#post1231331
I know I would be hesitant about showing that kind of a failure to the world! I saw that thread earlier, that's even bigger than my monster! Looks very heavy too. I wonder what he is using to move the joints and what his onboard power is.
I did want to post a picture of my test setup and the leg equations. My last post was from my iPad and I didn't have access to the files then. The drawing shows 2 views, the left drawing is a side view of the leg and the right drawing is the top view. The red circles are the pivot points and I included the primary dimensions. The formulas are used to calculate the position of the leg foot in 3D space. The top view of the leg shows the value L which is the total length of the leg looking down from the coxa pivot to the desired end point location of X,Y. The values of X and Y are input from the user. Y would be the distance out from the pivot point that the leg tip will be at. X is the actual gait that the leg will be taking. I'm still learning this next part but X is programatically sub-divided up into smaller increments as the leg moves so to smooth out the movement. I haven't gotten that far in my experiments. Once the value L is determined from the Pythagoras Theorem ( sqrt(X^2 + Y^2) the remaining values are measured from the side view of the leg. I won't get into the math but it is all basic trig. First time I've used trig outside of school in a long, long time! In the end you get the angles needed for each motor to move to. Of course there are many other elements that also get involved here such as the position of each leg around the body so that you get coordinated movement.
Have you considered applying the Proportional, Integral and Differential (PID) control algorithm to control the leg positions? Properly applied (which is an art), the "P" adjusts the speed of the motor in proportion to the travel distance, with closer being slower and further being faster. The "I" and "D" (used sparingly) can prevent over acceleration when, say, traveling downhill, and adjust for set point deltas. This would augment or replace your mx + b slope calculation, adding real-time adjustments to outside forces.
For whole body motion, have you considered the following theories in addition to Inverse Kinematics?
- non-holonomic motion planning
- Euler spirals, clothoids or Cornu spirals. (They're used in road/railway engineering to reduce centripetal acceleration on transition curves such as on/off ramps, etc.) https://en.wikipedia.org/wiki/Euler_spiral
I am thinking of the case when your robot begins to dance and rotate very quickly (or perhaps, run), causing centripetal acceleration resulting in issues with precise leg positioning.
Have you considered applying the Proportional, Integral and Differential (PID) control algorithm to control the leg positions? Properly applied (which is an art), the "P" adjusts the speed of the motor in proportion to the travel distance, with closer being slower and further being faster. The "I" and "D" (used sparingly) can prevent over acceleration when, say, traveling downhill, and adjust for set point deltas. This would augment or replace your mx + b slope calculation, adding real-time adjustments to outside forces.
For whole body motion, have you considered the following theories in addition to Inverse Kinematics?
- non-holonomic motion planning
- Euler spirals, clothoids or Cornu spirals. (They're used in road/railway engineering to reduce centripetal acceleration on transition curves such as on/off ramps, etc.) https://en.wikipedia.org/wiki/Euler_spiral
I am thinking of the case when your robot begins to dance and rotate very quickly (or perhaps, run), causing centripetal acceleration resulting in issues with precise leg positioning.
I don't imagine that this robot will ever 'run' or move very quickly! But the ideas sound interesting, I'll have to look at it closer. Thanks for the heads up! I'm still working on the motor control routines, it's been harder than I expected to it to be. I am running each motor in its own cog now but I'm getting some unexpected results. Sitting here I just had a thought, I'm running the ADC routine in the main cog but each motor is calling the same routine, now each is calling it at the same time. That explains the odd ADC readings I was seeing on the PST. Interesting problem, how do I get the ADC readings for each motor when each motor routine is in a separate cog?
Use locks if it is necessary for each motor use the same ADC.
My mind is having difficulty grasping how all motors use the same ADC routine. I expect each motor to have its own ADC pin.
All cogs have access to main memory. I declare variables or arrays in main memory and have each cog access its unique variable or array element. You can display the variables or array values in PST.
I've been spending more time over on the Propellor forum than usual lately. I'm on version 5 of the motor control setup, scrapped the last one and started over from scratch. The new version is already starting out working better but still need to apply ramping to the code. I've been searching for good examples of ramping, I like the S curve and Sine wave approaches, have to figure out how to shoehorn them in without making this overly complex and hard to troubleshoot.
This was a snow day up in Michigan, lots of snow coming down and blizzard conditions, good day for staying inside and programming. Time for dinner and then back to the shop!
Keep at it Bob. I learned quickly on my early prototype that nothing is as easy as it looks. The detail-devils come crawling out of the woodwork in a hurry past the "COOL IT MOVES" stage. Looking forward to seeing this beast start stomping around!
I've spent several days reading about and experimenting with various DC motor ramping schemas and thought I'd put down some of the things I've learned. I've added plots for each of these, unfortunately I don't know how to make them larger other by clicking on them.
The simplest motor control is simply turning on the motor, run it at full power until you reach your setpoint and then remove power. This is the easiest to implement but has the most issues. The motor and the mechanical items attached to it experience 'jerk'. During motor start and stop there is stress on the mechanical items as they abruptly either start moving or stop. This can be seen as a vibration that can be severe in some cases. The higher the mass the motor is moving, the greater the effect. Additionally, motors don't just stop on a dime. When power is removed, the motor takes a finite amount of time to coast to a stop. This can throw your expected stop location off by a significant amount. This method of motor control is best used for either moving small masses or the actual stopping point is not critical. I use this method only during initial motor testing to verify the code is correct and even then I run the motors at a greatly reduced speed.
The next motor control method is the one most commonly used in amateur robotics, linear ramps. This is an easily programmed method as the motor power is increased or decreased at a constant rate. This is represented in the graph as a straight line. This method reduces the amount of jerk that occurs by a significant amount. On the deceleration ramp the motor will still over shoot the entered set-point but the amount of over shoot is reduced as compared to the first method.
Time
Fr
Out
Out 1
0
0
0
1
1
0.1
0.028
0.997692
2
0.2
0.104
0.969802
3
0.3
0.216
0.880187
4
0.4
0.352
0.715516
5
0.5
0.5
0.5
6
0.6
0.648
0.284484
7
0.7
0.784
0.119813
8
0.8
0.896
0.030198
9
0.9
0.972
0.002308
10
1
1
0
The next method is designed to reduce the amount of jerk as much as possible and reduce the amount of overshoot. Mathematically it is called an S curve. I'll leave it up to you to Google the various examples but here is a modified version of an S curve that can be programed in fairly simply. The equation is broken into 2 parts for ease of understanding and coding. I can't take credit for this version, that belongs to Peter Nachtwey. This was found in the forum discussion here: http://www.plctalk.net/qanda/showthread.php?t=31007
This gives the two curves that range from 0 to 1 over a specific time period. As you can see the Out curve starts out slowly and rapidly builds until it comes close to the max value and then eases into this. Out1 reverses this action and brings the motor to a smooth stop. Those of you who Google the S curve equation will see that this is not the same equation but the output results are very similar and can be much more easily computed on the processors we use. From this point it is just a matter of using these values to fit them into the desired range. For my situation, I am using HB25 motor controllers that use PWM from 1ms (max speed one direction) to 2ms (max speed the other direction) with 1.5ms as the stop value. I used Excel to spreadsheet the equations and worked out the formulas for the HB25.
This shows Direction 1 and 2 moving from Fast to Slow and back again.
There are few other methods out there such as PID (Proportional, Integral and Derivative), Sine wave and others. This is the one that I felt would be the best for my situation is this modified S Curve. The next thing is to actually program this in and see how well it works in practice!
Once again visited my favorite surplus store, Skycraft in Orlando Fl. Got a bunch of little things I was running out of like heat shrink and odd bits and pieces. Still managed to acquire some stuff for future projects yet to be determined...
Since I'm away from my computer, no changes on the programming front. I am still doing a lot of reading on motor control systems and finding out a lot of things that may not be a major issue in a smaller, lighter robot but have to be considered in something this large. There is just too. Much inertia and mass involved in this system that parts will start breaking prematurely if the programming doesn't smooth out the leg movements. I am looking forward to trying to program these ideas into the system. I was trying to hurry so I could jump into the IK side of things but now I believe the safer approach is to really get these basic motor movements working 100% first.
Back from vacation in Florida. It was cool there but much warmer than here in Michigan! Swimming with the manatees was great, I have some video I'll post to my YouTube site later when I get some time to consolidate several hours of video. Now its back to sub freezing weather and lots of lake effect snow...
Finally got a chance to try out some of the motor control programming I've been thinking about and got a preliminary run at it. After programming in the formulas the light bulb went off that there are only 2 sets of ten PWM values, one for 1000 to 1500 and the other from 1500 to 2000 (actually these are 1.0 msec to 2.0 msec) from the table on Post #324. I set these values up as 2 arrays and can address the PWM values directly instead of computing them each time.
There are 3 separate phases for the motor control, ramp up, full speed, and ramp down. I'm still tweaking the code and will post it as soon as I get it working correctly. Since I'm using ADC readings instead of an encoder for reading position and the motor may only have to move a short distance, additional code is needed. An encoder would have been nice but I have to work with what I got. Here are some of the special code in the motor controller in the 3 phases.
For each motor move the halfway point is calculated based on the starting and target ADC value. If during the ramp up phase the half way point is reached, the loop is exited, full speed phase is skipped and the ramp down is commenced at the final ramp up speed.
During the full speed phase, the ADC value at the start of the ramp up and ADC at the end of the ramp up determine the absolute value of the change. This value (along with a fudge factor due to mechanical inertia) is added to the target ADC value. Once this value is reached the full speed phase exits and the ramp down phase starts.
Since the linear actuators have internal limit switches that are not accessible externally it is possible for the motor to stop without reaching the calculated target. ADC values are monitored and if there is no change in value while the motor is supposed to be running, the 'stuck' phase is exited. I should take one of these actuator apart and see if it is possible to modify the actuator and make these switches available (research project!)
Due to internal gearing backlash the motor may start but the ADC will not change for a significant time. This is most apparent when the motor reverses direction. The delay in getting an accurate position reading means the motor tends to overshoot the intended position and then trys to reverse direction to return. This causes the motor to 'hunt' back and forth. I am using a deadband to help reduce the occurance of this but this then reduces the precision that the motor can be postioned to. This will most likely be one of those items that is a trade-off between precision and hunting. Once weight is applied to the leg some of this should be reduced, I've tested this by putting some pressure on the leg
That is the basic program flow for motor control, there are still some issues to troubleshoot for and testing to ensure it works reliably. I'm sure there are some additional scenarios I'll have to code for also.
Got some unusual results tonight. After the motor reaches its target value a stop PWM of 1.5 ms is sent to the motor. I noticed that the ADC value continues to move slowly for quite a few cycles even as the stop command is being applied. This implies either a longer coast down for a stopped motor or the stop command is not truly stopping the motor and it continues to slowly turn.
Since we have a snow advisory tomorrow and I get the opportunity to stay home, I'll take apart one of the actuators so I can physically see if the motor is still turning. This should prove or disprove this theory!
I eliminated the hunting by incorporating a Done flag that is set when the motor stop command is sent out. The flag is only reset with a new motor position request. That's how I found the ADC value drifting.
The S curve ramping is working fairly well. I am using trial and error to determine the best time interval for the formula, right now it looks like between 25 to 35 msec are best.
Good day programming, I got the Tibia motor routine with ramping working the way I want. I tried to use the same routine on the Coxa but that didn't work out so good. Basic troubleshooting indicates some more in depth work is needed. I need to start from the basics and build up a new routine from scratch using the working routine as a guide. Getting closer!
Due to internal gearing backlash the motor may start but the ADC will not change for a significant time. This is most apparent when the motor reverses direction. The delay in getting an accurate position reading means the motor tends to overshoot the intended position and then trys to reverse direction to return. This causes the motor to 'hunt' back and forth. I am using a deadband to help reduce the occurance of this but this then reduces the precision that the motor can be postioned to. This will most likely be one of those items that is a trade-off between precision and hunting. Once weight is applied to the leg some of this should be reduced, I've tested this by putting some pressure on the leg
Our auto-pointing telesope takes into account backlash on direction changes by tracking which direction the motor *had* been moving before stopping. If there is a direction change when the motor restarts, then backlash is presumed when caclulating position (and in your case, you could disregard the lack of change from the ADCs for a short interval while the backlash works itself out). If the motor travels in the same direction it had been when restarting, the position is deemed accurate.
Our auto-pointing telesope takes into account backlash on direction changes by tracking which direction the motor *had* been moving before stopping. If there is a direction change when the motor restarts, then backlash is presumed when caclulating position (and in your case, you could disregard the lack of change from the ADCs for a short interval while the backlash works itself out). If the motor travels in the same direction it had been when restarting, the position is deemed accurate.
That gives me a couple of ideas to try out now! Thanks for the hint!
I created a seperate ramp routine for the Coxa for testing based on the tibia ramp routine. I've got the ramp up S-curve to work now but it stops as soon as the full speed or ramp down S-curve routines try to start. I added some print statements to localize the locations in the code where it is dropping out of the loop. Initial review is indicates the math will be slightly different for this motor, I may not be able to use the same ramp code for all three motors (the femur code should be the same as the tibia code) and have a seperate ramp routine just for the Coxa. I'll see what it looks like after it's working. I might be able to use a case statement to change up the math needed for each instance. It's not like I should run into a code space issue as the plan is to have one propellor controlling each leg.
The ramping using the S-curve routine is working out nicely. I'm not seeing the jerkiness that was being exhibited with the earlier tests.
This weekend got all three axis up and running at least individually! There are enough differences between the 3 motor ramping routines that it would be difficult to merge them into a single function. There are still some software errors that need resolving but the basic motor control capability is there. I video'd parts of the testing and managed to string the sequences together into something that makes some sense so here are video's taken over the last 3-4 weeks during software development and testing. I removed all but one leg to make a little room and frankly all those extra wires were getting in the way!
I will continue to troubleshoot the software and correct some of those annoying errors. I had to change out several of the objects I used originally because I ran out of cogs. I'm now using all 8 cogs however I haven't finished testing using all 3 motors at the same time. Needing 8 cogs for a single leg enforces the idea that I need a seperate propellor for each leg. I'll need to start creating a custom circuit board soon. More progress towards the goal, even if it is only a single leg right now!
Continuing on with programming leg movements. Issues that I've encountered in programming are being covered in the Prop forum. The biggest issue was having a noisy ADC input. This throws the motor ramping functions all out of whack and needed to be solved. The answer was to incorporate a median filter. In this filter I get 10 sequential ADC values, sort them in ascending order and then drop the 3 highest and lowest valves. The center 4 values are then averaged. The output is much smoother now and the filter programming is much happier!
The ramp function is similar for all three motors, just a few tweeks to account for design differences. The ramping is fairly straight forward, it's all the error checking that makes it complex.
I also miscounted the number of cogs needed, I forgot to take into account cog 0. So the design needs 9 cogs instead. I think the light bar will have to be dropped from operating off of the individual leg computers, and run it off the main computer.
With three motors running I'm ready to do some simultaneous motor moves and verify all the motors can move together. I also have some mechanical limits for the tibia and femur that need to be taken into account. The tibia range of motion is limited when the femur moves towards its full extension. I'll need to program that into a function soon. After that it's time to start some IK programming.
Initial tests of all three motors operating at the same time worked. The only glitch is that the Coxa motor feedback has changed from its calibration values. This indicates either the shaft extension or gear is slipping. I will either put in a set screw or put a pin in it to lock it down.
Ordered 6 Mikronauts RoboPi circuit boards to use as the individual leg controllers. Since they are kits I'll have to get the soldering iron out. Having boards already designed and tested will help save a lot of time. I've also been posting in the prop forum on the best prop to prop communications options. So far it looks like I'll use a star configuration of the six props feeding seperately into the master controller. I'll use a simple serial object to run comms to each leg and feedback info. Don't know just what I'll use for the master controller but I have one prop board that already has an XBee socket, that will most likely be the one.
Didn't get as much done this weekend, too many competing tasks!
Comments
I still have to finish some soldering on the wiring harnesses but I have enough done to get at least two legs up and running for initial calibrations and testing.
I did discover one issue I need to work through, the multi-turn pots I'm using have shafts that are just a bit too short for a reliable connection to the spur gear on the swing gear reduction. I either have to find pots with longer shafts or design some type of extension. More on that later
Bob
I have 10 of these - (PDF) http://www.vatronics.com/Upfiles/down/201171847057.pdf
They seem to have a long shaft, if you want I can send some to test out.
Thanks for the offer! I went online to check out some 10 turn, 10K shaft driven pots and got a serious case of sticker shock. I saw prices on Digikey ranging from $8+ to $175. The pots I'm using we're surplus and considerably less!
I think I'll first see about machining a shaft extension and use a set screw or roll pin to hold the extension and gear in place. This doesn't have to be fancy since I'm only using a nylon spur gear, no power transmission or other forces on the shaft so it can be lightweight. There is plenty of space available for it in the housing area. If that doesn't work then I might take you up on your offer!
I did get the RGB lights going, set up a couple of simple routines to push specific colors and flash a light if needed. It should look nice in the end. I didn't do the XBee wireless setup as I read some where that you shouldn't run it without an antenna so I ordered one of those for testing. I'll play with the motor controllers tonight, run some of the setup routines I've used previously to validate the wiring down to the motor level. Then I can start calibrations on the motors.
All the other tests have gone well so far, ADC circuitry and code, RGB lighting and some other general use routines. I'm confused as to why I can't get any output from the motor controllers. I have all day today to figure this one out. It's snowing hard outside and inside seems to be the best place to hang out!
Bob
Hi
The following is what I did to get my HB25's to initialize.
That was where my problems happened.
I use a relay to turn on the HB25 Power supply.
I'm using , for now, a BS1.
Startup:
HIGH BatVolt 'Turn on 12V motor power relay
IF PIN2 = 0 THEN Startup 'Wait for HB-25 Power Up
Let DIRS = %00001110 'Set Pin2 and Pin3 and Pin1 to Output
LOW HB25 'Make Pin2 Low
Pause 5 'Wait for HB-25 to Initialize
PULSOUT HB25, 150 'Stop Motor1
PAUSE 1
PULSOUT HB25, 150 'Stop Motor2
PAUSE 20 'Wait 20ms
Pause 5000 'Wait for the HB25s to warm up.
I realize that you are using Propeller, but just thought this might help you out.
Before using this initializing sequence, I could not get the HB25s to cooperate.
Aparantly, the HB25 is pretty particular in how they are initialized.
Anyway, I like your approach to setting up the HB25, it is particular about the order in which power is applied and a programmatic solution would be easiest to implement. I'll try your version out in the morning.
I was able to run all my calibration routines on the lift (tibia) motor. The final test was the routine where I was able to enter an angle in the Propellor serial terminal (PST) and the tibia moved to the location repeatibly. I need to repeat this for the tibia and Coxa motors tomorrow. Then I will work on the Inverse Kinematics routine and see how that turns out. It's nice to finally get back into the programming side again, I've been away too long! You may have noticed I haven't discussed the impact sensor, leg down sensor or the limit switches in the program. That's because I haven't installed them yet. I decided that I will add these sensors later once I get a program built that these can be added then.
I will post some photos and a video later when I get some time to put it together.
Bob
It's not a good idea to keep on working on this now, I'm sure I'll do something I'll regret later! I have a tendency to want to start tearing things apart to figure out the problem when sometimes I just missed a simple clue. Better to try tomorrow when fully rested.
Bob
I figured out that I need a better ramp up and down routine, I keep overshooting the intended target position. An example is entering 90 degrees which might have a ADC target value of 2500. The ramp I'm using is basically 2 speeds, it slows down when the actual ADC value minus the target ADC value is less than 50. I may end up with a final ADC value of 2550 when everything stops moving. Now if I enter 92 degrees it is possible that the leg moves the wrong direction since it is already over the new target value.
For this ramping routine I'm going to determine the best ramp for increasing and lowering speed. Once I know the time needed for a ramp up to full speed and back down again, I'll have to figure out how to handle situations where it doesn't have time to ramp all the way up and down again.
The calibration shows that the linkages on the production legs are much tighter than the test leg in that I'm getting the same ADC values no matter which direction the leg is moving. As a bonus, when I plotted the ADC values they are very linear.
I'm going to use this information to greatly simplify the calibration process by storing the ADC values for each extreme as constants and calculating the target ADC value using the slope of the plotted values. This removes the table of ADC values that I've been using.
So I've got my next programming challenges laid out. Now, back to the shop!
Bob Sweeney
I got tired of swapping screens from the spin compiler to the serial terminal. I located an old LCD screen I haven't been using and will get a dual screen video card from Best Buy tomorrow. That will speed up the troubleshooting as I write to the PST information I need for troubleshooting.
Since my last posting I'm now on version 4 of the motor control routine. They all worked except for little issues that couldn't be resolved easily. The current version is the best one yet but it has its own quirks that I'm trying to work thru. The biggest issue was overshooting the desired position but I got that down to a much lower value by stopping earlier than the target rather than wait until I reached the target. It makes sense now but it took some work to get here.
The current and hopefully last issue is the fact that the ADC shows smooth movement towards the goal and the final ADC value is within 10-15 increments of the target. However if I use the same input angle value that got to this point (should be no movement as it's the same angle and the actual ADC should be with the dead zone of +/- 20), but the new starting ADC value comes up 100-150 points either higher or lower depending on the direction. So entering the same angle has the motor moving first one way and then the other. I believe the problem is that the motor is still moving after I send the stop command as it coasts down. I am going to come up with a 'fudge factor' I can add to account for this extra movement.
This has taken longer than expected, I was planning on doing some IK stuff but this needs to be fixed first. Can't have the legs coming up with their own positions arbitrarily. I have some video and will post that and the code once it gets closer to a reliably working product.
Bob
I finished up the femur and tibia motor routines that incorporates some 'dead zone' to account for the extra motor movement. This seems to have helped quite a bit. The Coxa motor routine needs a bit more work, it uses a similar motor routine but it seems to be a bit pickier than the other two.
I was able to start work on the Inverse Kinematics calculations finally and have spent several days puzzling over the formulas. Paul Krasinski, the same person who developed the Q4 digital transmitter I'm using, is helping me understand the way he coded has hexapod. I finally figured out today that one of the reasons I was having so much difficulty in understanding his code and why mine wouldn't return good data was that we were using different frame references for our , Y and Z values. Once that was figured out my formulas started working. I've only got a simple gait installed on a single leg, the femur and Tibia seem to be responding as expected but the Coxa motor routine issues reared back up. Once I get that solved I'll make a video and post it here.
Bob Sweeney
I did want to post a picture of my test setup and the leg equations. My last post was from my iPad and I didn't have access to the files then. The drawing shows 2 views, the left drawing is a side view of the leg and the right drawing is the top view. The red circles are the pivot points and I included the primary dimensions. The formulas are used to calculate the position of the leg foot in 3D space. The top view of the leg shows the value L which is the total length of the leg looking down from the coxa pivot to the desired end point location of X,Y. The values of X and Y are input from the user. Y would be the distance out from the pivot point that the leg tip will be at. X is the actual gait that the leg will be taking. I'm still learning this next part but X is programatically sub-divided up into smaller increments as the leg moves so to smooth out the movement. I haven't gotten that far in my experiments. Once the value L is determined from the Pythagoras Theorem ( sqrt(X^2 + Y^2) the remaining values are measured from the side view of the leg. I won't get into the math but it is all basic trig. First time I've used trig outside of school in a long, long time! In the end you get the angles needed for each motor to move to. Of course there are many other elements that also get involved here such as the position of each leg around the body so that you get coordinated movement.
Bob
For whole body motion, have you considered the following theories in addition to Inverse Kinematics?
- non-holonomic motion planning
- Euler spirals, clothoids or Cornu spirals. (They're used in road/railway engineering to reduce centripetal acceleration on transition curves such as on/off ramps, etc.) https://en.wikipedia.org/wiki/Euler_spiral
I am thinking of the case when your robot begins to dance and rotate very quickly (or perhaps, run), causing centripetal acceleration resulting in issues with precise leg positioning.
Bob
My mind is having difficulty grasping how all motors use the same ADC routine. I expect each motor to have its own ADC pin.
All cogs have access to main memory. I declare variables or arrays in main memory and have each cog access its unique variable or array element. You can display the variables or array values in PST.
This was a snow day up in Michigan, lots of snow coming down and blizzard conditions, good day for staying inside and programming. Time for dinner and then back to the shop!
Bob
The simplest motor control is simply turning on the motor, run it at full power until you reach your setpoint and then remove power. This is the easiest to implement but has the most issues. The motor and the mechanical items attached to it experience 'jerk'. During motor start and stop there is stress on the mechanical items as they abruptly either start moving or stop. This can be seen as a vibration that can be severe in some cases. The higher the mass the motor is moving, the greater the effect. Additionally, motors don't just stop on a dime. When power is removed, the motor takes a finite amount of time to coast to a stop. This can throw your expected stop location off by a significant amount. This method of motor control is best used for either moving small masses or the actual stopping point is not critical. I use this method only during initial motor testing to verify the code is correct and even then I run the motors at a greatly reduced speed.
The next motor control method is the one most commonly used in amateur robotics, linear ramps. This is an easily programmed method as the motor power is increased or decreased at a constant rate. This is represented in the graph as a straight line. This method reduces the amount of jerk that occurs by a significant amount. On the deceleration ramp the motor will still over shoot the entered set-point but the amount of over shoot is reduced as compared to the first method.
Time
Fr
Out
Out 1
0
0
0
1
1
0.1
0.028
0.997692
2
0.2
0.104
0.969802
3
0.3
0.216
0.880187
4
0.4
0.352
0.715516
5
0.5
0.5
0.5
6
0.6
0.648
0.284484
7
0.7
0.784
0.119813
8
0.8
0.896
0.030198
9
0.9
0.972
0.002308
10
1
1
0
The next method is designed to reduce the amount of jerk as much as possible and reduce the amount of overshoot. Mathematically it is called an S curve. I'll leave it up to you to Google the various examples but here is a modified version of an S curve that can be programed in fairly simply. The equation is broken into 2 parts for ease of understanding and coding. I can't take credit for this version, that belongs to Peter Nachtwey. This was found in the forum discussion here: http://www.plctalk.net/qanda/showthread.php?t=31007
Fr = time / ramp_time (ramp_time = 10)
Out = (3 - 2 * Fr) * Fr * Fr
Out1 = 1 - (3 - 2 * Fr) * Fr * Fr
This gives the two curves that range from 0 to 1 over a specific time period. As you can see the Out curve starts out slowly and rapidly builds until it comes close to the max value and then eases into this. Out1 reverses this action and brings the motor to a smooth stop. Those of you who Google the S curve equation will see that this is not the same equation but the output results are very similar and can be much more easily computed on the processors we use. From this point it is just a matter of using these values to fit them into the desired range. For my situation, I am using HB25 motor controllers that use PWM from 1ms (max speed one direction) to 2ms (max speed the other direction) with 1.5ms as the stop value. I used Excel to spreadsheet the equations and worked out the formulas for the HB25.
This shows Direction 1 and 2 moving from Fast to Slow and back again.
Dir1 S-F = 1000+(1000*Out1)/2
Dir1 F-S =
1000+(1000+Out)/2
Dir2 S-F =
1500+(1500*Out)/3
Dir2 F-S =
1500+(1500*Out1)/3
Dir 1 S-F
Dir 1 F-S
Dir 2 S-F
Dir 2 F-S
1500.0
1000.0
1500.0
2000.0
1498.8
1014.0
1514.0
1998.8
1484.9
1052.0
1552.0
1984.9
1440.1
1108.0
1608.0
1940.1
1357.8
1176.0
1676.0
1857.8
1250.0
1250.0
1750.0
1750.0
1142.2
1324.0
1824.0
1642.2
1059.9
1392.0
1892.0
1559.9
1015.1
1448.0
1948.0
1515.1
1001.2
1486.0
1986.0
1501.2
1000.0
1500.0
2000.0
1500.0
There are few other methods out there such as PID (Proportional, Integral and Derivative), Sine wave and others. This is the one that I felt would be the best for my situation is this modified S Curve. The next thing is to actually program this in and see how well it works in practice!
Since I'm away from my computer, no changes on the programming front. I am still doing a lot of reading on motor control systems and finding out a lot of things that may not be a major issue in a smaller, lighter robot but have to be considered in something this large. There is just too. Much inertia and mass involved in this system that parts will start breaking prematurely if the programming doesn't smooth out the leg movements. I am looking forward to trying to program these ideas into the system. I was trying to hurry so I could jump into the IK side of things but now I believe the safer approach is to really get these basic motor movements working 100% first.
Finally got a chance to try out some of the motor control programming I've been thinking about and got a preliminary run at it. After programming in the formulas the light bulb went off that there are only 2 sets of ten PWM values, one for 1000 to 1500 and the other from 1500 to 2000 (actually these are 1.0 msec to 2.0 msec) from the table on Post #324. I set these values up as 2 arrays and can address the PWM values directly instead of computing them each time.
There are 3 separate phases for the motor control, ramp up, full speed, and ramp down. I'm still tweaking the code and will post it as soon as I get it working correctly. Since I'm using ADC readings instead of an encoder for reading position and the motor may only have to move a short distance, additional code is needed. An encoder would have been nice but I have to work with what I got. Here are some of the special code in the motor controller in the 3 phases.
- For each motor move the halfway point is calculated based on the starting and target ADC value. If during the ramp up phase the half way point is reached, the loop is exited, full speed phase is skipped and the ramp down is commenced at the final ramp up speed.
- During the full speed phase, the ADC value at the start of the ramp up and ADC at the end of the ramp up determine the absolute value of the change. This value (along with a fudge factor due to mechanical inertia) is added to the target ADC value. Once this value is reached the full speed phase exits and the ramp down phase starts.
- Since the linear actuators have internal limit switches that are not accessible externally it is possible for the motor to stop without reaching the calculated target. ADC values are monitored and if there is no change in value while the motor is supposed to be running, the 'stuck' phase is exited. I should take one of these actuator apart and see if it is possible to modify the actuator and make these switches available (research project!)
- Due to internal gearing backlash the motor may start but the ADC will not change for a significant time. This is most apparent when the motor reverses direction. The delay in getting an accurate position reading means the motor tends to overshoot the intended position and then trys to reverse direction to return. This causes the motor to 'hunt' back and forth. I am using a deadband to help reduce the occurance of this but this then reduces the precision that the motor can be postioned to. This will most likely be one of those items that is a trade-off between precision and hunting. Once weight is applied to the leg some of this should be reduced, I've tested this by putting some pressure on the leg
That is the basic program flow for motor control, there are still some issues to troubleshoot for and testing to ensure it works reliably. I'm sure there are some additional scenarios I'll have to code for also.Bob
Since we have a snow advisory tomorrow and I get the opportunity to stay home, I'll take apart one of the actuators so I can physically see if the motor is still turning. This should prove or disprove this theory!
I eliminated the hunting by incorporating a Done flag that is set when the motor stop command is sent out. The flag is only reset with a new motor position request. That's how I found the ADC value drifting.
The S curve ramping is working fairly well. I am using trial and error to determine the best time interval for the formula, right now it looks like between 25 to 35 msec are best.
Our auto-pointing telesope takes into account backlash on direction changes by tracking which direction the motor *had* been moving before stopping. If there is a direction change when the motor restarts, then backlash is presumed when caclulating position (and in your case, you could disregard the lack of change from the ADCs for a short interval while the backlash works itself out). If the motor travels in the same direction it had been when restarting, the position is deemed accurate.
I created a seperate ramp routine for the Coxa for testing based on the tibia ramp routine. I've got the ramp up S-curve to work now but it stops as soon as the full speed or ramp down S-curve routines try to start. I added some print statements to localize the locations in the code where it is dropping out of the loop. Initial review is indicates the math will be slightly different for this motor, I may not be able to use the same ramp code for all three motors (the femur code should be the same as the tibia code) and have a seperate ramp routine just for the Coxa. I'll see what it looks like after it's working. I might be able to use a case statement to change up the math needed for each instance. It's not like I should run into a code space issue as the plan is to have one propellor controlling each leg.
The ramping using the S-curve routine is working out nicely. I'm not seeing the jerkiness that was being exhibited with the earlier tests.
I will continue to troubleshoot the software and correct some of those annoying errors. I had to change out several of the objects I used originally because I ran out of cogs. I'm now using all 8 cogs however I haven't finished testing using all 3 motors at the same time. Needing 8 cogs for a single leg enforces the idea that I need a seperate propellor for each leg. I'll need to start creating a custom circuit board soon. More progress towards the goal, even if it is only a single leg right now!
Bob
The ramp function is similar for all three motors, just a few tweeks to account for design differences. The ramping is fairly straight forward, it's all the error checking that makes it complex.
I also miscounted the number of cogs needed, I forgot to take into account cog 0. So the design needs 9 cogs instead. I think the light bar will have to be dropped from operating off of the individual leg computers, and run it off the main computer.
With three motors running I'm ready to do some simultaneous motor moves and verify all the motors can move together. I also have some mechanical limits for the tibia and femur that need to be taken into account. The tibia range of motion is limited when the femur moves towards its full extension. I'll need to program that into a function soon. After that it's time to start some IK programming.
Ordered 6 Mikronauts RoboPi circuit boards to use as the individual leg controllers. Since they are kits I'll have to get the soldering iron out. Having boards already designed and tested will help save a lot of time. I've also been posting in the prop forum on the best prop to prop communications options. So far it looks like I'll use a star configuration of the six props feeding seperately into the master controller. I'll use a simple serial object to run comms to each leg and feedback info. Don't know just what I'll use for the master controller but I have one prop board that already has an XBee socket, that will most likely be the one.
Didn't get as much done this weekend, too many competing tasks!