Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pmos #327

Closed
wants to merge 9 commits into from
Closed

Pmos #327

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 98 additions & 0 deletions electronics_lib/PowerConditioning.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from typing import Optional, cast

from electronics_abstract_parts import *
from electronics_model.PassivePort import PassiveAdapterVoltageSink


class Supercap(DiscreteComponent, FootprintBlock): # TODO actually model supercaps and parts selection
Expand Down Expand Up @@ -263,3 +264,100 @@ def connected_from(self, gnd: Optional[Port[VoltageLink]] = None, pwr_hi: Option
if pwr_lo is not None:
cast(Block, builder.get_enclosing_block()).connect(pwr_lo, self.pwr_lo)
return self


class PmosReverseProtection(PowerConditioner, Block):
"""
, here is a tradeoff between the Gate discharge time and Zener biasing.
In most cases, 100R-330R is good if there are chances for the appearance of sudden reverse voltage in the circuit.
But if there are no chances of sudden reverse voltage during the continuous working of the circuit, anything from the 1k-50k resistor value can be used.
"""
@init_in_parent
def __init__(self, clamp_voltage: RangeLike, gate_resistor: RangeLike):
super().__init__()
self.gnd = self.Port(Ground.empty(), [Common])
self.pwr_in = self.Port(VoltageSink.empty()) # high-priority higher-voltage source
self.pwr_out = self.Port(VoltageSource.empty())

self.clamp_voltage = self.ArgParameter(clamp_voltage)
self.gate_resistor = self.ArgParameter(gate_resistor)

def contents(self):
super().contents()

output_current_draw = self.pwr_out.link().current_drawn
# Pfet
self.fet = self.Block(Fet.PFet(
drain_voltage=(0, self.pwr_out.link().voltage.upper()),
drain_current=output_current_draw,
# gate voltage accounts for a possible power on transient
gate_voltage=(self.clamp_voltage.upper(), (self.clamp_voltage.upper())),
))

self.res = self.Block(Resistor(self.gate_resistor))
self.diode = self.Block(ZenerDiode(self.clamp_voltage))
# PFet gate to res to gnd
self.connect(self.fet.gate, self.res.a)
self.connect(self.gnd, self.res.b.adapt_to(Ground()))
# pwr going through the PFet
self.connect(self.pwr_in, self.fet.source.adapt_to(VoltageSink()))
self.connect(self.pwr_out, self.fet.drain.adapt_to(VoltageSource()))
# Connectign the diode from the gate to the pwr out side
self.connect(self.fet.drain, self.diode.cathode)
self.connect(self.fet.gate, self.diode.anode)




class PmosChargerReverseProtection(PowerConditioner, KiCadSchematicBlock, Block):
@init_in_parent
def __init__(self, r1_val: RangeLike = 100*kOhm(tol=0.01), r2_val: RangeLike = 100*kOhm(tol=0.01), rds_on: RangeLike =(0, 0.1)*Ohm):
super().__init__()

self.gnd = self.Port(Ground.empty(), [Common])
self.pwr_out = self.Port(VoltageSource.empty(),) # Load
self.vbatt = self.Port(VoltageSink.empty(),) # Battery
self.chg = self.Port(VoltageSink.empty(),) # Charger

self.r1_val = self.ArgParameter(r1_val)
self.r2_val = self.ArgParameter(r2_val)
self.rds_on = self.ArgParameter(rds_on)

def contents(self):
super().contents()
max_vcharge_voltage = self.chg.link().voltage.upper()
max_vcharge_current = self.chg.link().current_drawn.upper()
max_vbatt_voltage = self.vbatt.link().voltage.upper()
max_vbatt_current = self.vbatt.link().current_limits.upper() # TODO: check if we should use current_limit or current_draw
# Create the PMOS transistors and resistors based on the provided schematic
self.mp1 = self.Block(Fet.PFet(
drain_voltage=(0, max_vcharge_voltage), drain_current=(0, max_vcharge_current),
gate_voltage=(- max_vbatt_voltage, max_vbatt_voltage),
rds_on=self.rds_on,
power=(0, max_vcharge_voltage * max_vcharge_current)
))
self.mp2 = self.Block(Fet.PFet(
drain_voltage=(0, max_vbatt_voltage), drain_current=(0, max_vbatt_current),
gate_voltage=(0, max_vcharge_voltage),
rds_on=self.rds_on,
power=(0, max_vbatt_voltage * max_vbatt_current)
))
self.r1 = self.Block(Resistor(resistance=self.r1_val))
self.r2 = self.Block(Resistor(resistance=self.r2_val))

chg_adapter = self.Block(PassiveAdapterVoltageSink())
setattr(self, '(adapter)chg', chg_adapter) # hack so the netlister recognizes this as an adapter
self.connect(self.mp1.source, chg_adapter.src)
self.connect(self.chg, chg_adapter.dst)

self.import_kicad(
self.file_path("resources", f"{self.__class__.__name__}.kicad_sch"),
conversions={
'vbatt': VoltageSink(
current_draw=max_vbatt_current
),
'pwr_out': VoltageSource(
voltage_out=max_vcharge_voltage),
'gnd': Ground(),
})

2 changes: 1 addition & 1 deletion electronics_lib/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@
from .BoostConverter_TexasInstruments import Tps61040
from .BuckConverter_Custom import CustomSyncBuckConverter
from .BuckBoostConverter_Custom import CustomSyncBuckBoostConverter
from .PowerConditioning import BufferedSupply, Supercap, SingleDiodePowerMerge, DiodePowerMerge, PriorityPowerOr
from .PowerConditioning import BufferedSupply, Supercap, SingleDiodePowerMerge, DiodePowerMerge, PriorityPowerOr, PmosReverseProtection, PmosChargerReverseProtection
from .LedDriver_Al8861 import Al8861
from .ResetGenerator_Apx803s import Apx803s
from .BootstrapVoltageAdder import BootstrapVoltageAdder
Expand Down
Loading
Loading