/
6S Power Module

6S Power Module

Project repo: GitHub - UWARG/efs-can-power-module: WARG 6s power module firmware with DroneCAN interface supported

Table of Contents

Specifications (from the EE Team)

Overall Hardware Architecture

Taken from https://uwarg-docs.atlassian.net/wiki/x/AoCsmQ

Background

The drone uses a battery pack containing 12 cells, where 2 groups of 6 cells are each connected in series (hence 6S).

Each group of 6 cells is connected to a battery monitoring circuit (shortened as BMC later).

This circuit measures:

  • The voltage of each cell

  • The current delivered by the group

    • This is done by forcing the battery to deliver current through a resistor with a tiny resistance. This resistor, called a shunt/shunt resistor, follows Ohmโ€™s law: V=IR

    • This implies that I=V/R, which means that the current passing through a shunt is equal to its voltage (which can be measured easily), divided by its resistance (which is a known constant).

And it sends:

We are not exactly sure of everything yet.

  • Battery-related information relating to the voltages and currents

  • The voltage and current information are sent as 2 analog signals, which our microcontroller converts to digital ones via an Analog-to-Digital Converter (ADC).

  • Some other information is sent via the I2C protocol

Description

  • MCU (STM32xX) in the top right is the microcontroller that we are writing the code to

  • Its job is to translate the messages it receives from the BQ76925 6s LiPo Battery Monitor boards and send the corresponding messages to the flight controller (FC) using the CAN protocol

    • The flight controller we are using is a Pixhawk 4, which runs the Ardupilot firmware

    • Because battery voltages and currents will change over time, the โ€œtranslationโ€ is continuous

The FC needs this information to make other decisions, e.g. if a part is consuming too much power, or when to land

Specific Hardware Information

Taken from https://uwarg-docs.atlassian.net/wiki/x/HYBXq

308fff19-3cb7-4e74-b29c-ef6484d78e5b-0000.png
MCU Schematics

The ports we are interested in:

  • PA9: SCL_1, Serial Clock line for I2C 1, to configure BMC 1

  • PA10: SDA_1, Serial Data line for I2C 1, to configure BMC 1

  • PA7: SCL_2, Serial Clock line for I2C 2, to configure BMC 2

  • PB4: SDA_2, Serial Data line for I2C 2, to configure BMC 2

  • PA12: CAN_TX, Transmit line for CAN

  • PA11: CAN_RX, Receive line for CAN

  • PA3: OVERCURRENT, receives 5.5 V when an overcurrent occurs, and 0 V otherwise

  • PA4: VIOUT_FILT, receives 0.25-1.25 V (REF_SEL=0) / 0.5-2.5 V (REF_SEL=1), representing the cell current for cells 1-6, as measured by a 1-milliohm shunt

  • PA5: VCOUT1_FILT, receives 1.47-1.53 V (REF_SEL=0) / 2.94-3.06 V (REF_SEL=1), representing the cell voltages for cells 1-6

  • PB0: ADC1_FILT, receives VREF, the ADC reference voltage

  • PB1: VCOUT2_FILT, receives 1.47-1.53 V (REF_SEL=0) / 2.94-3.06 V (REF_SEL=1), representing the cell voltages for cells 7-12

  • PA2: ADC2_FILT, receives VREF, the ADC reference voltage


ย Current Roadblocks

Libcanard has a high learning curve. Neither the DroneCAN website nor the Libcanard repo has beginner-friendly tutorials. YouTube videos also wonโ€™t help directly

Tasks Break Down:

Action Items

Initialize the Battery Monitoring Circuit using I2C
Read battery data using the specified ports
Fix suspected I2C timing issue during communication to the BMC

ย Milestones

Understand project specifications
Understand the I2C protocol
Understand the CAN protocol
Understand DroneCAN
etc.

Open Questions


ย Reference materials

Relevant protocols

Project Resources

Analog-to-Digital Converter (ADC) Explained

There are many physical quantitles in the world that we may want to measure, such as voltage, current, or temperature. These are analog quantities, which means that can change continuously and have infinitely many values (*).

Technically, quantum mechanics tells us that some quantities we think of as continuous are actually discrete, with extremely tiny but finitely tiny steps, called โ€œquantaโ€œ. In the context of WARG, these effects are negligible.

In WARG EFS, we work with microcontrollers quite regularly. They use digital signals to work, which means it works with a finite set of numbers; in particular, they use something like 0 V to represent a logic โ€˜0', and 5 V to represent a logic โ€˜1โ€™. By doing math with these โ€˜0โ€™ and '1โ€™ signals, we can program the microcontrollers to do anything we want.

An Analog-to-Digital Converter (ADC)'s job is to connect between these two worlds.

Specifically, it converts an analog voltage into a digital signal that the microcontroller can understand.

Reference Voltage

Thereโ€™s just one issue: voltages have a basically infinite range, but our ADC has a finite range. Therefore, we have to tell the ADC what voltage range it should expect. By convention, the lowest voltage an ADC can understand is usually 0 V.

On the other hand, you can specify the highest voltage it should expect.

This is the so-called ADC reference voltage.

Some ADCs can measure both positive and negative voltages. In these boards, it may require multiple reference voltages, or it may set the lower range to be a function of the higher range.

Counting and Resolution

Now our ADC is ready to do its job. To make its output easy to understand, the output of an ADC is directly proportional to its voltage input.

For example, an ADC may be told to sense an input voltage from 0-8 V into a natural number from 0 to 31. This would mean that an input of 4.25 V will correspond to a number of around 16.

To put this into jargon, since there are 32 numbers between 0 and 31, and 32 is 2 to the 5th power, we say that the ADCโ€™s resolution is 5 bits, and it counted a value of 16.

An ADCโ€™s resolution is the number of bits that are used to represent its outputs,
and its count is the number itโ€™s currently giving.

Battery Monitoring Circuit

Datasheet: BQ76925

Addressing

All I2C addresses are calculated using the formula

ADDRESS = 0x20 + REG_ADDR

Where ADDRESS is the real address to read/write to, and REG_ADDR is the register address mentioned on the datasheet, from 0x00 to 0x1F.
Remember this distinction between the real and register addresses. All I2C addresses you see after this point will be register addresses.

Source: Datasheet, 8.5.1.1 I2C Addressing

Selecting the cell for the VCOUT pin

To select the cell to measure the voltage of:

// Write to the register address: REG_ADDR = 0x01 // With data: DATA = 0x10 + CELL

Where CELL is the cell number. CELL=0x0 refers to cell 1, CELL=0x1 refers to cell 2, and so on, up to CELL=0x5referring to cell 6.

Source: Datasheet, 8.6.1 Register Descriptions (Tables 6 to 8)

Reference voltage selection

// Write to the register address: REG_ADDR = 0x04 // With data: DATA = REF_SEL

Where REF_SEL can be set to 0 or 1, with the following effects on the BMC pins:

Table 14. Reference Voltage Selection

REF_SEL

VREF (V)

VCOUT Gain (V)

VIOUT Voltage Range (V)

REF_SEL

VREF (V)

VCOUT Gain (V)

VIOUT Voltage Range (V)

0

1.5

0.3

0.25 - 1.25

1

3.0

0.6

0.5 - 2.5

Yes, itโ€™s true that you could also enable CRC with this memory address. To do that, add 0x80 to DATA above.

We havenโ€™t decided whether we want CRC though, so right now weโ€™ll use the default optionโ€ฆ which is โ€œdisabledโ€œ.

Source: Datasheet, 8.6.1 Register Descriptions (Tables 13 and 14)

Cell Voltage Monitoring

// The voltage of the currently selected cell, VCn, // is calculated with the following formula: VCn = ((VCOUT * GC_VREF + OC_VCOUT) / G_VCOUT) * (1 + GC_VCOUT) // Where: VCOUT = ADC_count / Full_scale_count * VREF_NOMINAL // This is the voltage of the VCOUT pin, as measured by the MCU GC_VCOUT = ((VCn_GC_4 << 4) + VCn_GAIN_CORR) * 1E-3 OC_VCOUT = ((VCn_OC_4 << 4) + VCn_OFFSET_CORR) * 1E-3 GC_VREF = (1 + ((VREF_GC_4 << 4) + VREF_GAIN_CORR) * 1E-3) + (((VREF_OC_5 << 5) + (VREF_OC_4 << 4) + VREF_OFFSET_CORR) * 1E-3)/VREF_NOMINAL

Several values can be accessed through the I2C interface:

  • VC1_GC_4

    • I2C register address: 0x17

    • Data bit location: 6

  • VC2_GC_4

    • I2C register address: 0x17

    • Data bit location: 4

  • VC3_GC_4

    • I2C register address: 0x18

    • Data bit location: 6

  • VC4_GC_4

    • I2C register address: 0x18

    • Data bit location: 4

  • VC5_GC_4

    • I2C register address: 0x18

    • Data bit location: 2

  • VC6_GC_4

    • I2C register address: 0x18

    • Data bit location: 0

  • VC1_OC_4

    • I2C register address: 0x17

    • Data bit location: 7

  • VC2_OC_4

    • I2C register address: 0x17

    • Data bit location: 5

  • VC3_OC_4

    • I2C register address: 0x18

    • Data bit location: 7

  • VC4_OC_4

    • I2C register address: 0x18

    • Data bit location: 5

  • VC5_OC_4

    • I2C register address: 0x18

    • Data bit location: 3

  • VC6_OC_4

    • I2C register address: 0x18

    • Data bit location: 1

VC1_OFFSET_CORR

  • I2C register address: 0x11

  • Data bit locations: 7 to 4

  • VC2_OFFSET_CORR

    • I2C register address: 0x12

    • Data bit locations: 7 to 4

  • VC3_OFFSET_CORR

    • I2C register address: 0x13

    • Data bit locations: 7 to 4

  • VC4_OFFSET_CORR

    • I2C register address: 0x14

    • Data bit locations: 7 to 4

  • VC5_OFFSET_CORR

    • I2C register address: 0x15

    • Data bit locations: 7 to 4

  • VC6_OFFSET_CORR

    • I2C register address: 0x16

    • Data bit locations: 7 to 4

  • VC1_GAIN_CORR

    • I2C register address: 0x11

    • Data bit locations: 3 to 0

  • VC2_GAIN_CORR

    • I2C register address: 0x12

    • Data bit locations: 3 to 0

  • VC3_GAIN_CORR

    • I2C register address: 0x13

    • Data bit locations: 3 to 0

  • VC4_GAIN_CORR

    • I2C register address: 0x14

    • Data bit locations: 3 to 0

  • VC5_GAIN_CORR

    • I2C register address: 0x15

    • Data bit locations: 3 to 0

  • VC6_GAIN_CORR

    • I2C register address: 0x16

    • Data bit locations: 3 to 0

  • VREF_OC_5

    • I2C register address: 0x1b

    • Data bit location: 2

  • VREF_OC_4

    • I2C register address: 0x1b

    • Data bit location: 1

  • VREF_GC_4

    • I2C register address: 0x1b

    • Data bit location: 0

Source: Datasheet, 8.3.2.2 Cell Voltage Monitoring

BMC Temperature monitoring

The internal temperature of the battery management circuit can be monitored. To do that, configure the VCOUT pin to output that temperature:

// Write to the register address: REG_ADDR = 0x01 // With data: DATA = 0x16

Then, the temperature can be deduced as follows:

// TEMP: temperature (degrees C) // V: voltage measured at the VCOUT pin (mV) TEMP = 5/22 * (V - 1090)

Note that TEMP has an uncertainty of plus/minus 7/22 โ‰ˆ 0.227 ยฐC.

Also note that TEMP will be between -25 to 85 ยฐC in normal operating conditions, which corresponds to 980 to 1464 mV.

These are visualized in the Desmos graph below.

Not with the board that we have now. Monitoring that requires connecting the BMC to an external thermister network, which the EE team didnโ€™t include.

Sources: Datasheet, 8.3.2.5.1 Internal Temperature Monitoring;
Datasheet, 7.12 Internal Temperature Measurement

Up-to-date electrical schematics from the EE team

Project 6s Power Module (Ask the EE team for access)

Oftentimes youโ€™ll want to connect to the board to download a program. Hereโ€™s how youโ€™ll find how to wire your connector, in case you forgot:

find_pins.gif
How to find programmer pins on the Altium design file

Receiving incoming messages (Polling/Interrupt/DMA)

We are going to receive messages from an external device (the BMC), but we canโ€™t predict when we will receive them. There are 3 solutions to this:

  • Polling: repeatedly checking whether a message was received using a loop. If a message gets detected, it gets processed, then the loop continues. This is a purely software solution.

    • Advantages:

      • Very easy to implement

      • You donโ€™t need to worry about race conditions (when multiple pieces of code unintentionally access and modify some variable at the same time)

    • Disadvantages:

      • Extremely inefficient. The loop eats up most of the microcontrollerโ€™s computational resources, which it needs for many other tasks.

  • Interrupt: when a message gets received, it triggers a hardware interrupt. This causes all other processes to stop. Then the message gets processed, and the other processes resume after that. STM32 microcontrollers support many internal interrupts (for common events like receiving an I2C message), and external interrupts (triggered by a GPIO pin).

    • Advantages:

      • More efficient than polling

    • Disadvantages:

      • You need to be careful about race conditions

      • Still needs the microcontroller for data reception

  • Direct Memory Access (DMA): Similar to an interrupt, except the peripheral writes its message directly to the microcontrollerโ€™s memory. Then it signals the microcontroller that a new message came.

    • Advantages:

      • Most efficient for large messages

    • Disadvantages:

      • You need to be careful about race conditions

      • Less efficient than regular interrupts for small messages

ย 

Related content