ShiboSoftwareDev/solar-battery-charger-module

This hardware setup integrates a solar panel, a lithium-ion battery, and a multi-rail buck converter with a battery charging IC, protection circuitry, and monitoring components, enabling solar power harvesting, battery charging, and power distribution in an embedded system.

Version
1.0.4
License
unset
Stars
0

index.circuit.tsx

PCBPCB preview for index.circuit.tsx
SchematicSchematic preview for index.circuit.tsx
import { B3B_PH_SM4_TB_LF__SN_ } from "./imports/B3B_PH_SM4_TB_LF__SN_"
import { BQ24650RVAR } from "./imports/BQ24650RVAR"
import { DFE252012P_1R5M_P2 } from "./imports/DFE252012P_1R5M_P2"
import { IHLP2525CZER100M01 } from "./imports/IHLP2525CZER100M01"
import { KF127S_5_08_2P } from "./imports/KF127S_5_08_2P"
import { SI7288DP_T1_GE3 } from "./imports/SI7288DP_T1_GE3"
import { STC3115AIQT } from "./imports/STC3115AIQT"
import { TPS63031DSKR } from "./imports/TPS63031DSKR"

const jlc = (code: string) => ({ jlcpcb: [code] })

const arcPoints = (
  centerX: number,
  centerY: number,
  radius: number,
  startDegrees: number,
  endDegrees: number,
  segments = 8,
) =>
  Array.from({ length: segments + 1 }, (_, index) => {
    const degrees =
      startDegrees + ((endDegrees - startDegrees) * index) / segments
    const radians = (degrees * Math.PI) / 180
    return {
      x: centerX + radius * Math.cos(radians),
      y: centerY + radius * Math.sin(radians),
    }
  })

// The reference PCB is a 30 mm square core with four castellated contact tabs
// on each side. Each tab protrudes from the core and has an inward semicircular
// edge cut through its exposed top-and-bottom copper.
const referenceBoardOutline = [
  { x: -15, y: 15 },
  { x: 15, y: 15 },
  { x: 15, y: 14.5 },
  { x: 17.2, y: 14.5 },
  { x: 17.2, y: 12.2 },
  ...arcPoints(17.2, 11.3, 0.9, 90, 270).slice(1),
  { x: 17.2, y: 8.1 },
  { x: 15.1, y: 8.1 },
  { x: 15.1, y: 7 },
  { x: 17.4, y: 7 },
  { x: 17.4, y: 4.7 },
  ...arcPoints(17.4, 3.8, 0.9, 90, 270).slice(1),
  { x: 17.4, y: 0.6 },
  { x: 15.1, y: 0.6 },
  { x: 15.1, y: -0.6 },
  { x: 17.4, y: -0.6 },
  { x: 17.4, y: -2.9 },
  ...arcPoints(17.4, -3.8, 0.9, 90, 270).slice(1),
  { x: 17.4, y: -7 },
  { x: 15, y: -7 },
  { x: 15, y: -8 },
  { x: 17.3, y: -8 },
  { x: 17.3, y: -10.3 },
  ...arcPoints(17.3, -11.2, 0.9, 90, 270).slice(1),
  { x: 17.3, y: -14.4 },
  { x: 15, y: -14.4 },
  { x: 15, y: -15 },
  { x: -15, y: -15 },
  { x: -15, y: -14.4 },
  { x: -17.4, y: -14.4 },
  { x: -17.4, y: -12.1 },
  ...arcPoints(-17.4, -11.2, 0.9, -90, 90).slice(1),
  { x: -17.4, y: -8 },
  { x: -15.1, y: -8 },
  { x: -15.1, y: -6.8 },
  { x: -17.3, y: -6.8 },
  { x: -17.3, y: -4.5 },
  ...arcPoints(-17.3, -3.6, 0.9, -90, 90).slice(1),
  { x: -17.3, y: -0.4 },
  { x: -15, y: -0.4 },
  { x: -15, y: 0.6 },
  { x: -17.3, y: 0.6 },
  { x: -17.3, y: 2.9 },
  ...arcPoints(-17.3, 3.8, 0.9, -90, 90).slice(1),
  { x: -17.3, y: 7 },
  { x: -15, y: 7 },
  { x: -15, y: 8.1 },
  { x: -17.4, y: 8.1 },
  { x: -17.4, y: 10.4 },
  ...arcPoints(-17.4, 11.3, 0.9, -90, 90).slice(1),
  { x: -17.4, y: 14.5 },
  { x: -15, y: 14.5 },
]

const referenceOutlineScale = 1.9
const boardOutline = referenceBoardOutline.map(({ x, y }) => ({
  x: Number((x * referenceOutlineScale).toFixed(4)),
  y: Number((y * referenceOutlineScale).toFixed(4)),
}))

const castellatedPadHalfWidth = 1.9
const castellatedPadHalfHeight = 5.7
const castellatedHoleCenterOffset = 2.28
const castellatedHoleRadius = 1.71
const castellatedOuterStripHeight =
  castellatedPadHalfHeight - castellatedHoleRadius
const castellatedOuterStripY =
  (castellatedPadHalfHeight + castellatedHoleRadius) / 2
const castellatedCenterStripWidth =
  castellatedPadHalfWidth +
  castellatedHoleCenterOffset -
  castellatedHoleRadius

const CastellatedPadPair = ({
  x,
  y,
  pin,
  side,
}: {
  x: number
  y: number
  pin: string
  side: "left" | "right"
}) => {
  const direction = side === "left" ? -1 : 1
  const padRegions = [
    {
      x: direction * castellatedPadHalfWidth,
      y: castellatedOuterStripY,
      width: castellatedPadHalfWidth * 2,
      height: castellatedOuterStripHeight,
    },
    {
      x: direction * castellatedPadHalfWidth,
      y: -castellatedOuterStripY,
      width: castellatedPadHalfWidth * 2,
      height: castellatedOuterStripHeight,
    },
    {
      x: direction * (castellatedCenterStripWidth / 2),
      y: 0,
      width: castellatedCenterStripWidth,
      height: castellatedHoleRadius * 2,
    },
  ]

  const [upperRegion, lowerRegion, centerRegion] = padRegions

  return (
    <>
      <smtpad shape="rect" width={upperRegion.width} height={upperRegion.height} pcbX={x + upperRegion.x} pcbY={y + upperRegion.y} layer="top" portHints={[pin]} coveredWithSolderMask={false} solderMaskMargin="0mm" />
      <smtpad shape="rect" width={lowerRegion.width} height={lowerRegion.height} pcbX={x + lowerRegion.x} pcbY={y + lowerRegion.y} layer="top" portHints={[pin]} coveredWithSolderMask={false} solderMaskMargin="0mm" />
      <smtpad shape="rect" width={centerRegion.width} height={centerRegion.height} pcbX={x + centerRegion.x} pcbY={y + centerRegion.y} layer="top" portHints={[pin]} coveredWithSolderMask={false} solderMaskMargin="0mm" />
      <smtpad shape="rect" width={upperRegion.width} height={upperRegion.height} pcbX={x + upperRegion.x} pcbY={y + upperRegion.y} layer="bottom" portHints={[pin]} coveredWithSolderMask={false} solderMaskMargin="0mm" />
      <smtpad shape="rect" width={lowerRegion.width} height={lowerRegion.height} pcbX={x + lowerRegion.x} pcbY={y + lowerRegion.y} layer="bottom" portHints={[pin]} coveredWithSolderMask={false} solderMaskMargin="0mm" />
      <smtpad shape="rect" width={centerRegion.width} height={centerRegion.height} pcbX={x + centerRegion.x} pcbY={y + centerRegion.y} layer="bottom" portHints={[pin]} coveredWithSolderMask={false} solderMaskMargin="0mm" />
    </>
  )
}

const CastellatedContactFootprint = ({
  side,
  contacts,
}: {
  side: "left" | "right"
  contacts: Array<{ x: number; y: number }>
}) => {
  return (
    <footprint insertionDirection="from_above">
      <CastellatedPadPair x={contacts[0].x} y={contacts[0].y} pin="pin1" side={side} />
      <CastellatedPadPair x={contacts[1].x} y={contacts[1].y} pin="pin2" side={side} />
      <CastellatedPadPair x={contacts[2].x} y={contacts[2].y} pin="pin3" side={side} />
      <CastellatedPadPair x={contacts[3].x} y={contacts[3].y} pin="pin4" side={side} />
    </footprint>
  )
}

type NetMap = Record<string, string[]>

const traces: NetMap = {
  SOLAR_IN: [".J_SOLAR > .pin1", ".D_REV > .pin2"],
  VIN_PROTECTED: [
    ".D_REV > .pin1",
    ".Q12 > .D1",
    ".C_IN1 > .pin1",
    ".C_IN2 > .pin1",
    ".R_DAMP > .pin1",
    ".R_VCC > .pin1",
  ],
  DAMP_NODE: [".R_DAMP > .pin2", ".C_DAMP > .pin1"],
  VCC_SENSE: [
    ".R_VCC > .pin2",
    ".C_VCC > .pin1",
    ".U_CHG > .VCC",
    ".R_MPPT_TOP > .pin1",
  ],
  MPPSET: [
    ".U_CHG > .MPPSET",
    ".R_MPPT_TOP > .pin2",
    ".R_MPPT_BOTTOM > .pin1",
    ".Q_CE > .D",
  ],
  CE_GATE: [
    ".J_CTRL > .pin1",
    ".Q_CE > .G",
    ".D_GAUGE_CE > .pin1",
    ".R_CE_PD > .pin1",
  ],
  HIDRV: [".U_CHG > .HIDRV", ".Q12 > .G1"],
  LODRV: [".U_CHG > .LODRV", ".Q12 > .G2"],
  PH: [
    ".U_CHG > .PH",
    ".Q12 > .S1",
    ".Q12 > .D2",
    ".C_BOOT > .pin2",
    ".L_CHG > .pin1",
  ],
  CHG_POWER_PRE_SENSE: [
    ".L_CHG > .pin2",
    ".R_CHG_SENSE > .pin1",
    ".R_SRP_KELVIN > .pin1",
  ],
  SRP_KELVIN: [
    ".R_SRP_KELVIN > .pin2",
    ".U_CHG > .SRP",
    ".C_SENSE_DIFF > .pin1",
    ".C_SRP_GND > .pin1",
  ],
  BATTERY_POWER: [
    ".R_CHG_SENSE > .pin2",
    ".J_BAT > .pin1",
    ".C_BAT > .pin1",
    ".R_SRN_KELVIN > .pin1",
    ".R_VBAT_KELVIN > .pin1",
    ".R_BUCK_INPUT > .pin1",
  ],
  BUCK_INPUT: [
    ".R_BUCK_INPUT > .pin2",
    ".U_3V3 > .VIN",
    ".U_3V3 > .VINA",
    ".C_3V3_IN > .pin1",
    ".C_3V3_BYP > .pin1",
  ],
  SRN_KELVIN: [
    ".R_SRN_KELVIN > .pin2",
    ".U_CHG > .SRN",
    ".C_SENSE_DIFF > .pin2",
    ".C_SRN_GND > .pin1",
  ],
  BATTERY_SENSE: [
    ".R_VBAT_KELVIN > .pin2",
    ".R_VFB_TOP > .pin1",
    ".C_VFB > .pin1",
    ".U_GAUGE > .VCC",
    ".C_GAUGE_VCC > .pin1",
    ".R_GAUGE_VIN > .pin1",
  ],
  VFB: [
    ".U_CHG > .VFB",
    ".R_VFB_TOP > .pin2",
    ".R_VFB_BOTTOM > .pin1",
    ".C_VFB > .pin2",
  ],
  REGN: [
    ".U_CHG > .REGN",
    ".C_REGN > .pin1",
    ".D_BOOT > .pin2",
  ],
  BTST: [".U_CHG > .BTST", ".D_BOOT > .pin1", ".C_BOOT > .pin1"],
  VREF: [
    ".U_CHG > .VREF",
    ".U_CHG > .TERM_EN",
    ".C_VREF > .pin1",
    ".R_TS_PULLUP > .pin1",
    ".R_STAT1 > .pin1",
    ".R_STAT2 > .pin1",
  ],
  CHG_AGND: [
    ".U_CHG > .GND",
    ".C_VCC > .pin2",
    ".R_MPPT_BOTTOM > .pin2",
    ".R_VFB_BOTTOM > .pin2",
    ".C_VREF > .pin2",
    ".R_TS_BOTTOM > .pin2",
    ".C_SRP_GND > .pin2",
    ".C_SRN_GND > .pin2",
    ".R_CHG_AGND > .pin2",
  ],
  TS: [
    ".U_CHG > .TS",
    ".J_BAT > .pin2",
    ".R_TS_PULLUP > .pin2",
    ".R_TS_BOTTOM > .pin1",
  ],
  STAT1_LED_A: [".R_STAT1 > .pin2", ".D_STAT1 > .pin2"],
  STAT1: [".D_STAT1 > .pin1", ".U_CHG > .STAT1"],
  STAT2_LED_A: [".R_STAT2 > .pin2", ".D_STAT2 > .pin2"],
  STAT2: [".D_STAT2 > .pin1", ".U_CHG > .STAT2"],
  BAT_NEG: [".J_BAT > .pin3", ".R_GAUGE_SENSE > .pin1", ".R_CG_KELVIN > .pin1"],
  GAUGE_CG: [".R_CG_KELVIN > .pin2", ".U_GAUGE > .CG"],
  GAUGE_GND_KELVIN: [
    ".R_GND_KELVIN > .pin2",
    ".U_GAUGE > .GND",
    ".C_GAUGE_VCC > .pin2",
    ".C_GAUGE_VIN > .pin2",
    ".R_BATD > .pin2",
  ],
  GAUGE_VIN: [
    ".R_GAUGE_VIN > .pin2",
    ".C_GAUGE_VIN > .pin1",
    ".U_GAUGE > .VIN",
  ],
  GAUGE_BATD: [".R_BATD > .pin1", ".U_GAUGE > .pin8", ".D_GAUGE_CE > .pin2"],
  ALM: [".U_GAUGE > .ALM", ".R_ALM > .pin2", ".J_CTRL > .pin3"],
  SDA: [".U_GAUGE > .SDA", ".R_SDA > .pin2", ".J_IO > .pin3"],
  SCL: [".U_GAUGE > .SCL", ".R_SCL > .pin2", ".J_IO > .pin4"],
  OUT_EN: [".U_3V3 > .EN", ".R_OUT_EN_PD > .pin1", ".J_CTRL > .pin2"],
  BUCK_L1: [".U_3V3 > .L1", ".L_3V3 > .pin1"],
  BUCK_L2: [".U_3V3 > .L2", ".L_3V3 > .pin2"],
  PS_SYNC_LOW: [".U_3V3 > .PS_SYNC", ".R_PS_SYNC > .pin1"],
  TPS_AGND: [
    ".U_3V3 > .GND",
    ".R_TPS_AGND > .pin2",
  ],
  VOUT_3V3: [
    ".U_3V3 > .VOUT",
    ".U_3V3 > .FB",
    ".C_3V3_OUT1 > .pin1",
    ".C_3V3_OUT2 > .pin1",
    ".R_ALM > .pin1",
    ".R_SDA > .pin1",
    ".R_SCL > .pin1",
    ".J_IO > .pin1",
  ],
  GND: [
    ".J_SOLAR > .pin2",
    ".C_IN1 > .pin2",
    ".C_IN2 > .pin2",
    ".C_DAMP > .pin2",
    ".Q_CE > .S",
    ".R_CE_PD > .pin2",
    ".Q12 > .S2",
    ".U_CHG > .EP",
    ".C_BAT > .pin2",
    ".C_REGN > .pin2",
    ".R_GAUGE_SENSE > .pin2",
    ".R_GND_KELVIN > .pin1",
    ".R_CHG_AGND > .pin1",
    ".U_3V3 > .PGND",
    ".U_3V3 > .EP",
    ".C_3V3_IN > .pin2",
    ".C_3V3_BYP > .pin2",
    ".C_3V3_OUT1 > .pin2",
    ".C_3V3_OUT2 > .pin2",
    ".R_TPS_AGND > .pin1",
    ".R_PS_SYNC > .pin2",
    ".R_OUT_EN_PD > .pin2",
    ".J_CTRL > .pin4",
    ".J_IO > .pin2",
  ],
}

const powerNets = new Set([
  "SOLAR_IN",
  "VIN_PROTECTED",
  "PH",
  "CHG_POWER_PRE_SENSE",
  "BATTERY_POWER",
  "BAT_NEG",
])

const mediumPowerNets = new Set(["BUCK_INPUT", "VOUT_3V3", "GND", "BUCK_L1", "BUCK_L2"])

const traceThickness = (netName: string) => {
  if (powerNets.has(netName)) return "0.6mm"
  if (netName === "VOUT_3V3") return "0.3mm"
  if (mediumPowerNets.has(netName)) return "0.4mm"
  return "0.15mm"
}

const Resistor = ({
  name,
  resistance,
  footprint,
  mpn,
  lcsc,
  pcbX,
  pcbY,
  pcbRotation = 0,
  schX,
  schY,
  schSectionName,
}: {
  name: string
  resistance: string
  footprint: string
  mpn: string
  lcsc: string
  pcbX: number
  pcbY: number
  pcbRotation?: number
  schX: number
  schY: number
  schSectionName: string
}) => (
  <resistor
    name={name}
    resistance={resistance}
    footprint={footprint}
    manufacturerPartNumber={mpn}
    supplierPartNumbers={jlc(lcsc)}
    pcbX={pcbX}
    pcbY={pcbY}
    pcbRotation={pcbRotation}
    schX={schX}
    schY={schY}
    schSectionName={schSectionName}
  />
)

const Capacitor = ({
  name,
  capacitance,
  footprint,
  mpn,
  lcsc,
  pcbX,
  pcbY,
  pcbRotation = 0,
  schX,
  schY,
  schSectionName,
}: {
  name: string
  capacitance: string
  footprint: string
  mpn: string
  lcsc: string
  pcbX: number
  pcbY: number
  pcbRotation?: number
  schX: number
  schY: number
  schSectionName: string
}) => (
  <capacitor
    name={name}
    capacitance={capacitance}
    footprint={footprint}
    manufacturerPartNumber={mpn}
    supplierPartNumbers={jlc(lcsc)}
    pcbX={pcbX}
    pcbY={pcbY}
    pcbRotation={pcbRotation}
    schX={schX}
    schY={schY}
    schOrientation="vertical"
    schSectionName={schSectionName}
  />
)

export default () => (
  <board
    title="Solar Battery Charger Module - fabrication revision"
    outline={boardOutline}
    layers={2}
    thickness="1.2mm"
    solderMaskColor="black"
    silkscreenColor="white"
    defaultTraceWidth="0.15mm"
    minTraceWidth="0.15mm"
    minTraceToPadEdgeClearance="0.1mm"
    minPadEdgeToPadEdgeClearance="0.15mm"
    minBoardEdgeClearance="0mm"
    minViaHoleDiameter="0.15mm"
    minViaPadDiameter="0.35mm"
    minViaEdgeToPadEdgeClearance="0.1mm"
    isViaInPadAllowed
    autorouter={{ preset: "default", traceClearance: "0.1mm" }}
    schAutoLayoutEnabled
    schTraceAutoLabelEnabled
  >
    <schematicsection name="Solar" displayName="Solar charger (BQ24650)" />
    <schematicsection name="Gauge" displayName="Battery gauge (STC3115)" />
    <schematicsection name="Output" displayName="3.3 V buck-boost output" />
    <schematicsection name="IO" displayName="Connectors and status" />

    <KF127S_5_08_2P
      name="J_SOLAR"
      pcbX={-23}
      pcbY={18}
      pcbRotation={0}
      schX={-19}
      schY={8}
      schSectionName="Solar"
    />

    <B3B_PH_SM4_TB_LF__SN_
      name="J_BAT"
      noConnect={["pin4", "pin5"]}
      pcbX={20}
      pcbY={23.5}
      pcbRotation={0}
      schX={18}
      schY={7}
      schHeight={0.6}
      schSectionName="Gauge"
    />

    <chip
      name="D_REV"
      pinLabels={{ pin1: "K", pin2: "A" }}
      footprint="sma"
      manufacturerPartNumber="SS54"
      supplierPartNumbers={jlc("C22452")}
      pcbX={-23}
      pcbY={9.5}
      pcbRotation={0}
      schX={-17}
      schY={8}
      schSectionName="Solar"
    />

    <Capacitor name="C_IN1" capacitance="10uF" footprint="1210" mpn="GRM32ER7YA106KA12L" lcsc="C97973" pcbX={-6.5} pcbY={16} pcbRotation={180} schX={-15} schY={9} schSectionName="Solar" />
    <Capacitor name="C_IN2" capacitance="10uF" footprint="1210" mpn="GRM32ER7YA106KA12L" lcsc="C97973" pcbX={-17} pcbY={7.5} pcbRotation={180} schX={-15} schY={7} schSectionName="Solar" />
    <Resistor name="R_DAMP" resistance="2" footprint="2512" mpn="FRC2512F2R00TS" lcsc="C3013321" pcbX={-13} pcbY={20.5} schX={-13} schY={9} schSectionName="Solar" />
    <Capacitor name="C_DAMP" capacitance="2.2uF" footprint="1210" mpn="1210B225K500NT" lcsc="C1950" pcbX={-6.7} pcbY={20.5} schX={-11} schY={9} schSectionName="Solar" />
    <Resistor name="R_VCC" resistance="10" footprint="1206" mpn="1206W4F100JT5E" lcsc="C17903" pcbX={-12.5} pcbY={12} schX={-13} schY={6} schSectionName="Solar" />
    <Capacitor name="C_VCC" capacitance="1uF" footprint="0805" mpn="CL21B105KBFNNNE" lcsc="C28323" pcbX={4.5} pcbY={11.8} schX={-11} schY={6} schSectionName="Solar" />

    <BQ24650RVAR
      name="U_CHG"
      pcbX={3.5}
      pcbY={8.5}
      pcbRotation={270}
      schX={-7.63}
      schY={7}
      schWidth={2.2}
      schHeight={1.8}
      schSectionName="Solar"
    />

    <SI7288DP_T1_GE3
      name="Q12"
      pcbX={0}
      pcbY={17.2}
      pcbRotation={0}
      schX={-3}
      schY={9}
      schSectionName="Solar"
    />

    <chip
      name="Q_CE"
      manufacturerPartNumber="2N7002"
      supplierPartNumbers={jlc("C8545")}
      footprint="sot23"
      pinLabels={{ pin1: "G", pin2: "S", pin3: "D" }}
      pcbX={-3}
      pcbY={8.5}
      pcbRotation={90}
      schX={-4.37}
      schY={6}
      schHeight={0.4}
      schSectionName="Solar"
    />

    <Resistor name="R_CE_PD" resistance="100k" footprint="0402" mpn="0402WGF1003TCE" lcsc="C25741" pcbX={-6} pcbY={6} schX={0} schY={6} schSectionName="Solar" />
    <chip
      name="D_GAUGE_CE"
      pinLabels={{ pin1: "K", pin2: "A" }}
      footprint="sod123"
      manufacturerPartNumber="MBR0540T1G"
      supplierPartNumbers={jlc("C21353")}
      pcbX={26.5}
      pcbY={14}
      pcbRotation={270}
      schX={3}
      schY={6}
      schSectionName="Gauge"
    />

    <IHLP2525CZER100M01 name="L_CHG" pcbX={8.5} pcbY={17.2} schX={1} schY={9} schSectionName="Solar" />

    <Resistor name="R_CHG_SENSE" resistance="0.02" footprint="1206" mpn="WSL1206R0200FEA" lcsc="C844895" pcbX={15.5} pcbY={17.2} schX={4} schY={9} schSectionName="Solar" />
    <Capacitor name="C_BAT" capacitance="10uF" footprint="1210" mpn="GRM32ER7YA106KA12L" lcsc="C97973" pcbX={14} pcbY={10.5} schX={7} schY={9} schSectionName="Solar" />

    <Resistor name="R_SRP_KELVIN" resistance="0" footprint="0402" mpn="0402WGF0000TCE" lcsc="C17168" pcbX={14} pcbY={13.5} pcbRotation={90} schX={2.6} schY={7.8} schSectionName="Solar" />
    <Resistor name="R_SRN_KELVIN" resistance="0" footprint="0402" mpn="0402WGF0000TCE" lcsc="C17168" pcbX={19.2} pcbY={15} pcbRotation={90} schX={5.4} schY={7.8} schSectionName="Solar" />
    <Resistor name="R_VBAT_KELVIN" resistance="0" footprint="0402" mpn="0402WGF0000TCE" lcsc="C17168" pcbX={25.5} pcbY={17.5} pcbRotation={90} schX={8} schY={7.5} schSectionName="Gauge" />
    <Capacitor name="C_SENSE_DIFF" capacitance="0.1uF" footprint="0402" mpn="CL05B104KB5NNNC" lcsc="C960916" pcbX={10} pcbY={3.5} schX={3.24} schY={7} schSectionName="Solar" />
    <Capacitor name="C_SRP_GND" capacitance="0.1uF" footprint="0402" mpn="CL05B104KB5NNNC" lcsc="C960916" pcbX={8.5} pcbY={7} schX={3} schY={4} schSectionName="Solar" />
    <Capacitor name="C_SRN_GND" capacitance="0.1uF" footprint="0402" mpn="CL05B104KB5NNNC" lcsc="C960916" pcbX={8.5} pcbY={5.3} schX={6} schY={4} schSectionName="Solar" />

    <Resistor name="R_MPPT_TOP" resistance="499k" footprint="0402" mpn="0402WGF4993TCE" lcsc="C25793" pcbX={-7} pcbY={9.5} schX={-9} schY={4} schSectionName="Solar" />
    <Resistor name="R_MPPT_BOTTOM" resistance="36k" footprint="0402" mpn="0402WGF3602TCE" lcsc="C43676" pcbX={-7} pcbY={7.5} schX={-7} schY={4} schSectionName="Solar" />
    <Resistor name="R_VFB_TOP" resistance="100k" footprint="0402" mpn="0402WGF1003TCE" lcsc="C25741" pcbX={10} pcbY={0} schX={7} schY={7} schSectionName="Solar" />
    <Resistor name="R_VFB_BOTTOM" resistance="100k" footprint="0402" mpn="0402WGF1003TCE" lcsc="C25741" pcbX={13} pcbY={0} schX={10} schY={7} schSectionName="Solar" />
    <Capacitor name="C_VFB" capacitance="22pF" footprint="0402" mpn="0402CG220J500NT" lcsc="C1555" pcbX={11.5} pcbY={-1.5} schX={8.5} schY={4} schSectionName="Solar" />
    <Capacitor name="C_REGN" capacitance="1uF" footprint="0805" mpn="CL21B105KBFNNNE" lcsc="C28323" pcbX={8} pcbY={9.25} schX={-5} schY={4} schSectionName="Solar" />
    <Capacitor name="C_VREF" capacitance="1uF" footprint="0805" mpn="CL21B105KBFNNNE" lcsc="C28323" pcbX={3.5} pcbY={4.5} schX={-4} schY={2} schSectionName="Solar" />
    <Resistor name="R_CHG_AGND" resistance="0" footprint="0402" mpn="0402WGF0000TCE" lcsc="C17168" pcbX={6.5} pcbY={4.2} schX={-1} schY={0} schSectionName="Solar" />

    <chip
      name="D_BOOT"
      pinLabels={{ pin1: "K", pin2: "A" }}
      footprint="sod123"
      manufacturerPartNumber="MBR0540T1G"
      supplierPartNumbers={jlc("C21353")}
      pcbX={-6.5}
      pcbY={12.5}
      pcbRotation={0}
      schX={-1.12}
      schY={2}
      schSectionName="Solar"
    />
    <Capacitor name="C_BOOT" capacitance="0.1uF" footprint="0402" mpn="CL05B104KB5NNNC" lcsc="C960916" pcbX={1.5} pcbY={12.1} schX={1.13} schY={2} schSectionName="Solar" />

    <Resistor name="R_TS_PULLUP" resistance="7.5k" footprint="0402" mpn="0402WGF7501TCE" lcsc="C25918" pcbX={-11} pcbY={2} schX={1} schY={0} schSectionName="Solar" />
    <Resistor name="R_TS_BOTTOM" resistance="82k" footprint="0402" mpn="0402WGF8202TCE" lcsc="C4142" pcbX={-9} pcbY={2} schX={4} schY={0} schSectionName="Solar" />

    <Resistor name="R_STAT1" resistance="10k" footprint="0402" mpn="0402WGF1002TCE" lcsc="C25744" pcbX={-5} pcbY={4.5} schX={-7} schY={-1} schSectionName="Solar" />
    <chip name="D_STAT1" pinLabels={{ pin1: "K", pin2: "A" }} footprint="0603" manufacturerPartNumber="LTST-C190GKT" supplierPartNumbers={jlc("C125093")} pcbX={-2} pcbY={4.5} schX={-3} schY={-1} schSectionName="Solar" />
    <Resistor name="R_STAT2" resistance="10k" footprint="0402" mpn="0402WGF1002TCE" lcsc="C25744" pcbX={-2} pcbY={-4} schX={0} schY={-1} schSectionName="Solar" />
    <chip name="D_STAT2" pinLabels={{ pin1: "K", pin2: "A" }} footprint="0603" manufacturerPartNumber="LTST-C190KRKT" supplierPartNumbers={jlc("C94869")} pcbX={1} pcbY={-4} schX={3} schY={-1} schSectionName="Solar" />

    <Resistor name="R_GAUGE_SENSE" resistance="0.005" footprint="1206" mpn="HoLLR1206-1W-5mR-1%" lcsc="C2988648" pcbX={20.5} pcbY={17.5} schX={11.81} schY={8} schSectionName="Gauge" />
    <Resistor name="R_CG_KELVIN" resistance="0" footprint="0402" mpn="0402WGF0000TCE" lcsc="C17168" pcbX={23.5} pcbY={13.2} pcbRotation={90} schX={13.6} schY={8} schSectionName="Gauge" />
    <Resistor name="R_GND_KELVIN" resistance="0" footprint="0402" mpn="0402WGF0000TCE" lcsc="C17168" pcbX={24.5} pcbY={8} pcbRotation={90} schX={16.4} schY={8} schSectionName="Gauge" />

    <STC3115AIQT
      name="U_GAUGE"
      noConnect={["NC", "RSTIO"]}
      pcbX={20.5}
      pcbY={9.5}
      pcbRotation={0}
      schX={14}
      schY={5}
      schSectionName="Gauge"
    />

    <Capacitor name="C_GAUGE_VCC" capacitance="1uF" footprint="0402" mpn="GRM155Z71A105KE01D" lcsc="C528974" pcbX={19.2} pcbY={12.5} pcbRotation={90} schX={18} schY={5} schSectionName="Gauge" />
    <Resistor name="R_GAUGE_VIN" resistance="1k" footprint="0402" mpn="0402WGF1001TCE" lcsc="C11702" pcbX={17.5} pcbY={10.2} schX={11.95} schY={2} schSectionName="Gauge" />
    <Capacitor name="C_GAUGE_VIN" capacitance="220nF" footprint="0402" mpn="CC0402KRX7R6BB224" lcsc="C705052" pcbX={17.2} pcbY={8.7} pcbRotation={270} schX={13.8} schY={2} schSectionName="Gauge" />
    <Resistor name="R_BATD" resistance="1k" footprint="0402" mpn="0402WGF1001TCE" lcsc="C11702" pcbX={23.5} pcbY={11.2} pcbRotation={90} schX={16.25} schY={2} schSectionName="Gauge" />

    <TPS63031DSKR
      name="U_3V3"
      pcbX={9}
      pcbY={-10}
      pcbRotation={0}
      schX={5}
      schY={-6}
      schHeight={1.2}
      schSectionName="Output"
    />
    <DFE252012P_1R5M_P2 name="L_3V3" pcbX={4} pcbY={-10} schX={1} schY={-6} schSectionName="Output" />
    <Resistor name="R_BUCK_INPUT" resistance="0" footprint="0402" mpn="0402WGF0000TCE" lcsc="C17168" pcbX={11.7} pcbY={-13.5} pcbRotation={180} schX={0.5} schY={-8} schSectionName="Output" />
    <Capacitor name="C_3V3_IN" capacitance="10uF" footprint="0603" mpn="CL10B106MQ8NRNC" lcsc="C3039698" pcbX={9} pcbY={-13.5} schX={3} schY={-8} schSectionName="Output" />
    <Capacitor name="C_3V3_BYP" capacitance="0.1uF" footprint="0402" mpn="CL05B104KB5NNNC" lcsc="C960916" pcbX={10.8} pcbY={-12.1} pcbRotation={180} schX={7} schY={-8} schSectionName="Output" />
    <Capacitor name="C_3V3_OUT1" capacitance="10uF" footprint="0603" mpn="CL10B106MQ8NRNC" lcsc="C3039698" pcbX={9} pcbY={-7} schX={9} schY={-6} schSectionName="Output" />
    <Capacitor name="C_3V3_OUT2" capacitance="10uF" footprint="0603" mpn="CL10B106MQ8NRNC" lcsc="C3039698" pcbX={14.5} pcbY={-8} pcbRotation={270} schX={9} schY={-8} schSectionName="Output" />
    <Resistor name="R_TPS_AGND" resistance="0" footprint="0402" mpn="0402WGF0000TCE" lcsc="C17168" pcbX={11.8} pcbY={-9.2} pcbRotation={180} schX={6.38} schY={-4} schSectionName="Output" />
    <Resistor name="R_PS_SYNC" resistance="0" footprint="0402" mpn="0402WGF0000TCE" lcsc="C17168" pcbX={13} pcbY={-10.5} schX={8.62} schY={-4} schSectionName="Output" />
    <Resistor name="R_OUT_EN_PD" resistance="1M" footprint="0402" mpn="0402WGF1004TCE" lcsc="C26083" pcbX={14} pcbY={-12} schX={3} schY={-4} schSectionName="Output" />

    <Resistor name="R_ALM" resistance="10k" footprint="0402" mpn="0402WGF1002TCE" lcsc="C25744" pcbX={16} pcbY={6.5} schX={13} schY={-1} schSectionName="IO" />
    <Resistor name="R_SDA" resistance="10k" footprint="0402" mpn="0402WGF1002TCE" lcsc="C25744" pcbX={19.5} pcbY={6.5} schX={15} schY={-1} schSectionName="IO" />
    <Resistor name="R_SCL" resistance="10k" footprint="0402" mpn="0402WGF1002TCE" lcsc="C25744" pcbX={22} pcbY={6.5} schX={17} schY={-1} schSectionName="IO" />

    {/* These pads intentionally intersect the board contour to form JLCPCB
        castellated contacts. The board-level edge clearance is therefore 0. */}
      <connector
        name="J_CTRL"
        displayName="LEFT CASTELLATED CONTACTS"
        footprint={
          <CastellatedContactFootprint
            side="left"
            contacts={[
              { x: -28.88, y: 21.47 },
              { x: -28.69, y: 7.22 },
              { x: -28.69, y: -6.84 },
              { x: -28.88, y: -21.28 },
            ]}
          />
        }
        pinLabels={{ pin1: "CHARGE_DISABLE", pin2: "OUT_EN", pin3: "ALM", pin4: "GND" }}
        pcbX={0}
        pcbY={0}
        doNotPlace
        allowOffBoard
        obstructsWithinBounds={false}
        schX={15}
        schY={-5}
        schSectionName="IO"
      />
      <connector
        name="J_IO"
        displayName="RIGHT CASTELLATED CONTACTS"
        footprint={
          <CastellatedContactFootprint
            side="right"
            contacts={[
              { x: 28.5, y: 21.47 },
              { x: 28.88, y: 7.22 },
              { x: 28.88, y: -7.22 },
              { x: 28.69, y: -21.28 },
            ]}
          />
        }
        pinLabels={{ pin1: "3V3", pin2: "GND", pin3: "SDA", pin4: "SCL" }}
        pcbX={0}
        pcbY={0}
        doNotPlace
        allowOffBoard
        obstructsWithinBounds={false}
        schX={19}
        schY={-5}
        schSectionName="IO"
      />

    <silkscreentext text="21V PANEL / 17.8V MPPT" fontSize={0.9} pcbX={-23} pcbY={23} />
    <silkscreentext text="1S Li-ion: + NTC -" fontSize={1.0} pcbX={19} pcbY={27} />
    <silkscreentext text="3V3 / GND / SDA / SCL" fontSize={0.8} pcbX={27} pcbY={-19} pcbRotation={90} />
    <silkscreentext text="CHG_OFF / OUT_EN / ALM / GND" fontSize={0.72} pcbX={-27} pcbY={-19} pcbRotation={90} />
    <silkscreentext text="2A SOLAR CHARGER - 3.3V OUT" fontSize={1.1} pcbX={0} pcbY={-22} />

    <tracehint for=".J_CTRL > .pin1" offset={{ x: -27, y: 21.47 }} />
    <tracehint for=".J_CTRL > .pin2" offset={{ x: -27, y: 7.22 }} />
    <tracehint for=".J_CTRL > .pin3" offset={{ x: -27, y: -6.84 }} />
    <tracehint for=".J_CTRL > .pin4" offset={{ x: -27, y: -21.28 }} />
    <tracehint for=".J_IO > .pin1" offset={{ x: 27, y: 21.47 }} />
    <tracehint for=".J_IO > .pin2" offset={{ x: 27, y: 7.22 }} />
    <tracehint for=".J_IO > .pin3" offset={{ x: 27, y: -7.22 }} />
    <tracehint for=".J_IO > .pin4" offset={{ x: 27, y: -21.28 }} />
    <tracehint for=".J_BAT > .pin3" offset={{ x: 18, y: 20 }} />

    {Object.entries(traces).flatMap(([netName, pins]) => {
      return pins.map((pin, index) => (
        <trace
          key={`${netName}-${pin}`}
          name={`T_${netName}_${index + 1}`}
          from={pin}
          to={`net.${netName}`}
          thickness={traceThickness(netName)}
        />
      ))
    })}

    <copperpour connectsTo="net.GND" layer="top" clearance="0.2mm" boardEdgeMargin="0.4mm" />
    <copperpour connectsTo="net.GND" layer="bottom" clearance="0.2mm" boardEdgeMargin="0.4mm" />
  </board>
)