From f575654d125aadecf29c0aa9ba8b60a56f07cfc2 Mon Sep 17 00:00:00 2001 From: Suke0811 <49264928+Suke0811@users.noreply.github.com> Date: Wed, 18 Mar 2026 10:58:39 +0100 Subject: [PATCH 1/4] Mark: Ap3418 as deprecated --- edg/parts/FuelGauge_Max17048.py | 84 +++++++++++++++++++++++++++++++++ edg/parts/__init__.py | 1 + 2 files changed, 85 insertions(+) create mode 100644 edg/parts/FuelGauge_Max17048.py diff --git a/edg/parts/FuelGauge_Max17048.py b/edg/parts/FuelGauge_Max17048.py new file mode 100644 index 000000000..ee3f1a480 --- /dev/null +++ b/edg/parts/FuelGauge_Max17048.py @@ -0,0 +1,84 @@ +from typing_extensions import override +from ..abstract_parts import * +from .JlcPart import JlcPart + + +class Max17048_Device(InternalSubcircuit, FootprintBlock, JlcPart): + """MAX17048 1-Cell Li-Ion Fuel Gauge""" + + def __init__(self) -> None: + super().__init__() + self.vdd = self.Port(VoltageSink( + voltage_limits=Range(2.5, 4.5), + current_draw=(0, 100) * uAmp, # ~23 uA typ, margin included + )) + self.gnd = self.Port(Ground()) + + # I2C target interface + # I/O tolerant to 5.5 V independent of VDD (per datasheet) + dio_model = DigitalBidir.from_supply( + self.gnd, self.vdd, + voltage_limit_abs=(-0.5 * Volt, 5.5 * Volt), + input_threshold_factor=(0.3, 0.7) + ) + self.i2c = self.Port(I2cTarget(dio_model, addresses=ArrayIntExpr())) + + self.alrt = self.Port(DigitalSingleSource( + voltage_out=Range(0, 5.5), + output_thresholds=Range(0, 5.5), + pullup_capable=True, + ), optional=True) + + self.qstrt = self.Port(Passive()) + + @override + def contents(self) -> None: + super().contents() + self.footprint( + 'U', 'Package_DFN_QFN:DFN-8-1EP_2x2mm_P0.5mm_EP0.8x1.6mm', + { + '1': self.gnd, + '3': self.vdd, + '4': self.gnd, + '5': self.alrt, + '6': self.qstrt, + '7': self.i2c.scl, + '8': self.i2c.sda, + '9': self.gnd, + }, + mfr='Analog Devices (Maxim)', part='MAX17048', + datasheet='https://www.analog.com/media/en/technical-documentation/data-sheets/MAX17048-MAX17049.pdf' + ) + self.assign(self.lcsc_part, 'C2682616') + self.assign(self.actual_basic_part, False) + + +class Max17048(DefaultExportBlock): + """MAX17048 fuel gauge with decoupling and internal ties""" + + def __init__(self) -> None: + super().__init__() + self.ic = self.Block(Max17048_Device()) + + self.vdd = self.Export(self.ic.vdd, [Power]) + self.gnd = self.Export(self.ic.gnd, [Common]) + self.i2c = self.Export(self.ic.i2c) + self.alrt = self.Export(self.ic.alrt, optional=True) + + self.addr = self.Parameter(IntExpr(0x36)) + + @override + def contents(self) -> None: + super().contents() + + # Required local decoupling 0.1 uF from VDD to GND + self.vdd_cap = self.Block(DecouplingCapacitor(0.1 * uFarad(tol=0.2))).connected(self.gnd, self.ic.vdd) + + # Tie QSTRT to ground unless otherwise needed + self.connect(self.ic.qstrt.adapt_to(Ground()), self.gnd) + + # Optional pull-up resistor for the alert pin + self.alrt_pull = self.Block(PullupResistor(10 * kOhm(tol=0.05))).connected(self.vdd, self.ic.alrt) + + # Try to assign the default I2C 7-bit address if the model supports it + self.assign(self.ic.i2c.addresses, [self.addr]) diff --git a/edg/parts/__init__.py b/edg/parts/__init__.py index f82c7bb78..4dd400794 100644 --- a/edg/parts/__init__.py +++ b/edg/parts/__init__.py @@ -181,6 +181,7 @@ from .CanTransceiver_Sn65hvd230 import Sn65hvd230 from .CurrentSense_Ad8418 import Ad8418a from .Ina219 import Ina219 +from .FuelGauge_Max17048 import Max17048 from .BatteryProtector_S8261A import S8261A from .BatteryCharger_Mcp73831 import Mcp73831 from .Distance_Vl53l0x import Vl53l0x, Vl53l0xConnector, Vl53l0xArray From d89c219967318c733262fbc64866e7f0be6a2516 Mon Sep 17 00:00:00 2001 From: Suke0811 <49264928+Suke0811@users.noreply.github.com> Date: Wed, 18 Mar 2026 11:25:42 +0100 Subject: [PATCH 2/4] Refactor: reformat MAX17048 fuel gauge for improved readability --- edg/parts/FuelGauge_Max17048.py | 53 ++++++++++++++++++--------------- 1 file changed, 29 insertions(+), 24 deletions(-) diff --git a/edg/parts/FuelGauge_Max17048.py b/edg/parts/FuelGauge_Max17048.py index ee3f1a480..33e6f9631 100644 --- a/edg/parts/FuelGauge_Max17048.py +++ b/edg/parts/FuelGauge_Max17048.py @@ -8,26 +8,29 @@ class Max17048_Device(InternalSubcircuit, FootprintBlock, JlcPart): def __init__(self) -> None: super().__init__() - self.vdd = self.Port(VoltageSink( - voltage_limits=Range(2.5, 4.5), - current_draw=(0, 100) * uAmp, # ~23 uA typ, margin included - )) + self.vdd = self.Port( + VoltageSink( + voltage_limits=Range(2.5, 4.5), + current_draw=(0, 100) * uAmp, # ~23 uA typ, margin included + ) + ) self.gnd = self.Port(Ground()) # I2C target interface # I/O tolerant to 5.5 V independent of VDD (per datasheet) dio_model = DigitalBidir.from_supply( - self.gnd, self.vdd, - voltage_limit_abs=(-0.5 * Volt, 5.5 * Volt), - input_threshold_factor=(0.3, 0.7) + self.gnd, self.vdd, voltage_limit_abs=(-0.5 * Volt, 5.5 * Volt), input_threshold_factor=(0.3, 0.7) ) self.i2c = self.Port(I2cTarget(dio_model, addresses=ArrayIntExpr())) - self.alrt = self.Port(DigitalSingleSource( - voltage_out=Range(0, 5.5), - output_thresholds=Range(0, 5.5), - pullup_capable=True, - ), optional=True) + self.alrt = self.Port( + DigitalSingleSource( + voltage_out=Range(0, 5.5), + output_thresholds=Range(0, 5.5), + pullup_capable=True, + ), + optional=True, + ) self.qstrt = self.Port(Passive()) @@ -35,21 +38,23 @@ def __init__(self) -> None: def contents(self) -> None: super().contents() self.footprint( - 'U', 'Package_DFN_QFN:DFN-8-1EP_2x2mm_P0.5mm_EP0.8x1.6mm', + "U", + "Package_DFN_QFN:DFN-8-1EP_2x2mm_P0.5mm_EP0.8x1.6mm", { - '1': self.gnd, - '3': self.vdd, - '4': self.gnd, - '5': self.alrt, - '6': self.qstrt, - '7': self.i2c.scl, - '8': self.i2c.sda, - '9': self.gnd, + "1": self.gnd, + "3": self.vdd, + "4": self.gnd, + "5": self.alrt, + "6": self.qstrt, + "7": self.i2c.scl, + "8": self.i2c.sda, + "9": self.gnd, }, - mfr='Analog Devices (Maxim)', part='MAX17048', - datasheet='https://www.analog.com/media/en/technical-documentation/data-sheets/MAX17048-MAX17049.pdf' + mfr="Analog Devices (Maxim)", + part="MAX17048", + datasheet="https://www.analog.com/media/en/technical-documentation/data-sheets/MAX17048-MAX17049.pdf", ) - self.assign(self.lcsc_part, 'C2682616') + self.assign(self.lcsc_part, "C2682616") self.assign(self.actual_basic_part, False) From 27869e3ff0ab0dd15e085d018da3940566c7a8b6 Mon Sep 17 00:00:00 2001 From: Suke0811 <49264928+Suke0811@users.noreply.github.com> Date: Fri, 20 Mar 2026 20:33:39 +0100 Subject: [PATCH 3/4] Refactor: update MAX17048 fuel gauge power naming and I/O handling --- edg/parts/FuelGauge_Max17048.py | 38 ++++++++++----------------------- 1 file changed, 11 insertions(+), 27 deletions(-) diff --git a/edg/parts/FuelGauge_Max17048.py b/edg/parts/FuelGauge_Max17048.py index 33e6f9631..9efd08765 100644 --- a/edg/parts/FuelGauge_Max17048.py +++ b/edg/parts/FuelGauge_Max17048.py @@ -4,33 +4,24 @@ class Max17048_Device(InternalSubcircuit, FootprintBlock, JlcPart): - """MAX17048 1-Cell Li-Ion Fuel Gauge""" - def __init__(self) -> None: super().__init__() - self.vdd = self.Port( + self.pwr = self.Port( VoltageSink( voltage_limits=Range(2.5, 4.5), - current_draw=(0, 100) * uAmp, # ~23 uA typ, margin included + current_draw=(0.5, 40) * uAmp, # ~23 uA typ ) ) self.gnd = self.Port(Ground()) # I2C target interface - # I/O tolerant to 5.5 V independent of VDD (per datasheet) + # I/O tolerant to 5.5 V independent of pwr (per datasheet) dio_model = DigitalBidir.from_supply( - self.gnd, self.vdd, voltage_limit_abs=(-0.5 * Volt, 5.5 * Volt), input_threshold_factor=(0.3, 0.7) + self.gnd, self.pwr, voltage_limit_abs=(-0.3, 5.5) * Volt, input_threshold_abs=(0.5, 1.4)*Volt ) - self.i2c = self.Port(I2cTarget(dio_model, addresses=ArrayIntExpr())) + self.i2c = self.Port(I2cTarget(dio_model, addresses=[0x36])) - self.alrt = self.Port( - DigitalSingleSource( - voltage_out=Range(0, 5.5), - output_thresholds=Range(0, 5.5), - pullup_capable=True, - ), - optional=True, - ) + self.alrt = self.Port(DigitalSource.low_from_supply(self.gnd), optional=True,) self.qstrt = self.Port(Passive()) @@ -42,7 +33,7 @@ def contents(self) -> None: "Package_DFN_QFN:DFN-8-1EP_2x2mm_P0.5mm_EP0.8x1.6mm", { "1": self.gnd, - "3": self.vdd, + "3": self.pwr, "4": self.gnd, "5": self.alrt, "6": self.qstrt, @@ -59,31 +50,24 @@ def contents(self) -> None: class Max17048(DefaultExportBlock): - """MAX17048 fuel gauge with decoupling and internal ties""" + """1-Cell Li-Ion voltage based fuel gauge. Senses its pwr as the battery voltage.""" def __init__(self) -> None: super().__init__() self.ic = self.Block(Max17048_Device()) - self.vdd = self.Export(self.ic.vdd, [Power]) + self.pwr = self.Export(self.ic.pwr, [Power]) self.gnd = self.Export(self.ic.gnd, [Common]) self.i2c = self.Export(self.ic.i2c) self.alrt = self.Export(self.ic.alrt, optional=True) - self.addr = self.Parameter(IntExpr(0x36)) - @override def contents(self) -> None: super().contents() - # Required local decoupling 0.1 uF from VDD to GND - self.vdd_cap = self.Block(DecouplingCapacitor(0.1 * uFarad(tol=0.2))).connected(self.gnd, self.ic.vdd) + # Required local decoupling 0.1 uF from pwr to GND + self.pwr_cap = self.Block(DecouplingCapacitor(0.1 * uFarad(tol=0.2))).connected(self.gnd, self.ic.pwr) # Tie QSTRT to ground unless otherwise needed self.connect(self.ic.qstrt.adapt_to(Ground()), self.gnd) - # Optional pull-up resistor for the alert pin - self.alrt_pull = self.Block(PullupResistor(10 * kOhm(tol=0.05))).connected(self.vdd, self.ic.alrt) - - # Try to assign the default I2C 7-bit address if the model supports it - self.assign(self.ic.i2c.addresses, [self.addr]) From 5e7f2551fa4d38b686297223699a41790ee699fe Mon Sep 17 00:00:00 2001 From: Suke0811 <49264928+Suke0811@users.noreply.github.com> Date: Fri, 20 Mar 2026 20:36:45 +0100 Subject: [PATCH 4/4] Refactor: reformat FuelGauge_Max17048 for consistent style and readability --- edg/parts/FuelGauge_Max17048.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/edg/parts/FuelGauge_Max17048.py b/edg/parts/FuelGauge_Max17048.py index 9efd08765..bd3b16af4 100644 --- a/edg/parts/FuelGauge_Max17048.py +++ b/edg/parts/FuelGauge_Max17048.py @@ -17,11 +17,14 @@ def __init__(self) -> None: # I2C target interface # I/O tolerant to 5.5 V independent of pwr (per datasheet) dio_model = DigitalBidir.from_supply( - self.gnd, self.pwr, voltage_limit_abs=(-0.3, 5.5) * Volt, input_threshold_abs=(0.5, 1.4)*Volt + self.gnd, self.pwr, voltage_limit_abs=(-0.3, 5.5) * Volt, input_threshold_abs=(0.5, 1.4) * Volt ) self.i2c = self.Port(I2cTarget(dio_model, addresses=[0x36])) - self.alrt = self.Port(DigitalSource.low_from_supply(self.gnd), optional=True,) + self.alrt = self.Port( + DigitalSource.low_from_supply(self.gnd), + optional=True, + ) self.qstrt = self.Port(Passive()) @@ -70,4 +73,3 @@ def contents(self) -> None: # Tie QSTRT to ground unless otherwise needed self.connect(self.ic.qstrt.adapt_to(Ground()), self.gnd) -