Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
main.cpp
- Committer:
- takuma1
- Date:
- 2021-04-08
- Revision:
- 5:f07de56debf3
- Parent:
- 4:e57b023e41f3
- Child:
- 6:802d0aa08b39
File content as of revision 5:f07de56debf3:
#include "mbed.h"
#include "bms.h"
#include "LTC681x.h"
#include "LTC6811.h"
#include "INA226.hpp"
#define UI_BUFFER_SIZE 64
#define SERIAL_TERMINATOR '\n'
#define ENABLED 1
#define DISABLED 0
#define DATALOG_ENABLED 1
#define DATALOG_DISABLED 0
DigitalOut led1(LED1);
Serial pc(USBTX, USBRX);
CAN canSlave(p30,p29);
I2C i2c(p28,p27);
DigitalOut led2(LED2);
DigitalOut BAT_MIN_safty(p21);
DigitalOut BAT_MAX_safty(p22);
//Timer timer; //書き込み時間を計測するタイマ
// CAN関係
short int forSend = 0; //データ送信時に一時的に使用する変数
bool CANsendOK = 0; //CAN送信完了時,セットする(mainでのprintfのため)
CANMessage msgSlave1; //CAN送信用
short int canSlaveID = 0x20; //canSlaveのIDをに設定
void Handler_canSend();
bool flag_can = 1;
//測定関係の関数(変更の際触る必要がない)
void run_command(uint32_t cmd); //測定コマンド送信関数
void measurement_loop(uint8_t datalog_en);
void print_cells(uint8_t datalog_en); //セル電圧の測定表示関数
void print_open();
void print_aux(uint8_t datalog_en);
void print_stat();
void print_config();
void print_rxconfig();
void print_pec(void);
void serial_print_hex(uint8_t data);
void check_error(int error);
//測定関係関数(使ってる)
void wakeup();//ICの起動関数、消費電力削減関数
void cell_read();//セルの電圧の読み込みコマンド
void spi_error();//SPIエラー処理関数
void ic_check();//ICが測定可能状態か診断して次のコマンドに持ち込むための関数
void spi_check();//SPIエラーの確認関数
void print_CAN(uint8_t datalog_en);//セルの電圧の表示コマンドと過充電過放電検出
void BAT_safty();
void print_math();
void can_sent1();
void can_sent2();
void can_sent3();
void can_sent4();
//void can_set();
void can_wait();
void ic_set();
const uint8_t TOTAL_IC = 3; //IC数
char ui_buffer[UI_BUFFER_SIZE];
const uint8_t ADC_CONVERSION_MODE = MD_7KHZ_3KHZ;
const uint8_t ADC_DCP = DCP_DISABLED;
const uint8_t CELL_CH_TO_CONVERT = CELL_CH_ALL;
const uint8_t AUX_CH_TO_CONVERT = AUX_CH_ALL;
const uint8_t STAT_CH_TO_CONVERT = STAT_CH_ALL;
const uint16_t MEASUREMENT_LOOP_TIME = 10;//milliseconds(mS)
const uint16_t OV_THRESHOLD = 41000; //
const uint16_t UV_THRESHOLD = 30000; //
const uint8_t WRITE_CONFIG = DISABLED;
const uint8_t READ_CONFIG = DISABLED;
const uint8_t MEASURE_CELL = ENABLED;
const uint8_t MEASURE_AUX = DISABLED;
const uint8_t MEASURE_STAT = DISABLED;
const uint8_t PRINT_PEC = DISABLED;
short n =0;
uint8_t read_data();
float read_float();
INA226 VCmonitor(i2c); // INA226
int32_t read_int();
float BAT_MIN ;
float BAT_MAX ;
float BAT_AVG ;
double BAT_C;
float BAT_SUM;
unsigned short BAT_CELL[23];
char *read_string();
/*
int Replace1;
int Replace2;
int Replace3;
int Replace4;
*/
int8_t read_char();
cell_asic bms_ic[TOTAL_IC];
void Handler_canSend() {
int Replace1 = 0;
int Replace2 = 0;
int Replace3 = 0;
short int Replace4 = 0;
short n =0;
int BAT_SUM = 0; // 0にする
int BAT_MIN = 55876;
double C;
//unsigned short BTA_MAX = 0;
for (int current_ic = 0 ; current_ic < TOTAL_IC; current_ic++) {
for (int i=0; i < bms_ic[0].ic_reg.cell_channels; i++) {
//pc.printf("C%d:", i+1);
printf("%.4f, ",bms_ic[current_ic].cells.c_codes[i]*0.0001);
BAT_SUM = bms_ic[current_ic].cells.c_codes[i] + BAT_SUM;
if(bms_ic[current_ic].cells.c_codes[i] > 10000){
if(bms_ic[current_ic].cells.c_codes[i] < BAT_MIN){
BAT_MIN = bms_ic[current_ic].cells.c_codes[i];
}
}
if( bms_ic[current_ic].cells.c_codes[i] > BAT_MAX){
BAT_MAX = bms_ic[current_ic].cells.c_codes[i];
}
}
if(VCmonitor.getCurrent(&C) == 0){ // INA226
BAT_C = C;
printf("C,%f\n",C);
}
}
// BMA_SUM
Replace1 = (int)(BAT_SUM / 100);
msgSlave1.data[0] = Replace1 / 100;
msgSlave1.data[1] = Replace1 % 100;
//BAT_MIN
Replace2 = (int)(BAT_MIN / 10);
msgSlave1.data[2] = Replace2 / 100;
msgSlave1.data[3] = Replace2 % 100;
//BAT_MAX
Replace3 = (int)(BAT_MAX /10);
msgSlave1.data[4] = Replace3 / 100;
msgSlave1.data[5] = Replace3 % 100;
//BAT_C
//short BAT_C = -233;
if(BAT_C < 1000){
BAT_C = BAT_C + 9002;
}
if(BAT_C < 0){ //正電流か負電流を判定する
BAT_C = BAT_C + 9001; //負だと正の電流に変更する。さらにモニタ側でマイナスに戻すための定数を9001とする
//最大放電電流は50000mA 充電電流は-40000mAであるため9001とした。
}
Replace4 = (short int)(BAT_C / 1);
msgSlave1.data[6] = Replace4 / 100;
msgSlave1.data[7] = Replace4 % 100;
pc.printf("BAT_C %d\n",Replace4 );
printf("Data in msgSlave1.data[6] : %d\n\r", msgSlave1.data[6]);
if(canSlave.write(msgSlave1)){ //格納したデータを送信する
led1 = !led1;
CANsendOK = 1;
}
ic_check();
}
void Handler_canRecieve(){ //canMasterから送信要求が来たとき,データ送信するための関数
if( flag_can ){
if( canSlave.read( msgSlave1 ) ){ //msgに送られたデータが入る
led2 = !led2;
if( msgSlave1.id == canSlaveID ){ //IDがcanSlaveIDであれば処理する
Handler_canSend();
}
}
}
}
int main(void)
{
uint32_t user_command;
//short int BAT_C = 2322;
pc.baud(115200);
//printf("main()\n\r");
canSlave.attach(&Handler_canRecieve, CAN::RxIrq); //CAN受信割り込みの設定
msgSlave1.id = canSlaveID; //CAN送信側(slave)のIDを決定
msgSlave1.len = 8; //CAN送信側で送るデータのバイト数
while(1) {
BAT_MIN = 0;
BAT_MAX = 0; // 0にする
/*
if ( fp == NULL )
{
pc.printf("USB fileopen!\r\n");
exit(1);
}
FILE *fp = fopen( "/usb/test.csv", "w"); //ファイルを開く "W"は新規作成して書き込みっていう命令?
*/
ic_check();
//timer.start(); //書き込み時間測定開始
//timer.stop(); //書き込み時間測定終了
//fclose(fp); //ファイルを閉じる
if( CANsendOK ) {
CANsendOK = 0;
printf("Data in msgSlave1.data[0] : %d\n\r", msgSlave1.data[0]); //CANで送信したデータをそのまま表示
printf("Data in msgSlave1.data[1] : %d\n\r", msgSlave1.data[1]); //上に同じ
printf("Data in msgSlave1.data[2] : %d\n\r", msgSlave1.data[2]); //上に同じ
printf("Data in msgSlave1.data[3] : %d\n\r", msgSlave1.data[3]);
printf("Data in msgSlave1.data[4] : %d\n\r", msgSlave1.data[4]);
printf("Data in msgSlave1.data[5] : %d\n\r", msgSlave1.data[5]);
printf("Data in msgSlave1.data[6] : %d\n\r", msgSlave1.data[6]);
printf("Data in msgSlave1.data[7] : %d\n\r", msgSlave1.data[7]); //上に同じ
printf("\n\r");
}
BAT_safty();
}
}
/*
void ic_set(){
// __disable_irq();
// flag_can = 0;
ic_check();
spi_check();
spi_error();
wakeup();
cell_read();
}
*/
void ic_check(){ //1
//__disable_irq();
spi_enable();
LTC681x_init_cfg(TOTAL_IC, bms_ic);
LTC6811_reset_crc_count(TOTAL_IC,bms_ic);
LTC6811_init_reg_limits(TOTAL_IC,bms_ic);
wakeup_sleep(TOTAL_IC);
LTC6811_wrcfg(TOTAL_IC,bms_ic);
print_config();
spi_check();
}
void spi_check(){ //2
//__disable_irq();
int countup;
int8_t error = 0;
wakeup_sleep(TOTAL_IC);
error = LTC6811_rdcfg(TOTAL_IC,bms_ic);
check_error(error);
print_rxconfig();
spi_error();
}
void wakeup(){ //3
//__disable_irq();
int countup;
int8_t error = 0;
uint32_t conv_time = 0;
wakeup_sleep(TOTAL_IC);
LTC6811_adcv(ADC_CONVERSION_MODE,ADC_DCP,CELL_CH_TO_CONVERT);
conv_time = LTC6811_pollAdc();
cell_read();
}
void spi_error(){
// __disable_irq();
int8_t error = 0;
int countup;
/*
if(error = -1 ){
for(countup = 0; countup <= 2; countup++){
spi_check();
if(error =1){
break;
}
}
}
if(error = 1){
wakeup();
}
*/
wakeup();
}
void cell_read(){ //4 電圧読み取り
//__disable_irq();
int8_t error = 0;
uint32_t conv_time = 0;
int8_t readIC=0;
wakeup_sleep(TOTAL_IC);
error = LTC6811_rdcv(0, TOTAL_IC,bms_ic);
check_error(error);
//print_cells(DATALOG_DISABLED);
print_CAN(DATALOG_DISABLED);
}
void print_CAN(uint8_t datalog_en){
/*
__disable_irq();
short n =0;
int BAT_SUM = 0; // 0にする
int BAT_MIN = 55876;
double C;
//unsigned short BTA_MAX = 0;
for (int current_ic = 0 ; current_ic < TOTAL_IC; current_ic++) {
for (int i=0; i < bms_ic[0].ic_reg.cell_channels; i++) {
//pc.printf("C%d:", i+1);
//pc.printf("%.4f, ",bms_ic[current_ic].cells.c_codes[i]*0.0001);
BAT_SUM = bms_ic[current_ic].cells.c_codes[i] + BAT_SUM;
if(bms_ic[current_ic].cells.c_codes[i] > 10000){
if(bms_ic[current_ic].cells.c_codes[i] < BAT_MIN){
BAT_MIN = bms_ic[current_ic].cells.c_codes[i];
}
}
if( bms_ic[current_ic].cells.c_codes[i] > BAT_MAX){
BAT_MAX = bms_ic[current_ic].cells.c_codes[i];
}
if(VCmonitor.getCurrent(&C) == 0){ // INA226
BAT_C = C;
//printf("C,%f\n",C);
}
}
}
/*
for (int current_ic = 0 ; current_ic < TOTAL_IC; current_ic++) {
//if (datalog_en == 0) {
//pc.printf("IC%d, ", current_ic+1);
//for(n = 0; n <= 12; n++){
for (int i=0; i < bms_ic[0].ic_reg.cell_channels; i++) {
//BAT_CELL= bms_ic[current_ic].cells.c_codes[i];
//fprintf(fp,"C%d:", i+1);
//fprintf(fp,"%.4f, ",bms_ic[current_ic].cells.c_codes[i]*0.0001);
BAT_SUM = bms_ic[current_ic].cells.c_codes[i] + BAT_SUM;
if(bms_ic[current_ic].cells.c_codes[i] > 10000){
if(bms_ic[current_ic].cells.c_codes[i] < BAT_MIN){
BAT_MIN = bms_ic[current_ic].cells.c_codes[i];
}
}
//unsigned short BTA_MAX = 0;
if( bms_ic[current_ic].cells.c_codes[i] > BAT_MAX){
BAT_MAX = bms_ic[current_ic].cells.c_codes[i];
}
if(VCmonitor.getCurrent(&C) == 0){ // INA226
BAT_C = C;
}
}
}
fprintf(fp,"SUM");
fprintf(fp,"%0.4f, ",BAT_SUM*0.0001);
BAT_AVG = BAT_SUM / 20;
fprintf(fp,"AVG");
fprintf(fp,"%.4f, ",BAT_AVG*0.0001);
fprintf(fp,"MIN");
fprintf(fp,"%.4f, ",BAT_MIN*0.0001);
fprintf(fp,"MAX");
fprintf(fp,"%.4f, ",BAT_MAX*0.0001);
fprintf(fp,"BAT_Current,%f\n",BAT_Current);
*/
}
void BAT_safty(){
if( BAT_MIN < 25000 ){
BAT_MIN_safty = 1 ;
wait(1);
BAT_MIN_safty = 0 ;
}
if( BAT_MAX > 42000){
BAT_MAX_safty = 1;
wait(1);
BAT_MAX_safty = 0;
}
if(BAT_C > 60000){
BAT_MIN_safty = 1 ;
wait(1);
BAT_MIN_safty = 0 ;
}
}
void measurement_loop(uint8_t datalog_en)
{
int8_t error = 0;
if (WRITE_CONFIG == ENABLED) {
wakeup_sleep(TOTAL_IC);
LTC6811_wrcfg(TOTAL_IC,bms_ic);
print_config();
}
if (READ_CONFIG == ENABLED) {
wakeup_sleep(TOTAL_IC);
error = LTC6811_rdcfg(TOTAL_IC,bms_ic);
check_error(error);
print_rxconfig();
}
if (MEASURE_CELL == ENABLED) {
wakeup_idle(TOTAL_IC);
LTC6811_adcv(ADC_CONVERSION_MODE,ADC_DCP,CELL_CH_TO_CONVERT);
LTC6811_pollAdc();
wakeup_idle(TOTAL_IC);
error = LTC6811_rdcv(0, TOTAL_IC,bms_ic);
check_error(error);
print_cells(datalog_en);
}
if (MEASURE_AUX == ENABLED) {
wakeup_idle(TOTAL_IC);
LTC6811_adax(ADC_CONVERSION_MODE , AUX_CH_ALL);
LTC6811_pollAdc();
wakeup_idle(TOTAL_IC);
error = LTC6811_rdaux(0,TOTAL_IC,bms_ic); // Set to read back all aux registers
check_error(error);
print_aux(datalog_en);
}
if (MEASURE_STAT == ENABLED) {
wakeup_idle(TOTAL_IC);
LTC6811_adstat(ADC_CONVERSION_MODE, STAT_CH_ALL);
LTC6811_pollAdc();
wakeup_idle(TOTAL_IC);
error = LTC6811_rdstat(0,TOTAL_IC,bms_ic); // Set to read back all aux registers
check_error(error);
print_stat();
}
if (PRINT_PEC == ENABLED) {
print_pec();
}
}
void print_cells(uint8_t datalog_en)
{
for (int current_ic = 0 ; current_ic < TOTAL_IC; current_ic++) {
if (datalog_en == 0) {
pc.printf("IC%d, ", current_ic+1);
for (int i=0; i < bms_ic[0].ic_reg.cell_channels; i++) {
pc.printf("C%d:", i+1);
pc.printf("%.4f, ", bms_ic[current_ic].cells.c_codes[i]*0.0001);
}
pc.printf("\n");
}
else {
pc.printf("Cells, ");
for (int i=0; i<bms_ic[0].ic_reg.cell_channels; i++) {
pc.printf("%.4f, ",bms_ic[current_ic].cells.c_codes[i]*0.0001);
}
}
}
pc.printf("\n");
}
void print_open()
{
for (int current_ic =0 ; current_ic < TOTAL_IC; current_ic++) {
if (bms_ic[current_ic].system_open_wire == 0) {
pc.printf("No Opens Detected on IC%d\n", current_ic+1);
} else {
for (int cell=0; cell<bms_ic[0].ic_reg.cell_channels+1; cell++) {
if ((bms_ic[current_ic].system_open_wire &(1<<cell))>0) {
pc.printf("There is an open wire on IC%d Channel: %d\n", current_ic + 1, cell);
}
}
}
}
}
void print_aux(uint8_t datalog_en)
{
for (int current_ic =0 ; current_ic < TOTAL_IC; current_ic++) {
if (datalog_en == 0) {
pc.printf(" IC%d", current_ic+1);
for (int i=0; i < 5; i++) {
pc.printf(" GPIO-%d:%.4f,", i+1, bms_ic[current_ic].aux.a_codes[i]*0.0001);
}
pc.printf("Vref2:%.4f\n", bms_ic[current_ic].aux.a_codes[5]*0.0001);
} else {
pc.printf("AUX, ");
for (int i=0; i < 6; i++) {
pc.printf("%.4f,", bms_ic[current_ic].aux.a_codes[i]*0.0001);
}
}
}
pc.printf("\n");
}
void print_stat()
{
for (int current_ic =0 ; current_ic < TOTAL_IC; current_ic++) {
pc.printf("IC%d", current_ic+1);
pc.printf(" SOC:%.4f,", bms_ic[current_ic].stat.stat_codes[0]*0.0001*20);
pc.printf(" Itemp:%.4f,", bms_ic[current_ic].stat.stat_codes[1]*0.0001);
pc.printf(" VregA:%.4f,", bms_ic[current_ic].stat.stat_codes[2]*0.0001);
pc.printf(" VregD:%.4f\n", bms_ic[current_ic].stat.stat_codes[3]*0.0001);
}
pc.printf("\n");
}
void print_config()
{
int cfg_pec;
//pc.printf("Written Configuration: \n");
for (int current_ic = 0; current_ic<TOTAL_IC; current_ic++) {
//pc.printf(" IC ");
//pc.printf("%d", current_ic+1);
// pc.printf(": ");
//pc.printf("0x");
serial_print_hex(bms_ic[current_ic].config.tx_data[0]);
// pc.printf(", 0x");
serial_print_hex(bms_ic[current_ic].config.tx_data[1]);
//pc.printf(", 0x");
serial_print_hex(bms_ic[current_ic].config.tx_data[2]);
//pc.printf(", 0x");
serial_print_hex(bms_ic[current_ic].config.tx_data[3]);
// pc.printf(", 0x");
serial_print_hex(bms_ic[current_ic].config.tx_data[4]);
// pc.printf(", 0x");
serial_print_hex(bms_ic[current_ic].config.tx_data[5]);
//pc.printf(", Calculated PEC: 0x");
cfg_pec = pec15_calc(6,&bms_ic[current_ic].config.tx_data[0]);
serial_print_hex((uint8_t)(cfg_pec>>8));
//pc.printf(", 0x");
serial_print_hex((uint8_t)(cfg_pec));
// pc.printf("\n");
}
// pc.printf("\n");
}
void print_rxconfig()
{
//pc.printf("Received Configuration ");
for (int current_ic=0; current_ic<TOTAL_IC; current_ic++) {
// pc.printf(" IC ");
// pc.printf("%d", current_ic+1);
//pc.printf(": 0x");
serial_print_hex(bms_ic[current_ic].config.rx_data[0]);
//pc.printf(", 0x");
serial_print_hex(bms_ic[current_ic].config.rx_data[1]);
//pc.printf(", 0x");
serial_print_hex(bms_ic[current_ic].config.rx_data[2]);
//pc.printf(", 0x");
serial_print_hex(bms_ic[current_ic].config.rx_data[3]);
//pc.printf(", 0x");
serial_print_hex(bms_ic[current_ic].config.rx_data[4]);
// pc.printf(", 0x");
serial_print_hex(bms_ic[current_ic].config.rx_data[5]);
//pc.printf(", Received PEC: 0x");
serial_print_hex(bms_ic[current_ic].config.rx_data[6]);
//pc.printf(", 0x");
serial_print_hex(bms_ic[current_ic].config.rx_data[7]);
// pc.printf("\n");
}
pc.printf("\n");
}
void print_pec()
{
for (int current_ic=0; current_ic<TOTAL_IC; current_ic++) {
pc.printf("\n%d", bms_ic[current_ic].crc_count.pec_count);
pc.printf(" : PEC Errors Detected on IC");
pc.printf("%d\n", current_ic+1);
}
}
void serial_print_hex(uint8_t data)
{
/*
if (data < 16) {
//pc.printf("0x0%X", data);
} else
pc.printf("0x%X", data);
*/
}
//Function to check error flag and print PEC error message
void check_error(int error)
{
if (error == -1) {
pc.printf("A PEC error was detected in the received data");
}
}
char hex_digits[16]= {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
};
char hex_to_byte_buffer[5]= {
'0', 'x', '0', '0', '\0'
}; // buffer for ASCII hex to byte conversion
char byte_to_hex_buffer[3]= {
'\0','\0','\0'
};
// シリアル インターフェイスから ui_バッファへのデータの読み取り
uint8_t read_data()
{
uint8_t index = 0; // 内の現在の場所を保持するインデックス
int c; // 着信キーストロークの格納に使用される単一の文字
//pc.printf("check 1\n");
while (index < UI_BUFFER_SIZE-1) {
//pc.printf("check 2\n");
c = pc.getc();
//return c;
//pc.printf("check 3\n");
if (((char) c == '\r') || ((char) c == '\n')) break;
if ( ((char) c == '\x7F') || ((char) c == '\x08') ) {
if (index > 0) index--;
} else if (c >= 0) {
ui_buffer[index++]=(char) c;
}
//pc.printf("check 4\n");
}
ui_buffer[index]='\0';
if ((char) c == '\r') {
wait_ms(1);
//pc.printf("check 5\n");
if (pc.readable()==1) {
//pc.printf("check 6\n");
pc.getc();
}
}
return index;
}
float read_float()
{
float data;
read_data();
data = atof(ui_buffer);
return(data);
}
int32_t read_int()
{
int32_t data;
read_data();
if (ui_buffer[0] == 'm')
return('m');
if ((ui_buffer[0] == 'B') || (ui_buffer[0] == 'b')) {
data = strtol(ui_buffer+1, NULL, 2);
} else
data = strtol(ui_buffer, NULL, 0);
return(data);
}
char *read_string()
{
read_data();
return(ui_buffer);
}
int8_t read_char()
{
read_data();
return(ui_buffer[0]);
}