Servo32v3
agodwin
Posts: 72
I've got a problem caused by the code in the library routine Servo32v3. I can see a fix for it, but don't want to creat another problem by failing to understand what's going on. Can someone advise, please ?
In Servo32v3, method Set, the pin being modified is first enabled in DirA and then the value of DirA recorded in ServoPinDirection for later use by the cog dedicated to servo outputs. The most important problem I have with this is that ServoPinDirection also records any other output pins active at the time. If some are subsequently set to be inputs, the servo cog will still have them set as outputs until Set is called again with the proper state.
I also have some misgivings about the state of the OutA register - Dira has also been set for the calling cog but OutA has not.
I would like to change the code to read ..
PUB Set(Pin, Width)
Width := 1000 #> Width <# 2000
Pin := 0 #> Pin <# 31 'This isn't too safe either ..
ServodataPin[noparse][[/noparse]Pin] := (clkfreq / _1us * Width)
ServoPinDirection |= |<Pin
i.e. don't set DirA at all for the cog using Set() and save only the servo pin bitmask for the servo cog, not ALL pins as stated in the comment.
What do you think ? Am I missing something ?
-adrian
In Servo32v3, method Set, the pin being modified is first enabled in DirA and then the value of DirA recorded in ServoPinDirection for later use by the cog dedicated to servo outputs. The most important problem I have with this is that ServoPinDirection also records any other output pins active at the time. If some are subsequently set to be inputs, the servo cog will still have them set as outputs until Set is called again with the proper state.
I also have some misgivings about the state of the OutA register - Dira has also been set for the calling cog but OutA has not.
I would like to change the code to read ..
PUB Set(Pin, Width)
Width := 1000 #> Width <# 2000
Pin := 0 #> Pin <# 31 'This isn't too safe either ..
ServodataPin[noparse][[/noparse]Pin] := (clkfreq / _1us * Width)
ServoPinDirection |= |<Pin
i.e. don't set DirA at all for the cog using Set() and save only the servo pin bitmask for the servo cog, not ALL pins as stated in the comment.
What do you think ? Am I missing something ?
-adrian
Comments
ServoPinDirection is read by the asm cog once on startup (when you call Start) (look just before Zone1 in the asm code), so it will copy the dir of any other pin to the asm cog and if you change the direction later then the asm cog will have it set to output.
If you dont set to output any pins you want to change direction on before calling servo start you will not have a problem.
If you really need to call servo start after you have initialized to output other pins that you need to change to input later then your change should work, if you dont want to change the servo code then just move the servo start and other init code earlier in your start up sequence
Also, is there any reason to set dira in the Set code ? I suppose it will force the pin to zero immediately but I can't think of any more important reason.
I changed the code in the IDE and was slightly irritated to find that it happily changed the library sources : I think I shall have to set them read-only as I'd prefer changed library modules to be kept within the project directory !
Thanks,
-adrian
I copy all the lib modules to another directory and use those including any mods I do to them mainly because when I write a driver I add it to the lib directory so I can use it easlier from multiple projects.
Sorry, I have been out of town with limited internet.
To answer your question, there is no particular reason to why I did it the way I did it other than it was my first assembly program attempt and I was trying to understand the Propeller myself. The way it is though, when I program, I typically think that anything that could potentially influence something in the "outside world" from the microcontroller perspective, you really should address first or early on upon program initialization ... other stuff, such as visual or any kind of input can wait. Applying this method of thinking and simply placing the servo initialization routines first should solve your problem in most cases.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Beau Schwabe
IC Layout Engineer
Parallax, Inc.
What I'm trying to do here is to place the values of a pot. into an array for a time, then read them out again with a servo.
Thanks in advance!
-Rob
·
I didn't see any evidence of your program locking up.· I am curious about what SERVOPOW is.· Is it power or ground·to the servo? ... and if so, the servo should not be powered through any of the I/O pins.· That said, you are initializing SERVOPOW as an output, but it remains·LOW in your program.· Is it supplying·ground?· Even so, the Propeller I/O's should not sink or source any power to a servo.
·
"What I'm trying to do here is to place the values of a pot. into an array..."
If you are reading a POT, then you should be using the RCTIME command rather than the COUNT command.
·
I ran your program as-is, and the servo on pin 18 puts out a·1ms pulse correctly.· Assuming that the COUNT command is returning a value of zero from pin 13, the formula that you have ... Value*20-300 ... would return a -300 which is considered out of bounds to the "Servo32v3" object.· As a result, the "Servo32v3" object will limit the lowest value to 1000 (likewise, the highest value to 2000), hence the 1ms servo signal that·your program is producing and what I can see on my scope.
·
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Beau Schwabe
IC Layout Engineer
Parallax, Inc.
-Rob
Can you provide a schematic and/or pictures of your setup?
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Beau Schwabe
IC Layout Engineer
Parallax, Inc.