project
Modular BMS
Public Made by Adomby adom
Modular Battery Management System — a composable BMS built from Adom molecules. TI BQ76952 monitor/protector with MSP430 host firmware, supporting 18650 cylindrical and EVE LF105 prismatic cell carriers.
← Commit history
Publish 1.0.0
11 files changed
+2049
Modular_BMS.glbadded⋯ 1 unchanged line ⋯
PlatformIO/MSP430_BQ76952/platformio.iniadded+14@@ -0,0 +1,14 @@+; PlatformIO Project Configuration File+;+; Build options: build flags, source filter+; Upload options: custom upload port, speed and extra flags+; Library options: dependencies, extra library storages+; Advanced options: extra scripting+;+; Please visit documentation for the other options and examples+; https://docs.platformio.org/page/projectconf.html++[env:lpmsp430f5529]+platform = timsp430+board = lpmsp430f5529+framework = arduino
PlatformIO/MSP430_BQ76952/src/BQ769x2Header.hadded+409@@ -0,0 +1,409 @@+//BQ769x2 General Program Header File++//Data Memory registers Name in TRM+#define Cell1Gain 0x9180 //Calibration:Voltage:Cell 1 Gain +#define Cell2Gain 0x9182 //Calibration:Voltage:Cell 2 Gain +#define Cell3Gain 0x9184 //Calibration:Voltage:Cell 3 Gain +#define Cell4Gain 0x9186 //Calibration:Voltage:Cell 4 Gain +#define Cell5Gain 0x9188 //Calibration:Voltage:Cell 5 Gain +#define Cell6Gain 0x918A //Calibration:Voltage:Cell 6 Gain +#define Cell7Gain 0x918C //Calibration:Voltage:Cell 7 Gain +#define Cell8Gain 0x918E //Calibration:Voltage:Cell 8 Gain +#define Cell9Gain 0x9190 //Calibration:Voltage:Cell 9 Gain +#define Cell10Gain 0x9192 //Calibration:Voltage:Cell 10 Gain +#define Cell11Gain 0x9194 //Calibration:Voltage:Cell 11 Gain +#define Cell12Gain 0x9196 //Calibration:Voltage:Cell 12 Gain +#define Cell13Gain 0x9198 //Calibration:Voltage:Cell 13 Gain +#define Cell14Gain 0x919A //Calibration:Voltage:Cell 14 Gain +#define Cell15Gain 0x919C //Calibration:Voltage:Cell 15 Gain +#define Cell16Gain 0x919E //Calibration:Voltage:Cell 16 Gain +#define PackGain 0x91A0 //Calibration:Voltage:Pack Gain +#define TOSGain 0x91A2 //Calibration:Voltage:TOS Gain +#define LDGain 0x91A4 //Calibration:Voltage:LD Gain +#define ADCGain 0x91A6 //Calibration:Voltage:ADC Gain +#define CCGain 0x91A8 //Calibration:Current:CC Gain +#define CapacityGain 0x91AC //Calibration:Current:Capacity Gain +#define VcellOffset 0x91B0 //Calibration:Vcell Offset:Vcell Offset +#define VdivOffset 0x91B2 //Calibration:V Divider Offset:Vdiv Offset +#define CoulombCounterOffsetSamples 0x91C6 //Calibration:Current Offset:Coulomb Counter Offset Samples +#define BoardOffset 0x91C8 //Calibration:Current Offset:Board Offset +#define InternalTempOffset 0x91CA //Calibration:Temperature:Internal Temp Offset +#define CFETOFFTempOffset 0x91CB //Calibration:Temperature:CFETOFF Temp Offset +#define DFETOFFTempOffset 0x91CC //Calibration:Temperature:DFETOFF Temp Offset +#define ALERTTempOffset 0x91CD //Calibration:Temperature:ALERT Temp Offset +#define TS1TempOffset 0x91CE //Calibration:Temperature:TS1 Temp Offset +#define TS2TempOffset 0x91CF //Calibration:Temperature:TS2 Temp Offset +#define TS3TempOffset 0x91D0 //Calibration:Temperature:TS3 Temp Offset +#define HDQTempOffset 0x91D1 //Calibration:Temperature:HDQ Temp Offset +#define DCHGTempOffset 0x91D2 //Calibration:Temperature:DCHG Temp Offset +#define DDSGTempOffset 0x91D3 //Calibration:Temperature:DDSG Temp Offset +#define IntGain 0x91E2 //Calibration:Internal Temp Model:Int Gain +#define Intbaseoffset 0x91E4 //Calibration:Internal Temp Model:Int base offset +#define IntMaximumAD 0x91E6 //Calibration:Internal Temp Model:Int Maximum AD +#define IntMaximumTemp 0x91E8 //Calibration:Internal Temp Model:Int Maximum Temp +#define T18kCoeffa1 0x91EA //Calibration:18K Temperature Model:Coeff a1 +#define T18kCoeffa2 0x91EC //Calibration:18K Temperature Model:Coeff a2 +#define T18kCoeffa3 0x91EE //Calibration:18K Temperature Model:Coeff a3 +#define T18kCoeffa4 0x91F0 //Calibration:18K Temperature Model:Coeff a4 +#define T18kCoeffa5 0x91F2 //Calibration:18K Temperature Model:Coeff a5 +#define T18kCoeffb1 0x91F4 //Calibration:18K Temperature Model:Coeff b1 +#define T18kCoeffb2 0x91F6 //Calibration:18K Temperature Model:Coeff b2 +#define T18kCoeffb3 0x91F8 //Calibration:18K Temperature Model:Coeff b3 +#define T18kCoeffb4 0x91FA //Calibration:18K Temperature Model:Coeff b4 +#define T18kAdc0 0x91FE //Calibration:18K Temperature Model:Adc0 +#define T180kCoeffa1 0x9200 //Calibration:180K Temperature Model:Coeff a1 +#define T180kCoeffa2 0x9202 //Calibration:180K Temperature Model:Coeff a2 +#define T180kCoeffa3 0x9204 //Calibration:180K Temperature Model:Coeff a3 +#define T180kCoeffa4 0x9206 //Calibration:180K Temperature Model:Coeff a4 +#define T180kCoeffa5 0x9208 //Calibration:180K Temperature Model:Coeff a5 +#define T180kCoeffb1 0x920A //Calibration:180K Temperature Model:Coeff b1 +#define T180kCoeffb2 0x920C //Calibration:180K Temperature Model:Coeff b2 +#define T180kCoeffb3 0x920E //Calibration:180K Temperature Model:Coeff b3 +#define T180kCoeffb4 0x9210 //Calibration:180K Temperature Model:Coeff b4 +#define T180kAdc0 0x9214 //Calibration:180K Temperature Model:Adc0 +#define CustomCoeffa1 0x9216 //Calibration:Custom Temperature Model:Coeff a1 +#define CustomCoeffa2 0x9218 //Calibration:Custom Temperature Model:Coeff a2 +#define CustomCoeffa3 0x921A //Calibration:Custom Temperature Model:Coeff a3 +#define CustomCoeffa4 0x921C //Calibration:Custom Temperature Model:Coeff a4 +#define CustomCoeffa5 0x921E //Calibration:Custom Temperature Model:Coeff a5 +#define CustomCoeffb1 0x9220 //Calibration:Custom Temperature Model:Coeff b1 +#define CustomCoeffb2 0x9222 //Calibration:Custom Temperature Model:Coeff b2 +#define CustomCoeffb3 0x9224 //Calibration:Custom Temperature Model:Coeff b3 +#define CustomCoeffb4 0x9226 //Calibration:Custom Temperature Model:Coeff b4 +#define CustomRc0 0x9228 //Calibration:Custom Temperature Model:Rc0 +#define CustomAdc0 0x922A //Calibration:Custom Temperature Model:Adc0 +#define CoulombCounterDeadband 0x922D //Calibration:Current Deadband:Coulomb Counter Deadband +#define CUVThresholdOverride 0x91D4 //Calibration:CUV:CUV Threshold Override +#define COVThresholdOverride 0x91D6 //Calibration:COV:COV Threshold Override +#define MinBlowFuseVoltage 0x9231 //Settings:Fuse:Min Blow Fuse Voltage +#define FuseBlowTimeout 0x9233 //Settings:Fuse:Fuse Blow Timeout +#define PowerConfig 0x9234 //Settings:Configuration:Power Config +#define REG12Config 0x9236 //Settings:Configuration:REG12 Config +#define REG0Config 0x9237 //Settings:Configuration:REG0 Config +#define HWDRegulatorOptions 0x9238 //Settings:Configuration:HWD Regulator Options +#define CommType 0x9239 //Settings:Configuration:Comm Type +#define I2CAddress 0x923A //Settings:Configuration:I2C Address +#define SPIConfiguration 0x923C //Settings:Configuration:SPI Configuration +#define CommIdleTime 0x923D //Settings:Configuration:Comm Idle Time +#define CFETOFFPinConfig 0x92FA //Settings:Configuration:CFETOFF Pin Config +#define DFETOFFPinConfig 0x92FB //Settings:Configuration:DFETOFF Pin Config +#define ALERTPinConfig 0x92FC //Settings:Configuration:ALERT Pin Config +#define TS1Config 0x92FD //Settings:Configuration:TS1 Config +#define TS2Config 0x92FE //Settings:Configuration:TS2 Config +#define TS3Config 0x92FF //Settings:Configuration:TS3 Config +#define HDQPinConfig 0x9300 //Settings:Configuration:HDQ Pin Config +#define DCHGPinConfig 0x9301 //Settings:Configuration:DCHG Pin Config +#define DDSGPinConfig 0x9302 //Settings:Configuration:DDSG Pin Config +#define DAConfiguration 0x9303 //Settings:Configuration:DA Configuration +#define VCellMode 0x9304 //Settings:Configuration:Vcell Mode +#define CC3Samples 0x9307 //Settings:Configuration:CC3 Samples +#define ProtectionConfiguration 0x925F //Settings:Protection:Protection Configuration +#define EnabledProtectionsA 0x9261 //Settings:Protection:Enabled Protections A +#define EnabledProtectionsB 0x9262 //Settings:Protection:Enabled Protections B +#define EnabledProtectionsC 0x9263 //Settings:Protection:Enabled Protections C +#define CHGFETProtectionsA 0x9265 //Settings:Protection:CHG FET Protections A +#define CHGFETProtectionsB 0x9266 //Settings:Protection:CHG FET Protections B +#define CHGFETProtectionsC 0x9267 //Settings:Protection:CHG FET Protections C +#define DSGFETProtectionsA 0x9269 //Settings:Protection:DSG FET Protections A +#define DSGFETProtectionsB 0x926A //Settings:Protection:DSG FET Protections B +#define DSGFETProtectionsC 0x926B //Settings:Protection:DSG FET Protections C +#define BodyDiodeThreshold 0x9273 //Settings:Protection:Body Diode Threshold +#define DefaultAlarmMask 0x926D //Settings:Alarm:Default Alarm Mask +#define SFAlertMaskA 0x926F //Settings:Alarm:SF Alert Mask A +#define SFAlertMaskB 0x9270 //Settings:Alarm:SF Alert Mask B +#define SFAlertMaskC 0x9271 //Settings:Alarm:SF Alert Mask C +#define PFAlertMaskA 0x92C4 //Settings:Alarm:PF Alert Mask A +#define PFAlertMaskB 0x92C5 //Settings:Alarm:PF Alert Mask B +#define PFAlertMaskC 0x92C6 //Settings:Alarm:PF Alert Mask C +#define PFAlertMaskD 0x92C7 //Settings:Alarm:PF Alert Mask D +#define EnabledPFA 0x92C0 //Settings:Permanent Failure:Enabled PF A +#define EnabledPFB 0x92C1 //Settings:Permanent Failure:Enabled PF B +#define EnabledPFC 0x92C2 //Settings:Permanent Failure:Enabled PF C +#define EnabledPFD 0x92C3 //Settings:Permanent Failure:Enabled PF D +#define FETOptions 0x9308 //Settings:FET:FET Options +#define ChgPumpControl 0x9309 //Settings:FET:Chg Pump Control +#define PrechargeStartVoltage 0x930A //Settings:FET:Precharge Start Voltage +#define PrechargeStopVoltage 0x930C //Settings:FET:Precharge Stop Voltage +#define PredischargeTimeout 0x930E //Settings:FET:Predischarge Timeout +#define PredischargeStopDelta 0x930F //Settings:FET:Predischarge Stop Delta +#define DsgCurrentThreshold 0x9310 //Settings:Current Thresholds:Dsg Current Threshold +#define ChgCurrentThreshold 0x9312 //Settings:Current Thresholds:Chg Current Threshold +#define CheckTime 0x9314 //Settings:Cell Open-Wire:Check Time +#define Cell1Interconnect 0x9315 //Settings:Interconnect Resistances:Cell 1 Interconnect +#define Cell2Interconnect 0x9317 //Settings:Interconnect Resistances:Cell 2 Interconnect +#define Cell3Interconnect 0x9319 //Settings:Interconnect Resistances:Cell 3 Interconnect +#define Cell4Interconnect 0x931B //Settings:Interconnect Resistances:Cell 4 Interconnect +#define Cell5Interconnect 0x931D //Settings:Interconnect Resistances:Cell 5 Interconnect +#define Cell6Interconnect 0x931F //Settings:Interconnect Resistances:Cell 6 Interconnect +#define Cell7Interconnect 0x9321 //Settings:Interconnect Resistances:Cell 7 Interconnect +#define Cell8Interconnect 0x9323 //Settings:Interconnect Resistances:Cell 8 Interconnect +#define Cell9Interconnect 0x9325 //Settings:Interconnect Resistances:Cell 9 Interconnect +#define Cell10Interconnect 0x9327 //Settings:Interconnect Resistances:Cell 10 Interconnect +#define Cell11Interconnect 0x9329 //Settings:Interconnect Resistances:Cell 11 Interconnect +#define Cell12Interconnect 0x932B //Settings:Interconnect Resistances:Cell 12 Interconnect +#define Cell13Interconnect 0x932D //Settings:Interconnect Resistances:Cell 13 Interconnect +#define Cell14Interconnect 0x932F //Settings:Interconnect Resistances:Cell 14 Interconnect +#define Cell15Interconnect 0x9331 //Settings:Interconnect Resistances:Cell 15 Interconnect +#define Cell16Interconnect 0x9333 //Settings:Interconnect Resistances:Cell 16 Interconnect +#define MfgStatusInit 0x9343 //Settings:Manufacturing:Mfg Status Init +#define BalancingConfiguration 0x9335 //Settings:Cell Balancing Config:Balancing Configuration +#define MinCellTemp 0x9336 //Settings:Cell Balancing Config:Min Cell Temp +#define MaxCellTemp 0x9337 //Settings:Cell Balancing Config:Max Cell Temp +#define MaxInternalTemp 0x9338 //Settings:Cell Balancing Config:Max Internal Temp +#define CellBalanceInterval 0x9339 //Settings:Cell Balancing Config:Cell Balance Interval +#define CellBalanceMaxCells 0x933A //Settings:Cell Balancing Config:Cell Balance Max Cells +#define CellBalanceMinCellVCharge 0x933B //Settings:Cell Balancing Config:Cell Balance Min Cell V (Charge) +#define CellBalanceMinDeltaCharge 0x933D //Settings:Cell Balancing Config:Cell Balance Min Delta (Charge) +#define CellBalanceStopDeltaCharge 0x933E //Settings:Cell Balancing Config:Cell Balance Stop Delta (Charge) +#define CellBalanceMinCellVRelax 0x933F //Settings:Cell Balancing Config:Cell Balance Min Cell V (Relax) +#define CellBalanceMinDeltaRelax 0x9341 //Settings:Cell Balancing Config:Cell Balance Min Delta (Relax) +#define CellBalanceStopDeltaRelax 0x9342 //Settings:Cell Balancing Config:Cell Balance Stop Delta (Relax) +#define ShutdownCellVoltage 0x923F //Power:Shutdown:Shutdown Cell Voltage +#define ShutdownStackVoltage 0x9241 //Power:Shutdown:Shutdown Stack Voltage +#define LowVShutdownDelay 0x9243 //Power:Shutdown:Low V Shutdown Delay +#define ShutdownTemperature 0x9244 //Power:Shutdown:Shutdown Temperature +#define ShutdownTemperatureDelay 0x9245 //Power:Shutdown:Shutdown Temperature Delay +#define FETOffDelay 0x9252 //Power:Shutdown:FET Off Delay +#define ShutdownCommandDelay 0x9253 //Power:Shutdown:Shutdown Command Delay +#define AutoShutdownTime 0x9254 //Power:Shutdown:Auto Shutdown Time +#define RAMFailShutdownTime 0x9255 //Power:Shutdown:RAM Fail Shutdown Time +#define SleepCurrent 0x9248 //Power:Sleep:Sleep Current +#define VoltageTime 0x924A //Power:Sleep:Voltage Time +#define WakeComparatorCurrent 0x924B //Power:Sleep:Wake Comparator Current +#define SleepHysteresisTime 0x924D //Power:Sleep:Sleep Hysteresis Time +#define SleepChargerVoltageThreshold 0x924E //Power:Sleep:Sleep Charger Voltage Threshold +#define SleepChargerPACKTOSDelta 0x9250 //Power:Sleep:Sleep Charger PACK-TOS Delta +#define ConfigRAMSignature 0x91E0 //System Data:Integrity:Config RAM Signature +#define CUVThreshold 0x9275 //Protections:CUV:Threshold +#define CUVDelay 0x9276 //Protections:CUV:Delay +#define CUVRecoveryHysteresis 0x927B //Protections:CUV:Recovery Hysteresis +#define COVThreshold 0x9278 //Protections:COV:Threshold +#define COVDelay 0x9279 //Protections:COV:Delay +#define COVRecoveryHysteresis 0x927C //Protections:COV:Recovery Hysteresis +#define COVLLatchLimit 0x927D //Protections:COVL:Latch Limit +#define COVLCounterDecDelay 0x927E //Protections:COVL:Counter Dec Delay +#define COVLRecoveryTime 0x927F //Protections:COVL:Recovery Time +#define OCCThreshold 0x9280 //Protections:OCC:Threshold +#define OCCDelay 0x9281 //Protections:OCC:Delay +#define OCCRecoveryThreshold 0x9288 //Protections:OCC:Recovery Threshold +#define OCCPACKTOSDelta 0x92B0 //Protections:OCC:PACK-TOS Delta +#define OCD1Threshold 0x9282 //Protections:OCD1:Threshold +#define OCD1Delay 0x9283 //Protections:OCD1:Delay +#define OCD2Threshold 0x9284 //Protections:OCD2:Threshold +#define OCD2Delay 0x9285 //Protections:OCD2:Delay +#define SCDThreshold 0x9286 //Protections:SCD:Threshold +#define SCDDelay 0x9287 //Protections:SCD:Delay +#define SCDRecoveryTime 0x9294 //Protections:SCD:Recovery Time +#define OCD3Threshold 0x928A //Protections:OCD3:Threshold +#define OCD3Delay 0x928C //Protections:OCD3:Delay +#define OCDRecoveryThreshold 0x928D //Protections:OCD:Recovery Threshold +#define OCDLLatchLimit 0x928F //Protections:OCDL:Latch Limit +#define OCDLCounterDecDelay 0x9290 //Protections:OCDL:Counter Dec Delay +#define OCDLRecoveryTime 0x9291 //Protections:OCDL:Recovery Time +#define OCDLRecoveryThreshold 0x9292 //Protections:OCDL:Recovery Threshold +#define SCDLLatchLimit 0x9295 //Protections:SCDL:Latch Limit +#define SCDLCounterDecDelay 0x9296 //Protections:SCDL:Counter Dec Delay +#define SCDLRecoveryTime 0x9297 //Protections:SCDL:Recovery Time +#define SCDLRecoveryThreshold 0x9298 //Protections:SCDL:Recovery Threshold +#define OTCThreshold 0x929A //Protections:OTC:Threshold +#define OTCDelay 0x920B //Protections:OTC:Delay +#define OTCRecovery 0x929C //Protections:OTC:Recovery +#define OTDThreshold 0x929D //Protections:OTD:Threshold +#define OTDDelay 0x929E //Protections:OTD:Delay +#define OTDRecovery 0x929F //Protections:OTD:Recovery +#define OTFThreshold 0x92A0 //Protections:OTF:Threshold +#define OTFDelay 0x92A1 //Protections:OTF:Delay +#define OTFRecovery 0x92A2 //Protections:OTF:Recovery +#define OTINTThreshold 0x92A3 //Protections:OTINT:Threshold +#define OTINTDelay 0x92A4 //Protections:OTINT:Delay +#define OTINTRecovery 0x92A5 //Protections:OTINT:Recovery +#define UTCThreshold 0x92A6 //Protections:UTC:Threshold +#define UTCDelay 0x92A7 //Protections:UTC:Delay +#define UTCRecovery 0x92A8 //Protections:UTC:Recovery +#define UTDThreshold 0x92A9 //Protections:UTD:Threshold +#define UTDDelay 0x92AA //Protections:UTD:Delay +#define UTDRecovery 0x92AB //Protections:UTD:Recovery +#define UTINTThreshold 0x92AC //Protections:UTINT:Threshold +#define UTINTDelay 0x92AD //Protections:UTINT:Delay +#define UTINTRecovery 0x92AE //Protections:UTINT:Recovery +#define ProtectionsRecoveryTime 0x92AF //Protections:Recovery:Time +#define HWDDelay 0x92B2 //Protections:HWD:Delay +#define LoadDetectActiveTime 0x92B4 //Protections:Load Detect:Active Time +#define LoadDetectRetryDelay 0x92B5 //Protections:Load Detect:Retry Delay +#define LoadDetectTimeout 0x92B6 //Protections:Load Detect:Timeout +#define PTOChargeThreshold 0x92BA //Protections:PTO:Charge Threshold +#define PTODelay 0x92BC //Protections:PTO:Delay +#define PTOReset 0x92BE //Protections:PTO:Reset +#define CUDEPThreshold 0x92C8 //Permanent Fail:CUDEP:Threshold +#define CUDEPDelay 0x92CA //Permanent Fail:CUDEP:Delay +#define SUVThreshold 0x92CB //Permanent Fail:SUV:Threshold +#define SUVDelay 0x92CD //Permanent Fail:SUV:Delay +#define SOVThreshold 0x92CE //Permanent Fail:SOV:Threshold +#define SOVDelay 0x92D0 //Permanent Fail:SOV:Delay +#define TOSSThreshold 0x92D1 //Permanent Fail:TOS:Threshold +#define TOSSDelay 0x92D3 //Permanent Fail:TOS:Delay +#define SOCCThreshold 0x92D4 //Permanent Fail:SOCC:Threshold +#define SOCCDelay 0x92D6 //Permanent Fail:SOCC:Delay +#define SOCDThreshold 0x92D7 //Permanent Fail:SOCD:Threshold +#define SOCDDelay 0x92D9 //Permanent Fail:SOCD:Delay +#define SOTThreshold 0x92DA //Permanent Fail:SOT:Threshold +#define SOTDelay 0x92DB //Permanent Fail:SOT:Delay +#define SOTFThreshold 0x92DC //Permanent Fail:SOTF:Threshold +#define SOTFDelay 0x92DD //Permanent Fail:SOTF:Delay +#define VIMRCheckVoltage 0x92DE //Permanent Fail:VIMR:Check Voltage +#define VIMRMaxRelaxCurrent 0x92E0 //Permanent Fail:VIMR:Max Relax Current +#define VIMRThreshold 0x92E2 //Permanent Fail:VIMR:Threshold +#define VIMRDelay 0x92E4 //Permanent Fail:VIMR:Delay +#define VIMRRelaxMinDuration 0x92E5 //Permanent Fail:VIMR:Relax Min Duration +#define VIMACheckVoltage 0x92E7 //Permanent Fail:VIMA:Check Voltage +#define VIMAMinActiveCurrent 0x92E9 //Permanent Fail:VIMA:Min Active Current +#define VIMAThreshold 0x92EB //Permanent Fail:VIMA:Threshold +#define VIMADelay 0x92ED //Permanent Fail:VIMA:Delay +#define CFETFOFFThreshold 0x92EE //Permanent Fail:CFETF:OFF Threshold +#define CFETFOFFDelay 0x92F0 //Permanent Fail:CFETF:OFF Delay +#define DFETFOFFThreshold 0x92F1 //Permanent Fail:DFETF:OFF Threshold +#define DFETFOFFDelay 0x92F3 //Permanent Fail:DFETF:OFF Delay +#define VSSFFailThreshold 0x92F4 //Permanent Fail:VSSF:Fail Threshold +#define VSSFDelay 0x92F6 //Permanent Fail:VSSF:Delay +#define PF2LVLDelay 0x92F7 //Permanent Fail:2LVL:Delay +#define LFOFDelay 0x92F8 //Permanent Fail:LFOF:Delay +#define HWMXDelay 0x92F9 //Permanent Fail:HWMX:Delay +#define SecuritySettings 0x9256 //Security:Settings:Security Settings +#define UnsealKeyStep1 0x9257 //Security:Keys:Unseal Key Step 1 +#define UnsealKeyStep2 0x9259 //Security:Keys:Unseal Key Step 2 +#define FullAccessKeyStep1 0x925B //Security:Keys:Full Access Key Step 1 +#define FullAccessKeyStep2 0x925D //Security:Keys:Full Access Key Step 2 ++//Direct Commands +#define ControlStatus 0x00+#define SafetyAlertA 0x02+#define SafetyStatusA 0x03+#define SafetyAlertB 0x04+#define SafetyStatusB 0x05+#define SafetyAlertC 0x06+#define SafetyStatusC 0x07+#define PFAlertA 0x0A+#define PFStatusA 0x0B+#define PFAlertB 0x0C+#define PFStatusB 0x0D+#define PFAlertC 0x0E+#define PFStatusC 0x0F+#define PFAlertD 0x10+#define PFStatusD 0x11+#define BatteryStatus 0x12+#define Cell1Voltage 0x14+#define Cell2Voltage 0x16+#define Cell3Voltage 0x18+#define Cell4Voltage 0x1A+#define Cell5Voltage 0x1C+#define Cell6Voltage 0x1E+#define Cell7Voltage 0x20+#define Cell8Voltage 0x22+#define Cell9Voltage 0x24+#define Cell10Voltage 0x26+#define Cell11Voltage 0x28+#define Cell12Voltage 0x2A+#define Cell13Voltage 0x2C+#define Cell14Voltage 0x2E+#define Cell15Voltage 0x30+#define Cell16Voltage 0x32+#define StackVoltage 0x34+#define PACKPinVoltage 0x36+#define LDPinVoltage 0x38+#define CC2Current 0x3A+#define AlarmStatus 0x62+#define AlarmRawStatus 0x64+#define AlarmEnable 0x66+#define IntTemperature 0x68+#define CFETOFFTemperature 0x6A+#define DFETOFFTemperature 0x6C+#define ALERTTemperature 0x6E+#define TS1Temperature 0x70+#define TS2Temperature 0x72+#define TS3Temperature 0x74+#define HDQTemperature 0x76+#define DCHGTemperature 0x78+#define DDSGTemperature 0x7A+#define FETStatus 0x7F++//Subcommands +#define DEVICE_NUMBER 0x0001+#define FW_VERSION 0x0002+#define HW_VERSION 0x0003+#define IROM_SIG 0x0004+#define STATIC_CFG_SIG 0x0005+#define PREV_MACWRITE 0x0007+#define DROM_SIG 0x0009+#define SECURITY_KEYS 0x0035+#define SAVED_PF_STATUS 0x0053+#define MANUFACTURINGSTATUS 0x0057+#define MANU_DATA 0x0070+#define DASTATUS1 0x0071+#define DASTATUS2 0x0072+#define DASTATUS3 0x0073+#define DASTATUS4 0x0074+#define DASTATUS5 0x0075+#define DASTATUS6 0x0076+#define DASTATUS7 0x0077+#define CUV_SNAPSHOT 0x0080+#define COV_SNAPSHOT 0X0081+#define CB_ACTIVE_CELLS 0x0083+#define CB_SET_LVL 0x0084+#define CBSTATUS1 0x0085+#define CBSTATUS2 0x0086+#define CBSTATUS3 0x0087+#define FET_CONTROL 0x0097+#define REG12_CONTROL 0x0098+#define OTP_WR_CHECK 0x00A0+#define OTP_WRITE 0x00A1+#define READ_CAL1 0xF081+#define CAL_CUV 0xF090+#define CAL_COV 0xF091++// Command Only Subcommands +#define EXIT_DEEPSLEEP 0x000E+#define DEEPSLEEP 0x000F+#define SHUTDOWN 0x0010+#define BQ769x2_RESET 0x0012 //"RESET" in documentation+#define PDSGTEST 0x001C+#define FUSE_TOGGLE 0x001D+#define PCHGTEST 0x001E+#define CHGTEST 0x001F+#define DSGTEST 0x0020+#define FET_ENABLE 0x0022+#define PF_ENABLE 0x0024+#define PF_RESET 0x0029+#define SEAL 0x0030+#define RESET_PASSQ 0x0082+#define PTO_RECOVER 0x008A+#define SET_CFGUPDATE 0x0090+#define EXIT_CFGUPDATE 0x0092+#define DSG_PDSG_OFF 0x0093+#define CHG_PCHG_OFF 0x0094+#define ALL_FETS_OFF 0x0095+#define ALL_FETS_ON 0x0096+#define SLEEP_ENABLE 0x0099+#define SLEEP_DISABLE 0x009A+#define OCDL_RECOVER 0x009B+#define SCDL_RECOVER 0x009C+#define LOAD_DETECT_RESTART 0x009D+#define LOAD_DETECT_ON 0x009E+#define LOAD_DETECT_OFF 0x009F+#define CFETOFF_LO 0x2800+#define DFETOFF_LO 0x2801+#define ALERT_LO 0x2802+#define HDQ_LO 0x2806+#define DCHG_LO 0x2807+#define DDSG_LO 0x2808+#define CFETOFF_HI 0x2810+#define DFETOFF_HI 0x2811+#define ALERT_HI 0x2812+#define HDQ_HI 0x2816+#define DCHG_HI 0x2817+#define DDSG_HI 0x2818+#define PF_FORCE_A 0x2857+#define PF_FORCE_B 0x29A3+#define SWAP_COMM_MODE 0x29BC+#define SWAP_TO_I2C 0x29E7+#define SWAP_TO_SPI 0x7C35+#define SWAP_TO_HDQ 0x7C40
PlatformIO/MSP430_BQ76952/src/README.mdadded+336@@ -0,0 +1,336 @@+# BQ76952EVM + MSP430F5529 BMS Firmware++Firmware for the **BQ76952EVM** using an **MSP430F5529** as the I²C host. This project is based on TI’s BQ769x2 demo framework and adds higher-level helpers for:++- n-cell configuration using `VCellMode`+- periodic measurement polling and alarm handling+- CHG/DSG FET control from two GPIO inputs (P3.3 and P3.4)+- structured output in **human-readable** or **JSON** notification format in Hydrogen Style++---++## Hardware++- **MSP430F5529LP** eval board (for programming over SBW)+- **MSP430F5529** (host MCU)+- **BQ76952EVM** (battery monitor + protection + balancing)+- I²C: UCB1 mapped to **P4.4=SCL**, **P4.5=SDA**+- UART: UCA1 mapped to **P4.2=RX**, **P4.3=TX**+- FET control inputs:+ - **P3.3** → enable **Discharge** (DSG)+ - **P3.4** → enable **Charge** (CHG)+ - Both are configured as GPIO inputs with pulldown resistors++---++## Build / Run++This code is intended to be built in PIO toolchain using the MSP430F5529 eval board for SBW programming.++At startup, `main()`:+1. Stops the watchdog+2. Initializes GPIO, port mapping, UART, I²C+3. Resets the BQ76952+4. Applies RAM configuration via `BQ769x2_Init()`+5. Enables FET control and disables sleep for full-speed measurement updates+6. Enters the main polling loop++---++## Configuration++### Cell Count++This project is configured for **3 cells** using `VCellMode`:++```c+#define NUM_CELLS 3+#define NUM_CELLS_BITS 0x0007 // enable Cell1..Cell3+```++`NUM_CELLS_BITS` is written to the `VCellMode` register inside `BQ769x2_Init()`.++---++## Output Modes++A global `output_mode` controls whether telemetry is printed as:+- `OUTPUT_HUMAN`: readable console logs via `printf`+- `OUTPUT_JSON`: JSON notification packets (Hydrogen-style wrapper)++Select mode:++```c+set_output_mode(OUTPUT_HUMAN);+// or+set_output_mode(OUTPUT_JSON);+```++### JSON Wrapper++JSON output is wrapped in a common “notification” envelope via:++- `send_json_notification_data(method, id, data_str)`+- `send_json_notification_fmt(method, id, data_fmt, ...)`++All BMS-specific output functions ultimately route through these.++---++## Key High-Level BQ76952 Functions++### `BQ769x2_Init()`++Applies the core BQ76952 RAM configuration:+- enters `CONFIG_UPDATE`+- sets power / regulator / TS pin config+- sets `VCellMode` for your pack (3S by default)+- enables protections (SCD/OCD/OV/UV/etc.)+- sets alarm mask, balancing config, thresholds+- exits `CONFIG_UPDATE`++**Used in `main()` once after reset**, before enabling FETs.++---++### `BQ769x2_ReadAlarmStatus()`++Reads `AlarmStatus` (direct command) and returns a 16-bit bitmask.++In `main()` this is used as the “scheduler”:+- if FULLSCAN bit is set → new measurements are ready+- if SafetyStatus alarm bits set → fetch safety status++---++### `BQ769x2_ReadAllVoltages()`++Updates:+- `CellVoltage[0..15]` from `Cell1Voltage..Cell16Voltage`+- `Stack_Voltage` from `StackVoltage`+- `Pack_Voltage` from `PACKPinVoltage`+- `LD_Voltage` from `LDPinVoltage`++**Important note:** on the EVM, `Pack_Voltage` is the PACK pin *after* the FETs, so it may read ~0V when DSG/CHG FETs are open.+**Important note:** on the EVM, `Stack_Voltage` is what we would usually call the "Battery Pack" voltage. Basically the voltage from top cell to GND. ++---++### `BQ769x2_ReadVoltage(command)`++Generic “direct command” voltage read:+- Cell voltages are returned in **mV**+- Stack/Pack/LD voltages are treated as **0.01V units** and converted to mV++---++### `BQ769x2_ReadCurrent()`++Reads `CC2Current` (direct command) and returns the raw 16-bit value.++**Current direction:** CC2 current is signed (two’s complement).++Recommended usage in this codebase:++```c+int16_t current_mA = (int16_t)BQ769x2_ReadCurrent();+// positive = charging, negative = discharging+```++---++### `BQ769x2_ReadTemperature(command)`++Reads a temperature direct command (e.g., `TS1Temperature`) and converts to °C:++```c+Temperature_C = 0.1 * raw_K - 273.15+```++---++## Protection / Fault Monitoring++### `BQ769x2_ReadSafetyStatus()`++Reads:+- `SafetyStatusA`+- `SafetyStatusB`+- `SafetyStatusC`++And derives high-level flags:+- `UV_Fault`, `OV_Fault`, `SCD_Fault`, `OCD_Fault`+- `ProtectionsTriggered`++In `main()`, safety status is checked whenever AlarmStatus indicates safety-related bits or when a protection was previously active.++---++### `BQ769x2_ReadPFStatus()`++Reads Permanent Failure status registers A/B/C. Useful when diagnosing “fuse LED” or persistent shutdown behavior.++---++## FET Control (CHG/DSG)++### `BQ769x2_ReadFETStatus()`++Reads `FETStatus` and updates globals:+- `CHG`, `DSG`, `PCHG`, `PDSG`++Use this to confirm the actual driver states.++---++### `BQ769x2_WriteFETStatus(bool DSG, bool CHG)`++Controls CHG/DSG using the **FET_CONTROL** subcommand.++This function uses the BQ76952 convention:+- writing `DSG_OFF=1` forces DSG OFF+- writing `CHG_OFF=1` forces CHG OFF++So the function takes **enable booleans** and internally writes the “OFF” bits as needed.++Example:++```c+BQ769x2_WriteFETStatus(true, false); // DSG enabled, CHG forced off+```++> Note: this is host control. The BQ76952 may still keep FETs open if protections are active (UV/OV/OCD/SCD/PF).++---++### `update_fets_from_buttons()`++Reads the two GPIO inputs and applies FET control:+- `P3.3 high` → enable discharge (DSG)+- `P3.4 high` → enable charge (CHG)++Then:++```c+BQ769x2_WriteFETStatus(dsg_enable, chg_enable);+```++This is called periodically from `main()` (currently every 20 cycles).++---++## Output Helpers (Human + JSON)++These functions produce either console output or JSON notifications depending on `output_mode`.++### `output_bms_config(battery_type, cell_count)`++Emits a config packet at startup and periodically.++### `output_bms_voltages(pack_mV, CellVoltage[], cell_count)`++Emits pack + per-cell voltages.++### `output_fet_status(chg, dsg)`++Emits CHG/DSG states as booleans/ints.++### `output_current_value(current_mA)`++Emits signed current in mA.++---++## Main Loop Behavior (Current Program)++The `while(1)` loop does:++1. Read `AlarmStatus`+2. If FULLSCAN complete → read voltages/current/temps → clear FULLSCAN bit+3. If safety alarm bits present → read safety status → clear alarm bits+4. Every ~20 cycles:+ - output voltages+ - update FETs from button inputs+ - read and output FET states+ - read and output current+5. Every ~100 cycles:+ - re-emit config and print faults if present+6. Delay ~20 ms++---++## How to Write Your Own `main()`++A minimal, clean template:++```c+int main(void)+{+ WDTCTL = WDTPW | WDTHOLD;++ GPIO_initPins();+ map_I2C_and_UART();+ UART_Init();+ I2C_initModule();++ set_output_mode(OUTPUT_JSON);++ CommandSubcommands(BQ769x2_RESET);+ delayUS(60000);++ BQ769x2_Init();+ delayUS(10000);++ CommandSubcommands(FET_ENABLE);+ CommandSubcommands(SLEEP_DISABLE);++ while (1)+ {+ uint16_t alarms = BQ769x2_ReadAlarmStatus();++ if (alarms & 0x80) {+ BQ769x2_ReadAllVoltages();+ int16_t current_mA = (int16_t)BQ769x2_ReadCurrent();++ // clear FULLSCAN complete bit+ DirectCommands(AlarmStatus, 0x0080, W);++ output_bms_voltages(Stack_Voltage, CellVoltage, NUM_CELLS);+ output_current_value(current_mA);+ }++ update_fets_from_buttons();++ if (alarms & 0xC000) {+ BQ769x2_ReadSafetyStatus();+ // clear safety alarm bits+ DirectCommands(AlarmStatus, 0xF800, W);+ }++ delayUS(20000);+ }+}+```++Recommended approach:+- Drive logic from `AlarmStatus` FULLSCAN rather than reading constantly.+- Keep FET control separate (e.g., button read each loop).+- Treat CC2 current as **signed** (cast to `int16_t`).++---++## Common Gotchas++- **PACK pin voltage reading 0V** is normal if the PACK node is not being driven and/or FETs are open.+- **Current is signed**; treat `CC2Current` as two’s-complement.+- Protections (UV/OV/OCD/SCD/PF) can override host FET commands.+- If the EVM “FUSE” LED is on, check PF status and PF-related configuration.++---++## Module Notes++- `BQ769x2Header.h`: contains direct command IDs, subcommands, and RAM register addresses+- Low-level comms:+ - `I2C_ReadReg()`, `I2C_WriteReg()`, ISR state machine+ - `DirectCommands()`, `Subcommands()`, `CommandSubcommands()`
PlatformIO/MSP430_BQ76952/src/main_MSP430FR2355_I2C.cppadded+1216@@ -0,0 +1,1216 @@+#include "msp430f5529.h"+#define ACTIVE+#ifdef ACTIVE++/* --COPYRIGHT--,BSD_EX+ * Copyright (c) 2021, Texas Instruments Incorporated+ * All rights reserved.+ *+ * Redistribution and use in source and binary forms, with or without+ * modification, are permitted provided that the following conditions+ * are met:+ *+ * * Redistributions of source code must retain the above copyright+ * notice, this list of conditions and the following disclaimer.+ *+ * * Redistributions in binary form must reproduce the above copyright+ * notice, this list of conditions and the following disclaimer in the+ * documentation and/or other materials provided with the distribution.+ *+ * * Neither the name of Texas Instruments Incorporated nor the names of+ * its contributors may be used to endorse or promote products derived+ * from this software without specific prior written permission.+ *+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.+ * --/COPYRIGHT--*/++//******************************************************************************+// BQ76952EVM demo code for MSP430FR2x55 + BQ769x2+//+// Description: MSP430FR2x55 functions as the I2C host that communicates+// with the BQ769x2 sending and receiving different types of commands.+// ACLK = 32.768kHz REFO or external XT1, MCLK = SMCLK = 1MHz DCO+//+// /|\ /|\+// MSP430FR2x55 10k |+// ----------------- | 10k+// /|\ | P4.5|---+---|-- I2C Data (UCB1SDA)+// | | | |+// ---|RST P4.4|-------+-- I2C Clock (UCB1SCL)+// | |+// | P2.3|---> SHUT+// | |+// | P4.2|---> UART RX+// | |+// LEDs <---|P8.0 -8.2 P4.3|<--- UART TX+// | |+//+//+// Andrew Han and Matt Sunna+// Texas Instruments Inc.+// August 2021+// Built with Code Composer Studio (CCS) v10.1.1+//******************************************************************************++//------------------------------------------------------------------------------+// Includes+//------------------------------------------------------------------------------+#include <assert.h>+#include <msp430.h>+#include <stdbool.h>+#include <stdint.h>+#include <stdio.h>++#include "BQ769x2Header.h"++//------------------------------------------------------------------------------+// Defines / macros+//------------------------------------------------------------------------------++// USER CONFIG HERE+#define NUM_CELLS 3+#define NUM_CELLS_BITS 0x0007 // bit 0 for cell 0, bit 3 for cell 3, etc. Write 1 to enable, write 0 to disable+++// other +#define DEV_ADDR 0x08 // BQ769x2 7-bit I2C address+#define CRC_Mode 0 // 0 = disabled, 1 = enabled++#define MAX_BUFFER_SIZE 10+#define R 0 // Read+#define W 1 // Write+#define W2 2 // Write data with two bytes++// Porting macros for F5529: match FR-style USCI flags+#define USCI_I2C_UCRXIFG0 USCI_I2C_UCRXIFG+#define USCI_I2C_UCTXIFG0 USCI_I2C_UCTXIFG++// These extra FIFO levels don't exist on F5529; they will never be hit+#define USCI_I2C_UCRXIFG1 0x12+#define USCI_I2C_UCRXIFG2 0x14+#define USCI_I2C_UCRXIFG3 0x16+#define USCI_I2C_UCTXIFG1 0x18+#define USCI_I2C_UCTXIFG2 0x1A+#define USCI_I2C_UCTXIFG3 0x1C++// Upper bound for __even_in_range+#define USCI_I2C_UCBIT9IFG USCI_I2C_UCTXIFG++//------------------------------------------------------------------------------+// Types+//------------------------------------------------------------------------------+typedef enum I2C_ModeEnum+{+ IDLE_MODE,+ NACK_MODE,+ TX_REG_ADDRESS_MODE,+ RX_REG_ADDRESS_MODE,+ TX_DATA_MODE,+ RX_DATA_MODE,+ SWITCH_TO_RX_MODE,+ SWITHC_TO_TX_MODE,+ TIMEOUT_MODE+} I2C_Mode;++typedef enum+{+ OUTPUT_HUMAN = 0,+ OUTPUT_JSON = 1+} OutputMode;++//------------------------------------------------------------------------------+// Globals+//------------------------------------------------------------------------------++// UART output mode++static OutputMode output_mode = OUTPUT_HUMAN; // default to human-readable output++// I2C state machine+I2C_Mode MasterMode = IDLE_MODE;+uint8_t TransmitRegAddr = 0;+uint8_t ReceiveBuffer[MAX_BUFFER_SIZE] = {0};+uint8_t RXByteCtr = 0;+uint8_t ReceiveIndex = 0;+uint8_t TransmitBuffer[MAX_BUFFER_SIZE] = {0};+uint8_t TXByteCtr = 0;+uint8_t TransmitIndex = 0;++// RX / measurement buffers+uint8_t RX_data[2] = {0x00, 0x00};+uint8_t RX_32Byte[32] = {+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};++uint16_t CellVoltage[16] = {+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};++float Temperature[3] = {0, 0, 0};+uint16_t Stack_Voltage = 0x00;+uint16_t Pack_Voltage = 0x00;+uint16_t LD_Voltage = 0x00;+uint16_t Pack_Current = 0x00;+uint16_t AlarmBits = 0x00;++uint8_t value_SafetyStatusA;+uint8_t value_SafetyStatusB;+uint8_t value_SafetyStatusC;+uint8_t value_PFStatusA;+uint8_t value_PFStatusB;+uint8_t value_PFStatusC;+uint8_t FET_Status;+uint16_t CB_ActiveCells;++uint8_t UV_Fault = 0;+uint8_t OV_Fault = 0;+uint8_t SCD_Fault = 0;+uint8_t OCD_Fault = 0;+uint8_t ProtectionsTriggered = 0;++uint8_t LD_ON = 0;+uint8_t DSG = 0;+uint8_t CHG = 0;+uint8_t PCHG = 0;+uint8_t PDSG = 0;++//------------------------------------------------------------------------------+// Function prototypes+//------------------------------------------------------------------------------++// Board / low-level+void GPIO_initPins(void);+void GPIO_configPins(void);+void LED_On(int32_t ledPin);+void LED_Off(int32_t ledPin);+void UART_Init(void);+void I2C_initModule(void);+void map_I2C_and_UART(void);++// Utility+void delayUS(uint16_t us);+int putchar(int c);+void CopyArray(uint8_t *source, uint8_t *dest, uint8_t count);+unsigned char Checksum(unsigned char *ptr, unsigned char len);++// I2C access+I2C_Mode I2C_ReadReg(uint8_t reg_addr, uint8_t *reg_data, uint8_t count);+I2C_Mode I2C_WriteReg(uint8_t reg_addr, uint8_t *reg_data, uint8_t count);++// BQ769x2 API+void BQ769x2_SetRegister(uint16_t reg_addr, uint32_t reg_data, uint8_t datalen);+void CommandSubcommands(uint16_t command);+void Subcommands(uint16_t command, uint16_t data, uint8_t type);+void DirectCommands(uint8_t command, uint16_t data, uint8_t type);+void BQ769x2_Init(void);++void BQ769x2_ReadFETStatus(void);+void BQ769x2_WriteFETStatus(bool DSG, bool CHG);+void update_fets_from_buttons(void);+void BQ769x2_ShutdownPin(void);+void BQ769x2_ReleaseShutdownPin(void);++uint16_t BQ769x2_ReadAlarmStatus(void);+void BQ769x2_ReadSafetyStatus(void);+void BQ769x2_ReadPFStatus(void);++uint16_t BQ769x2_ReadVoltage(uint8_t command);+void BQ769x2_ReadAllVoltages(void);+uint16_t BQ769x2_ReadCurrent(void);+float BQ769x2_ReadTemperature(uint8_t command);++// JSON/Hydrogen packets++void send_json_notification(const char *method,+ const char *id,+ const char *data_fmt, ...);++// --- 1. BMS output messages ---------------------------------------------------++void output_bms_config(const char *battery_type, int cell_count);+void output_bms_voltages(uint32_t v_mV, const uint16_t *CellVoltage, int cell_count);+void output_fet_status(bool chg, bool dsg);+void output_current_value(int16_t current_mA);++// --- output mode selection --------------------------------------------------++void set_output_mode(OutputMode mode)+{+ output_mode = mode; // set global output mode+}++//------------------------------------------------------------------------------+// main+//------------------------------------------------------------------------------+int main(void)+{+ // Stop watchdog timer+ WDTCTL = WDTPW | WDTHOLD;++ GPIO_initPins();+ map_I2C_and_UART();+ UART_Init();+ I2C_initModule();++ LED_On(0); // Popwer LED++ set_output_mode(OUTPUT_JSON); // or OUTPUT_JSON++ CommandSubcommands(BQ769x2_RESET); // Reset the BQ769x2 registers+ delayUS(60000);++ BQ769x2_Init(); // Configure all BQ769x2 RAM settings+ delayUS(10000);++ BQ769x2_WriteFETStatus(0,1);+ CommandSubcommands(FET_ENABLE); // Enable CHG and DSG FETs+ delayUS(10000);++ CommandSubcommands(SLEEP_DISABLE); // Disable Sleep for full-speed measurements++ // Wait for FETs to close and measurements to settle+ delayUS(60000);+ delayUS(60000);+ delayUS(60000);+ delayUS(60000);++ delayUS(20000);+ delayUS(20000);+ delayUS(20000);++ LED_On(1);+ printf("hello world\n\r");+ output_bms_config("Li-ion", 3);+++ while (1)+ {+ static int i = 0; // Loop counter for periodic output ++ // Read alarm status and check for new measurements+ AlarmBits = BQ769x2_ReadAlarmStatus();++ if (AlarmBits & 0x80)+ {+ // FULLSCAN complete: new measurements available+ BQ769x2_ReadAllVoltages();+ Pack_Current = BQ769x2_ReadCurrent();+ Temperature[0] = BQ769x2_ReadTemperature(TS1Temperature);+ Temperature[1] = BQ769x2_ReadTemperature(TS3Temperature);++ // Clear the FULLSCAN bit+ DirectCommands(AlarmStatus, 0x0080, W);+ }++ if (AlarmBits & 0xC000)+ {+ // Safety Status bits present in AlarmStatus+ BQ769x2_ReadSafetyStatus();++ if (ProtectionsTriggered & 1)+ {+ P1OUT |= BIT0; // Turn on LED to indicate protection+ }++ // Clear Safety Status Alarm bits+ DirectCommands(AlarmStatus, 0xF800, W);+ }+ else+ {+ if (ProtectionsTriggered & 1)+ {+ BQ769x2_ReadSafetyStatus();+ if (!(ProtectionsTriggered & 1))+ {+ P1OUT &= ~BIT0; // Turn off LED when protection clears+ printf("PROTECT");+ }+ }+ }++ // Output for every 20 cycles+ if (i % 20 == 0){+ printf("Running\n\r");+ output_bms_voltages(Stack_Voltage, CellVoltage, NUM_CELLS);+ update_fets_from_buttons();+ BQ769x2_ReadFETStatus();+ output_fet_status(CHG, DSG);+ output_current_value((int16_t)BQ769x2_ReadCurrent());+ }++ // Output for every 100 cycles+ if (i > 100){+ output_bms_config("Li-ion", 3);+ BQ769x2_ReadSafetyStatus();+ if (UV_Fault || OV_Fault || SCD_Fault || OCD_Fault){+ printf("Fault detected\n\r");+ printf("UV: %d", UV_Fault);+ printf("OV: %d", OV_Fault);+ printf("SCD: %d", SCD_Fault);+ printf("OCD: %d", OCD_Fault);+ } + i = 0; + }++ i++;+ delayUS(20000); // repeat loop every ~20 ms+ }+}++//------------------------------------------------------------------------------+// UART Output helper functions+//------------------------------------------------------------------------------++// Low level formatting function+static void send_json_notification_data(const char *method, const char *id, const char *data_str)+{+ uint32_t timestamp = 5005;++ printf("{\"method\":\"%s\","+ "\"data\":{%s},"+ "\"timestamp\":%lu,"+ "\"source\":\"robot\","+ "\"type\":\"notification\","+ "\"id\":\"%s\","+ "\"agent\":\"robot\"}\n",+ method, data_str, (unsigned long)timestamp, id);+}++// For simple, fixed data payloads+static void send_json_notification_fmt(const char *method,+ const char *id,+ const char *data_fmt, ...)+{+ char data_buf[256];+ va_list args;+ va_start(args, data_fmt);+ vsnprintf(data_buf, sizeof(data_buf), data_fmt, args); // format into data_buf+ va_end(args);++ send_json_notification_data(method, id, data_buf);+}++// -----------------------------------------------------------------------------+// Public “user” functions (no JSON/quote escaping here)+// -----------------------------------------------------------------------------++// 1. BMS/config --------------------------------------------------------------++void output_bms_config(const char *battery_type, int cell_count)+{+ const char* type = "battery_type";+ const char* count = "cell_count";+ if (output_mode == OUTPUT_HUMAN)+ {+ printf("BMS config:\n\r");+ printf(" %s: %s\n\r", type, battery_type);+ printf(" %s: %d\n\r", count, cell_count);+ }+ else+ {+ // all escaping handled inside send_json_notification_fmt()+ send_json_notification_fmt(+ "/BMS/config",+ "001",+ "\"%s\":\"%s\",\"%s\":%d",+ type, battery_type, count, cell_count);+ }+}++// 2. Pack + cell voltages ----------------------------------------------------+// v_mV: pack voltage in millivolts+// CellVoltage[i]: per-cell voltage in millivolts++void output_bms_voltages(uint32_t v_mV, const uint16_t *CellVoltage, int cell_count)+{+ if (output_mode == OUTPUT_HUMAN)+ {+ printf("Pack voltage: %u.%03u V\n\r",+ v_mV / 1000, v_mV % 1000);++ for (int i = 0; i < cell_count; i++)+ {+ printf(" Battery %d voltage: %u.%03u V\n\r",+ i + 1,+ CellVoltage[i] / 1000,+ CellVoltage[i] % 1000);+ }+ }+ else+ {+ // build dynamic JSON data body, then wrap with send_json_notification_data()+ char data_buf[256];+ int len = 0;++ // pack voltage+ len += snprintf(data_buf + len, sizeof(data_buf) - len,+ "\"pack_voltage_V\":%u.%03u",+ v_mV / 1000, v_mV % 1000);++ // cell voltages+ for (int i = 0; i < cell_count && len < (int)sizeof(data_buf); i++)+ {+ len += snprintf(data_buf + len, sizeof(data_buf) - len,+ ",\"cell%d_voltage_V\":%u.%03u",+ i + 1,+ CellVoltage[i] / 1000,+ CellVoltage[i] % 1000);+ }++ send_json_notification_data("/BMS/voltages",+ "002",+ data_buf);+ }+}++// Example function here+void output_fet_status(bool chg, bool dsg)+{+ const char* chgStatus = "CHG_Status";+ const char* dsgStatus = "DSG_Status";+ if (output_mode == OUTPUT_HUMAN)+ {+ printf("%s: %d %s: %d \n\r", chgStatus, chg, dsgStatus, dsg);+ }+ else+ {+ // all escaping handled inside send_json_notification_fmt()+ send_json_notification_fmt(+ "/BMS/fet_status",+ "003",+ "\"%s\":%d,\"%s\":%d",+ chgStatus, chg, dsgStatus, dsg);+ }+}++void output_error_notifications(bool UV, bool OV, bool SCD, bool OCD)+{+ const char* UV_s = "Under_Voltage_Status";+ const char* OV_s = "Over_Voltage_Status";+ const char* SCD_s = "SCD_Status";+ const char* OCD_s = "OCD_Status";+ if (output_mode == OUTPUT_HUMAN)+ {+ printf("%s: %d %s: %d %s: %d %s: %d \n\r", UV_s, UV, OV_s, OV, SCD_s, SCD, OCD_s, OCD);+ }+ else+ {+ // all escaping handled inside send_json_notification_fmt()+ send_json_notification_fmt(+ "/BMS/error_notifications",+ "004",+ "\"%s\":%d,\"%s\":%d,\"%s\":%d,\"%s\":%d",+ UV_s, UV, OV_s, OV, SCD_s, SCD, OCD_s, OCD);+ }+}++void output_current_value(int16_t current_mA)+{+ const char* current_s = "Current_mA";+ if (output_mode == OUTPUT_HUMAN)+ {+ printf("%s: %d \n\r", current_s, current_mA);+ }+ else+ {+ // all escaping handled inside send_json_notification_fmt()+ send_json_notification_fmt(+ "/BMS/current_measurement",+ "005",+ "\"%s\":%d",+ current_s, current_mA);+ }+}++++//------------------------------------------------------------------------------+// High-level BQ769x2 helpers+//------------------------------------------------------------------------------++void BQ769x2_Init(void)+{+ // Enter CONFIGUPDATE mode (Subcommand 0x0090)+ CommandSubcommands(SET_CFGUPDATE);++ // Power configuration+ BQ769x2_SetRegister(PowerConfig, 0x2D80, 2);++ // Enable REG0 pre-regulator+ BQ769x2_SetRegister(REG0Config, 0x01, 1);++ // Enable REG1 with 3.3 V output+ BQ769x2_SetRegister(REG12Config, 0x0D, 1);++ // DFETOFF pin controls both CHG and DSG FET+ BQ769x2_SetRegister(DFETOFFPinConfig, 0x42, 1);++ // ALERT pin configuration+ BQ769x2_SetRegister(ALERTPinConfig, 0x2A, 1);++ // TS1 measures cell temperature+ BQ769x2_SetRegister(TS1Config, 0x07, 1);++ // TS3 measures FET temperature+ BQ769x2_SetRegister(TS3Config, 0x0F, 1);++ // HDQ pin: no thermistor on EVM; set to 0+ BQ769x2_SetRegister(HDQPinConfig, 0x00, 1);++ // VCell Mode: enable 16 cells+ BQ769x2_SetRegister(VCellMode, NUM_CELLS_BITS, 2);++ // Enabled Protections A: SCD, OCD1, OCC, COV, CUV+ BQ769x2_SetRegister(EnabledProtectionsA, 0xBC, 1);++ // Enabled Protections B: all enabled+ BQ769x2_SetRegister(EnabledProtectionsB, 0xF7, 1);++ // Default Alarm Mask+ BQ769x2_SetRegister(DefaultAlarmMask, 0xF882, 2);++ // Cell balancing configuration+ BQ769x2_SetRegister(BalancingConfiguration, 0x03, 1);++ // CUV Threshold+ BQ769x2_SetRegister(CUVThreshold, 0x31, 1);++ // COV Threshold+ BQ769x2_SetRegister(COVThreshold, 0x55, 1);++ // OCC Threshold+ BQ769x2_SetRegister(OCCThreshold, 0x05, 1);++ // OCD1 Threshold+ BQ769x2_SetRegister(OCD1Threshold, 0x0A, 1);++ // SCD Threshold+ BQ769x2_SetRegister(SCDThreshold, 0x05, 1);++ // SCD Delay+ BQ769x2_SetRegister(SCDDelay, 0x03, 1);++ // SCDL latch limit+ BQ769x2_SetRegister(SCDLLatchLimit, 0x01, 1);++ // Exit CONFIGUPDATE mode+ CommandSubcommands(EXIT_CFGUPDATE);+}++uint16_t BQ769x2_ReadAlarmStatus(void)+{+ DirectCommands(AlarmStatus, 0x00, R);+ return (RX_data[1] * 256 + RX_data[0]);+}++void BQ769x2_ReadSafetyStatus(void)+{+ // Safety Status A+ DirectCommands(SafetyStatusA, 0x00, R);+ value_SafetyStatusA = (RX_data[1] * 256 + RX_data[0]);++ UV_Fault = ((0x4 & RX_data[0]) >> 2);+ OV_Fault = ((0x8 & RX_data[0]) >> 3);+ SCD_Fault = ((0x8 & RX_data[1]) >> 3);+ OCD_Fault = ((0x2 & RX_data[1]) >> 1);++ // Safety Status B+ DirectCommands(SafetyStatusB, 0x00, R);+ value_SafetyStatusB = (RX_data[1] * 256 + RX_data[0]);++ // Safety Status C+ DirectCommands(SafetyStatusC, 0x00, R);+ value_SafetyStatusC = (RX_data[1] * 256 + RX_data[0]);++ if ((value_SafetyStatusA + value_SafetyStatusB + value_SafetyStatusC) > 1)+ {+ ProtectionsTriggered = 1;+ }+ else+ {+ ProtectionsTriggered = 0;+ }+}++void BQ769x2_ReadPFStatus(void)+{+ DirectCommands(PFStatusA, 0x00, R);+ value_PFStatusA = (RX_data[1] * 256 + RX_data[0]);++ DirectCommands(PFStatusB, 0x00, R);+ value_PFStatusB = (RX_data[1] * 256 + RX_data[0]);++ DirectCommands(PFStatusC, 0x00, R);+ value_PFStatusC = (RX_data[1] * 256 + RX_data[0]);+}++void BQ769x2_ReadFETStatus(void)+{+ DirectCommands(FETStatus, 0x00, R);+ FET_Status = (RX_data[1] * 256 + RX_data[0]);++ DSG = ((0x4 & RX_data[0]) >> 2);+ CHG = (0x1 & RX_data[0]);+ PCHG = ((0x2 & RX_data[0]) >> 1);+ PDSG = ((0x8 & RX_data[0]) >> 3);+}++void BQ769x2_WriteFETStatus(bool DSG, bool CHG){+ uint8_t State = 0;++ // DSG control+ if (!DSG){+ State |= (1 << 0); // set DSG_OFF bit = force off+ }++ // CHG control+ if (!CHG){+ State |= (1 << 2); // set CHG_OFF bit = force off+ }++ Subcommands(FET_CONTROL, State, 1); // or whatever your write call requires+}++void update_fets_from_buttons(void)+{+ bool dsg_enable = false;+ bool chg_enable = false;++ if (P3IN & BIT3) {+ dsg_enable = true; // p3.3 high -> enable discharge+ }++ if (P3IN & BIT4) {+ chg_enable = true; // p3.4 high -> enable charge+ }++ BQ769x2_WriteFETStatus(dsg_enable, chg_enable); // apply fet control+}+++++void BQ769x2_ShutdownPin(void)+{+ P2OUT |= BIT3;+}++void BQ769x2_ReleaseShutdownPin(void)+{+ P2OUT &= ~BIT3;+}++uint16_t BQ769x2_ReadVoltage(uint8_t command)+{+ DirectCommands(command, 0x00, R);++ if (command >= Cell1Voltage && command <= Cell16Voltage)+ {+ // Cell 1–16: mV+ return (RX_data[1] * 256 + RX_data[0]);+ }+ else+ {+ // Stack / Pack / LD: 0.01 V units+ return 10 * (RX_data[1] * 256 + RX_data[0]);+ }+}++void BQ769x2_ReadAllVoltages(void)+{+ unsigned char x;+ int cellvoltageholder = Cell1Voltage;++ for (x = 0; x < 16; x++)+ {+ CellVoltage[x] = BQ769x2_ReadVoltage(cellvoltageholder);+ cellvoltageholder += 2;+ }++ Stack_Voltage = BQ769x2_ReadVoltage(StackVoltage);+ Pack_Voltage = BQ769x2_ReadVoltage(PACKPinVoltage);+ LD_Voltage = BQ769x2_ReadVoltage(LDPinVoltage);+}++uint16_t BQ769x2_ReadCurrent(void)+{+ DirectCommands(CC2Current, 0x00, R);+ return (RX_data[1] * 256 + RX_data[0]); // mA+}++float BQ769x2_ReadTemperature(uint8_t command)+{+ DirectCommands(command, 0x00, R);+ return (0.1f * (float)(RX_data[1] * 256 + RX_data[0])) - 273.15f;+}++//------------------------------------------------------------------------------+// Low-level BQ769x2 register / command helpers+//------------------------------------------------------------------------------++void BQ769x2_SetRegister(uint16_t reg_addr, uint32_t reg_data, uint8_t datalen)+{+ uint8_t TX_Buffer[2] = {0x00, 0x00};+ uint8_t TX_RegData[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};++ //TX_RegData in little endian format+ TX_RegData[0] = reg_addr & 0xff;+ TX_RegData[1] = (reg_addr >> 8) & 0xff;+ TX_RegData[2] = reg_data & 0xff; //1st byte of data++ switch(datalen)+ {+ case 1: //1 byte datalength+ I2C_WriteReg(0x3E, TX_RegData, 3);+ delayUS(2000);+ TX_Buffer[0] = Checksum(TX_RegData, 3);+ TX_Buffer[1] = 0x05; //combined length of register address and data+ I2C_WriteReg(0x60, TX_Buffer, 2); // Write the checksum and length+ delayUS(2000);+ break;+ case 2: //2 byte datalength+ TX_RegData[3] = (reg_data >> 8) & 0xff;+ I2C_WriteReg(0x3E, TX_RegData, 4);+ delayUS(2000);+ TX_Buffer[0] = Checksum(TX_RegData, 4);+ TX_Buffer[1] = 0x06; //combined length of register address and data+ I2C_WriteReg(0x60, TX_Buffer, 2); // Write the checksum and length+ delayUS(2000);+ break;+ case 4: //4 byte datalength, Only used for CCGain and Capacity Gain+ TX_RegData[3] = (reg_data >> 8) & 0xff;+ TX_RegData[4] = (reg_data >> 16) & 0xff;+ TX_RegData[5] = (reg_data >> 24) & 0xff;+ I2C_WriteReg(0x3E, TX_RegData, 6);+ delayUS(2000);+ TX_Buffer[0] = Checksum(TX_RegData, 6);+ TX_Buffer[1] = 0x08; //combined length of register address and data+ I2C_WriteReg(0x60, TX_Buffer, 2); // Write the checksum and length+ delayUS(2000);+ break;+ }+}++void CommandSubcommands(uint16_t command) //For Command only Subcommands+// See the TRM or the BQ76952 header file for a full list of Command-only subcommands+{ //For DEEPSLEEP/SHUTDOWN subcommand you will need to call this function twice consecutively++ uint8_t TX_Reg[2] = {0x00, 0x00};++ //TX_Reg in little endian format+ TX_Reg[0] = command & 0xff;+ TX_Reg[1] = (command >> 8) & 0xff;++ I2C_WriteReg(0x3E,TX_Reg,2);+ delayUS(2000);+}++void Subcommands(uint16_t command, uint16_t data, uint8_t type)+// See the TRM or the BQ76952 header file for a full list of Subcommands+{+ //security keys and Manu_data writes dont work with this function (reading these commands works)+ //max readback size is 32 bytes i.e. DASTATUS, CUV/COV snapshot+ uint8_t TX_Reg[4] = {0x00, 0x00, 0x00, 0x00};+ uint8_t TX_Buffer[2] = {0x00, 0x00};++ //TX_Reg in little endian format+ TX_Reg[0] = command & 0xff;+ TX_Reg[1] = (command >> 8) & 0xff;++ if (type == R) {//read+ I2C_WriteReg(0x3E,TX_Reg,2);+ delayUS(2000);+ I2C_ReadReg(0x40, RX_32Byte, 32); //RX_32Byte is a global variable+ }+ else if (type == W) {+ //FET_Control, REG12_Control+ TX_Reg[2] = data & 0xff;+ I2C_WriteReg(0x3E,TX_Reg,3);+ delayUS(1000);+ TX_Buffer[0] = Checksum(TX_Reg, 3);+ TX_Buffer[1] = 0x05; //combined length of registers address and data+ I2C_WriteReg(0x60, TX_Buffer, 2);+ delayUS(1000);+ }+ else if (type == W2){ //write data with 2 bytes+ //CB_Active_Cells, CB_SET_LVL+ TX_Reg[2] = data & 0xff;+ TX_Reg[3] = (data >> 8) & 0xff;+ I2C_WriteReg(0x3E,TX_Reg,4);+ delayUS(1000);+ TX_Buffer[0] = Checksum(TX_Reg, 4);+ TX_Buffer[1] = 0x06; //combined length of registers address and data+ I2C_WriteReg(0x60, TX_Buffer, 2);+ delayUS(1000);+ }+}++void DirectCommands(uint8_t command, uint16_t data, uint8_t type)+// See the TRM or the BQ76952 header file for a full list of Direct Commands+{ //type: R = read, W = write+ uint8_t TX_data[2] = {0x00, 0x00};++ //little endian format+ TX_data[0] = data & 0xff;+ TX_data[1] = (data >> 8) & 0xff;++ if (type == R) {//Read+ I2C_ReadReg(command, RX_data, 2); //RX_data is a global variable+ delayUS(2000);+ }+ if (type == W) {//write+ //Control_status, alarm_status, alarm_enable all 2 bytes long+ I2C_WriteReg(command,TX_data,2);+ delayUS(2000);+ }+}++//------------------------------------------------------------------------------+// Utility functions+//------------------------------------------------------------------------------++void delayUS(uint16_t us)+{+ uint16_t ms = us / 1000;+ for (uint16_t i = 0; i < ms; i++)+ {+ __delay_cycles(1000);+ }+}++int putchar(int c)+{+ while (!(UCA1IFG & UCTXIFG))+ ;+ UCA1TXBUF = (unsigned char)c;+ return c;+}++void CopyArray(uint8_t *source, uint8_t *dest, uint8_t count)+{+ for (uint8_t i = 0; i < count; i++)+ {+ dest[i] = source[i];+ }+}++unsigned char Checksum(unsigned char *ptr, unsigned char len)+{+ unsigned char checksum = 0;++ for (unsigned char i = 0; i < len; i++)+ {+ checksum += ptr[i];+ }++ checksum = 0xff & ~checksum;+ return checksum;+}++//------------------------------------------------------------------------------+// I2C register access+//------------------------------------------------------------------------------++I2C_Mode I2C_ReadReg(uint8_t reg_addr, uint8_t *reg_data, uint8_t count)+{+ /* Initialize state machine */+ MasterMode = TX_REG_ADDRESS_MODE;+ TransmitRegAddr = reg_addr;+ RXByteCtr = count;+ TXByteCtr = 0;+ ReceiveIndex = 0;+ TransmitIndex = 0;++ /* Initialize device address and interrupts */+ UCB1I2CSA = DEV_ADDR;+ UCB1IFG &= ~(UCTXIFG + UCRXIFG); // Clear any pending interrupts+ UCB1IE &= ~UCRXIE; // Disable RX interrupt+ UCB1IE |= UCTXIE; // Enable TX interrupt+ UCB1CTLW0 |= UCTR + UCTXSTT; // I2C TX, start condition+ __bis_SR_register(LPM0_bits + GIE); // Enter LPM0 w/ interrupts+ //For debugger+ __no_operation();++ /* Copy over received data */+ CopyArray(ReceiveBuffer, reg_data, count);++ return MasterMode;+}++I2C_Mode I2C_WriteReg(uint8_t reg_addr, uint8_t *reg_data, uint8_t count)+{+ /* Initialize state machine */+ MasterMode = TX_REG_ADDRESS_MODE;+ TransmitRegAddr = reg_addr;++ /* Copy register data to TransmitBuffer */+ CopyArray(reg_data, TransmitBuffer, count);++ TXByteCtr = count;+ RXByteCtr = 0;+ ReceiveIndex = 0;+ TransmitIndex = 0;++ /* Initialize device address and interrupts */+ UCB1I2CSA = DEV_ADDR;+ UCB1IFG &= ~(UCTXIFG + UCRXIFG); // Clear any pending interrupts+ UCB1IE &= ~UCRXIE; // Disable RX interrupt+ UCB1IE |= UCTXIE; // Enable TX interrupt+ UCB1CTLW0 |= UCTR + UCTXSTT; // I2C TX, start condition+ __bis_SR_register(LPM0_bits + GIE); // Enter LPM0 w/ interrupts+ //For debugger+ __no_operation();++ return MasterMode;+}++//------------------------------------------------------------------------------+// Board support: GPIO, I2C, UART, port mapping+//------------------------------------------------------------------------------++void LED_On(int32_t ledPin)+{+ assert(ledPin >= 0 && ledPin <= 2);+ P8OUT &= ~(1 << ledPin);+}++void LED_Off(int32_t ledPin)+{+ assert(ledPin >= 0 && ledPin <= 2);+ P8OUT |= (1 << ledPin);+}++void GPIO_initPins(void)+{+ P1OUT = 0x00;+ P2OUT = 0x00;+ P3OUT = 0x00;+ P4OUT = 0x0F;+ P5OUT = 0x00;+ P6OUT = 0x00;+ P8OUT = 0x00;++ P1DIR = 0xFF;+ P2DIR = 0xFF;+ P3DIR = 0xFF;+ P4DIR = 0x00;+ P5DIR = 0xFF;+ P6DIR = 0xFF;+ P8DIR = 0xFF;++ GPIO_configPins();+}++void GPIO_configPins(void)+{+ // P8.0 (LED1)+ P8OUT &= ~BIT0; // Set P8.0 to low+ P8DIR |= BIT0; // Set P8.0 to output direction++ // P8.1 (LED2)+ P8OUT |= BIT1; // Set P8.1 to high+ P8DIR |= BIT1; // Set P8.1 to output direction++ // P8.2 (LED3)+ P8OUT |= BIT2; // Set P8.2 to high+ P8DIR |= BIT2; // Set P8.2 to output direction++ P3DIR &= ~(BIT3 | BIT4); // Set P4.3 and P4.4 to input+ P3REN |= (BIT3 | BIT4); // Enable pull up/down resistor+ P3OUT &= ~(BIT3 | BIT4); // Output low (pull down)+}++void map_I2C_and_UART(void)+{+ PMAPKEYID = PMAPKEY; // Unlock port mapping + PMAPCTL |= PMAPRECFG;++ P4MAP4 = PM_UCB1SCL; // Set P4.4 as SCL+ P4MAP5 = PM_UCB1SDA; // Set P4.5 as SCL++ P4MAP2 = PM_UCA1RXD; // Set 4.2 as RXD+ P4MAP3 = PM_UCA1TXD; // Set 4.3 as TXD++ PMAPKEYID = 0;+}++void I2C_initModule(void)+{+ // --- Configure I2C pins for UCB1 on MSP430F5529 ---+ // P4.4 = UCB1SDA, P4.5 = UCB1SCL+ P4SEL |= BIT4 | BIT5; // select peripheral function for P4.4/P4.5+ //P4SEL |= BIT6 | BIT7; // select peripheral function for P4.6/P4.7++ // --- Configure USCI_B1 in I2C master mode ---+ UCB1CTL1 |= UCSWRST; // hold USCI in reset++ // CTL0: sync, I2C, master+ UCB1CTL0 = UCMST | // master mode+ UCMODE_3 | // I2C mode+ UCSYNC; // synchronous mode++ // CTL1: SMCLK as source while still in reset+ UCB1CTL1 = UCSWRST | UCSSEL_2; // UCSSEL_2 = SMCLK++ // Baud rate: BRCLK / (UCB1BR0+256*BR1)+ // For example: SMCLK = 16 MHz, BR=40 -> 400 kHz I2C+ // We are running now without FLL (1Mhz)+ UCB1BR0 = 10;+ UCB1BR1 = 0;++ // 7-bit slave address of BQ769x2 (0x08) – goes into UCB1I2CSA+ UCB1I2CSA = DEV_ADDR;++ // Release from reset and start operation+ UCB1CTL1 &= ~UCSWRST;++ // Enable NACK interrupt (optional – your ISR already handles NACK)+ UCB1IE |= UCNACKIE;+}++void UART_Init(void)+{+ P4SEL |= BIT2 | BIT3;+ P4DIR |= BIT3;+ P4DIR &= ~BIT2;++ UCA1CTL1 |= UCSWRST;+ UCA1CTL1 &= ~(UCSSEL_3);+ UCA1CTL0 = UCMODE_0;++ UCA1CTL1 |= UCSSEL_1; // ACLK+ UCA1BR0 = 0x03;+ UCA1BR1 = 0x00;+ UCA1MCTL = UCBRS_3 + UCBRF_0;++ UCA1CTL1 &= ~UCSWRST;+}++//------------------------------------------------------------------------------+// I2C ISR+//------------------------------------------------------------------------------+#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)+#pragma vector = USCI_B1_VECTOR+__interrupt void USCI_B1_ISR(void)+#elif defined(__GNUC__)+void __attribute__((interrupt(USCI_B1_VECTOR))) USCI_B1_ISR(void)+#else+#error Compiler not supported!+#endif+{+ uint8_t rx_val = 0;++ switch (UCB1IV)+ {+ case USCI_NONE:+ break;++ case USCI_I2C_UCALIFG:+ break;++ case USCI_I2C_UCNACKIFG:+ break;++ case USCI_I2C_UCSTTIFG:+ break;++ case USCI_I2C_UCSTPIFG:+ break;++ case USCI_I2C_UCRXIFG3:+ case USCI_I2C_UCTXIFG3:+ case USCI_I2C_UCRXIFG2:+ case USCI_I2C_UCTXIFG2:+ case USCI_I2C_UCRXIFG1:+ case USCI_I2C_UCTXIFG1:+ break;++ case USCI_I2C_UCRXIFG0:+ rx_val = UCB1RXBUF;+ if (RXByteCtr)+ {+ ReceiveBuffer[ReceiveIndex++] = rx_val;+ RXByteCtr--;+ }++ if (RXByteCtr == 1)+ {+ UCB1CTLW0 |= UCTXSTP;+ }+ else if (RXByteCtr == 0)+ {+ UCB1IE &= ~UCRXIE;+ MasterMode = IDLE_MODE;+ __bic_SR_register_on_exit(CPUOFF);+ }+ break;++ case USCI_I2C_UCTXIFG0:+ switch (MasterMode)+ {+ case TX_REG_ADDRESS_MODE:+ UCB1TXBUF = TransmitRegAddr;+ if (RXByteCtr)+ {+ MasterMode = SWITCH_TO_RX_MODE;+ }+ else+ {+ MasterMode = TX_DATA_MODE;+ }+ break;++ case SWITCH_TO_RX_MODE:+ UCB1IE |= UCRXIE;+ UCB1IE &= ~UCTXIE;+ UCB1CTLW0 &= ~UCTR;+ MasterMode = RX_DATA_MODE;+ UCB1CTLW0 |= UCTXSTT;++ if (RXByteCtr == 1)+ {+ while (UCB1CTLW0 & UCTXSTT)+ ;+ UCB1CTLW0 |= UCTXSTP;+ }+ break;++ case TX_DATA_MODE:+ if (TXByteCtr)+ {+ UCB1TXBUF = TransmitBuffer[TransmitIndex++];+ TXByteCtr--;+ }+ else+ {+ UCB1CTLW0 |= UCTXSTP;+ MasterMode = IDLE_MODE;+ UCB1IE &= ~UCTXIE;+ __bic_SR_register_on_exit(CPUOFF);+ }+ break;++ default:+ __no_operation();+ break;+ }+ break;++ default:+ break;+ }+}++#endif
SKILL.mdadded+8@@ -0,0 +1,8 @@+---+name: modular-bms+description: When to invoke this skill (Claude reads this to decide). Replace me.+---++# Modular BMS++What this skill does and how to use it.
docs/HERO.mdadded+1@@ -0,0 +1 @@+Put a 1200x630 `hero.png` in this folder. It is the billboard reused on the page header, the homepage, and the screensaver. Until it exists, `adom-wiki pkg lint` reports the hero as the one outstanding item.
docs/hero.pngadded⋯ 1 unchanged line ⋯
install.shadded+7@@ -0,0 +1,7 @@+#!/bin/sh+set -e++# Symlink your install targets back into the module dir so edits+# propagate and reinstalls do not clobber, e.g.:+# ln -sfn "$PWD/bin/run" "$HOME/.local/bin/run"+echo "installed"
package.jsonadded+53@@ -0,0 +1,53 @@+{+ "slug": "modular-bms",+ "title": "Modular BMS",+ "type": "component",+ "version": "1.0.0",+ "description": "Modular Battery Management System — a composable BMS built from Adom molecules. TI BQ76952 monitor/protector with MSP430 host firmware, supporting 18650 cylindrical and EVE LF105 prismatic cell carriers.",+ "tags": [+ "hardware",+ "bms",+ "battery",+ "bq76952",+ "msp430",+ "platformio",+ "18650",+ "lifepo4",+ "modular"+ ],+ "dependencies": {+ "adom/molecule-18650-battery": "^1.0.0",+ "adom/molecule-18650-jumper": "^1.0.0",+ "adom/molecule-eve-lf105-prismatic": "^1.0.0",+ "adom/molecule-bq76952-v2": "^1.0.0"+ },+ "discovery_triggers": [+ "modular bms",+ "battery management system",+ "bq76952",+ "18650 bms",+ "battery pack monitoring",+ "cell balancing",+ "charge discharge protection"+ ],+ "discovery_pitch": "A complete modular battery management system built from Adom molecules — BQ76952 monitor, MSP430 firmware, and swappable cell carriers for 18650 or prismatic cells.",+ "sample_prompts": [+ {+ "label": "Overview",+ "prompt": "Show me the Modular BMS project and its molecules"+ },+ {+ "label": "Firmware",+ "prompt": "How do I build and flash the Modular BMS firmware?"+ },+ {+ "label": "Configure",+ "prompt": "How do I configure the BQ76952 for a different cell count?"+ }+ ],+"hero": {+ "headline": "Modular BMS",+ "subhead": "Composable battery management system — BQ76952 + MSP430 with swappable 18650 and prismatic cell carriers.",+ "screenshot": "docs/hero.png"+ }+}
uninstall.shadded+5@@ -0,0 +1,5 @@+#!/bin/sh+set -e++# Undo what install.sh did (remove the symlinks you created).+echo "uninstalled"