![](templates/subSilver/images/CCSLogo.jpg) |
![CCS C Software and Maintenance Offers](templates/subSilver/images/forumAd6.jpg) |
View previous topic :: View next topic |
Author |
Message |
BLL
Joined: 11 Nov 2006 Posts: 181 Location: Birmingham, UK
|
Using 12F1840 to control r/c servo |
Posted: Thu Feb 13, 2020 2:22 pm |
|
|
Hi
I want to control an r/c servo, using a 12F1840. I have looked at various code but none seems to fit the 1840 timers. Can anyone help me please?
Thanks
Brian |
|
![](templates/subSilver/images/spacer.gif) |
temtronic
Joined: 01 Jul 2010 Posts: 9177 Location: Greensville,Ontario
|
|
Posted: Thu Feb 13, 2020 3:44 pm |
|
|
Here's one... http://www.ccsinfo.com/forum/viewtopic.php?t=55278&highlight=servo
Found in the code library forum....
Try search 'rc servo' but be sure to click the AND button !
there are several , so be sure to see which will do what you want, or at least a good starting point.
You can get a 16C84 to drive 8 RS servos........
Last edited by temtronic on Fri Feb 14, 2020 11:31 am; edited 1 time in total |
|
![](templates/subSilver/images/spacer.gif) |
gjs_rsdi
Joined: 06 Feb 2006 Posts: 468 Location: Bali
|
|
Posted: Fri Feb 14, 2020 6:46 am |
|
|
Hi BLL
In the link posted by Temtronic I used PIC18F26K22.
In PIC12F1840 Timer0 is 8 bit, you can use timer1, is 16 bit.
Best wishes
Joe |
|
![](templates/subSilver/images/spacer.gif) |
BLL
Joined: 11 Nov 2006 Posts: 181 Location: Birmingham, UK
|
|
Posted: Sat Feb 15, 2020 5:37 am |
|
|
Hi, Thanks for the replies. All I want to do is control ONE servo, using a 12F1840. The PIC also needs to flash some LEDs, but that's all.
The PIC has 2 CCP channels, so can I generate the pulses that way?
All I need is a pulse width of about 800us and one of 1500us, switching between the two, according to an ADC value. (the application is to control a water rudder on a model sea plane. 2 bolts in the hull act as input to an ADC channel to sense when water is present or not and extends/retracts the rudder as required)
I am not up to speed on pulse generation.
Brian |
|
![](templates/subSilver/images/spacer.gif) |
gjs_rsdi
Joined: 06 Feb 2006 Posts: 468 Location: Bali
|
|
Posted: Sat Feb 15, 2020 8:40 pm |
|
|
Hi BLL
The answer to your question is yes, you can generate the pulses with the PWM.
You need to read the data sheet to understand how.
I used PWM but for much higher period and pulses than 20ms period and pulses of 800us and 1500us
From the data sheet of PIC12F1840:
Quote: | PWM period = [(PR2)+1]*4*Tosc*(TMR2 Prescale Value)
Tosc=1/Fosc
PR2 Value = 0 to 255
Prescaler: 1:1, 1:4, 1:16, 1:64
Postscaler: 1:1 to 1:16
Resolution = log[4(PR2+1)]/log(2) |
You should make the calculations and see if it is feasible.
Best wishes
Joe |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19378
|
|
Posted: Sat Feb 15, 2020 11:41 pm |
|
|
The PWM, is not a good choice for RC servo control.
Problem is that to go slow enough to handle the total 'frame'
time, you have to run off an extremly large divider, and with the only
10bit maximum PWM resolution, this gives poor resolution on the actual
pulse.
The CCP though which the original poster mentioned, can be used, and
gives good results. This handles the timings much better, since it supports
16bit resolution allowing longer times with lower prescalers.
What you do is use just one CCP. turn the signal 'on' and program the
CCP to the period required for the 'on' pulse. Set the CCP to turn the
signal 'off'. This then gived you a nice accurately controlled pulse.
I posted code using this here:
<http://www.ccsinfo.com/forum/viewtopic.php?t=50914&highlight=servo>
Here I use a timer to give the 'frame', and the CCP to generate the pulse.
This was with a 400Hz frame, but for most systems a slower frame
like 40Hz is more normally used. The pulse widths remain the same
though, so all that needs to change is the values for the timings, |
|
![](templates/subSilver/images/spacer.gif) |
BLL
Joined: 11 Nov 2006 Posts: 181 Location: Birmingham, UK
|
|
Posted: Sun Feb 16, 2020 4:52 am |
|
|
Hi Ttelmah
Thank you for your reply.
Am I on the right lines here?
12F1840, internal osc at 16MHz:
#FUSES INTRC_IO
#use delay(internal=16M)
setup_timer1(T1_INTERNAL | T1_DIV_BY_1);
I only need these 2 values:
For 830us pulse, CCP_1 = 830/0.25 us = 3320
For 1500 pulse, CCP_1 = 1500/0.25 us = 6000
CCP1 on pin RA2
output_high(PIN_A2);
Now, I'm stuck!
Brian |
|
![](templates/subSilver/images/spacer.gif) |
temtronic
Joined: 01 Jul 2010 Posts: 9177 Location: Greensville,Ontario
|
|
Posted: Sun Feb 16, 2020 8:17 am |
|
|
Hmm, one 'trick' use is to set the clock to 4MHz, since 4MHz/4 = 1MHz which equates to a 1us 'tick'. This helps my old brain figure out timing 'math'. Well, sometimes. That PIC can have the internal oscillator of 4MHz...that I did just check. |
|
![](templates/subSilver/images/spacer.gif) |
BLL
Joined: 11 Nov 2006 Posts: 181 Location: Birmingham, UK
|
|
Posted: Sun Feb 16, 2020 10:38 am |
|
|
Hi Temtronic
That's a good idea.
I understand (I think) that if timer1 is set to zeroand the CCP1 o/p pin is set high, and timer1 is enabled, it will count up and when its value = the CCP1 set value, the CCP1 interrupt will be fired. Then, the CCP1 olutput pin can be set to zero. Fine, that gives me the on pulse, but now I need the much longer off time (at 20ms frame rate, I would need 20ms - the on pulse time to elapse before setting the CCP1 o/p high and repeating the code to get the next on time). Now, since timer1 is the only 16 bit timer we have on the 1840, do I calculate how many times timer1 overflows and triggers its interrupt function and test for this in timer1's interrupt function? This is what is confusing me.
Brian |
|
![](templates/subSilver/images/spacer.gif) |
BLL
Joined: 11 Nov 2006 Posts: 181 Location: Birmingham, UK
|
|
Posted: Tue Feb 18, 2020 12:04 pm |
|
|
Hi all
A question on timer2. As the datasheet states, timer2 is fed by a prescaler, fed by Fosc/4. So for example, if I set the RC osc to 16MHz, then Fosc/4 = 4MHz or 1 pulse every o.25us. If I set the prescaler to 1:64 (timer2_div_by_64), then timer2 will increment every 64 * 0.25us = 16us. As it's an 8 bit timer, it will overflow at 255, so it will overflow after 16 * 255 us = 4080 us. timer2 has an overflow interrupt function, so this would be triggered every 4080ms.
However, timer2 also has a post scaler. What is not clear to me is if the post scaler is set to say 4, does the timer overflow function still get called every 4080us or every 4 * 4080 = 16320us?
If the former, how do I get an 19ms delay unless I drastically reduce Fosc?
Brian |
|
![](templates/subSilver/images/spacer.gif) |
temtronic
Joined: 01 Jul 2010 Posts: 9177 Location: Greensville,Ontario
|
|
Posted: Tue Feb 18, 2020 1:21 pm |
|
|
The timer interrupt flag is at the 'end' of the divider chain.
So a prescale /2 then /4 then postdiv /8
is /2 * /4 * /8 , so /64 overall
If Fosc is 4MHz (magic number)
Fosc/4 = 1MHz or 1us
1us in----> gives 64 us
Clear as mud, right ?
If it's too fast, then reduce Fosc, say to 1MHz, that'll give you 1/4 the speed or 4x the delay.
Code: | //Timer1
//Prescaler 1:1; TMR1 Preload = 45536; Actual Interrupt Time : 20 ms
//Place/Copy this part in declaration section
void InitTimer1(){
T1CON = 0x01;
TMR1IF_bit = 0;
TMR1H = 0xB1;
TMR1L = 0xE0;
TMR1IE_bit = 1;
INTCON = 0xC0;
}
void Interrupt(){
if (TMR1IF_bit){
TMR1IF_bit = 0;
TMR1H = 0xB1;
TMR1L = 0xE0;
//Enter your code here
}
} |
This is a 20ms Interrupt. 4MHz clock
I got this from Mikroelectronica....
It's a PIC timer calculator.
C:\Users\Public\Documents\Mikroelektronika\Timer Calculator\TimerCalculator.exe
If you go to Mikroelectronica's site, it should be there, if not, let me know I'll try to find it, again.... |
|
![](templates/subSilver/images/spacer.gif) |
BLL
Joined: 11 Nov 2006 Posts: 181 Location: Birmingham, UK
|
|
Posted: Tue Feb 18, 2020 2:01 pm |
|
|
Hi Thanks for the reply. So, using the figures I gave, I can get my 19ms delay, using a post scale value and tyimer2 overflow interrupt function?
I can then use CCP1/timer1 to give me the 832 or 1500 us on pulse width?
Brian |
|
![](templates/subSilver/images/spacer.gif) |
BLL
Joined: 11 Nov 2006 Posts: 181 Location: Birmingham, UK
|
|
Posted: Thu Feb 20, 2020 8:25 am |
|
|
Hi all
Having figured out how to get 20ms out of timer2 for the space, I have been trying to understand how to use CCP1 to get my 830 or 1500 us mark pulse. The datasheet says "Compare mode makes use of the 16-bit Timer1 resource. The 16-bit value of the CCPR1H:CCPR1L register pair is constantly compared against the 16-bit value of the TMR1H:TMR1L register pair.
OK, so how do I set CCPR1H:CCPR1L to get either 830us or 1500us? I see "set_pwm1_duty(int16 value);", but how do I translate my 2 values to per centages?
If I use set_timer1(T1_Internal), I presume that timer1 will increment at Fosc/4, since no prescaler value is set?
When using SETUP_CCPx(), which of the constants do I use? I guess "CCP_COMPARE_SET_ON_MATCH", but I haven't found any description of what each of these does!
After either 830 or 1500 us, will the CCP1 interrupt be fired?
Oh I wish I could see the wood for the trees!!
Thanks
Brian |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19378
|
|
Posted: Thu Feb 20, 2020 9:12 am |
|
|
20mSec, is a 'not needed' value.
In fact servos can be updated much faster. The link I gave was for a servo being updated at 2.5mSec.
The reason for the 20mSec number, is 'historical'. Original analog RC
transmitters, send a 'packet' every 20mSec, with the pulse for servo#1 first,
then one for the next servo, and so on. Typically 8 pulses one after the
other. The receiver looked for the slightly longer 'gap' at the end of this
frame, then routed the first pulse out to the first servo, second to the
second, and so on. Result each servo received one pulse every 20mSec.
However modern 'digital' radios no longer do this. Instead outputting the
servo pulses one after the other without pauses. This is the so called
'400Hz' servo standard, and basically all servos now support this.
So honestly much better to forget the 20mSec....
Did you look at the link I gave:
<http://www.ccsinfo.com/forum/viewtopic.php?t=50914&highlight=servo>
This uses timer 3 and the CCP to handle the pulse and period.
You'll need to tweak these two values:
#define PERCENT 312
#define PERIOD 31250
For your lower clock frequency (these are for 50Mhz), so
25, & 2500 for 4Mhz.
It includes a routine to set the period in 'percent'. |
|
![](templates/subSilver/images/spacer.gif) |
gjs_rsdi
Joined: 06 Feb 2006 Posts: 468 Location: Bali
|
|
Posted: Thu Feb 20, 2020 4:17 pm |
|
|
Hi Ttelmah
You are 100% right regarding the 20ms.
Long time ago I worked with a chip from Philips (forgot the name) that was generating 7 pulses from the serial input from the receiver.
After starting to work with PIC (assembler) the Philips chip was not necessary anymore.
From experience, increased the period to 40ms, the servo had significantly less holding power.
Decreased the period to 10ms, the servo holding power was much higher.
I will make some experiments with shorter time and more servo's.
Best wishes
Joe |
|
![](templates/subSilver/images/spacer.gif) |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|