Skip to content

Commit ace0f31

Browse files
committed
fixup! Add the new REALTIME_DATA command
- Make mask2 optional in the request - Move battery SoC to mask1 - Add the FOC Id to mask2 - Fix checking of mask1 instead of mask2 when adding mask2 fields - Documentation improvements
1 parent 734b39b commit ace0f31

2 files changed

Lines changed: 108 additions & 99 deletions

File tree

doc/commands/REALTIME_DATA.md

Lines changed: 57 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,15 @@
22

33
**ID**: 33
44

5-
Provides selectable realtime data from the package to the client. This command allows the client to request specific data fields using a bitmask, and supports encoding floats as both float16 and float32.
5+
Provides selectable realtime data from the package to the client. This command allows the client to request specific data fields using a bitmask, and supports encoding floats as both [float16](float16.md) and float32.
66

77
## Request
88

9-
| Offset | Size | Name | Description |
10-
|--------|------|------------------|---------------|
11-
| 0 | 1 | `control_flags` | Control flags specifying format options:<br> `0x1`: Use float32 instead of float16 for numeric values |
12-
| 1 | 4 | `mask1` | Bitmask specifying which data fields to include (bits 0-31). See **Mask1** table below. |
13-
| 5 | 4 | `mask2` | Bitmask specifying which data fields to include (bits 32-63). See **Mask2** table below. |
9+
| Offset | Size | Name | Mandatory | Description |
10+
|--------|------|------------------|-----------|---------------|
11+
| 0 | 1 | `control_flags` | Yes | Control flags specifying format options:<br> `0x1`: Use float32 instead of [float16](float16.md) for numeric values |
12+
| 1 | 4 | `mask1` | Yes | Bitmask specifying which data fields to include (bits 0-31). See **Mask1** table below. |
13+
| 5 | 4 | `mask2` | No | Bitmask specifying which data fields to include (bits 32-63). See **Mask2** table below. |
1414

1515
## Response
1616

@@ -24,56 +24,57 @@ The response contains the data fields that were requested via the bitmasks. The
2424
| 9 | 4 | `time` | Timestamp of the data in ticks, as `uint32`. To convert to seconds, use `tick_rate` from the [INFO](INFO.md) command. |
2525
| 13 | N | `data_fields` | Sequence of requested data fields. |
2626

27-
### Mask1 Fields
28-
29-
The following bits in `mask1` control which fields are included in the response. When a bit is set, the corresponding field is included in the response in the order listed below.
30-
31-
| Bit | Field Name | Type | Description |
32-
|-----|----------------------------|--------------------------|--------------------------------------------------|
33-
| 0 | `extra_flags` | uint8 | Extra flags for various internal package state values. See **extra_flags** below. |
34-
| 1 | `state_flags` | uint32 | Combined state, mode, footpad, and alert information. See **state_flags** below. |
35-
| 2-5 | _(unused)_ | - | Reserved for future use. |
36-
| 6 | `speed` | float16/float32 | Current speed [km/h]. |
37-
| 7 | `erpm` | float16/float32 | Electrical RPM of the motor. |
38-
| 8 | `current` | float16/float32 | Motor current [A]. |
39-
| 9 | `dir_current` | float16/float32 | Directional motor current [A]. |
40-
| 10 | `filt_current` | float16/float32 | Filtered motor current [A]. |
41-
| 11 | `duty_cycle` | float16/float32 | Motor duty cycle (0.0-1.0). |
42-
| 12 | `batt_voltage` | float16/float32 | Battery voltage [V]. |
43-
| 13 | `batt_current` | float16/float32 | Battery current [A]. |
44-
| 14 | `mosfet_temp` | float16/float32 | MOSFET temperature [°C]. |
45-
| 15 | `motor_temp` | float16/float32 | Motor temperature [°C]. |
46-
| 16 | `pitch` | float16/float32 | IMU pitch angle [°]. |
47-
| 17 | `balance_pitch` | float16/float32 | Balance pitch angle [°]. |
48-
| 18 | `roll` | float16/float32 | IMU roll angle [°]. |
49-
| 19 | `adc1` | float16/float32 | Footpad sensor ADC1 value [V]. |
50-
| 20 | `adc2` | float16/float32 | Footpad sensor ADC2 value [V]. |
51-
| 21 | `remote_input` | float16/float32 | Remote control input value (0.0-1.0). |
52-
| 22 | `setpoint` | float16/float32 | Current balance setpoint [°]. |
53-
| 23 | `atr_setpoint` | float16/float32 | ATR setpoint [°]. |
54-
| 24 | `brake_tilt_setpoint` | float16/float32 | Brake tilt setpoint [°]. |
55-
| 25 | `torque_tilt_setpoint` | float16/float32 | Torque tilt setpoint [°]. |
56-
| 26 | `turn_tilt_setpoint` | float16/float32 | Turn tilt setpoint [°]. |
57-
| 27 | `remote_setpoint` | float16/float32 | Remote control setpoint [°]. |
58-
| 28 | `balance_current` | float16/float32 | Balance (output) current [A]. |
59-
| 29-31 | _(unused)_ | - | Reserved for future use. |
60-
61-
### Mask2 Fields
62-
63-
The following bits in `mask2` (using `mask1` parameter but referencing bits logically in a second 32-bit space) control additional fields:
64-
65-
| Bit | Field Name | Type | Description |
66-
|-----|----------------------------|--------------------------|--------------------------------------------------|
67-
| 0 | `odometer` | uint32 | Total lifetime distance traveled [m]. |
68-
| 1 | `distance_abs` | float16/float32 | Current ride absolute distance traveled [m]. |
69-
| 2 | `battery_level` | float16/float32 | Battery level (0.0-1.0). |
70-
| 3 | `charging_voltage` | float16/float32 | Charging voltage [V]. |
71-
| 4 | `charging_current` | float16/float32 | Charging current [A]. |
72-
| 5 | `amp_hours` | float16/float32 | Amp hours consumed [Ah]. |
73-
| 6 | `amp_hours_charged` | float16/float32 | Amp hours charged [Ah]. |
74-
| 7 | `watt_hours` | float16/float32 | Watt hours consumed [Wh]. |
75-
| 8 | `watt_hours_charged` | float16/float32 | Watt hours charged [Wh]. |
76-
| 9-31 | _(unused)_ | - | Reserved for future use. |
27+
### Mask Fields
28+
29+
The bits in `mask1` and `mask2` control which fields are included in the response. When a bit is set, the corresponding field is included in the response in the order listed below.
30+
31+
#### mask1
32+
33+
| Bit | Field Name | Type | Description |
34+
|-----|----------------------------|-----------------|--------------------------------------------------|
35+
| 0 | `extra_flags` | uint8 | Extra flags for various internal package state values. See **extra_flags** below. |
36+
| 1 | `state_flags` | uint32 | Combined state, mode, footpad, and alert information. See **state_flags** below. |
37+
| 2-5 | _(unused)_ | - | Reserved for future use. |
38+
| 6 | `speed` | float16/float32 | Current speed [km/h]. |
39+
| 7 | `erpm` | float16/float32 | Electrical RPM of the motor. |
40+
| 8 | `current` | float16/float32 | Motor current [A]. |
41+
| 9 | `dir_current` | float16/float32 | Directional motor current [A]. |
42+
| 10 | `filt_current` | float16/float32 | Filtered motor current [A]. |
43+
| 11 | `duty_cycle` | float16/float32 | Motor duty cycle (0.0-1.0). |
44+
| 12 | `battery_voltage` | float16/float32 | Battery voltage [V]. |
45+
| 13 | `battery_current` | float16/float32 | Battery current [A]. |
46+
| 14 | `battery_soc` | float16/float32 | Battery State of Charge (0.0..1.0). |
47+
| 15 | `mosfet_temp` | float16/float32 | MOSFET temperature [°C]. |
48+
| 16 | `motor_temp` | float16/float32 | Motor temperature [°C]. |
49+
| 17 | `pitch` | float16/float32 | IMU pitch angle [°]. |
50+
| 18 | `balance_pitch` | float16/float32 | Balance pitch angle [°]. |
51+
| 19 | `roll` | float16/float32 | IMU roll angle [°]. |
52+
| 20 | `adc1` | float16/float32 | Footpad sensor ADC1 value [V]. |
53+
| 21 | `adc2` | float16/float32 | Footpad sensor ADC2 value [V]. |
54+
| 22 | `remote_input` | float16/float32 | Remote control input value (0.0-1.0). |
55+
| 23 | `setpoint` | float16/float32 | Current balance setpoint [°]. |
56+
| 24 | `atr_setpoint` | float16/float32 | ATR setpoint [°]. |
57+
| 25 | `brake_tilt_setpoint` | float16/float32 | Brake tilt setpoint [°]. |
58+
| 26 | `torque_tilt_setpoint` | float16/float32 | Torque tilt setpoint [°]. |
59+
| 27 | `turn_tilt_setpoint` | float16/float32 | Turn tilt setpoint [°]. |
60+
| 28 | `remote_setpoint` | float16/float32 | Remote control setpoint [°]. |
61+
| 29 | `balance_current` | float16/float32 | Balance (output) current [A]. |
62+
| 30-31 | _(unused)_ | - | Reserved for future use. |
63+
64+
#### mask2
65+
66+
| Bit | Field Name | Type | Description |
67+
|-----|----------------------------|-----------------|--------------------------------------------------|
68+
| 0 | `odometer` | uint32 | Total lifetime distance traveled [m]. |
69+
| 1 | `distance_abs` | float16/float32 | Current ride absolute distance traveled [m]. |
70+
| 2 | `charging_voltage` | float16/float32 | Charging voltage [V]. |
71+
| 3 | `charging_current` | float16/float32 | Charging current [A]. |
72+
| 4 | `amp_hours` | float16/float32 | Amp hours consumed [Ah]. |
73+
| 5 | `amp_hours_charged` | float16/float32 | Amp hours charged [Ah]. |
74+
| 6 | `watt_hours` | float16/float32 | Watt hours consumed [Wh]. |
75+
| 7 | `watt_hours_charged` | float16/float32 | Watt hours charged [Wh]. |
76+
| 8 | `motor_id` | float16/float32 | FOC direct axis motor current [A]. |
77+
| 9-31 | _(unused)_ | - | Reserved for future use. |
7778

7879
### extra_flags
7980

@@ -155,8 +156,6 @@ The state flags are encoded as a 32-bit unsigned integer with the following bit
155156

156157
- Numeric values are encoded as [float16](float16.md) by default. Set bit 0 of `control_flags` to use float32 encoding instead.
157158
- The `odometer` field is always encoded as a uint32 regardless of the `control_flags` setting.
158-
- Fields appear in the response in the exact order they are listed in the mask tables above.
159-
- Only fields with their corresponding mask bit set to 1 will be included in the response.
160159

161160
## Example
162161

src/main.c

Lines changed: 51 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -2035,39 +2035,40 @@ enum {
20352035
RT_MASK1_DIR_CURRENT = 1 << 9,
20362036
RT_MASK1_FILT_CURRENT = 1 << 10,
20372037
RT_MASK1_DUTY_CYCLE = 1 << 11,
2038-
RT_MASK1_BATT_VOLTAGE = 1 << 12,
2039-
RT_MASK1_BATT_CURRENT = 1 << 13,
2040-
RT_MASK1_MOSFET_TEMP = 1 << 14,
2041-
RT_MASK1_MOTOR_TEMP = 1 << 15,
2042-
RT_MASK1_PITCH = 1 << 16,
2043-
RT_MASK1_BALANCE_PITCH = 1 << 17,
2044-
RT_MASK1_ROLL = 1 << 18,
2045-
RT_MASK1_ADC1 = 1 << 19,
2046-
RT_MASK1_ADC2 = 1 << 20,
2047-
RT_MASK1_REMOTE_INPUT = 1 << 21,
2048-
RT_MASK1_SETPOINT = 1 << 22,
2049-
RT_MASK1_ATR_SETPOINT = 1 << 23,
2050-
RT_MASK1_BRAKE_TILT_SETPOINT = 1 << 24,
2051-
RT_MASK1_TORQUE_TILT_SETPOINT = 1 << 25,
2052-
RT_MASK1_TURN_TILT_SETPOINT = 1 << 26,
2053-
RT_MASK1_REMOTE_SETPOINT = 1 << 27,
2054-
RT_MASK1_BALANCE_CURRENT = 1 << 28,
2038+
RT_MASK1_BATTERY_VOLTAGE = 1 << 12,
2039+
RT_MASK1_BATTERY_CURRENT = 1 << 13,
2040+
RT_MASK1_BATTERY_SOC = 1 << 14,
2041+
RT_MASK1_MOSFET_TEMP = 1 << 15,
2042+
RT_MASK1_MOTOR_TEMP = 1 << 16,
2043+
RT_MASK1_PITCH = 1 << 17,
2044+
RT_MASK1_BALANCE_PITCH = 1 << 18,
2045+
RT_MASK1_ROLL = 1 << 19,
2046+
RT_MASK1_ADC1 = 1 << 20,
2047+
RT_MASK1_ADC2 = 1 << 21,
2048+
RT_MASK1_REMOTE_INPUT = 1 << 22,
2049+
RT_MASK1_SETPOINT = 1 << 23,
2050+
RT_MASK1_ATR_SETPOINT = 1 << 24,
2051+
RT_MASK1_BRAKE_TILT_SETPOINT = 1 << 25,
2052+
RT_MASK1_TORQUE_TILT_SETPOINT = 1 << 26,
2053+
RT_MASK1_TURN_TILT_SETPOINT = 1 << 27,
2054+
RT_MASK1_REMOTE_SETPOINT = 1 << 28,
2055+
RT_MASK1_BALANCE_CURRENT = 1 << 29,
20552056
};
20562057

20572058
enum {
20582059
RT_MASK2_ODOMETER = 1 << 0,
20592060
RT_MASK2_DISTANCE_ABS = 1 << 1,
2060-
RT_MASK2_BATTERY_LEVEL = 1 << 2,
2061-
RT_MASK2_CHARGING_VOLTAGE = 1 << 3,
2062-
RT_MASK2_CHARGING_CURRENT = 1 << 4,
2063-
RT_MASK2_AMP_HOURS = 1 << 5,
2064-
RT_MASK2_AMP_HOURS_CHARGED = 1 << 6,
2065-
RT_MASK2_WATT_HOURS = 1 << 7,
2066-
RT_MASK2_WATT_HOURS_CHARGED = 1 << 8,
2061+
RT_MASK2_CHARGING_VOLTAGE = 1 << 2,
2062+
RT_MASK2_CHARGING_CURRENT = 1 << 3,
2063+
RT_MASK2_AMP_HOURS = 1 << 4,
2064+
RT_MASK2_AMP_HOURS_CHARGED = 1 << 5,
2065+
RT_MASK2_WATT_HOURS = 1 << 6,
2066+
RT_MASK2_WATT_HOURS_CHARGED = 1 << 7,
2067+
RT_MASK2_MOTOR_ID = 1 << 8, // The FOC direct axis motor current
20672068
};
20682069

20692070
static void cmd_realtime_data(Data *d, uint8_t *buf, int len) {
2070-
if (len < 9) {
2071+
if (len < 5) {
20712072
return;
20722073
}
20732074

@@ -2076,10 +2077,14 @@ static void cmd_realtime_data(Data *d, uint8_t *buf, int len) {
20762077
bool use_f32 = control_flags & 0x1;
20772078

20782079
uint32_t mask1 = buffer_get_uint32(buf, &ind);
2079-
uint32_t mask2 = buffer_get_uint32(buf, &ind);
2080+
uint32_t mask2 = 0;
2081+
2082+
if (len >= 9) {
2083+
buffer_get_uint32(buf, &ind);
2084+
}
20802085

2081-
// 9 header + 4 time + (64 fields * 4 bytes) = 269 bytes
2082-
static const int bufsize = 269;
2086+
// 9B header + 4B time + (65 fields * 4B)
2087+
static const int bufsize = 273;
20832088
uint8_t buffer[bufsize];
20842089
ind = 0;
20852090

@@ -2104,14 +2109,20 @@ static void cmd_realtime_data(Data *d, uint8_t *buf, int len) {
21042109
);
21052110
}
21062111

2112+
// MASK1
21072113
add_rt_item(buffer, &ind, mask1, RT_MASK1_SPEED, d->motor.speed, use_f32);
21082114
add_rt_item(buffer, &ind, mask1, RT_MASK1_ERPM, d->motor.erpm, use_f32);
21092115
add_rt_item(buffer, &ind, mask1, RT_MASK1_CURRENT, d->motor.current, use_f32);
21102116
add_rt_item(buffer, &ind, mask1, RT_MASK1_DIR_CURRENT, d->motor.dir_current, use_f32);
21112117
add_rt_item(buffer, &ind, mask1, RT_MASK1_FILT_CURRENT, d->motor.filt_current.value, use_f32);
21122118
add_rt_item(buffer, &ind, mask1, RT_MASK1_DUTY_CYCLE, d->motor.duty_cycle.value, use_f32);
2113-
add_rt_item(buffer, &ind, mask1, RT_MASK1_BATT_VOLTAGE, d->motor.batt_voltage, use_f32);
2114-
add_rt_item(buffer, &ind, mask1, RT_MASK1_BATT_CURRENT, d->motor.batt_current.value, use_f32);
2119+
add_rt_item(buffer, &ind, mask1, RT_MASK1_BATTERY_VOLTAGE, d->motor.batt_voltage, use_f32);
2120+
add_rt_item(
2121+
buffer, &ind, mask1, RT_MASK1_BATTERY_CURRENT, d->motor.batt_current.value, use_f32
2122+
);
2123+
add_rt_item(
2124+
buffer, &ind, mask1, RT_MASK1_BATTERY_SOC, VESC_IF->mc_get_battery_level(NULL), use_f32
2125+
);
21152126
add_rt_item(buffer, &ind, mask1, RT_MASK1_MOSFET_TEMP, d->motor.mosfet_temp, use_f32);
21162127
add_rt_item(buffer, &ind, mask1, RT_MASK1_MOTOR_TEMP, d->motor.motor_temp, use_f32);
21172128
add_rt_item(buffer, &ind, mask1, RT_MASK1_PITCH, d->imu.pitch, use_f32);
@@ -2134,37 +2145,36 @@ static void cmd_realtime_data(Data *d, uint8_t *buf, int len) {
21342145
add_rt_item(buffer, &ind, mask1, RT_MASK1_REMOTE_SETPOINT, d->remote.setpoint.value, use_f32);
21352146
add_rt_item(buffer, &ind, mask1, RT_MASK1_BALANCE_CURRENT, d->balance_current.value, use_f32);
21362147

2137-
if (mask1 & RT_MASK2_ODOMETER) {
2148+
// MASK2
2149+
if (mask2 & RT_MASK2_ODOMETER) {
21382150
buffer_append_uint32(buffer, VESC_IF->mc_get_odometer(), &ind);
21392151
}
21402152
add_rt_item(
2141-
buffer, &ind, mask1, RT_MASK2_DISTANCE_ABS, VESC_IF->mc_get_distance_abs(), use_f32
2142-
);
2143-
add_rt_item(
2144-
buffer, &ind, mask1, RT_MASK2_BATTERY_LEVEL, VESC_IF->mc_get_battery_level(NULL), use_f32
2153+
buffer, &ind, mask2, RT_MASK2_DISTANCE_ABS, VESC_IF->mc_get_distance_abs(), use_f32
21452154
);
2146-
add_rt_item(buffer, &ind, mask1, RT_MASK2_CHARGING_VOLTAGE, d->charging.voltage, use_f32);
2147-
add_rt_item(buffer, &ind, mask1, RT_MASK2_CHARGING_CURRENT, d->charging.current, use_f32);
2148-
add_rt_item(buffer, &ind, mask1, RT_MASK2_AMP_HOURS, VESC_IF->mc_get_amp_hours(false), use_f32);
2155+
add_rt_item(buffer, &ind, mask2, RT_MASK2_CHARGING_VOLTAGE, d->charging.voltage, use_f32);
2156+
add_rt_item(buffer, &ind, mask2, RT_MASK2_CHARGING_CURRENT, d->charging.current, use_f32);
2157+
add_rt_item(buffer, &ind, mask2, RT_MASK2_AMP_HOURS, VESC_IF->mc_get_amp_hours(false), use_f32);
21492158
add_rt_item(
21502159
buffer,
21512160
&ind,
2152-
mask1,
2161+
mask2,
21532162
RT_MASK2_AMP_HOURS_CHARGED,
21542163
VESC_IF->mc_get_amp_hours_charged(false),
21552164
use_f32
21562165
);
21572166
add_rt_item(
2158-
buffer, &ind, mask1, RT_MASK2_WATT_HOURS, VESC_IF->mc_get_watt_hours(false), use_f32
2167+
buffer, &ind, mask2, RT_MASK2_WATT_HOURS, VESC_IF->mc_get_watt_hours(false), use_f32
21592168
);
21602169
add_rt_item(
21612170
buffer,
21622171
&ind,
2163-
mask1,
2172+
mask2,
21642173
RT_MASK2_WATT_HOURS_CHARGED,
21652174
VESC_IF->mc_get_watt_hours_charged(false),
21662175
use_f32
21672176
);
2177+
add_rt_item(buffer, &ind, mask2, RT_MASK2_MOTOR_ID, VESC_IF->foc_get_id(), use_f32);
21682178

21692179
SEND_APP_DATA(buffer, bufsize, ind);
21702180
}

0 commit comments

Comments
 (0)