New to Propeller and I need some advice.
minitrue
Posts: 17
Hello, all
I am a physics and engineering teacher in Buffalo, NY. I have been using Basic Stamps in my classes for 5 years and am very comfortable with them.
My students recently entered a contest where they had to build a small car capable of negotiating an obstacle course and pick up items along the way for points. Their car has 4 continuous rotation servos being used as direct-drive wheels. There are also two arms on the front of the car that are each made up of two 180° servos so that the arms can rotate and elevate. Lastly, there was a continuous rotation servo that helped push the items that we picked up into a goal box. We were controlling the drive system and the pusher with a 8bit nintendo controller and we were controlling the arms haptically with 10k pots. The nintendo controller also used 2 buttons to change the speed of the car. We ideally wanted to do this wirelessly with a set of rf transceivers. We were able to do either the driving or the arms that way, but could not get them to work nicely together. Both systems became very jittery. We ended up going to the first round of our contest with a tethered car and we got second place.
The school that beat us had one kid driving by herself instead of two kids sharing duties. We want to be able to do that, and our plan is to make a controller from scratch that one girl can do by herself. We want to have four 2 axis joysticks. Two would only use the up and down function to do a tank drive system and two would be used on both axes to control the arms. We would not need the speed control functions we had since the drive could use proportional response. We would need to add one more switch or dial to control our pusher. We did not feel that a basic stamp could do this, but we tried it anyway. We do have working code, but the system is jittery because each servo is only being given instructions for 1/9th of each code loop.
I know that the propeller has 8 cogs that can work independently, and I thought we might try to run our car off of one of those.
I bought a propeller BOE a few days ago and have attached the 4 joysticks to it. I have done a lot of the SPIN tutorials on this site and have made some progress. I am going to use the four built in ADC pins for the arms and we made some RC circuits on a breadboard for reading the two drive sticks.
So far, I have been able to get readings from the drive sticks and manipulate that data into a range of values that can control a continuous servo. It works great. However, when I tried to add another servo, it still worked but the response rate slowed way down. I can't find any resources that talk about running multiple servos in multiple cogs.
This is what I have working so far:
system.Clock (80,000,000)
RC.start (0,1, @rightstick)
servo.Start
repeat
rightwheel := (94*rightstick/7) -800)
servo.Set (14, right wheel)
...and that works fine. But we want the right stick to control both right wheels. When we change the code to:
system.Clock (80,000,000)
RC.start (0,1, @rightstick)
servo.Start
repeat
rightwheel := (94*rightstick/7) -800)
servo.Set (14, right wheel)
servo.Set (15, right wheel)
...it still works but is VERY slow in responding. Can someone tell me why this is happening and what I can do about it?
Even the basic stamp could do this without an obvious delay.
What I would ultimately like to do for this project is this:
cog#1:
read right drive stick (U/D) with RC circuit
send instructions to both right wheels
cog#2:
read left drive stick (U/D) with RC circuit
send instructions to both left wheels
cog#3:
read right arm (U/D) with DAC pin and
send instructions to the right arm fixed rotation elevator
cog#4:
read right arm (L/R) with DAC pin and
send instructions to the right arm fixed rotation turntable
cog#5:
read left arm (U/D) with DAC pin and
send instructions to the left arm fixed rotation elevator
cog#6:
read left arm (L/R) with DAC pin and
send instructions to the left arm fixed rotation turntable
cog#7:
read another pot with a RC circuit and
send instructions to the pusher
I would appreciate any advice on this matter. If you know of a library or object that already exists to do something similar that would be awesome. Like I said, I already can control 1 servo, so I think I am well on my way to finishing this, I just need help with the cog assignments.
Thanks a lot!
Larry
I am a physics and engineering teacher in Buffalo, NY. I have been using Basic Stamps in my classes for 5 years and am very comfortable with them.
My students recently entered a contest where they had to build a small car capable of negotiating an obstacle course and pick up items along the way for points. Their car has 4 continuous rotation servos being used as direct-drive wheels. There are also two arms on the front of the car that are each made up of two 180° servos so that the arms can rotate and elevate. Lastly, there was a continuous rotation servo that helped push the items that we picked up into a goal box. We were controlling the drive system and the pusher with a 8bit nintendo controller and we were controlling the arms haptically with 10k pots. The nintendo controller also used 2 buttons to change the speed of the car. We ideally wanted to do this wirelessly with a set of rf transceivers. We were able to do either the driving or the arms that way, but could not get them to work nicely together. Both systems became very jittery. We ended up going to the first round of our contest with a tethered car and we got second place.
The school that beat us had one kid driving by herself instead of two kids sharing duties. We want to be able to do that, and our plan is to make a controller from scratch that one girl can do by herself. We want to have four 2 axis joysticks. Two would only use the up and down function to do a tank drive system and two would be used on both axes to control the arms. We would not need the speed control functions we had since the drive could use proportional response. We would need to add one more switch or dial to control our pusher. We did not feel that a basic stamp could do this, but we tried it anyway. We do have working code, but the system is jittery because each servo is only being given instructions for 1/9th of each code loop.
I know that the propeller has 8 cogs that can work independently, and I thought we might try to run our car off of one of those.
I bought a propeller BOE a few days ago and have attached the 4 joysticks to it. I have done a lot of the SPIN tutorials on this site and have made some progress. I am going to use the four built in ADC pins for the arms and we made some RC circuits on a breadboard for reading the two drive sticks.
So far, I have been able to get readings from the drive sticks and manipulate that data into a range of values that can control a continuous servo. It works great. However, when I tried to add another servo, it still worked but the response rate slowed way down. I can't find any resources that talk about running multiple servos in multiple cogs.
This is what I have working so far:
system.Clock (80,000,000)
RC.start (0,1, @rightstick)
servo.Start
repeat
rightwheel := (94*rightstick/7) -800)
servo.Set (14, right wheel)
...and that works fine. But we want the right stick to control both right wheels. When we change the code to:
system.Clock (80,000,000)
RC.start (0,1, @rightstick)
servo.Start
repeat
rightwheel := (94*rightstick/7) -800)
servo.Set (14, right wheel)
servo.Set (15, right wheel)
...it still works but is VERY slow in responding. Can someone tell me why this is happening and what I can do about it?
Even the basic stamp could do this without an obvious delay.
What I would ultimately like to do for this project is this:
cog#1:
read right drive stick (U/D) with RC circuit
send instructions to both right wheels
cog#2:
read left drive stick (U/D) with RC circuit
send instructions to both left wheels
cog#3:
read right arm (U/D) with DAC pin and
send instructions to the right arm fixed rotation elevator
cog#4:
read right arm (L/R) with DAC pin and
send instructions to the right arm fixed rotation turntable
cog#5:
read left arm (U/D) with DAC pin and
send instructions to the left arm fixed rotation elevator
cog#6:
read left arm (L/R) with DAC pin and
send instructions to the left arm fixed rotation turntable
cog#7:
read another pot with a RC circuit and
send instructions to the pusher
I would appreciate any advice on this matter. If you know of a library or object that already exists to do something similar that would be awesome. Like I said, I already can control 1 servo, so I think I am well on my way to finishing this, I just need help with the cog assignments.
Thanks a lot!
Larry
Comments
http://learn.parallax.com/node/252[/h]
Hello and welcome to the Parallax Forums!!!
Can you pleas attach your code using the " File--> Archive--> Project... " ? That would make it easier for us to see what all is running in your code that may be causing an issue.
I saw this, but I wasn't sure that it was the right way to go. It looks like this is for sending groups of servos to a bunch of predetermined points, and we want the motion to be fluid and proportional to the value of the pots in as close to "real time" as possible. Can a data set like this describes do that?
Thanks.
.robocross.spin
This code is now in the form that I think that I want it to be in, but it does not work. I have spent all day trying to make progress on this but I am at a loss.
Since servo's only need to update every 20ms (50 times a second) then you can do most if not all of your calculations in-between this period.
Without a complete attached archive file though it's difficult to tell what the OBJ items are doing. ... " File--> Archive--> Project... "
I can't archive it because the auto syntax checker does not like how my coginit lines are written. I have no parameters on my methods, which I don't think I need. I also don't have any stack space references because I don't really understand them.
This is my archived project. I commented out the part of my code that had the bad syntax.
Measuring Stack Space for Parallel Processes
http://www.parallaxsemiconductor.com/sites/default/files/appnotes/AN019-StackSpace-v1.0_1.pdf
The serial driver uses a cog, the RCTIME object uses a cog and the servo driver uses a cog. Your main loop will run in another cog which leaves you with four unused. You rarely want to use coginit to start a cog (I have never done so). Let the Propeller decide which cog to use with cognew but only when you really need another cog. I think the top object should be fine running in a single cog.
My hexapod uses one cog (with the assistance of another cog acting as a math coprocessor) to calculate all 18 servo positions based on some pretty hairy math and it can do this at the 50Hz servo refresh frequency. Your main loop should have plenty of time to do all the work without the need to start additional cogs.
instead of ...
RC.start( 0, 1, @rightwstick )
...use
RC.RCTIME( 0, 1, @rightwstick )
...This will eliminate excessive cog usage here.
I will look at the rest of your code later and see where there could be other optimizations.
See if the attached version is more like what you are wanting to do. One recommendation I would have would be to place an upper and lower limit to the value you are commanding to the servo's. This should be done within the Servo routine, but at a first glance I didn't see any evidence of input limitations. This is just in case one of your POTs fails or becomes unplugged, etc. This could be done in the 'Calculations' PUB in the attached file.
Beau-
This is great! It is a little sluggish in response on the sticks. I'll try splitting up the calculations into two different cogs to get the values to the servos quicker. Thanks for the help!
I noticed your dividing the RCTIME values by 8 ... what is the resistance of the POTs and what are the capacitor values that you are using? .... A smaller value capacitor and less division on RCTIME could also speed things up.
I am using .1 µF caps and the parallax 2 axis joysticks, which I believe have 10K ohm pots.
What would I need to do to the code to get the two joysticks for the arms to get data through the dedicated AD pins rather than using rc circuits on the breadboards? Is that worth doing?
Do something like this:
It's worth noting that adding the pst commands will slow down your loop, but they won't affect the calculation timing. The results you get back are clock cycles, so dividing by the clock frequency will tell you how much actual time the calculations in the 'do a bunch of work' blob are taking. Even without converting to seconds, you'll be able to see how much time things are taking relative to each other. For example, if FunctionA was 190,000 and FunctionB was 4,000,000, you'd know that FunctionB was taking about 20 times longer, and so you should focus your effort on that one.
If I'm not mistaken, the RCTime code is sensitive to the components attached to it. Rather than dividing by 8, use a smaller capacitor so it decays faster, and it'll take less time. I would be extremely surprised if your calculations or servo set functions were taking any human-noticeable time, but you'll know for sure if you measure.
Jason
Edit: I'll have to learn to type faster. Beau beat me to it.
The code that you suggested, Beau, is not that different than what could be done with a basic stamp. (Don't get me wrong- I love that it works!) but I think the slowness has to do with the fact that all the inputs are checked, one-at-a-time and then all the conversions are done one-at-a-time and then all the servos are given instructions one-at-a-time. I think I would like to try it using 6 different cogs. Each cog would be responsible for a loop of checking one joy stick, doing its own math and then sending that info to a servo. Could multiple cogs running a routine like that work?
Measure the time taken by the RCTime reading loop. I assure you that's your where your issue is. Your code would go much faster if you used an external ADC, but that will be more complicated than just using smaller caps.
Jason
Okay. Thanks. I shall try two of my caps in series and see if that fixes things.
If use an ADC, it's read digitally, so the time spent getting your inputs will be much more consistent which I'd advise in the long run anyway. There are objects in the OBEX for reading the MCP-3208, and they're available in through-hole versions, so that would be a relatively low-pain way to go.
"pot/8 -180" the new math is "pot/4 - 180" which makes sense based on the fact the capacitance is now half. I agree that if I switched to a 0.01µF cap I wouldn't need to do any division at all.
BUT- the cap change did nothing to fix the sluggish response time of the servo to the sticks. If I push the sticks forward, the servo turns, but if I quickly pull the stick back, the servo continues to spin in the first direction for almost a full second and then changes its behavior. It feels like I have to hold a position on the stick long enough for the data to be collected. The other thing I noticed is that if I just tap the stick all the way to one side and then return it to center, the servo will continue to spin for a full second before it stops.
I know that in Pbasic, you can set counters for how long a servo should go. In this code each servo is controlled by a line like:
servo.Set(11, rightpot)
What determines how long that servo is active for?
Okay. Here is a perfect example of my current issue. In this code that I attached here, I try to control two servos. One is on pin 14 and one is on 15. If I run this code, both servos work, but the lag is unbearable. If I don't change the code but unplug either servo, the other one still works and there is no lag at all. Is my lag problem just a power issue??
The BOE servo code has a loop in it that updates the servos sequentially, which is horrible - That's 1/50th a second per servo in the loop, and there are 14 of them. That's really bad. That's probably your issue. (which I would have discovered sooner if I had actually timed the code, like I suggested you do.. d'oh!)
I'd suggest trying the Servo32 object that ships with the Propeller IDE. You'll have to call the start method yourself, but I think your Set() commands will end up being the same.