My journal of creating and experimenting with circuits, CNC, programming, and robotics
Friday, November 30, 2007
Well I shot myself in the foot so to speak. I took my code to work to hammer out some of the details. This meant a lot of changes without being able to test them. Somehow I incorporated old code into the new code and contaminated both :(
Long story short, I'm going back to a reliable backup on 11/25/2007 which was before my last two posts. Thus, I'm progressing in the wrong direction. The good news it, I'm incorporating the code optimizations I made recently into the old code prior to me breaking out the functions into their own files. This way I can know they work before I change too many things at once.
On a good note, I've been mocking up a claw mechanism at lunch today. Saw a YouTube video of one I liked and fashioned a working model out of craft sticks.
Jay
Wednesday, November 28, 2007
I have successfully added RTOS (real time operating system) to my code. I'm using FreeRTOS (www.freertos.org) and it was relatively painless to incorporate. Some of the details that slowed me down:
- The kernel timer uses Output Compare 1A which is the same I was using for the right motor PWM.
- The port.c file configures the Timer 1 only for Output Compare 1A which overwrites all my settings for pwm I set in my motorInit code. As such, I changed the code in port.c to use |= when setting it's bits. This is the only kernel change I had to make.
- I used to have all my code in one file. This is due to the fact that I just kept adding on to experimental code rather than formalize everything. Prior to the addition of the RTOS, I broke out functions in to separate files based on organization (motors, motion, and eventually sensors).
- I was also using a lot of global variables (bad form I know but it's been fixed) in my one file. Rather than declare them extern in my new files (yes I tried that at first), I added functions to "get" and "set" key variables.
- Now I can add a task to the list to execute without other functions having to call it or be aware.
- No blocking (well except for serial, but it's the lowest priority) so now pauses (which used to nop for x milliseconds) just yield to other processes.
- Now I can build behaviors that can layer on top of each other and turn them on or off via a monitor/command line program.
- Sensors will run in their own task loops (like sonar) at set intervals which was more difficult to time with function calls especially when something new was added to the mix.
To do:
- Wire up the 4 IRPD sensors and 2 bump switches.
- Code a wall following behavior
- Code a avoid behavior (to drive/navigate) around an obstacle while still trying to get to a target coordinate :)
- I ordered a Lipo balancer for my battery. I got a great deal on the battery I use (4S 12C 33oomAH) and the replacement cost would be much more than I paid (thank you www.cheapbatterypacks.com) so I'm going to baby this one.
- Through typos I ran my motors full speed using the new RTOS code. The measured speeds were 90 ticks/ 20ms. The movie below shows the motors going 18 ticks/20ms so I plan to increase the max speed a bit. For shorter runs the code will auto slow the bot anyway, but this make longer distance "shorter" ;)
Jay
Monday, November 26, 2007
Friday, November 23, 2007
My code to command the robot to go x distance or turn x degrees works great .. .the issue is that due to slight differences in the motor speeds, the robot could be off by as much as an inch in a 2 foot span. So I decided to change the system over to a target based one.
The code is inspired/copied from David P Anderson's find_target and odometry code. I did add some tweaks of my own, and I've not yet started on using an RTOS.
I added a function that allows me to specify a target coordinate (x,y). Then I added find_target to my timer loop and call it every 30ms. The function looks at the distance and angle and commands the motors to those speeds. By using he distance left to set the speed I get nice fast and crisp movements. Before I added/fixed the code that your set the speeds proportionally, the robot was all over the map oscillating like crazy. Have a look at tonight's results.
The robot starts at 0,0. I then commanded it to go to 5,5 (that in inches BTW) and then to go to -10, 3. The pink and yellow lines are there for reference. The blue line is the plot of the X and Y coordinates reported by the robot. I have the printout function send data every 40ms (a bit too fast really) so the point markers are really close.
To dos:
1. Add the ability to create a point array from the drive pattern routine. Then have the robot traverse the array.
2. Figure out how to call the print routine every X ms. Because it uses an interrupt, it'll have to be outside the timer routine that I use for the PID and find_target.
3. Find a suitable and ready to go RTOS to port my code to. I'd rather quit fooling with ms timers and just run all the processes concurrently and have a central function call each when it's their turn.
Onward,
Jay
Saturday, October 13, 2007
Man what a day. I worked with the students today on getting the TIMER basics down, configuring their development platforms (WinAVR, AVR Studio, JTAG ICE), and learning how useful Excel is for calculating TIMER registers.
During all the back and forth, I had an epiphany. I was using code that limited my PID adjustment to +-100 (as in percent). I was using 10-bit PWM, but by limiting myself to (let's just look at forward speed) 100 possible values (out of 1024 (2^10)). Well that's still not totally true either. I'm using locked anti-phase PWM so only values above 512 generate forward motion. But I digress, I'm still only using 1/5 of the total values I could. So I modified my code and changed the limits to +-511. It works, and a lot better. Still need to tune the PID constants, but things are a lot smoother.
On a bad/disappointing note I ran my Lipo to 12.8V. Minimum is 12V (3V per cell) but I decided to check (for the first time since I had it) the individual cell voltages. Bad news:
- cell 1 - 2.9V
- cell 2 - 3.49V
- cell 3 -3.02V
- cell 4 - 3.34V
From now on, I'm going to check balance every time.
Jay
Thursday, October 11, 2007
As promised. A short video of my bot in action. The video starts with me showing the pattern function. I told it to drive a pattern with 5 vertices and sides that are 20" long. At this point I fix the speed at a mild rate. After the pattern completes I instruct it to drive 24" at full speed. You can really see the left steer. Then I instruct the bot to turn 360 degrees full speed.
Jay
Last night I was able to connect to my robot, send commands, and receive output. This is huge (to me at least). Next step is to modify the receive code to parse out the data into arrays. Then to plot them. To do this, I will create a JPanel class that I can override the paintComponent function to do my bidding.
This weekend is a bachelor weekend so I hope to have it mapping by Sunday. At which time I'll do a video ... finally.
Onward,
Jay
Tuesday, October 09, 2007
I wanted to see how accurate my bot is at this time. I took the output from the PID tests I did (see the graph below) and added odometry calculations and plotted the X and Y coordinates based on the data.
As you can see for 36" of travel my bot is off about .04". What else does this show ... that my left wheel leads the right wheel. Most interesting to me is that the the worse occasions of this steer is during velocity ramps. I may need to rethink my PID loop or add another component that can correct for this "steer". Then again, with an 8" diameter bot 40 thousandths of an inch doesn't seem that much ;)
I'm still working on my Java interface. I have made some progress (like getting the serial ports to enumerate and populate a JComboBox, redesigned the GUI layout) but I still need to get the serial listener portion to connect and communicate. I haven't had a big enough block of time to sit down and get my head around it though.
Onward,
Jay
Saturday, October 06, 2007
Here is my plan for version 1 of my GUI.
My plan is this. I will have a thread that does nothing but parse the incoming serial stream into a multidimensional array. The array components will consist of:
- time (this will be the value of the free-running timer from the AVR)
- left commanded velocity
- right commanded
- left measured velocity
- right measured velocity
- left distance (though I may omit these and let the GUI calculate these two)
- right distance
- sonar reading
- left PWM value (right now I'm set for 10-bit PWM, this might help me determine if I can use less resolution)
- right PWM value
- left PID proportional value (the I is silent :) )
- right PID proportional value
- left PID derivative value
- right PID derivative value
Stay tuned...
Friday, October 05, 2007
Well, I want one for sure. I am tired of the 5 step process I'm using to capture my robot's output and plot it in Excel. Therefore, I'm starting work on a Java application that will plot the PID output, map the path the robot has taken, and allow interactivity with the robot.
A buddy said I should try Netbeans (it's been a while since I did any Java coding but GUI layout was a PITA). With Netbeans I am able to design my GUI and then plug in my processing code. The GUI design is slick. Netbeans also have a nice UI for keeping my code straight and has it's own CVS. Screen shots to come soon.
Jay
Thursday, October 04, 2007
I modified my interrupt code to switch interrupt levels. On the Mega128 external interrupts 0-3 don't have the option of setting the interrupt level to both. Both meaning low to hi and hi to low edges. You get either or. So in my encoder code, I added a state variable to tell which was the last state. I'm only interrupting on the A channel but now I get double the interrupts by detecting both edges.
The good news it my resolution has improved to .0047" per tick. The bad news it, I have to re-tune my PID loop :(
Last night I decided to modify my motor control code to take in account how fast the bot is traveling, and how far it has left to go. The results are good and it has smoothed the ramping I had coded earlier. In fact, in hindsight, the previous code was too restrictive ... now the control is more adaptive. I know I keep promising a video, but there's always something I want to fix before showing it off. I'll do it tonight first thing before I enter another 3 hour coding stint.
As for the PID, have a look at last night's capture.
The thick red is the left encoder measurement, the dashed pink is the right encoder. The yellow (click the image to see a bigger version) is the commanded left velocity. As you can see, I have a lot of oscillation now as well as an overdamped response. I need to go back and refresh my memory on PID tuning and what do I need to do to clean this up. One more thing, the instruction was to drive the robot forward 36". It took about 4.8 seconds.
Jay
Tuesday, October 02, 2007
I've completed the CNC conversion of my mill and have it sitting on my work bench. This means:
- I can work on CNC in A/C comfort versus the garage
- I have to be very mindful of "dust" on whatever I mill so I have only played with engraving wood
- I need to make an enclosure so I can keep it in the house
As for me, I need/want to improve my robot speed/positioning. My encoders are 1000PPR, If I can double, triple, or sextuple that I can increase my accuracy. I'm looking at replacing my motors and encoders with some new ones. The encoder will be mounted on the motor and I calculate 6000PPR with them. As a bonus they have a higher output RPM. The con is that they are 7.2V motors and my Lipo is 14V. I can control the peak voltage via PWM so it's not that big a concern. The other con is cost. We are talking $94.
I need to post a video of what my robot looks like now. It's been a while, but I wrote a program the takes input variables for side length and number of verticies. It then commands the robot to draw that shape based on the calculated angles and distances. It works ok, but one motor always lags the other. My peak speed is 20 ticks for the PID time period I chose (20ms IIRC). This means I can command the robot to go 0 to 20 ticks. This is too small of a range. With the new motors, the range would be 0 to 120.
Onward,
Jay
Friday, March 16, 2007
Just wanted to post a graph of my measured velocities ... or put another way, how well my PD loop is controlling my motors. The motors have been commanded to go 14. 14 = 14 ticks per 20 ms. I have 1000ppr encoders on 3" wheels so that's .1357"/20ms at that speed. Expanding that the bot is traveling 6.7 inches per second or 407.12 inches per minute or 33.9 feet per minute or just for grins .382 miles per hour :D
Anyway, notice the error is only +-1 tick. I may play with adding in an integral component. The graph shows the output of the bot being commanded to drive in a 10" square. The first step drives both motors forward, then stop (it even reverse the motors to effect a quicker stop) then left reverse, right forward to turn to the left 90 degrees, the forward ...
One other neat side affect is that the motors resist any change from the commanded speed. Put another way, if the robot is told to stop (left and right = 0) then if you try to push it, it will resist (actively turn on the motors in the reverse direction. Cool, but is a big battery drain as the current will shoot to 1.2 amps.
Finally, at this PD rate (50Hz) the fastest encoder speed is 18ticks/20 ms which equals 8.7 in/s or 43.6 ft/min or .49 mph :)
Jay
Tuesday, March 13, 2007
The BlueSMiRF is paying huge dividends in my ability to code and test. My PID function is working great and I have set it for 50Hz. I have expanded my interactive menu to allow me to command distances and angles to the bot. Last night I finally added a separate switch for the motors, and mounted the motor controller circuit. I’ve been using a 3S Lithium Polymer battery for my power source, and am thinking of getting a 4S to see how fast I can go.
My next task will be to add the SoundGin circuit and play with announcing the current command or some phrase. Then I want to add odometry calculations and command waypoints. Then add in the sonar and some prox sensors. I’m still having fun with the blue tooth though.
On the CNC front, I lucked out (or maybe not, time will tell) in winning a CNC kit for my mill off Ebay. I’ve ordered the last missing components from McMaster Carr (great prices and fair shipping) and plan to install it this weekend. In the mean time, I need to disassemble the ball nuts to make sure they are not missing any and to clean them. It’s be a waste of time to install it all only to have to take it apart due to an issue regarding the ball nuts … at least that’s the way I see it.
Onward,
Jay
Monday, February 26, 2007
It's been a long time since I last posted. I have only one excuse CNC :) It's consumed me and my attention for 3 months now. What do I have to show for it? A mini mill, a wish list, a parts list, and an AWAOL machinist that was going to help me get there.
On the robotic front I got inspired to help the local college team again and thus worked on some A2D stuff for line sensors. I also spent 5 hours with them troubleshooting their LCD, braiding wires, and answering questions. The results: they were able to follow a line fairly well before the night was over. But, the system was a bit unstable if the angle to the line was too great the robot would run right over it. Thus we started discussing how to slave the wheel speeds together to truly go straight.
Enter PID (proportional integral derivative) loops and controls. Mobile Robotics implements a PI loop, while others using a PD (http://www.geology.smu.edu/~dpa-www/robots/doc/speedctl.txt). This weekend I typed out the code in the Mobile Robotics book modifying what I thought needed to be and letting her rip. Let me just say that I am using anti-phase PWM where 0 to 128 is reverse and 128 to 255 is forward with the duty cycle getting bigger the further you get from 128. Well, the robot did in fact slave the two motors together, but in opposite directions! When I added code to stop it after 4000 ticks (4 revolutions) the robot then when in a straight line. Great ... now why is it doing that?!
Long story short, I knocked together an Excel spreadsheet to simulate the result of the PI loop today. I had a multiplication error when trying to convert -100% <> 100% duty to and actual PWM value. DOH! On the otherhand, I changed over tot he PD loop David uses and now understand a lot better what is really going on. Can't wait to try it out later tonight.
Onward
Jay
A screenshot of my excel spreadsheet
Tuesday, January 16, 2007
I made a quick 20second video of my ball launcher in action. Don't be too critical as it's on;y a quick and dirty to test my progress but several friends requested it so here is is http://www.youtube.com/watch?v=r30vDsLaZn8
Oh, and here is a shot of the new wiring I did over the weekend:
Note the labels, the braided cables, and the empty spot on the right side for the mouting of the launcher.
Onward,
Jay
Monday, January 15, 2007
Monday, January 15, 2007 Update:
I got inspired to do some wiring on my project this weekend. I made 4 connectors for the encoders and motors. I also started working on the ball launcher. I took my 2” 90 degree PVC elbow and started hacking at it. I am using a DIY brushless motor I built for flying RC airplanes to drive the launch wheel www.gobrushless.com. The wheel is foam landing tire which I tapped for 3mm (to fir the motor shaft thread) and secured with a nyloc nut. I am using a homemade mount I turned from nylon previously to mount it to an “arm” of blue PVC. The arm will screw to a block of Delrin I have JB Welded to the modified elbow. This will allow me to adjust the motor/wheel assembly up and down, and the threaded motor shaft will allow me to adjust the wheel position with respect to the center of the tube.
Onward,
Jay
Saturday, January 06, 2007
Great questions. I have been researching and procuring a benchtop mill. It should make it easier and more fun to build parts of this robot, but it’ll become it’s own project as well. I plan to convert it to CNC (CNCZone). That said, I have not put much time into doing anything on this project except read some books on subsumption during this time.
I’m hoping I’ll get inspired to work on it this weekend, but right now, CNC and machining have piqued my full interest.
How the mill comes packed and crated. First order of business was to clean the protective packing grease off.
The mill installed in it's new home. Not sure I'll be needing the drill press or not. Need to find it a new home.
Onward,
Jay