Posted 03 August 2026,
Part 1 in this series laid out the strategy for adding vision processing capabilities to my 4-wheel robot. This post continues that effort.
The first step was to replace the Teensy 3.6 main controller with a Teensy 4.1. As part of this process, I also replaced the glued-on ‘Gnd’ and ‘+5V’ bussbars with a bit more finished product, as you can see in the following photos:








The next step is moving the old 4-wheel firmware to the ‘new-improved’ 4-wheel hardware. I started this by porting “C:\Users\Frank\Documents\Arduino\WallE3_Git\WallE3_Git\WallE3_Git.ino” to “C:\Users\Frank\Documents\Robot_Projects\VisionEnhaned4WheelRobot_V1\VisionEnhaned4WheelRobot_V1.ino”. This took a while, and I’m not sure I wouldn’t have been better off just cloning the entire WallE3_Git.ino file, but I “got it done’.
05 August 2026 Update:
It took a while, but I now have a working 4-wheel drive robot program running again on the 4-wheel chassis with a Teensy 4.1 main controller The only small ‘gotcha’ I encountered during the Teensy 3.5 -> Teensy 4.1 controller switch was the control lines for the right motor driver. It turns out the ‘speed’ (PWM) pin used on the Teensy 3.5 isn’t PWM-capable on the Teensy 4.1, so this required some minor pin swapping, as shown below:
|
1 2 3 4 5 6 7 8 9 |
//08/05/26 pin 35 isn't PWMable on Teensy 4.1, but pin 33 is //const uint16_t InA_Right = 34; //const uint16_t InB_Right = 33; //const uint16_t Spd_Right = 35; //Teensy 4.1 const uint16_t InA_Right = 34; const uint16_t InB_Right = 35; const uint16_t Spd_Right = 33; |
Using the manual control features built accessible via the ‘CheckforUserInput() function, I was able to perform left/right 10 degree turns and speed up/slow down, all from my keyboard. I don’t have the second deck connected up yet, but that is next on the agenda.
06 August 2026 Update:

At this point I have a complete 4-wheel drive robot assembled with a Raspberry Pi5 and OAKD-Lite camera, and I can send it basic (left/right/faster/slower/forward/reverse) movement commands via a serial port. In previous work on the 2-wheel robot I demonstrated the ability to send vision-processing-derived movement commands to the main processor from the Pi5 via a serial port.
It occurs to me that with the above capability, The robot doesn’t really need anything else for navigation and obstacle avoidance. The OAKD-Lite can provide visual depth information to the Pi5, and the Pi5 can send basic movement commands to the robot. In addition, it seems to me that I might be able to eliminate the entire ‘homing-to-charger’ software and hardware blocks, as the camera should be able to tell the Pi5 where the charger dock is located in the field of view, and the Pi5 should be able to tell the robot which way to turn and by how much, and when to speed up and slow down. This could make the robot a LOT simpler (as Elon Musk said about Tesla FSD “Once you have vision solved, you no longer need anything else’).
08 August 2026 Update:
The robot is alive! With Grok’s help I now have a python script running on the Pi5 that can direct the robot to turn left or right depending on image processing by the OAKD-Lite camera.
First, the Python shell script ‘restart_camera.sh’ is executed to get the OAKD-Lite camera ready:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
pi@RobotPi5:~$ cd my_vision_robot/ pi@RobotPi5:~/my_vision_robot$ ./software/scripts/restart_camera.sh === Killing old camera processes === === Sourcing environments === === Starting camera === [INFO] [launch]: All log files can be found below /home/pi/.ros/log/2026-08-08-08-25-25-554555-RobotPi5-3196 [INFO] [launch]: Default logging verbosity is set to INFO [INFO] [camera_node-1]: process started with pid [3200] [camera_node-1] [INFO] [1786191927.851165044] [camera]: Starting camera. [camera_node-1] [INFO] [1786191927.875363720] [camera]: No ip/mxid specified, connecting to the next available device. [camera_node-1] [INFO] [1786191930.182731755] [camera]: Camera with MXID: 19443010B166F01200 and Name: 4.1 connected! [camera_node-1] [INFO] [1786191930.184436975] [camera]: USB SPEED: SUPER [camera_node-1] [INFO] [1786191930.211320937] [camera]: Device type: OAK-D-LITE [camera_node-1] [INFO] [1786191930.213305230] [camera]: Pipeline type: Depth [camera_node-1] [ERROR] [1786191930.379447850] [camera]: rgb parameters not set, defaulting to 1280x720 unless specified otherwise. [camera_node-1] [INFO] [1786191930.380454015] [camera]: Finished setting up pipeline. [camera_node-1] [INFO] [1786191930.680038467] [camera]: Camera ready! |
Once the camera is ready, then the demo program ‘clearest_direction_node.py’ is executed on the Pi5 (with ‘VisionEnhanced4WheelRobot.ino already running on the Teensy 4.1)
Based on a rudimentary analysis of the depth (distance) distribution in the camera field of view, the ‘clearest_direction_node.py’ Python script sends left/right/stop commands to the Teensy 4.1 from the Pi5’s serial port to the Teensy 4.1’s ‘Serial1’ port. The commands use the already-existing robot manual motion control command structure shown below:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
ENTERING COMMAND MODE: 0 = 180 deg CCW Turn 1 = 180 deg CW Turn A = Abort - Reboots Processor / = Forward .(dot) = Reverse * = Exit ChkForUserInput() Faster 8 Left 4 5 6 Right 2 Slower |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
pi@RobotPi5:~/my_vision_robot$ python3 software/scripts/clearest_direction_node.py --ros-args -p enable_motion:=True [INFO] [1786192457.618821619] [clearest_direction_node]: Motion ENABLED – opened /dev/ttyAMA0 @ 115200 and sent "C" (command mode) [INFO] [1786192457.672358648] [clearest_direction_node]: Clearest Direction Node started (7 sectors, bottom half only) [INFO] [1786192457.689451373] [clearest_direction_node]: Sent "6" → right 10° (recommended 31°) [INFO] [1786192467.311608370] [clearest_direction_node]: Sent "5" → stop (turn 0° inside deadband ±6.0°) [INFO] [1786192468.114612060] [clearest_direction_node]: Sent "6" → right 10° (recommended 31°) [INFO] [1786192478.041447563] [clearest_direction_node]: Sent "4" → left 10° (recommended -10°) [INFO] [1786192478.846585878] [clearest_direction_node]: Sent "6" → right 10° (recommended 31°) [INFO] [1786192481.741594815] [clearest_direction_node]: Sent "5" → stop (turn 0° inside deadband ±6.0°) [INFO] [1786192482.545474512] [clearest_direction_node]: Sent "6" → right 10° (recommended 31°) [INFO] [1786192490.073479144] [clearest_direction_node]: Sent "4" → left 10° (recommended -31°) [INFO] [1786192490.877634051] [clearest_direction_node]: Sent "6" → right 10° (recommended 31°) [INFO] [1786192493.239450490] [clearest_direction_node]: Sent "5" → stop (turn 0° inside deadband ±6.0°) [INFO] [1786192494.044599603] [clearest_direction_node]: Sent "6" → right 10° (recommended 31°) |
Here’s a short video showing the action
At this point in the project, we have demonstrated that visual ‘depth’ information can be used to guide the robot, and we have separately demonstrated that the Teensy firmware can be updated ‘Over The Air’ (OTA) via the wifi connection to the Pi5. I believe the next step should be to add wifi OTA to the ‘clearest_direction_node.py’ script in order to remove the requirement for physically attaching a USB cable to the Teensy 4.1 to update the firmware.
Stay tuned!
Frank