基于STM32的桌面数控电源项目连载
基于STM32的桌面數(shù)控電源項(xiàng)目連載
一個(gè)數(shù)控桌面電源項(xiàng)目
文章目錄
- 基于STM32的桌面數(shù)控電源項(xiàng)目連載
- 前言
- 一、尺寸與外觀
- 二、元器件選型
- 1.升壓芯片
- 2.輔助電源
- 3.參考電源
- 4.電流檢測(cè)
- 4.溫度檢測(cè)
- 5.MCU
- 6.OLED
- 三、原理圖
- 1.電源部分
- 2.中控部分
- 3.顯示部分
- 四、PCB部分
- 1.電源部分
- 2.控制部分
- 3.顯示部分
- 五、說(shuō)說(shuō)原理
- 1.電壓控制部分
- 2.傳感器(電壓、電流、溫度)
- 3.PID算法
- 六、建模
- 七、制造過(guò)程
- 1.電源板
- 2.主控板
- 3.顯示面板
- 八、測(cè)試
- 1.開(kāi)機(jī)動(dòng)畫(huà)
- 2.過(guò)溫保護(hù)
- 3.過(guò)流保護(hù)
- 4.精度測(cè)試
- 5.使用測(cè)試
- 九、資料
- 1.PCB
- 2.源碼
- 3.外殼
- 總結(jié)
前言
作為一個(gè)大學(xué)僧,成品可調(diào)電源笨重且占據(jù)桌面空間;而市售USB升壓模塊2、3W的功率是在不堪大用。于是,博主將從零開(kāi)始,研發(fā)一款實(shí)用的桌面可調(diào)電源。
一、尺寸與外觀
尺寸上,該桌面電源參考華為22.5WSCP充電器,與華為系列快充較好兼容。
二、元器件選型
1.升壓芯片
為最大限度兼容PD/SCP/FCP/QC等協(xié)議,該電路模塊需要有寬電壓輸入范圍。主升壓芯片選用XL6019。該芯片為TO263-5封裝,最大電流5A,輸出電壓-0.3~60V,能夠滿足日常實(shí)用需求。
2.輔助電源
輔助電源供給STM32和OLED面板,要求并不高,選熟悉的3.3V線性穩(wěn)壓芯片即可。這里選用的是HT7333。
3.參考電源
參考電源輸入STM32的Vbat引腳,作為基準(zhǔn)電壓使用,一定程度上決定了電源的精度。若要求不高,可直接并入輔助電源。這里使用一顆TL431,分壓電阻為1.33K和4.22k。(TL431分壓電阻的計(jì)算小工具放在下面鏈接中)
4.電流檢測(cè)
由于本人不想搭模電電路,所以選用了德州儀器的電流檢測(cè)芯片INA180A3IDBVR,該型號(hào)芯片可以將檢流電阻上的微小電壓放大100倍,使用十分方便。
4.溫度檢測(cè)
選用溫度傳感器TC1047AVNBTR,該型號(hào)芯片輸出與溫度呈線性關(guān)系的電壓值,使用起來(lái)較為方便。
5.MCU
通過(guò)分析,MCU至少具備3路ADC(電流、電壓、溫度),一路DAC(控制電壓),一路SPI(OLED),一路UART(擴(kuò)展藍(lán)牙)。事實(shí)上,許多單片機(jī)不具備DAC,而因?yàn)閼胁幌朐黾覦AC芯片,所以選型比較受限制。最終選擇STM32F103RCT6。(千萬(wàn)不要買RBT6,RBT6沒(méi)有DAC!!!)
6.OLED
沒(méi)啥好說(shuō)的,爛大街的0.91寸SPI OLED(中景園15腳),放個(gè)圖,溜了。
三、原理圖
1.電源部分
2.中控部分
3.顯示部分
四、PCB部分
PCB分為三層,采用排針及FCP排線連接,方便不同模塊升級(jí)及替換。
1.電源部分
2.控制部分
3.顯示部分
五、說(shuō)說(shuō)原理
1.電壓控制部分
事實(shí)上,任何一款市售的電源模塊通過(guò)簡(jiǎn)單的改造均可實(shí)現(xiàn)數(shù)控。
5腳為電源的反饋引腳,查閱芯片手冊(cè),Vfb=1.25V,即該引腳上的電壓高于1.25V,MOS管關(guān)閉,否則MOS導(dǎo)通,從而實(shí)現(xiàn)電壓的控制。
分析電路可得公式:(Vo-Vfb)/R2 + ( Vdac-VF)/R6 = Vfb/R9(VF為二極管得壓降)
即可得到輸出電壓。
在本方案中R2=4.7K,R9=91K,R6=5.6K,可實(shí)現(xiàn)4.5~25V的調(diào)壓范圍。
2.傳感器(電壓、電流、溫度)
無(wú)非就是尋常的多通道ADC檢測(cè)+多次采樣平均+DMA傳輸。多通道ADC與DMA配置如下。
void Adc_Init(void) { GPIO_InitTypeDef GPIO_InitStructure;ADC_InitTypeDef ADC_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA| RCC_APB2Periph_ADC1 | RCC_APB2Periph_AFIO, ENABLE ); //RCC_APB2Periph_GPIOx,x=GPIOxRCC_ADCCLKConfig(RCC_PCLK2_Div8); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2; //PA0/1/2/3 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; GPIO_Init(GPIOA, &GPIO_InitStructure);ADC_DeInit(ADC1); //??íaéè ADC1 μ?è?2???′??÷??éè?aè±ê??μADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //ADC1¤×÷?£ê?:ADC1oíADC21¤×÷?ú?àá¢?£ê?ADC_InitStructure.ADC_ScanConvMode =ENABLE; //?àD?μàé¨?è?£ê?ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; //?£êy×a??1¤×÷?úá?D?×a???£ê?ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //ía2?′¥·¢×a??1?±?ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //ADCêy?Yóò????ADC_InitStructure.ADC_NbrOfChannel = 3; //′?′|?a6??D?μࣨ?é?aμ??a1~16£?ADC_Init(ADC1, &ADC_InitStructure); //?ù?YADC_InitStruct?D???¨μ?2?êy3?ê??ˉíaéèADCxμ???′??÷//ADC3£1?D?μà????//ADC1,ADCí¨μàx,1??ò2é?ù?3Dò?μ?ay,2é?ùê±???a239.5?ü?úADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_13Cycles5 ); ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 2, ADC_SampleTime_13Cycles5 );ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 3, ADC_SampleTime_13Cycles5 ); // ?a??ADCμ?DMA?§3?£¨òaêμ??DMA1|?ü£??1Dè?àá¢????DMAí¨μàμè2?êy£?ADC_DMACmd(ADC1, ENABLE); //ê1?üADC1μ?DMA′?ê? ADC_Cmd(ADC1, ENABLE); //ê1?ü???¨μ?ADC1ADC_ResetCalibration(ADC1); //?′?????¨μ?ADC1μ?D£×???′??÷while(ADC_GetResetCalibrationStatus(ADC1)); //??è?ADC1?′??D£×???′??÷μ?×′ì?,éè??×′ì??òμè′yADC_StartCalibration(ADC1); //?aê????¨ADC1μ?D£×?×′ì?while(ADC_GetCalibrationStatus(ADC1)); //??è????¨ADC1μ?D£×?3ìDò,éè??×′ì??òμè′y } void DMA_Config(DMA_Channel_TypeDef* DMA_CHx,u32 cpar,u32 cmar,u16 cndtr) { DMA_InitTypeDef DMA_InitStructure; RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); DMA_DeInit(DMA_CHx); //??DMAμ?í¨μà1??′??÷??éè?aè±ê??μDMA_InitStructure.DMA_PeripheralBaseAddr = cpar; //DMAíaéèADC?ùμ??·DMA_InitStructure.DMA_MemoryBaseAddr = cmar; //DMA?ú′??ùμ??·DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; //?ú′?×÷?aêy?Y′?ê?μ???μ?μ?DMA_InitStructure.DMA_BufferSize = cndtr; //DMAí¨μàμ?DMA?o′?μ?êy?Yμ¥?a′óD?DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //íaéèμ??·??′??÷2?±?DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //?ú′?μ??·??′??÷μY??DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //êy?Y?í?è?a16??DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; //êy?Y?í?è?a16??DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; //?-?·1¤×÷?£ê?DMA_InitStructure.DMA_Priority = DMA_Priority_High; //DMAí¨μà xóμóD??ó??è?? DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //DMAí¨μàx??óDéè???a?ú′?μ??ú′?′?ê?DMA_Init(DMA_CHx, &DMA_InitStructure); //?ù?YDMA_InitStruct?D???¨μ?2?êy3?ê??ˉDMAμ?í¨μà }3.PID算法
算法沒(méi)啥稀奇,普通PID,輸入電壓,調(diào)整DAC。直接放代碼。
#ifndef _pid_ #define _pid_ #include "stm32f10x_conf.h" #define MODEL_P 1 #define MODEL_PI 2 #define MODEL_PID 3typedef struct {u8 choose_model; float curr; float set; //ó??§éè?¨?μfloat En; //μ±?°ê±?ìfloat En_1; //?°ò?ê±?ìfloat En_2; //?°?tê±?ìfloat Kp; //Pfloat T; //2é?ù?ü?úu16 Tdata; //?D??ê?·?μ?2é?ù?ü?úfloat Ti; //ifloat Td; //dfloat Dout; //PID??á?float OUT0; //???èê?3?u16 currdac; //μ±?°dac?μu16 daccycle; //pwm??}PID;extern u8 STATUS; extern PID pid; void PIDParament_Init(void); void pid_calc(void); #endif #include "pid.h" #include "dac.h" #include "dac.h" #include "led.h"PID pid;void PIDParament_Init() // {pid.choose_model = MODEL_PID;pid.T=50; //?¨ê±?÷1ms ×?D?2é?ù?ü?ú330mspid.set =5.0; //ó??§éè?¨?μpid.Kp=0.4; //±èày?μêypid.Ti=80; //?¢·??μêy3£êypid.Td=2; //?y·?ê±??3£êypid.OUT0=0; //??3??μêypid.daccycle = 50; //PWM pid.currdac=2000; }void pid_calc() {float dk1,dk2;float t1,t2,t3;u16 temp; // // if(pid.Tdata < (pid.T)) //×?D??????ü?ú?′μ? // { // return ; // } // pid.Tdata = 0;pid.En=pid.set-pid.curr; //±?′??ó2?dk1=pid.En-pid.En_1; //±?′??ó2?ó?é?′??ó2???2?dk2=pid.En-2*pid.En_1+pid.En_2;t1=pid.Kp*dk1; //±èàyt2=(pid.Kp*pid.T)/pid.Ti; //?y·?t2=t2*pid.En;t3=(pid.Kp*pid.Td)/pid.T; //?¢·?t3=t3*dk2;switch(pid.choose_model){case MODEL_P: pid.Dout= t1; break;case MODEL_PI: pid.Dout= t1+t2; break;case MODEL_PID: pid.Dout= t1+t2+t3; //????PID??á?break;} pid.currdac-=77.69*pid.Dout; //ê?3?dac?μif(pid.currdac>4090) //D£?é·??§{pid.currdac=4090;}if(pid.currdac<2000){pid.currdac=2000;}pid.En_2=pid.En_1;pid.En_1=pid.En;temp=pid.currdac;temp=(int)pid.currdac;temp=(short)temp;DAC_SetChannel1Data(DAC_Align_12b_R,temp );}六、建模
開(kāi)篇說(shuō)了,要和手頭華為快充配套,那自然是大小,材質(zhì)一樣咯。
話說(shuō)立創(chuàng)EDA不能導(dǎo)出STEP是真蛋疼,三維模型折騰了好久,話說(shuō)有興趣可以開(kāi)一貼,如何從立創(chuàng)EDA導(dǎo)出三維模型(很煩很煩)。
建模和渲染都是基于Solidworks.
殼體
效果圖
七、制造過(guò)程
1.電源板
調(diào)壓測(cè)試,最高25V.
2.主控板
平平無(wú)奇的STM32開(kāi)發(fā)板
囊中羞澀的我并沒(méi)有買藍(lán)牙模塊,藍(lán)牙原計(jì)劃選的是易佰特E14 BT05。
3.顯示面板
顯示面板焊接不要太久,我有個(gè)賊漂亮的橙色OLED被我焊的光衰了,基本看不出了字,誰(shuí)有橙色0.91 SPI OLED的購(gòu)買方式麻煩私我一下,謝謝啦。
八、測(cè)試
1.開(kāi)機(jī)動(dòng)畫(huà)
2.過(guò)溫保護(hù)
警報(bào)燈亮起,屏幕顯示溫度計(jì)圖標(biāo)。
3.過(guò)流保護(hù)
警報(bào)燈亮起,屏幕顯示電流,輸出切斷。
看官老爺對(duì)不住,實(shí)在沒(méi)抓拍到。
4.精度測(cè)試
輸出10.10V,實(shí)測(cè)10.08~10.11浮動(dòng),可以接受,加個(gè)大電容會(huì)好一些。
5.使用測(cè)試
該表通過(guò)中鍵切換模式,有電流/電壓、溫度/功率、循環(huán)三檔。
左右鍵選擇電壓,步進(jìn)0.5v.
九、資料
1.PCB
https://download.csdn.net/download/YVONNEOH/12740947
2.源碼
https://download.csdn.net/download/YVONNEOH/12740952
3.外殼
https://download.csdn.net/download/YVONNEOH/12740960
總結(jié)
外殼還沒(méi)加工好,待更,勿催。。。
最后,在評(píng)論區(qū)評(píng)論+暗號(hào)awsl,抽一個(gè)人送一套PCB郵費(fèi)自理,截止日期2020.9.10.
總結(jié)
以上是生活随笔為你收集整理的基于STM32的桌面数控电源项目连载的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 【缓存】数据库缓存
- 下一篇: 前端笔记-echarts加载geo地图