PPM and Joystick optimisation

Status
Not open for further replies.

Garug

Well-known member
I am making RC simulator toggle that receives PPM from RC transmitter and outputs joystick to RC simulator.

The first and very fast version was this, and it works good, but has 150 ms latency from moving the stick before the controls move on computer screen, so not great.

Here is some latency testing. The LED lights based on PPM value as seen on code.

https://vimeo.com/475858573
https://vimeo.com/475870685

#include <PulsePosition.h>
float PPM[14];
float PPMvalue;
int16_t JSTvalue[14];

PulsePositionInput PPMin(RISING);

// When receiving, any time between rising edges longer than this will be
// treated as the end-of-frame marker.
#define RX_MINIMUM_SPACE 500.0

void setup() {
PPMin.begin(9);
pinMode(13, OUTPUT);
}

void loop() {


if(PPMin.available()==8){
for ( uint8_t n = 1; n < 9; n++) {
PPMvalue = PPMin.read(n) ;
if (PPMvalue > 1) PPM[n] = PPMvalue ;
JSTvalue[n] = round(PPM[n]- 988.0) ;
if ( JSTvalue[n] < 0) JSTvalue[n] = 0 ;
if ( JSTvalue[n] > 1023) JSTvalue[n] = 1023 ;

}

if(JSTvalue[1] < 900) digitalWrite(13,true); else digitalWrite(13,false);

Joystick.X(JSTvalue[1]); // "value" is from 0 to 1023
Joystick.Y(JSTvalue[2]); // 512 is resting position
Joystick.Z(JSTvalue[3]);
Joystick.Zrotate(JSTvalue[4]);
Joystick.sliderLeft(JSTvalue[5]);
Joystick.sliderRight(JSTvalue[6]);
if(JSTvalue[7] > 700) Joystick.button(1, 1); else Joystick.button(1, 0);
if(JSTvalue[7] < 300) Joystick.button(2, 1); else Joystick.button(2, 0);
if(JSTvalue[8] > 700) Joystick.button(3, 1); else Joystick.button(3, 0);
if(JSTvalue[8] < 300) Joystick.button(4, 1); else Joystick.button(4, 0);


}
}

Since that I made it so that Joystick is send only if values have changed and they are all send at the end using

if (JSTupdates > 0) Joystick.send_now();

And the latency seems to be better now (did not measure yet, could be jus me imagine.)

The unclear part for me regarding joystick is what does the Joystick message contain. i.e. if only Joystick.X(JSTvalue[1]); was called before Joystick.send_now(); will that message contain the structures only for Joystick.X or anyway all the values?

Is there some steps I could still take to reduce the latency regarding joystick messages?

Now I am looking into optimising PPM

myInput.available(); it says "Returns the number of channels recieved, or zero when no new data is available. "

But it seems it returns -1 or the total number of channels. In this case 8. So it seems it waits for the complete PPM message to be ready before updating. How ever PPM message is long. 22.5 ms according to this http://www.mftech.de/ppm_en.htm

I would like to access each channel as soon as that channel has been decoded from PPM. Is that possible?
 
Last edited:
I tried polling the PPM once in ms (all but the last channel). It seems all channels are updated only after the hole PPM is received. There is a PPM message every 22 ms. Some 20 ms could be saved on the latency if the PPM channel values could be read right after they have arrived, not after they have all arrived.

However the bigger latency seems to be on Joystick. This is with iPhone 7 so I think it is about 10 x reduced speed. You can see the 100 Hz flashing of 50 Hz AC.

https://vimeo.com/499546075

This is not as bad as it looks, flying with it is pretty ok, but would like to get it as good as possible. The PPM signal is remarkably clear, there is no noise on the signals.The problem is just the latency.

Note, this is with Teensy 3.2
 
Last edited:
The RAW HID has all kind of control that the Joystick seem to lack?

The USB host controller will reserve bandwidth for your device. You can configure how much bandwidth by adjusting the packet size and the number of milliseconds between packets.

#define RAWHID_TX_SIZE 64 // transmit packet size
#define RAWHID_TX_INTERVAL 2 // max # of ms between transmit packets
#define RAWHID_RX_SIZE 64 // receive packet size
#define RAWHID_RX_INTERVAL 8 // max # of ms between receive packets

How difficult would it be to make the Joystick functionality with RAW HID, could some one point to some good example. This would be good also for making more analogue channels than the now available 6.

Regarding the joystick, where are those libraries to see and modify. My finder does not find usb_desc.c etc.
 
Last edited:
I found the usb_desc files on GitHub. Still do not know where the are on my Mac Big Sur and how to access them.

Anyway, this looks promising, is there any description what these are, expesially NUM_USB_BUFFERS 20, what it affects? could I just reduce it this have less potential delay. Is there someway to know how much space on buffer, or better something like clear buffer (flush). It is no use to buffer the old values. it always should send the latest only.

#elif defined(USB_FLIGHTSIM_JOYSTICK)
#define VENDOR_ID 0x16C0
#define PRODUCT_ID 0x0488
#define BCD_DEVICE 0x0211
#define MANUFACTURER_NAME {'T','e','e','n','s','y','d','u','i','n','o'}
#define MANUFACTURER_NAME_LEN 11
#define PRODUCT_NAME {'T','e','e','n','s','y',' ','F','l','i','g','h','t',' ','S','i','m',' ','C','o','n','t','r','o','l','s'}
#define PRODUCT_NAME_LEN 26
#define EP0_SIZE 64
#define NUM_ENDPOINTS 5
#define NUM_USB_BUFFERS 20
#define NUM_INTERFACE 3
#define FLIGHTSIM_INTERFACE 0 // Flight Sim Control
#define FLIGHTSIM_TX_ENDPOINT 3
#define FLIGHTSIM_TX_SIZE 64
#define FLIGHTSIM_TX_INTERVAL 1
#define FLIGHTSIM_RX_ENDPOINT 4
#define FLIGHTSIM_RX_SIZE 64
#define FLIGHTSIM_RX_INTERVAL 1
#define SEREMU_INTERFACE 1 // Serial emulation
#define SEREMU_TX_ENDPOINT 1
#define SEREMU_TX_SIZE 64
#define SEREMU_TX_INTERVAL 1
#define SEREMU_RX_ENDPOINT 2
#define SEREMU_RX_SIZE 32
#define SEREMU_RX_INTERVAL 2
#define JOYSTICK_INTERFACE 2 // Joystick
#define JOYSTICK_ENDPOINT 5
#define JOYSTICK_SIZE 12 // 12 = normal, 64 = extreme joystick
#define JOYSTICK_INTERVAL 1
#define ENDPOINT1_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_ONLY
#define ENDPOINT3_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT4_CONFIG ENDPOINT_RECEIVE_ONLY
#define ENDPOINT5_CONFIG ENDPOINT_TRANSMIT_ONLY
 
Anyone?

I tried also teensy 4.0. when connected to USB 3 it is just slightly faster than teensy 3.2 , I did not yet try changing the usb_desc.c

I would imagine there would be some interested to optimise the joystick latency. Or is it already optimised as good as it gets?
 
Status
Not open for further replies.
Back
Top