CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

Using 12F1840 to control r/c servo
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
BLL



Joined: 11 Nov 2006
Posts: 181
Location: Birmingham, UK

View user's profile Send private message

Using 12F1840 to control r/c servo
PostPosted: Thu Feb 13, 2020 2:22 pm     Reply with quote

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
temtronic



Joined: 01 Jul 2010
Posts: 9081
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Thu Feb 13, 2020 3:44 pm     Reply with quote

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
gjs_rsdi



Joined: 06 Feb 2006
Posts: 468
Location: Bali

View user's profile Send private message Send e-mail

PostPosted: Fri Feb 14, 2020 6:46 am     Reply with quote

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
BLL



Joined: 11 Nov 2006
Posts: 181
Location: Birmingham, UK

View user's profile Send private message

PostPosted: Sat Feb 15, 2020 5:37 am     Reply with quote

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
gjs_rsdi



Joined: 06 Feb 2006
Posts: 468
Location: Bali

View user's profile Send private message Send e-mail

PostPosted: Sat Feb 15, 2020 8:40 pm     Reply with quote

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
Ttelmah



Joined: 11 Mar 2010
Posts: 19195

View user's profile Send private message

PostPosted: Sat Feb 15, 2020 11:41 pm     Reply with quote

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,
BLL



Joined: 11 Nov 2006
Posts: 181
Location: Birmingham, UK

View user's profile Send private message

PostPosted: Sun Feb 16, 2020 4:52 am     Reply with quote

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
temtronic



Joined: 01 Jul 2010
Posts: 9081
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Sun Feb 16, 2020 8:17 am     Reply with quote

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.
BLL



Joined: 11 Nov 2006
Posts: 181
Location: Birmingham, UK

View user's profile Send private message

PostPosted: Sun Feb 16, 2020 10:38 am     Reply with quote

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
BLL



Joined: 11 Nov 2006
Posts: 181
Location: Birmingham, UK

View user's profile Send private message

PostPosted: Tue Feb 18, 2020 12:04 pm     Reply with quote

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
temtronic



Joined: 01 Jul 2010
Posts: 9081
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Tue Feb 18, 2020 1:21 pm     Reply with quote

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....
BLL



Joined: 11 Nov 2006
Posts: 181
Location: Birmingham, UK

View user's profile Send private message

PostPosted: Tue Feb 18, 2020 2:01 pm     Reply with quote

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
BLL



Joined: 11 Nov 2006
Posts: 181
Location: Birmingham, UK

View user's profile Send private message

PostPosted: Thu Feb 20, 2020 8:25 am     Reply with quote

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
Ttelmah



Joined: 11 Mar 2010
Posts: 19195

View user's profile Send private message

PostPosted: Thu Feb 20, 2020 9:12 am     Reply with quote

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'.
gjs_rsdi



Joined: 06 Feb 2006
Posts: 468
Location: Bali

View user's profile Send private message Send e-mail

PostPosted: Thu Feb 20, 2020 4:17 pm     Reply with quote

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
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
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