数字恒流源(LM324运放+三极管+pid反馈采集)

您所在的位置:网站首页 反馈电路采样点 数字恒流源(LM324运放+三极管+pid反馈采集)

数字恒流源(LM324运放+三极管+pid反馈采集)

2024-07-16 07:24| 来源: 网络整理| 查看: 265

最近,在做课程设计了一款数字恒流源电路,其要求如下:

a)利用DA转换芯片输出200-1000mA电流信号 b)可设置并显示输出电流给定值 c)系统工作符合一般恒流源要求 d)可步进输出电流,步进值10mA e)保护电路

一、设计原理 (硬件部分)

通过STM32F103C8T6驱动MCP4725模块,产生模拟电压,模拟电压输入由LM324和S8050三极管构成的压控型恒流源,再通过采样电阻与恒流源电路串联进行差分运放电压采样,实现对电流的检测。将电流的检测结果送入STM32F103C8T6,进行PID运算,实现200-1000mA恒流源控制。 其Multism电路图如下: 在这里插入图片描述 压控恒流:如原理图,输入的电压为DAC4725输出的模拟电压Vin,该恒流源系统由LM324AD和三极管以及外部电阻构成,三极管采用8050能够实现集电极最大电流1.5A输出。图中RL2为负载电阻,R2为采样电阻,流过负载电阻的电为Vin/R2,LM324采用负反馈电路从而工作在线性区,由此有Vin=Up=Un,则R2的电流为Vin/R2。三极管集电极电流近似等于发射极电流,当流过的电流增大,R2的电流也会随之增大,进而电压增大,导致Un增大,(Up-Un)减小,从而运放输出减小,三极管电流减小,负载电流也会减小,R2电流随之减小,正是因为负反馈从而达到恒流目的。

差分运放:如图,电阻R1,R5分别接入到正向输入端和反向输入端,采集的电压信号分别从两端输入,输出端接入R6到反向输入端,同时正向输入端与地之间接入平衡电阻R8,其中R1=R5,反馈电阻为平衡电阻R8,从而构成对称电路。运放输出端为R6/(R8*(V1-V2 这是立创画的原理图

绘制原理框图,描述各功能单元之间的逻辑关系

在这里插入图片描述

1.软件部分 软件部分的代码使用的HAL 库编写的,原理如下:用iic驱动mcp4725模块,输出模拟电压,然后用c8t6自带的DA采集,采集电压,通过位置式pid计算,实现横流控制, 这里用的是HAL库,iic1和iic2分别驱动mcp4725芯片和oled屏幕;这里的mcp4725是一款集成的芯片,其实就是一个DA转换器,它用单片机输出的数字电压,产生一个模拟电压

这里是所需要的引脚配置,包括两个和IIC和一个串口(用于调试);KEY-1和KEY-2是外部中断,用来调节输出的电压 ADC1是用电电压采集的,目的是形成负反馈,pid闭环控制 这里是所需要的引脚配置,包括两个和IIC和一个串口(用于调试);KEY-1和KEY-2是外部中断,用来调节输出的电压 ADC1是用电电压采集的,目的是形成负反馈,pid闭环控制] 这里是两个IIC的配置,就是常规配置 标准模式100000HZ 这里是两个IIC的配置,就是常规配置 标准模式100000HZ] 这里是ADC 单通道 我选择的是IN0 加dma方式 [这里是ADC 单通道 我选择的是IN0 加dma方式]( 在这里插入图片描述

这里是两个按键的外部中断,目的是用于调节电压,控制输出电流 这里是两个按键的外部中断,目的是用于调节电压,控制输出电流 这里一定要注意打开外部中断 这里一定要注意打开外部中断](

在这里插入图片描述 这里是实物图 其中pid需要自己调试

所有的工程文件在这,包括multisim仿真和代码

链接:https://pan.baidu.com/s/18zVFmSFzKUN2d6Jb-nQy8g?pwd=7777 提取码:7777 –来自百度网盘超级会员V4的分享

代码如下(示例):

MX_GPIO_Init(); MX_DMA_Init(); MX_I2C2_Init(); MX_ADC1_Init(); MX_USART1_UART_Init(); MX_I2C1_Init(); /* USER CODE BEGIN 2 */ OLED_Init(); OLED_Clear(); PID_init(); HAL_ADCEx_Calibration_Start(&hadc1); // f1系列需要ADC校准,f4不需要 HAL_ADC_Start_DMA(&hadc1,(uint32_t )&ADC_DMA_Value,ADC_Channel_MAX); // 启动ADC的DMA转换 / USER CODE END 2 / / Infinite loop / / USER CODE BEGIN WHILE / while (1) { / USER CODE END WHILE */

/* USER CODE BEGIN 3 */ // OLED_FullyClear (); sprintf(i1_1, "Set i:%.1f mA", i1); sprintf(i2_2, "Acutal i:%.1f mA", i2); sprintf(i3_3, "Acutal V:%.1f V", i3); OLED_ShowString(4,2.,i1_1,1);//这个是oled驱动里面的,是显示位置的一个函数, OLED_ShowString(4,4,i2_2,1);//这个是oled驱动里面的,是显示位置的一个函数, OLED_ShowString(4,8,i3_3,1);//这个是oled驱动里面的,是显示位置的一个函数 ADC_Value = ADC_DMA_Value[0]; //printf("实际电压%0.1f \n",ADC_Value*5.0/4096.0);//测试时,串口调试 DAC_Value = DAC_Value + PID_realize((i1/1000)*RL, ADC_Value*5.0/4096.0); DAC_Value2 = DAC_Value*1.5;//硬件山的设计,采样的电压和实际的电压为1.5倍的关系 i3=ADC_Value*5.0/4096.0;

// /软件保护电路,如果计算出的输出电压过大,就关闭输出*******/ // if( DAC_Value2 >5.0) // { DAC_Value2 =0; // }

i2= (( ADC_Value*5.0/4096.0)*1000)/RL;//实际采集的电流 /*************************** //mcp4725的输出函数,当为5v接入时输出关系为 输入*1.2,当接入3.3v倍数为0.8 输入的单位为mV 比如输入3000 ,接入5v就输出3000*1.2=3600mV ;; ************************************/

// MCP4725_Out(&hi2c1,( DAC_Value2/1.2)*1000,1); MCP4725_Out(&hi2c1,3000,1); HAL_Delay(50); //printf(“输出电压%0.1d \n”, DAC_Value);

} /* USER CODE END 3 */ }

## 2.读入数据 代码如下(示例): #include "pid.h" #include "stdio.h" extern float i1 ; pid_p pid; //pid位置式 void PID_init() { // printf("PID_init begin \n"); pid.SetVoltage= 0.0; // 设定的预期电压值 pid.ActualVoltage= 0.0; // adc实际电压值 pid.err= 0.0; // 当前次实际与理想的偏差 pid.err_last=0.0; // 上一次的偏差 pid.voltage= 0.0; // 控制电压值 pid.integral= 0.0; // 积分值 pid.Kp= 0.5; // 比例系数 pid.Ki= 0.0; // 积分系数 pid.Kd= 0.0; // 微分系数 // printf("PID_init end \n"); } float PID_realize( float v, float v_r) { printf("设定值%0.1f \n", i1); pid.SetVoltage = v; // 固定电压值传入 pid.ActualVoltage = v_r; // 实际电压传入 = ADC_Value * 3.3f/ 4096 pid.err = pid.SetVoltage - pid.ActualVoltage; //计算偏差 pid.integral += pid.err; //积分求和 pid.result = pid.Kp * pid.err + pid.Ki * pid.integral + pid.Kd * ( pid.err - pid.err_last);//位置式公式 pid.err_last = pid.err; //留住上一次误差 //pid.ActualVoltage=pid.result*1.0; //实际角度应该由角度传感器+ADC返回 return pid.result; }


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3