-
-
Notifications
You must be signed in to change notification settings - Fork 7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Bug] ColorDistanceSensor takes two cycles to sync up on City Hub on boot #747
Comments
There seem to be several issue here. I made a test from pybricks/pybricks-micropython@d80df1a with the following patch to turn power to the I/O off and back on again before the device connection manager starts running: diff --git a/lib/pbio/drv/ioport/ioport_lpf2.c b/lib/pbio/drv/ioport/ioport_lpf2.c
index e609e0b5..f605b9e4 100644
--- a/lib/pbio/drv/ioport/ioport_lpf2.c
+++ b/lib/pbio/drv/ioport/ioport_lpf2.c
@@ -466,15 +466,20 @@ PROCESS_THREAD(pbdrv_ioport_lpf2_process, ev, data) {
PROCESS_BEGIN();
- etimer_set(&timer, 2);
+ pbdrv_gpio_out_low(&pbdrv_ioport_lpf2_platform_data.port_vcc);
for (int i = 0; i < PBDRV_CONFIG_IOPORT_LPF2_NUM_PORTS; i++) {
init_one(i);
}
+ etimer_set(&timer, 500);
+ PROCESS_WAIT_EVENT_UNTIL(ev == PROCESS_EVENT_TIMER && etimer_expired(&timer));
+
// Turn on power on pin 4 on all ports
pbdrv_gpio_out_high(&pbdrv_ioport_lpf2_platform_data.port_vcc);
+ etimer_set(&timer, 2);
+
for (;;) {
PROCESS_WAIT_EVENT();
Full log attached. Attachment can be viewed with Saleae Logic 2. |
Are we sure this is right? // To get in sync with the data stream from the sensor, we look for a valid TYPE command.
for (;;) {
PBIO_PT_WAIT_READY(&data->pt, err = pbdrv_uart_read_begin(data->uart, data->rx_msg, 1, EV3_UART_IO_TIMEOUT));
if (err != PBIO_SUCCESS) {
DBG_ERR(data->last_err = "UART Rx error during sync");
goto err;
}
PBIO_PT_WAIT_READY(&data->pt, err = pbdrv_uart_read_end(data->uart));
if (err == PBIO_ERROR_TIMEDOUT) {
continue;
}
if (err != PBIO_SUCCESS) {
DBG_ERR(data->last_err = "UART Rx error during sync");
goto err;
}
if (data->rx_msg[0] == (LUMP_MSG_TYPE_CMD | LUMP_CMD_TYPE)) {
break;
}
} It seems to just read all bytes and accept any value of So it would often hit In the current |
Combined with your findings, and assuming this device has no way of kicking it into the first stage of sync mode (unlike the other sensors), waiting for "1.5 cycles" on average is perhaps not a bug but the best we can do. Aside from boot (this issue), the dcm is just taking quite a bit longer since we changed the |
Yes, it has to get 3 bytes in a row that is a valid type command with checksum, not just one byte. |
I'm not sure what you mean by this, can you elaborate? |
I don't think we actually changed it, only fixed a bug where it was ignored after the first detection. We could probably get away with making it 10 instead of 20. |
But it is only reading one. |
Yes, but then it reads 2 more after that to validate. |
Right, and then it goes into the generic error, which triggers the whole Instead I'm thinking to just go back to the sync step a few times before giving up and handling the generic error. sync:
// To get in sync with the data stream from the sensor, we look for a valid TYPE command.
for (;;) {
PBIO_PT_WAIT_READY(&data->pt, err = pbdrv_uart_read_begin(data->uart, data->rx_msg, 1, EV3_UART_IO_TIMEOUT));
if (err != PBIO_SUCCESS) {
DBG_ERR(data->last_err = "UART Rx error during sync");
goto err;
}
PBIO_PT_WAIT_READY(&data->pt, err = pbdrv_uart_read_end(data->uart));
if (err == PBIO_ERROR_TIMEDOUT) {
continue;
}
if (err != PBIO_SUCCESS) {
DBG_ERR(data->last_err = "UART Rx error during sync");
goto err;
}
if (data->rx_msg[0] == (LUMP_MSG_TYPE_CMD | LUMP_CMD_TYPE)) {
break;
}
}
// then read the rest of the message
PBIO_PT_WAIT_READY(&data->pt, err = pbdrv_uart_read_begin(data->uart, data->rx_msg + 1, 2, EV3_UART_IO_TIMEOUT));
if (err != PBIO_SUCCESS) {
DBG_ERR(data->last_err = "UART Rx error while reading type");
goto err;
}
PBIO_PT_WAIT_READY(&data->pt, err = pbdrv_uart_read_end(data->uart));
if (err != PBIO_SUCCESS) {
DBG_ERR(data->last_err = "UART Rx error while reading type");
goto err;
}
bool bad_id = data->rx_msg[1] < EV3_UART_TYPE_MIN || data->rx_msg[1] > EV3_UART_TYPE_MAX;
checksum = 0xff ^ data->rx_msg[0] ^ data->rx_msg[1];
bool bad_id_checksum = data->rx_msg[2] != checksum;
if (bad_id || bad_id_checksum) {
DBG_ERR(data->last_err = "Bad device type id or checksum");
if (data->err_count > 10) {
data->err_count = 0;
goto err;
}
data->err_count++;
goto sync;
} |
I don't think it used to do that. I think this would be enough. If the sensor is disconnected, the read will time out triggering the goto err. diff --git a/lib/pbio/src/uartdev.c b/lib/pbio/src/uartdev.c
index 0271e208..dc8dba14 100644
--- a/lib/pbio/src/uartdev.c
+++ b/lib/pbio/src/uartdev.c
@@ -780,6 +780,7 @@ static PT_THREAD(pbio_uartdev_update(uartdev_port_data_t * data)) {
goto err;
}
+retry:
// To get in sync with the data stream from the sensor, we look for a valid TYPE command.
for (;;) {
PBIO_PT_WAIT_READY(&data->pt, err = pbdrv_uart_read_begin(data->uart, data->rx_msg, 1, EV3_UART_IO_TIMEOUT));
@@ -816,13 +817,13 @@ static PT_THREAD(pbio_uartdev_update(uartdev_port_data_t * data)) {
if (data->rx_msg[1] < EV3_UART_TYPE_MIN || data->rx_msg[1] > EV3_UART_TYPE_MAX) {
DBG_ERR(data->last_err = "Bad device type id");
- goto err;
+ goto retry;
}
checksum = 0xff ^ data->rx_msg[0] ^ data->rx_msg[1];
if (data->rx_msg[2] != checksum) {
DBG_ERR(data->last_err = "Bad checksum for type id");
- goto err;
+ goto retry;
}
// if all was good, we are ready to start receiving the mode info |
That's what the above does, only it doesn't keep trying forever. EDIT: I suppose the timeout handles that too. |
At least for about 3 years 😄 |
The city hub powers on the I/O ports (pin 4) during boot, so by the time the device connection manager detected a UART device, in many cases, it was too late to catch the device on the first sync. In the case of the BOOST color distance sensor, this meant waiting 10 seconds instead of 5 for the sensor to be ready. This adds an option to enable a workaround for the quirk that cycles power to the I/O ports immediately after boot. This is faster than waiting for the next sync cycle. Issue: pybricks/support#747
The flush needs to be immediately before the read, otherwise the read buffer can contain garbage that was read while sending the baud rate. Also, the ACK usually comes in < 1 ms so we don't need to wait so long. This improves the chances of not missing data if the ACK doesn't come, e.g. on the BOOST Color Distance sensor. Fixes: pybricks/support#747
The city hub powers on the I/O ports (pin 4) during boot, so by the time the device connection manager detected a UART device, in many cases, it was too late to catch the device on the first sync. In the case of the BOOST color distance sensor, this meant waiting 10 seconds instead of 5 for the sensor to be ready. This adds an option to enable a workaround for the quirk that cycles power to the I/O ports immediately after boot. This is faster than waiting for the next sync cycle. Issue: pybricks/support#747
The flush needs to be immediately before the read, otherwise the read buffer can contain garbage that was read while sending the baud rate. Also, the ACK usually comes in < 1 ms so we don't need to wait so long. This improves the chances of not missing data if the ACK doesn't come, e.g. on the BOOST Color Distance sensor. Fixes: pybricks/support#747
The city hub powers on the I/O ports (pin 4) during boot, so by the time the device connection manager detected a UART device, in many cases, it was too late to catch the device on the first sync. In the case of the BOOST color distance sensor, this meant waiting 10 seconds instead of 5 for the sensor to be ready. This adds an option to enable a workaround for the quirk that cycles power to the I/O ports immediately after boot. This is faster than waiting for the next sync cycle. Issue: pybricks/support#747
The flush needs to be immediately before the read, otherwise the read buffer can contain garbage that was read while sending the baud rate. Also, the ACK usually comes in < 1 ms so we don't need to wait so long. This improves the chances of not missing data if the ACK doesn't come, e.g. on the BOOST Color Distance sensor. Fixes: pybricks/support#747
The city hub powers on the I/O ports (pin 4) during boot, so by the time the device connection manager detected a UART device, in many cases, it was too late to catch the device on the first sync. In the case of the BOOST color distance sensor, this meant waiting 10 seconds instead of 5 for the sensor to be ready. This adds an option to enable a workaround for the quirk that cycles power to the I/O ports immediately after boot. This is faster than waiting for the next sync cycle. Issue: pybricks/support#747
This is not completely fixed yet since pybricks/pybricks-micropython#175 didn't get merged. |
The city hub powers on the I/O ports (pin 4) during boot, so by the time the device connection manager detected a UART device, in many cases, it was too late to catch the device on the first sync. In the case of the BOOST color distance sensor, this meant waiting 10 seconds instead of 5 for the sensor to be ready. Something similar was happening on Technic Hub, where it would always miss the first synchronization cycle. This adds a workaround that cycles power to the I/O ports immediately after boot. This is faster than waiting for the next sync cycle. Issue: pybricks/support#747
Describe the bug
When booting the City Hub with the Color Distance sensor plugged in, it takes two full cycles to sync up.
On the SPIKE Prime Hub, it syncs up quickly on boot, but it also needs two full cycles when plugging it in later.
See pybricks/pybricks-micropython#121 for a video and code example.
This is not critical for the beta, and also not really for the 3.2 release, so I will not add the 3.2 project tag for now.
The text was updated successfully, but these errors were encountered: