目录
一、方案流程及技术规格书设计
二、系统硬件电路设计
三、系统软件设计
四、系统调试测试与分析
前言
全球气温由于温室效应上升导致越来越多极端气候灾害,环境污染、能源危机等问题越来越严重。为此中国制定了实现碳中和计划的具体方案,由于电动汽车碳排放较少加上汽油价格持续走高,因此电动汽车得到了国家政策支持。
本设计以STM32F103RCT6作为控制器设计了电动汽车蓄电池充电管理系统,完成了软硬件的设计,并将诸如 LCD、 GSM等外部设备相连接,通过模数转换实时显示蓄电池状况,当检测蓄电池电流电压达到报警值时,用户会收到来自GSM模块的报警短信。系统程序运行稳定快速,可以实时监测电动汽车蓄电池的运行状况。
软件工具准备
软件:
电路设计:protel99 se(up主使用版本) 或者其他版本,或者其他电路设计软件;
单片机开发:Keil5;
调试测试:串口调试助手,逻辑分析仪等;
工具:
电路焊接:电烙铁,SMT(有条件的);
调试:
万用表、示波器(基础入门即可,可以白嫖学校或者公司)USB转串口工具、仿真器;
一、方案流程及技术规格书设计
方案流程设计
技术规格书设计
- 电池电压检测,当电池电压低于11.1V时,LCD1602液晶显示报警提醒,并通过GSM模块发送报警信到指定手机。
- 充电控制:当电池电压低于9.6V时,用脉冲方式进行充电;当电池电压高于9.6V时,用恒流充电方式充电;当电池电压高于15.6V时,用脉冲方式充电;当电池电压高于16.2V时停止充电,LCD1602液晶显示充电完成,GSM模块发送充电完成到指定手机。充电控制实现方式:单片机输出PWM波控制MOS管实现充电电流的控制。
- 放电控制:通过AD转换方式检测放电电流,如果放电电流大于3A,切断放电电路,保护电池。
- 单片机驱动LCD1602实时显示电池电压,充电中显示充电电流,放电时显示放电电流,并实时显示电池剩余容量。
二、系统硬件电路设计
2.1微处理控制电路
以STM32系列微处理器器为核心,利用STM32系列微处理器对各模块进行控制,STM32系列的核心是 ARMCortex-M3,;它具有36 MHz的基础频率,在16位的产品中,其性能大大提高了16位的性能,是32位产品的首选。这两款产品都有32K至128K的内存,区别在于SRAM的存储能力和外部设备的结合。在72兆赫的时钟频率下,由闪存执行编码,STM32功率消耗为36 mA,相当于0.5mA/MHz。
STM32系列的优点在于:高性能、低成本、低功耗、以及 模数转换等多种功能。可以达到预定的性能要求。
对我们的系统进行了全面的分析,重点在于充电控制、报警、数模转换,由于外设模块较多,使用I/O口较多,功能比较复杂,数据采集较多,所以不能选用内存太小,运行速度过慢的,根据这些分析,我选定了STM32F系列单片机作为本设计的主控装置。
ST公司在国内是最早推广ARM单片机厂家,在国内有众多用户。大部分教育培训平台都以ST公司产品为例子,尤其是STM32F系列单片机,中文资料齐全,容易理解。虽然51系列单片机应用广泛和价格便宜,但本设计需要控制LCD显示和AD转换,51单片机速度偏低,性能不能满足。
在综合考虑了GSM模块、充电控制和电压电流监测及显示等诸多因素后,决定采用ST公司的STM32F103RCT6单片机。
STM32F103RCT6单片机特点如下表:
外设 | 数量 | |
内存 | 256K | |
RAM | 48K | |
定时器 | 通用定时器 | 4个 |
高级定时器 | 2个 | |
基本定时器 | 2个 | |
通信 | SPI(I2S) | 3 |
I2S | 2 | |
USART | 5 | |
USB | 1 | |
CAN | 1 | |
SDIO | 1 | |
通用I/O端口 | 51 | |
12位同步ADC | 3×16通道 | |
12位DAC | 1×2通道 | |
CPU频率 | 72MHz | |
工作电压 | 2.0~3.6V | |
工作温度 | -40℃~+125℃ | |
封装 | LQFP64 |
2.2 LCD1602液晶显示电路
LCD1602是一种可以同时显示16x2的32个字符的工业级液晶。LCD1602 LCD的工作原理是利用 LCD的物理性质,通过电压来控制显示器的显示面积,使其有电时,就能显示,从而实现图形的显示。它可以显示数字、文字图形,显示方式多样,也非常清晰可见,市场上运用广泛,目前市场上使用的字符液晶大多采用HD44780 LCD,其控制原理基本一致,所以以HD44780为基础编写的控制软件能够在市场上广泛使用,各引脚功能如表。
引脚 | 功能 |
1 | GND(接地) |
2 | VCC(接电源) |
3 | VEE(液晶显示器对比度调整接口,接正电源时对比度最弱,接地时对比度最高) |
4 | RS(寄存器选择,高电平时选择数据寄存器,低电平时选择指令寄存器) |
5 | RW(读写信号线,高电平时进行读操作,低电平时进行写操作) |
6 | E(使能端,高电平时读取信息,负跳变时执行指令) |
7 | D0(Data I/O) |
8 | D1(Data I/O) |
9 | D2(Data I/O) |
| D3(Data I/O) |
11 | D4(Data I/O) |
12 | D5(Data I/O) |
13 | D6(Data I/O) |
14 | D7(Data I/O) |
15 | 空脚或者背电电源(背光正极) |
16 | 空脚或者背电电源(背光负极) |
2.3 报警电路
设计中采用了GSM模块作为报警装置,GSM模块程序见附录,模块已经集成了一个射频天线、SIM卡, GSM模块和一个单片机的接口只是一个串口。由于GA6 - B通信模块的一个输入和输出口电平都是3. 3V, U_RXD、U_TXD连接模块串口。接口电路如图所示。
单片机与GSM模块通信时,要进行反接,即单片机的RXD接模块的TXD,单片机的TXD接模块的RXD。
2.4充电电路设计
J1为充电端口,采用的是一个DC座,通过AOC28B1H电源适配器为蓄电池充电,当蓄电池没有电时。它可以直接给整个系统供电,它是一个19V的直流电源,通过程序控制MOS管对电源适配器的电流从而对电源进行充电控制,电压电流的测量则是采用STMC109芯片,它是一款可以通过采样电阻R6两端的电压差将其转换成电流的电压值,再通过单片机ADC采样转换成电流值。充电电路如图所示。
图中J4为MOS管,J1为DC底座其作用是为了连接电源适配器。L1为47uH的电感,其作用是储能给蓄电池充电。J5连接的是12V蓄电池。
2.5 放电电路设计
系统通过使用12V蓄电池进行系统的供电它与充电电路共用一个STMC109电流检测芯片,当放电时芯片来检测放电时的电流大小,电压的检测通过电阻的分压在使用单片机内具有A/D功能的接口实现数模转换最终完成电压的测量。图中的三极管通过单片机控制MOS管的导通与关断来控制电路的导通与关断。
图中的D3是一个LED灯泡,由于它的单向导通性在放电时LED灯泡处于导通状态,此事灯泡会亮。当系统处于充电状态时LED灯泡处于关断状态灯泡熄灭,因此可以作为一个充放电提醒装置。
2.6 ADC电压采集电路设计
利用单片机的ADC模块得到接入ADC管脚上的实际电压值。ADC位数表明这个该ADC采集共有2n个刻度,STM32的ADC有212个刻度,因此系统采样的ADC值是从0到4095,这个数值也为ADC的分辨率,当数值越大,结果越精确。之后将读到的值通过计算比例电阻换成实际的电压值,当管脚接地时,读到的值是0,如果管脚接到VDD,得到的值是4095,拿万用表测量的时候VDD的实际电压并不是标准的3.3V,但是AD采样时还是4095这个数据,误差比较大,因此,现在的芯片制造商,都会将基准电压引入到ADC模块中。
基准电压引脚通常配备在STM32系列它的引脚在大于等于100以的芯片,本设计所使用的是STM32F103RCT6没有参考电压管脚,因此需要将基准电压接到VDDA引脚上,但是 VDDA与 VDD之间的电压差异不能大于0.3 V,如果 VDD为3.3 V,则 VDD可以将3.3 V的基准电压芯片或3.0 V的基准电压芯片连接到 VDDA,而不能连接2.5 V的基准电压芯片。ADC管脚的输入电压范围,通常为0- Vref,在0-2 Vref之间。若所测电压比 ADC输入电压高,例如,用STM32F103RCT6来测量0至12V的电压,则可以在 ADC管脚输入前加上两个电阻进行分压,将电压降到3.3V以内,如图。
图中的电阻R10为51Ω,R11为10Ω,通过采用R10和R11两个电阻进行分压,BATT DET=12V×R11÷(R10+R11),单片机控制采样时间进行采样,再通过计算进而得到实际电压值。
2.7 电源电路
本系统采用外部9 V的电源适配器,但是 MCU、 LCD器件等均要求5 V的稳定电压,由9 V降至5 V,采用普通的7805三端稳压集成电路。7805三端稳压电路具有以下特点:1、具有较高的纹波抑制率。2、内部有过热触发短路保护,具有较高的安全性。3、价格低廉。4、所需的周边器件很小,外部器件仅需输入滤波器和输出滤波器。
三端电压整流器7805仅有三脚,一脚输入,二脚接地,三脚输出。输出电压为7805,输出电压为5 V,C3输入滤波电容,C6输出滤波电容。电路如图。
GSM模块的接口电平为3.3伏,因此必须提供3.3 V的电力。AMS1117稳压电路的研制,电路如图。
2.8 PCBA板图
将上述各部分硬件电路整合到同一电路图中,整体电路设计如图附录A所示。在 Protel99se 软件中将原理图绘制完毕、元件编号、创立网络表完毕完成电路连接的电气检查,新建PCB文件设置好PCB板的大小,本设计使用的是100mm×100mm的板子,在基于原理的排线图直接生成元器件在PCB板上,再对元器件的位置进行布局排线后绘出 PCB 板,在布线时相邻平面走线方向应该成正交结构,为了减小层间不必要的串扰,应尽量避免在相邻层内使不同的信号线路在同一方向上走动;当这种情况因板状结构的局限(例如一些后板)而很难避免,尤其是在信号率高的情况下,应该将土地平面上的各个接线层隔离起来,土地信号线将各个信号线隔离起来。将PCB板绘制完成后如图蓄电池充电管理PCB板所示。
三、系统软件设计
3.1 主程序设计
本系统使用STM32F103RCT6单片机主控芯片,需要实现电压电流和容量的检测,通过计算分析,控制设备对电池的充放电控制,实现对蓄电池的运行状态进行检测和预警。控制部分有充电控制、放电控制、GSM报警控制、LCD显示控制。首先需要初始化单片机系统时钟和外设。正常工作时,STMC109芯片检测电压电流,单片机单线通信读取对应的模拟量,经过AD转换,计算得到电压电流,通过电压,计算蓄电池容量大小,通过液晶显示模块实时显示电压电流容量和充放电状态,当达到报警值时设备进行报警。
单片机的常用编程类型语言主要类型有两种,一种编程类型语言就是编程汇编语言,它们既需要可以直接对一个单片机的内部和对外资源管理系统程序进行直接的逻辑操作,程序紧凑简洁,但是必须能够适合各种应用环境当系统规模较大时编程人员更趋向于使用C语言。
本设计编程语言选择的是C语言C是一种能够简单地进行编译的通用程序语言。可以自由处理较低成本级别的数据存储器、在无条件限制地自由运行的各种情况下甚至可以自由使用各种编程脚本语言。C++语言本身仍然保持着良好的支持跨线程平台和多线程微处理器的功能,标准化完成后所自行编写的一个应用程序由该语言同时可在多个平台计算机上同时启动运行,甚至可以在单片机和超级电脑上使用。C语言具有以下七个特点:
(1)语言简洁明了、编写语言时结构比较紧凑、使用方便。
(2)数据结构丰富。
(3)运算符丰富。
(4)可以进行模块化程序设计。
(5)可以直接对计算机硬件进行操作。
(6)可移植性好。
(7)程序执行效率高。
系统上电后,首先系统关闭总中断,然后对芯片内部定时器初始化,AD初始化,LCD显示初始化,GSM通信模块初始化,完成初始化后,打开总中断。后面循环执行LCD显示程序,AD转换程序实时采集电池电压,然后LCD1602实时显示电压电流及容量等信息,GSM模块发送程序。系统流程图如图。
3.2 AD转换程序和计算程序设计
STM32F103单片机内部具有12位AD转换器,所以采用内部的模数转换器。AD转换功能需要初始化配置AD转换器。否则无法使用其功能。由于电压输入信号连接在PA1,所以配置通道1为AD输入。
AD初始化完成后,就读取AD值并计算电压、电流、容量。图是ADC计算流程图。
分辨率是AD采集数据输出数值的单位,3.3V的参考电压,系统采用12位的AD,那么分辨率就是4095。采样电压=(采样值/4095)×3.3V ,因为使用了分压电路进行采样,所以计算实际电压时要将采样换算回去,以图3.10为例,实际电压=采样电压×(51+10)÷10)。
程序代码:
//初始化ADC1
void adc_init(void)
{
ADC_InitTypeDef ADC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |RCC_APB2Periph_ADC1,ENABLE); //使能ADC1通道时钟
RCC_ADCCLKConfig(RCC_PCLK2_Div6); //设置ADC分频因子6 72M/6=12,ADC最大时间不能超过14M
//PA1 作为模拟通道输入引脚
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //模拟输入引脚
GPIO_Init(GPIOA, &GPIO_InitStructure);
ADC_DeInit(ADC1); //复位ADC1,将外设 ADC1 的全部寄存器重设为缺省值
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //ADC工作模式:ADC1和ADC2工作在独立模式
ADC_InitStructure.ADC_ScanConvMode = DISABLE; //模数转换工作在单通道模式
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; //模数转换工作在单次转换模式
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //转换由软件而不是外部触发启动
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //ADC数据右对齐
ADC_InitStructure.ADC_NbrOfChannel = 1; //顺序进行规则转换的ADC通道的数目
ADC_Init(ADC1, &ADC_InitStructure); //根据ADC_InitStruct中指定的参数初始化外设ADCx的寄存器
ADC_Cmd(ADC1, ENABLE); //使能指定的ADC1
ADC_ResetCalibration(ADC1); //使能复位校准
while(ADC_GetResetCalibrationStatus(ADC1)); //等待复位校准结束
ADC_StartCalibration(ADC1); //开启AD校准
while(ADC_GetCalibrationStatus(ADC1)); //等待校准结束
}
//获得ADC值
//ch:通道值 0~8
unsigned short int get_adc(unsigned char ch)
{
//设置指定ADC的规则组通道,一个序列,采样时间
ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_239Cycles5 ); //ADC1,ADC通道,采样时间为239.5周期
ADC_SoftwareStartConvCmd(ADC1, ENABLE); //使能指定的ADC1的软件转换启动功能
while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));//等待转换结束
return ADC_GetConversionValue(ADC1); //返回最近一次ADC1规则组的转换结果
}
//通道0-8切换
unsigned short int get_adc_average(unsigned char ch,unsigned char times)
{
unsigned int temp_val=0;
unsigned char t;
for(t=0;t<times;t++)
{
temp_val += get_adc(ch);
delay_ms(5);
}
return temp_val/times;
}
int get_adc_value(unsigned char _ADC_Channel_n)
{
int adcx;
adcx = get_adc_average(_ADC_Channel_n,10);
return adcx;
}
3.3 液晶显示驱动及显示程序设计
LCD1602A采用HD44780 LCD芯片.HD44780内建有 DDRAM, CGROM, CGRAM.DDRAM是一种用于存储要被显示的字符编码的内存。80字节,其地址和屏幕的对应关系如下表地址和屏幕对应关系:
显示位置 | 1 | 2 | 3 | 4 | 5 | 6 | … | 40 | |
DDRAM 地址 | 第一行 | 00H | 01H | 02H | 03H | 04H | 05H | … | 27H |
第二行 | 40H | 41H | 42H | 43H | 44H | 45H | … | 67H |
1602 A的液晶第1排16位,地址为00H-0FH,第2排16位,地址为40H-4FH。
以下是一个屏幕清屏的命令,比如,表格的屏幕清理。
指令功能 | RS | RW | D7 | D6 | D5 | D3 | D2 | D1 | D0 |
清屏 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
RS控制线用于识别指令与资料, RS在低时为控制指令, RS在高时为显示资料。屏幕清空是一个控制指令,因此 RS值很低。
RW是读写控制, RW低,是写 LCD模块,在 RW高时读取 LCD的数据。透明屏幕是写 LCD的,因此 RW值很低。
D7-D0是一条数据线,而屏幕上的数字是0x01。
常见的指令有0x06、0x04、0x04、0x38等。
与液晶显示器进行通讯,首先要具备写入和写入的功能,图是写LCD命令和数据流程图。
程序代码:
/***写命令***/
void cmd_w(uchar cmd)
{
RW=0;
RS=0;
E=1;
P2=cmd;
delay(1);
E=0;
}
1602A液晶模块显示前需要初始化,初始化主要是设置LCD的工作状态。图是LCD初始化流程。
LCD1602A初始化和其他程序代码:
/***初始化**/
void Lcd1602_init(void)
cmd_w(0x38);
cmd_w(0x0c);
cmd_w(0x06);
cmd_w(0x01);
void put_display_ch(uchar _ch) //显示字符
{
dat_w(_ch);
}
3.4 串口通信和GSM发送程序设计
GSM发送程序的设计主要是串口通信程序设计单片机通过串口通信引脚发送AT指令控制GSM发送短信。STC32F103RCT6有2个串口,UART1和UART2。串口1用于程序下载和仿真,所以本设计用串口2和GSM模块通信。串口2和GSM模块通信首先需要初始化串口,串口初始化主要是配置工作模式、设置波特率等。图是串口初始化流程图。
串口初始化完成后,STM32F103RCT6单片机发送AT指令函数控制GSM模块发送报警短信。
程序代码:
/*******************************************************************************
* 函数名 : USART2_Init_Config
* 描述 : USART2初始化配置
* 输入 : bound:波特率(常用:2400、4800、9600、19200、38400、115200等)
* 输出 : 无
* 返回 : 无
* 说明 : 无
*******************************************************************************/
void USART2_Init_Config(u32 bound)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
/*使能USART2外设时钟*/
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
/*复位串口2*/
USART_DeInit(USART2);
/*USART2_GPIO初始化设置*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; //USART2_TXD(PA.2)
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //设置引脚输出最大速率为50MHz
GPIO_Init(GPIOA, &GPIO_InitStructure); //调用库函数中的GPIO初始化函数,初始化USART1_TXD(PA.9)
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; //USART2_RXD(PA.3)
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入
GPIO_Init(GPIOA, &GPIO_InitStructure); //调用库函数中的GPIO初始化函数,初始化USART1_RXD(PA.10)
/*USART2 初始化设置*/
USART_InitStructure.USART_BaudRate = bound; //设置波特率
USART_InitStructure.USART_WordLength = USART_WordLength_8b; //8位数据格式
USART_InitStructure.USART_StopBits = USART_StopBits_1; //1个停止位
USART_InitStructure.USART_Parity = USART_Parity_No; //无奇偶校验位
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //无硬件数据流控制
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //工作模式设置为收发模式
USART_Init(USART2, &USART_InitStructure); //初始化串口2
/*Usart2 NVIC配置*/
NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1; //抢占优先级1
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //从优先级0
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器
USART_ITConfig(USART2, USART_IT_RXNE, ENABLE); //使能串口2接收中断
USART_Cmd(USART2, ENABLE); //使能串口
USART_ClearFlag(USART2, USART_FLAG_TC); //清除发送完成标志
}
/*******************************************************************************
* 函数名 : UART2_SendString
* 描述 : USART2发送字符串
* 输入 : *s字符串指针
* 输出 : 无
* 返回 : 无
* 说明 : 无
*******************************************************************************/
void UART2_SendString(char* s)
{
while(*s)//检测字符串结束符
{
while(USART_GetFlagStatus(USART2, USART_FLAG_TC)==RESET);
USART_SendData(USART2 ,*s++);//发送当前字符
}
}
void UART2_Send_Command(char* s)
{
rx_count = 0;
UART2_SendString(s); //发出字符串
UART2_SendString("\r"); //再自动发送 \r\n两个字符
}
/*******************************************************************************
* 函数名 : USART2_IRQHandler
* 描述 : 串口1中断服务程序
* 输入 : 无
* 返回 : 无
* 说明 :
*******************************************************************************/
void USART2_IRQHandler(void)
{
unsigned char rx_dat;
rx_dat = USART_ReceiveData(USART2);
if(rx_count < BUF_MAX)
{
rx_buf[rx_count++] = rx_dat;
}
}
3.5 充电控制程序设计
当蓄电池充电时,STC109芯片检测电流,AD转换检测电压,单片机对电压进行判断,当电压小于9.5V时,系统控制MOS管对蓄电池进行脉冲充电,当电压在9.5-13.5V时,系统对蓄电池进行恒流充电,当电压在13.5-14.1V时,系统对蓄电池进行脉冲充电,当电压大于14.1V时,系统停止充电,并控制GSM模块发送报警信息,进行提示。图是充电控制流程图。
该程序通过ADC将电压检测出来,在和电池的充电指标进行对比判断选择充电方式,充电方式由单片机控制PWM的占空比来实现脉冲充电和恒流充电。
程序代码:
unsigned short int charge_current(void) //得到充电电流
{
float batt_val;
float ad_val;
float vad_input;
ad_val = get_adc_value(ADC_Channel_7);
vad_input = ((ad_val / 4095) * 3.3); /* AD input voltage */
batt_val = vad_input * 200; /* batt_val really voltage */
return (unsigned short int)batt_val;
}
/******************************************************************************
** Function: charge_constant_on
** Description: This function is constant current charge on
** Parameter: None
** Return: None
******************************************************************************/
void charge_constant_on(void) //通过占空比调整充电电流
{
TIM4_PWM_Init(35999,0); //不分频 PWM频率=36000/(899+1)=80Khz
devstate.pwm_duty = CHARGE_DUTY_1;
TIM_SetCompare1(TIM4,CHARGE_DUTY_1);
TIM_Cmd(TIM4, ENABLE); //使能TIM4
}
/******************************************************************************
** Function: batt_charge_control
** Description: This function is charge handle
** Parameter: None
** Return: None
******************************************************************************/
void batt_charge_control(void)
{
if(work_state == DEV_CONSTANT)
{
if(devstate.batt_state == BATT_STATE_LOW_9V6)
{
/* pulse charge */
if(batt_charge_state != CHARGE_PLUSE_LOW)
{
charge_pulse_on();
batt_charge_state = CHARGE_PLUSE_LOW;
//send_text_message("pulse charging");
}
}
else if(devstate.batt_state == BATT_STATE_BETWEEN_9V6_15V6)
{
/* constant charge */
if(batt_charge_state != CHARGE_CONST)
{
charge_constant_on();
batt_charge_state = CHARGE_CONST;
//send_text_message("const current charging");
}
if(devstate.charge_current > 90)
{
devstate.pwm_duty--;
if(devstate.pwm_duty < CHARGE_DUTY_PLUSE)
{
devstate.pwm_duty = CHARGE_DUTY_PLUSE;
}
TIM_SetCompare1(TIM4,devstate.pwm_duty);
}
if(devstate.charge_current < 60)
{
devstate.pwm_duty++;
if(devstate.pwm_duty > CHARGE_DUTY_1 +3)
{
devstate.pwm_duty = CHARGE_DUTY_1 +3;
}
TIM_SetCompare1(TIM4,devstate.pwm_duty);
}
}
else if(devstate.batt_state == BATT_STATE_BETWEEN_15V6_16V2)
{
/* pulse charge */
if(batt_charge_state != CHARGE_PLUSE_HIGH)
{
charge_pulse_on();
batt_charge_state = CHARGE_PLUSE_HIGH;
//send_text_message("pulse charging");
}
}
else if(devstate.batt_state == BATT_STATE_HIGH_16V2)
{
/* close charge */
if(batt_charge_state != CHARGE_OFF)
{
charge_off();
batt_charge_state = CHARGE_OFF;
send_text_message("battery charge end");
}
}
}
else
{
if(batt_charge_state != CHARGE_OFF)
{
charge_off();
batt_charge_state = CHARGE_OFF;
}
}
}
3.6 放电控制程序设计
当蓄电池放电时,STC109芯片检测电流,AD转换检测电压,单片机对电压进行判断,当电压小于11.5V时,系统控制GSM模块发送报警信息到指定手机进行提示。当放电电流大于3A时,系统控制MOS管关闭电路,达到保护作用。图是充电控制流程图。
程序代码:
void discharge_control(void) //放电控制(在充电状态和低电压状态不能放电)
{
if(work_state == DEV_CONSTANT) //充电状态
{
discharge_close();
}
else if(work_state == DEV_DISCHARGE ) //放电状态
{
if(devstate.batt_state == BATT_STATE_LOW_9V6)
{
discharge_close();
}
else
{
discharge_open();
}
}
else if(work_state == DEV_CHARGE_FULL) //充满状态
{
discharge_close();
}
}
四、系统调试测试与分析
4.1 硬件电路焊接
用电烙铁和焊锡将单片机、STMC109高端电流检测芯片,LCD1602液晶显示、GSM通信模块、及0805电容、0805电阻、等元器件焊接在电路板上,并焊接上多个插座和插针。
当连接电源或接通电池时,系统开始初始化,本设计采用的是上电复位,此时LCD1602液晶显示显示“intializing…”运行情况如图。
系统初始化完成之后, GSM模块会进行信号检测,检测GSM模块是否接收到2G网络信号,当检测到信号时模块会显示“GSM OK”如果没有信号系统显示“GSM Error Register”通过运行调试系统运行正常。当检GSM模块测到信号时,运行情况如图。当没有检测到信号时运行情况如图。
4.3 系统放电
当系统初始化完成后,显示电压电流等信息并会控制GSM模块发送系统正常运行的短信“system start”对用户进行提醒,运行情况涉及号码隐私不做展示。
LCD1602液晶显示屏上第一排显示:“11.3V”“116mA”“30%”第二排显示:“OUT-”,运行情况如图。表示蓄电池当前电压为11.3V ,电流为116mA,电池容量为30%,OUT-表示当前为放电状态,当显示“IN-”时,表示当前系统处于充电状态,该系统电池容量共有10个容量等级每10%一个等级。
当蓄电池电压小于11.1V时,会在LCD1602 液晶显示屏上第一排显示当前电压、电流、容量,同时系统会控制GSM模块给指定手机18140778051发送短信息“battery voltage low”。
LCD1602液晶显示屏上第一排显示:“10.6V”,“111mA”,“20%”第二排显示:“OUT-”,“ WORNING”,表示蓄电池当前电压为10.6V ,电流为111mA,电池容量为20%,当前系统处于放电状态,WORNING表示当前电压低,进行警报提醒。如图电量低报警。
4.3 系统充电
当蓄电池电压达到14.1V时,系统会控制GSM模块给指定手机18140778051发送短信息“battery charge end”。
LCD1602液晶显示屏上第一排显示:“14.5.V”,“000mA”,“100%”第二排显示:“FULL-”, ,表示系统当前充电电压为14.5V ,充电电流为000mA,电池容量为100%,“FULL-”表示当前蓄电池以充满。如图蓄电池充满状态。
通过对系统的调试与完善,本次设计基于单片机的电动汽车蓄电池充电管理系统实现了对电动汽车12V蓄电池的电压电流的检测与显示,通过电压在计算出容量并显示在液晶显示屏上,当电池放电大于3A时,系统会断开充电,当时系统充电时,会根据电压选择充电方式,当系统当电池电压不足和电池电量充满时,通过GSM 模块发送报警短信到“131xxxx3959”这个指定的手机号。