Íñigo Gutiérrez Febles
← Back to overview
Week 10

Output Devices

in-progress

weekly schedule.

Time blockWedThuFriSatSunMonTueWed
Global class3 h
Local class1,5 h1,5 h
Research1 h2 h
Design2 h4 h
Fabrication1 h
Documentation2 h3 h
Review

overview.

If input devices are about reading the world, output devices are about acting on it. This week the assignment is to add an output device to a microcontroller board I’ve designed and make it do something. The obvious connection to my final project — a height-adjustable standing desk — is motors. The desk has four telescopic legs, each driven by a stepper motor. That makes stepper control the natural target here: useful now, essential later.

The group assignment is to measure power consumption of an output device. Both the individual and group work are documented here and on the Fab Lab León 2026 Group Page.


learning objectives.

  • Understand the role of PWM as the foundation of output device control.
  • Know when to use a MOSFET vs an H-bridge vs a dedicated driver IC.
  • Design and fabricate a PCB that interfaces a stepper motor driver to the XIAO RP2040.
  • Write firmware that drives a stepper motor with acceleration/deceleration.
  • Measure power consumption of an output device using a multimeter.
  • Connect this week’s work directly to the standing desk final project.

assignments.

  • Group assignment: measure the power consumption of an output device — document on group page and reflect here on what I learned.
  • Individual assignment: add an output device to a microcontroller board I’ve designed, program it to do something.

research.

Neil’s class this week opened with the usual safety reminder, but with more weight than usual — we’re moving up in voltage and current. One thing he said that stuck with me: approach higher voltage work the same way you approach machining. Don’t do it late at night, don’t do it alone, don’t do it when you’re angry. Same discipline, different danger. A milliamp through your heart is fibrillation; 10 milliamps contracts your muscles and you lose control. The numbers are not abstract.

Beyond that, the class was a tour of the full output device landscape:

Pulse Width Modulation (PWM) is the foundation of most of what we’re doing. A digital pin can only be fully on (3.3 V) or fully off (0 V) — there is no middle ground. PWM cheats around this: instead of holding a steady voltage, it switches the pin on and off thousands of times per second and varies the fraction of time it stays on. That fraction is the duty cycle. This is also why Arduino’s analogWrite() function is misleadingly named — it doesn’t produce a true analog voltage, it produces a PWM signal. More on that in the Arduino Analog Output documentation.

Two PWM waveforms showing period and duty cycle: top at 90% duty cycle, bottom at 50% duty cycle. Each shows three complete periods with arrows labelling the on-time fraction.
The period is the time for one complete on/off cycle (fixed by the PWM frequency). The duty cycle is the fraction of that period where the signal is high. Top: 90% — the pin is on for 90% of each period. Bottom: 50% — equal on and off time. Source: SlideServe — Pulse Width Modulation (PWM) presentation.

The key insight is that the output device — an LED, a motor coil, a speaker — cannot react fast enough to follow the individual pulses. It only sees the average. If the pin is on 50% of the time at 10 V, the device behaves as if it were receiving a steady 5 V. At 75% on-time it sees 7.5 V. At 25% it sees 2.5 V. The processor is always switching between fully on and fully off; the physics of the load does the averaging for free.

Three PWM waveforms at 50%, 75% and 25% duty cycle, each with an orange horizontal line showing the resulting average voltage: 5V, 7.5V and 2.5V respectively.
The orange line is the average voltage the load actually experiences. 50% duty cycle on a 10 V supply → 5 V average. 75% → 7.5 V. 25% → 2.5 V. The waveform switches between 0 and 10 V at all times — the average is the only thing the output device responds to. Source: CircuitBread — What is a PWM signal?.

Power transistors — MOSFETs — are what actually drive the current. A processor pin can push maybe 50 mA. A motor or a bright LED needs much more. A MOSFET (a 20-cent part) sits between the processor and the load: the processor sets the gate voltage, the MOSFET handles the current. NMOSFET sinks current to ground; PMOSFET sources it. For one direction, a single NMOSFET is enough. For two directions (reversible motors), you need an H-bridge: two PMOSFETs on top, two NMOSFETs on bottom, and you alternate which pair is on to flip the current direction.

H-bridge diagram showing two operating states: left — Q1 and Q4 ON (green), current flows left-to-right through the motor; right — Q2 and Q3 ON (red), current flows right-to-left through the motor.
H-bridge operating states. Left: Q1 (PMOS top-left) and Q4 (NMOS bottom-right) conduct — current flows forward through the motor (green). Right: Q2 (NMOS bottom-left) and Q3 (PMOS top-right) conduct — current flows in reverse (red). Alternating diagonal pairs is how bidirectional motor control works. Source: Cyril BUTTAY — Wikimedia Commons, CC BY-SA 2.5.

Power measurement is the group assignment. The key idea: power is voltage × current, not just one or the other. Neil demonstrated three approaches: using the ammeter input on the multimeter (series with the load), using a shunt resistor (measure the tiny voltage drop across a known resistance with V = IR), and using a USB power meter if the device is USB-powered.

Output device types Neil covered:

  • LEDs — blink and fade via PWM. Charlieplexing (N pins control N×(N-1) LEDs), NeoPixels (smart RGB LEDs chained over a single data line), and high-power LEDs (require MOSFETs; thermal runaway risk).
  • Displays — LCD (character only, not recommended), OLED via I2C (pixel-addressable, cheap — SSD1306, already used in Week 04), TFT via SPI (colour, larger), e-ink (retains image without power).
  • Audio — MP3 module with SD card, I2S DAC chip for wavetable synthesis (Neil’s recommendation), or Class D audio through an H-bridge.
  • DC motors — H-bridge, PWM to control speed. Gearhead motors for high-torque low-speed applications.
  • BLDC motors — brushless DC: three sets of coils, triple half-bridge. Used in drone propellers, fans, milling spindles.
  • Stepper motors — the one I care about most. Two sets of coils, driven in sequence. Full step → half step → microstepping → sinusoidal drive: each level smoother than the last. Standard step angle: 1.8° (200 steps/revolution).
  • Servo motors — a DC motor with a gear train, potentiometer, and closed-loop controller built in. Driven by 50 Hz PWM, 1–2 ms pulse width sets the angle.

Connection to my final project: the standing desk legs use stepper motors. Each leg needs a stepper running off a dedicated XIAO RP2040, with RS485/CAN communication to the master controller. This week is the right time to get the stepper driver working on a board I’ve designed, even if it’s a test board rather than the final one.


group assignment.

The group assignment for this week is to measure the power consumption of an output device. I used a small DC motor as the device under test, measuring voltage and current with the Fluke 179 multimeter in ammeter mode. Both the methodology and the results are documented on the Fab Lab León 2026 Group Page.

Device under test: small DC motor, no load.

Measurement setup: the multimeter was placed in series with the motor using the ammeter input (mA port). Voltage was read directly from the 9 V battery.

Fluke 179 True RMS multimeter showing 7.68 V DC reading, connected to a 9V Energizer battery with red and black crocodile clips.
Fluke 179 measuring the actual voltage of the 9 V battery under load — 7.68 V, typical for a partially discharged alkaline cell. The multimeter is in DC voltage mode; for current measurement it was switched to the mA input.

Results:

ParameterValue
Voltage (V)7.68 V
Current (I)10 mA = 0.01 A
Power (P = V × I)0.077 W

The power formula is straightforward: P = V × I. At 7.68 V and 10 mA, the motor draws roughly 77 mW with no load attached. That is a realistic idle figure for a small DC motor — under load, current rises and so does power consumption proportionally, since P scales linearly with both V and I.

One thing worth keeping in mind: milliamps need to be converted to amps before applying the formula. 10 mA = 0.01 A, not 10. Easy mistake to make when reading the multimeter display.

DC motor running at 7.68 V, multimeter showing 10 mA current draw.

What I learned: the measurement itself is simple, but it makes you think about what the numbers mean in practice. A motor drawing 77 mW at idle will draw significantly more under load — the current is what changes, not the voltage. For the standing desk final project, where four stepper motors will run simultaneously, knowing idle vs loaded current draw is critical for sizing the power supply correctly.

Two rookie mistakes worth flagging for anyone doing this for the first time:

1. Wrong probe port. The Fluke 179 has three input jacks: COM (black, always), V/Ω (red, for voltage and resistance), and mA/400mA or 10A (red, for current). Plugging the red probe into V/Ω and switching the dial to amps does nothing useful — the current path goes through the wrong jack. The probe must go into the mA port. For currents above 400 mA, use the 10A port instead or you will blow the internal fuse.

2. Parallel instead of series. A voltmeter goes in parallel with the load — an ammeter goes in series. The diagram below shows both instruments in the same circuit: the ammeter (A) is part of the main current loop, the voltmeter (V) taps across the resistance without interrupting it. Connecting an ammeter in parallel instead of series creates a near short-circuit: the multimeter’s internal resistance is almost zero, so all the current from the source flows through the meter instead of the load. Best case: the internal fuse blows. Worst case: damage to the meter or the source.

Circuit diagram showing a cell, resistance, ammeter in series (A) and voltmeter in parallel (V), with current flow direction indicated by an arrow.
Ammeter (A) connected in series — current flows through it. Voltmeter (V) connected in parallel — it measures voltage across the resistance without interrupting the circuit. These are the two instruments used in the group assignment: the Fluke 179 in ammeter mode for current, and direct voltage reading for V. Source: The Engineering Toolbox — Electrical Units.

spiral 0 — output device selection.

The first step was to go through the kit and list the available actuators at Fab Lab León.

Collection of output devices laid out on a wooden table: speaker, DC motor, small custom PCBs, OLED display, LCD display, servo motor in packaging, and a NEMA 17 stepper motor with A4953 driver board. An orange and blue robotic arm assembly is visible on the right.
Output devices available at Fab Lab León this week: speaker, DC motor, OLED, LCD, servo, and the NEMA 17 stepper motor with its A4953 driver board — Adrián's design, which I borrowed for the first tests.

Selection rationale:

The standing desk needs stepper motors — one per leg, four total. The whole final project depends on getting stepper control right. That makes this week’s individual assignment a direct investment in the final project rather than a detour.

The motor is the Usongshine 17HS4023 — a NEMA 17 bipolar stepper with a step angle of 1.8° (200 steps/revolution), 0.7 A per phase, 4 Ω phase resistance. The step angle is printed in the motor’s datasheet: olimex.com/Products/Robot-CNC-Parts/StepperMotors/SM-17HS4023.


spiral 1 — first test with Adrián’s board.

Before designing my own PCB, I borrowed Adrián’s A4953 dual H-bridge board to validate the full chain: XIAO RP2040 → driver → NEMA 17. The A4953 is a single full-bridge DMOS driver (±2 A, up to 40 V) — two of them on the same board cover the two coils of a bipolar stepper. Control is simple: two pins per driver (IN1, IN2) set the current direction via a truth table.

Connection — XIAO RP2040 → Adrián’s board (6-pin FTDI connector):

FTDI pinSignalXIAO pin
1GNDGND
2IN2-AD0 (GPIO26)
3IN1-AD1 (GPIO27)
4IN2-BD2 (GPIO28)
5IN1-BD3 (GPIO29)
6VCC3V3

Motor power (9 V) goes to the VDO/GND pads on the board — completely separate from the logic supply. GND common between XIAO and driver board is mandatory.

🤖 Claude (Anthropic) on the stepper motor full-step sequence prompt:

I need to control a NEMA 17 bipolar stepper motor via two Allegro A4953 H-bridge drivers using a XIAO RP2040. Write a minimal Arduino sketch that rotates the motor one full revolution clockwise, pauses one second, then one full revolution counter-clockwise, using a manual full-step sequence without any library.

The sketch drives four control pins (coilA_IN1, coilA_IN2, coilB_IN1, coilB_IN2) using a 4-step sequence array. Each step applies a specific combination of HIGH/LOW to alternate current direction in each coil. After every move, coast() sets all pins LOW to put both A4953s into standby and prevent coil heating. STEP_DELAY_US = 2000 µs gives a safe starting speed of 500 steps/s — well below the measured pull-in rate of ~695 steps/s for this motor at 9 V.

🤖 Claude (Anthropic) on the stepper serial control and acceleration prompt:

Extend the previous sketch to accept Serial commands at 115200 baud: s to rotate N steps CW, s- for CCW, v to set speed in steps/s, and ‘a’ to run an acceleration/deceleration demo without any external library. Limit the maximum speed to the measured pull-in rate.

The sketch implements a step() function that advances one step and delays 1000000/stepsPerSecond microseconds, making speed a live variable. The ‘a’ command ramps linearly from 100 to 1200 steps/s over 150 steps using integer interpolation, cruises at peak speed for 200 steps, then ramps back down — demonstrating the difference between pull-in rate (~695 steps/s cold start) and slew rate (1200 steps/s with ramp). The ‘v’ command is capped at 700 steps/s to prevent stall on cold starts.

tab: stepper-spiral1.ino | stepper-spiral1.ino

// Fab Academy 2026 - Fab Lab León
// Week 10: Output Devices — stepper motor spiral 1
// NEMA 17 bipolar (Usongshine 17HS4023) via 2x Allegro A4953 (Adrián's board)
// XIAO RP2040 (arduino-pico core)
// Spiral 1: rotate CW 200 steps, pause, CCW 200 steps

// A4953 #1 — coil A
const int coilA_IN1 = D1;  // GPIO27 → PA6 → IN1
const int coilA_IN2 = D0;  // GPIO26 → PA7 → IN2

// A4953 #2 — coil B
const int coilB_IN1 = D3;  // GPIO29 → PA4 → IN1
const int coilB_IN2 = D2;  // GPIO28 → PA5 → IN2

const int STEP_DELAY_US = 2000;

// Full-step sequence [coilA_IN1, coilA_IN2, coilB_IN1, coilB_IN2]
// A4953 truth table: IN1=1,IN2=0 → Forward | IN1=0,IN2=1 → Reverse
const int seq[4][4] = {
  {1, 0, 1, 0},
  {0, 1, 1, 0},
  {0, 1, 0, 1},
  {1, 0, 0, 1}
};

void coast() {
  // IN1=IN2=0 → Coast/Standby — releases coils, saves power
  digitalWrite(coilA_IN1, 0); digitalWrite(coilA_IN2, 0);
  digitalWrite(coilB_IN1, 0); digitalWrite(coilB_IN2, 0);
}

void setCoils(int s) {
  s = ((s % 4) + 4) % 4;
  digitalWrite(coilA_IN1, seq[s][0]);
  digitalWrite(coilA_IN2, seq[s][1]);
  digitalWrite(coilB_IN1, seq[s][2]);
  digitalWrite(coilB_IN2, seq[s][3]);
}

void rotate(int numSteps, bool clockwise) {
  for (int i = 0; i < numSteps; i++) {
    int s = clockwise ? (i % 4) : (3 - (i % 4));
    setCoils(s);
    delayMicroseconds(STEP_DELAY_US);
  }
  coast();
}

void setup() {
  pinMode(coilA_IN1, OUTPUT); pinMode(coilA_IN2, OUTPUT);
  pinMode(coilB_IN1, OUTPUT); pinMode(coilB_IN2, OUTPUT);
  coast();
  delay(500);
}

void loop() {
  rotate(200, true);   // 1 full revolution CW — 200 steps × 1.8° = 360°
  delay(1000);
  rotate(200, false);  // 1 full revolution CCW
  delay(1000);
}

tab: stepper-spiral2.ino | stepper-spiral2.ino

// Fab Academy 2026 - Fab Lab León
// Week 10: Output Devices — stepper motor spiral 2
// NEMA 17 bipolar (Usongshine 17HS4023) via 2x Allegro A4953
// XIAO RP2040 (arduino-pico core)
//
// Serial interface at 115200 baud. Commands:
//   s<steps>  → rotate N steps CW  (e.g. "s400" = 2 revolutions)
//   s-<steps> → rotate N steps CCW (e.g. "s-200")
//   v<speed>  → set speed in steps/s (max reliable without ramp: ~695)
//   a         → run acceleration/deceleration demo
//   ?         → print current settings

const int coilA_IN1 = D1;
const int coilA_IN2 = D0;
const int coilB_IN1 = D3;
const int coilB_IN2 = D2;

const int seq[4][4] = {
  {1, 0, 1, 0},
  {0, 1, 1, 0},
  {0, 1, 0, 1},
  {1, 0, 0, 1}
};

int stepsPerSecond = 500;
int currentStep = 0;

void coast() {
  digitalWrite(coilA_IN1, 0); digitalWrite(coilA_IN2, 0);
  digitalWrite(coilB_IN1, 0); digitalWrite(coilB_IN2, 0);
}

void setCoils(int s) {
  s = ((s % 4) + 4) % 4;
  digitalWrite(coilA_IN1, seq[s][0]);
  digitalWrite(coilA_IN2, seq[s][1]);
  digitalWrite(coilB_IN1, seq[s][2]);
  digitalWrite(coilB_IN2, seq[s][3]);
}

// step() advances one step in the given direction at current speed
void step(int direction) {
  currentStep += direction;
  setCoils(currentStep);
  delayMicroseconds(1000000 / stepsPerSecond);
}

void rotate(int numSteps) {
  int direction = (numSteps > 0) ? 1 : -1;
  for (int i = 0; i < abs(numSteps); i++) step(direction);
  coast();
}

// accelDemo() ramps from 100 to 1200 steps/s, cruises, then ramps down
// demonstrates smooth acceleration without any external library
void accelDemo() {
  const int minSpeed = 100;
  const int maxSpeed = 1200;
  const int accelSteps = 150;
  const int cruiseSteps = 200;

  Serial.println("Ramp up -> cruise -> ramp down (CW)");
  for (int i = 0; i < accelSteps; i++) {
    stepsPerSecond = minSpeed + (maxSpeed - minSpeed) * i / accelSteps;
    step(1);
  }
  stepsPerSecond = maxSpeed;
  for (int i = 0; i < cruiseSteps; i++) step(1);
  for (int i = accelSteps; i > 0; i--) {
    stepsPerSecond = minSpeed + (maxSpeed - minSpeed) * i / accelSteps;
    step(1);
  }
  coast();
  delay(800);

  Serial.println("Returning CCW...");
  for (int i = 0; i < accelSteps; i++) {
    stepsPerSecond = minSpeed + (maxSpeed - minSpeed) * i / accelSteps;
    step(-1);
  }
  stepsPerSecond = maxSpeed;
  for (int i = 0; i < cruiseSteps; i++) step(-1);
  for (int i = accelSteps; i > 0; i--) {
    stepsPerSecond = minSpeed + (maxSpeed - minSpeed) * i / accelSteps;
    step(-1);
  }
  coast();
  stepsPerSecond = 500;
  Serial.println("Done. Speed reset to 500 steps/s.");
}

void printHelp() {
  Serial.println("---------------------------------");
  Serial.println("Stepper serial control — XIAO RP2040 + A4953");
  Serial.println("  s<n>   rotate N steps CW");
  Serial.println("  s-<n>  rotate N steps CCW");
  Serial.println("  v<n>   set speed steps/s (max reliable: ~695)");
  Serial.println("  a      acceleration demo");
  Serial.println("  ?      help + current settings");
  Serial.print("Current speed: "); Serial.print(stepsPerSecond); Serial.println(" steps/s");
}

void parseSerial() {
  String input = Serial.readStringUntil('\n');
  input.trim();
  if (input.length() == 0) return;
  char cmd = input.charAt(0);

  if (cmd == 's') {
    int steps = input.substring(1).toInt();
    if (steps == 0) { Serial.println("Invalid step count."); return; }
    Serial.print("Rotating "); Serial.print(steps); Serial.println(" steps...");
    rotate(steps);
    Serial.println("Done.");
  } else if (cmd == 'v') {
    int spd = input.substring(1).toInt();
    if (spd < 50 || spd > 700) { Serial.println("Speed out of range (50-700 steps/s)."); return; }
    stepsPerSecond = spd;
    Serial.print("Speed set to "); Serial.print(stepsPerSecond); Serial.println(" steps/s.");
  } else if (cmd == 'a') {
    accelDemo();
  } else if (cmd == '?') {
    printHelp();
  } else {
    Serial.println("Unknown command. Send '?' for help.");
  }
}

void setup() {
  pinMode(coilA_IN1, OUTPUT); pinMode(coilA_IN2, OUTPUT);
  pinMode(coilB_IN1, OUTPUT); pinMode(coilB_IN2, OUTPUT);
  coast();
  Serial.begin(115200);
  delay(1500);
  printHelp();
}

void loop() {
  if (Serial.available()) parseSerial();
}

tab: end


testing and results.

Complete test setup on a wooden table: NEMA 17 stepper motor connected via four-wire cable to Adrián's A4953 driver board, which connects via a ribbon cable to the XIAO RP2040 week 08 board. A 9V battery provides motor power via red and black wires. A USB cable connects the XIAO to the computer.
Complete test setup: NEMA 17 stepper → A4953 driver board (Adrián's) → XIAO RP2040 week 08 board. 9 V battery for motor power, USB-C for logic and programming.

Motor characterisation — Usongshine 17HS4023 at 9 V, full-step:

ParameterValue
Pull-in rate (cold start, no ramp)~695 steps/s
Safe operating speed (no ramp)≤ 600 steps/s
Peak speed with acceleration ramp1200 steps/s
Motor supply9 V (battery)
Step angle1.8°
Steps per revolution200

The pull-in rate is the maximum speed at which the motor can start moving from standstill without losing steps. Above ~695 steps/s the coils don’t have time to build up enough current before the next step fires — the field changes faster than the rotor can follow, and the motor stalls. The electrical time constant explains why: L/R = 3.2 mH / 4 Ω = 0.8 ms. At 1000 steps/s the step period is only 1 ms — barely more than one time constant.

With a ramp (command a), the motor has time to accelerate gradually and reaches 1200 steps/s without issue. This is the difference between pull-in rate (cold start limit) and slew rate (speed reachable with a ramp).

Spiral 1: NEMA 17 rotating one full revolution CW, pause, one full revolution CCW. 200 steps × 1.8°/step = 360°.


spiral 2 — PCB design with A4950.

With the full-step behaviour validated on Adrián’s board, the next step was designing my own driver board using the Allegro A4950 — the same H-bridge architecture as the A4953, pin-compatible, but with higher current capacity (±3.5 A vs ±2 A) and lower RDS(on) (0.6 Ω vs 0.8 Ω). The A4950 is the part available in Fab Lab León stock.

Board decisions:

  • 2× A4950, one per coil
  • No sense resistor (LSS tied to GND directly) — valid for light loads at 0.7 A
  • VREF tied to 3.3 V
  • 2× 100 µF bulk capacitors + 2× 100 nF decoupling capacitors
  • 6-pin horizontal SMD header for XIAO control signals
  • 2×2 SMD connector for motor coils
  • 2-pin connector for 9 V motor supply

Fabrication — Roland MDX-20:

Roland MDX-20 milling machine mid-job on a copper FR1 board. The endmill is cutting traces around an IC pad area, with fine copper dust visible. A second smaller board outline is visible to the right on the same copper sheet.
Roland MDX-20 milling the A4950 driver board. Two boards fit on the same copper sheet. The dense trace area around the IC pads required careful Z-origin calibration.
Close-up of the freshly milled PCB showing copper traces for the dual A4950 stepper driver board. The routing shows wide power traces around the perimeter and finer signal traces in the centre.
Close-up of the milled PCB. Wide traces for VBB and GND power rails, narrower traces for IN1/IN2 control signals. Two 0 Ω resistors (1206) bridge the trace crossings required by the single-layer layout.

problems and solutions.

Pull-in rate limit at 9 V. Sending v1000 via Serial caused the motor to do nothing. Root cause: at 1000 steps/s the delay between steps is 1 ms, but the motor’s electrical time constant (L/R = 3.2 mH / 4 Ω = 0.8 ms) means the coil current barely reaches rated value before the next step fires. The motor can’t build enough torque. Solution: limit v command to 700 steps/s for cold starts; use the a command (ramp) to reach higher speeds.

Two trace crossings in PCB routing. The motor connector forced COIL_A and COIL_B traces to cross each other in the centre of the board — unavoidable on a single-layer PCB with this component arrangement. The green lines in the screenshot below are KiCad’s ratsnest showing the unrouted connections: two separate +9V paths that needed to reach their destination but had no clear route that didn’t cut through existing copper.

KiCad PCB editor showing two green ratsnest lines — unrouted connections — crossing through already-placed copper traces between the A4950 drivers and the motor connector pads.
The green lines are ratsnest — KiCad showing where connections still need to be made. Both paths needed to cross existing copper traces with no way around on a single-layer board. Solution: two 0 Ω resistors (1206) as physical bridges — one trace runs underneath through the copper layer, the other jumps over it through the resistor pads.

The 0 Ω bridge technique is the standard fix for single-layer routing conflicts: place a 1206 resistor footprint perpendicular to the blocking trace, route one net through the resistor pads, and let the other pass underneath in the gap between them.

PWR_FLAG ERC errors. Multiple PWR_FLAG symbols on the same net caused KiCad ERC to report “Pins of type Power output and Power output are connected.” Fix: one PWR_FLAG per power net maximum.


files and resources.

Assignment links:

Referenced boards:

Design files:

  • KiCad project: week10-stepper-driver.zip — {/* to be added */}
  • Source code: available via download buttons above

conclusions.

{/* To be written after soldering and final test */}

{/* Key takeaways: /} {/ - Pull-in rate vs slew rate — real measured data at 9 V, full-step /} {/ - A4950 pin-compatible with A4953, higher current headroom /} {/ - 0 Ω bridge technique for single-layer routing /} {/ - Direct path to final project: same driver architecture for the PoC */}