PID算法实战之利用PWM控制LED以使光敏电阻稳定在特定值

来源:互联网 发布:oracle数据导入sql文件 编辑:程序博客网 时间:2024/05/16 09:41

上一篇博客简单的利用程序模拟飞行器定高的算法

本次我们来利用最常用的 LED和光敏电阻配合STM32实战

原理也很简单

我们可以通过STM32pwm输出控制发光二极管亮度

光敏电阻会随着LED亮度变化而改变阻值(在黑暗环境下实验排除其他光源干扰)

通过pid算法让光敏电阻稳定在特定值(比如我设定的是6000欧)

我们用的单片机时stm32f103RC很常见的一款 然后配合J-LINK在线调试(debug)读取电阻阻值(其实是比较懒不想输出到显示屏上哈哈)


然后pid算法可以参考上一篇博客

不同的是因为LED亮度增大导致光敏电阻阻值减小,也就是说两者负相关,所以PWM输出时应减去pid计算后的值


然后贴上主程序代码以及截图

#include "led.h"#include "delay.h"#include "sys.h"#include "usart.h"#include "lcd.h"#include "adc.h"#include "pwm.h"#include "stm32f10x_tim.h"/*从程序说明 利用pid调节pwm输出控制LED亮度达到使光敏电阻在稳定在6000欧?接线为LED两端接PA7和VCC光敏电阻与10K标准电阻串联接在3.3V与GND之间然后标准电阻两端接PA1与GND两端通过AD测的电压继而计算得到光敏电阻阻值*/double res,target,err_now,err_old,rat;  //分别为当前阻值,目标阻值,当前(目标值与当前阻值)差值,上一次差值typedef struct{double p;double i;double d;}pid;typedef struct{double kp;double ki;double kd;}Kpid; int main(void) { pid light = {0,0,0};Kpid Klight = {5,0.1,0.5};u16 adcx,pwm_value=300;float temp;target = 6000.0;err_old = 0;rat = 10; //表示 pid后的值与输出值之间的系数delay_init();     //延时函数初始化  uart_init(9600); //串口初始化为9600LED_Init();  //初始化与LED连接的硬件接口PWM_Init(899,0);// LCD_Init(); Adc_Init();  //ADC初始化    while(1){adcx=Get_Adc_Average(ADC_Channel_1,10);temp=(float)adcx*(3.3/4096);adcx=temp;res = (double)(3.3-temp)/temp*10000;temp-=adcx;temp*=1000;LED0=!LED0;/*pid control*/err_now = target - res;/*target res量级为10000 所以归一化err_now*/err_now /= 10000;light.p = err_now;light.i += err_now;light.d = err_now - err_old;pwm_value = pwm_value - ( Klight.kp*light.p + Klight.ki*light.i + Klight.kd*light.d ) * rat;err_old = err_now;  TIM_SetCompare2(TIM3,pwm_value);delay_ms(250);}    }


还有其他的库函数代码太多就不贴了



以及线路图


1 0