Frsky bidirectional telemetry implementation

yes, here

Starting .... C:\Users\Eric\Documents\GitHub\+esp32_wip\Mav2PT_TwoWay_v2.45c\Mav2PT_TwoWay_v2.45c
Target Board is ESP32 / Variant is Dev Module
Air Mode
Battery_mAh_Source = 3 - Define battery capacities in the LUA script
Using Serial_1 for S.Port
RSSI Automatic Select
Mavlink Serial In
Waiting for telemetry
ESP32 S.Port pins NOT inverted for Air or Relay Modes. Must use a converter
hb_count=1
hb_count=2
hb_count=3
mavgood=true
FrSky from S.Port: 0x0D:0x30:1000:52455314
FrSky from S.Port: 0x0D:0x30:4901:5F314C41
FrSky from S.Port: 0x0D:0x30:5002:4F544F52
FrSky from S.Port: 0x0D:0x30:4303:00EC4C4F
FrSky from S.Port: 0x0D:0x30:1000:52455314
FrSky from S.Port: 0x0D:0x30:4901:5F314C41
FrSky from S.Port: 0x0D:0x30:5002:4F544F52
FrSky from S.Port: 0x0D:0x30:4303:00EC4C4F
FrSky from S.Port: 0x0D:0x30:1000:52455314
FrSky from S.Port: 0x0D:0x30:4901:5F314C41
FrSky from S.Port: 0x0D:0x30:5002:4F544F52
FrSky from S.Port: 0x0D:0x30:4303:00EC4C4F
FrSky from S.Port: 0x0D:0x30:1000:52455314
FrSky from S.Port: 0x0D:0x30:4901:5F314C41
FrSky from S.Port: 0x0D:0x30:5002:4F544F52
FrSky from S.Port: 0x0D:0x30:4303:00EC4C4F
FrSky from S.Port: 0x0D:0x30:1000:52455314
FrSky from S.Port: 0x0D:0x30:4901:5F314C41
FrSky from S.Port: 0x0D:0x30:5002:4F544F52
FrSky from S.Port: 0x0D:0x30:4303:00EC4C4F
FrSky from S.Port: 0x0D:0x30:1000:52455314
FrSky from S.Port: 0x0D:0x30:4901:5F314C41
FrSky from S.Port: 0x0D:0x30:5002:4F544F52
FrSky from S.Port: 0x0D:0x30:4303:00EC4C4F
FrSky from S.Port: 0x0D:0x30:1000:52455314
FrSky from S.Port: 0x0D:0x30:4901:5F314C41
FrSky from S.Port: 0x0D:0x30:5002:4F544F52
FrSky from S.Port: 0x0D:0x30:4303:00EC4C4F

:sunglasses: yesss, looking good!

1 Like

Another small step. We could use the param index rather than the id string.

Did I mention we are off to Australia for a month, leaving tomorrow? I have to pause this project now, but will work from there.

S.Port Read raw: 0D 30 00 10 14 53 45 52 	0x0D:0x30:1000:52455314
S.Port Read raw: 0D 30 01 49 41 4C 31 5F 	0x0D:0x30:4901:5F314C41
S.Port Read raw: 0D 30 02 50 52 4F 54 4F 	0x0D:0x30:5002:4F544F52
S.Port Read raw: 0D 30 03 43 4F 4C EC 00 	0x0D:0x30:4303:00EC4C4F
Mavlite #20 Request_Param_Read :SERIAL1_PROTOCOL:
Mavlink from FC #22 Param_Value: param_id=SERIAL1_PROTOCOL  param_value=2.0000  param_count=802  param_index=65535

great Eric :+1: the mavlite decoder is working!

[Q] are you doing your testing in air mode or ground mode?

yes I know but to get the index I’d have to query the param first and cache the response.
In a regular GCS I’d do it this way but in lua I’m already using memory to store paramenter names and I opted to trade some memory vs speed, but I’m open to change it, actually it would improve speed quite a bit but only after the first pass with full parameter names.

yes you did :slight_smile: have a nice trip Eric!

Air mode right now. Thank you. :slight_smile:

@yaapu I’ve done a PR for an implementation of FPort here:


This support FPort for RC input. I’m hoping you can give me some assistance with the 2nd part of this, which is to use FPort for the SPort pass-through output as well.
What I need to know is how to deal with the “prim” and “appid” fields that come in with a FPort control packet and how they relate to the sport IDs in the ArduPilot sport passthru code.

Hi @tridge,
prim_id is the frame type, ardupilot as of current (no bidirectional) only used 0x10, so each packet sent down the link had 0x10 as prim_id.
app_id is used by regular frsky sensors to distinguish “instances”, but ardupilot used it to mark packets with prim_id 0x10 as passthrough by using for app_id a “special” range above 0x5000 known as the DIY packet range.
By using 0x10 as prim_id and 0x5000 ad app_id the payload is only 4 bytes, OpenTX passes to LUA all 0x10 packets with app_id in the DIY range.
downlink/control traffic (master → slave) should use prim_id 0x00/0x10(R/W), 0x30(RO), 0x31(WO)
uplink traffic (slave → master) should use 0x10 and 0x32 where 0x32 is special because OpenTX always passes 0x32 up to the lua stack irregardless of the app_id, in this case the payload is 6 bytes, app_id + data.

  • every time we receive 0x10 or 0x00 we have a chance to send passtrough telemetry data

  • every time we receive 0x30,0x31 we should invoke the bidirectional passthrough packet decoder by passing app_id and data (6 bytes) (we will eventually respond with prim_id 0x32)

  • we respond to 0x00/0x10 with 0x10, and to 0x30,0x31 with 0x32, so for 0x00,0x10,0x30,0x31 the passthrough packet scheduler should be invoked.

hope this makes sense, later tonight I will have the time to check your code,

great stuff :slight_smile:

Edit: I got your branch working on a Pixhawk1 + X4R, I wired the X4R sport pint to the RCIN pin
To process incoming packets from LUA (master->slave) you provide the decode_downlink() method, what we need is a method to write to the bus an fport_frame, something like send_uplink()

I hacked together something for the F765-Wing which works with yaapu telem over fport. It is pretty ugly at the moment, but I think I can clean it up.
One thing that is wrong is the uart pin is idling high, whereas it should idle low as the fport signal is inverted (using a X4R). I checked with inav on the same board and it idles low. Something wrong in the uart config.

great! If you think I can be of any help, let me know!

I’ve updated the PR with first working version. To use it you need to set some serial port with:
SERIALn_PROTOCOL=23
which sets the serial port as RCIN. You will also need:
SERIALn_OPTIONS=7
to enable half-duplex inverted. After that the passthru telem output should work.
I’m looking at the possibility of supporting the output using soft-serial so it can work with a uart. FPort input does work in the PR for input without a UART, but not yet for output.

I’ve got a test patch that allows FPort including telemetry without a UART, using soft-serial to output the SPort data. It does work, but is not suitable for merging in it’s current form.
One of the key issues is that when we don’t use a UART the RC protocol decoder doesn’t get told about a new frame until after it is too late to send the reply. The problem is that the SoftSigReader and SoftSigReaderInt implementations gather level transitions in pairs. So it can sit waiting for the first transition for the next packet before it passes the data to the RC decoder. I put in a hack to work around this just to test the soft-serial send part, but we need to fix this properly if we want to use a non-UART implementation for sport.

Hi Alex and tridge

Very nice progress, by the sounds of it! Alex I enjoyed your explanation of the FrSky sensor protocols. You illuminated some of the dark corners that have eluded me.

Tridge, it’s a pleasure to hear/see your insights into the workings of the ardupilot eco system. Awesome.

Alex I have bi-directional mavlite working in my modest little protocol translator, but I need to tidy up before I give you something to test. I don’t have a Horus here with me, so I hacked a spare esp32 board to send and read test data similar to openTX. It might not represent real life. Also, after reading your treatise above, I want to relook at how I respond to ids. :roll_eyes:

The Dragonlink boards arrived today, so I also look forward to playing with those. In between my vacation duties, of course. :grin:

Hi Tridge,
this is just to confirm that I had it working in UART mode on an X4R and a pixhawk1 by using serial4 with an inverter (classic max3232 inverter).

The general setup instructions if someone wants to try your fport code in UART mode is:

  • set some serial port with SERIALn_PROTOCOL=23 to enable RCIN
  • set SERIALn_OPTIONS=0 and use an s.port inverter for boards that do not have built in inversion/half duplex
  • set SERIALn_OPTIONS=7 for boards that support inversion and half duplex
  • set SERIALn_BAUD to 115200

Eric, I would not call your project “modest little protocol translator”, it turned out into way much more than that!

The above ID explanation is for f.port which does not use physical IDs, but in the bidirectional s.port implementation we should stick to that standard as well.
Tridge is doing a great job (as usual) at keeping the rc protocol f.port implementation separated from the telemetry code so it won’t be too hard to plug the bidirectional stack on top of f.port

Dragonlink has been so kind to send me one unit too so we will both be able to do end to end testing!

I’ll update the parameters API to also use parameter ID, I agree it’s a good choice and will speed things up quite a bit.
After parameters I would like to give a try at mavlink command_long messages :slight_smile:

Alex, I’ve posted v2.46i which includes foundation support for Mavlite. It’s NOT properly tested, mainly because I don’t have a TX or a proper test mule here.

End-to-end testing

Um, ok, I’ll be looking for a very, very high-gain UHF antenna in the meantime. Or we could try EME (moon bounce). But this got me thinking. We could perhaps try a tcp socket. With full feedback to Mission Planner, and fly remote. UHF repeaters on each end. :sweat_smile:

1 Like

OK, I’ll take a look at it.
I’d like to publish the lua scripts but I still cannot find a good name for the project, some candidates:

  • ardupilotlua
  • luagcs
  • ??

same for the “mavlite” library classes, some candidates:

  • mavsport
  • frskymav
  • ??
    Mavlite gives a rough idea of what this is but I really am open to suggestions

hahaha, you got me laughing loud this morning…but after reading it you also got me thinking that since we share the same timezone we might eventually put something together to have you fly one of my birds or viceversa over tcp + uhf repeaters, would be cool actually, technically one of us would have direct sight and would make this kind of legal, no idea of the latency at my flying field tough…

EME (moon bounce) now that sounds like fun count me in lol

1 Like

Latency would be a problem

only 2.7 sec i can fly with that :rofl: