R/C decoder or BlueTooth game controller?

Discuss development of drivers for external hardware and components, such as LCD screens, sensors, motor drivers, etc.
Target audience: Users and developers of drivers.
User avatar
dbc
Posts: 89
Joined: Fri Aug 28, 2015 11:02 pm
Location: Sunnyvale, CA

R/C decoder or BlueTooth game controller?

Post by dbc » Tue Sep 20, 2016 4:07 pm

Has anyone written a library to decode the pulse train from a standard R/C receiver? I want to set up some kind of simple tele-operation interface for a mostly-autonomous robot. So a simple solution would be to decode the pulse train from an R/C receiver. Ideally, picking up the signal before it is demultiplexed into servo commands. Another option would be enough Bluetooth to deal with a PS/3 game controller or Wii controller, but I'm pretty sure neither of these are Bluetooth SPP, so the simple Bluetooth add-on boards aren't going to help much.

User avatar
deshipu
Posts: 1388
Joined: Thu May 28, 2015 5:54 pm

Re: R/C decoder or BlueTooth game controller?

Post by deshipu » Tue Sep 20, 2016 4:32 pm

I know of no such library in MicroPython, but it would surely be fun to write one using the information from http://www.sbprojects.com/knowledge/ir/index.php

User avatar
dhylands
Posts: 3821
Joined: Mon Jan 06, 2014 6:08 pm
Location: Peachland, BC, Canada
Contact:

Re: R/C decoder or BlueTooth game controller?

Post by dhylands » Tue Sep 20, 2016 4:59 pm

I've used the Input Capture module to measure the width of a pulse from a single channel.
https://github.com/dhylands/upy-example ... ic_test.py

I've done the RC decoding thing in C on an AVR.
https://github.com/dhylands/robostix/bl ... /RCInput.c
https://github.com/dhylands/robostix/bl ... /RC-Test.c

For parsing the combined stream (where one signal contains all of the channels), I think you could easily do it using input capture just on rising edges and use that to determine the pulse widths.

User avatar
deshipu
Posts: 1388
Joined: Thu May 28, 2015 5:54 pm

Re: R/C decoder or BlueTooth game controller?

Post by deshipu » Tue Sep 20, 2016 5:14 pm

Come to think of it, if you have room for a bluetooth board, you might as well fit a Pro Mini board there, with an IR receiver and a library like https://github.com/NicoHood/IRLremote, sending the decoded commands to your board with I2C and an interrupt pin, or something similar.

User avatar
dbc
Posts: 89
Joined: Fri Aug 28, 2015 11:02 pm
Location: Sunnyvale, CA

Re: R/C decoder or BlueTooth game controller?

Post by dbc » Tue Sep 20, 2016 5:22 pm

Thanks for the reference code. There is no doubt an Arduino library, too, if I went googling for it.

So I guess since the IC timer callback runs at interrupt priority it should give reasonably accurate timings. 4 uSec accuracy would be 1 bit in an 8 bit int, if memory serves. (1mSec / 250) I was imagining that it would require a C extension, but it is probably doable as pure Python.

@dhylands I can easily try out your Python code with a live servo, so that is the next step, I think.

User avatar
dhylands
Posts: 3821
Joined: Mon Jan 06, 2014 6:08 pm
Location: Peachland, BC, Canada
Contact:

Re: R/C decoder or BlueTooth game controller?

Post by dhylands » Tue Sep 20, 2016 7:01 pm

Yeah input capture will capture at the resolution of the timer being run. So in the examples I posted, I was running the timer at 1 MHz, so you get 1 usec resolution.

Since the RC pulses are typically 1-2msec long, the edges are far enough apart that you can deal with them in python. Even if the python is delayed by 100 usec, the timer will still have captured the timer counter back when the edge actually occurred.

I did a logic analyzer capture of the ic_test.py signals that shows the servo signal and the debug signal:
https://github.com/dhylands/upy-example ... c_test.png

User avatar
dbc
Posts: 89
Joined: Fri Aug 28, 2015 11:02 pm
Location: Sunnyvale, CA

Re: R/C decoder or BlueTooth game controller?

Post by dbc » Tue Sep 27, 2016 9:09 pm

So an R/C PPM decoder was actually quick and easy to get going. I'm using a Spektrum AR7700 receiver which has direct PPM out, but on many if not most R/C receivers it is easy to find the PPM signal and bring it out. I tested this code with a cheap 5 channel transmitter. (And by tested, I mean after 10 minutes of playing around randomly, it seems to work...YMMV)

The module:

Code: Select all

from array import array
import pyb

THROTTLE = 0
RUDDER = 1
ELEVATOR = 2
AILERON = 3
GEAR = 4

SYNC_MIN = 3000 #  3 mSec or more indicates next pulse is sync
_prev_t = 0
_next_ch = 0

def init_ppm_decode(timer_num, timer_channel_num, pin, num_rc_channels=8):
    global _num_channels
    global channel
    global _in_comp_channel
    _num_channels = num_rc_channels 
    channel = array('L', [0] * (_num_channels + 1))
    timer = pyb.Timer(timer_num, prescaler=83, period=0x0fffffff)
    _in_comp_channel = timer.channel(timer_channel_num, pin=pin,
        polarity=pyb.Timer.RISING, mode=pyb.Timer.IC)
    _in_comp_channel.callback(_ppm_callback)
    
def _ppm_callback(tim):
    global channel
    global _next_ch
    global _prev_t
    t = _in_comp_channel.capture()
    delta = t - _prev_t
    _prev_t = t
    if delta > SYNC_MIN:
        _next_ch = 0
    else:
        channel[_next_ch] = delta
        _next_ch = _next_ch + 1 if _next_ch < _num_channels else _next_ch

if __name__ == '__main__':
    pass
A simple test:

Code: Select all

import micropython
import pyb
import ppmdecoder as ppm

micropython.alloc_emergency_exception_buf(100)

ppm_input_pin = pyb.Pin('X1', pyb.Pin.IN)
ppm.init_ppm_decode(timer_num=2, timer_channel_num=1, pin=ppm_input_pin)

for i in range(80):
    print (ppm.channel[ppm.THROTTLE], ppm.channel[ppm.RUDDER], 
        ppm.channel[ppm.ELEVATOR], ppm.channel[ppm.AILERON],
        ppm.channel[ppm.GEAR])
    pyb.delay(1000)
The intent of having one more element in the channel array than there are R/C channels is so that if for some reason it misses a sync pulse or otherwise runs off the end, the last bucket can catch all the noise where it is easy to ignore.

User avatar
kfricke
Posts: 342
Joined: Mon May 05, 2014 9:13 am
Location: Germany

Re: R/C decoder or BlueTooth game controller?

Post by kfricke » Tue Sep 27, 2016 10:20 pm

Sorry for my possibly dumb question, but does this mean you can use any or most cheap R/C toy remote control receiver or are only the sophisticated hobby R/C links using that protocol?

User avatar
dbc
Posts: 89
Joined: Fri Aug 28, 2015 11:02 pm
Location: Sunnyvale, CA

Re: R/C decoder or BlueTooth game controller?

Post by dbc » Tue Sep 27, 2016 11:10 pm

Well, the really super-cheap R/C units for low-end toys don't have proportional control. But if the receiver has outputs for driving a standard R/C servo, it is likely to have a PPM signal inside it even if it isn't brought out.

Way back in the 1960's when proportional, multi-channel R/C was created, they did what was simple to do with the parts available. The standard architecture is to feed the pulses coming out of the radio detector to the clock input of an 8-bit shift register. If you contrive to load a '1' into the shift register at the start (and only at the start) of every frame, and shift that '1' on every received pulse, then the 8 outputs of the shift register can directly drive the 8 servos. So if you crack open an R/C receiver and see a shift register chip, the clock pin will have the PPM signal on it. The PPM signal usually also goes to the trigger of a one-shot that generates the '1' on start-of-frame.

Now that everyone is goofy for multi-rotor drones, receivers with direct PPM output are more common. If you check out the usual sources of cheap R/C gear you can find some.

User avatar
dhylands
Posts: 3821
Joined: Mon Jan 06, 2014 6:08 pm
Location: Peachland, BC, Canada
Contact:

Re: R/C decoder or BlueTooth game controller?

Post by dhylands » Tue Sep 27, 2016 11:24 pm

I hacked a 2 channel R/C receiver to get at the PPM signal. A typical implementation is that the PPM signal is used as a clock to a shift register and you shift a 1 through the shift register. Each bit of the shift register is used for one channel of control going to an RC Servo.

The VEX receiver directly outputs a PPM signal. It looks like you can get one on eBay for about $35 US. This is a six channel system.
http://www.vexrobotics.com/75mhz.html

Post Reply