Shop OBEX P1 Docs P2 Docs Learn Events
Reading PWM data from RC Radio — Parallax Forums

Reading PWM data from RC Radio

sreid55sreid55 Posts: 3
edited 2008-02-21 18:29 in Propeller 1
Hi all -
I'm trying to read four PWM values from an R/C radio reciever, and I've come up with the code below adapted from the BS2_functions.spin PULSIN code.· It generally works, but the data I get from it is rather jittery.· Also, rapid changes in one channel will erroneously impact the results of another channel.· I've ruled out errors in the RC hardware; servos connected to the channels are stable and clean.
Any ideas?
Thanks
Scott
{
                          ********************************************
                              READSERVO - Read R/C PCM Input Pulses
                          ********************************************
}
CON
  PINROLL = 3
  PINPITCH = 4
  PINTHR = 5
  PINYAW = 6
  PINMASKROLL =  %00001000 
  PINMASKPITCH = %00010000 
  PINMASKTHR =   %00100000 
  PINMASKYAW =   %01000000
VAR
  long stack[noparse][[/noparse]26]
  word roll,pitch,thr,yaw
PUB start
  dira[noparse][[/noparse]PINROLL]~
  dira[noparse][[/noparse]PINPITCH]~
  dira[noparse][[/noparse]PINTHR]~
  dira[noparse][[/noparse]PINYAW]~
  cognew(rsmonitor,@stack)
                 
PUB readservo(channel) | i
  {{ readservo(channel):
      1 = roll
      2 = pitch
      3 = throttle
      4 = yaw
  }}
 
  if channel==1
    i := roll
  elseif channel==2
    i := pitch 
  elseif channel==3
    i := thr
  else
    i := yaw
  return i

 
PRI rsmonitor '' constantly poll input channels from RC radio and update variables
  repeat
  
    ctra := 0
    ctra := (%10100 << 26 ) | (%001 << 23) | (0 << 9) | (PINTHR)  
    frqa := 1
    waitpne(0,PINMASKTHR,0)
    phsa := 0
    waitpeq(0,PINMASKTHR,0)
    waitpne(0,PINMASKTHR,0)
    thr := (phsa ~> 8)  ' divide to get result in desired range
    ctra := 0
    ctra := (%10100 << 26 ) | (%001 << 23) | (0 << 9) | (PINROLL)  
    frqa := 1
    waitpne(0,PINMASKROLL,0)
    phsa := 0
    waitpeq(0,PINMASKROLL,0)
    waitpne(0,PINMASKROLL,0)
    roll := (phsa ~> 8)                                                                                                                                                                                                                  
    ctra := 0
    ctra := (%10100 << 26 ) | (%001 << 23) | (0 << 9) | (PINPITCH)  
    frqa := 1
    waitpne(0,PINMASKPITCH,0)
    phsa := 0
    waitpeq(0,PINMASKPITCH,0)
    waitpne(0,PINMASKPITCH,0)
    pitch := (phsa ~> 8)
    ctra := 0
    ctra := (%10100 << 26 ) | (%001 << 23) | (0 << 9) | (PINYAW)  
    frqa := 1
    waitpne(0,PINMASKYAW,0)
    phsa := 0
    waitpeq(0,PINMASKYAW,0)
    waitpne(0,PINMASKYAW,0)
    yaw := (phsa ~> 8)                                                                                                                                                                                                                  
 
    
  
  

Comments

  • stevenmess2004stevenmess2004 Posts: 1,102
    edited 2008-02-16 05:06
    How much jitter are you getting? I would hazard a guess that you should be using counter mode %01000 'POS detector' and not mode %10100 'Logic !A&B' I would assume that pin 0 is floating and this is what would be giving you the jitter. Also, it may be a better idea to clear phsa after the waitpeq but I'm happy to be corrected.
  • Shane De CataniaShane De Catania Posts: 67
    edited 2008-02-16 08:16
    G'day Scott,
    This was posted some time ago... it may help.
    Cheers,
    Shane.
  • deSilvadeSilva Posts: 2,967
    edited 2008-02-16 08:41
    Steven has it nearly right! What you need is the NEG detection mode = %01100.

    The structure of your algorithm indicates that you use negative logic;
    if otherwise you have to invert the waits and use POS detection mode.

    And don't set the PLL, it has no effect, but is confusing.
    Your code looks much different than I would code, but that is a feature, not a bug smile.gif

    Edit/BTW: A pulse of 1 to 2 ms will have 160,000 counts, divided by 256 gives you an result of 320 to 640. Is that what yopu want?

    @Shane: It's a different program you quote, reading the "raw" RC data, where all (eight) channels are still interleaved.

    Post Edited (deSilva) : 2/16/2008 9:09:09 AM GMT
  • deSilvadeSilva Posts: 2,967
    edited 2008-02-16 09:00
    Example, not tested:
    ' Now version 2!
    CON
      PINROLL = 3
      PINPITCH = 4
      PINTHR = 5
      PINYAW = 6
    
    DAT
      stack    LONG  0[noparse][[/noparse] 26 ]
      results  WORD 0[noparse][[/noparse] 5 ]
    
    PUB start
      cognew(rsmonitor, @stack)
                    
    PUB readservo(channel) | i
      {{ readservo(channel):
          1 = roll
          2 = pitch
          3 = throttle
          4 = yaw
      }}
      return results[noparse][[/noparse]channel]
    
     
    PRI rsmonitor |logPin, truePin, pinMask
     '' constantly poll input channels from RC radio and update variables
     '' using negative logic, i.e. pulse is low
     REPEAT
    
      REPEAT logPin FROM 1 TO 4
        truePin := LOOKUP(logPin:  PINROLL, PINPITCH, PINTHR, PINYAW)
        pinMask := |<l truePin
    
        ctra := (%01100 << 26 ) | truePin
        frqa := 1 
        waitpne(0,PINMASK,0)
        phsa := 0
        waitpeq(0,PINMAS,0)
        waitpne(0,PINMASK,0)
    
        results[noparse][[/noparse]logPin] := (phsa >> 8)
    

    Post Edited (deSilva) : 2/16/2008 9:38:07 AM GMT
  • stevenmess2004stevenmess2004 Posts: 1,102
    edited 2008-02-16 09:11
    deSilva, I believe that you should have made results an array instead of a single variable smile.gif Also it may be better to make logPin go from 0 to 3 to make it fit in the array smile.gif
  • deSilvadeSilva Posts: 2,967
    edited 2008-02-16 09:29
    If you had taken a very close look you would have spotted this line
    results  WORD 0[noparse][[/noparse] 5 ]
    


    scrambled by the forum software :-(

    But thank you for the hint!

    And 0..3 rather than 1..4
    I grew up with FORTRAN, where we started things with "One" and still try to avoid this superoptimal C-thinking.
    I just WASTE the first word of RESULTS smile.gif

    Nevertheless there was a real bug in it (|<logPin rather than |<truePin)

    Post Edited (deSilva) : 2/16/2008 9:39:27 AM GMT
  • sreid55sreid55 Posts: 3
    edited 2008-02-16 15:02
    Thanks guys! - I got it working with a few of your suggestions; I think I'm going to go with the library that Shane reposted.
    Scott
  • deSilvadeSilva Posts: 2,967
    edited 2008-02-16 15:07
    That is always a good idea. When using libraries one need not understand to precisely what's going on smile.gif
  • rjo_rjo_ Posts: 1,825
    edited 2008-02-17 04:57
    deSilva,

    I could differ with you slightly but who would care? BUT

    Integration is more fun than perspiration[noparse]:)[/noparse] AND

    At the top level, the Prop is all about object integration, no need to feel a slight when you use the platform the way it was intended[noparse]:)[/noparse]

    Rich
  • deSilvadeSilva Posts: 2,967
    edited 2008-02-17 10:04
    @Rich: A very wise remark! Re-Use (as abstraction, which is something very similar)
    is the root of successful software engineering. This is not only a belief of SWE managers
    but seems to be really true smile.gif

    Due to the memory restrictions true module re-use was not too popular among microcontroller
    developers, at most they recycled their source code, and especially the algorithmically more demanding
    pieces (square root, filters, floating point as a whole,..) You see it expands.... The current development
    going from 128 kB to 256 kB in micro controller program memory has its root mainly in more advanced
    HLL "re-use thinking". But this is around 10 times the program memory we have available in the Prop....
  • stevenmess2004stevenmess2004 Posts: 1,102
    edited 2008-02-17 10:07
    But we will soon have the PropII which will be in exactly that range smile.gif. It will be interesting how to class the PropII. Heaps more power than most other microcontrollers but not enough to class it as much else.
  • deSilvadeSilva Posts: 2,967
    edited 2008-02-17 10:24
    This now becomes VERY OT, but a last remark from my side:
    So much depends on market exceptance! For years the host of MC developers AND their managers
    refused to even think of using a 32 bit processor despite the obvious advantages even for smaller
    projects. Reasons they gave were mostly pretext to hide their basic conservative adjustment.
    Unbeatable however was always the recurrent cost argument...

    ARM producing companies now have earned enough money they could start very aggressive
    marketing campaigns, selling ARM7 variants around $1. This can change the mind setting..

    Note however that ARM7 is a nearly out-dated concept with many weaknesses which are addressed
    by a newer technology. However basically a COG is quite similar to an ARM7 chip.
  • JasonEJasonE Posts: 16
    edited 2008-02-19 14:24
    sreid55,

    · I have attached some code that I believe does exactly what you want.· It's a derivative of the code that shane posted.· It's not very elegent (it's my first foray into assembly) but should work for you.· When channels slip (due to a missed pulse edge), it resorts·the data·such that your channels do not get re-ordered. (It would be very bad if mid-flight your elevator and rudder signals were switched!!!)

    ·I use this to read my 3 channel reciever (propeller-motor speed, elevator, and rudder),·modulate on one·wire connected·to pin 5 of my Propeller chip with good success.

    ·Please let me know if you have any questions.

    -JasonE
  • sreid55sreid55 Posts: 3
    edited 2008-02-19 21:22
    Jason - Thanks for the code -- Where are you getting an output with three channels modulated on one wire?
    I can't say that I've ever seen that. I have a regular Futaba 7 channel receiver with 7 outputs, four are connected to four propeller pins
    Scott
  • JasonEJasonE Posts: 16
    edited 2008-02-20 00:06
    Scott,

    I'm using a fairly low-end receiver/transmitter - it's what came with my HobbyZone supercub. The signal I'm describing is the actual (raw) signal that gets modulated to the carrier frequency. Somewhere on your reciever it decodes the pulse train and breaks out the channels to different ports for you. I probed around with my usb-oscilloscope until I found a signal I could decipher. I had to do this because the supercub uses 5-wire servos instead of the standard 3-wire servos. The control signal from a 5-wire servo can not be easily interpreted, as the 5 wire servo is part of a feedback loop with the receiver.
  • J.A.B.J.A.B. Posts: 13
    edited 2008-02-20 13:53
    The raw servo signal stream is called PPM. A great thing about reading the raw stream is that you can read 8 channels (PPM is always 8 channels) from receivers that have for example only 3 or 4 channel outputs.
  • JasonEJasonE Posts: 16
    edited 2008-02-20 14:03
    JAB,

    If I want to increase the functionality of my transmitter and use some of the (currently) untapped channels, how could I go about that? Can you point me towards any good websites or reference information?

    Thanks,

    Jason
  • J.A.B.J.A.B. Posts: 13
    edited 2008-02-20 18:34
    http://www.mp.ttu.ee/risto/rc/electronics/radio/signal.htm

    But you need a 8ch transmitter to be able to control all 8 channels. Transmitters with less then 8 ch. just send a blank signal on the unused channels in the ppm signal. I guess you might be able to hack more channels for some transmitters, but there is no sure method.

    Edit: I just remembered that you can use the trainer port on some transmitters to insert data for the missing channels. Don't remember which ones had the possibility, but some searching should give you an answer.

    Post Edited (J.A.B.) : 2/20/2008 6:44:28 PM GMT
  • Beau SchwabeBeau Schwabe Posts: 6,559
    edited 2008-02-21 03:42
    JasonE.

    "If I want to increase the functionality of my transmitter and use some of the (currently) untapped channels, how could I go about that?"

    If you have at least two channels that are not used, you can multiplex the channel functions by setting one Channel to a "specific" locations or value, and then using the remaining channel for your data.


    For example, You can create 4 Auxiliary Channels from 2 Channels if you take Ch1 and divide it so that it has 4 equal parts (250uS separation) ranging...
    1000us to 1250us ... 1125us Aux1
    1250us to 1500us ... 1375us Aux2
    1500us to 1750us ... 1625us Aux3
    1750us to 2000us ... 1875us Aux4
    ...and send your data on Ch2 so that it corresponds to the correct Aux position.

    Note:
    Sending data this way will require adjustments to the transmitter, and should be done at your own risk.
    I have successfully done this with a transmitter to add a 16-key keypad (one channel for rows, another channel for columns) similar to above.
    No software required on the transmitter, just weighted resistor values that created enough discrepancy on the receiver end to distinguish them.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Beau Schwabe

    IC Layout Engineer
    Parallax, Inc.
  • JasonEJasonE Posts: 16
    edited 2008-02-21 14:14
    Beau,

    Thank you for your input; I think I understand what you were trying to convey to me, but let me ask a slightly different question:

    Here is the pulse train my transmitter outputs: (p = hi pulse, d = low delay)

    ________________----___----___----___---________________----___----___----___---
    (reset) p0 d0 p1 d1 p2 d2 p3 (reset) p0 d0 p1 d1 p2 d2 p3

    where the data (channels 1,2, and 3) are described by length of the delays (d0, d1, d2, 1200us +/- 320us), currently all the hi-pulses are permanently fixed at 250us. I would think the easiest way to output more channels would be for me to change the length of the hi-pulses. Do you know of a way to intercept and change those pulses? I suppose that would require software and more integration work with the transmitter?

    Thanks,

    Jason
  • JasonEJasonE Posts: 16
    edited 2008-02-21 14:16
    Sorry the spacing was removed when I posted, the pulse train should read:

    ________________----___----___----___---________________----___----___----___---
    ....(reset)............. p0..d0..p1..d1..p2.d2.p3.....(reset).............p0..d0..p1..d1..p2.d2..p3
  • Beau SchwabeBeau Schwabe Posts: 6,559
    edited 2008-02-21 18:29
    JasonE.

    "I would think the easiest way to output more channels would be for me to change the length of the hi-pulses. Do you know of a way to intercept and change those pulses?" ... sorry not easily.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Beau Schwabe

    IC Layout Engineer
    Parallax, Inc.
Sign In or Register to comment.