Close

Day 2: Obstacle-Aware Tracing, Arm Control and Integration

A project log for EWNA Hackathon Team 12

This is our page for the EWNA Hackathon

arya-patelArya Patel 3 hours ago0 Comments

Mapping the maths to the real servos. Inverse kinematics now takes the measured arm dimensions: 105 mm and 98 mm links, with the shoulder 60 mm above the table. Its result is converted into actual servo commands using each servo's zero point and direction. Any angle outside a servo's safe range is rejected before it is sent. The solver also calculates a wrist angle that keeps the pen pointing straight down.

Check everything before moving: Before the arm moves at all, every point it will visit is checked for reachability: the marker, the lift height, and every waypoint on the path. If anything is out of reach, the run stops up front instead of halfway through a drawing.

The full sequence. One run goes like this:

  1. Home the arm.
  2. Find the marker and remember where it is.
  3. Find the path.
  4. Travel to the marker with the pen raised.
  5. Lower to grasp height, close the gripper, and lift.
  6. Travel to the path start.
  7. Lower the pen and trace the line.
  8. Return the marker to the exact spot it was picked from.
  9. Home again.

Not mistaking itself for an obstacle: Obstacle detection compares each frame with the empty-workspace reference. The arm itself would show up as a difference, so each frame we blank out the arm's own area: a 70 mm-wide strip from the base to the arm's current position, plus a 35 mm circle at the gripper. We blank out the marker's pick-up spot the same way. Only real obstacles are left.

Handling the obstacle on the line. While tracing, the arm looks 80 mm ahead along the path. When an obstacle lies within 25 mm of the upcoming line:

  1. The pen lifts.
  2. The arm travels around the obstacle at pen-up height, choosing whichever side it can actually reach.
  3. It rejoins the line at the first waypoint that is at least 30 mm clear of the obstacle.
  4. The pen goes back down and tracing continues.

If the obstacle covers the rest of the line, the arm holds and waits for it to be removed, giving up after 2 minutes. The same logic protects every other movement too.

Staying in sync with the servos: The Python side estimates how long each move takes (15 ms per degree) and waits for it to finish before sending the next one. This keeps it from flooding the ESP32 with commands. When the link connects, it sends PING commands until the ESP32 answers. The ESP32 is found automatically by its USB-serial chip, and the camera by its ID. If the kill switch is pressed during a move, the controller switches to an OVERRIDE state. When the switch is released, it resumes and repeats the interrupted move.

Dry-run mode: python main.py --dry-run runs the complete task against a simulated arm that logs every command it would send. This let us test the whole sequence with the real camera before risking the hardware.

ESP32 firmware updates: We replaced the ESP32Servo library with direct 16-bit PWM using the ESP32's built-in LEDC hardware. The new code builds on both Arduino-ESP32 core version 2 and version 3. We also measured the arm's home pose (85.7°, 26.4°, 72.1°, 81.0°). On boot the arm now eases back to that pose at 5°/s. The current position is saved to flash every second, so after a power cut the arm resumes from where it actually was.

Discussions