I am attempting to control a servo, but in all of the online documentation regarding servo control it says that I should use a 50 Hz PWM signal. AFAIK the lowest I can get using GCBASIC is 1 kHz. How would one go about sending a 50 hz pwm signal to a servo? I would prefer not to use a software version since I need to check inputs and do some other processing at the same time.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
The servo only looks at the ON TIME of the pulse, with the control range running between 1ms and 2ms. A 1ms ON TIME pulse is at one end of the servos travel range and a 2ms ON TIME pulse moves it to the other end (a 1.5ms positive pulse will center the servo).
The OFF TIME is not really all that critical so for simple basic programs it's probably simpler to just send a command like:
PULSEOUT PORTB.0, position 10us
So this is really pretty simple - if you have a number between 0 and 100 (think of it as percentage of rotation) you can simple add 100 to move the baseline up, so the range of the 'position' value used in the PULSEOUT command is between 100 and 200 (which is 1ms to 2ms with the 'time unit' parameter set to '10us').
So we just make sure 'position' is in the range of 100 to 200, then after sending the PULSEOUT we wait long enough (with code processing delay of the rest of the loop and an explicit 'WAIT' command) to fill out a 10ms to 20ms delay period, then LOOP to send the PULSEOUT command above again. Note you should loop and resend the 'position' at least every 20ms even if the position doesn't change. If you violate this rule and wait too long between positive position pulses, some servos will just freeze at their current position, which isn't too bad, but others will go to Min, Max or Center positon.
For some of the more advanced PICS, you can indeed setup the hardware PWM to drive your servo using about a 50Hz to 100Hz PWM frequency with the dutycycle range limited to the appropriate values to give the proper 1ms to 2ms ON TIME. For example with a 100Hz PWM frequency the PWM cycle will repeat every 10ms, so to get a 1ms pulse ON TIME we have to set the dutycycle to a narrow 10% setting and to get a 2ms ON TIME pulse we shift the duty cycle up to 20%. Using only this limited range will limit the positional resolution of the servo, but fortunatly the hardware PWM in the most of the advanced PICS like the 16F877 has 10 bit resolution, so even if we are using only the bottom end of the resolution range, it doesn't hurt too much.
The main advantage of the HARDWARE PWM approach is that it runs continously in hardware, freeing the program from having to loop continously at about 10ms to 50ms intervals, but the low end PICS don't have HARDWARE PWM so we are limited to SOFTWARE PWM.
For these low-end PICS, I think the above simple PULSEOUT and LOOP technique is better than trying to use the SOFTWARE PWM, because GCBasic limits the SOFTWARE PWM resolution to 8 bits, and doesn't yet seem to have a way to keep this software PWM running continously in the background while other code is executing unless you write your own timer interrupt code (so it won't free you from having to loop continously anyway).
It's generally much easier to just PULSEOUT and then LOOP continously, rather than deal with complicated interrupt code, so that's probably your best approach to get a servo under quick control in a simple application.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Take a look at www.merlotti.com/EngHome/Computing/servo_controller.pdf. He gives a detailed discussion of interfacing a servo to a PIC, including pseudo code. Also, look at www.rentron.com, their project page. There is one design using a Pic 12F series with serial communication. The code is written in Pic Basic.
Richard
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
That looks like a valid message. The desired PMW is invalid.
As I do not know your code, I am assuming the code shown below , but, my guess is that have a clock frequency of greater that 1. The PWM frquency cannot be calculated with a register value of less than 255.
#chip PIC12F683,0.5
#define PWM_Freq 0.05
I you know a method of where we could support these lower frequencies at higher clock speeds then please do share. We can look at integrating.
Also, I could update the library to issue this message.
Error: Invalid PWM Frequency value: Lower chip frequency or increase PWM frequency. Trying to set a byte register to the value of 312
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I am attempting to control a servo, but in all of the online documentation regarding servo control it says that I should use a 50 Hz PWM signal. AFAIK the lowest I can get using GCBASIC is 1 kHz. How would one go about sending a 50 hz pwm signal to a servo? I would prefer not to use a software version since I need to check inputs and do some other processing at the same time.
The servo only looks at the ON TIME of the pulse, with the control range running between 1ms and 2ms. A 1ms ON TIME pulse is at one end of the servos travel range and a 2ms ON TIME pulse moves it to the other end (a 1.5ms positive pulse will center the servo).
The OFF TIME is not really all that critical so for simple basic programs it's probably simpler to just send a command like:
PULSEOUT PORTB.0, position 10us
So this is really pretty simple - if you have a number between 0 and 100 (think of it as percentage of rotation) you can simple add 100 to move the baseline up, so the range of the 'position' value used in the PULSEOUT command is between 100 and 200 (which is 1ms to 2ms with the 'time unit' parameter set to '10us').
So we just make sure 'position' is in the range of 100 to 200, then after sending the PULSEOUT we wait long enough (with code processing delay of the rest of the loop and an explicit 'WAIT' command) to fill out a 10ms to 20ms delay period, then LOOP to send the PULSEOUT command above again. Note you should loop and resend the 'position' at least every 20ms even if the position doesn't change. If you violate this rule and wait too long between positive position pulses, some servos will just freeze at their current position, which isn't too bad, but others will go to Min, Max or Center positon.
For some of the more advanced PICS, you can indeed setup the hardware PWM to drive your servo using about a 50Hz to 100Hz PWM frequency with the dutycycle range limited to the appropriate values to give the proper 1ms to 2ms ON TIME. For example with a 100Hz PWM frequency the PWM cycle will repeat every 10ms, so to get a 1ms pulse ON TIME we have to set the dutycycle to a narrow 10% setting and to get a 2ms ON TIME pulse we shift the duty cycle up to 20%. Using only this limited range will limit the positional resolution of the servo, but fortunatly the hardware PWM in the most of the advanced PICS like the 16F877 has 10 bit resolution, so even if we are using only the bottom end of the resolution range, it doesn't hurt too much.
The main advantage of the HARDWARE PWM approach is that it runs continously in hardware, freeing the program from having to loop continously at about 10ms to 50ms intervals, but the low end PICS don't have HARDWARE PWM so we are limited to SOFTWARE PWM.
For these low-end PICS, I think the above simple PULSEOUT and LOOP technique is better than trying to use the SOFTWARE PWM, because GCBasic limits the SOFTWARE PWM resolution to 8 bits, and doesn't yet seem to have a way to keep this software PWM running continously in the background while other code is executing unless you write your own timer interrupt code (so it won't free you from having to loop continously anyway).
It's generally much easier to just PULSEOUT and then LOOP continously, rather than deal with complicated interrupt code, so that's probably your best approach to get a servo under quick control in a simple application.
Thanks for the info, using the pulseout with an estimated wait command is alot easier than trying to make the waveform precisely 50hz.
Take a look at www.merlotti.com/EngHome/Computing/servo_controller.pdf. He gives a detailed discussion of interfacing a servo to a PIC, including pseudo code. Also, look at www.rentron.com, their project page. There is one design using a Pic 12F series with serial communication. The code is written in Pic Basic.
Richard
Thanks, that will be really helpful, it seems that there are alot of good ways to do it depending on what fits your application the best.
And finally, is there any solution to have 50Hz with CCP1? for 500Hz I found that this worked!
define PWM_Freq 0.5
but not this
define PWM_Freq 0.05
for 50Hz
Do you get an error message?
What is the simple code you are using?
Last edit: Anobium 2019-09-02
no error for the first (0.5) but for the second (0.05) it stops compile with the message "Error: Invalid PWM Frequency value"
That looks like a valid message. The desired PMW is invalid.
As I do not know your code, I am assuming the code shown below , but, my guess is that have a clock frequency of greater that 1. The PWM frquency cannot be calculated with a register value of less than 255.
I you know a method of where we could support these lower frequencies at higher clock speeds then please do share. We can look at integrating.
Also, I could update the library to issue this message.
Error: Invalid PWM Frequency value: Lower chip frequency or increase PWM frequency. Trying to set a byte register to the value of 312
hmm...I have no serious code until now...just only experimenting. Anyway if I have any news I will share....
Last edit: sfyris 2019-09-04