H2Woah OTV
An autonomous vehicle for ENES100's water-sampling mission. An overhead camera tells it where it is in the arena. At the pool it lowers an arm, measures the water's depth, checks it for pollution and pumps a sample. Then it follows the wall past the obstacles and drives under the limbo to the goal.
I wire the robot and write most of its code. My teammates each write a subsystem as its own Arduino sketch, and I merge those into one codebase and fix whatever breaks. I test everything in ENES100's browser simulator first. A single build flag switches the same code between the simulator and the real robot.
- 40/40
- randomized simulator runs passed
- 1,620
- lines of firmware
- 7
- bench tests, one per subsystem
Select a block to see what it does and how it's wired.
The arena's overhead camera reads an ArUco marker on top of the robot and sends its position and heading over Wi-Fi. Every navigation decision uses that position. Watches for obstacles ahead so the robot can steer around them. Each reading is the median of several pings, so a single bad echo won't stop the robot. Points down at the water from a known height. The depth is that height minus the distance to the surface. Reads the water's color through filtered channels to check for pollution. It uses six pins, more than any other part. The same C++ runs on the real robot and in ENES100's browser simulator, chosen by a build flag. GitHub Actions compiles both versions on every push. Two DRV8871 H-bridges drive the motors. PWM is capped at 153 of 255 because the motors are rated for 6 V and the pack is 9.6 V. Two SG90 servos move together one degree at a time, which keeps their current spikes from browning out the 5 V rail they share. A MOSFET on D10 turns the pump on and off to pull the water sample. A 9.6 V NiMH pack powers the motor drivers directly. The Arduino runs from its own regulated supply.The route my code drives in ENES100's simulator, drawn to scale on the 4 × 2 m arena. The robot starts in a random square and samples the pool in the other one. It then drives up to the top wall, follows it through the 25 cm gap past both rows of obstacles, and cuts down to the limbo lane to reach the goal. I checked 40 randomized runs against the robot's footprint. It never went more than 1 mm past a wall, and it cleared the obstacles by 1.6 to 2 cm.