• 正文
    • 1??硬件設(shè)計思路
    • 2??軟件開發(fā)思路
  • 相關(guān)推薦
申請入駐 產(chǎn)業(yè)圖譜

用STM32設(shè)計BMS從控模塊手把手教你

03/04 12:00
994
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點資訊討論

 

大家好,我是專注分享職業(yè)規(guī)劃/技術(shù)科普/智能生活有關(guān)原創(chuàng)文章的allen康哥。今天分享下關(guān)于用STM32設(shè)計BMS從控模塊的思路。

1??硬件設(shè)計思路

>電壓采集電路設(shè)計(精度±2mV)

精密分壓電路設(shè)計

采用0.1%精度的金屬膜電阻

分壓比計算:Vcell_max = 4.2V時,ADC輸入≤3.3V

典型取值:R1=100kΩ,R2=22kΩ(分壓比1:0.22)

低通濾波設(shè)計:RC時間常數(shù)τ=10ms(R=1kΩ,C=10μF)

運放緩沖電路

選用零漂移運放AD8628

配置電壓跟隨器消除阻抗影響

共模電壓抑制比>120dB

ADC配置要點

STM32F4內(nèi)置12位ADC

參考電壓使用外部2.5V基準(zhǔn)源(REF3025)

采樣周期配置為480周期(提高信噪比

>被動均衡電路設(shè)計
// 均衡控制邏輯示例typedef struct {  uint8_t cell_num;  uint16_t balance_threshold;  GPIO_TypeDef* port;  uint16_t pin;} BalanceChannel;
void balance_control(BalanceChannel* ch, float cell_voltage) {  if (cell_voltage > ch->balance_threshold) {    HAL_GPIO_WritePin(ch->port, ch->pin, GPIO_PIN_SET);  } else {    HAL_GPIO_WritePin(ch->port, ch->pin, GPIO_PIN_RESET);  }}

2??軟件開發(fā)思路

>開發(fā)環(huán)境搭建

    • CubeMX配置(時鐘樹/ADC/DMA)FreeRTOS任務(wù)劃分(500ms采集周期)
?>電壓采集核心代碼
// ADC DMA配置(8通道循環(huán)采樣)#define CELL_NUM 8volatile uint16_t adc_buffer[CELL_NUM];
void ADC_Init() {  hadc1.Instance = ADC1;  hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;  hadc1.Init.Resolution = ADC_RESOLUTION_12B;  hadc1.Init.ScanConvMode = ENABLE;  hadc1.Init.ContinuousConvMode = ENABLE;  hadc1.Init.DiscontinuousConvMode = DISABLE;  hadc1.Init.NbrOfDiscConversion = 0;  hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;  hadc1.Init.DMAContinuousRequests = ENABLE;  HAL_ADC_Init(&hadc1);
  ADC_ChannelConfTypeDef sConfig = {0};  for(int i=0; i<CELL_NUM; i++) {    sConfig.Channel = ADC_CHANNEL_0 + i;    sConfig.Rank = i+1;    sConfig.SamplingTime = ADC_SAMPLETIME_480CYCLES;    HAL_ADC_ConfigChannel(&hadc1, &sConfig);  }  HAL_ADC_Start_DMA(&hadc1, (uint32_t*)adc_buffer, CELL_NUM);}

>軟件濾波算法

// 滑動平均濾波實現(xiàn)#define FILTER_WINDOW 8typedef struct {  float buffer[FILTER_WINDOW];  uint8_t index;} MovingAverage;
float filter_voltage(MovingAverage* filter, float new_val) {  filter->buffer[filter->index] = new_val;  filter->index = (filter->index + 1) % FILTER_WINDOW;    float sum = 0;  for(int i=0; i<FILTER_WINDOW; i++) {    sum += filter->buffer[i];  }  return sum / FILTER_WINDOW;}

 

相關(guān)推薦