基于STM32的桌面数控电源项目连载

基于STM32的桌面数控电源项目连载

一个数控桌面电源项目


![在这里插入图片描述](https://img-blog.csdnimg.cn/20200823153042355.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L1lWT05ORU9I,size_16,color_FFFFFF,t_70#pic_center)

前言

作为一个大学僧,成品可调电源笨重且占据桌面空间;而市售USB升压模块2、3W的功率是在不堪大用。于是,博主将从零开始,研发一款实用的桌面可调电源。

在这里插入图片描述


一、尺寸与外观

尺寸上,该桌面电源参考华为22.5WSCP充电器,与华为系列快充较好兼容。
在这里插入图片描述

二、元器件选型

1.升压芯片

为最大限度兼容PD/SCP/FCP/QC等协议,该电路模块需要有宽电压输入范围。主升压芯片选用XL6019。该芯片为TO263-5封装,最大电流5A,输出电压-0.3~60V,能够满足日常实用需求。
在这里插入图片描述

2.辅助电源

辅助电源供给STM32和OLED面板,要求并不高,选熟悉的3.3V线性稳压芯片即可。这里选用的是HT7333。
在这里插入图片描述

3.参考电源

参考电源输入STM32的Vbat引脚,作为基准电压使用,一定程度上决定了电源的精度。若要求不高,可直接并入辅助电源。这里使用一颗TL431,分压电阻为1.33K和4.22k。(TL431分压电阻的计算小工具放在下面链接中)
在这里插入图片描述

4.电流检测

由于本人不想搭模电电路,所以选用了德州仪器的电流检测芯片INA180A3IDBVR,该型号芯片可以将检流电阻上的微小电压放大100倍,使用十分方便。
在这里插入图片描述

4.温度检测

选用温度传感器TC1047AVNBTR,该型号芯片输出与温度呈线性关系的电压值,使用起来较为方便。

在这里插入图片描述

5.MCU

通过分析,MCU至少具备3路ADC(电流、电压、温度),一路DAC(控制电压),一路SPI(OLED),一路UART(扩展蓝牙)。事实上,许多单片机不具备DAC,而因为懒不想增加DAC芯片,所以选型比较受限制。最终选择STM32F103RCT6。(千万不要买RBT6,RBT6没有DAC!!!

6.OLED

没啥好说的,烂大街的0.91寸SPI OLED(中景园15脚),放个图,溜了。

在这里插入图片描述

三、原理图

1.电源部分

在这里插入图片描述

2.中控部分

在这里插入图片描述

3.显示部分

在这里插入图片描述

四、PCB部分

PCB分为三层,采用排针及FCP排线连接,方便不同模块升级及替换。

1.电源部分

在这里插入图片描述

2.控制部分

在这里插入图片描述

3.显示部分

在这里插入图片描述

五、说说原理

1.电压控制部分

事实上,任何一款市售的电源模块通过简单的改造均可实现数控。
在这里插入图片描述
5脚为电源的反馈引脚,查阅芯片手册,Vfb=1.25V,即该引脚上的电压高于1.25V,MOS管关闭,否则MOS导通,从而实现电压的控制。
分析电路可得公式:(Vo-Vfb)/R2 + ( Vdac-VF)/R6 = Vfb/R9(VF为二极管得压降)
即可得到输出电压。
在本方案中R2=4.7K,R9=91K,R6=5.6K,可实现4.5~25V的调压范围。

2.传感器(电压、电流、温度)

无非就是寻常的多通道ADC检测+多次采样平均+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=GPIOx
	    RCC_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);  //½«ÍâÉè ADC1 µÄÈ«²¿¼Ä´æÆ÷ÖØÉèΪȱʡֵ
        ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;        //ADC¹¤×÷ģʽ:ADC1ºÍADC2¹¤×÷ÔÚ¶ÀÁ¢Ä£Ê½
        ADC_InitStructure.ADC_ScanConvMode =ENABLE;        //¶àÐŵÀɨÃèģʽ
        ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;  //Ä£Êýת»»¹¤×÷ÔÚÁ¬Ðøת»»Ä£Ê½
        ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;   //Íⲿ´¥·¢×ª»»¹Ø±Õ
        ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;        //ADCÊý¾ÝÓÒ¶ÔÆë
        ADC_InitStructure.ADC_NbrOfChannel = 3;        //´Ë´¦¿ª6¸öÐŵÀ£¨¿É¿ªµÄΪ1~16£©
        ADC_Init(ADC1, &ADC_InitStructure);        //¸ù¾ÝADC_InitStructÖÐÖ¸¶¨µÄ²ÎÊý³õʼ»¯ÍâÉèADCxµÄ¼Ä´æÆ÷
        
		//ADC³£¹æÐŵÀÅäÖÃ
        //ADC1,ADCͨµÀx,¹æÔò²ÉÑù˳ÐòֵΪy,²ÉÑùʱ¼äΪ239.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 );                

         // ¿ªÆôADCµÄDMAÖ§³Ö£¨ÒªÊµÏÖDMA¹¦ÄÜ£¬»¹Ðè¶ÀÁ¢ÅäÖÃDMAͨµÀµÈ²ÎÊý£©
         ADC_DMACmd(ADC1, ENABLE);       //ʹÄÜADC1µÄDMA´«Êä         
         ADC_Cmd(ADC1, ENABLE);           //ʹÄÜÖ¸¶¨µÄADC1
         ADC_ResetCalibration(ADC1);        //¸´Î»Ö¸¶¨µÄADC1µÄУ׼¼Ä´æÆ÷
         while(ADC_GetResetCalibrationStatus(ADC1));        //»ñÈ¡ADC1¸´Î»Ð£×¼¼Ä´æÆ÷µÄ״̬,ÉèÖÃ״̬ÔòµÈ´ý
         ADC_StartCalibration(ADC1);                //¿ªÊ¼Ö¸¶¨ADC1µÄУ׼״̬
         while(ADC_GetCalibrationStatus(ADC1));                //»ñÈ¡Ö¸¶¨ADC1µÄУ׼³ÌÐò,ÉèÖÃ״̬ÔòµÈ´ý
}				  

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¼Ä´æÆ÷ÖØÉèΪȱʡֵ
    DMA_InitStructure.DMA_PeripheralBaseAddr =  cpar;  //DMAÍâÉèADC»ùµØÖ·
    DMA_InitStructure.DMA_MemoryBaseAddr = cmar;  //DMAÄÚ´æ»ùµØÖ·
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;  //ÄÚ´æ×÷ΪÊý¾Ý´«ÊäµÄÄ¿µÄµØ
    DMA_InitStructure.DMA_BufferSize = cndtr;  //DMAͨµÀµÄDMA»º´æµÄÊý¾Ýµ¥Ôª´óС
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;  //ÍâÉèµØÖ·¼Ä´æÆ÷²»±ä
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;  //ÄÚ´æµØÖ·¼Ä´æÆ÷µÝÔö
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;  //Êý¾Ý¿í¶ÈΪ16λ
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; //Êý¾Ý¿í¶ÈΪ16λ
    DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;  //Ñ­»·¹¤×÷ģʽ
    DMA_InitStructure.DMA_Priority = DMA_Priority_High; //DMAͨµÀ xÓµÓиßÓÅÏȼ¶ 
    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;  //DMAͨµÀxûÓÐÉèÖÃΪÄÚ´æµ½ÄÚ´æ´«Êä
    DMA_Init(DMA_CHx, &DMA_InitStructure);  //¸ù¾ÝDMA_InitStructÖÐÖ¸¶¨µÄ²ÎÊý³õʼ»¯DMAµÄͨµÀ
}


3.PID算法

算法没啥稀奇,普通PID,输入电压,调整DAC。直接放代码。

#ifndef _pid_
#define _pid_
#include "stm32f10x_conf.h"
#define     MODEL_P         1
#define     MODEL_PI         2
#define     MODEL_PID     3

typedef struct
{
    u8 choose_model;    
    
  float curr;              
    float set;               //Óû§É趨ֵ
    

    float En;                    //µ±Ç°Ê±¿Ì
    float En_1;                //ǰһʱ¿Ì
    float En_2;                //Ç°¶þʱ¿Ì
        
    float Kp;               //P
    float T;                //²ÉÑùÖÜÆÚ
    u16   Tdata;            //ÅжÏÊÇ·ñµ½²ÉÑùÖÜÆÚ
    float Ti;               //i
    float Td;               //d
    
    float Dout;                //PIDÔöÁ¿
    float OUT0;                //άÎÈÊä³ö
    
    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 ×îС²ÉÑùÖÜÆÚ330ms
    pid.set =5.0;            //Óû§É趨ֵ
    pid.Kp=0.4;                //±ÈÀýϵÊý
    pid.Ti=80;                //΢·ÖϵÊý³£Êý
    pid.Td=2;                //»ý·Öʱ¼ä³£Êý
    pid.OUT0=0;                //ά³ÖϵÊý
    pid.daccycle = 50;       //PWM 
	  pid.currdac=2000;
}

    
void pid_calc()  
{
  float dk1,dk2;
  float t1,t2,t3;
	u16 temp;
//    
//    if(pid.Tdata < (pid.T))  //×îС¼ÆËãÖÜÆÚδµ½
//     {
//            return ;
//     }
//    pid.Tdata = 0;
    
    pid.En=pid.set-pid.curr;  //±¾´ÎÎó²î
    dk1=pid.En-pid.En_1;   //±¾´ÎÎó²îÓëÉÏ´ÎÎó²îÖ®²î
    dk2=pid.En-2*pid.En_1+pid.En_2;
    
    t1=pid.Kp*dk1;                            //±ÈÀý
    
    t2=(pid.Kp*pid.T)/pid.Ti;      //»ý·Ö
    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;  //Êä³ödacÖµ
    
    if(pid.currdac>4090)            //УÑ鷶Χ
    {
      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 );
    
    
    
    

}

六、建模

开篇说了,要和手头华为快充配套,那自然是大小,材质一样咯。

话说立创EDA不能导出STEP是真蛋疼,三维模型折腾了好久,话说有兴趣可以开一贴,如何从立创EDA导出三维模型(很烦很烦)。

建模和渲染都是基于Solidworks.
壳体
在这里插入图片描述
效果图
在这里插入图片描述

七、制造过程

1.电源板

在这里插入图片描述
在这里插入图片描述
调压测试,最高25V.
在这里插入图片描述

2.主控板

平平无奇的STM32开发板
在这里插入图片描述
囊中羞涩的我并没有买蓝牙模块,蓝牙原计划选的是易佰特E14 BT05。
在这里插入图片描述
在这里插入图片描述

3.显示面板

在这里插入图片描述
在这里插入图片描述
显示面板焊接不要太久,我有个贼漂亮的橙色OLED被我焊的光衰了,基本看不出了字,谁有橙色0.91 SPI OLED的购买方式麻烦私我一下,谢谢啦。

八、测试

1.开机动画

在这里插入图片描述

2.过温保护

在这里插入图片描述
警报灯亮起,屏幕显示温度计图标。

3.过流保护

警报灯亮起,屏幕显示电流,输出切断。
看官老爷对不住,实在没抓拍到。

4.精度测试

在这里插入图片描述
输出10.10V,实测10.08~10.11浮动,可以接受,加个大电容会好一些。

5.使用测试

该表通过中键切换模式,有电流/电压、温度/功率、循环三档。
左右键选择电压,步进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

总结

外壳还没加工好,待更,勿催。。。
最后,在评论区评论+暗号awsl,抽一个人送一套PCB邮费自理,截止日期2020.9.10.

前言: 美国Vicor公司是现时世界最大的高密度电源模块生产商, 同时也是全球唯一能以零电压、零电流技术大批量生产电源模块的厂家。Vicor电源模块包括DC-DC、AC-DC电源模块,隔离、非隔离电源模块转换器。其中VICOR公司电源模块的核心技术是 “零电流”开关,它使变换器的工作频率达到 了1MHz,效率大于80%。 本文介绍多功能数控电源设计 从最基本的说起吧,DC-DC的变换电路有很多种,线性电源、开关电源、电荷泵,线性电源大家比较熟悉的应该就是78XX系列的芯片了,电荷泵主要用在小电流的应用中,我们也不加讨论。主要讲讲开关电源,我呢也是一个先学先卖的人,就对照资料啥的随便介绍下拉,权当是开源本设计前的一点准备工作。 开关稳压器的工作原理,就是通过控制电路来控制开关器件的通断,配合负反馈完成稳压,跟线性稳压比起来,具有效率高体积小的特点,但是输出没有线性电源稳定。开关电源的基本结构有很多种,包括BUCK、BOOST、BUCK-BOOST、CUK等非隔离式的DCDC变换器,也有Flyback、LLC等隔离式的DCDC变换器。 开源的这个设计,是以buck拓扑为核心,配合STM32F334的高级定时器的PWM、PI算法,实现的一个很简单的闭环控制,设计输入电压60V时,输出电压可调,输出电流最大5A,输出最大功率在200W左右。 数控电源系统设计框图: 首先说明我这款电压是从HP电源的基础上增加人机界面和改善栅极驱动做的,具体设计心得及电路分析详见附件内容。 数控电源程序的设计思路: 因为这款设计为了尽可能减少体积,因此使用了较大频率的PWM波,取值为250k,所采用的主控stm32f334是意法半导体专为数控电源所设计的一款MCU。STM32F334xx微控制器具有高分辨率定时器(HRTIM)外设,可产生多达10个信号,能够处理用于控制、同步或保护的各种不同输入信号。其模块化架构允许对大部分转换拓扑和多并联转换器进行处理,并可在运行中重新配置它们。(具体详见附件内容) 配置的代码和PI算法的代码部分截图展示:
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

YVONNEOH

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值