You are on page 1of 10

11/21/2022

0
PROJECT

 Practical Phase

 Summary
The aim of this phase of the work is to design and implement a charger for a 12.8 V- lithium-ion battery and
monitor and control the output voltage and current of the charger.
 To design the charger, the following steps have been done:
 To charge and discharge the lithium-ion battery, we used two Boost and Buck converters. The output
voltage and current of the Boost and Buck converters are observed and controlled via Arduino.
o Elements used to setup the charger are as follows:
 Buck converter (Q48SC12042 500W DC/DC Power Module)
 Boost Converter (QSB30024S48 – DC/DC Converter)
 Arduino Board (MEGA 2560)
 Fuses, Capacitors, Resistors, and Schottky diode for the connections between lithium-ion battery,
Buck – Boost converts and Arduino (To find the values of these elements, please refer to the data
sheets)
 In the first step, according to the data sheets, we established a circuit as shown in the below figure
to drive the Buck converter and make sure it works properly.

 In the second step, to establish the communication with the Buck converter, we used the Arduino
board (MEGA 2560) and I2C protocol, since the Buck converter support Power Management Bus
(PMBus). The Power Management Bus (PMBus) is a variant of the System Management
Bus (SMBus) which is targeted at digital management of power supplies. Like SMBus, it is a
relatively slow speed two wire communications protocol based on I2C. Unlike either of those
standards, it defines a substantial number of domain-specific commands rather than just saying how
to communicate using commands defined by the reader.
 Note 1: Please, carefully read Power System Management Protocol Specification to understand
how to send and read data.

1
 In the final step, we integrated Buck converter (Delta Q48SC12042 500W DC/DC Power
Module) with Arduino using SMBus Communication.
 Note 2: The process should be according to the PMBus specification:
 PMBus_SPEC:
• The host sends the PMBus device’s seven bit address plus Bit 0 equal to zero.
• The slave device ACKs.
• The host sends the command code for VOUT_OV_FAULT_LIMIT.
• The slave device ACKs.
• The host device sends a Repeated START Condition, the PMBus device’s seven bit address
plus Bit 0 equal to one (indicating a read).
• The slave device ACKS and transmits the lower byte of the two data bytes.
• The host ACKS.
• The slave device ACKS and transmits the upper byte of the two data bytes.
• The host does not acknowledge (NACKS) and sends a STOP Condition. This ends the
transaction. However, I explain in detail the process of SMBus Communication for Changing
Vout (Over Voltage Protection (OVP) & Over Current Protection (OCP)), which I did as follows:

 Step 1: Unlock PMBUS write protection


 Write Byte with PEC,Command:0x10 Data:0x00

 Let’s take address 127 as an example:


o First, we need to convert 127 (decimal) address to 7F (Hexadecimal).
o Second, we need to know the PEC value. For this purpose, we must calculate a CRC-8 value,
which is calculated by CRC online calculation tools. CRC calculation online tool.
o Now, we can send the command to unlock the module like below picture.

 Note 3: Calculated CRC value is PEC byte.


 Note 4: To calculate the CRC value, you need to change the slave address (7bit) to 8bit, and for
this purpose I put a link here to convert it online. To convert 7bit to 8bit.
 Note 5: To calculate the CRC value, you need to put the hexadecimal data (the whole command
data) into the online tool, which I put its link above.

 Step 2. VOUT OVP setpoint can be modified by command: 0x40. The data format is
PMBUS VOUT MODE format described in the data sheet.

 For example, if VOUT OVP setpoint is modified to 14.0V.


o a). Command: 0x21
o b). 14.0 should be changed to 0xE000 (14.0 * 2^12) in PMBUS VOUT MODE format.
o c). Byte#0:0x00 Byte#1:0xE0 should be sent.

2
 Note 6: PMBus Data Format
o The module receives and reports data in LINEAR format. The Exponent of the data
words is fixed at a reasonable value for the command; altering the exponent is not
supported. DIRECT format is not supported by the module.
o For commands that set or report any voltage thresholds related to the output voltage,
the module supports the linear data format consisting of a two-byte value with a 16-
bit, unsigned mantissa, and a fixed exponent of -12. The format of the two data bytes
is shown below:

o The equation can be written as:


Vout = Mantissa * 2(-12)
 For example, considering set Vout to 12V by VOUT_COMMAND, the
read/write data can be calculated refer to below process:
Mantissa =Vout/2(-12) = 12/2(-12) =49152;
Converter the calculated Mantissa to hexadecimal (0xC000).

 Step 3. Set VOUT_OV_WARN by command: 0x42.The data format is PMBUS VOUT


MODE format described in the data sheet.
 For example, Set VOUT_OV_WARN to 13.2V.
o a). Command: 0x42
o b). 13.2 should be changed to 0xD333(13.2 * 2^12) in PMBUS VOUT MODE format.
o c). Byte#0:0x33 Byte#1:0xD3 should be sent.

 Step 4. Set IOUT_OC_FAULT_LIMIT by command: 0x46.The data format is PMBUS


Linear format described in the data sheet.
 For example, Set IOUT_OC_FAULT_LIMIT to 33A.
o a). Command: 0x46
o b). 33A should be converted to 0xE210 (refer to below calculation process) in PMBUS
Linear format.
o c). Byte#0:0x10 Byte#1:0xE2 should be sent.

Calculation Process:
Get the exponent of Iout, -4; whose binary is 11100
Mantissa =Iout/2(-4)=33/2(-4)=528;
Converter the calculated Mantissa to hexadecimal
210, then converter to binary
010 0001 0000; Combine the exponent and the
mantissa, 11100 and 010 0001 0000;
Converter binary 1110 0010 0001 0000 to
hexadecimal E210.
3
 Note 7: PMBus Data Format
o For commands that set or report all other thresholds, including input voltages, output
current, temperature, time and frequency, the supported linear data format is a two-
byte value with: an 11-bit, two’s complement mantissa, and a 5-bit, two’s
complement exponent (scaling factor). The format of the two data bytes is shown as
in below.

 Step 5. Command 0xEC should be sent to unlock the MCU which save the data.
 Command: 0xEC
 Byte Count = N: 4
 Byte #0~Byte#3: 7E,15, DC,42.
o The detail Command is as follows.

 Let’s take address 127 as an example:

 Step 6. Command 0x11 should be sent to save the Vout setpoint in the MCU. The detail
Command is as follows.

 Byte #0: 0x11

 Step 7. Repower on module and check if data has been written successfully.

Vout OVP can be read by command:0x40.


VOUT_OV_WARN can be read by command 0x42
IOUT_OC_FAULT can be read by command 0x46

4
Byte #0, Byte #1 and PEC is sent by our MCU.
Data return from MCU is in Vout Mode format: (Byte #1<<8) + (Byte #0)

 Note 8: Be careful, PEC value should be calculated to send commands in step 1 to step 6. It
is not optional.
 Note 9: The output data of the module are in a linear format, so to convert them to actual
number first you need to use the mentioned equation in the Note 6 to convert Mantissa to
hexadecimal, then to convert hexadecimal to actual number you can use the Excel sheet,
which I have added to this document.

 SMBus packet element keys are shown in the below picture.

 Note 8: After every received 8 bits the Slave Device (SD) should issue ACK or NACK.
When a Master Device (MD) initiates communication, it first sends the address of the slave
and only the SD which recognizes the address will ACK, the rest will remain silent. In case
the SD NACKs one of the bytes, the MD should stop the communication and repeat the
message. A NACK could be received after the PEC. This means that there is an error in the
received message and the MD should try sending the message again. The PEC calculation
includes all bits except the START, REPEATED START, STOP, ACK, and NACK bits.
The PEC is a CRC-8 with polynomial X8+X2+X1+1. The Most Significant Bit of every
byte is transferred first.

 The entire Arduino code to modify the output voltage of the converter and monitor the output
voltage and current of the converter is as follows:

#include <Wire.h>

void setup() {

5
Wire.begin(); // join i2c bus (address optional for master)

Serial.begin(9600); // start serial communication at 9600bps


}

uint16_t msb = 0;
uint8_t lsb = 0;
uint16_t V_out = 0;
uint16_t I_out = 0;

void loop() {

// step 1: Unlock PMBUS write protection

Wire.beginTransmission(0x38); // transmit to device(0x38)

Wire.write(0x10); // sets register pointer to the command register (0x10)

Wire.write(0x00); // sends Data:0x00

Wire.write(0x30); // PEC

Wire.endTransmission(); // stop transmitting

delay(50);

// step 2: VOUT setpoint

Wire.beginTransmission(0x38); // transmit to device(0x38)

Wire.write(0x21); // sets register pointer to the command register(0x21)

Wire.write(0x66); //sends Byte#0:0x66 to the command register (0x21)

Wire.write(0xC6); //sends Byte#1:0xC6 to the command register (0x21)

Wire.write(0x73); // PEC

Wire.endTransmission(); // stop transmitting

delay(50);

// step 3: Set VOUT_OV_WARN

Wire.beginTransmission(0x38); // transmit to device(0x38)

Wire.write(0x42); // sets register pointer to the command register(0x42)

Wire.write(0x33); //sends Byte#0:0x33 to the command register (0x42)


6
Wire.write(0xD3); //sends Byte#1:0xD3 to the command register (0x42)

Wire.write(0x93); // PEC

delay(50);

//Step 4. Set IOUT_OC_FAULT_LIMIT by command: 0x46.

Wire.beginTransmission(0x38); // transmit to device(0x38)

Wire.write(0x46); // sets register pointer to the command register(0x46)

Wire.write(0x10); //sends Byte#0:0x10 to the command register (0x46)

Wire.write(0xE2); //sends Byte#1:0xE2 to the command register (0x46)

Wire.write(0x3E); // PEC

delay(50);

// step 5: Command 0xEC should be sent to unlock the MCU which save the data.

Wire.beginTransmission(0x38); // transmit to device(0x38)

Wire.write(0xEC); //sets register pointer to the command register(0xEC)

Wire.write(0x04); //sends Byte count:N:4(0x04) to the command register (0xEC)

Wire.write((byte)0x7E); //sends Byte#0:0x7E to the command register (0xEC)

Wire.write((byte)0x15); //sends Byte#1:0x15 to the command register (0xEC)

Wire.write((byte)0xDC); //sends Byte#2:0xDC to the command register (0xEC)

Wire.write((byte)0x42); //sends Byte#3:0x42 to the command register (0xEC)

Wire.write(0xE9); // PEC

Wire.endTransmission(); // stop transmitting

delay(50);

//step 6: Command 0x11 should be sent to save the Vout setpoint in the MCU

Wire.beginTransmission(0x38); // transmit to device(0x38)

Wire.write(0x11); //sets register pointer to the command register(0x11)

Wire.endTransmission(); // stop transmitting

7
delay(50);

// step 7: request reading Vout setpoint from the Buck Converter

Wire.beginTransmission(0x38); // transmit to device(0x38)

Wire.write(0x8B); //sets register pointer to the command register(0x21)

Wire.endTransmission(false); // stop transmitting

// request 2 bytes from peripheral device #0x38

// step 8: receive reading from the Buck Converter

if (Wire.requestFrom(0x38, 2) == 2) { // if two bytes were received

uint16_t msb = Wire.read(); // receive high byte (overwrites previous reading)

msb = msb << 8; // shift high byte to be high 8 bits

uint8_t lsb = Wire.read(); // receive low byte as lower 8 bits

uint16_t V_out = msb | lsb;

Serial.print(" V_out = ");


Serial.print(V_out, HEX); // print the reading
Serial.println(" V");

Wire.beginTransmission(0x38); // transmit to device(0x38)

Wire.write(0x8C); //sets register pointer to the command register(0x21)

Wire.endTransmission(false); // stop transmitting

if (Wire.requestFrom(0x38, 2) == 2) { // if two bytes were received

uint16_t msb = Wire.read(); // receive high byte (overwrites previous reading)

msb = msb << 8; // shift high byte to be high 8 bits

uint8_t lsb = Wire.read(); // receive low byte as lower 8 bits

uint16_t I_out = msb | lsb;

Serial.print(" I_out = ");


Serial.print(I_out, HEX); // print the reading
8
Serial.println(" A");

delay(500); // wait a bit since people have to read the output :)


}
}

You might also like