MustafaMulla29/rp2040-bldc-motor-controller-new
A USB‑C PD–powered RP2040 BLDC motor controller PCB with 3.3 V logic, MCT8329A sensorless commutation, three MOSFET half-bridges, protected power switching, USB data, controls, and motor connectors.
- Version
- 0.3.82
- License
- unset
- Stars
- 0
firmware/select_pd_voltage.py
"""Guarded runtime selection. No NVM writes and never enables motor operation.
Hardware adapter is power_manager.py. SW4 must be OFF and the motor bus below
1 V before renegotiation. This prevents changing voltage on an energized motor
or on the charged 470 uF motor bus. A new ARM action is required afterwards.
"""
from pd_profile import configure_runtime, verify_runtime, profiles
from power_policy import DEFAULT_MV, valid_motor_contract
class VoltageSelector:
def __init__(self, bus, disarm, sample, clock, address=0x28, service=lambda: None):
self.bus, self.disarm, self.sample, self.clock = bus, disarm, sample, clock
self.address, self.service = address, service
self.selected_mv = DEFAULT_MV
self.ready = False
def select(self, millivolts, timeout_ms=5000):
# Disarm even for an invalid command or failed prerequisite.
self.disarm()
self.ready = False
profiles(millivolts) # Reject unsupported settings before any I2C write.
s = self.sample()
if not 0 <= s['vmotor_mv'] < 1000:
raise OSError("Set SW4 OFF and wait for VMOTOR below 1 V before selection")
configure_runtime(self.bus, self.address, millivolts)
start = self.clock.ticks_ms()
good_since = None
while self.clock.ticks_diff(self.clock.ticks_ms(), start) < timeout_ms:
self.disarm()
self.service()
verify_runtime(self.bus, self.address, millivolts)
s = self.sample()
if not 0 <= s['vmotor_mv'] < 1000:
raise OSError("Keep SW4 OFF until voltage selection completes")
rdo = int.from_bytes(self.bus.readfrom_mem(self.address, 0x91, 4), 'little')
pe = self.bus.readfrom_mem(self.address, 0x29, 1)[0]
good = valid_motor_contract(s['vbus_mv'], rdo, pe, s['pd_ok2_low'], millivolts)
now = self.clock.ticks_ms()
if good:
if good_since is None: good_since = now
if self.clock.ticks_diff(now, good_since) >= 250:
self.selected_mv = millivolts
self.ready = True
return millivolts
else:
good_since = None
self.clock.sleep_ms(25)
raise OSError("Selected PD contract unavailable or unstable; motor remains OFF")