Frsky bidirectional telemetry implementation

No, that’s not possible, this project is about a basic OpenTX based lua GCS.

1 Like

Good morning Alex,nice work on your presentation to the AP Developers conference. The video includes all the information I need. Is it possible to get a copy of the slides? Or maybe you could publish the docs?

Hi Eric, thanks,
I realized I never published the video, so here it is

and here’s the link to the slides

let me know if you need lua scripts to test the implementation.



Thanks Alex. Yes I likely will need the lua source, if that’s possible.

sure Eric, sources are on github

1 Like

Alex, sorry to ask such a basic question. How do I easily stop your regular lua script from running? Also, when I execute yaapu GCS.lua I get this:


I know its me, but what?

Ok, I seem to have it working.

ok good!
In case anybody else wonders, the lua gcs script has to be run as a one time script by browsing to the SD card and choosing execute, while one time scripts run all other lua scripts are paused, so to answer your question when you launch it it will automatically pause my telemetry script.
This is true on Horus/T16 as well, all widgets are paused when a one time script runs

Hi Alex,

I’m being a bit lazy :wink: , but exactly what does this mean?


Hi Eric,
the script waits for the frame type parameter from passthrough and for planes only asks for the Q_PLANE parameter using bidirectional telemetry.
If you’r using my ardupilot branch and is hanging there your receiver firmware does not fully support bidirectional telemetry.

Perfect. Thanks Alex.

Could you please email me directly eric at zs6buj do com. Not urgent.

I installed the LUA extension for VSCode. Looks ok.

the lua script waits for DIY packet 0x5007 to get the frame type.
If it’s a plane it also sends an uplink “PARAM_REQUEST_READ” to get the value for Q_PLANE.
It uses frame type and Q_PLANE to select which pages to show.
In your case if its hanging at “detecting vehicle” it’s either waiting for 0x5007 (all frame types) or after getting 0x5007 for a plane is trying to send a param request read for Q_PLANE.

perfect, thanks Alex. Could you please email me when you get a chance. eric at zs6buj dot com

Alex, I’m busy with this right now and hoping you can help. Here is my debugging information:

I receive a parameter request from your Yaapu GCS:

MavLite #20 Param_Request_Read :ATC_RAT_RLL_P:

Send a request to the FC:

Sending to FC: MavLINK #20 Param_Request_Read :ATC_RAT_RLL_P:

Get an answer back from the FC:

Mavlink return from FC #22 Param_Value for MavLITE: ap_param_id=ATC_RAT_RLL_P ap_param_value=0.135

Create a full size message:

PackMavLiteParamValue16 msg_id=0x16 lth=20 param_value=0.135 param_id=ATC_RAT_RLL_P

which looks like this in the raw:

mliteMsg=|16 14 |00 00 71 3D |0A 3E 41 54 43 5F |52 41 54 5F 52 4C |4C 5F 50 00 |Crc=EE | q=>ATC_RAT_RLL_P|

now start chunking and sending 6 Byte frames and push them onto scheduler stack (with all the other (passthru) downlink frames);

Chunk 1 / seq= 0

Push row= 2 msg_id=0x16 sub_id= 0 MavLite payload 71>00>00>14>16>00> q

Chunk 2

Push row= 3 msg_id=0x16 sub_id= 0 MavLite payload 54>41>3E>0A>3D>01> TA>=

Chunk 3

Push row= 13 msg_id=0x16 sub_id= 0 MavLite payload 54>41>52>5F>43>02> TAR_C

Chunk 4

Push row= 14 msg_id=0x16 sub_id= 0 MavLite payload 5F>4C>4C>52>5F>03> LLR

Chunk 5 seq=4

Push row= 15 msg_id=0x16 sub_id= 0 MavLite payload 00>00>EE>00>50>04> P

wait for uplink bytes 7E<1B, and pop the chunks and send them

Pop  row=   2  msg_id=0x16   sub_id=  0 MavLite payload 71>00>00>14>16>00>|q|  age=590 mS |

Pop  row=   3  msg_id=0x16   sub_id=  0 MavLite payload 54>41>3E>0A>3D>01>|TA>=|  age=592 mS |

Pop  row=  13  msg_id=0x16   sub_id=  0 MavLite payload 54>41>52>5F>43>02>|TAR_C|  age=580 mS|

Pop  row=  14  msg_id=0x16   sub_id=  0 MavLite payload 5F>4C>4C>52>5F>03>	_LLR_	  age=820 mS 

Pop  row=  15  msg_id=0x16   sub_id=  0 MavLite payload 00>00>EE>00>50>04>	P	  age=1194 mS 

these are the downlink bytes of the first chunk, with 0x32 prefix:


and so on.

Your GCS sends a parameter request, the waits for the answer, then shows an ERROR before sending the next request for that particular parameter id.

Maybe you can see what I’m missing :slight_smile:

Hi Eric,
I tried sending the same message from ardupilot, I get 4 chunk not 5

TX(MSG) -> pkts=4, state=7, id=22, len=17, name=ATC_RAT_RLL_P, value=0.135000

RX(PEEK) -> 1100:0A3D7116
RX(PEEK) -> 3E01:5F435441
RX(PEEK) -> 5202:525F5441
RX(PEEK) -> 4C03:39505F4C

Thank you Alex! Huge help.

1 Like

Hi again Alex. Sorry to bother. I’m making (modest) progress in my spare time :slight_smile: Since this CRC code works for S.Port Passthru, I assume it will work for Mavlite, but no.

I include the payload only, including the IEEE 754 float. I padded the struct to get the bytes aligned. So my bytes co-inside with yours above, but my CRC = EE , including a final 1’s complement on the resulting byte.

mliteMsg=16 11 |00 00 |71 3D 0A 3E 41 54 |43 5F 52 41 54 5F |52 4C 4C 5F 50 |Crc=EE |

I add in 17 bytes from byte[4]

int16_t CRC;

void AddInCrc(uint8_t b) {
   CRC += b;          //0-1FF
   CRC += CRC >> 8;   //0-100
   CRC &= 0x00ff;
   CRC += CRC >> 8;   //0-0FF
   CRC &= 0x00ff;

Hi Eric, my checksum is constrained to be an uint8_t, just like sport/fport

void MAVLITE::mavlite_update_checksum(mavlite_message_t* msg, uint8_t c)
    msg->checksum += c; //0-1FF
    msg->checksum += msg->checksum >> 8;
    msg->checksum &= 0xFF;

the sport/fport one in current master is

uint16_t sum = 0;
for (uint8_t i=0; i<sizeof(buf)-1; i++) {
    sum += buf[i];
    sum += sum >> 8;
    sum &= 0xFF;

@yaapu Hi Alex!
i try to build your ardupilot fork and make a max3232+diode coverter. i successfully get telemetry for FrskyTelemetryScript. but LuaGCS show me only “…loading” screen. maybe i’m lost something? thank you!