Loading...
Pages: [1] 2   Go Down
Author Topic: Using pulseIn() to read PWM stream for radio control  (Read 1721 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Sr. Member
****
Karma: 5
Posts: 469
what?
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi All,

I have a 40mhz 6 channel RC transmitter and reciever, the rx has no individual servo channels, it continually outputs the pwm channel stream to a controller board on a boat.

On the transmitter, channel 6 is a simple non latching push to make switch, i have replaced this with a 3 way non latching toggle switch, so it gives me down, centre and up, so 3 functions from 1 switch.

Everything works but i'd like to know if there is a better way of extracting individual stick positions from a pwm stream, Does PulseIn() require pull up / pull down resistor

Heres the code incase anyone might find it usefull, the leds will be replaced by a servo modded for continous rotation hence, up, down, centre off

Thanks

Code:
int inpin = 2;  // PWM input pin
unsigned long inval[7];  // Array to hold channels

void setup()
{
  Serial.begin(9600);
  pinMode(9,OUTPUT);   // Low val led pin
  pinMode(10,OUTPUT);  // Neutral val led pin
  pinMode(11,OUTPUT);  // High val led pin

}

void loop()
{
  for(int i=1; i<7; i++)  // loop through channel 1 to 6
  {
    inval[i] = pulseIn(inpin,LOW);  // get pwm value for that channel
  }
//  Serial.print("Inval1 = ");
//  Serial.println(inval[1]);
//  Serial.print("Inval2 = ");
//  Serial.println(inval[2]);
//  Serial.print("Inval3 = ");
//  Serial.println(inval[3]);
//  Serial.print("Inval4 = ");
//  Serial.println(inval[4]);
//  Serial.print("Inval5 = ");
//  Serial.println(inval[5]);
  Serial.print("Inval6 = ");  // debug channel 6 to serial
  Serial.println(inval[6]);  //  debug channel 6 to serial
 
  if ((inval[6]>590) & (inval[6]<610))  // if channel 6 stick is down light low led
  {
    digitalWrite(9,HIGH);
    digitalWrite(10,LOW);
    digitalWrite(11,LOW);
  }
 
  if ((inval[6]>1100) & (inval[6]<1120)) // if channel 6 stick is neutral light neutral led
  {
    digitalWrite(9,LOW);
    digitalWrite(10,HIGH);
    digitalWrite(11,LOW);
  }
 
  if ((inval[6]>1600) & (inval[6]<1620)) // if channel 6 stick is up light high led
  {
    digitalWrite(9,LOW);
    digitalWrite(10,LOW);
    digitalWrite(11,HIGH);
  }

  delay(250);  // stable delay down to 50, anything less is unstable
}
Logged

Dubai, UAE
Offline Offline
Edison Member
*
Karma: 20
Posts: 1627
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,
  Try using interrupts -

This link refers to individual servo channels, but could easily be adapted to read the pulse train-
http://rcarduino.blogspot.com/2012/01/how-to-read-rc-receiver-with.html

Duane B

rcarduino.blogspot.com
Logged


Offline Offline
Full Member
***
Karma: 0
Posts: 197
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I wonder if i can use this for what im after,

Duane , im reading your links, they look good,
Logged

0
Offline Offline
Sr. Member
****
Karma: 5
Posts: 469
what?
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks for that Duane, I've never really understood interupts, although my code is working i think it's more luck than anything as im not detecting where the stream starts i.e. channel one, when i drop the delay then channel become out of sync, i'll have to scope the stream some more, thanks for the link
Logged

Dubai, UAE
Offline Offline
Edison Member
*
Karma: 20
Posts: 1627
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I have a library that reads PPM RC signals by combining six channels into two, it might be too low level to be useful to you- you would need to mod it a bit - I will have a look in the morning and let you know.

Duane B



Logged


0
Offline Offline
Sr. Member
****
Karma: 5
Posts: 469
what?
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks for that, all i need is to know what channel 6 is doing but the receiver i have has no channels, instead it outputs the continous stream into a custom decoder board, channel 6 on the decoder board is simply on or off but i want it to opperate a continous rotation servo bolted to a winch, therefore i have modded the transmitter and want to intercept channel 6 on the reciever,  i hope makes some sense as to why i cant just use the receiver channel, there is no outputs on it

The Custom controller board, the chip in the bottom right decodes the pwm stream


The Receiver with no channel outputs, only signal


Centre off


UP


Down
Logged

Dubai, UAE
Offline Offline
Edison Member
*
Karma: 20
Posts: 1627
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I am sure I have something that will help, I will have a look when I get home this evening, in the meantime how about a picture of the boat ?

Duane B

Logged


0
Offline Offline
Sr. Member
****
Karma: 5
Posts: 469
what?
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

As requested, some more pictures

The bait boat itself, it has a wireless camera on the front


the winch I made as it will be mounted


The winch itself, the servo is modded for continuous rotation, so position 90 is stop, 0 = down & 180 is up, the winch will raise and lower a waterproof CCD camera attached to a transmitter on the boat, I've drilled a hole in the end of the servo and mounted a cermet pot inside to adjust zero rotation trim


my code is a bit sucky, it works but more by luck i think as im not checking for the start of channel 1, so if anyones got any better ideas like how to check for the start pulse im all ears
Code:
#include <Servo.h>
Servo myservo;
int inpin = 2;  // PWM input pin
int pos = 90;
unsigned long inval[7];  // Array to hold channels

void setup()
{
  myservo.attach(4);
}

void loop()
{
  for(int i=1; i<7; i++)  // loop through channel 1 to 6
  {
    inval[i] = pulseIn(inpin,LOW);  // get pwm value for that channel
  }
  if ((inval[6]>590) & (inval[6]<610))  // if channel 6 stick is down light low led
  {
    myservo.write(180);
  }
 
  if ((inval[6]>1100) & (inval[6]<1120)) // if channel 6 stick is neutral light neutral led
  {
    myservo.write(90);
  }
 
  if ((inval[6]>1600) & (inval[6]<1620)) // if channel 6 stick is up light high led
  {
    myservo.write(0);
  }

  delay(250);  // stable delay down to 50, anything less is unstable
 
}
Logged

Dubai, UAE
Offline Offline
Edison Member
*
Karma: 20
Posts: 1627
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,
    The way I have done this is to track the start time of each pulse using micros(), if the current pulse arrives more than 3000us later than the last pulse I know that it is the start of a new frame and therefore is channel 0. I used an array index to track the pulse number so set this to zero at this point. For each pulse that arrives after the first one I increment the array index which also represents the channel number - I store the period between pulses in the array based on the index/channel number.

    I add a lot of checking code to ensure that all later pulses match my expectations i.e. they arrive within 1 to 2 milliseconds. If any pulses arrive outside of this timeframe, they are probably noise and so I reject any following pulses and look for the next pulse which arrives later than 3000us to signify the start of the next pulse frame - when I find this I set the channel number (array index) to 0 and start recording pulses again.

I wrote a low level library to do this, but do not like it in my applications where my brushed motors generate a large amount of electrical noise which I have found makes the technique less attractive, the amount of checking code I need to add cancels any advantage I might have otherwise had.

If you are working in a less noisey environment or with lower powered or brushless motors it should be fine.

I am travelling at the moment but should be able to post a variation of the code individual channel based code that reads PPM instead. This code is not low level so you should be able to rework it in any way you want.

Will be modded to read PPM -
http://rcarduino.blogspot.ie/2012/01/how-to-read-rc-receiver-with.html
 
Duane B.

rcarduino.blogspot.com



Logged


0
Offline Offline
Sr. Member
****
Karma: 5
Posts: 469
what?
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks for that explanation Duane, I kind of understand what your getting at, I just have a problem translating idea's into practice, I'll give it a go tonight, one thing that didn't cross my mind was motor noise, it uses 2 chunky brushed motors and so far i haven't tested it with the motors running, another thing to test tonight

Cheers
Shaun
Logged

Dubai, UAE
Offline Offline
Edison Member
*
Karma: 20
Posts: 1627
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,
   I do my testing in RC Race cars so its a lot of accelerating, deccelerating and bumping around. I also use powerful batteries and performance brushed motors so its very noisey. Most of the glitches happen during hard accelerate and also when I lift off the throttle and let the car coast.

   My guess is that standard receivers include a lot of well established software and hardware that does a reasonable job of decoding the incoming PPM into the individual channels, Futaba have been at this longer than I have so I trust them to get this bit right.

   I know that in your case you have no option but to use the PPM signal, I also suspect that your operating enviroment is less challenging and so you will probably be ok.

If I find time to put some code up for you in the next few days, I will include an indicator for the number of glitches during a period, you can use this to judge whether its a practical solution or not - as I mentioned I think in your case it will be.

Duane B

rcarduino.blogspot.com
Logged


Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 138
Posts: 19066
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
My guess is that standard receivers include a lot of well established software and hardware that does a reasonable job of decoding the incoming PPM into the individual channels,
My guess is that they use mechanical inertia and a 50Hz repetition rate to get them out of difficulties   smiley-wink
Logged

Pete, it's a fool looks for logic in the chambers of the human heart.

Dubai, UAE
Offline Offline
Edison Member
*
Karma: 20
Posts: 1627
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,
   While you might be right, momentum at 60Km/h on a 1 meter wide race track is not always an ideal situation.

   Probably not too much of an issue on a lake though

Duane B.
Logged


Dubai, UAE
Offline Offline
Edison Member
*
Karma: 20
Posts: 1627
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Shaun,

Are you still looking for code for this ?

Do you have time to test some code that should read all of your channels ?

Duane B

rcarduino.blogspot.com
Logged


0
Offline Offline
Sr. Member
****
Karma: 5
Posts: 469
what?
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I took your advice and added a while condition to the beggining of loop() which waits for a pulse of at least 3000 before progressing to decode the PPM, it seems to work well as i no longer need the delay at the end of loop(), it's all working pretty well, i've chopped 2" of the frame of the winch and attached it onto the back of the boat with ball joints so it can snap on and snap off when not in use, all that's left to do is etch a pcb and house it, thanks for all you help Duane and yes i'd like to have a look at your code anyway as it's always good to get a 2nd opinion and aproach
Logged

Pages: [1] 2   Go Up
Print
 
Jump to: