ART
BEAUTY & WELLNESS
CRAFT
CULTURE & HISTORY
ENTERTAINMENT
ENVIRONMENT
FOOD & DRINKS
REVERSE ENGINEERING
SCIENCES
SPORTS
TECHNOLOGY
WEARABLES
Bring-Up: The First Hour with Your Own Chip, Tested by an ESP32
Youblob (drawn from the sketch's pin map) · CC0
Ed

Created by

Ed

29. September 2026FI
1
0
0
0
0

Bring-Up: The First Hour with Your Own Chip, Tested by an ESP32

Bring-up is what engineers call the first power-on of new silicon, and the order of it matters more than any single test. Look before you power, power before you clock, and limit the current before you do anything, because a short that a current limit would have caught in a second can destroy the only chips you have. This rung is the bring-up plan for the PWM dimmer of the earlier rungs, on the breakout board from rung 2. An ESP32 does the work of a lab: it makes the chip's clock, holds its reset, sets the duty on eight pads and times the PWM that comes back, then prints PASS or FAIL for each duty. A notebook turns a failure into the name of the pad whose wire is wrong. Honestly stated: there is no chip yet. The sketch was compiled for this blueprint and the expected numbers come from the simulations of the earlier rungs; the first real run is yours.
Advanced
An afternoon, once the chip arrives

Instructions

1

The numbers to expect, and how to read a failure

Loading Jupyter Notebook...
2

The chip you are bringing up

The embedded blueprint puts pull-downs on every input, so an unplugged chip sits disabled. That is the core this plan tests.
3

Before any power

With nothing connected, look at the chip-on-board seated on the breakout under the loupe: seated square, no solder bridge, nothing loose. Then measure the resistance between a VDD IO pad and a GND IO pad of the breakout with the multimeter, in both polarities, and write both numbers down. A reading near zero is a short: stop there. The run-1 pad table names which breakout pads are VDD IO and GND IO; use your run's table, because wafer.space says pinouts change between runs. Check the same way that no data pad is shorted to its neighbour or to ground.

Materials for this step:

Custom ASIC DieCustom ASIC Die1 piece
Printed Circuit BoardPrinted Circuit Board1 piece

Tools needed:

MultimeterMultimeter
4

Power, with the current limit low

Set the bench supply to your chip's supply voltage before connecting it. That voltage depends on the libraries your chip was built with: the template's default libraries are 5 V ones, and it can also build with 3.3 V libraries. Take the exact value from your run's documentation; the run-1 pad table names the power pads but not their voltage. Set the current limit to the lowest setting that lets the supply regulate, connect VDD IO and GND IO, and switch on with the ESP32 still disconnected. With no clock and every input pulled down, the chip should sit still. Write down the current. If the supply goes straight into current limiting, switch off: something is shorted. Record the current twice more later, in reset with the clock running and while it plays a pattern. Those three numbers are your chip's own signature; a board that later draws much more than it did today has a fault.

Tools needed:

Bench Power Supply (30V/5A)Bench Power Supply (30V/5A)
MultimeterMultimeter
5

Wire the ESP32

Twelve wires, as in the picture and in the sketch's header: GPIO 27 to the clock pad, 26 to rst_n, 32 to input 0 (enable), 13, 14, 18, 19, 21, 22, 23 and 25 to bidirectional pads 0 to 7, and bidirectional pad 8 back to GPIO 34, plus a common ground. GPIO 34 is an input-only pin on the ESP32, so it can never fight the chip's output. The ESP32 is a 3.3 V part and its inputs are not 5 V tolerant. If your chip's I/O is not 3.3 V, put level converters in all twelve lines: three four-channel boards. The common kind has pull-up resistors on both sides, which may override the chip's weak pull-downs until the ESP32 drives its pins; the sketch holds reset and enable low as soon as it starts, before the clock runs.

Materials for this step:

Logic Level ConverterLogic Level Converter3 pieces
Jumper Wire SetJumper Wire Set1 piece

Tools needed:

Breadboard - ClassicBreadboard - Classic
6

The test sketch

bringup.ino. It starts the chip's clock with the ESP32's LED PWM peripheral at 100 kHz, with 1-bit resolution for a plain square wave; holds reset low for 1,000 chip clocks; checks that the output stays low while enable is off; then sets seven duty values and measures the high time with pulseIn, averaged over eight periods, against 10 microseconds per step, within 3 microseconds. It compiles for the ESP32 with the Arduino ESP32 core 3.3.12; it has not been run, because the chip does not exist yet.
bringup.inocpp
// SPDX-License-Identifier: Apache-2.0
// First-light test for the PWM dimmer chip (Youblob silicon rungs 3 and 6), run from an ESP32.
// The ESP32 is the whole lab: it makes the chip's clock, holds its reset, sets the duty on eight
// pads, and times the PWM that comes back, then prints PASS or FAIL for each duty value.
//
// Wiring, through a logic level converter if your chip's I/O is not 3.3 V (see the blueprint):
//   CLK      GPIO 27  -> clk pad         RST_N  GPIO 26 -> rst_n pad   (both clear of the boot strapping pins)
//   EN       GPIO 32  -> input[0]        D0..D7 GPIO 13,14,18,19,21,22,23,25 -> bidir[0..7]
//   PWM_IN   GPIO 34  <- bidir[8]        (GPIO 34 is input-only on the ESP32: it cannot fight the chip)
//   and a common ground.

const int PIN_CLK = 27, PIN_RST = 26, PIN_EN = 32, PIN_PWM = 34;
const int DATA_PINS[8] = {13, 14, 18, 19, 21, 22, 23, 25};

// 100 kHz: slow enough for a level converter's pull-up edges, and one chip clock is 10 us,
// so pulseIn's 1 us resolution sees a tenth of a clock.
const uint32_t CHIP_CLK_HZ = 100000;
const float US_PER_CLK = 1e6f / CHIP_CLK_HZ;
const float PERIOD_US = 256 * US_PER_CLK;          // one PWM period: 256 chip clocks = 2560 us
const float TOL_US = 3.0f;                         // allowed error, about a third of a clock

void setDuty(uint8_t d) {
  for (int b = 0; b < 8; b++) digitalWrite(DATA_PINS[b], (d >> b) & 1);
}

// Average high time over n periods; returns -1 if the pin never went high (pulseIn timed out).
float meanHighUs(int n) {
  float sum = 0;
  for (int i = 0; i < n; i++) {
    unsigned long t = pulseIn(PIN_PWM, HIGH, 3 * (unsigned long)PERIOD_US);
    if (t == 0) return -1;
    sum += t;
  }
  return sum / n;
}

bool alwaysLow(unsigned long ms) {
  unsigned long t0 = millis();
  while (millis() - t0 < ms)
    if (digitalRead(PIN_PWM)) return false;
  return true;
}

void setup() {
  Serial.begin(115200);
  delay(500);
  for (int b = 0; b < 8; b++) pinMode(DATA_PINS[b], OUTPUT);
  pinMode(PIN_RST, OUTPUT);
  pinMode(PIN_EN, OUTPUT);
  pinMode(PIN_PWM, INPUT);

  // Reset low BEFORE the clock starts, then give the chip some clocks in reset.
  digitalWrite(PIN_RST, LOW);
  digitalWrite(PIN_EN, LOW);
  setDuty(0);
  if (!ledcAttach(PIN_CLK, CHIP_CLK_HZ, 1)) {      // 1-bit resolution: a plain square wave
    Serial.println("FAIL: could not start the clock on GPIO 27");
    return;
  }
  ledcWrite(PIN_CLK, 1);                           // 1 of 2 steps high = 50 % duty
  delay(10);                                       // 1,000 chip clocks in reset
  digitalWrite(PIN_RST, HIGH);

  Serial.printf("# chip clock %lu Hz, PWM period %.0f us\n", (unsigned long)CHIP_CLK_HZ, PERIOD_US);
  Serial.println("duty,expected_us,measured_us,result");
  int fails = 0;

  // Disabled: the output must stay low whatever the duty.
  setDuty(200);
  bool low = alwaysLow(20);
  Serial.printf("disabled,0,%s,%s\n", low ? "0" : "high seen", low ? "PASS" : "FAIL");
  fails += !low;

  digitalWrite(PIN_EN, HIGH);
  const uint8_t duties[] = {0, 1, 16, 64, 128, 200, 254};
  for (uint8_t d : duties) {
    setDuty(d);
    delay(10);                                     // let a few periods pass with the new value
    float expected = d * US_PER_CLK;
    float got;
    bool ok;
    if (d == 0) {
      ok = alwaysLow(20);
      got = ok ? 0 : meanHighUs(8);                // a pad stuck high shows up here as a duty above 0
    } else {
      got = meanHighUs(8);
      ok = got >= 0 && fabsf(got - expected) <= TOL_US;
    }
    Serial.printf("%u,%.1f,%.1f,%s\n", d, expected, got, ok ? "PASS" : "FAIL");
    fails += !ok;
  }
  Serial.printf("# %d failure(s)\n", fails);
}

void loop() {}

Tools needed:

ESP32 Development BoardESP32 Development Board
Desktop ComputerDesktop Computer
7

What a good chip prints

Open the serial monitor at 115200 baud. A chip that works prints, per line, the duty, the expected and measured high time in microseconds, and the result: # chip clock 100000 Hz, PWM period 2560 us duty,expected_us,measured_us,result disabled,0,0,PASS 0,0.0,0.0,PASS 1,10.0,10.0,PASS ... 254,2540.0,2540.0,PASS # 0 failure(s) Then look at pad 8 with the oscilloscope as well: one period should be 2,560 microseconds at this clock, with clean edges. The sketch measures time; the scope shows shape, and a slow or ringing edge through a level converter is visible only there.

Tools needed:

Digital OscilloscopeDigital Oscilloscope
8

A chip that does not come up

Bring-up troubleshooting.

Flow

Loading...
9

Sources and honest limits

**Sources**, read 29 September 2026: wafer-space/chip-on-board-wire-bonded-pcbs, run-1/README.md (the pad table naming VDD IO and GND IO pads, and the note that pinouts change between runs); wafer-space/gf180mcu-project-template, README.md and Makefile (the 5 V default and 3.3 V library options); the earlier rungs' simulations for the expected high times. **Honest limits.** No chip exists yet: this plan and its sketch have not been run on silicon. The supply voltage and current are not stated here because the run documentation available at the time of writing does not state them. The level converter's effect on the pull-downs depends on the board you use.

Materials

4

Tools Required

6

CC0 Public Domain

This blueprint is released under CC0. You are free to copy, modify, distribute, and use this work for any purpose, without asking permission.

Support the Maker by purchasing products through their Blueprint where they earn a Maker Commission set by Vendors, or create a new iteration of this Blueprint and include it as a connection in your own Blueprint to share revenue.

Discussion

(0)

Log in to join the discussion

Loading comments...