Can I control servos and multitask at the same time?

Discussion about the ZBasic language including the System Library. If you're not sure where to post your message, do it here. However, do not make test posts here; that's the purpose of the Sandbox.
Post Reply
ZBWillUser
Posts: 13
Joined: 15 March 2012, 15:18 PM

Can I control servos and multitask at the same time?

Post by ZBWillUser »

I want to multitask, but I also need to control up to 3 servos at the same time. Will there be any "gotchas" I need to look out for in this situation?

I don't want to risk damaging the servos because their timing gets messed up. Would it be better to put servo control in the main task to improve their timing?

"Problems seen in advance and avoided aren't problems at all."

Thanks in advance.
dkinzer
Site Admin
Posts: 3120
Joined: 03 September 2005, 13:53 PM
Location: Portland, OR

Re: Can I control servos and multitask at the same time?

Post by dkinzer »

ZBWillUser wrote:I don't want to risk damaging the servos because their timing gets messed up. Would it be better to put servo control in the main task to improve their timing?
If you use hardware PWM to control the servos the only issue you might have is some latency between when you detect/decide that you want to change the position (i.e. the duty cycle of the PWM) and when the code executes that actually changes the duty cycle.

On the other hand, if you're planning to implement the servo pulse streams entirely in software then multi-tasking will almost certainly interfere.

If I recall correctly, you're using a mega1280-based ZX so you have plenty of hardware PWM channels to use.
- Don Kinzer
ZBWillUser
Posts: 13
Joined: 15 March 2012, 15:18 PM

Now I need more info on hardware PWM prog for a servo.

Post by ZBWillUser »

You are correct, I have a ZX-1280n (I would think being an n would be a help in this situation).

Where are some good examples of using a harware PWM to drive a servo?

I am used to using the Servo() command in the Arduino which didn't multitask and didn't run Basic, but wasn't bad for what it was.

As usual, thanks for the fast response.
ZBWillUser
Posts: 13
Joined: 15 March 2012, 15:18 PM

Got it!

Post by ZBWillUser »

Got it!
(Basically like this...)

Code: Select all

Dim taskStack(1 to 100) as Byte

sub main()
	CallTask "MyTask", taskStack
	'This works on Channel 2 (B.6)
	Call OpenPWM(2, 50.0, zxFastPWM)' prepare for 50Hz Fast PWM using channel 2
	Call PWM(2, 7.5) ' generate PWM with 7.5% duty cycle (1.5mS)
end sub

Sub MyTask()
	Do
		Debug.Print "Hello from MyTask"
		Debug.Print "Taking a break from Main()"
		Call Delay(2.0)
	Loop
End Sub
(Your SysLib is just awesome!)
dkinzer
Site Admin
Posts: 3120
Joined: 03 September 2005, 13:53 PM
Location: Portland, OR

Re: Now I need more info on hardware PWM prog for a servo.

Post by dkinzer »

ZBWillUser wrote:Where are some good examples of using a harware PWM to drive a servo?
It is helpful to understand how servos work. With that foundational information, you should be able to understand the following code (untested).

Code: Select all

'
'' InitServo
'
' Initialize a PWM channel for driving a servo.  The base frequency
' is set to 50Hz (20mS period) and the duty cycle is set so that the
' "on" time is 1.5mS, i.e., the neutral postion.
'
Sub InitServo(ByVal chan as Byte)
    Call OpenPWM(chan, 50.0, zxFastPWM)
    Call SetServoPos(chan, 0)
End Sub

'
'' SetServoPos
'
' Set the duty cycle on a PWM channel to correspond to a given position
' expressed as a signed value from -100 (corresponding to an "on" time
' of 1.0mS) to +100 (corresponding to an "on" time of 2.0mS).  It is
' assumed that the PWM channel is already open and set to the proper base
' frequency.
'
Sub SetServoPos(ByVal chan as Byte, ByVal pos as Integer)
    ' validate the position
    If &#40;&#40;pos >= -100&#41; And &#40;pos <= 100&#41;&#41; Then
        ' compute the duty cycle corresponding to the position &#40;5% to 10%&#41;
        Dim duty as Single
        duty = 7.5 + &#40;&#40;CSng&#40;pos&#41; / 100.0&#41; * 2.5&#41; 
        Call PWM&#40;chan, duty&#41;
    End If
End Sub
- Don Kinzer
ZBWillUser
Posts: 13
Joined: 15 March 2012, 15:18 PM

Nice!

Post by ZBWillUser »

Yes, I understand. Nice!

In my example I was a lot less elaborate (and precise) and was trying to show a little multitasking as well.

(It also can be done without the SysLib, but that is such a great addition to ZBasic!)

ZBasic is awesome and I wish more people knew that.
dkinzer
Site Admin
Posts: 3120
Joined: 03 September 2005, 13:53 PM
Location: Portland, OR

Re: Nice!

Post by dkinzer »

ZBWillUser wrote:In my example I was a lot less elaborate (and precise) and was trying to show a little multitasking as well.
I was only attempting to illustrate how PWM can be used to drive a servo. The routine SetServoPos() may not be a good match to your needs. For example, if you are using a standard servo that rotates -90* and +90* from neutral it might make more sense to have the pos parameter range from -90 to +90 rather than -100 to +100. You should be able to modify it to meet the needs of your application.

If you are using a servo modified for continuous rotation, you'll want to come up with a different routine for setting the duty cycle of the PWM signal.
- Don Kinzer
spamiam
Posts: 739
Joined: 13 November 2005, 6:39 AM

Re: Nice!

Post by spamiam »

dkinzer wrote:...The routine SetServoPos() may not be a good match to your needs. For example, if you are using a standard servo that rotates -90* and +90* from neutral it might make more sense to have the pos parameter range from -90 to +90 rather than -100 to +100....
Interesting idea. It can be extended even further. Depending on the geometry of the linkage, you might be converting epicyclic(?) rotational motion of the servo to a linear motion. You might want to work with a linear position, and then you would have to do more sophisticated math to convert to rotational angle, then to duty factor.

I have never done this, but I can see that it might be a useful approach for some purposes.

-Tony
Post Reply