Introduction

Building a humanoid robot on wheels is one of the most challenging and rewarding engineering experiences. This guide covers the real-world lessons learned — from power failures to programming architecture decisions — while building a 4'5" humanoid robot with face detection, speech, and obstacle avoidance.


Phase 1 — Concept & Planning

Target Feature Set


Phase 2 — Power System (The Hard Lessons)

Attempt 1 — Power Bank (Failed)

We initially used a 20000mAh power bank rated at 18W output. Under load with the Raspberry Pi 4B running vision processing, the system became unstable and glitched constantly.

LESSON #1: Always check peak draw, not just idle. The Pi 4B can spike to 3A+ during AI processing. A power bank's burst output often can't sustain this — it throttles and causes voltage drops.

Attempt 2 — Lead-Acid Battery (Better, but Heavy)

We switched to a 12V 2.5Ah lead-acid scooter battery with a buck converter stepping voltage down to 5V for the Pi. This resolved the instability entirely.

LESSON #2: Lead-acid batteries are reliable but heavy. For portable robots, lithium-ion is the better choice. Always match your charger's current rating to battery specs — using a 12V 2A charger on this battery caused undercharging and performance degradation over time.

Attempt 3 — Wireless Charger Adapter (Wrong Tool)

We tested a 12V 3.5A wireless charger adapter. While it could supply more current, it was incompatible with the lead-acid chemistry and caused charging irregularities.

LESSON #3: Lead-acid batteries require chargers specifically designed for them with proper CC/CV charging profiles. Do not adapt other power sources — it risks battery damage and reduced lifespan.

Phase 3 — Python Layer (High-Level Tasks)

Python handles face recognition, speech synthesis and coordination between modules. Fast to prototype, but has real-time limitations.

Motor Control

import RPi.GPIO as GPIO

GPIO.setmode(GPIO.BCM)
GPIO.setup(MOTOR_PIN, GPIO.OUT)
GPIO.output(MOTOR_PIN, GPIO.HIGH)  # Motor ON

Face Recognition with OpenCV + Dlib

import cv2
import dlib

detector = dlib.get_frontal_face_detector()
camera = cv2.VideoCapture(0)

while True:
    ret, frame = camera.read()
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    faces = detector(gray)
    for face in faces:
        print(f"Face at: {face}")

Speech Synthesis

import pyttsx3

engine = pyttsx3.init()
engine.say("Hello human, I am operational.")
engine.runAndWait()

Multi-Threading

import threading

t1 = threading.Thread(target=control_motors)
t2 = threading.Thread(target=face_recognition)

t1.start()
t2.start()
PYTHON LIMITATION: Python's Global Interpreter Lock (GIL) prevents true parallel execution. For time-sensitive motor control, Python threading is insufficient — offload to C++.

Phase 4 — C++ Layer (Real-Time Control)

C++ owns anything touching hardware in real time — motor signals, sensor reads, interrupt handling.

Motor Control via WiringPi

#include <wiringPi.h>

wiringPiSetup();
pinMode(MOTOR_PIN, OUTPUT);
digitalWrite(MOTOR_PIN, HIGH);
delay(1000);
digitalWrite(MOTOR_PIN, LOW);

Ultrasonic Distance Sensor

long duration, distance;

digitalWrite(TRIG_PIN, LOW);
delayMicroseconds(2);
digitalWrite(TRIG_PIN, HIGH);
delayMicroseconds(10);
digitalWrite(TRIG_PIN, LOW);

duration = pulseIn(ECHO_PIN, HIGH);
distance = duration * 0.034 / 2;  // cm

Parallel Threads in C++

#include <thread>

std::thread motorThread(controlMotors);
std::thread sensorThread(readSensors);

motorThread.join();
sensorThread.join();

Phase 5 — Java Layer (Application Architecture)

Java manages the structured application logic, GPIO abstraction via Pi4J, and inter-module communication.

GPIO via Pi4J

import com.pi4j.io.gpio.*;

GpioController gpio = GpioFactory.getInstance();

GpioPinDigitalOutput motor = gpio.provisionDigitalOutputPin(
    RaspiPin.GPIO_01, "Motor", PinState.LOW
);

motor.high();               // Motor ON
Thread.sleep(1000);
motor.low();                // Motor OFF
gpio.shutdown();

Ultrasonic Sensor in Java

public class Test_Ultrasonic {
    public static void main(String[] args) throws Exception {
        PiJavaUltrasonic sonic = new PiJavaUltrasonic(
            0,          // Echo PIN
            1,          // Trig PIN
            1000,       // Rejection start (ns)
            23529411    // Rejection time  (ns)
        );

        System.out.println("Sensor Online");
        while (true) {
            System.out.println("Distance: " + sonic.getDistance() + " mm");
            Thread.sleep(1000);
        }
    }
}

Software Architecture — Final Split

FINAL ARCHITECTURE LESSON: Never try to do everything in one language on an embedded system. Match the language to the task's timing requirements. Python for brain, C++ for muscles, Java for skeleton.

Conclusion

This project was a crash course in real engineering — where textbook theory meets hardware failure, power constraints and real-time deadlines. Every failed power supply and throttled processor taught something no tutorial ever could.

The robot is a work in progress. Next steps include switching to LiPo batteries, adding a ROS communication layer and improving face recognition latency with a dedicated Edge AI module.

CONTACT TERMINAL