ESP32-C3 Multi-Board Design


Placed 36 component(s): C7, C1, J4, U2, C14, C2, C3, R4, C4, U1, L1, J9, C12, J6, C11, D1, R2, R7, R5, R3, J8, U4, J5, J3, R6, J7, C6, C5, J10, U5, J2, U3, F1, R1, J1, C13
Work done
  • Updated the schematic into a dual-board stack concept: primary board keeps ESP32-C3, TMP117, LIS2DW12, and J8; secondary board carries LiPo charging/power, pogo access, external antenna interface, and J9/J10.
  • Added and wired the J8/J9 board-to-board interconnect and J10 U.FL antenna interface; core ERC checks are passing.
  • Reconfigured the PCB into a two-board 28 mm-wide stack/panel representation and re-placed the components into primary/secondary clusters.
  • Documented the partition, interconnect pinout, verification state, and manual-routing priorities in Two-Board Stack Revision.
Success criteria review
  • ✅ Dual-board partition defined and reflected in schematic/component roles.
  • ✅ Core functions preserved: ESP-NOW MCU, TMP117, LIS2DW12, LiPo charging/power, and pogo access remain connected.
  • ⚠️ Layout de-risked but not fully clean: missing footprints and ERC checks pass, but remaining physical-layout issues still need routing/layer cleanup before fabrication.
Next steps
  • Refresh/regenerate routing for the new two-board placement, then clear the remaining physical layout issues before manufacturing export.
Check DRC issues
Export assembly files
Show interconnect pinout
Document routing priorities

Firmware Starter
Target
  • MCU/module: ESP32-C3-MINI-1U-N4
  • Wireless mode: ESP-NOW
  • Sensors:
    • TMP117-compatible temperature sensor on I2C
    • LIS2DW12 accelerometer on I2C
Pin map from schematic
  • GPIO4 -> I2C SDA
  • GPIO5 -> I2C SCL
  • GPIO1 -> TMP117 ALERT
  • GPIO0 -> LIS2DW12 INT1
  • GPIO6 -> Charger status input
  • GPIO9 -> BOOT strap
  • TXD0 / RXD0 -> pogo UART programming/debug
Arduino-style starter sketch

Cpp


#include <WiFi.h>
#include <esp_now.h>
#include <Wire.h>
#include <Adafruit_TMP117.h>
#include <SparkFun_LIS2DW12.h>

static const int PIN_I2C_SDA = 4;
static const int PIN_I2C_SCL = 5;
static const int PIN_TMP_ALERT = 1;
static const int PIN_ACCEL_INT = 0;
static const int PIN_CHG_STAT = 6;

Adafruit_TMP117 tmp117;
LIS2DW12 accel;

uint8_t peerAddress[] = {0x24, 0x6F, 0x28, 0x00, 0x00, 0x00}; // TODO: replace

struct Payload {
  float temperature_c;
  float ax_g;
  float ay_g;
  float az_g;
  uint8_t charging_active;
};

void onDataSent(const wifi_tx_info_t *info, esp_now_send_status_t status) {
  (void)info;
  Serial.print("ESP-NOW send status: ");
  Serial.println(status == ESP_NOW_SEND_SUCCESS ? "OK" : "FAIL");
}

void setupEspNow() {
  WiFi.mode(WIFI_STA);
  if (esp_now_init() != ESP_OK) {
    Serial.println("ESP-NOW init failed");
    return;
  }

  esp_now_register_send_cb(onDataSent);

  esp_now_peer_info_t peerInfo = {};
  memcpy(peerInfo.peer_addr, peerAddress, 6);
  peerInfo.channel = 0;
  peerInfo.encrypt = false;

  if (!esp_now_is_peer_exist(peerAddress)) {
    if (esp_now_add_peer(&peerInfo) != ESP_OK) {
      Serial.println("Failed to add ESP-NOW peer");
    }
  }
}

void setupSensors() {
  Wire.begin(PIN_I2C_SDA, PIN_I2C_SCL);

  if (!tmp117.begin()) {
    Serial.println("TMP117 not found");
  }

  if (!accel.begin()) {
    Serial.println("LIS2DW12 not found");
  } else {
    accel.setMode(LIS2DW12_MODE_LOW_POWER);
    accel.setDataRate(LIS2DW12_ODR_50HZ);
    accel.setRange(LIS2DW12_RANGE_2G);
  }

  pinMode(PIN_TMP_ALERT, INPUT);
  pinMode(PIN_ACCEL_INT, INPUT);
  pinMode(PIN_CHG_STAT, INPUT_PULLUP);
}

void setup() {
  Serial.begin(115200);
  delay(200);
  setupSensors();
  setupEspNow();
}

void loop() {
  Payload payload{};

  payload.temperature_c = tmp117.readTemperature();
  payload.ax_g = accel.x;
  payload.ay_g = accel.y;
  payload.az_g = accel.z;
  payload.charging_active = digitalRead(PIN_CHG_STAT) == LOW ? 1 : 0;

  esp_now_send(peerAddress, reinterpret_cast<const uint8_t*>(&payload), sizeof(payload));

  Serial.print("T=");
  Serial.print(payload.temperature_c);
  Serial.print(" C, A=");
  Serial.print(payload.ax_g); Serial.print(", ");
  Serial.print(payload.ay_g); Serial.print(", ");
  Serial.print(payload.az_g);
  Serial.print(", CHG=");
  Serial.println(payload.charging_active);

  delay(1000);
}
Bring-up checklist
  1. Confirm the peer MAC address for the ESP-NOW receiver.
  2. Verify the TMP117 and LIS2DW12 I2C addresses match the hardware strapping.
  3. Check that the pogo UART path works at 115200 baud.
  4. Confirm charger-status polarity in hardware bring-up.
  5. If low-power firmware is required later, switch the reporting loop to a timer / wake-on-interrupt strategy.
  • Target

  • Pin map from schematic

  • Arduino-style starter sketch

  • Bring-up checklist