FAQ
This page is organized around the current CoCube MicroPython workflow. When something goes wrong, check "Connection and Flashing" first, then "Running and Files," and only then move on to the specific modules.
Connection and flashing
Thonny cannot see CoCube, or there is no serial port to select
Check these items first:
- Make sure CoCube is powered on. Hold the bottom power button for about
3seconds before connecting. - Make sure the USB cable supports data transfer. Some cables are charge-only and the computer will never see a serial port.
- Check whether the port changed after reconnecting the cable. Open Thonny's interpreter settings again and reselect the port manually.
- Make sure the computer has the serial driver it needs. On Windows, or on some macOS setups, you may need the
CH343driver.
If it still does not work, try a different cable first, then a different USB port. That is usually more effective than repeatedly restarting everything.
Flashing finished, but the Shell still does not show >>>
Check in this order:
- Make sure Thonny is still set to the correct port and the
MicroPython (ESP32)interpreter in the lower-right corner. - Click the red stop button in the toolbar to restart the interpreter.
- Unplug and reconnect CoCube, then select the port again in Thonny.
If you used the lower-level Flash Download Tool, also double-check:
- whether the chip model is correct
- whether the firmware file matches CoCube
- whether the flash address is correct
If any one of those is wrong, the device may fail to boot normally.
Why is firmware flashing always recommended over a wired USB connection?
Firmware flashing requires the highest stability, and a wired USB connection is still the safest option.
For the current MicroPython docs, it is also helpful to think of "flashing firmware" and "uploading .py files" as two separate things:
- Firmware flashing: prefer wired USB
- Daily development: then use Thonny to connect, run, and save scripts
Running and files
I saved the code to the device. Why does it not auto-run after reboot?
The most common reason is the filename.
MicroPython only auto-runs a file named main.py when the device powers on.
Files such as test.py or demo.py are saved on the device, but they do not start automatically.
If you want CoCube to keep running the program after it is disconnected from the computer, save the script as main.py.
main.py is already there. Why does it look like it stopped running as soon as I connect Thonny?
That is Thonny's default behavior. It does not necessarily mean the program is broken.
When Thonny connects, it usually interrupts the currently running program and enters the REPL.
That is why you can see this pattern:
- When the device powers on by itself,
main.pystarts automatically - As soon as Thonny connects, the program is interrupted and the Shell only shows
>>>
In that case you can:
- press
Ctrl + Din the Shell to soft reboot and watch the full startup sequence again - or change the related Thonny setting so that connecting does not interrupt the running program
The upload succeeded, but the screen does not respond
Do not assume the whole board is broken. Check these first:
- Does the program actually call
display.init()? - Are the text color and background color too similar?
- Does the code only use
print(...)in the Shell instead of drawing on the screen?
If you only want to verify that the screen works, start with the smallest possible example. The current firmware already includes a default Chinese font, so display.write() is enough:
import display
tft = display.init()
tft.fill(display.BLACK)
display.write("Hello, CoCube", 24, 40, display.YELLOW, display.BLACK)
Once the program enters while True, I cannot do anything in Thonny
That is normal. An infinite loop keeps the interpreter busy.
You can stop it by:
- clicking the red stop button in the Thonny toolbar
- or pressing
Ctrl + Cin the Shell
If you see KeyboardInterrupt in the Shell, that usually means the program was interrupted successfully, not that a new error has appeared.
Motion and positioning
Why does the robot not move as expected?
Time-based control is affected by many real-world factors, for example:
- the floor may be too slippery or too rough
- the battery level may be different
- the two tracks may have slightly different friction
So the same move_ms(...) or rotate_ms(...) code can produce slightly different paths on different surfaces.
A safer tuning order is:
- Keep the speed around
20~30first - Confirm the direction first
- Then adjust the timing values gradually
move_to(), rotate_to(), or cocube.pos.x does not look right
Check cocube.pos.state first.
- If
cocube.pos.stateis true, the position and angle data are reliable - If
cocube.pos.stateis false, do not continue relying on coordinate-based APIs
Common reasons include:
- CoCube is not on CoMaps
- it has moved outside the valid positioning area
- the current position is not updating stably
If positioning is invalid, move the robot back into the normal CoMaps area before testing further.
Expansion modules
The external module is attached, but nothing responds in the program
Check the easiest step to miss first: did you call cm.power_on()?
With the current firmware, many external modules should begin like this before you read from or control them:
import cocube_module as cm
cm.power_on()
Then test the smallest possible interface, for example:
- ToF:
cm.tof_connected()andcm.tof_distance() - Light sensor:
cm.dlight_level() - Voice:
cm.asr_get_command() - Gripper:
cm.gripper_open()
If even the smallest interface does not respond, then check whether the magnetic connection is secure.
The first ToF reading is false, -1, or -2
This is common. In many cases the module has just powered on and is not ready yet.
Use this order:
- after
cm.power_on(), wait a short moment first - if the first read fails, read again instead of assuming the module is broken
- treat negative values as invalid data first
Common return values in the current firmware are:
- a normal millimeter value: read succeeded
-1: invalid data-2: measurement timeout
Why does the gripper not move, or why does its angle look strange?
Check these items first:
- whether
cm.power_on()has been called - whether the angle is inside the
0~70range - whether
gripper_open(),gripper_close(), andgripper_degree(...)each work by themselves
In the current firmware:
0is closer to fully open70is closer to fully closed
If you mix base motion, gripper control, and coordinate control all at once from the start, it becomes much harder to tell which step is actually wrong.
Voice recognition
Why does the voice module never respond?
The most common reasons fall into four groups:
- the module has just powered on and is not ready yet
- the environment is too noisy
- the wake phrase was not spoken first
- the action logic was written too early before confirming the command ID
A safer test order is:
- Call
cm.power_on() - Wait a moment
- Speak a wake phrase first, such as
你好小智 - Then speak the command phrase
- In the program, only print the result of
cm.asr_get_command()
Once the command IDs are stable, then map them to actions.
Why do my learned custom commands not work?
Confirm these two things first:
- learned command IDs start from
4 - you have actually printed and confirmed the returned ID in code
Do not guess the number just because "this was the first command I recorded."
The safest way is still to print it first:
import time
import cocube_module as cm
cm.power_on()
time.sleep_ms(500)
while True:
print(cm.asr_get_command())
time.sleep_ms(50)
Also, before relearning commands, it is best to delete the old learned wake phrase or commands first, keep the environment quiet, and speak clearly.
AI camera
Why do read_card(), read_color(), or get_line() throw an error immediately?
That usually means the order is wrong, not that the camera is broken.
Camera APIs must be used in this order:
init()change_algo(...)- call the read function that matches the current algorithm
For example:
read_card()requiresCard Recogread_color()requiresColor Recogget_line(...)requiresLine Detect
If the algorithm does not match, the firmware throws an error directly instead of quietly returning an empty result.
The camera recognition result is unstable. What should I tune first?
Tune the environment and target before the code.
The best things to check first are:
- whether the target stands out clearly from the background
- whether line following uses a high-contrast scene such as black on white
- whether the line thickness is appropriate
- whether the card or target is too far away, making
wandhtoo small - whether multiple vision tasks are being mixed at the same time
The safest workflow is still:
- test one algorithm at a time
- print the result first
- only map it to chassis actions after the result is stable
Why do other peripherals behave differently as soon as the camera is initialized?
That is a resource-sharing characteristic of the current firmware, not a random bug.
After camera init():
cocube_moduleenters camera mode- the gripper control path changes
- the resources used by NeoPixel are occupied
So at the beginning of debugging, do not mix the camera, gripper, and NeoPixel all at once.
A safer order is:
- Get the camera working by itself
- Get the peripherals working by themselves
- Only then build a combined program
Still not solved?
Review the docs in this order:
- Set Up the Development Environment
- Basic Concepts
- The "Common issues / reminders" section in the related lesson page
- cocube core reference
- cocube_module reference
- Camera modules
If you can narrow the issue down to a more specific symptom such as "cannot connect," "no >>>," "cannot read data," or "has an ID but no action," troubleshooting usually becomes much faster.