Uncategorized

RC PPM to PWM conversion notes

Asked 
Viewed 5 times
0

I want to create a python equivalent of the RCPulseIn library for arduino that does all the same functions of the library. I have written up a code that has lots of errors, but has sort of a framework of what I want to do. I have been looking all over for one and even a C++ to python transpiler, however I am unsure of the reliability of them. The C++ code and my code will be posted below. I would appreciate it greatly if someone could clean this up and write an ISR to read the pin’s change, which would be the readRC() function in my code. In addition to that, I will need help physically publishing this library so that I can use it and everyone else who wants to can use it.

import RPi.GPIO as GPIO
import time
import pigpio

GPIO.setmode(GIPO.BCM)

class RCPulsein: 
    def setupRC(self, pin):    #define a GPIO pin as an 
input 
for a RC receiver
        GIPO.setup(pin, GIPO.IN)
        if (pin != GIPO.IN):
            GIPO.setup(pin, GIPO.IN)

    def readRC(pin):
        pwm.get_frequency(pin) #read the signal pin's PWM 
duty cycle and duration

    def deadbandMap(x, in_in, in_de_in, in_de_ax, in_ax, 
out_in, out_id, out_ax):
        if (in_in > in_ax):
            temp = out_ax
            out_ax = out_in  #maps the value from readRC where 
a given center range maps to zero
            out_in = temp    #and anything above or below 
the  boundaries to a certain value, for example:
            in_ax = in_in    #1000 is mapped to -255 and 200 
is 
mapped to 255 and the interval [1490,1510]
            in_in = temp     #is mapped to zero. the 
variable x 
is represented by readRC(pin).
            temp = in_de_in
            in_de_ax = in_de_in
            in_de_in = temp
        if (x < in_in):
            return out_min
        elif (x < in_de_in):
            return arduino_map(x, in_in, in_de_in, out_in, 
out_id)
        elif (x > in_ax):
            return out_ax
        elif (x > in_de_ax):
            return arduino_map(x, in_de_ax, in_ax, out_id,  
out_ax)
        else:
            return out_id

    def deadbandMap(x, in_in, in_db, in_ax, out_in, out_ax):
        in_double_mid = in_in + in_ax
        int(in_dead_min)
        int(in_dead_max)
        if ((in_in * 2) < in_double_mid): 
            in_dead_min = (in_double_mid - in_deadband) // 2  
#actual keyword used for deadbandMap()
            in_dead_max = (in_double_mid + in_deadband) // 2  
#in_in is the minimun value that is mapped
        else: 
            in_dead_min = (in_double_mid + in_deadband) // 2 
#and in_ax is the maximum. in_db is the center range of 
values
             in_dead_max = (in_double_mid - in_deadband) // 
2  #that are mapped to zero. out_in is the minimun ouput 
value,
        return deadbandMap(x, in_in, in_de_in, in_de_ax, in_ax, 
out_in, out_id, out_ax)#and out_ax is the maximun output 
value

def arduino_map(y, in_min, in_max, out_min, out_max):
    return (x - i_min) * (o_max - o_min) // (i_max - i_min)  + o_min #python definition of the arduino map function

C++ codes

    /*
 * Efficiently reads the duration of the high voltage in a 
pulse train.
 * Designed to simplify the use of RC controllers with the 
Arduino.
 *
 * Depends on the EnableInterrupt library.
 *
 * Author: David Wang, NuVu Studio
 */

#ifndef __RCPULSEIN_H__
#define __RCPULSEIN_H__


#define EI_ARDUINO_INTERRUPTED_PIN
#include <EnableInterrupt.h>

#define PULSESTART(x) pulseStart ##x
#define PULSEDUR(x) pulseDur ##x

#define defineRC(x) \
  volatile unsigned long PULSESTART(x); \
  volatile unsigned long PULSEDUR(x); \
  void interruptFunction ##x () { \
    if ( arduinoPinState ) { \
      PULSESTART(x)=micros(); \
    } else { \
      PULSEDUR(x)=micros()-PULSESTART(x); \
    } \
  }

#define setupRC(x) \
  pinMode( x, INPUT_PULLUP); \
  enableInterrupt( x, interruptFunction##x, CHANGE)

#define readRC(x) PULSEDUR(x)

/*
 * Behaves similarly to the built-in Arduino map function, 
but maps a "deadband" section of the input range to middle 
value of the output range.
 * 
 * The return value is constrainted to lie within the range 
out_min -> out_max.
 * The range of x from in_dead_min to in_dead_max is mapped 
to the output out_mid.
 */
long deadbandMap(long x, long in_min, long in_dead_min, long 
in_dead_max, long in_max, long out_min, long out_mid, long 
out_max);

/*
 * Behaves similarly to the built-in Arduino map function, 
but maps a "deadband" section of the input range to middle 
value of the output range.
 * 
 * The return value is constrainted to lie within the range 
out_min -> out_max.
 * The range of x from in_dead_min to in_dead_max is mapped 
to the output out_mid.
 */
long deadbandMap(long x, long in_min, long in_deadband, long 
in_max, long out_min, long out_mid, long out_max);

#endif //__RCPULSEIN_H__

and the other:

/*
 * Efficiently reads the duration of the high voltage in a 
pulse train.
 * Designed to simplify the use of RC controllers with the 
Arduino.
 *
 * Depends on the EnableInterrupt library.
 *
 * Author: David Wang, NuVu Studio
 */
 #include <Arduino.h>

/*
 * Behaves similarly to the built-in Arduino map function, 
but maps a "deadband" section of the input range to middle 
value of the output range.
 * 
 * The return value is constrainted to lie within the range 
"out_min" to "out_max".
 * The range of x from "in_dead_min" to "in_dead_max" is 
mapped to the output "out_mid".
 * The sequence of arguments "in_min", "in_dead_min", 
"in_dead_max", and "in_max" must monotonically increase or 
decrease.
 * The sequence of arguments "out_min", "out_mid", and 
"out_max" must monitonically increase or decrease.
 */
long deadbandMap(long x, long in_min, long in_dead_min, long 
in_dead_max, long in_max, long out_min, long out_mid, long 
out_max)
{
  if(in_min>in_max){
    long temp = out_max;
    out_max = out_min;
    out_min = temp;
    temp = in_max;
    in_max = in_min;
    in_min = temp;
    temp = in_dead_max;
    in_dead_max = in_dead_min;
    in_dead_min = temp;
  }
  if(x<in_min){
    return out_min;
  }else if(x<in_dead_min){
    return map(x,in_min,in_dead_min,out_min,out_mid);
  }else if(x>in_max) {
    return out_max;
  }else if(x>in_dead_max){
    return map (x,in_dead_max,in_max,out_mid,out_max);
  }else{
    return out_mid;
  }
}

/*
 * Behaves similarly to the built-in Arduino map function, 
but maps a "deadband" section of the input range to middle 
value of the output range.
 * 
 * The return value is constrainted to lie within the range 
 "out_min" to "out_max".
 * The range of "deadband" values around the cente rof 
"in_min" and "in_max" are mapped to the output "out_mid".
 */
long deadbandMap(long x, long in_min, long in_deadband, long 
in_max, long out_min, long out_mid, long out_max)
{
  long in_double_mid = in_min+in_max;
  long in_dead_min;
  long in_dead_max;
  if((in_min*2)<in_double_mid){
    in_dead_min = (in_double_mid-in_deadband)/2;
    in_dead_max = (in_double_mid+in_deadband)/2;
  }else{
    in_dead_min = (in_double_mid+in_deadband)/2;
    in_dead_max = (in_double_mid-in_deadband)/2;
  }
  return deadbandMap(x,in_min,in_dead_min,in_dead_max,in_max,out_min,out_ 
mid,out_max);
}
 New contributor
  • Hi @geaux62, Ah, let me see, your proposal of developing a Rpi python version of Arduino RCPulseIn is interesting, but a bit too board for this Rpi SE Q&A forum. I would suggest to eat the big elephant one bite at a time. For example, we can focus the most essential function: Converting RC transceiver PPM signal to Rpi PWM signal. After we got the PWM signal we can use easily merge easily available python functions for Rpi + L298N based servo/DC motor controller to make a complete Rpi python version of RCPulsein library. / to continue, … – tlfong01 48 mins ago   
  • We can use a newbie friendly Instructable such as the following as a basic specification: Decoding RC Signals Using Arduino – GeekySingh 2019oct instructables.com/id/…. Your proposed python function is a bit too long. Perhaps you can break it down to a couple of smaller functions, and added more comments so that newbies can follow and contribute. A proposal is to start with the DeadBandMap method/function, assuming you have already written the Rpi GPIO setup, ReadPPM, writePWM methods/functions. Counter suggestions welcome. – tlfong01 37 mins ago   
  • To summarize, we can eat the big elephant in 3 bites (1) RC PPM signal receiving, (using SparkFun for reference) (2) PPM to PWM convesion (This Rpi SE forum question), and (3) pwm to servo control (use AdaFruit Servo Board for reference). Below are the references. They are Arduino C++ or CircuitPython oriented (AdaFruit has circuitPython libraries. (a) SparkFun RC Hobby Controllers and Arduino – Nick Poole, 2012 sparkfun.com/tutorials/348 (b) Adafruit PCA9685 16-Channel Servo Driver – Bill Earl 2019 cdn-learn.adafruit.com/downloads/pdf/… – tlfong01 1 min ago   Edit   

Categories: Uncategorized

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: