Skip to content

Week 10 : Output devices

Week 10 assignment could be categorized as follows:

  • Group assignment

    • Power consumption measurement of output devices
  • Individual assignment

    • Integration of output device (to designed embedded microcontroller system)
Types of Output Sensors and Actuators
  • Displays

    • E-ink / E-paper: Extremely low power, retains image without power, readable under any light.
    • LCD (Liquid Crystal Display): Can show text and simple graphics, but limited pixel control. Not recommended for flexible projects.
    • OLED (Organic Light-Emitting Diode): Pixel-addressable, brighter, higher contrast, and more versatile than LCD. Common driver is the SSD1306 module.
    • TFT (Thin-Film Transistor): Larger than OLED, supports full-color graphics.
  • LEDs

    • RGB LED: Combines Red, Green, and Blue LEDs in a single package to produce multiple colors.
    • Single-color LED
  • Motors

    Motor Type Rotation Type / Motion Control Method Noise Level Maintenance Torque Type Applications
    Brushed DC Motor Continuous rotation Voltage / PWM (speed control) Noisy Brushes wear out Torque ∝ Current Simple motion, toys, fans
    Brushless DC (BLDC) Motor Continuous rotation PWM via driver (speed control; driver handles commutation) Quiet Low Torque ∝ Current Drones, fans, smooth continuous motion
    Servo Motor Controlled rotation / specific angle Closed-loop position control (PWM sets desired position; feedback adjusts motor) Low Low Controlled by feedback (position) Robotics, RC vehicles, precise positioning
    Stepper Motor Discrete steps / incremental rotation Step pulses (each pulse moves a fixed step; open-loop) Moderate Low Torque per step CNC, 3D printers, repeatable positioning
    • Brushed DC Motor

      • To drive a DC motor in one direction, an N-channel MOSFET can be used to switch the current.
      • To drive in both directions (bipolar), an H-bridge (typically with N- and P-channel MOSFETs) is required.
      • Adding a capacitor across the H-bridge supply helps reduce voltage spikes and protect the MOSFETs.
      • Always check torque vs. current curves from the datasheet to ensure safe operation and proper sizing.
    • Brushless DC (BLDC) Motor

      • No brushes → quieter and longer-lasting than brushed DC motors.
      • Requires a triple half-bridge driver, e.g., A4949.
      • Back EMF affects current and torque (see notes below).
      • Ideal for smooth, continuous rotation.
    • Servo Motor

      • Uses closed-loop feedback (potentiometer or encoder) to maintain precise position.
      • Typically controlled with PWM at ~50 Hz.
      • Can be built with DC or BLDC motors internally.
    • Stepper Motor

      • Moves in discrete steps, usually 1.8° per step.
      • Has a stall (holding) torque rating, the maximum torque it can hold without moving.
      • Half-stepping and microstepping improve smoothness and resolution. Adding decoupling capacitance to the driver can further reduce voltage fluctuations.
      • Bipolar stepper motors require two complete H-bridges (one per coil) and drivers like DRV8428.
      • Stepper vs. Servo: Without feedback, stepper motors are open-loop; adding feedback makes them behave like a servo. Stepper motors are generally lower-cost and more available, but may require microstepping for smooth motion.
    • Back EMF (Electromotive Force)

      • Voltage generated by a spinning motor that opposes the applied voltage, caused by electromagnetic induction.
      • Present in all rotating motors (Brushed DC, BLDC, Stepper).
      • Low speed → small back EMF → higher current → high starting torque.
      • High speed → higher back EMF → lower current → prevents overcurrent and protects motor.

      • Formulas:

        1. Back EMF proportional to angular speed:
        \[ E_b = k_e \cdot \omega \]

        Where:
        - \(E_b\) = Back EMF (V)
        - \(k_e\) = Motor back EMF constant (V·s/rad)
        - \(\omega\) = Angular velocity (rad/s)

        1. Voltage-current relationship in a DC motor:
        \[ V_{\text{applied}} = I \cdot R + E_b \]

        or equivalently:

        \[ I = \frac{V_{\text{applied}} - E_b}{R} \]

        Where:
        - \(V_{\text{applied}}\) = Supply voltage (V)
        - \(I\) = Motor current (A)
        - \(R\) = Motor winding resistance (Ω)
        - \(E_b\) = Back EMF (V)

  • Speaker

    • The MA98357A is a digital audio amplifier chip that communicates using the I²S (Inter-IC Sound) protocol, which is similar to I²C but for audio data.
  • Solenoid

    • An electromechanical device that converts electrical energy into linear motion.
    • When current flows through the coil, it generates a magnetic field that moves a metal plunger or armature.

Source: ChatGPT by OpenAI, March 2026

Basics of USB - data & power

The universal serial bus (USB) is widely used standard for connecting devices and so this section is dedicated to discusss it.

  • USB ports :
    • USB Type-A: Classic rectangular port, usually a host/power source.
    • USB Type-B: Squarish port, common for printers or older devices.
    • Micro-USB / Mini-USB: Smaller connectors for older mobile devices or development boards.
    • USB Type-C: Reversible (i.e. no "up" or "down" orientation, both sides are okay), supports higher data rates and Power Delivery up to 100 W.
  • Standards
    • USB 2.0 :
      • Data transfer speed : 480 Mbps
      • Supports power delivery : Yes
    • USB 3.0/3.1/3.2 :
      • Data transfer speed : 5 Gbps / 10Gbps / 20 Gbps
      • Supports power delivery : Yes (except some gen 3.2 USB)
      • Additional note :
        • Apple's thunderbolt is basically USB 3.2.
        • Backward compatible i.e. can be used at USB 2.0 ports
    • Regarding power delivery:
      • Some power/charging standards allow devices to draw more power safely than standard USB limits
      • USB BC (battery charging) : Often marked as BC on older computers, chargers, or hubs.
      • USB PD (power delivery) : Usually available on USB-C ports. Often marked as "PD" or USB-C logo with a lightning bolt symbol

Source: ChatGPT by OpenAI, March 2026

Power consumption measurement of output devices

Electrical safety considerations

  • On current :
    • 1 mA : still okay
    • 10 mA : can cause involuntary muscle constraction. Possibly difficult in letting go of the conductor
    • 100 mA : can cause heart attack
  • On capacitors : can store electrical charge even after the power supply is turned off and so could pose the risk of electric shock. Proper discharge of it is required before handling or modifying a circuit.

The SEEED studio Grove system is used again this week, but focusing more on the output devices. At the time of writing this documentation there are 7 Grove devices that are available at Chaihuo makerspace and 2 of it were tested for power consumption - due to the following reasons :

  • Grove - Speaker : Enables variation in output e.g. frequency and so allows to detect power consumption changes
  • Grove - Mini fan (brushless motor) : Power consumption can be characterized by varying the supply voltage and measuring the resulting current draw
Device Name Interface Additional notes
Grove - Speaker Analog -
Grove - Mini Fan Digital -
Device Name Interface Additional notes
Grove - Electromagnet Digital -
Grove - Buzzer Digital -
Grove - Relay Digital -
Grove - LCD RGB Backlight I2C Not recommended to use - see notes above
Grove - Vibration Motor Digital Produces vibration (haptic output)

The following sections describes the result of the experiment.

Speaker

Sound is generated by applying Pulse Width Modulation (PWM) to the speaker module. The frequency of these signals determine the pitch of the sound : higher frequencies produce higher-pitched notes while lower frequencies produce deeper tones.

Yes, it's playing twinkle-twinkle litte star.

The working speaker code could be seen at the admonition below.

Speaker x XIAO ESP32C3 code
#define SPEAKER 3

// Notes (Hz)
#define C4 262
#define D4 294
#define E4 330
#define F4 349
#define G4 392
#define A4 440

// Melody (Twinkle Twinkle)
int melody[] = {
C4, C4, G4, G4, A4, A4, G4,
F4, F4, E4, E4, D4, D4, C4
};

// Note durations
int duration[] = {
400, 400, 400, 400, 400, 400, 800,
400, 400, 400, 400, 400, 400, 800
};

void setup() {
ledcAttach(SPEAKER, 1000, 8);
}

void loop() {
for (int i = 0; i < 14; i++) {
    ledcWriteTone(SPEAKER, melody[i]);
    delay(duration[i]);
    ledcWriteTone(SPEAKER, 0); // pause between notes
    delay(50);
}

delay(2000); // wait before repeating
}

Where :

  • ledcAttachPin(pin,channel) links a physical GPIO pin to a PWM channel on the ESP32.
  • ledcWriteTone(channel, frequency) generates a square wave (tone) at a specified frequency on the attached PWM channel

The power consumption of the speaker was measured with the digital multimeter and the DC power supply.

Power consumption = 58 - 65 mA x 5 V = 0.290 - 0.325 W

Power consumption = 59 - 60 mA x 5 V = 0.300 W

With a constant 5 V, greater fluctuation on the current reading was observed on the digital multimeter compared to the DC power supply. This behaviour is perhaps due to the difference in internal filtering and averaging feature between these two machines. However, the difference is minimum and so no further investigation is done to check the reason of the discrepancy.

Mini fan

The next experiment is observing the behaviour of the DC brushless motor mini fan by varying the voltage (i.e. 3 V , 4 V, 5 V) with the DC power supply. No code is used and connection is made directly between the two.

Power consumption = 205 mA x 3 V = 0.62 W

Power consumption = 295 mA x 4 V = 1.18 W

Power consumption = 388 mA x 5 V = 1.94 W

It is observed that as voltage increases, the motor's power rises rapidly due to increased current draw. Furthermore, the motor operates on a higher power level compared to the speaker (i.e. for 5V, mini fan consumes 6x more power).

Previous tests were conducted under no-load conditions. The system was then tested under full load by manually applying resistance (using a finger) to completely stop the movement.

Under full load, the system consumes approximately 5 W of power (1000 mA × 5 V). Notably, this is higher than the power consumption of many modern 1 W LED bulbs available today.

Brushless DC motor

A 20 A ESC (Electronic Speed Controller) with an integrated 5 V/2 A BEC (Battery Eliminator Circuit) and a brushless motor was available at the makerspace, and the owner kindly agreed to lend the equipment - so a test that goes beyond the standard 5 V could be conducted. Specifications of the motor are as follows :

  • ESC: Interprets PWM signals to control the speed and direction of the brushless motor. This model can supply up to 20 A continuously to the motor.

  • BEC: Steps down the battery voltage to a stable 5 V supply capable of providing up to 2 A. In this setup, the 5 V output is used to power the CCPM Servo Consistency Master - the signal generator.

  • Input voltage: 2-4S LiPo battery (i.e. 1S = 3.7 V, and so 2S = 7.4V , 4S = 14.8 V)

The brushless motor draws enough current to reach a maximum power of around 14 W with the 12 V (i.e. 3 x the mini fan).

The next experiment was conducted at 24 V. However, this exceeded the maximum voltage rating of the motor driver (i.e. 4S = 14.8 V), and as a result, the ESC was damaged. This was evident when the DC power supply switched from CV to CC mode, indicating an overcurrent condition and activation of the protection circuitry. Lessons learnt : understand the limits of the equipments before conducting tests

Integration of output device

Building on Week 6 : Electronics design, a 0.96-inch OLED display (128 × 64 pixels, I2C) has been added to the setup to visually show both the current angle or position of the servo motor and the readings from the photoresistors; and so the only addition to the original code is the interface with the display. This could be seen at the following admonition.

XIAO ESP32C3 x 2 servo motors x 4 photoresistors x 0.96 inch OLED code
#include <Arduino.h>
#include <Servo.h>
#include <Wire.h>
#include <Adafruit_SSD1306.h>

// ---------------- OLED SETTINGS ----------------
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET    -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

// Specify your OLED pins
#define SDA_PIN 6
#define SCL_PIN 7

// ---------------- SERVO SETTINGS ----------------
Servo servoVertical;     
Servo servoHorizontal;   

int verticalPos = 90;
int horizontalPos = 90;

const int servoLimitHigh = 180;
const int servoLimitLow  = 0;

// ---------------- SERVO PINS ----------------
const int servoVerticalPin   = D10;
const int servoHorizontalPin = D9; 

// ---------------- LDR PINS ----------------
const int ldrNorth = A0;
const int ldrSouth = A1; 
const int ldrEast  = A2;  
const int ldrWest  = A3; 

const int ADC_MAX = 4095;   // 12-bit ADC for ESP32
const int tolerance = 150;

void setup() {
Serial.begin(115200);

// Set ADC to 12-bit for ESP32
analogReadResolution(12);  // Now analogRead() returns 0-4095

// Initialize Servos
servoVertical.attach(servoVerticalPin);
servoHorizontal.attach(servoHorizontalPin);
servoVertical.write(verticalPos);
servoHorizontal.write(horizontalPos);
delay(1000);

// Initialize I2C with custom pins
Wire.setSDA(SDA_PIN);
Wire.setSCL(SCL_PIN);
Wire.begin();

// Initialize OLED
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println("SSD1306 allocation failed");
    for(;;);
}
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0,0);
display.println("Solar Tracker Init");
display.display();
delay(1000);

Serial.println("===== PIN CONFIGURATION =====");
Serial.print("North LDR -> GPIO "); Serial.println(ldrNorth);
Serial.print("South LDR -> GPIO "); Serial.println(ldrSouth);
Serial.print("East  LDR -> GPIO "); Serial.println(ldrEast);
Serial.print("West  LDR -> GPIO "); Serial.println(ldrWest);
Serial.print("Vertical Servo   -> GPIO "); Serial.println(servoVerticalPin);
Serial.print("Horizontal Servo -> GPIO "); Serial.println(servoHorizontalPin);
Serial.println("OLED SDA -> GPIO 6 | SCL -> GPIO 7");
Serial.println("=============================");
}

void loop() {
// -------- READ LDR VALUES --------
int northValue = analogRead(ldrNorth);
int southValue = analogRead(ldrSouth);
int eastValue  = analogRead(ldrEast);
int westValue  = analogRead(ldrWest);

int diffVertical   = northValue - southValue;
int diffHorizontal = eastValue - westValue;

// -------- VERTICAL MOVEMENT --------
String vertDir = "-";
if (abs(diffVertical) > tolerance) {
    int stepSize = map(abs(diffVertical), tolerance, ADC_MAX, 1, 5);
    if (diffVertical > 0) {
    verticalPos += stepSize;
    vertDir = "^";  // ASCII UP
    } else {
    verticalPos -= stepSize;
    vertDir = "v";  // ASCII DOWN
    }
    verticalPos = constrain(verticalPos, servoLimitLow, servoLimitHigh);
    servoVertical.write(verticalPos);
}

// -------- HORIZONTAL MOVEMENT --------
String horDir = "-";
if (abs(diffHorizontal) > tolerance) {
    int stepSize = map(abs(diffHorizontal), tolerance, ADC_MAX, 1, 5);
    if (diffHorizontal > 0) {
    horizontalPos += stepSize;
    horDir = ">";  // ASCII RIGHT
    } else {
    horizontalPos -= stepSize;
    horDir = "<";  // ASCII LEFT
    }
    horizontalPos = constrain(horizontalPos, servoLimitLow, servoLimitHigh);
    servoHorizontal.write(horizontalPos);
}

// -------- SERIAL OUTPUT --------
Serial.print("Vert: "); Serial.print(verticalPos); Serial.print(" "); Serial.print(vertDir);
Serial.print(" | Hor: "); Serial.print(horizontalPos); Serial.println(horDir);

// -------- OLED UPDATE --------
display.clearDisplay();
display.setCursor(0,0);
display.setTextSize(1);
display.println("Solar Tracker");
display.println("-------------------");
display.print("V: "); display.print(vertDir); display.print(" "); display.println(verticalPos);
display.print("H: "); display.print(horDir); display.print(" "); display.println(horizontalPos);
display.println("-------------------");
display.print("N:"); display.print(northValue); display.print(" ");
display.print("S:"); display.print(southValue); display.println();
display.print("E:"); display.print(eastValue); display.print(" ");
display.print("W:"); display.print(westValue); display.println();

display.display();
delay(100); // small delay for stability
}

Where :

  • display.begin(SSD1306_SWITCHCAPVCC, 0x3C) initializes the OLED display at I2C address 0x3C
  • display.setCursor(x, y) sets the starting position (in pixels) for text or graphics on the OLED
  • display.setTextSize(n) sets the text scale
  • display.setTextColor(SSD1306_WHITE) sets the text color
  • display.print()/display.println() writes text to display at the current cursor lication
  • display.display() must be called after writing content for it to appear on the screen

This setup highlights how a breadboard-based design can become very messy, especially with multiple components and long jumper wires. For improved reliability and clarity, transferring the circuit to a PCB design is recommended. Additionally, using darker-colored wires for ground and bright or distinct colors for power lines can help prevent wiring mistakes and make the circuit easier to debug.

It is well-known that transient (sudden) spikes in current occur when motor like servos, start or change direction. Although the overall power change can be observed using the DC power supply, a more detailed visualization of this phenomenon using the oscilloscope could perhaps provide insight into the magnitude and effects.This in turn helps user to evaluate potential benefit of adding capacitors (see notes in Week 6 : Electronics design).

It was found later that the available series resistor at the makerspace was only 0.25 W. Since previous measurements at 5 V showed currents on the order of 0.2 A, using this resistor in series would exceed its safe power rating. As a result, the current spikes could not be measured directly. Instead, a check on the voltage dip (i.e. because current increases, voltage needs to decrease if resistance are the same overall) is done to detect this change.

A test is also made to see the effect of adding 100 µF capacitor into the system.

The result could be seen below.

Maximum voltage : 5.5 V, Minimum voltage : 4.3 V

Maximum voltage : 5.2 V, Minimum voltage : 4.3 V

With it installed, the voltage spike was reduced from approximately 5.5 V to 5.2 V, showing that the capacitor helps smooth transient fluctuations. It would be interesting in the future to see the impact of higher-capacitance capacitor to the system especially on the voltage dip.