Skip to content

Commit ef08c52

Browse files
authored
Fixes Missing RBR Readings (#368)
Ensures that probing the RBR cannot happen at the same time that an expected reading is incoming. This is due to the fact that the RBR cannot transmit and receive over UART at the same time! This is called "Data Blanking" in RBR's terminology.
1 parent 2a159f0 commit ef08c52

File tree

4 files changed

+78
-28
lines changed

4 files changed

+78
-28
lines changed

src/apps/bristleback_apps/bm_rbr/user_code/rbr_sensor.cpp

Lines changed: 34 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
#include "rbr_sensor.h"
22
#include "FreeRTOS.h"
33
#include "OrderedSeparatorLineParser.h"
4-
#include "spotter.h"
54
#include "configuration.h"
65
#include "payload_uart.h"
76
#include "rbr_sensor_util.h"
87
#include "serial.h"
8+
#include "spotter.h"
99
#include "stm32_rtc.h"
1010
#include "task_priorities.h"
1111
#include "uptime.h"
@@ -18,10 +18,10 @@ static constexpr char PRESSURE[] = "pressure";
1818
static constexpr char TEMPERATURE[] = "temperature";
1919

2020
/*!
21-
* @brief Initialize the RBR sensor driver.
22-
* @param type The sensor type.
23-
* @param min_probe_period_ms How often to check the sensor type in milliseconds.
24-
*/
21+
* @brief Initialize the RBR sensor driver.
22+
* @param type The sensor type.
23+
* @param min_probe_period_ms How often to check the sensor type in milliseconds.
24+
*/
2525
void RbrSensor::init(BmRbrDataMsg::SensorType_t type, uint32_t min_probe_period_ms) {
2626
_type = type;
2727
_stored_type = type;
@@ -52,12 +52,30 @@ void RbrSensor::init(BmRbrDataMsg::SensorType_t type, uint32_t min_probe_period_
5252
}
5353

5454
/*!
55-
* @brief Probe the sensor type if enough time has passed.
56-
*/
55+
* @brief Probe the sensor type if enough time has passed.
56+
*/
5757
void RbrSensor::maybeProbeType(uint64_t last_power_on_time) {
5858
uint64_t now = uptimeGetMs();
59+
60+
// Cannot transmit to the RBR while a reading is ongoing or else the
61+
// RBR will "blank" the streaming data, see:
62+
// https://docs.rbr-global.com/l3-command-reference/N/External/timeouts-output-blanking-and-power-saving
63+
// Create a window in which the probe can occur:
64+
//+--------------+---------------+---------------+
65+
//| 0ms | 200-300ms | 500ms |
66+
//+--------------+---------------+---------------+
67+
//| RBR reading | Probe TX | RBR reading |
68+
//+--------------+---------------+---------------+
69+
static constexpr uint32_t window_start_time =
70+
RBR_READING_PERIOD_MS / 2 - PROBE_WINDOW_WIDTH_MS / 2;
71+
static constexpr uint32_t window_end_time =
72+
RBR_READING_PERIOD_MS / 2 + PROBE_WINDOW_WIDTH_MS / 2;
73+
bool lower_window = now > _last_data_time + window_start_time;
74+
bool upper_window = now < _last_data_time + window_end_time;
75+
bool can_transmit = lower_window && upper_window;
76+
5977
if (now - _lastProbeTime >= _minProbePeriodMs &&
60-
now - last_power_on_time >= _minProbePeriodMs) {
78+
now - last_power_on_time >= _minProbePeriodMs && can_transmit) {
6179
PLUART::write((uint8_t *)typeCommand, strlen(typeCommand));
6280
_lastProbeTime = uptimeGetMs();
6381
_awaitingProbeResponse = true;
@@ -78,9 +96,12 @@ bool RbrSensor::getData(BmRbrDataMsg::Data &d) {
7896
handleOutputformat(_payload_buffer, read_len);
7997
} else if (BmRbrSensorUtil::validSensorDataString(_payload_buffer, read_len)) {
8098
success = handleDataString(_payload_buffer, read_len, d);
99+
if (success) {
100+
_last_data_time = uptimeGetMs();
101+
}
81102
} else {
82103
spotter_log(0, RBR_RAW_LOG, USE_TIMESTAMP, "Invalid line from sensor: %.*s\n", read_len,
83-
_payload_buffer);
104+
_payload_buffer);
84105
spotter_log_console(0, "Invalid line from sensor: %.*s", read_len, _payload_buffer);
85106
printf("Invalid line from sensor: %.*s\n", read_len, _payload_buffer);
86107
}
@@ -119,7 +140,7 @@ void RbrSensor::handleOutputformat(const char *s, size_t read_len) {
119140
BM_CFG_PARTITION_SYSTEM, CFG_RBR_TYPE, strlen(CFG_RBR_TYPE),
120141
static_cast<uint32_t>(BmRbrDataMsg::SensorType::PRESSURE_AND_TEMPERATURE));
121142
spotter_log(0, RBR_RAW_LOG, USE_TIMESTAMP,
122-
"Detected temp & pressure sensor, saving config\n");
143+
"Detected temp & pressure sensor, saving config\n");
123144
spotter_log_console(0, "Detected temp & pressure sensor, saving config");
124145
printf("Detected temp & pressure sensor, saving config.\n");
125146
save_config(BM_CFG_PARTITION_SYSTEM, true); // reboot
@@ -160,10 +181,10 @@ bool RbrSensor::handleDataString(const char *s, size_t read_len, BmRbrDataMsg::D
160181
rtcPrint(rtcTimeBuffer, NULL);
161182
if (_sensorBmLogEnable) {
162183
spotter_log(0, RBR_RAW_LOG, USE_TIMESTAMP, "tick: %" PRIu64 ", rtc: %s, line: %.*s\n",
163-
uptimeGetMs(), rtcTimeBuffer, read_len, s);
184+
uptimeGetMs(), rtcTimeBuffer, read_len, s);
164185
}
165-
spotter_log_console(0, "rbr | tick: %" PRIu64 ", rtc: %s, line: %.*s", uptimeGetMs(), rtcTimeBuffer,
166-
read_len, s);
186+
spotter_log_console(0, "rbr | tick: %" PRIu64 ", rtc: %s, line: %.*s", uptimeGetMs(),
187+
rtcTimeBuffer, read_len, s);
167188
printf("rbr | tick: %" PRIu64 ", rtc: %s, line: %.*s\n", uptimeGetMs(), rtcTimeBuffer,
168189
(int)read_len, s);
169190

src/apps/bristleback_apps/bm_rbr/user_code/rbr_sensor.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ class RbrSensor {
1010
_stored_type(BmRbrDataMsg::SensorType_t::UNKNOWN), _sensorDropDebounceCount(0),
1111
_sensorBmLogEnable(false), _minProbePeriodMs(0), _lastProbeTime(0),
1212
_awaitingProbeResponse(false), _parserTwoArguments(",", 256, parserValueTypeOne, 2),
13-
_parserThreeArguments(",", 256, parserValueTypeTwo, 3){};
13+
_parserThreeArguments(",", 256, parserValueTypeTwo, 3) {};
1414
void init(BmRbrDataMsg::SensorType_t type, uint32_t min_probe_period_ms);
1515
void maybeProbeType(uint64_t last_power_on_time);
1616
bool getData(BmRbrDataMsg::Data &d);
@@ -32,6 +32,9 @@ class RbrSensor {
3232
static constexpr char typeCommand[] = "outputformat channelslist\n";
3333
static constexpr uint8_t SENSOR_DROP_DEBOUNCE_MAX_COUNT = 3;
3434
static constexpr uint32_t PROBE_TYPE_TIMEOUT_MS = 1000;
35+
static constexpr uint32_t PROBE_WINDOW_WIDTH_MS = 100;
36+
static constexpr uint32_t RBR_READING_PERIOD_MS = 500;
37+
3538
static constexpr uint8_t NUM_PARSERS = 4;
3639
static constexpr char sensor_bm_log_enable[] = "sensorBmLogEnable";
3740

@@ -42,6 +45,7 @@ class RbrSensor {
4245
uint32_t _sensorBmLogEnable = 0;
4346
uint32_t _minProbePeriodMs = 0;
4447
uint64_t _lastProbeTime = 0;
48+
uint64_t _last_data_time = 0;
4549
bool _awaitingProbeResponse = false;
4650
OrderedSeparatorLineParser _parserTwoArguments;
4751
OrderedSeparatorLineParser _parserThreeArguments;

src/apps/rs232_expander_apps/bm_rbr/user_code/rbr_sensor.cpp

Lines changed: 34 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
#include "rbr_sensor.h"
22
#include "FreeRTOS.h"
33
#include "OrderedSeparatorLineParser.h"
4-
#include "spotter.h"
54
#include "configuration.h"
65
#include "payload_uart.h"
76
#include "rbr_sensor_util.h"
87
#include "serial.h"
8+
#include "spotter.h"
99
#include "stm32_rtc.h"
1010
#include "task_priorities.h"
1111
#include "uptime.h"
@@ -18,10 +18,10 @@ static constexpr char PRESSURE[] = "pressure";
1818
static constexpr char TEMPERATURE[] = "temperature";
1919

2020
/*!
21-
* @brief Initialize the RBR sensor driver.
22-
* @param type The sensor type.
23-
* @param min_probe_period_ms How often to check the sensor type in milliseconds.
24-
*/
21+
* @brief Initialize the RBR sensor driver.
22+
* @param type The sensor type.
23+
* @param min_probe_period_ms How often to check the sensor type in milliseconds.
24+
*/
2525
void RbrSensor::init(BmRbrDataMsg::SensorType_t type, uint32_t min_probe_period_ms) {
2626
_type = type;
2727
_stored_type = type;
@@ -52,12 +52,30 @@ void RbrSensor::init(BmRbrDataMsg::SensorType_t type, uint32_t min_probe_period_
5252
}
5353

5454
/*!
55-
* @brief Probe the sensor type if enough time has passed.
56-
*/
55+
* @brief Probe the sensor type if enough time has passed.
56+
*/
5757
void RbrSensor::maybeProbeType(uint64_t last_power_on_time) {
5858
uint64_t now = uptimeGetMs();
59+
60+
// Cannot transmit to the RBR while a reading is ongoing or else the
61+
// RBR will "blank" the streaming data, see:
62+
// https://docs.rbr-global.com/l3-command-reference/N/External/timeouts-output-blanking-and-power-saving
63+
// Create a window in which the probe can occur:
64+
//+--------------+---------------+---------------+
65+
//| 0ms | 200-300ms | 500ms |
66+
//+--------------+---------------+---------------+
67+
//| RBR reading | Probe TX | RBR reading |
68+
//+--------------+---------------+---------------+
69+
static constexpr uint32_t window_start_time =
70+
RBR_READING_PERIOD_MS / 2 - PROBE_WINDOW_WIDTH_MS / 2;
71+
static constexpr uint32_t window_end_time =
72+
RBR_READING_PERIOD_MS / 2 + PROBE_WINDOW_WIDTH_MS / 2;
73+
bool lower_window = now > _last_data_time + window_start_time;
74+
bool upper_window = now < _last_data_time + window_end_time;
75+
bool can_transmit = lower_window && upper_window;
76+
5977
if (now - _lastProbeTime >= _minProbePeriodMs &&
60-
now - last_power_on_time >= _minProbePeriodMs) {
78+
now - last_power_on_time >= _minProbePeriodMs && can_transmit) {
6179
PLUART::write((uint8_t *)typeCommand, strlen(typeCommand));
6280
_lastProbeTime = uptimeGetMs();
6381
_awaitingProbeResponse = true;
@@ -78,9 +96,12 @@ bool RbrSensor::getData(BmRbrDataMsg::Data &d) {
7896
handleOutputformat(_payload_buffer, read_len);
7997
} else if (BmRbrSensorUtil::validSensorDataString(_payload_buffer, read_len)) {
8098
success = handleDataString(_payload_buffer, read_len, d);
99+
if (success) {
100+
_last_data_time = uptimeGetMs();
101+
}
81102
} else {
82103
spotter_log(0, RBR_RAW_LOG, USE_TIMESTAMP, "Invalid line from sensor: %.*s\n", read_len,
83-
_payload_buffer);
104+
_payload_buffer);
84105
spotter_log_console(0, "Invalid line from sensor: %.*s", read_len, _payload_buffer);
85106
printf("Invalid line from sensor: %.*s\n", read_len, _payload_buffer);
86107
}
@@ -119,7 +140,7 @@ void RbrSensor::handleOutputformat(const char *s, size_t read_len) {
119140
BM_CFG_PARTITION_SYSTEM, CFG_RBR_TYPE, strlen(CFG_RBR_TYPE),
120141
static_cast<uint32_t>(BmRbrDataMsg::SensorType::PRESSURE_AND_TEMPERATURE));
121142
spotter_log(0, RBR_RAW_LOG, USE_TIMESTAMP,
122-
"Detected temp & pressure sensor, saving config\n");
143+
"Detected temp & pressure sensor, saving config\n");
123144
spotter_log_console(0, "Detected temp & pressure sensor, saving config");
124145
printf("Detected temp & pressure sensor, saving config.\n");
125146
save_config(BM_CFG_PARTITION_SYSTEM, true); // reboot
@@ -160,10 +181,10 @@ bool RbrSensor::handleDataString(const char *s, size_t read_len, BmRbrDataMsg::D
160181
rtcPrint(rtcTimeBuffer, NULL);
161182
if (_sensorBmLogEnable) {
162183
spotter_log(0, RBR_RAW_LOG, USE_TIMESTAMP, "tick: %" PRIu64 ", rtc: %s, line: %.*s\n",
163-
uptimeGetMs(), rtcTimeBuffer, read_len, s);
184+
uptimeGetMs(), rtcTimeBuffer, read_len, s);
164185
}
165-
spotter_log_console(0, "rbr | tick: %" PRIu64 ", rtc: %s, line: %.*s", uptimeGetMs(), rtcTimeBuffer,
166-
read_len, s);
186+
spotter_log_console(0, "rbr | tick: %" PRIu64 ", rtc: %s, line: %.*s", uptimeGetMs(),
187+
rtcTimeBuffer, read_len, s);
167188
printf("rbr | tick: %" PRIu64 ", rtc: %s, line: %.*s\n", uptimeGetMs(), rtcTimeBuffer,
168189
(int)read_len, s);
169190

src/apps/rs232_expander_apps/bm_rbr/user_code/rbr_sensor.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ class RbrSensor {
1010
_stored_type(BmRbrDataMsg::SensorType_t::UNKNOWN), _sensorDropDebounceCount(0),
1111
_sensorBmLogEnable(false), _minProbePeriodMs(0), _lastProbeTime(0),
1212
_awaitingProbeResponse(false), _parserTwoArguments(",", 256, parserValueTypeOne, 2),
13-
_parserThreeArguments(",", 256, parserValueTypeTwo, 3){};
13+
_parserThreeArguments(",", 256, parserValueTypeTwo, 3) {};
1414
void init(BmRbrDataMsg::SensorType_t type, uint32_t min_probe_period_ms);
1515
void maybeProbeType(uint64_t last_power_on_time);
1616
bool getData(BmRbrDataMsg::Data &d);
@@ -32,6 +32,9 @@ class RbrSensor {
3232
static constexpr char typeCommand[] = "outputformat channelslist\n";
3333
static constexpr uint8_t SENSOR_DROP_DEBOUNCE_MAX_COUNT = 3;
3434
static constexpr uint32_t PROBE_TYPE_TIMEOUT_MS = 1000;
35+
static constexpr uint32_t PROBE_WINDOW_WIDTH_MS = 100;
36+
static constexpr uint32_t RBR_READING_PERIOD_MS = 500;
37+
3538
static constexpr uint8_t NUM_PARSERS = 4;
3639
static constexpr char sensor_bm_log_enable[] = "sensorBmLogEnable";
3740

@@ -42,6 +45,7 @@ class RbrSensor {
4245
uint32_t _sensorBmLogEnable = 0;
4346
uint32_t _minProbePeriodMs = 0;
4447
uint64_t _lastProbeTime = 0;
48+
uint64_t _last_data_time = 0;
4549
bool _awaitingProbeResponse = false;
4650
OrderedSeparatorLineParser _parserTwoArguments;
4751
OrderedSeparatorLineParser _parserThreeArguments;

0 commit comments

Comments
 (0)