A JETI EX BUS protocol implementation in Python or more specifically in MicroPython. This allows to use microcontrollers (aka boards) like Raspbery Pi, ESP32 or similar to act as a sensor hub for Jeti RC receivers and to transmit telemetry data from the board to the receiver and back to the transmitter (i.e. RC controls like this DC24).
Raspberry Pi RP2040 based platforms were used for development. The main application is to use the software on these boards together with one or more sensors attached to it. The main sensor interface is based on the I2C protocol. So all sensors using this interafce can be easiliy integrated, some are already predifined (see section features).
The code runs on two cores. One core handles the telemetry transfer, the other core prepares the telemetry based on data retrieved from sensors.
- Pure Python (MicroPython) implementation of the Jeti Ex Bus protocol
- Variometer functionality - currently following pressure sensors are supported:
- Can be extended by any I2C capable sensor
- Simple firmware/software update via USB-C
- Easy logging of sensor data
- Runs on boards which are supported by MicroPython (see forum or code repository)
- Two core implementation
- Core-0 handles the transfer of JETI telemetry data via UART
- Core-1 does the sensor reading via I2C and prepares the packets for the EX and EX-BUS protocols
NOTE: Due to the implementation only boards with two cores are supported
Raspberry Pi RP2040 based boards are the main platform for this software. Other boards featuring two cores and running on MicroPython will be checked in the future.
- Raspberry Pi Pico series
- Pimoroni TINY 2040, small form factor (22.9 x 18.2 mm)
- Seeed Studio XIAO RP2040, small form factor (21 x 17.5 mm)
After finishing board and sensors (see further down) the MicroPython firmware needs to be installed. The firmware then is the operating system where MicroPython code can run. After this the software must be copied onto the board.
-
Download the Micropython firmware for the specific board in use
- As an example, the XAIO RP2040 runs the Raspberry Pi Pico firmware
- The firmware typically comes in the USB flashing format (UF2), for example rp2-pico-20230426-v1.20.0.uf2
-
Press and hold the boot button (B) on the board, connect the USB-C cable and then release the button. This will put the board into the so called bootloader mode. The board should now appear as USB drive on the computer
-
Copy (drag) the firmware onto this USB drive
-
Disconnect and re-connect the USB-C plug. The board is now ready to run MicroPython code
-
Use one of the following tools (mpremote, Thonny, rshell, tio, etc.) to upload all files and folders to the board. The command line tool
mpremote
is the recommended way, as it allows to copy all files at once. The following command installs all files from this repository onto the board:mpremote mip install --target=/ github:chiefenne/JETI_EX_BUS
To install a specific GitHub branch (e.g., develop) use:
mpremote mip install --target=/ github:chiefenne/JETI_EX_BUS@develop
-
Unplug the USB-C cable and connect the board/sensor to the JETI receiver
-
Ready to go!
NOTE: From the MicroPython docs: "The exact procedure for these steps is highly dependent on the particular board and you will need to refer to its documentation for details."
NOTE: If there is already an older release of JETI Ex Bus protocol (Python) installed, and an upddate to a newer version is performed, it is highly recommended to delete at first all files from the board. See below how to do that.
Wiping the board, is at the time of this writing, not easily possible with mpremote
. The filesystem can be formatted with the following fancy command for RP2040 boards (copied from here):
mpremote exec --no-follow "import os, machine, rp2; os.umount(/); bdev = rp2.Flash(); os.VfsLfs2.mkfs(bdev, progsize=256); vfs = os.VfsLfs2(bdev, progsize=256); os.mount(vfs, /); machine.reset()"
Sooner or later mpremote
will have an option to achieve this in a simpler way. Check for this.
The flowchart (Fig. 1) describes the setup of the hardware and indicates the physical connections. The microcontroller is connected with the receiver via a serial asynchronous interface UART. Physically the connection uses three wires (vcc, gnd, signal). Examples are shown in figures 9, 10 and 11.
The Jeti telemetry runs via a half-duplex serial communication protocol. This means that there is a master (receiver) controlling the data flow and a slave (microcontroller/sensor) which is only allowed to answer upon request from the master. The master reserves a 4ms period for this to work. Measurments show approximately a 6ms period (see also figure 10).
The connection between the board and the sensors is established via I2C. Four wires (vcc, gnd, sda, scl) are needed to connect each of the sensors.
Fig. 1: Data flow and physical connections
The program logic consists of two parts. Those are the similar to the Arduino setup() and loop() functions.
- In the beginning the communication channels (UART, I2C) are initialized. A serial connection (UART) is established between the microcontroller and the receiver. Additionally an I2C connection is setup between the microcontroller and the sensor(s).
- After the setup of the communication, the two main (infinite) loops start, one infinite loop on each core.
Fig. 2: Communication layer and multicore protocol handler
Below example shows how a BME280 pressure sensor is soldered to a XIAO RP2040 board. In a similar way the VCC and GND connections between both boards are soldered as well (see figures 4, 5, 7).
Fig. 3: BME280 sensor at first connected to SDA, SCL. The sensor is then flipped down.
The following images show the components and connections for a XIAO RP2040 board. For other boards the respective UART pins (TX, RX) have to be selected according the board specific pinout. After the pressure sensor is flipped down, the power and ground (GND) connections can be established. Double-sided adhesive tape or hot glue fix the board and the sensor to each other.
The voltage requirements of the sensor have to be checked, the used BME280 sensor runs on 3.3V. The respective 3.3V pin on the microcontroller has then to be connected to VCC on the sensor.
The servo cable (red, brown, orange) is soldered according to the image below. The servo signal cable (orange) goes to RX (pin D7). The VIN pin (5V) is used for the power connection between receiver and board. If the board is connected to a USB-C cable then this pin outputs approximately 5V and powers the receiver if it is attached. If used in the RC plane then the power comes from the receiver to the board (of course no USB cable is attached then).
A resistor (2.4 kΩ up to a few kΩs) needs to be soldered between the TX and RX pins. On the XIAO RP2040 these are pins D6 and D7 respectively. The resitor enables the half-duplex communication which is triggered by the JETI receiver.
Fig. 4: Setup with a BME280 sensor. 3.3V (red) and GND (black) from board to sensor
Fig. 5: Data (SDA, yellow) and clock (SCL, green) connections for I2C bus
Figure 6 shows a USB-C plug connected to the microcontroller. The connection from the microcontroller to the JETI receiver needs to be on a socket (here 6), which is set to run the EX BUS protocol (see figure 8).
Fig. 6: Setup for software update and development
Fig. 7: Here an MS5611 sensor is attached
a
Fig. 7a: Compare altitude readings of MS5611 sensor to Jeti MVario2
Below figure depicts the JETI display for the receiver settings (German language).
Fig. 8: The receiver channel where the microcontroller is connected needs the EX Bus setting activated
The data recorded are coming from the master (receiver) and show a duration of approximately 3.8ms for the channel data and the concatenated telemetry request (see figure below). Click on the image to see a larger version.
Fig. 9: Jeti EX BUS protocol. Example shows channel data (i.e., transmitter controls) and then a telemtry request
The time between two channel/telemetry request packages is approximately 6.2ms. The EX bus protocol documentation states that a period of 4ms after the telemetry/JetiBox request is reserved for the answer from the sensor, etc. Click on the image to see a larger version.
Fig. 10: Jeti EX BUS protocol. Example shows the waiting period allowed for answering with telemetry
The image below shows a detailed view of the beginning of a packet (digital and analog). Click on the image to see a larger version.
Fig. 11: Jeti EX BUS protocol. Zoomed view (digital/analog data from the logic level analyzer).
The next figure depicts a telemetry answer from the microcontroller/sensor (slave). In this case it is an answer from a Jeti MVario 2 sensor. The telemetry data were sent in aprox. 2.7ms. In order to answer a telemetry request, there are 4ms reserved on the EX bus, so this packet fits well into that. Click on the image to see a larger version.
Fig. 12: Jeti EX BUS protocol. Example of Jeti MVario 2 telemetry answer.
Written by the function Streamrecorder.py which should only be activated to record the serial stream. This is only meaningful for debugging purposes.
The receiver is the master and triggers the half-duplex communication. As an example 3e:03 is the beginning of a packet containing channel data sent by the receiver (the packet describes the current actuator settings of the transmitter). A telemetry request (from receiver/master to the microcontroller/sensor) is indicated by 3d:01 which is the start of an 8 byte packet. After this there is a 4ms window to send telemetry data back from the board to the receiver (not visible in this data stream).
02:02:7d:dd:2e:e7:2e:f2:2e:e0:2e:e0:2e:e0:2e:e0:2e:e0:2e:e0:2e:e0:2e:e0:2e:e0:2e:e0:2e:e0:2e:e0:2e:78:69:3e:03:28:42:31:20:40:1f:dd:2e:e7:2e:f2:2e:e0
2e:e0:2e:e0:2e:e0:2e:e0:2e:e0:2e:e0:2e:e0:2e:e0:2e:e0:2e:e0:2e:e0:2e:e0:2e:78:69:3d:01:08:42:3a:00:8f:e4:3e:03:28:42:31:20:40:1f:dd:2e:e7:2e:f2:2e:e0
2e:e0:2e:e0:2e:e0:2e:e0:2e:e0:2e:e0:2e:e0:2e:3e:03:28:42:31:20:40:1f:dd:2e:e7:2e:f2:2e:e0:2e:e0:2e:e0:2e:e0:2e:e0:2e:e0:2e:e0:2e:e0:2e:e0:2e:e0:2e:e0
2e:e0:2e:78:69:3d:01:08:42:3a:00:8f:e4:3e:03:28:42:31:20:40:1f:dd:2e:e7:2e:f2:2e:e0:2e:e0:2e:e0:2e:e0:2e:e0:2e:e0:2e:e0:2e:e0:2e:e0:2e:e0:2e:e0:2e:e0
2e:78:69:3d:01:08:42:3a:00:8f:e4:3e:03:28:42:31:20:40:1f:dd:2e:e7:2e:f2:2e:e0:2e:e0:2e:e0:2e:e0:2e:e0:2e:e0:2e:e0:2e:e0:2e:e0:2e:e0:2e:e0:2e:e0:2e:78
69:3d:01:08:42:3a:00:8f:e4:3e:03:28:42:31:20:40:1f:dc:2e:e7:2e:f2:2e:e0:2e:e0:2e:e0:2e:e0:2e:e0:2e:e0:2e:e0:2e:e0:2e:e0:2e:e0:2e:e0:2e:e0:2e:8b:49:3d
See EX_Bus_stream.txt for a 1 second recording of the bus (this feature can be activated in the code for debugging purposes).
Apart from the JETI telemetry documentation, the code of this repo has learned from many sources.
Following sources were most helpful (without those I couldn't have done this at all):
- MicroPython docs
- MicroPython forum
- Sepp62
- nichtgedacht
- nightflyer88
- Pulsar07
- Betaflight Jeti telemetry
- RC-Thoughts
Distributed under the MIT license. See LICENSE for more information.
2023 Andreas Ennemoser – [email protected]