Controlling Servo to One of Three Positions
Hello,
I am new to this language besides the course I am in. This also is not my major so it is not my strong suit. I am trying to get the servo to stay at one of three positions depending on ultrasonic sensor readings. The servo controls the rudder of a boat and operates at one of three positions: Forward (0 Degrees), Left (-45 Degrees), Right (45 Degrees). I pass the variable "tHa" from my main file in values from 1.5 (Forward), 1.3 (Left), and 1.7 (Right). I am not sure if the way I went to approach this is wrong or where the issue may be. The code is posted below:
Thank You in advance for any help.
I am new to this language besides the course I am in. This also is not my major so it is not my strong suit. I am trying to get the servo to stay at one of three positions depending on ultrasonic sensor readings. The servo controls the rudder of a boat and operates at one of three positions: Forward (0 Degrees), Left (-45 Degrees), Right (45 Degrees). I pass the variable "tHa" from my main file in values from 1.5 (Forward), 1.3 (Left), and 1.7 (Right). I am not sure if the way I went to approach this is wrong or where the issue may be. The code is posted below:
CON _clkmode = xtal1 + pll16x ' System clock → 80 MHz _xinfreq = 5_000_000 Var long ServoStack[30] 'Stack Space for Servo Cog long tC, t 'Variables for Controlling Time and Frequency PUB Begin (tHa) ctra[30..26] := %00100 ' Configure Counter A to NCO ctra[5..0] := 31 frqa := 1 'dira[31]~~ 'Pin for Servo cognew(Position(tHa), @ServoStack[0]) 'Starts New Cog to Run Servo Continuosly Pub Position (tHa) tC := clkfreq 'Constant t := cnt/50 'Constant 20ms Reading Times by Servo repeat ' Repeat PWM signal phsa := -tHa ' Set up the pulse t += tC ' Calculate next cycle repeat waitcnt(t) ' Wait for next cycle
Thank You in advance for any help.
Comments
I don't see any provision to use floating point numbers. The Propeller uses integer math unless an object (such as F32) is used to allow floating point calculations. It appears you are passing a value "tHa" from the parent. With the present code, the child object has no way of knowing when the parent's variable has changed. Instead of passing the value of the variable you would need to pass the variable's address and then access the value with "long[address]".
Under the Propeller Tool's "File" menu is an option to archive a project. If you archive the top object it will include all the child objects you're using. It would probably be easier for us to help you if attached the entire program to a post.
Thank you again,
Boat Team
I have started to do what you suggested by sending the address, which I found out how to do by looking at your other posts. I want to refer to the variable in the child, so therefore I send the address instead by putting "@tHa". then in the child I can just use the variable, is that correct?
I also am now using float math instead of integer math, so to calculate tHa, I use the formula:
tHa := fMath.FMUL (Forward, clkfreq/20), where forward holds 1.5, which can be replaced by Left (1.3) or Right (1.7)
Obviously there are still some mistakes because I my servo still isn't responding, and I forgot to mention that it is a standard Parallax Servo. Is there any way from you to tell if the values I am passing are correct for Pulse Width Modulation of a servo? I have noticed that my way of going about it is very different than others so I am unsure if I am correct in that part. I will attach the new files below.
You can disregard the above comment.
Current file edited with cogs and floats - Archive [Date 2014.04.29 Time 14.43].zip
Instead of floats, I'd suggest using scaled integers (Heater told me the correct name for this technique but I don't remember what that name is). Multiply the integers you want to use by some fixed value like 1,000. So instead of attempting to have 0.5, you'd now have 500 which is but easier to work with.
Not only can you not mix floats and integers, but you can't really use "<" or ">" comparisons between floats and other floats or floats and integers. Keeping your numbers as integers will save you a lot of trouble (you are presently using floats incorrectly).
To display these scaled integers you can use a method like this:
If "x" had been scaled by 1000 you could display the value in decimal format with the following line of code.
If x equaled 500 it would display as "0.500".
The forum member "local roger" (possibly one word) posted a better formatting method "fdec" in an object call "strfmt". "fdec" isn't as simple to use as my DecPoint but it's much more versatile.
I looks like you're passing the address of the variable but you're not using the address correctly in the child object.
should be
and
should be
And in the top object, you don't need (nor do you want) the final
The top object just needs to change the value of "tHa" and the child will read it new value automatically.
I think using scaled integers and making the other changes I suggest will go a long way in improving your code. I'm pretty sure there will be other mistakes (there are lots of ways to make them) but you should be closer to a working program.
I mean if the variable adds up to be in the range of turn left, then case := A, if the boat needs to turn right, then case := B...
Math is hard enough for me, let alone trying to put a dot into the middle of a number just to try and trip me up.
But if anyone can do the math, it will be the mighty Duane Degn.
However you wind up doing it, +1 for using a Rudder..:thumb::thumb:
-Tommy
Maybe it is different now because I am not referring to the address since I am passing an integer now.
Once again I have attached the code at the bottom. The main issue I am having is that when I try to call Servo #2 a second time with a new value, the parallax serial terminal goes berserk and sends random symbols at me. If I comment the last part out, the Parallax works correctly, but it only moves the rudder to the forward position and does not change it to any change from the sensors.
I am sorry I am being such a pain here and I wish I knew more so I didnt have to ask, I am learning new things every time though, but there is still plenty to learn.
Thanks again.
And @Ttailspin, I realize now that I can use "case" statements now, but I is there any benefit besides it is more straightforward, like is it faster or someting? And thanks, the rudder boat is pretty cool, we had one with a dual prop but we figured this one would allow us better control. I just hope the HC SR04's will be accurate enough because I did not feel like spending 300 dollars on laser sensors for my school project although I am sure they would be loads more accurate.
Current file edited with cogs and floats New - Archive [Date 2014.04.29 Time 17.33].zip
Instead of calling "Rudder.Begin(Position)" at the end of your loop in the parent object call the "Rudder.Change(Position)" method.
The "Begin" method starts a cog each time it is called until all the cogs are used up.
Fantastic!
I hope you keep us posted on your project. It would be great to see some video.
thanks again for all of your help
As for the GPS mapping side of things, it's actually insanely easy with the Propeller. Check out this recent thread which discusses this a bit. The code on this post from another thread has the code from my Google Earth Datalogger spawned from Paul_H's code that might do everything you are looking for as well. It parses GPS NMEA strings into KML formatting to be imported directly into Google Earth.