Making the robot's head
Reinforced them with cardboard with vertical grain
Done with the body structure!
➡️
Teaching us how to cut 90 degree on band saw machine
❌
✅
Done!
One of the arm(human-like)
Redo body structure
Saw the base support wood at an angle so that the top board is flat
design arms (both)
make arms (both)
base!!!!!(do it in the lab)
how to attach motor?(add wooden board maybe)
finish the head(cut paper, dig holes, leave space for LED)
how to attach head? will we have a neck?
Done 2
L- brackets
Done the last L- bracket and the base
Fixed servos
Second arm(Robot-like)
(and then use zip ties to fix the shape)
One of the arm(human-like)
Redo body structure
Saw the base support wood at an angle so that the top board is flat
How we fixed two different arms to servos:
⬅️ Zip ties & hot glue
Cut a servo horn-shaped hole in the intermediate connecting cardboard
& hot glue ➡️
arduino mega (also the circuit board)
neck structure (servo+board cut)
Fix the middle column
Fix mega to the middle column
code+test servo!!!!!!!!
Made the arm move!
Completed human arm +
robotic arm
layer1
➡️
Completed the neck structure.
layer2
➡️
The red arrow is the direction of the face.
layer3
circuit board+soldering
make 3 servos (head、arms) move properly! (may need a extra power bank)
after this,do some fixing like servo to board...
try to do the antenna (the forth servo,dig holes...)
Tested 2 servos and head moving together ✅
Built the internal structure
Make transmitter and receiver work together:
2 neopixel eyes
Music shield
Soldering pixel LED screens using sockets and wires
We labeled the different pins on the wires to prevent confusion
Debug1:fixed the radio(signal) connection
Debug2:Fixed the sound by resoldering the music shield
Debug3:Fixed the transmitter error
Successfully enabled the transmitter to control sound and light:
Making antenna📍
Small wooden pieces used to help screws secure the socket
The antenna was fixed to the servo using strong glue
➡️
Arm LED📍
Debug:
The first time, the LED short-circuited at the solder joint (possibly due to the hand gripping the connection), causing the LED to overheat abnormally.
The second time, the high temperature during soldering damaged the LED.
The third time, the LED didn't respond to the code; it only started randomly changing colors when a hand touched the wire (this was probably also a short circuit)
Fixed Eyes LED
Debug:
The second pixel wasn't emitting light. After testing, we found that the problem was with the output soldering of the first pixel.
Eyes LED ✅
Arm LED ✅
➡️
We finally figured out the power supply layout:
the wheel motor needs 12V
the Arduino controlling the wheels needs 5V
the Arduino board above needs two 5V supplies to the two boards *We previously thought the three servos needed 12V, and we suspect that's why we burned out two LED strips
After rehearsals, we preliminary finalized the script and cases.
Case testing:
Fixed eyes!
➡️
Wire management
Plan Until Final
November 25 (after class):
• Finalize the script for the child robot
• Fix remaining bugs in the case code
• Design around 10 cases
• Produce around 10 audio files
• Write and successfully test code for ~10 cases (including the newly added LED strips)
November 26 (entire afternoon):
• Continue designing cases
• Continue producing audio files
• Continue writing and testing code — as many cases as possible
Before class on November 27:
• Complete all hardware mounting and component fixing
November 28–29:
• Finish all case development
November 30:
• Rest day
National Day Holiday — December 1 & 2:
• Complete all external elements: painting, costume, head shell, internal structural fixing, and additional small components/lights
Remaining time:
• I expect the coding process may not go as smoothly as planned, so the rest of the time will be dedicated to debugging.
We created a new document to write cases.
What I found useful was that:
We used blue highlights to represent actions, making it easier for Sarah to control the robot's movement during the performance; yellow to represent test cases, making it easier for me to control the robot's behavior; and red to indicate problematic areas, such as bugs in the code, making it easier to troubleshoot later. Fixed bugs were then highlighted again with pink, making it easier to recall the process later.
Regarding the code, I'll use summarize to explain the problem I solved:
1. Making a servo move smoothly and synchronously isn't difficult, but achieving both simultaneously is challenging, prone to lag, and can even affect the transmitter.
(in this case, loop also has LED in it)
for (int i = 0; i <= smoothSteps; i++) {
float t = i / (float)smoothSteps;
Head.write(headCenter + (headLeft - headCenter) * t);
//left forward leftCenter - armStep * t
LeftArm.write(leftCenter - armStep * t);
//right behind = rightCenter + armStep * t
RightArm.write(rightCenter + armStep * t);
// LED:
unsigned long now = millis();
if (now - lastDiscoUpdate > discoInterval) {
lastDiscoUpdate = now;
for (int j = 0; j < LED_COUNT; j++) {
strip.setPixelColor(j,
random(20, 60),
random(20, 60),
random(20, 60)
);
}
strip.show();
}
delay(30);
}
delay(100);
I use this simple method for about half of my work to prevent lag:
// Arms
int leftCenter = 60;
int rightCenter = 100;
int armStep = 30;
int smoothSteps = 40;
// Forward
for (int i = 0; i <= smoothSteps; i++) {
float t = i / (float)smoothSteps;
LeftArm.write(leftCenter - armStep * t);
RightArm.write(rightCenter + armStep * t);
delay(20);
}
delay(100);
// Backward
for (int i = 0; i <= smoothSteps; i++) {
float t = i / (float)smoothSteps;
LeftArm.write((leftCenter - armStep) + armStep * t * 2);
RightArm.write((rightCenter + armStep) - armStep * t * 2);
delay(20);
}
delay(100);
2. Although we paid attention to the angles when fixing the servo, we still stumbled a bit while writing the code.
The left hand is defined as having a 60° angle when the arm hangs naturally.
Raising it forward decreases the angle, swinging it backward increases the angle.
All movements are: smooth interpolation from start to target.
The left and right hands are mirror images.
The left hand is defined as having a 100° angle when the arm hangs naturally.
Raising the left hand forward uses subtraction, raising the right hand forward uses addition.
Eg.
case 29: {
Serial.println(F("Case 29"));
// raise arm first
int startPos = 100; // current position
int endPos = 180; // highest position
int smoothSteps = 50; // smoother for high lift
for (int i = 0; i <= smoothSteps; i++) {
float t = i / (float)smoothSteps;
int armPos = startPos + (endPos - startPos) * t; // 100 → 180
RightArm.write(armPos);
delay(20);
}......
3. Regarding the arm LED and servo movement:
Firstly, I was using `millis()` for all LEDs.
I tried directly writing the code within the `case` statements, but due to insufficient battery power, the servo vibrated violently.
I tried using function calls, repeatedly writing `discoMode=false; setWhiteDim()...` in each `case`, which also caused the servo to vibrate violently.
Eg.
// light section
// disco
void discoLights() {
if (!discoMode) return; // do not flash if disabled
unsigned long now = millis();
if (now - lastDiscoUpdate > discoInterval) {
lastDiscoUpdate = now;
// random flashing
for (int i = 0; i < LED_COUNT; i++) {
strip.setPixelColor(i,
random(30, 255),
random(30, 255),
random(30, 255)
);
}
strip.show();
}
}
// white
void setWhiteDim() {
for (int i = 0; i < LED_COUNT; i++) {
strip.setPixelColor(i, strip.Color(40, 40, 40));
}
strip.show();
}
// red
bool detectMode = false;
unsigned long lastDetectUpdate = 0;
int detectState = 0; // 0=off, 1=on
void detectLights() {
if (!detectMode) return;
unsigned long now = millis();
if (now - lastDetectUpdate > 150) { // blink speed
lastDetectUpdate = now;
detectState = !detectState;
for (int i = 0; i < LED_COUNT; i++) {
if (detectState) {
strip.setPixelColor(i, strip.Color(255, 0, 0)); // bright red
} else {
strip.setPixelColor(i, 0); // off
}
}
strip.show();
}
}
So, I tried resetting to white light mode by default at the beginning of the loop, and then enabling the corresponding mode in each `case`:
`discoMode = false;`
`detectMode = false;`
`finalMode = false;`
`finalfinalMode = false;`
`discoDeepMode = false;`
`setWhiteDim();`
However, this caused the code to freeze, and repeatedly calling `strip.show()` in the `case` statements caused frequent color changes. Chatgpt said that the conflict between these two approaches would generate huge current spikes.
3. I looked at Meera's code. First, their entire code logic is completely different from ours; modifying it would basically require rewriting. Second, I think their code works because their servo has almost no movement.
So in the end I changed it to have the LED blink first, and then the servo move, and the effect was surprisingly good.
Eg.
Case 7: {
Serial.println(F("Case 7"));
// LED blink effect (multiple flashes)
Serial.println(F("LED blinking..."));
int blinkCount = 3; // Number of blinks
int blinkDelay = 200; // Blink interval (ms)
for (int blink = 0; blink < blinkCount; blink++) {
// ON (brighter red than case 6)
for (int i = 0; i < LED_COUNT; i++) {
strip.setPixelColor(i, 60, 0, 0); // Brighter red
}
strip.show();
delay(blinkDelay);
// OFF
for (int i = 0; i < LED_COUNT; i++) {
strip.setPixelColor(i, 0, 0, 0);
}
strip.show();
delay(blinkDelay);
}
// After blinking, keep red light on
for (int i = 0; i < LED_COUNT; i++) {
strip.setPixelColor(i, 60, 0, 0); // Bright red steady
}
strip.show();
Serial.println(F("Red light maintained - starting arm movement..."));
// Arm continues from case 6
int startPos = 100 + 30; // End of case 6 = 130°
int endPos = 100 + 60; // Target = 160°
int smoothSteps = 40;
for (int i = 0; i <= smoothSteps; i++) {
float t = i / (float)smoothSteps;
int armPos = startPos + (endPos - startPos) * t; // 130 → 160
RightArm.write(armPos);
delay(20);
}
Decorative design draft :
1.Color with metallic paint
2.Using gel as the head (Sarah and I noticed this in our film class ⬇️) gives it a more futuristic feel
3. Draw some children's doodles
4. Arm patterns
5. Hung up the strip lights (we actually did this on the day of the performance).
The strip lights were very long, and to prevent them from drawing the audience's attention away from the robot's belly, we took two paper bags from the cafeteria to wrap them up and secure them.
Perfect!
Fixed a huge problem:
When I added the arm-raising code, I found that a single servo horn was not enough to raise the entire arm, causing the arm to tilt to one side.
The arm structure was redesigned using zip ties, allowing it to naturally tilt inwards ⬇️
Fixed!
Plan Update for last 3 days:
External components: install decorative lights, antenna lights, and head lights; organize wiring and power supply
Code: add arm lights; add two group cheering sound effects; update case names for the transmitter
Sound clips: two clips still missing; add two group cheering sound effects
Block movement and print the final version
Fix the wheels
After rehearsals, we found that the gel on the head was too dark and lacked the translucent mecha feel. Also, the antenna weren't very noticeable.
Therefore, we plan to place a backward-facing LED strip on the front of the head and two ring-shaped LEDs on the antenna.
Since we ran out of empty pins on the Mega, we used a new Arduino board and a power bank for power, and also added a breadboard ➡️ *Because the wires in the breadboard were prone to coming loose, we sealed them with several layers of tape.
The two circular patterns are continuous, forming a figure eight
Lit up!
To Prof. Michael,
This was honestly one of the most interesting classes I’ve taken. The class atmosphere and workload were both really well balanced.
Beyond being incredibly helpful, I also think you’re just a really cool professor, the marathon running, gym life, all of that 🙂 Thank you so much for the time and energy you put into this course. It truly became one of the highlights of my study-away experience and made it feel especially meaningful.