View previous topic :: View next topic |
Author |
Message |
chris101
Joined: 01 Sep 2005 Posts: 46
|
Posted: Sun Jul 10, 2011 2:18 pm Post subject: Reading the output of an RC receiver (radio control) |
|
|
Hi All.
What is the BEST and FASTEST way to read the pulse length of 5 channels of an model RC receiver ?
Does anybody have some sample code, that they can share?. _________________ Best Regards from.
Christian |
|
Back to top |
|
|
cucuruzel
Joined: 18 Mar 2010 Posts: 53 Location: Cluj-Napoca
|
Posted: Sun Jul 10, 2011 5:49 pm Post subject: |
|
|
The way I would do it is use pin change interrupts, and a timer
pseudo-code:
Configure timer for needed resolution
configure pin change interrupts
dim pulse_lengths(5) as word?
dim initial_times(5) as word?
Isr:
pins_changed = old_states XOR new_states 'detecht what pins have changed
old_states = new_state 'save new pin state for later checks
For each pin in pins_changed 'a loop for each pin changed
pulse_length(pin) = Timer_now - initial_times(pin) 'time difference between changes
initial_times(pin) = timer_now
next
return
Maybe there is need to add checks for logic level ...so that measurement is done only for high level |
|
Back to top |
|
|
Tubeampman
Joined: 27 Feb 2006 Posts: 100 Location: Bodo
|
Posted: Sun Jul 10, 2011 7:39 pm Post subject: |
|
|
hi
Take a look at this site.
If you look at the end of the sourcecode i think you find what you looking for.
http://shrediquette.blogspot.com/
If you take a look at the aplications ant tricopter you will fin it also.
Fixmann |
|
Back to top |
|
|
s_sergiu
Joined: 25 Sep 2006 Posts: 81
|
Posted: Wed Jul 13, 2011 1:40 pm Post subject: |
|
|
Hi,
Very simple and VERY fast with XMEGA.Below is portion from one auto-pilot source code for Quattro. All RC channels will read direct in ms (1000 to 2000). You can read up to 14 RC by modifying below code.
$regfile = "xm128a1def.dat"
'$crystal = 48000000
$crystal = 32000000
$hwstack = 512
$swstack = 512
$framesize = 512
$lib "xmega.lib"
'$lib "Long_trig.lbx"
'$lib "Long.lbx"
$external _xmegafix_clear
$external _xmegafix_rol_r1014
'Config Single = Scientific , Digits = 1
'*******************************************************************************
Rem 32Mhz clock
Config Osc = Disabled , Extosc = Enabled , Range = 12mhz_16mhz , Startup = Xtal_256clk
Cpu_ccp = &HD8
'Osc_pllctrl = &B11_0_00011 '48Mhz
Osc_pllctrl = &B11_0_00010 '32Mhz
Bitwait Osc_status.3 , Set
Set Osc_ctrl.4
Config Sysclock = Pll , Prescalea = 1 , Prescalebc = 1_1
'*******************************************************************************
Config Priority = Static , Vector = Application , Hi = Enabled
Enable Interrupts
'*******************************************************************************
Rem RC channels AILE ELEV THRO RUDD GEAR AUX
Config Porte.0 = Input : Config Porte.1 = Input
Config Porte.2 = Input : Config Porte.3 = Input
Config Porte.4 = Input : Config Porte.5 = Input
'******************************************************************************
Rem R/C Input
Dim Temp1_rc As Word , Temp2_rc As Word , Temp3_rc As Word , Temp4_rc As Word
Dim Temp5_rc As Word , Temp6_rc As Word , Kca As Bit , Kcb As Bit
Dim Kc1a As Bit , Kc1b As Bit , Kcc As Bit , Kcd As Bit
Dim Aile As Integer , Elev As Integer , Rudd As Integer , Thro As Word
Dim Aux As Integer , Gear As Integer , Thro1 As Integer , Thro2 As Single
Dim Rc_inp_tmp As Integer , Gain_servo As Single , Ofs_servo As Single
'********************
Declare Sub Rc_inp()
'********************
Porte_pin0ctrl = &H00
Porte_pin1ctrl = &H00
Porte_pin2ctrl = &H00
Porte_pin3ctrl = &H00
Porte_pin4ctrl = &H00
Porte_pin5ctrl = &H00
'********************
Tce0_per = 32767
Tce1_per = 32767
'********************
'clk/8 , 32M/8=4MHz (.25us per tick)
Tce0_ctrla = &B0000_0100
Tce1_ctrla = &B0000_0100
'********************
Tce0_ctrlb = &B1111_0000
Tce1_ctrlb = &B1111_0000
'*******************
Tce0_ctrld = &B1100_1000
Tce1_ctrld = &B1100_1100
'*******************
Evsys_ch0mux = &B0111_0000
Evsys_ch1mux = &B0111_0001
Evsys_ch2mux = &B0111_0010
Evsys_ch3mux = &B0111_0011
Evsys_ch4mux = &B0111_0100
Evsys_ch5mux = &B0111_0101
Evsys_ch6mux = &B0111_0110
Evsys_ch7mux = &B0111_0111
'*******************
' read to clear interrupt
Temp1_rc = Tce0_cca
Temp2_rc = Tce0_ccb
Temp3_rc = Tce0_ccc
Temp4_rc = Tce0_ccd
Temp5_rc = Tce1_cca
Temp6_rc = Tce1_ccb
'**********************************
Enable Tce0_cca , Hi
On Tce0_cca Capte0_a
Enable Tce0_ccb , Hi
On Tce0_ccb Capte0_b
Enable Tce0_ccc , Hi
On Tce0_ccc Capte0_c
Enable Tce0_ccd , Hi
On Tce0_ccd Capte0_d
Enable Tce1_cca , Hi
On Tce1_cca Capte1_a
Enable Tce1_ccb , Hi
On Tce1_ccb Capte1_b
'**********************************
Rem RC Servo Travel Settings
Const Fsc_servo = 3000
Const Zero_servo = 1500
Const Rc_inp_min = 4430
Const Rc_inp_max = 7720
Rc_inp_tmp = Rc_inp_max - Rc_inp_min
Gain_servo = Fsc_servo - Zero_servo
Gain_servo = Gain_servo / Rc_inp_tmp
Ofs_servo = Rc_inp_min * Gain_servo
Ofs_servo = Zero_servo - Ofs_servo
'*******************************************************************************
Do
Rc_inp
Loop
'********************************************************************************
'*******************************************************************************
Capte0_a:
Temp1_rc = Tce0_cca
Kca = 1
Return
'*****************
Capte0_b:
Temp2_rc = Tce0_ccb
Kcb = 1
Return
'*****************
Capte0_c:
Temp3_rc = Tce0_ccc
Kcc = 1
Return
'****************
Capte0_d:
Temp4_rc = Tce0_ccd
Kcd = 1
Return
'****************
Capte1_a:
Temp5_rc = Tce1_cca
Kc1a = 1
Return
'***************
Capte1_b:
Temp6_rc = Tce1_ccb
Kc1b = 1
Return
'*******************************************************************************
Sub Rc_inp()
If Kca = 1 Then
Aile = Temp1_rc / 4
Aile = Aile - 1520
Aile = Aile / 4
Kca = 0
End If
'***************
If Kcb = 1 Then
Elev = Temp2_rc / 4
Elev = Elev - 1520
Elev = Elev / 4
Kcb = 0
End If
'***************
If Kcc = 1 Then
Thro1 = Temp3_rc
Kcc = 0
Thro2 = Thro1 * Gain_servo
Thro2 = Thro2 + Ofs_servo
Thro = Thro2
End If
'***************
If Kcd = 1 Then
Rudd = Temp4_rc / 4
Rudd = Rudd - 1520
Rudd = Rudd / 4
Kcd = 0
End If
'***************
If Kc1a = 1 Then
Gear = Temp5_rc / 40
Gear = Gear - 100
If Gear <= 0 Then Gear = 0
If Gear >= 100 Then Gear = 100
Kc1a = 0
End If
'***************
If Kc1b = 1 Then
Aux = Temp6_rc / 40
Aux = Aux - 100
If Aux <= 0 Then Aux = 0
If Aux >= 100 Then Aux = 100
Kc1b = 0
End If
End Sub
'******************************************************************************* |
|
Back to top |
|
|
Kiedro
Joined: 08 Mar 2006 Posts: 81
|
Posted: Wed Jul 13, 2011 5:29 pm Post subject: |
|
|
Nice, Sergiu - thanks for sharing!
To Chris101: This is the most general solution which works with all receivers. Depending how the servo pulses are generated by the receiver (one after the other, or groupwise generation, or simultaneously), the latency for a 5 channel setup may be up to 10 ms (or even more) in the worst case (= one after the other), or 2ms in the best. For Spektrum-based systems one may consider to listen to the serial communication from one (or more) satellite receivers instead. Reading and analyzing such a serial frame is a matter of about 2ms for 8 channels. One may apply mixing and do other "intelligent stuff" usually done in the radio and enjoy very synchrone servo response (see AN#171 Ar7212 forum for details). So the question about the best and fastest way to read servo signals really depends on your setup. Some radio brands "shoot" for 2 ms and keep quiet for the rest of the time (20ms), others still send kind of ppm pulse trains in 2.4 GHz times. |
|
Back to top |
|
|
|
|
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 You cannot attach files in this forum You cannot download files in this forum
|
|