Skip to content
Noah Spiegelman
Back to all projects

Project

RASTICrane

ME416, Boston University · Fall 2026

A wooden robotic arm built for ME416: Intro to Robotics, with three servos driven by an ESP32. The instructions and laser-cut files were provided, so the challenge wasn't designing an arm. It was getting the hardware and software to work together in about a week. Still in progress: next, it will pick up rubber stamps and stamp names onto paper.

Role
Assembly, soldering and servo control
Tools
ESP32, Arduino (C++), Servo motors, Soldering, MQTT
  • Mechanical
  • Embedded
Side view of the wooden robotic arm reaching out to the left from its base, with three servo wires and a USB cable running to the ESP32 board on the right
In progress
The arm reaching out from its base, with the ESP32 on the right.
The arm moving under servo control, in two clips shown back to back.

Problem

The arm's design, instructions and laser-cut files were all provided to us, so the challenge of this project wasn't designing a robotic arm. It was to struggle through and persevere, working with hardware and software to make this work in a short amount of time, about a week.

Robotics is difficult because if one part of the robot doesn't work, none of it does. This project took a lot of effort and made me adapt over and over.

Approach

The laser-cut file was designed for a thinner piece of wood than the one I used, so I had to sand down a lot of the connections and jam some of the others together. I also had to sand the tight servo horn pockets that were cut out of the wood.

The joints took tuning too. They had to be loose enough to rotate freely, but not so loose that they came undone.

The ESP32 sits on a PCB that I soldered by hand. The pin headers had to be perfectly vertical for the ESP32 to fit onto the board, and the connections were so close together that too much solder would spill over while too little would give a poor electrical joint. We ran continuity tests and resoldered whenever one failed.

Getting the ESP32 to communicate over MQTT took the longest. A good chunk of the class, along with the professor, worked together in the robotics maker space from noon until 11:30 at night trying to figure it out. The cause turned out to be that some of the wood was blocking the ESP32's Wi-Fi chip, and that requirement was removed.

We were instructed to write all the code with AI, for two reasons: AI is going to be part of our work anyway, so we might as well use it to our advantage, and there wasn't nearly enough time to write it all by hand.

We had discretion over how to move and control the arm, so I chose to select a servo and an angle and send the arm there. The sketch runs on the ESP32 and drives three servos, one 300° and two 180°. The snippets below show how it works.

The full range of a servo isn't necessarily the full range of the robot. If I sent an angle too far one way or the other, the arm crashed into itself or the surface it sat on and the servo stalled, so I had to be careful about which angles I commanded.

Results

The arm is assembled and moving under servo control (video above), and the project is still in progress. The biggest lesson was persistence: a tight fit, a bad solder joint or a blocked antenna can stop the whole robot, and each one had to be found and fixed.

Next, the arm becomes a stamp machine for the course's second lab. A magnet on the end effector lifts rubber stamps by their steel discs, inks each one on an ink pad, presses it onto a sheet of paper and returns it to the rack, one letter at a time, until our names are on the page. Nothing is measured by hand while it runs, so it all has to come through the camera.

That means calibrating the camera and finding AprilTags on the base plate, the stamps, the ink pad and the paper. A homography from the base tag turns pixels into positions on the table, and inverse kinematics turns those positions into servo commands sent to the arm over MQTT. We will run the same code on both of our arms and compare how far each letter lands from where it was commanded.

Code

Moving smoothly
void stepToUs(ServoUnit &s, float targetUs) {
  while (abs(targetUs - s.currentUs) > STEP_US) {
    s.currentUs += (targetUs > s.currentUs) ? STEP_US : -STEP_US;
    writePulseUs(s.pin, s.currentUs);
    delay(STEP_DELAY_MS);
  }
  s.currentUs = targetUs;
  writePulseUs(s.pin, s.currentUs);
}

Each servo remembers where it currently is. To move, it steps toward the target pulse width 7 microseconds at a time with an 8 millisecond pause between steps, so the arm glides instead of snapping to position. Those two constants set the speed.

Choosing a servo and an angle
void moveServo(int index, float angle) {
  ServoUnit &s = servos[index];

  if (angle < 0 || angle > s.maxAngle) {
    // print an error and ignore the command
    return;
  }

  float targetUs = mapFloat(angle, 0, s.maxAngle, MIN_US, MAX_US);
  stepToUs(s, targetUs);
}

A command names a servo and an angle. The angle is checked against that servo's limit (300° for the first servo, 180° for the other two), converted to a pulse width between 500 and 2500 microseconds, and then eased there with the function above.

Serial commands and reset
if (line.equalsIgnoreCase("reset")) {
  // Retract distal joints first so the arm is folded
  // before the shoulder swings
  const int resetOrder[3] = {2, 1, 0};
  for (int k = 0; k < 3; k++) {
    stepToUs(servos[resetOrder[k]], 1500);
  }
  return;
}

int servoNum;
float angle;
int parsed = sscanf(line.c_str(), "%d %f", &servoNum, &angle);
// ...checks that both values were read and servoNum is 1-3...
moveServo(servoNum - 1, angle);

The sketch reads a line over serial, such as "2 90" to send the second servo to 90°. Typing "reset" returns every servo to its center position, moving the outer joints first so the arm folds up before the shoulder swings and doesn't crash into anything.

Front view of the robotic arm's base with its servo, laser-engraved labels and the soldered ESP32 board, and the arm extended behind it
The base, with the servo and the ESP32 board I soldered.
Angled view of the robotic arm reaching to the right, with parallel wooden links held together by screws and the base engraved with ME416: Intro to Robotics, Fall 2026
The parallel links, held together with screws.
Three-quarter view of the robotic arm reaching out to the left and down from its base, with the end plate close to the table
The arm reaching out and down.