HV Pulse Power Design


Expanded the schematic from 92 to 172 components with:
  • Six-cell graphene/EDLC supercapacitor interface
  • External 4S LiFePO₄/BMS interface
  • Isolated charger and bidirectional converter interfaces
  • Channel 4 auxiliary self-power path with startup-power ORing
  • ESP32-WROOM-32E and three ADS1115 telemetry ADCs
  • Independent hardware charger/inverter shutdown
  • Protected 40 A-class external inverter interface
  • Separate HV GND and low-voltage LV_GND
Floating comparator and control-power errors were corrected; floating-pin and missing-power checks are now clean.
Open items
  • Exact isolated charger, bidirectional converter, BMS, and active supercapacitor-balancer modules require measured capture voltage, source impedance, and sustainable power.
  • The new components still need PCB placement; routing has not started.
  • The inverter remains an external certified module rather than onboard mains circuitry.
Project files
Next steps
  1. Re-size and place all 172 footprints by power domain.
  2. Select the external converter and BMS modules from measured source data.
  3. Apply HV/high-current layout rules and isolation boundaries.
  4. Review placement before routing.
Place expanded PCB
Select power modules
Set high-voltage rules
Review safety design

Firmware Starter
Platform
  • MCU: ESP32-WROOM-32E, 16 MB
  • Framework: Arduino with PlatformIO
  • Function: telemetry and command requests only; hardware shutdown remains authoritative
Pin Mapping

Table


NetESP32 pin
I2C_SDAGPIO21
I2C_SCLGPIO22
ADC1_ALERT_NGPIO32
ADC2_ALERT_NGPIO33
ADC3_ALERT_NGPIO4
HW_FAULT_NGPIO27
CHARGER_ENABLE_CMDGPIO16
INVERTER_ENABLE_CMDGPIO17
CHARGER_ILIM_CMDGPIO23
BIDIR_ENABLEGPIO5
BIDIR_DIRECTIONGPIO19
BIDIR_CURRENT_CMDGPIO13
BIDIR_FAULT_NGPIO14
CHARGER_FAULT_NGPIO2
BIDIR_SC_V_TELEMGPIO34, input only
BIDIR_BAT_V_TELEMGPIO35, input only
CHARGER_V_TELEMSENSOR_VP / GPIO36
CHARGER_I_TELEMSENSOR_VN / GPIO39
ESP_BOOT_GPIO0GPIO0
UART RX/TXRXD0/TXD0
platformio.ini

Ini


[env:esp32dev]
platform = espressif32
board = esp32dev
framework = arduino
monitor_speed = 115200
build_flags = -DCORE_DEBUG_LEVEL=3
src/main.cpp

Cpp


#include <Arduino.h>
#include <Wire.h>

static constexpr int PIN_HW_FAULT_N = 27;
static constexpr int PIN_CHARGER_CMD = 16;
static constexpr int PIN_INVERTER_CMD = 17;
static constexpr int PIN_CHARGER_ILIM = 23;
static constexpr int PIN_BIDIR_ENABLE = 5;
static constexpr int PIN_BIDIR_DIR = 19;
static constexpr int PIN_BIDIR_CURRENT = 13;
static constexpr int PIN_BIDIR_FAULT_N = 14;
static constexpr int PIN_CHARGER_FAULT_N = 2;
static constexpr int PIN_ADC1_ALERT_N = 32;
static constexpr int PIN_ADC2_ALERT_N = 33;
static constexpr int PIN_ADC3_ALERT_N = 4;
static constexpr int PIN_SC_TELEM = 34;
static constexpr int PIN_BAT_TELEM = 35;
static constexpr int PIN_CHARGER_V = 36;
static constexpr int PIN_CHARGER_I = 39;

static constexpr uint8_t ADS_ADDR[3] = {0x48, 0x49, 0x4A};

bool writeADS(uint8_t addr, uint8_t reg, uint16_t value) {
  Wire.beginTransmission(addr);
  Wire.write(reg);
  Wire.write(value >> 8);
  Wire.write(value & 0xFF);
  return Wire.endTransmission() == 0;
}

bool readADS(uint8_t addr, uint8_t reg, int16_t &value) {
  Wire.beginTransmission(addr);
  Wire.write(reg);
  if (Wire.endTransmission(false) != 0) return false;
  if (Wire.requestFrom((int)addr, 2) != 2) return false;
  value = (int16_t)((Wire.read() << 8) | Wire.read());
  return true;
}

bool readADSChannel(uint8_t addr, uint8_t channel, int16_t &raw) {
  uint16_t mux = 0x4000u + ((uint16_t)channel << 12);
  uint16_t config = 0x8000u | mux | 0x0200u | 0x0100u | 0x0080u | 0x0003u;
  if (!writeADS(addr, 0x01, config)) return false;
  delay(10);
  return readADS(addr, 0x00, raw);
}

void forceSafeState() {
  digitalWrite(PIN_CHARGER_CMD, LOW);
  digitalWrite(PIN_INVERTER_CMD, LOW);
  digitalWrite(PIN_BIDIR_ENABLE, LOW);
  digitalWrite(PIN_BIDIR_CURRENT, LOW);
  digitalWrite(PIN_CHARGER_ILIM, LOW);
}

void setup() {
  Serial.begin(115200);
  Wire.begin(21, 22);

  pinMode(PIN_HW_FAULT_N, INPUT_PULLUP);
  pinMode(PIN_BIDIR_FAULT_N, INPUT_PULLUP);
  pinMode(PIN_CHARGER_FAULT_N, INPUT_PULLUP);
  pinMode(PIN_ADC1_ALERT_N, INPUT_PULLUP);
  pinMode(PIN_ADC2_ALERT_N, INPUT_PULLUP);
  pinMode(PIN_ADC3_ALERT_N, INPUT_PULLUP);

  pinMode(PIN_CHARGER_CMD, OUTPUT);
  pinMode(PIN_INVERTER_CMD, OUTPUT);
  pinMode(PIN_CHARGER_ILIM, OUTPUT);
  pinMode(PIN_BIDIR_ENABLE, OUTPUT);
  pinMode(PIN_BIDIR_DIR, OUTPUT);
  pinMode(PIN_BIDIR_CURRENT, OUTPUT);
  forceSafeState();

  analogReadResolution(12);
  Serial.println("Hybrid power supervisor starting in SAFE/OFF state");
}

void loop() {
  const bool hwHealthy = digitalRead(PIN_HW_FAULT_N) == HIGH;
  const bool chargerHealthy = digitalRead(PIN_CHARGER_FAULT_N) == HIGH;
  const bool bidirHealthy = digitalRead(PIN_BIDIR_FAULT_N) == HIGH;

  if (!hwHealthy || !chargerHealthy || !bidirHealthy) forceSafeState();

  for (uint8_t adc = 0; adc < 3; ++adc) {
    for (uint8_t channel = 0; channel < 4; ++channel) {
      int16_t raw = 0;
      if (readADSChannel(ADS_ADDR[adc], channel, raw)) {
        Serial.printf("ADS%u CH%u=%d ", adc + 1, channel, raw);
      } else {
        Serial.printf("ADS%u CH%u=ERR ", adc + 1, channel);
      }
    }
  }

  Serial.printf("SC=%d BAT=%d CHG_V=%d CHG_I=%d HW=%d\n",
                analogRead(PIN_SC_TELEM), analogRead(PIN_BAT_TELEM),
                analogRead(PIN_CHARGER_V), analogRead(PIN_CHARGER_I), hwHealthy);
  delay(1000);
}
Build and Flash

Bash


pio run
pio run -t upload
pio device monitor
Hold BOOT while resetting if automatic download entry is unavailable. Do not enable the charger, bidirectional converter, or inverter until measured scaling factors and safe state thresholds are implemented.
  • Platform

  • Pin Mapping

  • platformio.ini

  • src/main.cpp

  • Build and Flash