-
Notifications
You must be signed in to change notification settings - Fork 54
API v.4
Each Chorus node Receives and Transmits data. Here's how the communication flow is organized.
- Each node comprising the Chorus has its ID (order number), which is assigned dynamically upon initialization of the Chorus device from a race control application. Normally enumeration starts with 0 (using
"N0\n"
command). - Each data chunk is a plain string terminated with "\n" character (ASCII=0xA) and having a predefined structure.
- There are 3 types of data chunks:
- Requests
- Responses
- Pass-through data
- Each Request produces a Response. In certain cases Chorus nodes generate responses themselves (e.g. Laps data in race mode; RSSI values in monitoring mode, etc.)
- Pass-through data is either a request to one of the next nodes in a chain (either addressed or broadcast), or a response from any previous node which needs to pass through the current node to reach a transmitting device (Bluetooth/WiFi dongle) and be sent to a race control application.
There are 2 types of requests:
- Nodes enumeration: (3 characters)
"N" + <first_ID> + "\n"
. Example:"N0\n"
- Command / Get value: (4 characters)
"R" + <node_ID> + <item/command> + "\n"
. Example:"R1r\n"
;"R0J\n"
- Set value: (5+ characters)
"R" + <node_ID> + <item> + [<value>] + "\n"
. Example:"R1B0\n"
;"R0JFFFFEEC0\n"
Any request may be addressed to a particular node by specifying its <node_ID>
, or "broadcasted" (i.e. addressed to all nodes) by setting "*"
as a <node_ID>
. Example: "R*A\n"
Note: for broadcast requests the order of responses from different nodes is not defined. Example: "S1R1\nS0R1\nS2R1\n"
Response structure: "S" + <node_ID> + <response_type> + <data> + "\n"
Each response type has its own predefined length depending on size of data to be transmitted.
Note:
- All broadcast requests pass through all nodes and return to sender unchanged.
- All addressed requests return to sender unchanged if target node is not found.
- All addressed requests DON'T return to sender and are normally followed by a response (see API).
The most recent version of the API can be found in the docs folder (MS Excel format).
NOTE: In commands used below I omit the trailing "/n"
character for simplicity, but this character is mandatory in each command!
-
Run "Enumerate Nodes" command (
"N0"
) to enumerate modules (REQUIRED!). Read the response to find out the number of nodes in the device. Modules numbering will start from zero. (Hint: you may send"N1"
to start numbering from 1 if it's more convenient to you). -
Set Minimal Lap Time for all nodes, which must be less than the fastest possible lap time during the upcoming race (e.g.
"R*M0F"
). This will make sure that Chorus won't report false laps if accidentally catches VTX RSSI peak from a nearby drone before the latter crosses the finish line. Also you should plan the track to avoid situations when drones fly in close proximity to the Chorus before the end of a lap. -
Set Frequency into each node using either "Set Frequency" (e.g.
"R0F1636"
) command or "Set Channel" + "Set Band" (2 commands) (e.g."R0C4"
+"R0B0"
). Note: it's the responsibility of the race control software to remember which node is monitoring which frequency to further match Chorus responses to pilots in each heat. -
Adjust Arduino Timers (optional step, but increases accuracy of measured lap times during the race across nodes). The reason for that is: although all Arduinos are supposed to run at 16 MHz, the oscillation generator in them is not very precise and different devices may give a difference of several milliseconds for a measured period of tens of seconds. In order to compensate that difference I suggest the following algorithm:
- Send "Get Time" command to all nodes:
"R*t"
. Chorus will respond with each node's internal time (milliseconds from start):S1t000CA710
,S0t000CA715
.... Remember these values. Let's name a time from any particular node ast0
. - Wait for some time (I use about 10 seconds). Let's name this time in milliseconds as
tc
(in my casetc = 10000
). - Send another "Get Time" command to all nodes:
"R*t"
. Chorus will again respond with measured times from each node. Let's name this time from any particular node ast1
. - Calculate a time span for each node:
ts = t1 - t0
. - Perform the following calculation for each node:
cc = tc/(tc - ts)
,if tc - ts = 0, then set cc = 0x7FFFFFFF
. Herecc
would mean something like "what time measured by this arduino should be increased/decreased by 1 ms". E.g.cc = 1000
means that each second measured by arduino gives an error of -1 millisecond, so this millisecond should be added to each measured second to compensate the error. - Send calculated
cc
values to each corresponding node using "Set Time Adjustment Value" command (note it must be a signed 32 bit value, e.g."R0JFFFFFA24"
is negative value-1500
). - You're done. Alternatively you may perform all adjustments (steps 4 - 5) in the race control software upon receiving measured lap times from Chorus:
realLapTime = reportedLapTime + reportedLapTime / cc
.
- Send "Get Time" command to all nodes:
-
Set threshold for each pilot. You may use one of the following:
- "Set Threshold Value" command (
"R1T00BE"
)- to set already known threshold value (e.g. if you stored known good value from previous threshold setup attempt). - "Setup Threshold" command (
"R*H1"
) to start the threshold setting algorithm in all or specific node. This will eventually reply with threshold value(s) for the specified node(s). Also the algorithm will report stages of the process:"S0H2"
..."S0H0"
, where the stage meanings are:stage 0
- threshold setup is over/not started;stage 1
- threshold setup is started;stage 2
- threshold setup is halfway (measured RSSI value passed the lower bound and algorithm is now "finding" a maximum value). If using this approach, you should carefully monitor whether the threshold values are returned for all pilots which take part in the procedure, otherwise some pilot(s) might be not correctly tracked during the heat. NOTE: Setup Threshold algorithm won't run in Race Mode. Starting the Race Mode immediately stops the Setup Threshold algorithm without setting new threshold value.
- "Set Threshold Value" command (
-
Start race in one of 2 possible modes. Choose whatever is convenient to you:
- Start race with relative lap times:
"R*R1"
, - once the race is started, lap times will be calculated based on previous lap end: e.g. lap #1: 0:30.500, lap #2: 0:28.240, ... - Start race with absolute lap times:
"R*R2"
, - once the race is started, lap times will represent time passed since the race start: e.g. lap #1: 0:30.500, lap #2: 0:58.740 (time of lap 1 + time of lap 2), ...
- Start race with relative lap times:
-
Stop the race when it's over using "End Race" command:
"R*R0"
. (This is required!). -
Repeat from step 5 or 6 for each subsequent heat.
- Battery voltage calculation if implemented, should be done on the race control software side, because Chorus just reports the absolute value it reads from Arduino ADC pin. Conversion formula: voltageReading * 55 / 1024