Arduino Forum

Forum 2005-2010 (read only) => Hardware => Interfacing => Topic started by: mem on Dec 01, 2008, 02:18 pm

Title: Decoding Radio Control signal pulses
Post by: mem on Dec 01, 2008, 02:18 pm
I posted a library for decoding signals from a radio control transmitter (with a 'trainer port') or from an RC receiver that provides access to the pulse stream. The original code and discussion was in a huge thread titled '3 axis auto stabilized platform' http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1204020386

I've heard that people have trouble compiling the ServoDecode library under 0012. I have created a new thread here to make it easier to find. The following change is needed in ServoDecode.h file to get it to compile under Arduino release 0012.

Remove the line:
Code: [Select]
#include <wiring.h>
and replace it with:
Code: [Select]
typedef uint8_t byte;


This fixes a conflict with a pesky macro in wiring.h that I hope will be removed in future versions.

But in the mean time, you can make the above change to the previously posted ServoDecode file or use the code  in the following posts. Note that there is no change needed to the ServoDecode.cpp file
Title: Re: Decoding Radio Control signal pulses
Post by: mem on Dec 01, 2008, 02:21 pm
ServoDecode.h
Code: [Select]
// ServoDecodeClass.h
//This library decodes typical RC composite servo inputs into individual channel pulse widths

#ifndef ServoDecode_H
#define ServoDecode_H

#include <inttypes.h>
//#include <wiring.h> //removed for 0012
typedef uint8_t byte;

#define icpPin            8         // this interrupt handler must use pin 8
#define TICKS_PER_uS      2          // number of timer ticks per microsecond


typedef enum {
   NULL_state=-1, NOT_SYNCHED_state, ACQUIRING_state, READY_state, FAILSAFE_state    
} decodeState_t;

#define MAX_CHANNELS    8         // maximum number of channels we can store, don't increase this above 8
#define MIN_IN_PULSE_WIDTH (750 * TICKS_PER_uS) //a valid pulse must be at least 750us (note clock counts in 0.5 us ticks)
#define MAX_IN_PULSE_WIDTH (2250 * TICKS_PER_uS) //a valid pulse must be less than  2250us
#define SYNC_GAP_LEN      (3000 * TICKS_PER_uS) // we assume a space at least 3000us is sync (note clock counts in 0.5 us ticks)
#define FAILSAFE_PIN   13  // if defined, this will set the given pin high when invalid data is received


class ServoDecodeClass
{
 public:
     ServoDecodeClass(); //Constructor
     void begin();
     decodeState_t getState(); //State Function
     int GetChannelPulseWidth(byte chan);  // this is the access function for channel data
     void setFailsafe(byte chan, int value); // pulse width to use if invalid data, value of 0 uses last valid data
     void setFailsafe();// setFailsafe with no arguments sets failsafe for all channels to their current values
                      // useful to capture current tx settings as failsafe values
     byte getChanCount();
private:

};

extern ServoDecodeClass ServoDecode;  // make an instance for the user

#endif

ServoDecode.cpp
Code: [Select]

//ServoDecode.cpp
#include "ServoDecode.h"
#include <wiring.h>
#include <avr/interrupt.h>

#define PULSE_START_ON_RISING_EDGE  0
#define PULSE_START_ON_FALLING_EDGE (1<<ICES1)
#define ACQUISITION_COUNT  8  // must have this many consecutive valid frames to transition to the ready state.
volatile byte pulseEnd = PULSE_START_ON_RISING_EDGE ; // default value
static volatile unsigned int Pulses[ MAX_CHANNELS + 1]; // array holding channel pulses width value in microseconds
static volatile unsigned int Failsafe[MAX_CHANNELS + 1]; // array holding channel fail safe values
static volatile byte Channel;      // number of channels detected so far in the frame (first channel is 1)
static volatile byte NbrChannels; // the total number of channels detected in a complete frame
static volatile decodeState_t State;         // this will be one of the following states:
static volatile byte stateCount;         // counts the number of times this state has been repeated

static void processSync(){
// Sync was detected so reset the channel to 1 and update the system state      
  Pulses[0] = ICR1 / TICKS_PER_uS;  // save the sync pulse duration for debugging
  if(State == READY_state) {  
        if( Channel != NbrChannels){  // if the number of channels is unstable, go into failsafe
              State = FAILSAFE_state;
        }
  }
  else{
    if(State == NOT_SYNCHED_state){
            State = ACQUIRING_state;        // this is the first sync pulse, we need one more to fill the channel data array    
            stateCount = 0;
      }
      else if( State == ACQUIRING_state)      {
         if(++stateCount > ACQUISITION_COUNT) {
           State = READY_state;           // this is the second sync and all channel data is ok so flag that channel data is valid    
               NbrChannels = Channel; // save the number of channels detected
           }
    }
      else if( State == FAILSAFE_state)      {  
            if(Channel == NbrChannels){  // did we get good pulses on all channels
                 State = READY_state;
           }
      }
  }
  Channel = 0;       // reset the channel counter
}

ISR(TIMER1_OVF_vect){
 if(State == READY_state){
   State = FAILSAFE_state;  // use fail safe values if signal lost  
   Channel = 0; // reset the channel count
 }
}

ISR(TIMER1_CAPT_vect)
{
 // we want to measure the time to the end of the pulse
 if( (_SFR_BYTE(TCCR1B) & (1<<ICES1)) == pulseEnd ){         
   TCNT1 = 0;       // reset the counter
   if(ICR1 >= SYNC_GAP_LEN){   // is the space between pulses big enough to be the SYNC
     processSync();
   }    
   else if(Channel < MAX_CHANNELS) {  // check if its a valid channel pulse and save it
     if( (ICR1 >= MIN_IN_PULSE_WIDTH)  && (ICR1 <= MAX_IN_PULSE_WIDTH) ){ // check for valid channel data                  
       Pulses[++Channel] = ICR1 / TICKS_PER_uS;  // store pulse length as microsoeconds
     }
     else if(State == READY_state){
       State = FAILSAFE_state;  // use fail safe values if input data invalid  
       Channel = 0; // reset the channel count
     }
   }      
 }
}

ServoDecodeClass::ServoDecodeClass(){
}

void ServoDecodeClass::begin(){
 pinMode(icpPin,INPUT);
 Channel = 0;            
 State = NOT_SYNCHED_state;
 TCCR1A = 0x00;         // COM1A1=0, COM1A0=0 => Disconnect Pin OC1 from Timer/Counter 1 -- PWM11=0,PWM10=0 => PWM Operation disabled
 TCCR1B = 0x02;         // 16MHz clock with prescaler means TCNT1 increments every .5 uS (cs11 bit set
 TIMSK1 = _BV(ICIE1)|_BV (TOIE1);   // enable input capture and overflow interrupts for timer 1
 for(byte chan = 1; chan <=  MAX_CHANNELS; chan++)
       Failsafe[chan] = Pulses[chan]= 1500; // set midpoint as default values for pulse and failsafe
}

decodeState_t ServoDecodeClass::getState(){
 return State;
}

byte ServoDecodeClass::getChanCount(){
 return NbrChannels;
}

void  ServoDecodeClass::setFailsafe(byte chan, int value){
// pulse width to use if invalid data, value of 0 uses last valid data
 if( (chan > 0) && (chan <=  MAX_CHANNELS)  ) {
      Failsafe[chan] = value;
 }
}
void  ServoDecodeClass::setFailsafe(){
// setFailsafe with no arguments sets failsafe for all channels to their current values
// usefull to capture current tx settings as failsafe values
 if(State == READY_state)
   for(byte chan = 1; chan <=  MAX_CHANNELS; chan++) {
       Failsafe[chan] = Pulses[chan];
   }
}

int ServoDecodeClass::GetChannelPulseWidth( uint8_t channel)
{
 // this is the access function for channel data
 int result = 0; // default value
 if( channel <=  MAX_CHANNELS)  {
    if( (State == FAILSAFE_state)&& (Failsafe[channel] > 0 ) )
        result = Failsafe[channel]; // return the channels failsafe value if set and State is Failsafe
      else if( (State == READY_state) || (State == FAILSAFE_state) ){
        cli();       //disable interrupts
        result =  Pulses[channel] ;  // return the last valid pulse width for this channel
        sei(); // enable interrupts
      }
 }
 return result;
}
// make one instance for the user
ServoDecodeClass ServoDecode = ServoDecodeClass() ;


ServoDecode.pde Test Sketch
Code: [Select]
// ServoDecodeTest

#include <ServoDecode.h>

char * stateStrings[] = {
 "NOT_SYNCHED", "ACQUIRING", "READY", "in Failsafe"};

void setup()                    // run once, when the sketch starts
{
 Serial.begin(38400);  
 pinMode(12,OUTPUT);
 pinMode(13,OUTPUT);  
 ServoDecode.begin();
 ServoDecode.setFailsafe(3,1234); // set channel 3 failsafe pulse  width
}

void loop()                     // run over and over again
{
 int pulsewidth;

 // print the decoder state
 if( ServoDecode.getState()!= READY_state) {
   Serial.print("The decoder is ");
   Serial.println(stateStrings[ServoDecode.getState()]);
   for ( int i =0; i <=MAX_CHANNELS; i++ ){ // print the status of the first four channels
     Serial.print("Cx"); // if you see this, the decoder does not have a valid signal
     Serial.print(i);
     Serial.print("= ");
     pulsewidth = ServoDecode.GetChannelPulseWidth(i);
     Serial.print(pulsewidth);
     Serial.print("  ");
   }
   Serial.println("");
 }
 else {
   // decoder is ready, print the channel pulse widths
   for ( int i =1; i <=MAX_CHANNELS; i++ ){ // print the status of the first four channels
     Serial.print("Ch");
     Serial.print(i);
     Serial.print("= ");
     pulsewidth = ServoDecode.GetChannelPulseWidth(i);
     Serial.print(pulsewidth);
     Serial.print("  ");
   }
   Serial.println("");
   digitalWrite(12,LOW);
   digitalWrite(13,LOW);
 }
 delay(500); // update 2 times a second        
}
Title: Re: Decoding Radio Control signal pulses
Post by: dave82 on Dec 09, 2008, 05:57 am
Thank you again for posting the servo decoder.  I uploaded it and it worked like a charm!  My only problem now is that when i try to use the analogWrite function whle running the decoder, it doesn't seem to work.  Has anyone else run into this problem?
Title: Re: Decoding Radio Control signal pulses
Post by: mem on Dec 16, 2008, 08:16 pm
Hi dave, this code uses hardware support from timer1 so analogWrite() for digital pins 9 and 10 will not work. Try it on the other pins and report back here if it works.
Title: Re: Decoding Radio Control signal pulses
Post by: ubuntucat on Dec 30, 2008, 03:45 am
I'm really new to arduino..... How do I use these 3 files.  I have them each open in a tab and when I compile it says:

25: error: ServoDecode.h: No such file or directory In function 'void setup()':
In function 'void loop()':
Title: Re: Decoding Radio Control signal pulses
Post by: mem on Dec 30, 2008, 03:33 pm
This code is intended to be used as an Arduino library. Create a new directory called ServoDecode in the directory with the other libraries ( ? hardware\libraries\ServoDecode)

Copy ServoDecode.h and ServoDecode.cpp into this directory.

The ServoDecode.pde code should be pasted into the IDE to create a new sketch. This example sketch includes <ServoDecode.h> but if you create your own sketch, you can use the 'Sketch/Import Library' function from the IDE menu.

There is some information in the playground on Arduino Libraries that goes into more detail.

Have fun!    
Title: Re: Decoding Radio Control signal pulses
Post by: ubuntucat on Jan 07, 2009, 09:55 pm
what all needs to be changed in order for this to work with the 6-channel Vex
Title: Re: Decoding Radio Control signal pulses
Post by: mem on Jan 07, 2009, 11:39 pm
I don't think anything needs to be changed in the library, you may want to contact jamiemcshan about connecting it up -  see this post:
http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1204020386/176#176

When you get it going, please come back here and post details of how you did it.

Have fun!
Title: Re: Decoding Radio Control signal pulses
Post by: aerodolphin on Feb 20, 2009, 12:28 am
It's every time in failsafe.

How I do the connections?

Where I connect the PWM input?
Title: Re: Decoding Radio Control signal pulses
Post by: mem on Feb 20, 2009, 09:26 am
You connect the PPM stream to arduino pin 8.
Title: Re: Decoding Radio Control signal pulses
Post by: arcore on Feb 23, 2009, 04:53 am
Hello mem,

thanks for the great libraries. New life for the old receiver - I used your code with GWS R-4PII/H receiver with only 3 channels working - accidentally burned one channel long time ago. The beauty is I get all 6 channels on arduino. Now I'm wondering if the library could be used to decode Futaba PCM signal? Have you heard if anyone tried that? I found arduino helicopter autopilot thread (another great project) mentions PCM in several places, but looking at the code samples in the thread it seems its just PPM.

Title: Re: Decoding Radio Control signal pulses
Post by: mem on Feb 23, 2009, 09:01 am
The technique used in this library is completely different from that needed to decode a signal encoded using the Futaba PCM protocol. That protocol uses proprietary serial encoding and would required much more processing than the PPM decoding used here.

In my opinion it would not be worth the effort to do this - of course you are welcome to take it on if you are up for the challenge. But I would think in most situations there would be no benefit and for those cases with strong interference you would be better of using 2.4ghz technology.

What was the reason you were interested in PCM?
Title: Re: Decoding Radio Control signal pulses
Post by: arcore on Feb 24, 2009, 03:35 pm
I just thought it would be fun to get PCM out or PPM receiver. But PPM works great and I don't want to spend time working on PCM if will eat up too much arduino processing power, though your interrupt method could probably be adopted to read the bits of PCM transmission too?

By the way the library works with inverted signals too. For some reason my GWS receiver had it inverted and the only problem i noticed first channel had very high numbers (around 10,000 or so) but the rest of the channels were fine.
Title: Re: Decoding Radio Control signal pulses
Post by: mem on Feb 24, 2009, 03:56 pm
In my opinion, PCM would be a lot of work for no benefit. There are many more productive and fun things to do with your time.

BTW, if you want to use the library with a receiver with an inverted output, in ServorDecode.cpp change:
[font=Courier New]volatile byte pulseEnd = PULSE_START_ON_RISING_EDGE ; // default value[/font]
 to
[font=Courier New]volatile byte pulseEnd = PULSE_START_ON_FALLING_EDGE; // [/font]inverted pulses

then recompile the library (by deleting ServoDecode.o and rebuilding your sketch)
Title: Re: Decoding Radio Control signal pulses
Post by: arcore on Feb 25, 2009, 05:17 am
Bummer, should have asked earlier about the inverted. I already soldered a simple amplifier/inverter right on to GWS R4PII/H :(
Well, it needed amplifier though - only had 2.5V impulses without it and was getting very noisy feedback from arduino controller back into the receiver. But with this code change i could have gotten away with just one transistor...
Thanks for the info!  ;)
Title: Re: Decoding Radio Control signal pulses
Post by: mem on Feb 25, 2009, 08:42 am
I would have thought that the transistor and resistor would have been enough to invert the signal with the 2.5 volt pulses and drive the Arduino input. But no worries if you now have something that works.
Title: Re: Decoding Radio Control signal pulses
Post by: frank26080115 on Mar 11, 2009, 04:06 pm
Hi, I have a suggestion for the code, instead of using "TCNT1 = 0;", why not remember the previous value of ICR1 and keep track of overflows, this way you can get an unlimited value for the pulse width, also it's more accurate since it takes a few clock cycles to clear TCNT1

http://code.google.com/p/circle-of-current/source/browse/vex_ppm_reader/main.c

The only thing that can go wrong is if the capture event happens when TCNT1 is 0 and the capture interrupt executes before the overflow interrupt
Title: Re: Decoding Radio Control signal pulses
Post by: mem on Mar 11, 2009, 04:38 pm
Hi Frank, resetting TCNT to 0 takes 250 nanoseconds on a 16Mhz Arduino. Because the timer is counting in 500 nanosecond ticks I don't think this delay makes any difference. Indeed I would be surprised to hear if any of the radio control equipment that would be used with this kind of application would notice differences in timing of less than a microsecond.

I am  not clear if  the ability to detect unlimited values for the pulse width are something one would would use in radio control or if you have another application for the code.

Many thanks for taking the time to share your comments, its always interesting to see the different ways people approach things.
Title: Re: Decoding Radio Control signal pulses
Post by: frank26080115 on Mar 11, 2009, 04:50 pm
oh i totally agree that it's overkill, the RC radio would need a 16 bit ADC for the joystick if it wants to make the accuracy worthwhile, i'm not dividing my timer so i'm getting 0.05 microsecond resolution if i run my chip at 20 MHz
Title: Re: Decoding Radio Control signal pulses
Post by: gmv on Mar 23, 2009, 02:36 pm
Quote
You connect the PPM stream to arduino pin 8.


Hi all, mem.... could you tell me what would be the designation for the pin 8, i´m using an Arduino Duemilinove board with an atmega 328 and i think pin 8 is not the indicated one for this board . ::)

thanks in advance
Title: Re: Decoding Radio Control signal pulses
Post by: mem on Mar 23, 2009, 02:45 pm
All the pin assignments are the same for the 328 and the 168. have you tried it on pin 8?
Title: Re: Decoding Radio Control signal pulses
Post by: gmv on Mar 23, 2009, 05:19 pm
Hi again, i think you mean pin 8 at the top board, i haven´t tried yet...i ment IC pin 8(atmega), so i understand now,...i´ve loaded the code and i could visualize the data stream on the arduino serial monitor.
One more dumb question, what are the pin´s used for the outputs ?  :)

 regards
Title: Re: Decoding Radio Control signal pulses
Post by: mem on Mar 23, 2009, 05:44 pm
If you are using Arduino (and most compatibles) ,  digital pin 8 is clearly marked on the board.
http://arduino.cc/en/Main/ArduinoBoardDuemilanove

If you have built your own board, the pin assignments can be found here: http://www.arduino.cc/en/Hacking/PinMapping168
Title: Re: Decoding Radio Control signal pulses
Post by: gmv on Mar 23, 2009, 11:08 pm
Thanks again mem . ;)

gmv
Title: Re: Decoding Radio Control signal pulses
Post by: ubuntucat on Mar 24, 2009, 01:28 am
I have the ServoDecode_pde sketch working with my chepo VEX transmitter.  When I attach my scope probe to the ppm pin to view the pulses while it's going to the arduino it switches to Failsafe mode the moment I touch the pin.

Any ideas what would cause this?  The scopes input impedance is 1M ohm.  Not sure why this would effect anything.  I can see the pulses fine on the scope but the arduino goes immediately into failsafe.

Edit:
I just noticed that if I touch the pull-up resistor with my finger it also goes into failsafe mode....  I'm confused!
Title: Re: Decoding Radio Control signal pulses
Post by: ubuntucat on Mar 24, 2009, 01:30 am
Also when I have the sticks centered the values displayed are ~1500.  The pulses when viewed on the scope are ~1ms so I would have expected the values to be around 1000 instead of 1500.  (or is it 2 ticks per us so then it would be 2000)
Title: Re: Decoding Radio Control signal pulses
Post by: mem on Mar 24, 2009, 06:24 am
Most transmitters send 1.5ms pulses with the stick centered. When was the last time you had your scope calibrated?  ;)

How are you connecting the signal to arduino - are you sure you need pull-ups?
Title: Re: Decoding Radio Control signal pulses
Post by: ubuntucat on Mar 24, 2009, 02:37 pm
thanks for the reply the details of the ppm signal from the vex are listed here http://www.allelectronics.com/mas_assets/spec/JS-6.pdf  As you can see the total range for the pulses is 0.5ms - 1.5ms and 1ms is the center position.  

And yes you do need a pull up in order to see the pulses.
Title: Re: Decoding Radio Control signal pulses
Post by: mem on Mar 24, 2009, 02:54 pm
You would need to change MIN_IN_PULSE_WIDTH and MAX_IN_PULSE_WIDTH constants to lower values to work with the vex. It looks like the space betwen pulses is the same as  valid pulse width so some of the error checking wont work.

Does the vex support 12 channels?

I don't have a vex so may not be much help if you run into problems. I suggest you keep things simple at first and try to get it working with 6 channels.
Title: Re: Decoding Radio Control signal pulses
Post by: ubuntucat on Mar 24, 2009, 04:03 pm
Thanks mem will try that when I get home....I forgot about the min pulse widths....  The vex only supports 6 channels (4 analog, 2 digital)

Also it is the low portion of the pulse that changes not the high the high pulses are always 500us.  Is this different than most transmitters?
Title: Re: Decoding Radio Control signal pulses
Post by: jds on Mar 24, 2009, 04:10 pm
It is correct that the Vex transmitter has 6 channels, but I read (after doing a Google search for this transmitter) that you can connect an extra transmitter and have 12 channels.

I don't know the details, but those that are interested can look it up.
Title: Re: Decoding Radio Control signal pulses
Post by: mem on Mar 24, 2009, 04:30 pm
Most transmitters start a channel on the rising edge, but You can easily change it by making a small mod to the library.

in ServoDecode.cpp, change:  
[font=Courier New]
 volatile byte pulseEnd = PULSE_START_ON_RISING_EDGE ; // default value[/font]
to[font=Courier New]
 volatile byte pulseEnd = PULSE_START_ON_FALLING_EDGE; // inverted pulses[/font]
Title: Re: Decoding Radio Control signal pulses
Post by: ubuntucat on Mar 24, 2009, 05:45 pm
I was thinking that  pulseEnd changed what defined the end of the pulse (when it stops counting).  I want it to start counting on the falling edge and stop counting at the leading edge.

When I try your suggestion mem it never synchs..  keeps repeating "the decoder is NOT_SYNCHED" Cx0= 0  and all the rest are 0

I'm assuming this is because the synch pulse is low and it is only reading the 0.5ms high pulses that never change.

Is there a way to make it start on a falling edge instead of rising edge?  This would also explain why my measurements seemed to be 0.5ms too long
Title: Re: Decoding Radio Control signal pulses
Post by: mem on Mar 24, 2009, 06:26 pm
what values did you use for MIN_IN_PULSE_WIDTH and MAX_IN_PULSE_WIDTH
Title: Re: Decoding Radio Control signal pulses
Post by: ubuntucat on Mar 24, 2009, 06:51 pm
changed the min to 450
Title: Re: Decoding Radio Control signal pulses
Post by: ubuntucat on Mar 25, 2009, 11:18 pm
bump
Title: Re: Decoding Radio Control signal pulses
Post by: gmv on Mar 29, 2009, 08:00 am
Hi all, i´ve been out for a few days but last night i got the chance to connect the PWM data stream of my radio to the pin8 of my board, with Arduino monitor i could see the data on the screen but the "fail safe" message was always there, i even tested with my scope just to confirm and nothing at the outputs, i must check the values(TTL), i guess it may need to be rised a little bit,.....any ideias ?

p.s - i got the data stream from the radio output plug (after the TX module been removed) .

 thanks
Title: Re: Decoding Radio Control signal pulses
Post by: mem on Mar 29, 2009, 08:29 am
ubuntucat, sorry for the delayed reply, I have been busy and did not see your post.

I have no experience with the vex and it's difficult to help without having the actual hardware on the bench. Did you try and contact jamiechan?
Title: Re: Decoding Radio Control signal pulses
Post by: mem on Mar 29, 2009, 08:29 am
gmv, what transmitter are you using? Can you post a snippet of the data you get on the Arduino monitor? The voltage level of the pulses need more than 2.5 volts when high, ideally between 3 and 5 volts, what do you see on your scope?
Title: Re: Decoding Radio Control signal pulses
Post by: jds on Mar 29, 2009, 09:56 am
does it matter if his radio is in pcm or ppm mode?
Title: Re: Decoding Radio Control signal pulses
Post by: mem on Mar 29, 2009, 11:36 am
Yes, it must be in PPM mode for this library to decode the signal
Title: Re: Decoding Radio Control signal pulses
Post by: gmv on Mar 29, 2009, 04:51 pm
Hi mem, i´ve changed my transmitter and now i got a good signal from the trainer port to pin8, now i can see the changes each time i move the channel switchs or the joysticks, but how can i drive the servos ?.....wich outputs should i use, ...the PWM ones i supose,....., could you please edit and post here the full sketch file in order for me to compare with mine ? ::)

thanks again and sorry to take your time
Title: Re: Decoding Radio Control signal pulses
Post by: ubuntucat on Mar 29, 2009, 04:58 pm
Well I've got it working....  When I ran the example sketch for servoDecode it would frequently go into fail safe.  When I run my own sketch everything seems to be working fine.  It's being used to run 4 motor controllers and 3 servos using a servo controller.  Thanks for the help mem, and everyone else.

On a side note, which PWM pins will no longer work when using ServoDecode?
Title: Re: Decoding Radio Control signal pulses
Post by: mem on Mar 29, 2009, 06:05 pm
ubuntucat, good to hear you have it working.

ServoDecode uses timer1, therefore analogWrite on pins 9 and 10 are not available.

I am surprised to hear that changing a sketch would make any difference to fail safe. I would want to modify the example if it could prevent anyone in future from having a similar problem, please tell me more about what you needed to change.
Title: Re: Decoding Radio Control signal pulses
Post by: mem on Mar 29, 2009, 06:08 pm
Quote
On a side note, which PWM pins will no longer work when using ServoDecode?

Servos don't operate with the pwm output from analogWrite, but you can use the ServoTimer2 library. This was developed specifically for use with ServoDecode.

http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1230479947/0

Here is a simple test sketch:
Code: [Select]

// ServoDecodeTest
#include <ServoTimer2.h>
#include <ServoDecode.h>

// define the servo pins
#define servoApin  2   // the pin the servo is attached to/
ServoTimer2 servoA;    // declare variables for the servos

char * stateStrings[] = {
 "NOT_SYNCHED", "ACQUIRING", "READY", "in Failsafe"};


void setup()                    // run once, when the sketch starts
{
 Serial.begin(38400);  
 servoA.attach(servoApin);
 ServoDecode.begin();
 ServoDecode.setFailsafe(3,1234); // set channel 3 failsafe pulse  width
}


void loop()                     // run over and over again
{
 int count=0;
 int pulsewidth;

 // print the decoder state
 if( ServoDecode.getState()!= READY_state) {
   Serial.print("The decoder is ");
   Serial.println(stateStrings[ServoDecode.getState()]);
   for ( int i =0; i <=MAX_CHANNELS; i++ ){ // print the status of the first four channels
     Serial.print("Cx");
     Serial.print(i);
     Serial.print("= ");
     pulsewidth = ServoDecode.GetChannelPulseWidth(i);
     Serial.print(pulsewidth);
     Serial.print("  ");
   }
   Serial.println("");
 }
 else {  
   if( count % 20 == 0){   // decoder is ready, print the channel pulse widths every second
     for ( int i =1; i <=MAX_CHANNELS; i++ ){ // print the status of the first four channels
       Serial.print("Ch");
       Serial.print(i);
       Serial.print("= ");
       pulsewidth = ServoDecode.GetChannelPulseWidth(i);
       Serial.print(pulsewidth);
       Serial.print("  ");
     }
     Serial.println("");
   }
   count++;
 }
 servoA.write(ServoDecode.GetChannelPulseWidth(3));
 delay(20); // update 50 times a second        

}
Title: Re: Decoding Radio Control signal pulses
Post by: rasc1234 on Apr 12, 2009, 11:35 pm
Hi,
I have tried to use ServoDecode on a Duemilanove-Board and it works perfectly - thank you! However, when using the same sketch on the new Mega-Board the library says "no sync" - any insight what needs to be changed?

Title: Re: Decoding Radio Control signal pulses
Post by: mem on Apr 13, 2009, 09:13 am
The chip used on the mega board has the hardware connected differently than the 168. I need to modify the library for it to work (timer1 Input Capture is not connected to an Arduino pin so I will need to use a different timer on the mega board)

If you don't see something posted in a week or so, send me a PM to remind me.  
Title: Re: Decoding Radio Control signal pulses
Post by: rasc1234 on Apr 13, 2009, 05:12 pm
Thank you so much for extending the library! :)
Title: Re: Decoding Radio Control signal pulses
Post by: gmv on Apr 16, 2009, 11:32 pm
Hi guys, it is getting dificult to get this task forward, when i compile this sketch, i got some error messages as follows.

// ServoDecodeTest
#include <Servodecode.h>
#include <ServoTimer2.h>  // the servo library


// define the servo pins
#define servo1Pin 2   //the pin the servo is attached to
#define servo2Pin 3

ServoTimer2 servo1;    // declare variables for the servos
ServoTimer2 servo2;

void setup()
{
 Serial.begin(38400);
 servo1.attach(servo1Pin);
 servo2.attach(servo2Pin);
 ServoDecode.begin();
}


void loop()
{
 int pulsewidth[MAX_CHANNELS];

 if (ServoDecode.getState()!= READY_state) {
   Serial.println("The decoder is not ready");
 }
}
 else {
   // decoder is ready, do something with the channel pulse widths
   if (ServoDecode.GetChannelPulseWidth(1) > 1500)
   
   {  // run script 1 if pulse width greater than 1500 ;
     int argumentA = (2250 - ServoDecode.GetChannelPulseWidth(2)) / 200; // some values proportional to stick position
     boolean argumentB = ServoDecode.GetChannelPulseWidth(2) < 1500; // true if channel 2 less than 1500
     runScript1(argumentA, argumentB);
   }
 }
 delay(100); // update 10 times a second
}

void  runScript1(int argumentA, boolean argumentB)

{ // do something here to control servo...
 servo1.write(2000);
 delay(5000);  // note that all servo are pulsed by the interrupt handler with their current value every 20ms
 if (argumentA)
    servo2.write(2000);
 delay(argumentB * 10); //delay a time determined by the transmitter stick position
 servo1.write(1000);
 servo2.write(1000);

}



In file included from C:\Users\ABBA\Desktop\arduino-0013-Servo Decode\hardware\cores\arduino/WProgram.h:4,


c:/users/abba/desktop/arduino-0013-servo decode/hardware/tools/avr/lib/gcc/../../avr/include/stdlib.h:111: error: expected unqualified-id before 'int'


c:/users/abba/desktop/arduino-0013-servo decode/hardware/tools/avr/lib/gcc/../../avr/include/stdlib.h:111: error: expected `)' before 'int'


c:/users/abba/desktop/arduino-0013-servo decode/hardware/tools/avr/lib/gcc/../../avr/include/stdlib.h:111: error: expected `)' before 'int'


In file included from C:\Users\ABBA\Desktop\arduino-0013-Servo Decode\hardware\cores\arduino/WProgram.h:6,

thanks in advance.
Title: Re: Decoding Radio Control signal pulses
Post by: mem on Apr 17, 2009, 04:16 pm
gmv, from the look of those messages, I think you are not using the latest versions of the libraries, they were both updated to work with recent Arduino releases. Your sketch compiles ok for me (although I needed to remove an extra curly brackets }  before the first else in loop)

Check that you have the latest versions of both libraries.
You can find the latest version of ServoDecode in this thread and ServoTimer2 is here:
http://www.arduino.cc/playground/uploads/Main/ServoTimer2.zip
Title: Re: Decoding Radio Control signal pulses
Post by: gmv on Apr 17, 2009, 07:09 pm
Hi mem, many thanks...now i got it compling,..., i´ve loaded the sketch to the board and connected the PPM frame output of my Futaba to pin 8, the servo to pin 3 or 2 but i couldn´t get it moving when i move the sticks of my radio, also on my serial monitor, i got the message "the decoder is not ready ",...do you think it could have anything to do with inverted signals ?......any ideias what could be ? :-/

thanks again
Title: Re: Decoding Radio Control signal pulses
Post by: mem on Apr 18, 2009, 05:45 pm
Why not try it with the example sketch posted in this thread. If it still doesn't work, then you can try inverting the pulse detection as follows:  replace the line in ServoDecode.cpp:
[font=Courier New]volatile byte pulseEnd = PULSE_START_ON_RISING_EDGE ; // default value[/font]
with
[font=Courier New]volatile byte pulseEnd = PULSE_START_ON_FALLING_EDGE ; [/font]

delete SevoDecode.o and then rebuild your sketch.
Title: Re: Decoding Radio Control signal pulses
Post by: gmv on Apr 18, 2009, 10:08 pm
Hi mem, this morning i finally could make it work as expected, now i can drive all servos from my Tx !

Now my next goal is to drive a relay, just using one servo output from the Arduino Board . :)

Any ideias are welcome.

GMV
Title: Re: Decoding Radio Control signal pulses
Post by: mem on Apr 18, 2009, 11:31 pm
GMV, good to hear you have it working, was it inverting the pulse or something else that got it going?

You can control a relay by using the pulse width returned from the GetChannelPulseWidth method. If the pulse is above (or below) a given threshold you can set a pin high. There is info on connecting relay here if you need it: http://www.arduino.cc/playground/uploads/Learning/relays.pdf

Title: Re: Decoding Radio Control signal pulses
Post by: gmv on Apr 19, 2009, 11:38 am
Hi mem, i didn´t inverted the pulses,...., only deleted old arduino´s folders and instaled the new version and created a new sketch based on the servotest sketch that you mentioned on the previous page, made some changes and voilá !

Listen, i´ll try to implement your ideia for driving the relay, but then if i needed to drive 8 relay´s from a single pwm output, do i need any extra library´s or the existing ones (servo.*, servodecode.*, servotimer2:
) are enough ?

Could you give some example of a code from where i could starting working ?  8-)

 thanks in advance
Title: Re: Decoding Radio Control signal pulses
Post by: mem on Apr 19, 2009, 12:05 pm
gmv, if you post a fragment of your sketch indicating where you want the relays to be triggered I will be happy to guide you with the code. I suggest you start a new thread for your specific application.

Title: Re: Decoding Radio Control signal pulses
Post by: gmv on Apr 19, 2009, 03:25 pm
Ok, i´ll do it !

GMV
Title: Re: Decoding Radio Control signal pulses
Post by: jds on Apr 28, 2009, 04:29 pm
This is the pin description of the buddy port of my Sanwa RD6000 (Airtronics equivalen):

1 = ??
2 = Ground
3 = OUT
4 = +V switched
5 = IN

If I am correct, I have to connect pin 2 of buddy port to gnd on Arduino and pin 3 on buddy port to pin 8 of Arduino.

Can anyone confirm?

I have tried it this way and I get the "The decoder is in Failsafe" message all the time.
Title: Re: Decoding Radio Control signal pulses
Post by: mem on Apr 28, 2009, 05:11 pm
I have no experience with the sanwa. It is possible that the signal is inverted so it my be worth recompiling the library to use an inverted signal. A search in this thread should turn up the information on how do to it.

some keywords to try in the search are : pulseEnd PULSE_START_ON_FALLING_EDGE
Title: Re: Decoding Radio Control signal pulses
Post by: jds on Apr 28, 2009, 07:32 pm
I tried that, but I get
Code: [Select]
The decoder is NOT_SYNCHED

Cx0= 0  Cx1= 0  Cx2= 0  Cx3= 0  Cx4= 0  Cx5= 0  Cx6= 0  Cx7= 0  Cx8= 0


Maybe the voltage level is not high enough?
Title: Re: Decoding Radio Control signal pulses
Post by: mem on Apr 28, 2009, 07:41 pm
> Maybe the voltage level is not high enough?

You could try to use a transistor to condition the signal. If you have an NPN transistor (almost anything will do)  connect the output of the transmitter to the base of the transistor, the emitter to arduino Gnd, The collector to a resistor (any thing from 1k to 10k ohms would work).  Also connect the arduino pin 8 to the junction of the resistor and the transistor. Connect the other side of the resistor to +5v.

Try that with the library  configured for the inverted signal ( the transistor will invert the signal again).
Title: Re: Decoding Radio Control signal pulses
Post by: jds on Apr 28, 2009, 08:35 pm
Could I use a scope to see if voltage level is too low? I have this scope, but not very experienced in using scopes:

http://jyetech.com/en/default.html
Title: Re: Decoding Radio Control signal pulses
Post by: mem on Apr 28, 2009, 09:18 pm
Yes, that should tell you a lot about the pulses. If you can take a picture and post it that will be even better.
Title: Re: Decoding Radio Control signal pulses
Post by: jds on Apr 28, 2009, 10:20 pm
Sorry about quality, but this is the best I could get now:
http://www.flickr.com/photos/11991128@N04/3484304140/

I also have a movie posted at flickr:
http://www.flickr.com/photos/11991128@N04/3484305340/

Thanks for your suggestions/support mem!
Title: Re: Decoding Radio Control signal pulses
Post by: mem on Apr 28, 2009, 10:41 pm
It looks like the pulses are just under two divisions high, what is the scale set for?

It also looks inverted, that is the widths of spaces between the higher pulses is changing, I expect to  see the high pulse width change.  

Perhap you can touch the scope probe the the Arduino +5v pin to check that the polarity of the scop is not reversed.
Title: Re: Decoding Radio Control signal pulses
Post by: jds on Apr 28, 2009, 11:01 pm
Thanks again mem!

>It looks like the pulses are just under two divisions high, what is the scale set for?

I was afraid you were going to ask questions like these :) I am not an experienced scope user. All that I can tell is:
- There is a switch with x1, x2 and x5, I have it set to X5
- 2ns switch has GND, 1V and 0,1V, I have it set to 1V
- 3rd switch has AC, DC, Freq M, I have it set to DC
Also, the LCD mentions 1MS

Does that ring a bell to you?

>Perhap you can touch the scope probe the the Arduino +5v pin to check that the polarity of the scop is not reversed
I just did that and all I see is a nice sine/wave, difference between high and low is not too big.

I hope this enough information to get me a step closer to a working environment.
Title: Re: Decoding Radio Control signal pulses
Post by: mem on Apr 28, 2009, 11:43 pm
You should see the trace move when you touch the scope probe to Gnd and to +5v. If its set for 1v per division and x5 then I would expect it to move up 5 divisions above the poisition when the probe is connecte to Gnd. have a play around and see if you can get the hang of how the trace behaves when connected between Gnd and +5v and use that to get the approx value of the waveforms you see from your Transmitter
Title: Re: Decoding Radio Control signal pulses
Post by: jds on Apr 30, 2009, 09:49 pm
Shoot me!

Suddenly, it started working without changing anything.

It seems that the serial speed is lacking, there is a time difference between a change of a stick and seeing the change in the serial window. Maybe this is caused by my Windows 7 x64 notebook?

I will check on other pc's
Title: Re: Decoding Radio Control signal pulses
Post by: rasc1234 on Apr 30, 2009, 10:07 pm
@mem

Hi,
have you already found any time to adapt the library to the Mega board? Would it would together with the servo-library for that board?
Title: Re: Decoding Radio Control signal pulses
Post by: mem on Apr 30, 2009, 10:09 pm
At 9600 baud, serial will be working flat out to send 20 characters in each frame.

anyway, good to hear you have it going.

Have fun!

Title: Re: Decoding Radio Control signal pulses
Post by: mem on Apr 30, 2009, 10:36 pm
Quote
have you already found any time to adapt the library to the Mega board? Would it would together with the servo-library for that board?


Unfortunately I have not had the time to complete the code for a version that works with both, but here is a first pass if you want to test it. It should work with the existing MegaServo library (up to 36 servos instead of 48) but untested and this version hard coded for mega only.  
Code: [Select]
/*
* ServoDecode.cpp
* this version for Mega only
*/

#include "ServoDecode.h"
#include <wiring.h>
#include <avr/interrupt.h>

#define PULSE_START_ON_RISING_EDGE  0
#define PULSE_START_ON_FALLING_EDGE (1<<ICES4)
#define ACQUISITION_COUNT  8  // must have this many consecutive valid frames to transition to the ready state.
volatile byte pulseEnd = PULSE_START_ON_RISING_EDGE ; // default value
static volatile unsigned int Pulses[ MAX_CHANNELS + 1]; // array holding channel pulses width value in microseconds
static volatile unsigned int Failsafe[MAX_CHANNELS + 1]; // array holding channel fail safe values
static volatile byte Channel;      // number of channels detected so far in the frame (first channel is 1)
static volatile byte NbrChannels; // the total number of channels detected in a complete frame
static volatile decodeState_t State;         // this will be one of the following states:
static volatile byte stateCount;         // counts the number of times this state has been repeated

static void processSync(){
// Sync was detected so reset the channel to 1 and update the system state      
  Pulses[0] = ICR4 / TICKS_PER_uS;  // save the sync pulse duration for debugging
  if(State == READY_state) {  
        if( Channel != NbrChannels){  // if the number of channels is unstable, go into failsafe
              State = FAILSAFE_state;
        }
  }
  else{
    if(State == NOT_SYNCHED_state){
            State = ACQUIRING_state;        // this is the first sync pulse, we need one more to fill the channel data array    
            stateCount = 0;
      }
      else if( State == ACQUIRING_state)      {
         if(++stateCount > ACQUISITION_COUNT) {
           State = READY_state;           // this is the second sync and all channel data is ok so flag that channel data is valid    
               NbrChannels = Channel; // save the number of channels detected
           }
    }
      else if( State == FAILSAFE_state)      {  
            if(Channel == NbrChannels){  // did we get good pulses on all channels
                 State = READY_state;
           }
      }
  }
  Channel = 0;       // reset the channel counter
}

ISR(TIMER4_OVF_vect){
 if(State == READY_state){
   State = FAILSAFE_state;  // use fail safe values if signal lost  
   Channel = 0; // reset the channel count
 }
}

ISR(TIMER4_CAPT_vect)
{
 // we want to measure the time to the end of the pulse
 if( (_SFR_BYTE(TCCR4B) & (1<<ICES4)) == pulseEnd ){         
   TCNT1 = 0;       // reset the counter
   if(ICR4 >= SYNC_GAP_LEN){   // is the space between pulses big enough to be the SYNC
     processSync();
   }    
   else if(Channel < MAX_CHANNELS) {  // check if its a valid channel pulse and save it
     if( (ICR4 >= MIN_IN_PULSE_WIDTH)  && (ICR4 <= MAX_IN_PULSE_WIDTH) ){ // check for valid channel data                  
       Pulses[++Channel] = ICR4 / TICKS_PER_uS;  // store pulse length as microsoeconds
     }
     else if(State == READY_state){
       State = FAILSAFE_state;  // use fail safe values if input data invalid  
       Channel = 0; // reset the channel count
     }
   }      
 }
}

ServoDecodeClass::ServoDecodeClass(){
}

void ServoDecodeClass::begin(){
 pinMode(icpPin,INPUT);
 Channel = 0;            
 State = NOT_SYNCHED_state;
 TCCR4A = 0x00;         // COM1A1=0, COM1A0=0 => Disconnect Pin OC from Timer/Counter  -- PWM11=0,PWM10=0 => PWM Operation disabled
 TCCR4B = 0x02;         // 16MHz clock with prescaler means TCNT increments every .5 uS (cs11 bit set
 TIMSK4 = _BV(ICIE4)|_BV (TOIE4);   // enable input capture and overflow interrupts for timer 1
 for(byte chan = 1; chan <=  MAX_CHANNELS; chan++)
       Failsafe[chan] = Pulses[chan]= 1500; // set midpoint as default values for pulse and failsafe
}

decodeState_t ServoDecodeClass::getState(){
 return State;
}

byte ServoDecodeClass::getChanCount(){
 return NbrChannels;
}

void  ServoDecodeClass::setFailsafe(byte chan, int value){
// pulse width to use if invalid data, value of 0 uses last valid data
 if( (chan > 0) && (chan <=  MAX_CHANNELS)  ) {
      Failsafe[chan] = value;
 }
}
void  ServoDecodeClass::setFailsafe(){
// setFailsafe with no arguments sets failsafe for all channels to their current values
// usefull to capture current tx settings as failsafe values
 if(State == READY_state)
   for(byte chan = 1; chan <=  MAX_CHANNELS; chan++) {
       Failsafe[chan] = Pulses[chan];
   }
}

int ServoDecodeClass::GetChannelPulseWidth( uint8_t channel)
{
 // this is the access function for channel data
 int result = 0; // default value
 if( channel <=  MAX_CHANNELS)  {
    if( (State == FAILSAFE_state)&& (Failsafe[channel] > 0 ) )
        result = Failsafe[channel]; // return the channels failsafe value if set and State is Failsafe
      else if( (State == READY_state) || (State == FAILSAFE_state) ){
        cli();       //disable interrupts
        result =  Pulses[channel] ;  // return the last valid pulse width for this channel
        sei(); // enable interrupts
      }
 }
 return result;
}
// make one instance for the user
ServoDecodeClass ServoDecode = ServoDecodeClass() ;

In the .h, you need to change icpPin from 8 to 49 // Input is on digital pin 49 on Mega

Will try to the the version with conditional defines next week
Title: Re: Decoding Radio Control signal pulses
Post by: nikinick on May 07, 2009, 05:18 am
ubuntucat : what are your settings in the servodecoder  for the vex transmitter?
Title: Re: Decoding Radio Control signal pulses
Post by: halley on May 20, 2009, 07:03 pm
mem, have you done anything like ServoDecode when you don't have access to the combined receiver pulse train?  I'd like to basically recreate the data for a pulse train by spying on the individual servo lines.  This is for data logging or analysis.

I am guessing that it's typical that only one servo output of the receiver unit is getting its pulse at any given time, at least until you get up to the models with more channels than would fit in the 20ms servo clock.
Title: Re: Decoding Radio Control signal pulses
Post by: mem on May 20, 2009, 07:31 pm
I have had mixed results. For receivers that have a break between each channel you can connect the channels to an 'or' gate and monitor that. But many receivers don't provide any break between channels so the decoder can't tell when one pulse ends and the other begins. Also, many digital receivers  overlap the pulses (starting all channels at the same time).

I found the easiest solution was to tap into the composit signal in a non-digital receiver, but if you have a scope its worth looking at the channel outputs to see if you can produce a composite signal.  
Title: Re: Decoding Radio Control signal pulses
Post by: halley on May 20, 2009, 08:47 pm
mem, thanks for that.

I just happened to find someone who displayed timing for the Futaba R617FS which is one rx I'm using.  http://www.rcgroups.com/forums/showthread.php?p=11002684#post11002684

(http://static.rcgroups.com/forums/attachments/8/0/3/7/a2189805-247-R617FS%20100%20epa.jpg)

I haven't found a "where to solder" guide to find the composite ppm signal.
Title: Re: Decoding Radio Control signal pulses
Post by: gmv on May 26, 2009, 02:30 am
Hi guys, i´ve playing with the Arduino with the servo decoder sketch and while connecting the 2 servos i tried to disconnect the radio to test the "fail safe" feature but i noticed that the servos don´t stay at middle position, they move to the maximum position(2,1ms), my question is.....how can i activate this feature for each servo ?  :o

thanks in advance
Title: Re: Decoding Radio Control signal pulses
Post by: mem on May 26, 2009, 07:31 am
The failsafe value can be set for any channel by calling the setFailsafe() method with the desired channel and value:
[font=Courier New]  ServoDecode.setFailsafe(3,1234); // set channel 3 failsafe pulse  width to 1234[/font]
Calling  setFailsafe with just the channel sets the failsafe to the last valid received pulse width
[font=Courier New]   ServoDecode.setFailsafe(4); // set channel 4 failsafe to use the last received pulse  width[/font]

By default, all channels are set with a failsafe pulse width of 1500.
Title: Re: Decoding Radio Control signal pulses
Post by: gmv on May 26, 2009, 11:52 am
Hi mem, well this is what i´ve tested but the problem persist,...when i disconnect the radio the servo just doesn´t stays at center position, in the sketch, when i declare to use the last received position,..the arduino just return and error message while compiling.

thanks
Title: Re: Decoding Radio Control signal pulses
Post by: mem on May 26, 2009, 01:03 pm
Quote
when i declare to use the last received position,..the arduino just return and error message while compiling.

Could you clarify what you mean by 'last received position'.
What error message did you get?
Can you post a fragment of the sketch that illustrates the change that is causing the problem?
Title: Re: Decoding Radio Control signal pulses
Post by: gmv on May 26, 2009, 08:09 pm
I ment "last pulse width" received, today i could finally get failsafe on channel 1 but thats all, how can i put the others with failsafe as well ?

here is a part of the sketch :

Code: [Select]
void setup()  
{
 Serial.begin(115200);
 

 servoA.attach(servoApin);
 servoB.attach(servoBpin);
 servoC.attach(servoCpin);
 servoD.attach(servoDpin);
 servoE.attach(servoEpin);
 servoF.attach(servoFpin);
 servoG.attach(servoGpin);

 ServoDecode.begin();
 
 ServoDecode.setFailsafe(1,1234); // set channel 1 failsafe pulse  width
 ServoDecode.setFailsafe(2,1234); // set channel 2 failsafe pulse  width
 ServoDecode.setFailsafe(3,1234); // set channel 3 failsafe pulse  width
 ServoDecode.setFailsafe(4,1234); // set channel 4 failsafe pulse  width
 ServoDecode.setFailsafe(5,1234); // set channel 5 failsafe pulse  width
 ServoDecode.setFailsafe(6,1234); // set channel 6 failsafe pulse  width
 ServoDecode.setFailsafe(7,1234); // set channel 7 failsafe pulse  width  
 ServoDecode.setFailsafe(8,1234); // set channel 8 failsafe pulse  width


 thanks

Title: Re: Decoding Radio Control signal pulses
Post by: mem on May 26, 2009, 09:16 pm
It works for me, running this code:
Code: [Select]
// ServoDecodeTest

#include <ServoDecode.h>

char * stateStrings[] = {
 "NOT_SYNCHED", "ACQUIRING", "READY", "in Failsafe"};

void setup()  
{
 Serial.begin(9600);
 ServoDecode.begin();
 for( int i=1; i <=8; i++){
    ServoDecode.setFailsafe(i,1230 + i);
 }
}


void loop()      
{
 int pulsewidth;

 // print the decoder state
 if( ServoDecode.getState()!= READY_state) {
   Serial.print("The decoder is ");
   Serial.println(stateStrings[ServoDecode.getState()]);
   for ( int i =1; i <=MAX_CHANNELS; i++ ){ // print the status of the first four channels
     Serial.print("Cx"); // if you see this, the decoder does not have a valid signal
     Serial.print(i);
     Serial.print("= ");
     pulsewidth = ServoDecode.GetChannelPulseWidth(i);
     Serial.print(pulsewidth);
     Serial.print("  ");
   }
   Serial.println("");
 }
 else {
   // decoder is ready, print the channel pulse widths
   for ( int i =1; i <=MAX_CHANNELS; i++ ){ // print the status of the first four channels
     Serial.print("Ch");
     Serial.print(i);
     Serial.print("= ");
     pulsewidth = ServoDecode.GetChannelPulseWidth(i);
     Serial.print(pulsewidth);
     Serial.print("  ");
   }
   Serial.println("");
 }
 delay(500); // update 2 times a second        
}



I get this ouput:
Code: [Select]

The decoder is ACQUIRING
Cx1= 0  Cx2= 0  Cx3= 0  Cx4= 0  Cx5= 0  Cx6= 0  Cx7= 0  Cx8= 0  
Ch1= 1504  Ch2= 1509  Ch3= 1562  Ch4= 1489  Ch5= 1124  Ch6= 1041  Ch7= 1500  Ch8= 1500  
Ch1= 1505  Ch2= 1509  Ch3= 1561  Ch4= 1490  Ch5= 1123  Ch6= 1041  Ch7= 1500  Ch8= 1500  
Ch1= 1506  Ch2= 1507  Ch3= 1562  Ch4= 1489  Ch5= 1123  Ch6= 1039  Ch7= 1500  Ch8= 1500  
<transmitter switch off here>
The decoder is in Failsafe
Cx1= 1231  Cx2= 1232  Cx3= 1233  Cx4= 1234  Cx5= 1235  Cx6= 1236  Cx7= 1237  Cx8= 1238  
The decoder is in Failsafe
Cx1= 1231  Cx2= 1232  Cx3= 1233  Cx4= 1234  Cx5= 1235  Cx6= 1236  Cx7= 1237  Cx8= 1238  
The decoder is in Failsafe
Cx1= 1231  Cx2= 1232  Cx3= 1233  Cx4= 1234  Cx5= 1235  Cx6= 1236  Cx7= 1237  Cx8= 1238  


Title: Re: Decoding Radio Control signal pulses
Post by: gmv on May 28, 2009, 09:45 pm
Thanks mem, i guess i'm missing something here, i still have no failsafe besides channel 1, are using the same libraries for servodecoder and servotimer2 placed before on this thread, is any update for these two ?

I'll give it a try later and see whats is going wrong.

thanks
Title: Re: Decoding Radio Control signal pulses
Post by: mem on May 28, 2009, 10:24 pm
gmv, did you try the test sketch posted above?

I would be interested to see the output when the transmitter is on and then when it is switched off
Title: Re: Decoding Radio Control signal pulses
Post by: gmv on May 29, 2009, 11:22 am
Hi mem, finally i could make it work, just changed the delay =50, i was using 500, also i changed the speed to 57600.
I used your sketch above.

thanks a lot for your help. :D
Title: Re: Decoding Radio Control signal pulses
Post by: mem on May 29, 2009, 01:05 pm
Hmmm, I am curious to know why it started working. Changing the delay should only increase how often the information is printed. And the baud rate shouldn't affect the failsafe. Did anything else change?  

If you change the delay in that sketch back to 500 and the baud to 9600 would it stop working?
Title: Re: Decoding Radio Control signal pulses
Post by: gmv on May 29, 2009, 11:08 pm
Hi mem, in fact at first attempt i couldn't make it start, then i reload the code in to the chip and it started working but the servos didn't seem to responde as quickly as i moved the sticks, so i tried to increase the speed and it worked, but then when i switched off and on the radio, sometimes i had failsafe and some others none, tried several delays and it worked out with 50, now if you ask me why,..... ???  ::) ::) ::)

GMV
Title: Re: Decoding Radio Control signal pulses
Post by: mem on May 30, 2009, 08:37 am
Hi gmv, for the benefit of others that read this thread and think you had a problem with the test sketch posted in #reply 80, could you try it and it confirm if it works with the values as posted. Your posts seem to say that you needed to change the values in that sketch to get it to work.

If that sketch works but yours has a problem when the values change, then we would need to look at your code to see what the problem is.
Title: Re: Decoding Radio Control signal pulses
Post by: alpha_tayyab on May 30, 2009, 03:37 pm
can u explain me ur problem, may be i help you!!!!!!!!!
Title: Re: Decoding Radio Control signal pulses
Post by: mem on May 30, 2009, 03:55 pm
Hi TAYTAB, I think gmv has fixed his problem; it's just not clear what he has changed to get it working.
Title: Re: Decoding Radio Control signal pulses
Post by: zitron on Sep 27, 2009, 08:49 pm
Hi,

Sorry for digging this up, I spent ages trying to get MEM's ServoDecode to work, sometimes it worked fine, other times not at all. In the end, it turns out the problem was my receiver's PPM "HIGH" was not quite enough for the 168. So all I had to do to get it working was to add digitalWrite(icpPin, HIGH) in servodecode.begin() to enable the internal pull-up resistor. Now it's perfect.

Hope this helps someone.

-Z-

Title: Re: Decoding Radio Control signal pulses
Post by: mem on Sep 27, 2009, 08:54 pm
zitron, thanks for that tip.
BTW, you don't need to modify the library, you can put that code to enable the internal pull up in setup.
Title: Re: Decoding Radio Control signal pulses
Post by: dakkar on Nov 27, 2009, 09:45 pm
I have a 3ch Hitec Aggressor.  The first 2 channels control servos.  I want the 3rd channel to be read by my Arduino Duemilanove.  When I press the 3rd channel button, I want the Arduino to sense the change and send one of my digital pins to HIGH.  

I have tried using ServoDecode and I do not see a change when the 3rd channel button is activated.  Any help?
Title: Re: Decoding Radio Control signal pulses
Post by: jds on Nov 27, 2009, 10:31 pm
Please try this: if you have a receiver with an inverted output, in ServorDecode.cpp change:
volatile byte pulseEnd = PULSE_START_ON_RISING_EDGE ; // default value
to
volatile byte pulseEnd = PULSE_START_ON_FALLING_EDGE; // inverted pulses

please confirm if this helps
Title: Re: Decoding Radio Control signal pulses
Post by: dakkar on Nov 27, 2009, 11:18 pm
just tried that and I get

"The decoder is NOT_SYNCHED
Cx0= 0  Cx1= 0  Cx2= 0  Cx3= 0  Cx4= 0  Cx5= 0  Cx6= 0  Cx7= 0  Cx8= 0  
"

In the original state, all of the values seem to be independent of input from the transmitter anyway.  I have a feeling I am completely off the mark.  I am new to this stuff so any help is greatly appreciated!
Title: Re: Decoding Radio Control signal pulses
Post by: mem on Nov 27, 2009, 11:28 pm
The ServoDecode library is designed to decode a composite pulse stream containing all the transmitted servo signals. If you want to decode a single servo channel, It may be easier to use pulseIn to read the pulse width.  See the Arduino reference for more on pulseIn
Title: Re: Decoding Radio Control signal pulses
Post by: dakkar on Nov 27, 2009, 11:51 pm
I have tried that as well and it gives me values seemingly independent of transmitter input.  I'm thinking I may have to cheat and read the values used to drive the servo motor.
Title: Re: Decoding Radio Control signal pulses
Post by: mem on Nov 28, 2009, 09:31 am
Quote
I'm thinking I may have to cheat and read the values used to drive the servo motor.


not sure what you me an, the servo motor is driven by the pulse you are trying to measure.

Did you try the tip mentioned earlier in this thread of turning pull-ups on to increase the voltage on the arduino pin used to sense the pulse?
Title: Re: Decoding Radio Control signal pulses
Post by: dakkar on Nov 28, 2009, 04:07 pm
Quote
not sure what you me an, the servo motor is driven by the pulse you are trying to measure.


By that I mean the small electric motor inside the servo.  When an input from the the 3rd channel is received, +5v is applied to the motor making it operate.  I would use the circuitry inside the servo as the decoder. Instead of applying +5v to a motor when it receives a signal, it would apply it to the Arduino which would then run a certain piece of code.  

I was just trying to get away without having to break into a servo, although I have a few cheap ones lying around.  

I did try to use a pull-up but it sent everything to +5v no matter what.  I think I may have been using pulseIn() incorrectly though.  I still have a lot to learn... 
Title: Re: Decoding Radio Control signal pulses
Post by: mem on Nov 28, 2009, 04:23 pm
Try something like this test to see if you are able to read the pulses from the receiver. Don't have the servo connected when you run the test

Code: [Select]

int pin = 7;  // set this to the pin connected to your receiver
unsigned long duration;

void setup()
{
 Serial.begin(9600);
 pinMode(pin, INPUT);
}

void loop()
{
 duration = pulseIn(pin, HIGH);
 Serial.println(duration);
 delay(1000);
}


Title: Re: Decoding Radio Control signal pulses
Post by: dakkar on Nov 30, 2009, 08:27 pm
Thanks.  I've written that sketch a billion times thinking I was messing something up.

As a matter of fact I've figured out my problem.  The power supply to the receiver is +6v.  I was using that to power the receiver while attempting to read the control signal with the Arduino.  In an act of desperation, I decided to use the +5v on the Arduino to power the receiver and it magically started to work.  I really didnt think that a 1 volt power differential would make a difference, clearly I was wrong.  

In my research I noticed people putting a 220ohm resistor in line with the pulse being read by the Arduino.  Is that necessary?

I am also using a 10k pull-up per the suggestion and in both cases (using the 220 on the pulse and 10K as a pull up) there seems to be no difference with or without them.  Any thoughts on that?
Title: Re: Decoding Radio Control signal pulses
Post by: ardudillo on Dec 31, 2009, 01:40 am
Very nice tool thanks a lot. One quick question, in the first post you 're talking about "an RC receiver that provides access to the pulse stream". What manner of beast is this? I 've played a bit with RC at various stages and I don't think I 'ever seen a receiver that offered anything except a normal servo plug for each channel. Is it a feature that I perhaps have missed? Do most manufacturers make them? How do I go about getting one? What do I ask for?
Title: Re: Decoding Radio Control signal pulses
Post by: mem on Dec 31, 2009, 04:31 am
dakkar, sorry I missed your post, I hope my reply is not too late.

> I really didnt think that a 1 volt power differential would make a difference, clearly I was wrong.  
Did you have the receiver ground connected to Arduino ground?
Powering the receiver from the Arduino volt supply is best because this ensures that the voltage on the Arduino pins is not too high.

>In my research I noticed people putting a 220ohm resistor in (the input), Is that necessary?
No but its no bad thing. Although all the receivers I have looked at drive the servo outputs at a logic level suitable for direct connect to arduino, using a resistor provides an additional degree of protection.

>I am also using a 10k pull-up per the suggestion and in both cases  
A pull-up should not be required in this application but the Arduino internal pull-up value is high enough that it should not be a problem if you have this enabled.
Title: Re: Decoding Radio Control signal pulses
Post by: mem on Dec 31, 2009, 04:36 am
ardudillo, I have never seen a receiver that provided this signal out of the box. The thread  suggests a number that can be modified by soldering a wire onto the receiver circuit board.

This post mentions one that is cheap and easy to modify: http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1248474405/13#13

Here is another receiver that has been discussed in earlier posts : http://www3.towerhobbies.com/cgi-bin/WTI0001P?I=LXGZT0&P=8
Title: Re: Decoding Radio Control signal pulses
Post by: Heyarnold on Feb 05, 2010, 03:27 pm
I have this library working with my VEX controller now and was hoping to use it to contol motors with an H-Bridge.  

How would I create a PWM singnal for the H-Bridge?  

I tried using the ServoTimer2 library (it works very well too!) but it isn't suitable PWM for an H-bridge.   Any way to modifiy the ServoTimer2 library to do what I want?    Ideally, I would like to contol both servo motors and H-bridge together. :)
Title: Re: Decoding Radio Control signal pulses
Post by: mem on Feb 05, 2010, 04:34 pm
Heyarnold, you control PWM for things like an H-Bridge using the standard arduino analogWrite function. Bear in mind that the decode library uses timer1 and  servoTimer2 uses timer2 so you only have pins 5 & 6 available for analogWrite on a standard Arduino board.
Title: Re: Decoding Radio Control signal pulses
Post by: Heyarnold on Feb 05, 2010, 05:51 pm
Hi mem!  Thanks for such a quick response ( and the libraries!).  

I didn't think analogWrite function would work at all with both libraries going.  
I will try it out on pins 5 and 6 this weekend and report my results back to you.
Title: Re: Decoding Radio Control signal pulses
Post by: loris on Mar 21, 2010, 07:34 pm
Hi,

I tried to use your librairies (ServoTimer2 and ServoDecode) and I have a problem. My transmitter is a Graupner MX 16s.

I used your sample sketch and this is the result :

Code: [Select]
The decoder is in Failsafe
Cx0= 9628  Cx1= 1500  Cx2= 1500  Cx3= 1491  Cx4= 1500  Cx5= 1490  Cx6= 1517  Cx7= 1881  Cx8= 1087  
Ch1= 1877  Ch2= 1488  Ch3= 1491  Ch4= 1488  Ch5= 1489  Ch6= 1512  Ch7= 1880  Ch8= 1088  
Ch1= 1878  Ch2= 1488  Ch3= 1492  Ch4= 1487  Ch5= 1490  Ch6= 1517  Ch7= 1880  Ch8= 1087  
Ch1= 1878  Ch2= 1488  Ch3= 1490  Ch4= 1489  Ch5= 1488  Ch6= 1517  Ch7= 1880  Ch8= 1088  
Ch1= 1877  Ch2= 1488  Ch3= 1490  Ch4= 1488  Ch5= 1489  Ch6= 1517  Ch7= 1500  Ch8= 1500  
The decoder is in Failsafe
Cx0= 9628  Cx1= 1500  Cx2= 1488  Cx3= 1490  Cx4= 1489  Cx5= 1490  Cx6= 1518  Cx7= 1880  Cx8= 1088  
Ch1= 1878  Ch2= 1487  Ch3= 1491  Ch4= 1489  Ch5= 1490  Ch6= 1511  Ch7= 1880  Ch8= 1088  
Ch1= 1877  Ch2= 1488  Ch3= 1491  Ch4= 1488  Ch5= 1490  Ch6= 1517  Ch7= 1881  Ch8= 1088  
Ch1= 1878  Ch2= 1487  Ch3= 1490  Ch4= 1488  Ch5= 1490  Ch6= 1518  Ch7= 1880  Ch8= 1087  
The decoder is in Failsafe
Cx0= 9628  Cx1= 1500  Cx2= 1500  Cx3= 1485  Cx4= 1500  Cx5= 1500  Cx6= 1500  Cx7= 1880  Cx8= 1089  
Ch1= 1873  Ch2= 1488  Ch3= 1491  Ch4= 1488  Ch5= 1490  Ch6= 1517  Ch7= 1880  Ch8= 1089  
Ch1= 1878  Ch2= 1488  Ch3= 1490  Ch4= 1488  Ch5= 1490  Ch6= 1517  Ch7= 1880  Ch8= 1088  
Ch1= 1878  Ch2= 1488  Ch3= 1491  Ch4= 1487  Ch5= 1490  Ch6= 1514  Ch7= 1880  Ch8= 1088  


The decoder is always going on failsafe and even with ServoDecode.setFailsafe() the output servos is moving. I tried to put a servos on the output of the receiver and this servos had also noise when the receiver is connected to the Arduino).

I tried with digitalWrite(8, HIGH); and the servo connected to the receiver didn't have noise any more but I have the same problem of failsafe.

Do you have an idea of the problem? and why even with ServoDecode.setFailsafe() the servo had noise ?


Thanks.
Title: Re: Decoding Radio Control signal pulses
Post by: mem on Mar 21, 2010, 09:12 pm
are you sure you have all the grounds connected together?

Can you post a link to a picture that shows your wiring?
Title: Re: Decoding Radio Control signal pulses
Post by: loris on Mar 21, 2010, 09:19 pm
Yes I'am sure that the ground is connected. I plug the ground and the 5V to the arduino board.

I used this receiver with paparazzi before so it should work. Maybe the signal is not high enough, I will try the get a scope to check.
Title: Re: Decoding Radio Control signal pulses
Post by: loris on Mar 22, 2010, 08:44 pm
I managed to make it works!! The problem was that the board (+receiver + 2 servos) was powered by the usb and it was not power enough!
Title: Re: Decoding Radio Control signal pulses
Post by: mem on Mar 22, 2010, 09:09 pm
Good to hear you have it working
Title: Re: Decoding Radio Control signal pulses
Post by: loris on Mar 24, 2010, 08:23 pm
In fact my problem is not solved. When I only try do decode the PPM signal with your lib it works fine but when I want to control servos with your ServoTimer2 lib I have the same problem. Sometimes I lost the PPM signal.

I have a main loop at 50Hz where I read the channel pulses and then write commands to servos (2 servos and 4 ESCs) and if the decoder state is not ready I light on a LED. This LED is very often on and there is some noise on the servos.
Title: Re: Decoding Radio Control signal pulses
Post by: mem on Mar 24, 2010, 08:35 pm
It sounds like the problem is on the servo side, why not try and isolote the problem, perhaps try a test sketch using serial commands to control the servos.
Title: Re: Decoding Radio Control signal pulses
Post by: loris on Mar 24, 2010, 08:57 pm
The servos control works fine. I manage to control the servo with serial commands.

I though the problem came from interrupts. I also use ADC interrupt in my software buy I tried without and I have the same problem.

I tried with your test sketch for ServoDecoder and ServoTimer2 and this is the problem:

Code: [Select]
The decoder is in Failsafe
Cx0= 10819  Cx1= 1099  Cx2= 1497  Cx3= 1482  Cx4= 1497  Cx5= 1482  Cx6= 1489  Cx7= 1493  Cx8= 1087  
The decoder is in Failsafe
Cx0= 10824  Cx1= 1099  Cx2= 1497  Cx3= 1482  Cx4= 1497  Cx5= 1482  Cx6= 1489  Cx7= 1493  Cx8= 1086  
The decoder is in Failsafe
Cx0= 10822  Cx1= 1099  Cx2= 1497  Cx3= 1482  Cx4= 1497  Cx5= 1482  Cx6= 1497  Cx7= 1491  Cx8= 1081  
Ch1= 1100  Ch2= 1489  Ch3= 1493  Ch4= 1484  Ch5= 1487  Ch6= 1493  Ch7= 1489  Ch8= 1094  
The decoder is in Failsafe
Cx0= 10820  Cx1= 1099  Cx2= 1497  Cx3= 1482  Cx4= 1496  Cx5= 1488  Cx6= 1490  Cx7= 1491  Cx8= 1084  
The decoder is in Failsafe


Without attaching a servo it works fine.

I used the Ardu IMU 2+ board.

Edit : I tried with this sketch

Code: [Select]
// ServoDecodeTest
#include <ServoTimer2.h>
#include <ServoDecode.h>

// define the servo pins
#define servoApin  9   // the pin the servo is attached to/
ServoTimer2 servoA;    // declare variables for the servos

char * stateStrings[] = {
 "NOT_SYNCHED", "ACQUIRING", "READY", "in Failsafe"};

int count;
void setup()                    // run once, when the sketch starts
{
 Serial.begin(38400);
 count=0;
 
//  digitalWrite(8, HIGH);       // turn on pullup resistor on pin 8
servoA.attach(servoApin);
 pinMode(5,OUTPUT);   // Red
 ServoDecode.begin();
 delay(1000);
 ServoDecode.setFailsafe();
}


void loop()                     // run over and over again
{
 int pulsewidth;

 // print the decoder state
 if( ServoDecode.getState()!= READY_state) {
   Serial.print("The decoder is ");
   Serial.println(stateStrings[ServoDecode.getState()]);
   for ( int i =0; i <=MAX_CHANNELS; i++ ){ // print the status of the first four channels
     Serial.print("Cx");
     Serial.print(i);
     Serial.print("= ");
     pulsewidth = ServoDecode.GetChannelPulseWidth(i);
     Serial.print(pulsewidth);
     Serial.print("  ");
   digitalWrite(5,HIGH); // Light on Red led
   }
   Serial.println("");
 }
 else {
   if( count % 20 == 0){   // decoder is ready, print the channel pulse widths every second
     for ( int i =1; i <=MAX_CHANNELS; i++ ){ // print the status of the first four channels
       Serial.print("Ch");
       Serial.print(i);
       Serial.print("= ");
       pulsewidth = ServoDecode.GetChannelPulseWidth(i);
       Serial.print(pulsewidth);
       Serial.print("  ");

     digitalWrite(5,LOW); // Light off Red led
     }
     Serial.println("");
   }
   count++;
 }
 servoA.write(ServoDecode.GetChannelPulseWidth(3));
 delay(20); // update 50 times a second

}


And the LDE is always blinking. (I cannot have the telemetry because I powered the board with the ESC)
Title: Re: Decoding Radio Control signal pulses
Post by: mem on Mar 24, 2010, 10:14 pm
Try simplifying things to try and isolate the problem . Try it with just one servo wired up.  Does that work ok? If it does, experiment with various combinations of components to see if you can find out what triggers the problem.

Can  you post a link to a clear picture showing how the setup that has the problem is wired.
Title: Re: Decoding Radio Control signal pulses
Post by: loris on Mar 25, 2010, 09:09 am
It is very very strange. I tried with only 1 servos + 1 receiver + power supply from an ESC and I have the same problem.

Then I tried with an other brand of servo and it works ...

Do you think digital servos can create problems?
Title: Re: Decoding Radio Control signal pulses
Post by: mem on Mar 25, 2010, 10:19 am
It sounds like the problem is related to power or wiring issues.
Title: Re: Decoding Radio Control signal pulses
Post by: loris on Mar 25, 2010, 01:29 pm
Everything is powered by one ESC (5V 2A). I tried to wire only the ESCs and it worked but when I plugged one servo the problem occured.

I checked the connections and all grounds and all 5V are connected. The signal are connected to pin 9, 10 (servos) and 11, 12 (ESC).

Maybe servos have a problem but it is strange it interferes with the PPM decoder.
Title: Re: Decoding Radio Control signal pulses
Post by: mem on Mar 25, 2010, 02:22 pm
digital servos do draw more current than standard servos which is why I think there may be a power or wiring problem. you could try testing using another 5v power supply instead of  the ESC as the power source. Also have you tried adding decoupling capacitors to the power leads?
Title: Re: Decoding Radio Control signal pulses
Post by: loris on Mar 25, 2010, 06:52 pm
I tried with an external power supply and there is the same problem.

The power consumption is very low (60mA) and servos small (5g) so I think an ESC has enough power to drive it. I don't see any wiring problem.

It is very strange that servos disturb the PPM decoder.
Title: Re: Decoding Radio Control signal pulses
Post by: mem on Mar 25, 2010, 07:51 pm
Quote
The power consumption is very low (60mA) and servos small (5g) ...


I thought it was the digital servo that caused the problem, can you post a link to the servos specifications

I don't know of any servo that only draws 60mA when moving.

BTW, did you try using decoupling capacitors on the power supply?

Title: Re: Decoding Radio Control signal pulses
Post by: loris on Mar 25, 2010, 08:23 pm
60mA is when servos are idle. It is very small servos (http://www.hobbycity.com/hobbycity/store/uh_viewItem.asp?idProduct=9904&Product_Name=Blue_Arrow__3.9g_/_.18kg_/_.10sec_High_Speed_Micro_Servo)

I thought they were digital but they look to be analog. (I am not sure of the reference because the label had been erased).

I don't have a big capacitor, I will try to get one this week end.
Title: Re: Decoding Radio Control signal pulses
Post by: mem on Mar 25, 2010, 08:51 pm
That servo seems to be designed for 3.7 volt nominal opertion. According to one reviewer on that site, the servo should not be connected to 5 volts.

I suggest you try some tests to verify if the problem is caused by those servos running on 5 volts. either try using standard servos or try them with a 3.3v power supply.

I suggest you create a new thread to continue this discussion so that this thread can focus on providing  general adice on the library.
Post a link to your thread here so I and others interested can find it.
Title: Re: Decoding Radio Control signal pulses
Post by: walterwangus on Jun 09, 2010, 01:06 am
mem,

Thanks for the ServoDecode work. It works great for me. I was reading the old post on the evolution/development of the servodecode.c to get a better understanding (I'm new to AVR programming). There was a point where the toggling code went away :

         TCCR1B ^= _BV(ICES1);         // toggle bit value to trigger on the other edge.

I can't figure out how  the current code resets TCNT1 to 0 when a rising edge(start of next channel pulse) occurs. I appreciate your help, thanks.


Title: Re: Decoding Radio Control signal pulses
Post by: mem on Jun 09, 2010, 10:05 am
Hi Bebee,

The code was changed to make it easy to select between pulses that start on rising or falling edges.

The  pulseEnd variable is defined by the user to determine the pulse start (it will be set to 0 if starting on a rising edge, or  (1<<ICES1) if starting on a falling edge

Te following line in the ISR determines if the interrupt was caused by a pulse start or pulse end and if it's the end then TCNT1 is set to 0 ready to start measuring the next pulse duration.
Code: [Select]
if( (_SFR_BYTE(TCCR1B) & (1<<ICES1)) == pulseEnd ){         
   TCNT1 = 0;       // reset the counter


the code is slightly more cryptic than the previous version but has the advantage that inverted pulses can be handled.
Title: Re: Decoding Radio Control signal pulses
Post by: walterwangus on Jun 09, 2010, 04:30 pm
Mem,

Thanks for the response. I'm still a bit confused. I'm comparing two "ISR(TIMER1_CAPT_vect)" functions that you had posted previously one after the other. The first (11-06-08) :

Code: [Select]

ISR(TIMER1_CAPT_vect)
{
 // we want to measure the time to the end of the pulse
 if( (_SFR_BYTE(TCCR1B) & (1<<ICES1)) == pulseEnd ){
   TCNT1 = 0;               // reset the counter
     if(ICR1 >= SYNC_GAP_LEN){   // is the space between pulses big enough to be the SYNC
     processSync();
   }    
   else if(Channel <= MAX_CHANNELS) {  // else its channel pulse so save it
      Pulses[Channel++] = ICR1 / TICKS_PER_uS;  // store pulse length as microsoeconds
   }
 }
 else {        // the start of the pulse was detected  
   TCNT1 = 0;        // so reset the counter to start timing
     if(ICR1 >= SYNC_GAP_LEN){   // is the space between pulses big enough to be the SYNC    
     processSync();
     }
   if( State != READY_state && (ICR1 >= MIN_IN_PULSE_WIDTH) ){   // if the 'off' pulse is greater than minimum pulse, we need to invert the signal test
     pulseEnd ^= 1; // invert the pulse mode
     State = NOT_SYNCHED_state; //reset the state to start measuring from channel 1
   }
 }
 TCCR1B ^= _BV(ICES1);         // toggle bit value to trigger on the other edge
}


This code was modified next to (21-07-08):
Code: [Select]

ISR(TIMER1_CAPT_vect)
{
 // we want to measure the time to the end of the pulse
 if( (_SFR_BYTE(TCCR1B) & (1<<ICES1)) == pulseEnd ){  
   TCNT1 = 0;       // reset the counter
   if(ICR1 >= SYNC_GAP_LEN){   // is the space between pulses big enough to be the SYNC
     processSync();
   }    
   else if(Channel < MAX_CHANNELS) {  // check if its a valid channel pulse and save it
     if( (ICR1 >= MIN_IN_PULSE_WIDTH)  && (ICR1 <= MAX_IN_PULSE_WIDTH) ){ // check for valid channel data
       Pulses[++Channel] = ICR1 / TICKS_PER_uS;  // store pulse length as microsoeconds
     }
     else if(State == READY_state){
       State = FAILSAFE_state;  // use fail safe values if input data invalid  
       Channel = 0; // reset the channel count
     }
   }
 }
}




Both versions began with :
Code: [Select]

Code:
if( (_SFR_BYTE(TCCR1B) & (1<<ICES1)) == pulseEnd ){  
   TCNT1 = 0;       // reset the counter


However only the earlier version had the line :
Code: [Select]

TCCR1B ^= _BV(ICES1);         // toggle bit value to trigger on the other edge.


Looks like this line is needed to reset TCNT1 to 0 every time a falling edge and leading edge is detected so that it can set TCNT1 to 0 at the start of a pulse and get ICR1 at the end of a pulse.


From my understanding, the ICES1 in TCCR1B never changes once initialized in the begin(). Therefore (in default case) the beginning if-statement that tests for pulseEnd will only enter if a falling edge is detected.  And at that point, set TCNT1 = 0.  But i'm still confused as to where is TCNT1 set to 0 when a rising edge is detected? It looks like there is only 1 line in the entire code where TCNT1 is reset  to 0(or set to anything).

Thanks again mem.
Title: Re: Decoding Radio Control signal pulses
Post by: mem on Jun 09, 2010, 06:12 pm
The  older code was incorrectly resetting TCNT1 on both the mark (the length of the high pulse) and the space (the length of the low pulse). This worked on receivers that used a very short space interval.  But correct PPM decoding measures the time between transitions of the same edge - the sum of the mark and space. So TCNT1 only needs to be reset on one edge, as in the later code.

Here is an example of four PPM chanels as received followed by the four decoded servo pulses

Code: [Select]
/^^^^^^\_/^^^^^^\_/^^^^\_/^^^^^^^\_________________

/^^^^^^^^\______________________________________
_________/^^^^^^^^^\______________________________
___________________/^^^^^\_________________________
_________________________/^^^^^^^^^\________________
Title: Re: Decoding Radio Control signal pulses
Post by: walterwangus on Jun 09, 2010, 07:15 pm
That clarifies everything for me. Thanks mem.
Title: Re: Decoding Radio Control signal pulses
Post by: gmv on Jun 15, 2010, 07:34 am
@mem,

Hi mem, just a dumb question....is there any chance that you could add some kind of F/S feature in to the "ServoDecode.cpp " by pressing a button  connected to the decoder that could store the selected servos positions in to the Atmega eeprom  and when there was no PPM frame sync it would load these pre-selected positions back to the servos again ?  ::)

thanks - gmv
Title: Re: Decoding Radio Control signal pulses
Post by: mem on Jun 15, 2010, 09:05 am
@gmv

The library has functions to set failsafe values to the current servo positions or to any given position.  You could add functionality in your sketch to detect a button press and read the values for all the channels and save these in EEPROM as default failsafe values.
At startup you set the failsafe for all the channels from the EEPROM values.
Title: Re: Decoding Radio Control signal pulses
Post by: AlexanderB on Jul 05, 2010, 06:33 pm
Thank you mem, for the great routines.

I am new to it and I expect to get my Nano Board V3 very soon.

Will your Servo Decoder work on the Nano Board?
Is there a newer version available?

Thank you

Alexander
Title: Re: Decoding Radio Control signal pulses
Post by: mem on Jul 05, 2010, 07:33 pm
The code in the start of this thread is the latest version for the 168 and 328 chips and should work fine with the Nano.

Please tell us about your project when you have the nano board and have connected everthing up.
Title: Re: Decoding Radio Control signal pulses
Post by: AlexanderB on Jul 05, 2010, 07:42 pm
Thank you. I will post information about this project. Also because it's my first and I sure will have tons of questions.

So much for here: I will program am motor controller for my Douglas DC-6 model (100" span / 2,5m). I want to use two channels to control the four motor ESC: first start all motors one after the other in the order 3-4-2-1 then use channel 1 to control all four ESC like a V-cable. Then - after landing - use only motors 2 and 3 to taxi to the park position. I hope that I get this done. It will save me two precious channels on my TX.

Cheers Alexander
Title: Re: Decoding Radio Control signal pulses
Post by: mem on Jul 05, 2010, 08:11 pm
Hi Alexander, that sounds like an interesting and very do-able project. I will look forward to following your progress - the DC-6 was the first airliner that I flew in, although I don't remember much about it, I was six months old.
Title: Re: Decoding Radio Control signal pulses
Post by: AlexanderB on Jul 05, 2010, 08:25 pm
Thank you mem

One thing you may give me some advice about before I start the project:

What of course concerns me most is the reliability. I heard a lot about brown outs, watchdogs and stuff. What I have to make sure ist that the motor controller will work flawless. And if it quits working it must recover.

Is stability an issue with Arduino or can I rely on that (given a flawless working software)? Is there a situation possible where I cannot control my motors anymore?

Cheers Alexander
Title: Re: Decoding Radio Control signal pulses
Post by: mem on Jul 05, 2010, 08:55 pm
No software is flawless and its fair to say that the Arduino platform is not intended for mission critical applications. That said, I have not seen any problems that would rule out the Arduino for your application.

My advice is to use the failsafe to keep the engines running if there is a problem with the signal and do a lot of testing prior to your maiden flight.

Have fun!
Title: Re: Decoding Radio Control signal pulses
Post by: AlexanderB on Jul 08, 2010, 07:05 pm
I'm so happy! After finally managing to connect the GND wire (how emparassing!) It works like a charme! This is the first and important step!

Cheers Alexander
Title: Re: Decoding Radio Control signal pulses
Post by: mrmeval on Jul 08, 2010, 07:27 pm
http://autopilot.sourceforge.net/pcm.html

PCM is really complex. The link has limited information but allows comparison of them visually with two oscilloscope screen captures.

The DIY UAV looks interesting
http://autopilot.sourceforge.net/
Title: Re: Decoding Radio Control signal pulses
Post by: AlexanderB on Jul 08, 2010, 07:51 pm
Mem,

I'm stuck. I got your example running and the Servo example sweep does work as well.

I tried to let one servo follow CH 1. It does not work at all. I stripped as much as possible to prevent any side effects. Still nothing.

I also tried different pins. Nothing.

Code: [Select]

// ServoDecodeTest

#include <ServoDecode.h>
#include <Servo.h>

Servo myservo;  // create servo object to control a servo
               // a maximum of eight servo objects can be created

char * stateStrings[] = {
 "NOT_SYNCHED", "ACQUIRING", "READY", "in Failsafe"};

void setup()                    // run once, when the sketch starts
{
 myservo.attach(2);  // attaches the servo on pin X to the servo object
 ServoDecode.begin();
 ServoDecode.setFailsafe(3,1234); // set channel 3 failsafe pulse  width
}

void loop()                     // run over and over again
{
 int pulsewidth;
 if( ServoDecode.getState()== READY_state) {
         pulsewidth = ServoDecode.GetChannelPulseWidth(1);
         myservo.writeMicroseconds(pulsewidth);
 } else {
         pulsewidth = 1500;
         myservo.writeMicroseconds(pulsewidth);

 }  
}


Any ideas? BTW I use ARDUINO 0018

Cheers Alexander
Title: Re: Decoding Radio Control signal pulses
Post by: AlexanderB on Jul 08, 2010, 08:10 pm
Another try:

Code: [Select]

// ServoDecodeTest
#include <ServoDecode.h>
#include <ServoTimer2.h>  // the servo library


// define the servo pins
#define servo1Pin  2   // the pin the servo is attached to
#define servo2Pin  3

ServoTimer2 servo1;    // declare variables for the servos
ServoTimer2 servo2;

void setup()
{
Serial.begin(38400);
servo1.attach(servo1Pin);
servo2.attach(servo2Pin);
ServoDecode.begin();
}


void loop()
{
int pulsewidth;  //[MAX_CHANNELS];

if( ServoDecode.getState()!= READY_state) {
  Serial.println("The decoder is not ready");
}
else {
  // decoder is ready, do somthing with the channel pulse widths
  servo1.write(ServoDecode.GetChannelPulseWidth(1));
}
}



Here something happens but the servo flutteres.

Any ideas? Thank you  :)
Title: Re: Decoding Radio Control signal pulses
Post by: mem on Jul 08, 2010, 08:32 pm
try adding delay(20) at the end of loop.
Title: Re: Decoding Radio Control signal pulses
Post by: AlexanderB on Jul 08, 2010, 09:08 pm
No, does not help. Still fluttering.

BTW Why can't I use the Servo Library that comes with Arduino?

Cheers
Alexander
Title: Re: Decoding Radio Control signal pulses
Post by: AlexanderB on Jul 08, 2010, 09:14 pm
Sorry, I got the solution: the composit signal from the sat Extension of the RX sent a bad signal I connected the original Sat (that has no other task than giving that signal) and it works OK. Still a little noise but acceptable.

Still one open question: why can't I use the regular servo lib that comes with Arduino 0018?

Cheers Alexander
Title: Re: Decoding Radio Control signal pulses
Post by: mem on Jul 08, 2010, 09:34 pm
Good to hear you have it going. I still recommend adding the delay(20) in loop.

The standard servo library uses the same timer as the ServoDecode library so only one of them will run on an Atmega168 or 328. ServoTimer2 was written to use a different timer so it will work with ServoDecode on standard Arduino boards.

But you can use the standard library if you have a Mega board (see earlier in the thread for getting ServoDecode working on the Mega.
Title: Re: Decoding Radio Control signal pulses
Post by: AlexanderB on Jul 08, 2010, 09:40 pm
Thank you.

Since I want to learn: what is the idea behind using the delay(20)?

Cheers
Alexander
Title: Re: Decoding Radio Control signal pulses
Post by: mem on Jul 08, 2010, 10:01 pm
The servo library will update the servo every 20 milliseconds, writing to the servo more frequently does not improve performance.

Indeed, constantly rewriting values much more frequently than necessary can actually slow things down.
Title: Re: Decoding Radio Control signal pulses
Post by: AlexanderB on Jul 08, 2010, 10:18 pm
Thank you,

the code will - of course - get more complex in the future. This was just a basic test and it works. Unfortunately the composit signal that the receiver is supposed to deliver is faulty. Using the basic Satellite works though. So I go on with my tests.

Cheers
Alexander
Title: Re: Decoding Radio Control signal pulses
Post by: vinceherman on Jul 09, 2010, 10:31 pm
Wow, this thread has been active for (almost) 2 years!  [ch61514]

I have read through the entire thing, and I have learned a lot, which also means that it has raised a lot of questions.

Can I use this decoding method if I OR together several RC receiver channels together with diodes?  Here is a schematic of what I am thinking of.  I took it from the wiki page on diodes and modified it for my plans.
http://www.vinceherman.net/robot/media/OrDiodes.JPG

I have successfully decoded individual channels using attachinterrupt on 6 channels.  But that maxes out the number if pins available on my Mega for using the attachinterrupt.  I would rather just use 1 pin, even if it is just for 4 channels.  In the future I am sure I will want more channels.

I guess I need to go through my box'o'parts and see if any of them are diodes.  If not, where do I order, and anyone have recommendation on what type?  I have not ordered much in the way of individual electronic components.

Am I on the right track?
Where can I get current versions of the ServoDecode library?
Title: Re: Decoding Radio Control signal pulses
Post by: mem on Jul 09, 2010, 11:02 pm
vinceherman,  I don't think that will work because most RC receivers do not have a break between one channel going low and the next going high. In that case the signal will simply remain high from the start of the first channel to the end of the last and no valid decoding will occur.

I have thought about the possibility of using an or gate to trigger a monostable circuit (google 555 timer) but have not had the time to try anything along those lines. Perhaps somone else here has?

The code at the start of the thread is the latest version, with a modification posted in reply #70  to use timer4 if you have a Mega board so ServoDecode can be used with the standard servo library
Title: Re: Decoding Radio Control signal pulses
Post by: vinceherman on Jul 10, 2010, 04:54 am
Thanks for the quick reply.
Do you think I can put all the odd number channels on one pin, and the evens on another, so that I do get a break?
Or if I put 1,3 and 5 on one pin, can I use the low signal time as the duration of the even channels?
Title: Re: Decoding Radio Control signal pulses
Post by: mem on Jul 10, 2010, 07:10 am
Separating odd and even channels could work although it would require very significant rework of the library to support this.

I don't have the time to look into this but would be happy to assist if someone  comfortable working with timer interrupts wants to try and get this going.

But in my opinion, its much less effort to modify a suitable RC receiver to get access to the PPM stream so it can be decoded by the current code.
Title: Re: Decoding Radio Control signal pulses
Post by: AlexanderB on Jul 12, 2010, 10:48 am
Since I aked a lot I just want to give a short update. Yes. Arduino does a perfect job for RC models. I started with a fully programmable Gear Door Sequencer that can handel as mans Servos as pins are available.

Every delay and speed of each servo can be individually set.

This is the init of the servos shown on the video below.

Code: [Select]
 // Prepare Servo Parameters and timings
 gearParameters[sNosegear].servoPin = 2;
 gearParameters[sNosegear].upPos_us = 1000;
 gearParameters[sNosegear].downPos_us = 2000;
 gearParameters[sNosegear].delays[GEAR_UP].wait_ms = 100;
 gearParameters[sNosegear].delays[GEAR_UP].delay_ms = 4000;
 gearParameters[sNosegear].delays[GEAR_DOWN].wait_ms = 7500;
 gearParameters[sNosegear].delays[GEAR_DOWN].delay_ms = 4000;

 gearParameters[sNoseDoor].servoPin = 4;
 gearParameters[sNoseDoor].upPos_us = 1000;
 gearParameters[sNoseDoor].downPos_us = 2000;
 gearParameters[sNoseDoor].delays[GEAR_UP].wait_ms = 4500;
 gearParameters[sNoseDoor].delays[GEAR_UP].delay_ms = 750;
 gearParameters[sNoseDoor].delays[GEAR_DOWN].wait_ms = 6700;
 gearParameters[sNoseDoor].delays[GEAR_DOWN].delay_ms = 750;

 gearParameters[sMainGear].servoPin = 3;
 gearParameters[sMainGear].upPos_us = 800;
 gearParameters[sMainGear].downPos_us = 2200;
 gearParameters[sMainGear].delays[GEAR_UP].wait_ms = 100;
 gearParameters[sMainGear].delays[GEAR_UP].delay_ms = 5000;
 gearParameters[sMainGear].delays[GEAR_DOWN].wait_ms = 1000; // Wait for door to open
 gearParameters[sMainGear].delays[GEAR_DOWN].delay_ms = 5000;

 gearParameters[sMainDoor].servoPin = 5;
 gearParameters[sMainDoor].upPos_us = 800;
 gearParameters[sMainDoor].downPos_us = 2000;
 gearParameters[sMainDoor].delays[GEAR_UP].wait_ms = 5500;
 gearParameters[sMainDoor].delays[GEAR_UP].delay_ms = 750;
 gearParameters[sMainDoor].delays[GEAR_DOWN].wait_ms = 100;
 gearParameters[sMainDoor].delays[GEAR_DOWN].delay_ms = 750;


Here it is in action:

http://www.youtube.com/watch?v=VtJAJNm8W8k

I plan to add a swicth that tells Arduino if the gear is up to prevent damage if the switch on the TX is set to down and the gear is actually down or vice versa.

Downside: I cannot use the Decoding lib as I had hoped. The PPM signal of the Jeti R10, R14 or R18 is not sufficient. BTW it is also not sufficient to use it in the way Jeti intended it, that one RX can serve as a satellite in case of signal loss. I did some more investigation and observed the same behaviour: wild servo movements if the Sat signal from the other RX is used.

But I am totally happy that I stumbled into Ardino.

And thank you mem for your initial suppport  :)

Cheers Alexander
Title: Re: Decoding Radio Control signal pulses
Post by: mem on Jul 12, 2010, 01:40 pm
Looks good, can't wait to see a video of it installed in the DC-6.

I am curious why the PPM signal was unable to be decoded by Arduino. Do you have any technical information on the JETI PPM output (or a scope trace showing the voltage levels and timing)
Title: Re: Decoding Radio Control signal pulses
Post by: AlexanderB on Jul 12, 2010, 01:51 pm
Thank you mem. Well I guess you have to be patient.

If you're interestes please follow my build thread on rcgroups.com

http://www.rcgroups.com/forums/showthread.php?t=1116302&page=31#post15520864

Regarding the PPM signal. I don't have the electronic knowledge. That's why I use Arduino ;)

But to me it looks like a Problem on the Jeti Receiver. Another Jeti receiver isn't either capable to deal with the signal and shows the same weird behaviour of the servos when forcing it into signal loss.

I forwarded it to Jeti and let's see.

Cheers Alexander
Title: Re: Decoding Radio Control signal pulses
Post by: mem on Jul 12, 2010, 02:06 pm
I have subscribed to your rcgroups thread and will follow it with interest.

If you get any info from JETI (or if anyone else with one of those receivers has a scope) I will see if I can help get it working with the library.
Title: Re: Decoding Radio Control signal pulses
Post by: AlexanderB on Jul 12, 2010, 02:15 pm
Thank you for our interest!

I'll post information here if I find something on the Jeti issue.

Cheers Alexander
Title: Re: Decoding Radio Control signal pulses
Post by: MatrixGTI on Aug 19, 2010, 12:06 pm
Hi all,
It's my first post on this Forum  ;)
I start programming Arduino only few weeks ago.
My problem is use the ServoDecode Library to grab 7 ch from a modifyed Graupner RX.
The RX send the impulse train all toghether on one wire connected to digital pin of Arduino 2009.
I add Servodecode library to my sketch and I have this errors compiling the library: (also with the example sketch)

o: In function `__vector_13':
C:\DOCUME~1\ADMINI~1\IMPOST~1\Temp\build1989424199835515901.tmp/ServoDecode.cpp:45: multiple definition of `__vector_13'

C:\DOCUME~1\ADMINI~1\IMPOST~1\Temp\build1989424199835515901.tmp\ServoDecode\ServoDecode.cpp.o:D:\arduino-0018\arduino-0018\libraries\ServoDecode/ServoDecode.cpp:45: first defined here

o: In function `__vector_10':
C:\DOCUME~1\ADMINI~1\IMPOST~1\Temp\build1989424199835515901.tmp/ServoDecode.cpp:52: multiple definition of `__vector_10'

C:\DOCUME~1\ADMINI~1\IMPOST~1\Temp\build1989424199835515901.tmp\ServoDecode\ServoDecode.cpp.o:D:\arduino-0018\arduino-0018\libraries\ServoDecode/ServoDecode.cpp:52: first defined here

o: In function `__vector_13':
C:\DOCUME~1\ADMINI~1\IMPOST~1\Temp\build1989424199835515901.tmp/ServoDecode.cpp:45: multiple definition of `pulseEnd'

C:\DOCUME~1\ADMINI~1\IMPOST~1\Temp\build1989424199835515901.tmp\ServoDecode\ServoDecode.cpp.o:D:\arduino-0018\arduino-0018\libraries\

and many more.....

I'm running Arduino 018 with the library taken from the start of this thread.

Any help will be apreciated and sorry for my bad english  ;)
Title: Re: Decoding Radio Control signal pulses
Post by: mem on Aug 19, 2010, 01:55 pm
@MatrixGTI

are you sure you tried the code and the example sketch exactly as posted at the start of this thread? they compile okay for me using 0018
Title: Re: Decoding Radio Control signal pulses
Post by: MatrixGTI on Aug 19, 2010, 02:35 pm
@mem
I copy/past the code in the first page, maybe happend something during copy.  May I ask u the link of the library as file and not as code.
just to be sure of the file structure.

Thanks

Flavio
Title: Re: Decoding Radio Control signal pulses
Post by: mem on Aug 19, 2010, 03:18 pm
This forum does not have a mechanism to upload files but if you compare the beginning and end of the code you copied you should be able to see if there were any characters added or removed.
Title: Re: Decoding Radio Control signal pulses
Post by: MatrixGTI on Aug 19, 2010, 03:35 pm
Problem Solved... was my fault. the example file was in the same dir of the library.... moved away and now i'm able to read data from my 7 ch RX  :D

Just to save time in experiment what is the minum delay between two reading loops ? 20ms will be enaugh ?
Title: Re: Decoding Radio Control signal pulses
Post by: mem on Aug 19, 2010, 04:17 pm
The data is updated at the rate it comes in typically every 20ms. Each read turns interrupts off while getting the data so I would not read it more quickly  than every 10ms or so.  
Title: Re: Decoding Radio Control signal pulses
Post by: LukeZ on Oct 01, 2010, 11:53 pm
Vince and Mem, check here for a design that uses diodes to encode a PPM stream from individual servo pulses:
Title: Re: Decoding Radio Control signal pulses
Post by: LukeZ on Oct 01, 2010, 11:53 pm
Sorry, here is the link:

http://paparazzi.enac.fr/wiki/MeekPE_PPM_Encoder_Board
Title: Re: Decoding Radio Control signal pulses
Post by: Tweaked on Oct 24, 2010, 09:05 pm
mem,
I've been working with the Mega and this library interfaced with a Multiplex Profi 403 transmitter.  I ran the following sketch:
Code: [Select]
int pin = 49;  // set this to the pin connected to your receiver
unsigned long duration;

void setup()
{
 Serial.begin(9600);
 pinMode(pin, INPUT);
}

void loop()
{
 duration = pulseIn(pin, HIGH);
 Serial.println(duration);
 delay(250);
}
with the following result:
Code: [Select]
349
349
349
349
343
350
349
349
349
343
343
349
349
342
342
 the ppm signal appears to have a fixed mark and variable space, so I changed the sketch above to monitor the signal space instead with the following result:
Code: [Select]
646
646
1142
652
1136
1631
1142
652
1136
1632
1142
1632
1142
1632
 Adding the two together, it seems I'm sucessfully detecting anywhere from 997 to 1980ms pulses in the ppm signal.  Now that I'm confident I'm on the correct signal pin, I try the example sketch and get the following result:
Code: [Select]
The decoder is READY
Cx0= 5935  Cx1= 1936  Cx2= 2056  Cx3= 1131  Cx4= 1500  Cx5= 1500  Cx6= 1500  Cx7= 1500  
Ch1= 820  Ch2= 1823  Ch3= 1131  Ch4= 1500  Ch5= 1500  Ch6= 1500  Ch7= 1500  
The decoder is READY
Cx0= 7034  Cx1= 1040  Cx2= 2039  Cx3= 1131  Cx4= 1500  Cx5= 1500  Cx6= 1500  Cx7= 1500  
Ch1= 1590  Ch2= 2039  Ch3= 1131  Ch4= 1500  Ch5= 1500  Ch6= 1500  Ch7= 1500  
The decoder is READY
Cx0= 8133  Cx1= 1137  Cx2= 2139  Cx3= 1131  Cx4= 1500  Cx5= 1500  Cx6= 1500  Cx7= 1500  
Ch1= 1686  Ch2= 2023  Ch3= 1131  Ch4= 1500  Ch5= 1500  Ch6= 1500  Ch7= 1500  
The decoder is READY
Cx0= 9232  Cx1= 767  Cx2= 2236  Cx3= 1131  Cx4= 1500  Cx5= 1500  Cx6= 1500  Cx7= 1500  
Ch1= 1317  Ch2= 2123  Ch3= 1131  Ch4= 1500  Ch5= 1500  Ch6= 1500  Ch7= 1500  
Ch1= 1866  Ch2= 2006  Ch3= 1131  Ch4= 1500  Ch5= 1500  Ch6= 1500  Ch7= 1500  
The decoder is READY
Cx0= 7884  Cx1= 917  Cx2= 2219  Cx3= 1131  Cx4= 1500  Cx5= 1500  Cx6= 1500  Cx7= 1500  
Ch1= 1466  Ch2= 1990  Ch3= 1131  Ch4= 1500  Ch5= 1500  Ch6= 1500  Ch7= 1500  
The decoder is READY
Cx0= 8983  Cx1= 2016  Cx2= 1990  Cx3= 1131  Cx4= 1500  Cx5= 1500  Cx6= 1500  Cx7= 1500  
Ch1= 2086  Ch2= 1990  Ch3= 1131  Ch4= 1500  Ch5= 1500  Ch6= 1500  Ch7= 1500  
Ch1= 1450  Ch2= 1973  Ch3= 1131  Ch4= 1500  Ch5= 1500  Ch6= 1500  Ch7= 1500  
The decoder is READY
Cx0= 6631  Cx1= 1190  Cx2= 1973  Cx3= 1131  Cx4= 1500  Cx5= 1500  Cx6= 1500  Cx7= 1500  
Ch1= 1740  Ch2= 1973  Ch3= 1131  Ch4= 1500  Ch5= 1500  Ch6= 1500  Ch7= 1500  
The decoder is in Failsafe
Cx0= 8733  Cx1= 1287  Cx2= 1956  Cx3= 1131  Cx4= 1500  Cx5= 1500  Cx6= 1500  Cx7= 1500  
Ch1= 1836  Ch2= 1956  Ch3= 1131  Ch4= 1500  Ch5= 1500  Ch6= 1500  Ch7= 1500  
The decoder is READY
Cx0= 9832  Cx1= 1723  Cx2= 1956  Cx3= 1131  Cx4= 1500  Cx5= 1500  Cx6= 1500  Cx7= 1500  
Ch1= 941  Ch2= 1940  Ch3= 1131  Ch4= 1500  Ch5= 1500  Ch6= 1500  Ch7= 1500  
The decoder is READY
Cx0= 9928  Cx1= 1490  Cx2= 1940  Cx3= 1131  Cx4= 1500  Cx5= 1500  Cx6= 1500  Cx7= 1500  
Ch1= 1037  Ch2= 2040  Ch3= 1131  Ch4= 1500  Ch5= 1500  Ch6= 1500  Ch7= 1500  
The decoder is READY
Cx0= 11027  Cx1= 808  Cx2= 1923  Cx3= 1131  Cx4= 1500  Cx5= 1500  Cx6= 1500  Cx7= 1500  
Ch1= 1357  Ch2= 1923  Ch3= 1131  Ch4= 1500  Ch5= 1500  Ch6= 1500  Ch7= 1500  
The decoder is READY
Cx0= 12126  Cx1= 904  Cx2= 1907  Cx3= 1131  Cx4= 1500  Cx5= 1500  Cx6= 1500  Cx7= 1500  
Ch1= 1453  Ch2= 2240  Ch3= 1131  Ch4= 1500  Ch5= 1500  Ch6= 1500  Ch7= 1500  
The decoder is in Failsafe
Cx0= 13225  Cx1= 2003  Cx2= 2240  Cx3= 1131  Cx4= 1500  Cx5= 1500  Cx6= 1500  Cx7= 1237  
Ch1= 1367  Ch2= 1890  Ch3= 1131  Ch4= 1500  Ch5= 1500  Ch6= 1500  Ch7= 1500  
 The transmitter is 7 channel with a 25ms ppm signal period.

Any insight why the above is happening?

Thanks in advance,
Billy
Title: Re: Decoding Radio Control signal pulses
Post by: Tweaked on Oct 25, 2010, 03:22 am
Good news: It's working!  Bad news: No 'smoking gun' to explain the results of my previous post.  During troubleshooting, I reduced the delay from 500ms to 50ms and Voila!  Oddly enough, I changed the delay back to 500ms and the library continued to function properly.  I seem to recall another poster in this thread having a similar experience...

Regardless, the library is now fully functional in my application!  Now onto the next step of manipulating the servo signals and encoding back into a ppm stream, but that belongs in another thread.

Thanks for a great library, mem!!!
Title: Re: Decoding Radio Control signal pulses
Post by: mem on Oct 25, 2010, 11:57 am
Good to hear you have it working. I can't shed any light on what happened, I have not experienced anything similar.
Title: Re: Decoding Radio Control signal pulses
Post by: gmv on Dec 08, 2010, 12:07 pm
@ mem.

Is it possible for you to make some changes on the servoDecode lib in order that we could use Timer2 as well and thus decoding frames with more than 8 servos, i´ll  not need to drive any servo, only need to see each pulse width on the screen.
Since it uses Timer1 and servoTimer2 is free i think it could be used for this purpose (ex: 12 channels).

again, thanks mem and sorry to make too many questions.  :-/

 GMV
Title: Re: Decoding Radio Control signal pulses
Post by: mem on Dec 08, 2010, 03:07 pm
@GMV
ServoDecode uses a capability within 16 bit timers to time pulse durations entirely in hardware. This enables very accurate measurements but it does require a 16 bit timer . A standard Arduino only has one of these -  Timer0 and Timer2 are 8 bit timers and do not have the capability needed by ServoDecode.
Title: Re: Decoding Radio Control signal pulses
Post by: gmv on Dec 08, 2010, 03:38 pm
right again, so do you think it can be done with 2 x atmega 168/328, i ask this because at the moment i use my own ATM168 Pcb and i would like to use the MEGA board for other applications but since it seems very difficult to implent such task perhaps ordering another MEGA wouldn´t be a bad ideia.

Do you have any ServoDecode type lib that use more than one 16bit timer and could be used with the Mega board for decode more than 8 servos ? thanks

GMV
Title: Re: Decoding Radio Control signal pulses
Post by: mem on Dec 08, 2010, 04:17 pm
If your transmitter sends more than 8 channels you can set the constant MAX_CHANNELS to the appropriate value.

If you want to decode output from two transmitter/receivers using one mega board then the code in post #70 could be modified to add support for timer5 which would provide another 8 channels. Unfortunately I don't have the time to do this. Perhaps someone else reading this thread could pick this up, although using two ATmega328 boards the cheaper option.
Title: Re: Decoding Radio Control signal pulses
Post by: gmv on Dec 09, 2010, 10:54 am
mem, thanks !!!  ;)

GMV
Title: Re: Decoding Radio Control signal pulses
Post by: NCSANTOS on Jan 06, 2011, 01:40 am
Im tring to use a gyroscope that send the angle in signal for arduino so I have dificult to comunicate with this system.
the especification from WWW.parallax.com at LISY300  information is
The LISY300 Gyroscope Module is a single-axis yaw rate sensor providing up to 300°/s full scale rotation detection at up to 88 Hz. Useful in balancing robots or auto-pilot systems, the LISY300 Gyroscope Module can detect how many degrees it has turned on its planar axis allowing the host microcontroller to stabilize the platform or correct for drift.

Features:

   * ± 300°/s full scale
   * Easy SPI interface
   * Small DIP form factor

Application Ideas:

   * R/C Helicopter stabilization
   * Auto-pilot system for R/C airplanes
   * Balancing robot

Key Specifications:

   * Power requirements: 3.4 VDC to 6.5 VDC (5 VDC recommended) @ 5.25 mA
   * Communication: SPI (4 MHz max)
   * Dimensions: 0.75 x 0.69 x 0.47 in (19.18 x 17.56 x 11.95 mm)
   * Operating temp range: +32°F to +158°F (0°C to +70°C)

Any body can help-me ? since the  forum have decoding radio contrl signal pulse
Nilo
Title: Re: Decoding Radio Control signal pulses
Post by: x-sven on Jan 07, 2011, 10:19 pm
Hi, I was  really happy to find a lot of hints in this thread to decoding the PPM-Stream of my receiver. I thank you all and would like to give some experience back to the community...


My first observation was some inconsistency of numbering the channels. From [font=Courier]ServoDecode.cpp[/font] we can find out that the servo are counted from 1 to a number defined by MAX_CHANNELS:

[font=Courier]for(byte chan = 1; chan <=  MAX_CHANNELS; chan++)[/font]

...but, in the test sketch on page 3 the first for-statement start's at zero. So watch out and use the right numbering!

Moreover, the comparison of an older and a newer version by Beebee on page 9 of the "ISR(TIMER1_CAPT_vect)" function indicates an issue with the "else if"-statement.

The first (11-06-08):
[font=Courier]else if(Channel <= MAX_CHANNELS) { ... [/font]
The second (21-07-08):
[font=Courier]else if(Channel < MAX_CHANNELS) {  ...[/font]

The declaration of "Channel" :

[font=Courier]static volatile byte Channel;   // number of channels detected so far in the frame (first channel is 1)[/font],

indicates it goes from one to MAX, but at some points its reset to zero. Due to the pre-increment (Pulses[++Channel] =...) it seems not to make a difference, but it may be misleading this way... And I'm not sure about the "else if"-statemant (from above). I selected to let Channel start from zero (because I'm more used to it) and changed the code accordingly...



I'm using a DIY-Drones ARDUIMU to decode the PPM-stream. This board has only the digital-I/Os 10...13 (=PB2...PB5) accessible. Therefore, I have to use on of these pins. Instead of using the TIMER0 CAPT ISR the PCINT0 is used to measure the puls width. It's my first ISR so I hope I did it right, at least - it works for me ;-)

Code: [Select]

static volatile unsigned int tics;  // holds tics from Timer1
...

ISR(PCINT0_vect)
{

 tics = TCNT1;   /* Read TCNT1 */
 
 if ( LOW == digitalRead(PPM_PIN) ) //End of channel
 {
   TCNT1 = 0;   //Reset Timer1
   if(tics >= SYNC_GAP_LEN){   // is the space between pulses big enough to be the SYNC
       processSync();
   }
   else if(Channel < MAX_CHANNELS) {  // check if its a valid channel pulse and save it
       if( (tics >= MIN_IN_PULSE_WIDTH)  && (tics <= MAX_IN_PULSE_WIDTH) ){ // check for valid channel data
         Pulses[Channel++] = tics / TICKS_PER_uS;  // store pulse length as microsoeconds
       }
       else if(State == READY_state){
         State = FAILSAFE_state;  // use fail safe values if input data invalid
         Channel = 0; // reset the channel count
       } //ELSE IF
   } //ELSE IF
 } //IF
} //ISR


The PPM-signal is connected to PIN 10. The PORTB pin change interrupt is activated by

Code: [Select]

 PCMSK0  = (1<<PCINT2);  //Un-mask PCINT2
 PCICR   = (1<<PCIE0);   //Enable the PORTB pin change interrupt




Last minor issue: Sometimes, when I connect the receiver and without activating the transmitter first, the state stays in "no_sync". Then, the ppm-signal remains at zero. But, this is not valid (e.g. when directly given to a servo). I like to have signals between MIN_IN_PULSE_WIDTH and MAX_IN_PULSE_WIDTH. Therefore, I've changed the "GetChannelPulseWidth( )"-method to give the failsafe values...

Code: [Select]

int ServoDecodeClass::GetChannelPulseWidth( uint8_t channel)
{
 // this is the access function for channel data
 int result = 0; // default value
 if( channel <  MAX_CHANNELS)  {
    if( ((State == FAILSAFE_state) || (State == NOT_SYNCHED_state)) && (Failsafe[channel] > 0 ) )
          result = Failsafe[channel]; // return the channels failsafe value if set and State is Failsafe
    else if( (State == READY_state) || (State == FAILSAFE_state) )
    {
       cli();        //disable interrupts
       result =  Pulses[channel] ;  // return the last valid pulse width for this channel
       sei(); // enable interrupts
    }
 }
 return result;
}


I hope this helps somebody!? Best regards,
Sven