Pages: 1 ... 10 11 [12]   Go Down
Author Topic: Decoding Radio Control signal pulses  (Read 34080 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Newbie
*
Karma: 0
Posts: 16
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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!!!
Logged

London
Offline Offline
Tesla Member
***
Karma: 10
Posts: 6255
Have fun!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Good to hear you have it working. I can't shed any light on what happened, I have not experienced anything similar.
Logged

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 52
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

@ 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
« Last Edit: December 08, 2010, 06:07:44 am by gmv » Logged

London
Offline Offline
Tesla Member
***
Karma: 10
Posts: 6255
Have fun!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

@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.
Logged

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 52
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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
Logged

London
Offline Offline
Tesla Member
***
Karma: 10
Posts: 6255
Have fun!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 52
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

mem, thanks !!!  smiley-wink

GMV
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 1
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 1
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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 ServoDecode.cpp we can find out that the servo are counted from 1 to a number defined by MAX_CHANNELS:

for(byte chan = 1; chan <=  MAX_CHANNELS; chan++)

...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):
else if(Channel <= MAX_CHANNELS) { ...
 The second (21-07-08):
else if(Channel < MAX_CHANNELS) {  ...

The declaration of "Channel" :

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

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:
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:
 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:
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
« Last Edit: January 08, 2011, 02:46:13 am by x-sven » Logged

Pages: 1 ... 10 11 [12]   Go Up
Jump to: