-
-
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] LPF2 Motors appear to go out of sync sometimes. #679
Comments
How long do you let the program run before stopping? How many iterations does it take to get a failure? Which motors are you using? Which hub are you using? |
A second, maybe two. It doesn’t seem to matter. Sometimes it happens in 5 tries, sometimes more. This particular test was two medium angular motors (blue) on a prime hub. |
It’s quite possible it’s something else though. I was planning to see if I could reproduce it with just the IODevice class to rule that out. Now that we use a single mode, that class works fine for reading motor modes too. |
I've also noticed that it gets stuck in an infinite poll loop sometimes after this happens when you restart the program. So here's a theory why this usually happens at the start of a program, and why it didn't happen before. In pb_device we now always call set_mode at the start. This is supposed to do nothing if the mode is already set, but maybe we occasionally get a bad message that sets the mode wrong. Then when setting the mode again on restart, it all goes wrong. |
I am not able to reproduce the issue with firmware built from pybricks/pybricks-micropython@697a368 and the same hardware. |
I've seen it multiple times today even with the latest build. I'll try on different hardware tomorrow. |
The aforementioned infinite loop (light matrix keeps going) when immediately restarting when this occurs is probably a separate bug. When you try set up the motor, |
Back to the main bug. With debug prints on, we see a bit more:
But that's only part of it. The mode may be "valid" (low enough), but still wrong. I also added the following debug info. See also comment about mode check: diff --git a/lib/pbio/src/uartdev.c b/lib/pbio/src/uartdev.c
index a0f77af5..cb23364c 100644
--- a/lib/pbio/src/uartdev.c
+++ b/lib/pbio/src/uartdev.c
@@ -15,7 +15,7 @@
#if PBIO_CONFIG_UARTDEV
-#define DEBUG 0
+#define DEBUG 1
#if DEBUG
#include <inttypes.h>
#define debug_pr(fmt, ...) printf((fmt), __VA_ARGS__)
@@ -579,11 +579,14 @@ static void pbio_uartdev_parse_msg(uartdev_port_data_t *data) {
DBG_ERR(data->last_err = "Invalid mode received");
goto err;
}
- data->iodev.mode = mode;
+ data->iodev.mode = mode; // <--- Should this be inside the switch below?
if (mode == data->new_mode) {
memcpy(data->iodev.bin_data, data->rx_msg + 1, msg_size - 2);
}
-
+ else {
+ debug_pr("Expected data for mode %d ", data->new_mode);
+ debug_pr("but got data for mode %d\n", mode);
+ }
// setting type_id in info struct lets external modules know a device is connected and receiving good data
data->info->type_id = data->type_id; And then we see:
Which explains this:
|
This script triggers it more quickly. Since this script completes quickly, just keep pressing F5 to run it: from pybricks.pupdevices import Motor
from pybricks.tools import wait
from pybricks.parameters import Port, Direction
from pybricks.robotics import DriveBase
from pybricks import version
print(version)
unused = Motor(Port.A)
left_motor = Motor(Port.C, Direction.COUNTERCLOCKWISE)
right_motor = Motor(Port.D)
drive_base = DriveBase(left_motor, right_motor, wheel_diameter=56, axle_track=112)
drive_base.straight(10) Build it with debug print on, with a variant of the above patch to print debug info on a bad mode. This happens more often (but still not every time). |
Or maybe this is of those inconvenient timing issues that make it harder to reproduce. If I comment out pb_flash_file_write("/_pybricks/main.mpy", *buf, len); in main, which is partially blocking, this does not appear to occur, so far. |
That makes sense (and is why we can't have any blocking functions). The UART buffer is probably overflowing while the blocking function is running. To add a hack on top of a hack, we could probably run PBIO events ( |
This replaces the polling SPI implementation (deactivated in the previous commit) with asynchronous DMA driven SPI transfers. This fixes motors going out of sync when starting programs. Fixes pybricks/support#679 This also avoids touching file systems used by other known firmwares, so that Pybricks can operate entirely stand alone. This reduces the complexity of firmware installation and troubleshooting, because there are no dependencies on prior firmwares or hub state. It also lays the groundwork for saving and storing program data on Powered Up hubs, but this isn't fully implemented in order to preserve compatibility with Pybricks Code and the existing tutorial videos.
This replaces the polling SPI implementation (deactivated in the previous commit) with asynchronous DMA driven SPI transfers. This fixes motors going out of sync when starting programs. Fixes pybricks/support#679 This also avoids touching file systems used by other known firmwares, so that Pybricks can operate entirely stand alone. This reduces the complexity of firmware installation and troubleshooting, because there are no dependencies on prior firmwares or hub state. It also lays the groundwork for saving and storing program data on Powered Up hubs, but this isn't fully implemented in order to preserve compatibility with Pybricks Code and the existing tutorial videos.
This replaces the polling SPI implementation (deactivated in the previous commit) with asynchronous DMA driven SPI transfers. This fixes motors going out of sync when starting programs. Fixes pybricks/support#679 This also avoids touching file systems used by other known firmwares, so that Pybricks can operate entirely stand alone. This reduces the complexity of firmware installation and troubleshooting, because there are no dependencies on prior firmwares or hub state. It also lays the groundwork for saving and storing program data on Powered Up hubs, but this isn't fully implemented in order to preserve compatibility with Pybricks Code and the existing tutorial videos.
This replaces the polling SPI implementation (deactivated in the previous commit) with asynchronous DMA driven SPI transfers. This fixes motors going out of sync when starting programs. Fixes pybricks/support#679 This also avoids touching file systems used by other known firmwares, so that Pybricks can operate entirely stand alone. This reduces the complexity of firmware installation and troubleshooting, because there are no dependencies on prior firmwares or hub state. It also lays the groundwork for saving and storing program data on Powered Up hubs, but this isn't fully implemented in order to preserve compatibility with Pybricks Code and the existing tutorial videos.
This replaces the polling SPI implementation (deactivated in the previous commit) with asynchronous DMA driven SPI transfers. This fixes motors going out of sync when starting programs. Fixes pybricks/support#679 This also avoids touching file systems used by other known firmwares, so that Pybricks can operate entirely stand alone. This reduces the complexity of firmware installation and troubleshooting, because there are no dependencies on prior firmwares or hub state. It also lays the groundwork for saving and storing program data on Powered Up hubs, which can be implemented in a future commit.
This still seems to be happening, but now it has to be for different reasons. EDIT: See #738 |
This was reopened for #738 which is now fixed, so we can close this too. |
Describe the bug
Sometimes the control update loop stops, which manifests as a ENODEV at the user level.
Although technically inconclusive, this appears to have started in pybricks/pybricks-micropython@ae927ac, so before switching to the new calib mode and before fixing uartdev for fast syncing.
The reason why I currently believe it really does goes out of sync, is that you can restart the failed script a bit sooner than before, now that we fixed the fast syncup.
To reproduce
While it doesn't seem deterministic, the following program seems to eventually reproduce it within a few minutes.
Repeatedly Use F5/F6 in Pybricks Code to stop and restart the following program. Just let two motors C and D spin freely. No need to build a drivebase.
Repeat until you eventually get:
The text was updated successfully, but these errors were encountered: