Beruflich Dokumente
Kultur Dokumente
Battery 1:
Battery 2:
Therefore, R
total
= 120 m + 90 m = 210 m.
Maximum voltage tested = 4.045 Volts.
= 19.262 A.
Therefore, MOSFET saturation current >> 19.262 A.
F
i
g
u
r
e
9
:
S
c
h
e
m
a
t
i
c
D
i
a
g
r
a
m
o
f
t
h
e
S
i
m
u
l
a
t
e
d
C
i
r
c
u
i
t
Figure 10: Actual Implementation of the Circuit Version 1
Figure 11: Actual Implementation of the Circuit Version 2
I2C Communications:
The data of the voltage and temperature of the battery are being collected by converting their
analog data into digital by the Analog-to-Digital Conversion of the pic. As soon as the data is
collected, the pic connected to the battery, which is called Slave, will send it to another pic,
called Master, using Inter-Integrated Circuit or commonly known as I2C. The Master will begin
by sending a start bit followed by SSPADD. The SSPADD determines the address of the slave
and whether the Master wants to Read from or Write to the Slave. If the address sent by the
master is equal to the slave, an acknowledgement will be sent by the Slave. Then, the data will
be sent by the slave. When the data is sent, the Master will now send an acknowledgement to the
Slave for it to know that the data was accepted. A stop bit will also be sent by the master to end
the transmission.
I2C Slave Code:
/*
* File: i2cSlave_pic16f1823.c
* Author: carlo
*
* Created on March 1, 2014, 3:09 PM
*/
#include <stdio.h>
#include <stdlib.h>
#include <xc.h>
#include <pic16f1823.h>
/*
#pragma config FOSC = INTOSC
#pragma config PWRTE = ON
#pragma config LVP = OFF
#pragma config WDTE = OFF
#pragma config CP = OFF
*/
__CONFIG (FOSC_INTOSC & WDTE_SWDTEN & PWRTE_ON & MCLRE_ON & CP_OFF &
CPD_OFF & BOREN_OFF & CLKOUTEN_OFF & IESO_OFF);
__CONFIG (FCMEN_OFF & WRT_OFF & PLLEN_OFF & STVREN_OFF & LVP_OFF );
#define ADDRESS_I2C 0x30
/*
*
*/
unsigned char dummy;
void interrupt isr();
main(){
// initialization
// internal oscillator
//set to 8MHz
IRCF3 = 1;
IRCF2 = 1;
IRCF1 = 1;
IRCF0 = 0;
//set system clock select bits to internal osc
SCS1 = 1;
SCS0 = 0;
// i2c slave init
TRISC = 0x03; // Make i2c pins input
SSP1CON1 = 0b00110110; // Enable MSSP module as I2C slave w/
7bit addr
SSP1CON3bits.SDAHT = 1; // 300ns hold time on SDA after SCL
falling edge
SSP1CON3bits.AHEN = 1; // Address Hold Enable
SSP1ADD = (ADDRESS_I2C<<1); // Slave Address
GIE = 1;
PEIE = 1;
SSP1IE = 1; // Enable interrupts
SSP1IF = 0;
TRISA = 0;
//SSP1MSK = 0xFE;
while(1);
}
void interrupt isr(){
if(SSP1IF){
if(1){
// State 1: Write operation, last byte was an address
if(!R_nW && !D_nA && BF){
SSP1IF = 0;
dummy = SSP1BUF;
//I2C_var1 = 0;
CKP = 1;
}
// State 2: Write operation, last byte was an data
else if(!R_nW && D_nA && BF){
SSP1IF = 0;
//I2C_receiveArray[I2C_var1++] = SSP1BUF;
CKP = 1;
}
// State 3: Read operation, last byte was an address
else if(R_nW && !D_nA){
SSP1IF = 0;
dummy = SSP1BUF;
//I2C_var2 = 0;
SSP1BUF = 0x04;
CKP = 1;
}
// State 4: Read operation, last byte was an data
else if(R_nW && D_nA && !BF){
// RC4 = 0;
SSP1IF = 0;
SSP1BUF = 0x01;
CKP = 1;
}
// State 5: Slave I2C logic reset by NACK from master
else if(D_nA && !BF && CKP){
}
}
}
}
I2C Master Code:
/*
* File: i2cMaster.c
* Author: carlo
*
* Created on February 25, 2014, 8:44 PM
*/
#include <stdio.h>
#include <stdlib.h>
#include <pic16f877a.h>
#include <xc.h>
#pragma config FOSC = HS
#pragma config PWRTE = ON
#pragma config LVP = OFF
#pragma config WDTE = OFF
#pragma config CP = OFF
#define _XTAL_FREQ 16000000
#define CLOCKSPEED 1000
#define BAUDRATE 19200
#define CTRLIN 0XA0 // Control In Byte
configures the EEPROM to be in input mode
#define CTRLOUT 0XA1 // Control Out Byte
configures the EEPROM to be in output mode
#define TEST_PIC
#define I2C_DEBUG
void wait_SSPIF();
void init_I2C();
void init_UART();
void sendByte_I2C(unsigned char TX);
void UART_send(unsigned char data);
void dispError();
void errorCheck_I2C();
unsigned char readFrom_PIC(unsigned char ctrl);
unsigned char readFrom_EEPROM(unsigned char ctrl, unsigned char
address);
void writeTo_PIC(unsigned char ctrl, unsigned char data);
void writeTo_EEPROM(unsigned char ctrl,unsigned char address, unsigned
char data);
void UART_sendString(unsigned char* data);
void UART_sendHex(unsigned char data);
void UART_sendBytes(unsigned char* data, unsigned char num);
main(){
init_I2C();
init_UART();
//while(1) UART_send('A');
#ifdef TEST_EEPROM
TRISB = 0;
PORTB = 0;
//writeTo_EEPROM(1,0,0x12);
//writeTo_EEPROM(0,0,0x21);
while(1){
PORTB = readFrom_EEPROM(1,0);
__delay_ms(500);
}
//PORTB = readFrom_EEPROM(0,0);
#endif
#ifdef TEST_PIC
TRISB = 0;
PORTB = 0;
while(1){
readFrom_PIC(0x30);
__delay_ms(1000);
}
#endif
}
void init_I2C(){
SSPSTAT = 0x80;//10X0 0000 SMB off & SMP std mode
SSPCON = 0x28;//0X1X 1000 SSPEN on & Master mode
SSPADD = (_XTAL_FREQ/(4*CLOCKSPEED)) - 1;
TRISC = 0B00011000;
SSPIF = 0;
}
void init_UART(void){
//sync =1 syncro, sync = 0 ascn
// spen = 1;
// 8 bit
/* TRISC6 = 0;
TRISC7 = 1;
SPBRG = 129;
BRGH = 1;
TXSTA = 0x24; //00100100
RCSTA = 0x90;
*/
SPEN = 1;
CREN = 0;
ADDEN = 0;
TXSTA = 0b00100100;
// SPBRG = 129;
TRISC6 = 0;
TRISC7 = 1;
//SPBRG = (_XTAL_FREQ/(16*BAUDRATE))-1;
SPBRG = 51;
}
void UART_send(unsigned char data){
while(!TXIF);
TXREG = data;
}
/*Reading from PIC*/
unsigned char readFrom_PIC(unsigned char address){
unsigned char read_ctrl = (address<<1) | 1;
//read_ctrl =| 1;
unsigned char read_bat = 0x00;
#ifdef I2C_DEBUG
UART_sendString("\r\nI2C Master Read\r\n");
UART_sendString("Start Condition\r\n");
#endif
/*Start*/
RSEN = 1;
wait_SSPIF();
#ifdef I2C_DEBUG
UART_sendString("Sending Start bit was successful!\r\n");
UART_sendString("Sending address..\r\n");
#endif
/*Control Byte*/
sendByte_I2C(read_ctrl);
wait_SSPIF();
//errorCheck_I2C();
#ifdef I2C_DEBUG
UART_sendString("Adress sent\r\n");
#endif
#ifdef I2C_DEBUG
if(ACKSTAT){
UART_sendString("Slave Acknowledge failed\r\n");
return 0;
}
#endif
#ifdef I2C_DEBUG
UART_sendString("Slave Acknowledge was successful!\r\n");
UART_sendString("Start Receiving data\r\n");
#endif
/*Start Receive*/
RCEN = 1;
wait_SSPIF();
read_bat = SSPBUF;
#ifdef I2C_DEBUG
UART_sendString("Data was received successfully!\r\n");
UART_sendString("Data was:\r\n");
UART_sendHex(read_bat);
UART_sendString("\r\nSending Acknowledgement\r\n");
#endif
ACKDT = 1; //ACKDT is originally = 0
ACKEN = 1; //Send Acknoweldge bit
wait_SSPIF();
#ifdef I2C_DEBUG
UART_sendString("Acknowledgement sent!\r\n");
UART_sendString("Sending Stop bit\r\n");
#endif
/*Stop*/
PEN = 1;
wait_SSPIF();
#ifdef I2C_DEBUG
UART_sendString("SUCCESSFULY READ from Slave\r\n");
#endif
return read_bat;
}
unsigned char readFrom_EEPROM(unsigned char ctrl, unsigned char
address){
unsigned char ctrl_in = CTRLIN | (ctrl<<1);
unsigned char ctrl_out = CTRLOUT | (ctrl<<1);
unsigned char read_bat;
/*Start*/
RSEN = 1;
wait_SSPIF();
/*Send Control IN*/
sendByte_I2C(ctrl_in);
wait_SSPIF();
errorCheck_I2C();
/*Send address*/
sendByte_I2C(address);
wait_SSPIF();
errorCheck_I2C();
RSEN = 1; // Sends Restart Bit so that EEPROM
will distinguish that the next data byte will be a control byte.
wait_SSPIF(); // Wait until tranmission is
finished.
/*Send Control OUT*/
sendByte_I2C(ctrl_out);
wait_SSPIF();
errorCheck_I2C();
/*Start Receive*/
RCEN = 1;
wait_SSPIF();
ACKDT = 0; //NACK bit
ACKEN = 1; //Send Acknoweldge bit
/*Stop*/
PEN = 1;
wait_SSPIF();
//read_bat = SSPBUF;
return SSPBUF;
}
/*Writting to EEPROM*/
void writeTo_EEPROM(unsigned char ctrl,unsigned char address, unsigned
char data){
unsigned char ctrl_in = CTRLIN | (ctrl<<1);
unsigned char ctrl_out = CTRLOUT | (ctrl<<1);
/*start*/
SEN = 1;
wait_SSPIF();
/*Send control*/
sendByte_I2C(ctrl_in);
wait_SSPIF();
errorCheck_I2C();
/*Send Address*/
sendByte_I2C(address);
wait_SSPIF();
errorCheck_I2C();
/*Send data*/
sendByte_I2C(data);
wait_SSPIF();
errorCheck_I2C();
/*Stop*/
PEN = 1;
wait_SSPIF();
__delay_ms(1);
return;
}
/*Writting to PIC*/
void writeTo_PIC(unsigned char ctrl, unsigned char data){
/*Start*/
SEN = 1;
wait_SSPIF();
/*Send Ctrl*/
//sendByte_I2C();
wait_SSPIF();
errorCheck_I2C();
/*Send data*/
//sendByte_I2C();
wait_SSPIF();
errorCheck_I2C();
/*Stop*/
PEN = 1;
wait_SSPIF();
return;
}
/**/
void wait_SSPIF(){
while(!PIR1bits.SSPIF);
PIR1bits.SSPIF = 0;
}
void sendByte_I2C(unsigned char TX){
SSPBUF = TX;
}
void errorCheck_I2C(){
if(ACKSTAT) dispError();
}
void dispError(){
PORTB = 0xFF;
while(1);
}
void UART_sendString(unsigned char *data){
while(*data!=0)
UART_send(*data++);
}
void UART_sendHex(unsigned char data){
char buffer[2];
for(int i=1; i>=0; i--){
if(data%16 < 10)
buffer[i] = (data%16 + 48);
else
buffer[i] = (data%16 - 10 + 'A');
data/=16;
}
UART_sendBytes(buffer,2);
}
void UART_sendBytes(unsigned char *data, unsigned char num){
for(int i=0;i<num;i++)
UART_send(*data++);
}
Android Application UI:
Figure 12: Android User Interface Version 1
Android Application Code:
package com.prolific.pl2303hxdsimpletest;
import java.io.IOException;
import java.util.Arrays;
import java.util.Random;
import tw.com.prolific.driver.pl2303.PL2303Driver;
import tw.com.prolific.driver.pl2303.PL2303Driver.DataBits;
import tw.com.prolific.driver.pl2303.PL2303Driver.FlowControl;
import tw.com.prolific.driver.pl2303.PL2303Driver.Parity;
import tw.com.prolific.driver.pl2303.PL2303Driver.StopBits;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.hardware.usb.UsbManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.preference.PreferenceManager;
import android.text.format.Time;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
public class ActiveBalancing extends Activity {
PL2303Driver mSerial;
private Button btn_Refresh;
private TextView txt_Voltage;
private int mDisplayType = DISP_CHAR;
private int mReadLinefeedCode = LINEFEED_CODE_LF;
private PL2303Driver.BaudRate mBaudrate =
PL2303Driver.BaudRate.B9600;
private PL2303Driver.DataBits mDataBits =
PL2303Driver.DataBits.D8;
private PL2303Driver.Parity mParity = PL2303Driver.Parity.NONE;
private PL2303Driver.StopBits mStopBits =
PL2303Driver.StopBits.S1;
private PL2303Driver.FlowControl mFlowControl =
PL2303Driver.FlowControl.OFF;
private static final String ACTION_USB_PERMISSION =
"com.prolific.pl2303hxdsimpletest.USB_PERMISSION";
public int PL2303HXD_BaudRate;
public String PL2303HXD_BaudRate_str="B4800";
private String strStr;
@Override
public void onCreate(Bundle savedInstanceState) {
Log.d(TAG, "Enter onCreate");
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_pl2303_hxdsimple_test);
Button mButton01 = (Button)findViewById(R.id.button1);
mButton01.setOnClickListener(new Button.OnClickListener() {
public void onClick(View v) {
openUsbSerial();
}
});
mSerial = new PL2303Driver((UsbManager)
getSystemService(Context.USB_SERVICE),
this, ACTION_USB_PERMISSION);
if (!mSerial.PL2303USBFeatureSupported()) {
Toast.makeText(this, "No Support USB host API",
Toast.LENGTH_SHORT)
.show();
Log.d(TAG, "No Support USB host API");
mSerial = null;
}
Log.d(TAG, "Leave onCreate");
}//onCreate
protected void onStop() {
Log.d(TAG, "Enter onStop");
super.onStop();
Log.d(TAG, "Leave onStop");
}
@Override
protected void onDestroy() {
Log.d(TAG, "Enter onDestroy");
if(mSerial!=null) {
mSerial.end();
mSerial = null;
}
super.onDestroy();
Log.d(TAG, "Leave onDestroy");
}
public void onStart() {
Log.d(TAG, "Enter onStart");
super.onStart();
Log.d(TAG, "Leave onStart");
}
public void onResume() {
Log.d(TAG, "Enter onResume");
super.onResume();
String action = getIntent().getAction();
Log.d(TAG, "onResume:"+action);
//if (UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(action))
if(!mSerial.isConnected()) {
if (SHOW_DEBUG) {
Log.d(TAG, "New instance : " + mSerial);
}
if( !mSerial.enumerate() ) {
Toast.makeText(this, "no more devices found",
Toast.LENGTH_SHORT).show();
return;
} else {
Log.d(TAG, "onResume:enumerate succeeded!");
}
}//if isConnected
Toast.makeText(this, "attached",
Toast.LENGTH_SHORT).show();
Log.d(TAG, "Leave onResume");
}
private void openUsbSerial() {
Log.d(TAG, "Enter openUsbSerial");
if(null==mSerial)
return;
if (mSerial.isConnected()) {
if (SHOW_DEBUG) {
Log.d(TAG, "openUsbSerial : isConnected ");
}
String str =
PL2303HXD_BaudRate_spinner.getSelectedItem().toString();
int baudRate= Integer.parseInt(str);
switch (baudRate) {
case 9600:
mBaudrate = PL2303Driver.BaudRate.B9600;
break;
case 19200:
mBaudrate =PL2303Driver.BaudRate.B19200;
break;
case 115200:
mBaudrate =PL2303Driver.BaudRate.B115200;
break;
default:
mBaudrate =PL2303Driver.BaudRate.B9600;
break;
}
Log.d(TAG, "baudRate:"+baudRate);
// if (!mSerial.InitByBaudRate(mBaudrate)) {
if (!mSerial.InitByBaudRate(mBaudrate,700)) {
if(!mSerial.PL2303Device_IsHasPermission()) {
Toast.makeText(this, "cannot open, maybe no
permission", Toast.LENGTH_SHORT).show();
}
if(mSerial.PL2303Device_IsHasPermission() &&
(!mSerial.PL2303Device_IsSupportChip())) {
Toast.makeText(this, "cannot open, maybe
this chip has no support, please use PL2303HXD / RA / EA chip.",
Toast.LENGTH_SHORT).show();
}
} else {
Toast.makeText(this, "connected",
Toast.LENGTH_SHORT).show();
}
}//isConnected
Log.d(TAG, "Leave openUsbSerial");
}//openUsbSerial
private void readDataFromSerial() {
int len;
byte[] rbuf = new byte[4096];
StringBuffer sbHex=new StringBuffer();
Log.d(TAG, "Enter readDataFromSerial");
if(null==mSerial)
return;
if(!mSerial.isConnected())
return;
len = mSerial.read(rbuf);
if(len<0) {
Log.d(TAG, "Fail to bulkTransfer(read data)");
return;
}
if (len > 0) {
if (SHOW_DEBUG) {
Log.d(TAG, "read len : " + len);
}
for (int j = 0; j < len; j++) {
sbHex.append((char) (rbuf[j]&0x000000FF));
}
txt_Voltage.setText(sbHex.toString());
Toast.makeText(this, "len="+len,
Toast.LENGTH_SHORT).show();
}
else {
etRead.setText("empty");
return;
}
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.d(TAG, "Leave readDataFromSerial");
}//readDataFromSerial
References:
[1] S.T. Huang, D. C. Hopkins, C.R. Mosling, Extension of battery life via charge
equalization control, IEEE Trans. Ind. Electron., vol.40, no.1, February 1993.
[2] S. Wen, Cell Balancing buys extra run time and battery life, Analog Applications
Journal, Texas Instruments Incorporated, March 2009.
[3] J. Cao, N. Schofield, A. Emadi, Battery balancing methods: A comprehensive
review, Proc, IEEE Ven. Power Propulsion Conf., Harbin, China, September 2008.
[4] J. Lonzano, E. Cadaral, M.I. Montero, M. Asmartinez, Battery Equalization active
methods, Journal of Power Sources, Vol. 246, January 2014.
[5] Y.N. Chang, Y.S. Shen, H.L. Cheng, S.Y. Chan, Design of active balance circuit
for lithium battery pack, Future Energy Electronics Conference, November 2013.
[6] Y. S. Lee, M. W. Cheng, "Intelligent Control Battery Equalization for Series
Connected Lithium Ion Battery Strings", IEEE Trans. on Industrial Electronics, Oct.
2005.
[7] D. Mohamed, A. Mailier, O. Noshin, P. Van den Bossche, J. Van Mierlo, Single
switched Capacitor Battery Balancing System Enhancements, energies, Vol. 6, April
2013.
[8] A.C. Baughman, M. Ferdowsi, Double-Tiered switched-capacitor battery charge
equalization technique, Industrial Electronics, IEEE transaction, Volume 55, June 2008.
[9] Y.J. Rong, C.Y. Hua, W.B. Tang, Charging and Discharging Equalization with
Improved switching Matrix for Series-Connected Battery Pack in EV, Applied
Mechanics and Materials, Vol. 260-261, December 2012.
[10] M. Daowd, N. Omar, P. Van Den Bossche, J. Van Mierlo, Passive and active
battery balancing comparison based on MATLAB simulation, Vehicle Power and
Propulsion Conference (UPPC), September 2011.
[11] M. Preindl, C. Danielson, F. Burrelli, Performance evaluation of battery balancing
hardware, Control Conference (ECC), July 2013.
[12] K. Hettrich, Transportations Battery Bottleneck: Context, Challenges, and Path
Forward, Stanford energy club, Issue 3, June 2013.