Main Content

BMS Cell Voltage Monitoring and SOC Estimation on C2000 Microcontroller

R2026b

This example shows how to monitor cell voltages and estimate state of charge (SOC) for a lithium-ion battery pack using a C2000™ microcontroller and a BQ79718 analog front end. You simulate and validate the estimation algorithms in Simulink®, then generate and deploy C code to a Texas Instruments® (TI) LAUNCHXL-F28P55X LaunchPad using C2000 Microcontroller Blockset. The BQ79718B-Q1 analog front end (AFE) acquires cell voltages and communicates with the LaunchPad over UART.

This example supports two configurations:

  • Single device (18S) — One BQ79718EVM monitors an 18-cell pack.

  • Daisy chain (36S) — Two BQ79718EVMs in a daisy chain monitor a 36-cell pack.

Required Hardware

Single Device (18S)

Component

Description

TI LAUNCHXL-F28P55X LaunchPad

Microcontroller (MCU) development board (F28P55x series)

BQ79718EVM

Evaluation module for the BQ79718B-Q1 AFE

DC voltage source (75 V, 1 A minimum)

Simulates the 18-cell lithium-ion battery stack input

Note: The BQ79718EVM is not commercially available. Use a custom board that meets the BQ79718/BQ79758 interface requirements.

Daisy Chain (36S)

In addition to the single-device hardware, daisy-chain operation requires one additional EVM:

  • BQ79718EVM #1 — base device connected to the MCU; measures cell voltages for cells 1–18.

  • BQ79718EVM #2 — stack device daisy-chained to the base device; measures cell voltages for cells 19–36.

Open MATLAB Project

This MATLAB® project contains all example models, data scripts, and custom C files. To open the project, click the Open Project hyperlink below or run the following command:

openExample("c2b/DeployBMSCellMonitorToC2000Example")

Available Models

The target models generate code for the C2000 MCU. The host models run on the host computer to display live cell voltages and SOC from the deployed target.

Target Models

Model

Configuration

Description

c2000BMSSingleDeviceModel

18S (1 device)

Single BQ79718 cell monitor

c2000BMSDaisyChainModel

36S (2 devices)

Daisy-chain with auto-addressing

Host Models

Model

Configuration

Description

c2000BMSSingleDeviceHostModel

18S

Receives 18 cell voltages + SOC via serial

c2000BMSDaisyChainHostModel

36S

Receives 36 cell voltages + SOC via serial

All models share the parameter script c2000BMSData.m. Each model sets numberOfDevices in its InitFcn callback before calling the data script.

Data Flow: AFE to Host ECU

c2000BMSSingleDeviceModel implements a cell voltage monitoring and SOC estimation pipeline. The C2000 MCU communicates with the AFE over a 1 Mbps UART connection, reads 18 cell voltages, estimates SOC, and reports results to a host electronic control unit (ECU) over UART and CAN.

Pipeline Subsystems

Both models implement the same pipeline:

  • InitializeAFE — Sends wake pulse, auto-addressing, and ADC start commands to the BQ79718 device(s) over SCIB UART at 1 Mbps.

  • SendCommand — Constructs a single-read request for cell voltage registers and transmits it periodically.

  • SCI Receive with Buffer — Accumulates FIFO interrupts into a complete response frame using the MW_dataBuffer.c ring buffer.

  • ReadCellVoltages — Unpacks HI/LO byte pairs into cell voltages.

  • EstimateSOC — Estimates SOC using Coulomb counting (current integration).

The daisy-chain model extends this with a two-device initialization sequence (directed writes for auto-addressing, TOP_STACK configuration) and a doubled buffer size (100 bytes) to accommodate responses from both devices. For a detailed breakdown of each stage, see Cell Voltage Monitoring Pipeline.

Model Simulation

To verify algorithm behavior before deploying to hardware, simulate the model with a Simscape Battery plant model. The Simscape Battery block models an 18S (or 36S) series-connected lithium-ion pack with realistic voltage and SOC dynamics. To run the simulation, on the Simulation tab, click Run.

The model InitFcn callback runs c2000BMSData.m automatically to load workspace variables. This script defines register addresses, frame sizes, and battery parameters:

% numberOfDevices = 1;
% run("c2000BMSData.m")  % Single device (18S). Ensure "c2000BMSData.m" is in the current folder or on the MATLAB path

% numberOfDevices = 2;
% run("c2000BMSData.m")  % Daisy chain (36S)

Simulation Results

Visualize the cell voltages on the display blocks in the Simulink canvas.

Each value is the terminal voltage of one cell in the Simscape™ Battery™ pack. The pack voltage equals the sum of all 18 or 36 cells. Per-cell values in the 3.5–4.2 V range confirm that the model correctly senses voltages across the full SOC range.

The EstimateSOC subsystem operates at a 1-second update period. The initial SOC estimate is 0.5 (50%), and the algorithm bounds the output to the range [0.0, 1.0].

The SOC estimate tracks the battery state as the Simscape Battery model charges and discharges. The Coulomb counting method integrates current over time to track charge consumed or added to the pack.

This example uses Coulomb counting with OCV correction. For a more advanced estimator, such as an extended Kalman filter, see the Battery State-of-Charge Estimation example (Simscape Battery). To compare different estimation techniques, see Explore Techniques to Estimate Battery State of Charge.

SOC Estimation Method

The EstimateSOC subsystem uses a variant selection (SOC_Algorithm in c2000BMSData.m) to choose between two estimation techniques. Only one is active at a time.

  • Coulomb Counting (SOC_Algorithm = 1, default) — Integrates current over time to track charge flow. Uses the SOC Estimator (Coulomb Counting) block from the Simscape Battery library. Requires a current measurement (Ibat).

  • Voltage Lookup Table (SOC_Algorithm = 2) — Maps pack voltage to SOC through a discharge curve (OCV table) defined in c2000BMSData.m. For example, a cell at 3.65 V corresponds to approximately 50% SOC. Does not require a current measurement but is accurate only at rest (open-circuit conditions).

Note: The BQ79718B-Q1 does not have an integrated current sense amplifier (CURRENT registers read 0). To use Coulomb counting on hardware, connect an external current sensor. Without one, use the voltage lookup table variant. The BQ79758-Q1 (an AFE with integrated current sensing) is an alternative that supports Coulomb counting without an external sensor.

Connect Hardware

Single Device (18S)

To prepare the hardware for deployment, connect the BQ79718EVM to the LaunchPad and apply power. Connect the DC voltage source to the EVM BATT+ and BATT− terminals to simulate the battery stack.

Close-up photo showing jumper wires connecting the LaunchPad J5 header pins (GPIO14 and GPIO15) to the BQ79718EVM J12 UART connector, with a ground wire between GND pins on both boards.

Daisy Chain (36S)

For daisy-chain operation, connect two BQ79718EVMs. The MCU communicates with the base EVM (dev0), which relays commands to the stack EVM (dev1) via the COMH-to-COML link.

MCU to Base EVM (dev0)

MCU Pin

EVM Pin

Signal

J5-44/45 (GPIO56)

J12 Pin 7

MCU TX → EVM RX

J5-43 (GPIO15)

J12 Pin 8

EVM TX → MCU RX

GND

J12 GND

Common ground

Daisy-Chain Link (Base to Stack)

Base EVM Pin

Stack EVM Pin

Signal

J4 COMH TX

J3 COML RX

Data uplink

J4 COMH RX

J3 COML TX

Data downlink

Base EVM (dev0) Jumper Settings

Jumper

Setting

J7, J8, J9

Installed (UART isolator)

J10

Installed (COMH enabled for daisy chain)

J21, J23, S1-S3

Installed

Stack EVM (dev1) Jumper Settings

Jumper

Setting

J7, J8, J9

Removed (no MCU connection)

J10

Removed (topmost device)

J21, J23, S1-S3

Installed

For EVM jumper settings, contact TI for EVM user guide. For LaunchPad header pin outs, see the LAUNCHXL-F28P55x Quick Start Guide on the TI website.

Cell Voltage Monitoring Pipeline

The model implements a six-step data pipeline that periodically reads cell voltages from the AFE (18 per device):

Step

Component

Action

1

SendCommand

Constructs a single-read request to VCELL registers (0x0574), appends CRC-16-IBM checksum, transmits via SCIB TX

2

SCIB RX ISR

SCIB interrupt fires after 5 bytes arrive (FIFO interrupt level = 5)

3

MW_dataBuffer.c

Accumulates 5-byte chunks into a 50-byte (18S) or 100-byte (36S) ring buffer; returns data-ready flag when full

4

SCI Receive with Buffer

Detects data-ready flag and passes the complete frame to downstream processing

5

ReadCellVoltages

Unpacks data bytes into uint16 cell voltages from HI/LO pairs; computes pack voltage

6

EstimateSOC

Estimates SOC using OCV correction and Coulomb counting

Each BQ797x device replies to a Single-Device Read with a fixed 50-byte frame. The trailing padding byte keeps the frame size a multiple of the SCI FIFO interrupt level (5 bytes), so RX interrupts always fire on whole-frame boundaries.

Offset

Bytes

Field

1

1

Init

2

1

Device address

3–4

2

Register address (HI, LO)

5–40

36

VCELL data (18 cells × 2 bytes)

41–42

2

Vcell_actual_sum

43–44

2

VBAT

45–47

3

CURRENT (24-bit signed)

48–49

2

CRC-16

50

1

Padding

For a single device (18S), the receive buffer is 50 bytes — one frame.

For the daisy-chain configuration (36S, two devices), the buffer is 100 bytes: device 0's frame occupies bytes 1–50 and device 1's frame occupies bytes 51–100. The ring buffer notifies the model when the first 50 bytes arrive so it can trigger the second device's read; the full 100 bytes then complete the response and are handed to the decoder.

Single Device Initialization Sequence

Step

Command

Description

1

GPIO56 wake pulse

4 ms LOW pulse to wake the base device from SHUTDOWN

2

ADC_CTRL2

Start continuous ADC conversion (0x0D) on both devices

Daisy-Chain Initialization Sequence

c2000BMSDaisyChainModel uses a multi-step initialization for two devices:

Step

Command

Description

1

GPIO56 wake pulse

4 ms LOW pulse to wake the base device from SHUTDOWN

2

SEND_WAKE (dev0)

Dev0 forwards wake to dev1 via COMH daisy-chain link

3

CONTROL1 (directed write)

Enable daisy-chain communication on all devices

4

DIR0_ADDR (directed write)

Auto-address: assign address 0 to base, 1 to stack

5

TOP_STACK (dev1)

Mark dev1 as the topmost device in the chain

6

ACTIVE_CELL (both)

Configure 18S mode on both devices

7

ADC_CTRL2 (both)

Start continuous ADC conversion (0x0D) on both devices

The MCU connects only to the base device (dev0). The stack device (dev1) is reached through the COMH-to-COML daisy-chain link. The J10 jumper on the base EVM must be installed to enable the COMH uplink.

Communication Protocol

The BQ79718B-Q1 uses a proprietary UART protocol at 1 Mbps:

  • CRC-16-IBM — Polynomial 0x8005, init 0xFFFF, reflected I/O. Implemented in generateChecksum.m (MATLAB) and in C init code.

  • Single Read (0x80) — Requests N registers starting from a specified address.

  • Single Write (0x90) — Writes one register on a specified device.

  • Directed Write (0xD0) — Broadcasts a write for auto-addressing (daisy chain).

  • Response frame format (per device):

[InitByte][DevAddr][RegAddr_HI][RegAddr_LO][Data...][CRC_LO][CRC_HI]

1 byte 1 byte 1 byte 1 byte N bytes 1 byte 1 byte

Custom C Code Integration

The model integrates custom C code, provided with this example, for UART data buffering:

  • MW_dataBuffer.c and MW_dataBuffer.h — Ring buffer that accumulates SCI FIFO data into complete response frames. Supports both single-device (50 bytes) and daisy-chain (100 bytes) modes.

  • generateChecksum.m — CRC-16-IBM reference implementation for validating UART frames in MATLAB.

These files reside in the components/ folder. The model includes them via the CustomSource and CustomHeaderCode parameters.

Generate and Deploy Code to Target Hardware

Simulink generates C code from the model and deploys it to the LaunchPad over USB.

  1. To confirm algorithm behavior before deploying, simulate the target model (c2000BMSSingleDeviceModel or c2000BMSDaisyChainModel). If you have not already done so, on the Simulation tab, click Run.

  2. To prepare for deployment, complete hardware connections between the LaunchPad and the BQ79718EVM as described in Connect Hardware.

  3. To configure for your hardware, open the target model. If your hardware uses a different SCIB channel or baud rate, on the Modeling tab, click Model Settings. In the Configuration Parameters dialog box, navigate to Hardware Implementation > Target hardware resources > SCI_B, and update the Baud rate parameter. The default is 1000000 (1 Mbps).

  4. To generate code and deploy to the LaunchPad, on the Hardware tab, click Build, Deploy & Start.

Verify Deployment on Hardware

To open the host model, click the hyperlink in the target model or run one of the following commands:

% open_system("c2000BMSSingleDeviceHostModel")  %18S
% open_system("c2000BMSDaisyChainHostModel")    %36S
  1. To connect to the target hardware, set the COM port parameter in the host model Serial Receive and Serial Transmit blocks to match the port assigned to your LaunchPad. To find the COM port, open Windows Device Manager and look under Ports (COM & LPT) for the entry labeled "XDS110 Class Application/User UART."

  2. To start receiving data from the target, on the Simulation tab, click Run.

  3. Verify that cell voltages appear in the 3.5–4.2 V range per cell in the Display blocks. SOC estimates update at 1-second intervals. If values show 0 or NaN, check UART wiring and baud rate settings.

Next Steps

After you deploy the BMS cell monitor, you can:

  • Add an external current sensor to enable Coulomb counting alongside the OCV lookup, improving SOC accuracy under dynamic load.

  • Implement an extended Kalman filter for SOC estimation to reduce drift during sustained charge-discharge cycles.

  • Add cell balancing logic to equalize voltages across the pack, extending pack life by preventing individual cells from reaching cutoff limits.

  • Extend the CAN interface to report cell-level diagnostics to a vehicle network for fleet-level monitoring.

See Also

Related Examples

Concepts

Copyright © 2026 The MathWorks, Inc.