Shop our Airplanes Products Shop our Surface Products
Thread Tools
Old Nov 15, 2013, 03:50 PM
comode is offline
Find More Posts by comode
No fun above tree level
comode's Avatar
Joined Jan 2012
39 Posts
Data
[DIY][Arduino] joystick to PPM

Hello,

I made this 6 moth ago :

ppm signal from an arduino and an old joystick (0 min 43 sec)


It was based on an arduino sketch that converted potentiometers positions into PPM signal. Each potentiometer's center pin must be connected to an A0-A5 arduino's pin, one pin on +5v and the last one on ground.

I just rewrited the source code, so i'd like to share it :

Code:
#define NB_WAY 6 // number of ways
#define LOW_LENGTH 300 // How long last (in s) a low between 2 pulses
#define MIN_PPM_PULSE 1300 // minimum pulse length in s
#define PPM_PULSE_LENGTH 700 // how much more s will last the max pulse length
#define PACKET_LENGTH 21000 // How long (s) last a full trame

// trame length is fixed ! Every trame will make PACKET_LENGTH s !
// MUST NO BE MORE THAN 32ms !!! (timer's prescaler constraint)

#define PPM_OUTPUT 13 // OUTPUT PIN

int way_value[NB_WAY];
int way_pin[NB_WAY];
int way_min[NB_WAY];
int way_max[NB_WAY];

int i = 0;
int p = 0; // temp var for duty cycle calculation
int last_i_timer = 0; // last way's value sent through PPM signal
unsigned long int trame_elapsed_time = 0;
bool output_state = LOW;

void setup() {
  // ppm output :
  pinMode(PPM_OUTPUT, OUTPUT);
  digitalWrite(PPM_OUTPUT, output_state);
  
  // inits arrays
  for(i=0;i<NB_WAY;i++)
  {
    way_pin[i] = 14 + i;
    pinMode(way_pin[i], INPUT);
    way_value[i] = analogRead(way_pin[i]);
    way_min[i] = way_value[i];
    way_max[i] = way_value[i];
  }

  // init timer
  cli();          // desactivation interruptions
  TCCR1A = 0x00;  // set timer1 registers to 0
  TCCR1B = 0x00;     
  TIMSK1 = 0x00;
    
  OCR1A = 65535;// set to the max
    // CTC mode:
  TCCR1B |= (1 << WGM12);
    // prescaler to 8, that allow (@16mhz) 32.8ms trame
  TCCR1B |= (0 << CS10);
  TCCR1B |= (1 << CS11);
  TCCR1B |= (0 << CS12);
    // timer activation
  TIMSK1 |= (1 << OCIE1A);
  sei();
}

ISR(TIMER1_COMPA_vect)
{
  TIMSK1 &= (0 << OCIE1A);
  if(output_state)
  { // END OF A HIGH, we have to wait LOW_LENGTH ms before next pulse 
    output_state = LOW;
    digitalWrite(PPM_OUTPUT, output_state);
    OCR1A = 2 * LOW_LENGTH; // set when next timer interruption will occur
    TIMSK1 |= (1 << OCIE1A);  // restart timer
    trame_elapsed_time += LOW_LENGTH;
  }
  else
  { // END of a LOW_LENGTH, new pulse !
    output_state = HIGH;
    digitalWrite(PPM_OUTPUT, output_state);
    if(last_i_timer >= NB_WAY) // last way, so wait until next packet
    {
      OCR1A = (2 * PACKET_LENGTH) - (trame_elapsed_time * 2);// set when next timer interruption will occur
      TIMSK1 |= (1 << OCIE1A); // restart timer
      last_i_timer = 0;
      trame_elapsed_time = 0; 
    }
    else
    {
      OCR1A = 2 * way_value[last_i_timer];// set when next timer interruption will occur
      TIMSK1 |= (1 << OCIE1A); // restart timer
      last_i_timer ++;
      trame_elapsed_time += way_value[NB_WAY];
    }
  }  
}


void loop() {

  for(i=0;i<NB_WAY;i++)
  {
     // Read current value of way i :
     p = analogRead(way_pin[i]);
     
     // auto calibration...
     if(p > way_max[i]) way_max[i] = p;
     if(p < way_min[i]) way_min[i] = p;
     
     // Arduino map function sucks
      way_value[i] = MIN_PPM_PULSE + PPM_PULSE_LENGTH * (float)((float)(p - way_min[i]) / (float)(way_max[i] - way_min[i]));
  }
}
This's really nothing special, but i though it could be some help for people who'd like to do something like this.
comode is offline Find More Posts by comode
Reply With Quote
Sign up now
to remove ads between posts
Old Mar 30, 2014, 09:34 PM
Skystream is offline
Find More Posts by Skystream
Registered User
Joined Dec 2012
120 Posts
This code was actually really helpful, thanks. I had tried some somewhat similar code by Hasi but just couldn't get it to work right. The timing was off and the servos were jittery as heck. This code works perfectly and no servo jitter. Driving the PPM radio module directly that I removed from the HobbyKing 6CH 2.4Ghz transmitter for a custom RC ship transmitter. Thanks again for posting this.
Skystream is offline Find More Posts by Skystream
Reply With Quote
Old Apr 04, 2014, 09:13 AM
whimsical is offline
Find More Posts by whimsical
Registered User
Australia, WA, O'Connor
Joined Jan 2014
197 Posts
I did the same but a bit more complex. Input 2 PPM streams and combine with some local switches and output the required channels to a 3rd stream.
The Teensy library makes it super simple to mix and add channels
http://www.pjrc.com/teensy/td_libs_PulsePosition.html
whimsical is offline Find More Posts by whimsical
Reply With Quote
Old Apr 25, 2014, 02:55 AM
kareemashry is offline
Find More Posts by kareemashry
Registered User
Joined Dec 2013
5 Posts
Man you just give me hope in this issue i was going to forget about this idea. okay i've dragon link V2 and i connected with Mike from the support team and he told me there's no way to do that as long as the joystick will never give a PPM signal. now please tell me the part number for this board and how i can program it i'm not so familiar with this things
kareemashry is offline Find More Posts by kareemashry
Reply With Quote
Old Apr 25, 2014, 06:27 AM
whimsical is offline
Find More Posts by whimsical
Registered User
Australia, WA, O'Connor
Joined Jan 2014
197 Posts
Are you looking for the Teensy or the Arduino
Teensy
http://www.pjrc.com/store/teensy31.html
Teensy forum, i started a thread there about the PPM stream
http://forum.pjrc.com/threads/25265-Arduino-RC-library
I posted my mixer and code here at RCGroups
http://www.rcgroups.com/forums/showthread.php?t=2131278
I am waiting for a couple of things then i will finish my install inside a Taranis With 6 push buttons for APM and some extra switches and pots.
The pulse position library makes the code quite trivial to do. I will have a play with the joystick when i get the Taranis back together. I added 2 inputs for PPM streams so ez to add the joystick.

Mike
whimsical is offline Find More Posts by whimsical
Reply With Quote
Old Sep 06, 2014, 10:50 PM
ramdak is offline
Find More Posts by ramdak
Registered User
Joined Dec 2013
2 Posts
Quote:
Originally Posted by Skystream View Post
This code was actually really helpful, thanks. I had tried some somewhat similar code by Hasi but just couldn't get it to work right. The timing was off and the servos were jittery as heck. This code works perfectly and no servo jitter. Driving the PPM radio module directly that I removed from the HobbyKing 6CH 2.4Ghz transmitter for a custom RC ship transmitter. Thanks again for posting this.
Would you please post or send me a photo of your setup? I'm trying the same.
Thanks!
ramdak is offline Find More Posts by ramdak
Reply With Quote
Old Nov 10, 2014, 09:13 AM
Davincescu is offline
Find More Posts by Davincescu
Registered User
Joined Jun 2010
12 Posts
Hi all

I tried to simulate the above code in Proteus, but not working.
Can anyone help me?
Davincescu is offline Find More Posts by Davincescu
Reply With Quote
Old Nov 14, 2014, 11:39 AM
comode is offline
Find More Posts by comode
No fun above tree level
comode's Avatar
Joined Jan 2012
39 Posts
I don't know Proteus and never tried to simulate anything (i'm a noob), so i can't tell.

However, this code need calibration at each lauch (or you need to add some lines to save calibration datas). Calibration is done my making circle with the joystick (going from min to max value on each axis) after power on. Do you did it when simulating ?

The board i used for dev was arduino Uno R3, but it should work with any atmega-328 based boards. The final product is a homemade board.
comode is offline Find More Posts by comode
Reply With Quote
Old Nov 14, 2014, 12:09 PM
Davincescu is offline
Find More Posts by Davincescu
Registered User
Joined Jun 2010
12 Posts
I use arduino nano v3, atmega 328p, you can change the code to autocalibrate?
Davincescu is offline Find More Posts by Davincescu
Reply With Quote
Old Nov 14, 2014, 02:43 PM
comode is offline
Find More Posts by comode
No fun above tree level
comode's Avatar
Joined Jan 2012
39 Posts
Calibration is needed in real life.
But for testing purpose, you can add those lines at the end of the setup() :

Code:
for(i=0;i<NB_WAY;i++)
  {
    way_min[i] = 512;
    way_max[i] = 1023;
  }
It will calibrate your potentiometers as if they where perfect (mean they will output from 2.5V to 5V).
comode is offline Find More Posts by comode
Reply With Quote
Old Nov 14, 2014, 03:38 PM
Davincescu is offline
Find More Posts by Davincescu
Registered User
Joined Jun 2010
12 Posts
Tanks comode

Not just for the tests, I want to build it.

But for testing purpose, you can add those lines at the end of the setup() : ??? where exactly?
Davincescu is offline Find More Posts by Davincescu
Reply With Quote
Old Nov 17, 2014, 12:16 PM
comode is offline
Find More Posts by comode
No fun above tree level
comode's Avatar
Joined Jan 2012
39 Posts
Exactly at the end of the setup...

Code:
void setup() {
  // ppm output :
  pinMode(PPM_OUTPUT, OUTPUT);
  digitalWrite(PPM_OUTPUT, output_state);
  
  // inits arrays
  for(i=0;i<NB_WAY;i++)
  {
    way_pin[i] = 14 + i;
    pinMode(way_pin[i], INPUT);
    way_value[i] = analogRead(way_pin[i]);
    way_min[i] = way_value[i];
    way_max[i] = way_value[i];
  }

  // init timer
  cli();          // desactivation interruptions
  TCCR1A = 0x00;  // set timer1 registers to 0
  TCCR1B = 0x00;     
  TIMSK1 = 0x00;
    
  OCR1A = 65535;// set to the max
    // CTC mode:
  TCCR1B |= (1 << WGM12);
    // prescaler to 8, that allow (@16mhz) 32.8ms trame
  TCCR1B |= (0 << CS10);
  TCCR1B |= (1 << CS11);
  TCCR1B |= (0 << CS12);
    // timer activation
  TIMSK1 |= (1 << OCIE1A);
  sei();

// here you add the lines !!!!

}
comode is offline Find More Posts by comode
Reply With Quote
Old Apr 12, 2015, 09:04 AM
Thomas.b is offline
Find More Posts by Thomas.b
Registered User
Sweden, Stockholms ln, Stockholm
Joined Mar 2015
24 Posts
Hello Does this code need any changing for arduino pro mini 3,3v 8mhz
Thomas.b is offline Find More Posts by Thomas.b
Reply With Quote
Old Jun 07, 2015, 09:21 PM
comode is offline
Find More Posts by comode
No fun above tree level
comode's Avatar
Joined Jan 2012
39 Posts
Quote:
Originally Posted by Thomas.b View Post
Hello Does this code need any changing for arduino pro mini 3,3v 8mhz
Yes :

1 - the timer is based on the MCU frequency. At 8Mhz, you have to change the prescaler from 8 to 4...

2 - the output will be 3.3V... PPM is 5V.
comode is offline Find More Posts by comode
Reply With Quote
Old Jun 13, 2015, 12:13 PM
Burakko is offline
Find More Posts by Burakko
Registered User
Burakko's Avatar
Joined Aug 2012
136 Posts
You can add 4 switches as trimmers ? I do not know C only Bascom.
Burakko is offline Find More Posts by Burakko
Reply With Quote


Thread Tools

Similar Threads
Category Thread Thread Starter Forum Replies Last Post
Question PPM to TX problem with arduino generated PPM Nase DIY Electronics 65 Jul 22, 2016 06:42 PM
Discussion Arduino ppm signal reader and generator Hasi DIY Electronics 150 Jun 07, 2016 07:54 AM
Idea One more Joystick project, or smart USB -> PPM converter. Tahorg DIY Electronics 59 Apr 11, 2016 07:39 AM
Cool Inexpensive MultiWii IMU for Dragon OSD V2 (Arduino DIY!) Hawkeye2 FPV Equipment 41 Sep 11, 2015 02:21 PM
Discussion DIY PPM generator PPM reader and PPM expander Dennis Frie FPV Talk 62 Dec 09, 2014 04:07 AM