找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4576|回复: 0
打印 上一主题 下一主题
收起左侧

基于stm8的pid控制器课程设计

[复制链接]
跳转到指定楼层
楼主
ID:83710 发表于 2015-6-25 02:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
                               孙鹏
   摘要:
随着信息技术的发展,越来越多的电子设备开始变得智能化。对于传统pid控制法,在一些简单,精度要求低的场所下,起着很重要的作用,本文介绍实习过程中做pid电机调速的一些心得。
一题目要求:
本题是以8/16位微控制器为基础,实现小型直流电机闭环调速功能,设计PID数字控制器。
具体设计要求:熟悉微控制器,选择适合的微控制器芯片;设计转速编码检测、驱动调节设计;实现PID闭环控制设计,电机速度由按键分段给定或电位器连续给定,数码管跟踪显示当前给定速度和电机实际运行速度,实现PID参数在线显示和修改;完成硬件电路设计和测控程序的设计;文挡整理,撰写报告。

二题目理解:
因为之前焊了了stm8开发板,而stm8作为意法半导体的一款8mcu,自带ad,定时器,捕获,电机控制pwm波,完全能够满足题目8位微处理器的要求。实现直流电机闭环控制,即需要用pid 控制,因为之前风驰电掣比赛上有看过,所以代码也很简单。
我选用的是stm103k3t6,8kflash,1kram640bitepprom.内置高级定时器time1,通用定时器(16位)timer2,8位定时器time4.电机使用废弃的剃须刀上的马达,传感器是用100k的光敏电阻和100mw的激光头,电机驱动使用航模通用nmosst2302.使用锂电池供电,lcd1602作为显示模块,红外遥控作为控制键盘。
三硬件设计3.1CPU选择因为stm3232位单片机,而43016位单片机,c518位单片机。用stm32430均可实现本题的要求,但用c51来完成本题恐怕有些挑战性。为了用最简单的方法完成本题,我选用了stm8103k3t6.8位单片机中性价比之王。其内部结构如图一所示:

图一
3.2显示模块:   因为题目要求显示模块需要显示当前速度和设定速度外,还需要能够修改pid的参数,所以选择了最通用的显示屏幕lcd1602.
3.3控制模块
因为之前用过按键扫描和按键中断的函数,但发现按键需要延时,很浪费CPU资源,所以选择用红外发射接收模块。既可拓展功能,又可节省CPU资源,最大的好处就是不用触摸按键,桌面的抖动可能导致光电传感器检测到的计数脉冲不准确。
3.4电源部分
电源为自己手机电池,系统工作电流120ma-200ma,待机电流80ma左右。而电池的电量为2100ma/h。实际在带电机工作情况下可以工作5小时上。
为了方便电池充电,本系统自带锂电池专用充电芯片tp4056.
为了给系统提供稳定的5v电源,本系统采用了专用700ma5v升压模块,实际测得升压模块输出电压为5.1-5.2v。可以给系统大部分电路供电。
3.5驱动模块
为了给电机添上驱动,我开始考虑到lm298,但其体积庞大,需要7v以上电源。但我发现了一款实用的nmosst2302,航模经典驱动芯片,3.3v就可以驱动。所以按照网上的电路图给焊接起来,发现确实管用。
3.6传感器
因为手上有激光头和光敏电阻,所以选择了激光头打在光敏电阻上产生脉冲波,实现转速测量。由逻辑器件产生电压比较输出脉冲波,由稳压二极管1n4733产生3.3v电压,供单片机采集脉冲。
四软件设计4.1pwm波生成     Pwm波由定时器2产生,初始化为1khzspwm波,占空比设置为1/10.通过在程序中调节定时器相关寄存器值可以改变pwm波的占空比。
4.2lcd显示     因为是用遥控控制lcd1602的翻页和相关参数的设置,所以我选择每1.4slcd屏幕上字幕刷新一次。如果刷新时间太短,红外遥控可能无法工作。当刷新时间太快时,字幕跳的太快会看不清字幕。
4.3脉冲捕获    我采用的是stm8外部中断源,当pc1捕获到上升沿时,改为下降沿捕获,连续一次上升沿和一次下降沿为一个周期,通过定时器4算出10个周期内时间,这样算10次,去掉最高值和最低值,即为平均值。

4.4pid算法     因为pi,pk,pd均为float值,而系统时钟只用16MHZ,用c语言编写需要消耗上百条指令周期,所以我将pid算法放入定时器4运算,每200ms运算一次。

                                                                                                      程序是我一个一个敲进去的

#pragma vector=0x07 // 这里很关键!看下面说明。
__interrupt void EXTI_PC1(void)
{
  asm("sim");
  switch(EXTI_CR1)
  {
  case 0x10:EXTI_CR1=0x20;exit_flag=1;break;
  case 0x20:EXTI_CR1=0x10;exit_flag=2;break;
  default :exit_flag=0;break;
  }
if(exit_flag==2)
{
    t++;
   exit_flag=0;
   if(t%10==0)
   {
      ulong chaju;
      now_nus=TIM4_CNTR;
      now_ms=cishu;
     chaju_ms=now_ms-last_ms;
   if(cishu_flag==1)
   {
     cishu_flag=0;
     chaju_ms=30000+now_ms-last_ms;
   }
      chaju_nus=now_nus-last_nus;
      chaju=chaju_ms*250+chaju_nus;
      now_rads=(1250000/chaju);
      last_nus=now_nus;
      last_ms=now_ms;
      last_rads[rads_flag++]=now_rads;
      if(rads_flag==10)
        rads_flag=0;

    pid_error1=pid_error;
    pid_error=set_rads-now_rads;

     pid_dt2=pid_dt1;
     pid_dt1=pid_error-pid_error1;
     last_radsss=last_radss;
     last_radss =now_rads;
   }
}

   asm("rim");
}

#pragma vector=TIM4_OVR_UIF_vector//0x19
__interrupt void TIM4_OVR_UIF_IRQHandler(void)//对应IAP的中断地址:0x8060
{
      ++cishu;

      TIM4_SR=0x00;     
      if(cishu==29999)
      {
        cishu_flag=1;
        cishu=0;
        minute++;
       ds1820_flag=0;
      }
      if(cishu%100==0)
       pid_caculate();

}
//pid算法核心
void pid_caculate()
{
   int ppk,ppi,ppd;
   ppk=(int)((long)(((int)(pk*100))*(pid_error))/100);
   ppi=(int)((long)(((int)(pi*100))*(pid_error-pid_error1))/100);
   ppd=(int)((long)(((int)(pd*100))*(pid_dt1-pid_dt2))/100);
   pid_out+=ppk-ppi+ppd;
   if(pid_out>2000)pid_out=2000;
   if(pid_out<800)pid_out=800;
   TIM2_CCR1H =pid_out/256;
   TIM2_CCR1L = pid_out%256;
}





分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表