搜索
bottom↓
回复: 5

继 前面的可控硅电机调速贴-----代码篇

[复制链接]

出0入0汤圆

发表于 2016-5-9 09:19:57 | 显示全部楼层 |阅读模式
本人,从初次接触松翰单片机到现在2个月了,从小白开始认识松翰单片机;有幸接触到了可控硅,又从小白认识可控硅电机调速;在茫茫的大海又 撞到难题,再次来这里寻求帮助。
上次发的汇编带反汇编的;看了一段时间,感觉难度好大,根本无法理解,所以自己用C写一个。
以下是本人写的C,写的不好。
问题点:
1、电机无法控速,上电直奔20000RMP,自己设定值在调不起作用?
2、本芯片支不支持本代码算法?
3、电机使用的是六级磁环,使用闭环调速,现在开环都无法做到控速?

        事先在在这感谢前辈,多多拍砖,指正错误!!交流地址:QQ_ 1151174742
————————————————————————————————————————————————————————————————————————————————————————————————————————————————
#include <SN8F27E65.h>

#define uint8        unsigned int
#define uchar8        unsigned char
#define        uint16        unsigned long
struct bitDefine{
                                unsigned bit0:1;
                                unsigned bit1:1;
                                unsigned bit2:1;
                                unsigned bit3:1;
                                unsigned bit4:1;
                                unsigned bit5:1;
                                unsigned bit6:1;
                                unsigned bit7:1;
                               
                                }Mode_Flag;
struct PIDValue{
                                uint16        liEkVal[3];        //差值保存,给定值和反馈值的差
                                uchar8        uEkFlag[3];        //符号,1 对应负数,0 对应正数
                                uchar8        uKP_Coe;        //比例系数
                                uchar8        uKI_Coe;        //积分系数
                                uchar8        uKD_Coe;        //微分系数
                                uint16        iPriVal;        //上一时刻的值
                                uint16        iSetVal;        //设定值
                                uint16        iCurVal;        //实际值

                                }PID;


#define Flag_AC_HI                 (Mode_Flag.bit0)
#define Flag_AC_LW                 (Mode_Flag.bit1)
#define Flag_AC_Point         (Mode_Flag.bit2)
#define Flag_Motor_Point         (Mode_Flag.bit3)
#define Flag_Hall_Point         (Mode_Flag.bit4)
#define Flag_Time_Point         (Mode_Flag.bit5)



void IO_Setting(void);
void Timer_Setting(void);
void Key_Scan(void);
void PID_Operation(void);
void Speed_Solver(void);


#define        AC_Point        FP04        //交流过零输入脚
#define        Motor_Out        FP03        //可控硅控制脚

#define Key_Select        FP43        //按键输入
#define Key_Auto        FP44
#define Key_Start        FP46
#define LED                        FP45


uint8 Key_Count_Select = 0;
uint8 Key_Count_Auto = 0;
uint8 Key_Count_Start = 0;

uint8        Time_CNT = 0;                //输出控制时间
uint8        Control_Speed = 0;        //
uint16        Hall_Speed_Cnt = 0;
uint16        Speed_Time_ms = 0;
//uint16        Speed_Time_s = 0;
//uint8        Speed_Time[2] ;
uint16        Speed_Value;
uint16        Set_Speed_Value;
uint8        Control_Speed_1 = 0;

void main(void)
{


       
  WDTR = 0x5A;
  IO_Setting();
  Timer_Setting();
  Time_CNT = 0;
  FGIE = 1;
  PID.uKP_Coe = 0;
  PID.uKI_Coe = 0;
  PID.uKD_Coe = 0;
  //LED = 0;

Set_Speed_Value = 40960;        //设置的速度值



        while(1)
        {


                if(!AC_Point)                //低
                 {

                        if(Flag_AC_HI == 1)
                        {        Flag_AC_HI = 0; Flag_AC_Point = 1;}
                         else
                        {Flag_AC_HI = 0;}

                 }
                else                                //高
                {

                        if(Flag_AC_HI == 0)
                        {        Flag_AC_HI = 1;        Flag_AC_Point = 1;}
                        else
                        {Flag_AC_HI = 1;}
                }

                while(Flag_AC_Point)
                {
                        Time_CNT = 0;
                        Flag_AC_Point = 0 ;
                        Flag_Motor_Point = 1;
               
       
                        //Control_Speed = 150;                        //0~900
                        PID_Operation();
                        Speed_Solver();

       
               
       

                }
        }
}
void PID_Operation(void)
{       
        uint16        Temp[3] = {0};        //中间变量
        uint16        PostSum = 0;        //正数和
        uint16        NegSum = 0;                //负数和

        PID.iCurVal = Speed_Value;        //测出来的实时值速度
        PID.iSetVal = Set_Speed_Value;        //设定值速度


        if(PID.iSetVal > PID.iCurVal)                        //设定值与实际值比较
        {
                Temp[0] = PID.iSetVal - PID.iCurVal ;//偏差值
       
                PID.uEkFlag[1] = 0;                                                                                //为正数

                PID.liEkVal[2] = PID.liEkVal[1];
                PID.liEkVal[1] = PID.liEkVal[0];
                PID.liEkVal[0] = Temp[0];

                if(PID.liEkVal[0] > PID.liEkVal[1] )                          //E(k)>E(k-1) 这一时刻值 大于 上一时刻的值
                        {
                                Temp[0] = PID.liEkVal[0] - PID.liEkVal[1];
                                PID.uEkFlag[0] = 0;                                                                       
                        }
                else                                                                                          //E(k)<E(k-1) 这一时刻值 小于 上一时刻的值
                        {
                                Temp[0] = PID.liEkVal[1] - PID.liEkVal[0];
                                PID.uEkFlag[0] = 1;       
                        }

                Temp[2] = 2 * PID.liEkVal[1];                                         //2*E(k-1) 上一时刻的值 * 2

                if((PID.liEkVal[0] + PID.liEkVal[2]) > Temp[2]) //这一时刻的值 与 上上次值 的和  大于 上一时刻的值 * 2
                        {
                                Temp[2] = (PID.liEkVal[0] + PID.liEkVal[2]) - Temp[2];
                                PID.uEkFlag[2] = 0;       
                        }
                else                                                                                        //这一时刻的值 与 上上次值 的和  小于 上一时刻的值 * 2
                        {
                                Temp[2] = Temp[2] - (PID.liEkVal[0] + PID.liEkVal[2]);
                                PID.uEkFlag[2] = 1;       
                        }

                        Temp[0] = (uint16)PID.uKP_Coe * Temp[0];                // P 乘以 这一时刻值 和 上一时刻的值 的差值
                        Temp[1] = (uint16)PID.uKI_Coe * PID.liEkVal[0]; // I
                        Temp[2] = (uint16)PID.uKD_Coe * Temp[2];                // D
                        /* 正数项叠加,负数项叠加 */
                        if(PID.uEkFlag[0] == 0)
                PostSum += Temp[0];                         //正数和
            else                                            
                NegSum += Temp[0];                          //负数和
            /* ========= 计算KI*E(k)的值 ========= */
            if(PID.uEkFlag[1] == 0)     
                PostSum += Temp[1];                         //正数和
            else
        
            /* ========= 计算KD*[E(k-2)+E(k)-2E(k-1)]的值 ========= */
            if(PID.uEkFlag[2]==0)
                PostSum += Temp[2];             //正数和
            else
                NegSum += Temp[2];              //负数和
            /* ========= 计算U(k) ========= */                        
            PostSum += (uint16)PID.iPriVal;         
            if(PostSum > NegSum)                 //是否控制量为正数
            {
                Temp[0] = PostSum - NegSum;
              
                PID.iPriVal = (uint16)Temp[0];
                                Flag_Motor_Point = 1;
               
            }
            else                                //控制量输出为负数,则输出0(下限幅值输出)
            {
                Temp[0] = NegSum - PostSum;
              
                PID.iPriVal = (uint16)Temp[0];
                                Flag_Motor_Point = 1;
               
            }

        }
        else
        {
                Temp[0] =  PID.iCurVal - PID.iSetVal ;//偏差值
       
                PID.uEkFlag[1] = 0;                                                                                //为正数

                PID.liEkVal[2] = PID.liEkVal[1];
                PID.liEkVal[1] = PID.liEkVal[0];
                PID.liEkVal[0] = Temp[0];

                if(PID.liEkVal[0] > PID.liEkVal[1] )  //E(k)>E(k-1)
                        {
                                Temp[0] = PID.liEkVal[0] - PID.liEkVal[1];
                                PID.uEkFlag[0] = 0;                                                                       
                        }
                else
                        {
                                Temp[0] = PID.liEkVal[1] - PID.liEkVal[0];
                                PID.uEkFlag[0] = 1;       
                        }

                Temp[2] = 2 * PID.liEkVal[1];

                if((PID.liEkVal[0] + PID.liEkVal[2]) > Temp[2])
                        {
                                Temp[2] = (PID.liEkVal[0] + PID.liEkVal[2]) - Temp[2];
                                PID.uEkFlag[2] = 0;       
                        }
                else
                        {
                                Temp[2] = Temp[2] - (PID.liEkVal[0] + PID.liEkVal[2]);
                                PID.uEkFlag[2] = 1;       
                        }

                        Temp[0] = (uint16)PID.uKP_Coe * Temp[0];
                        Temp[1] = (uint16)PID.uKI_Coe * PID.liEkVal[0];
                        Temp[2] = (uint16)PID.uKD_Coe * Temp[2];
                        /* 正数项叠加,负数项叠加 */
                        if(PID.uEkFlag[0] == 0)
                PostSum += Temp[0];                         //正数和
            else                                            
                NegSum += Temp[0];                          //负数和
            /* ========= 计算KI*E(k)的值 ========= */
            if(PID.uEkFlag[1] == 0)     
                PostSum += Temp[1];                         //正数和
            else
        
            /* ========= 计算KD*[E(k-2)+E(k)-2E(k-1)]的值 ========= */
            if(PID.uEkFlag[2]==0)
                PostSum += Temp[2];             //正数和
            else
                NegSum += Temp[2];              //负数和
            /* ========= 计算U(k) ========= */                        
            PostSum += (uint16)PID.iPriVal;         
            if(PostSum > NegSum)                 //是否控制量为正数
            {
                Temp[0] = PostSum - NegSum;
              
                PID.iPriVal = (uint16)Temp[0];
                                Flag_Motor_Point = 1;
               
            }
            else                                //控制量输出为负数,则输出0(下限幅值输出)
            {
                Temp[0] = NegSum - PostSum;
              
                PID.iPriVal = (uint16)Temp[0];
                                Flag_Motor_Point = 1;
               
            }
        }

       
}

void Speed_Solver(void)
{


                Control_Speed = (PID.iPriVal / 256);

}



void IO_Setting(void)

{
  P0M = 0x6E;        //P0 Input-Output value  0110 1110
  P0UR = 0x01;        //P0 pull up value
  P0OC = 0x00;        //P0 open drain value
  FP00IRQ = 0;
  FP00IEN = 1;      //P00 interrupt flag setting
  PEDGE = 0x01;   //Trigger edge:P00 set Rising edge
  P0 = 0X00;        //P0 register value
  P4M = 0xA7;        //P4 Input-Output value  1010  0111
  P4UR = 0x58;     //P4 pull up value         0101  1000
  P4CON = 0x00;        //P4 Analog-Digital value
  P4 = 0X00;        //P4 register value
}

void Timer_Setting(void)
{
  T0M = 0x60;        //T0M register value, Fcpu: 4.000000MHZ//CLK source: Fcpu//
  FT0IRQ = 0;
  FT0IEN = 1;        //T0 Interrupt enable
  FT0ENB = 1;        //T0 enable
  
  TC0M = 0xB4;        //TC0M register value, Fhosc: 16.000000MHZ//CLK source: Fhosc
  TC0C = 0xCE;        //TC0C register value, time: 50.000000us(20000.000000HZ)
  TC0R = 0xCE;        //TC0R register value
  FTC0IRQ = 0;
  FTC0IEN = 1;        //TC0 Interrupt enable
  FTC0ENB = 1;        //TC0 enable
}



void __interrupt [0x09] ISR_INT0(void)
{
  if(FP00IRQ)
  {
          FP00IRQ=0;
        Hall_Speed_Cnt++;                //脉冲计数


  }
}
void __interrupt [0x0B] ISR_T0(void)        //        1us
{
  if(FT0IRQ)
  {
                  FT0IRQ=0;
//        Speed_Time_s ++;
        if(Hall_Speed_Cnt > 1)
        {
                Speed_Time_ms++;
       
       
                        Speed_Value = (Speed_Time_ms*256)/Hall_Speed_Cnt;
                        Flag_Time_Point = 1;

                        if(Speed_Time_ms > 50)
                        {
                                Flag_Time_Point = 0;
                                Speed_Time_ms = 0;
                                Hall_Speed_Cnt = 0;
                                Flag_Time_Point = 0;
                        }
       
               
        }
        else
        {
                        Speed_Value = 0;
                        Speed_Time_ms = 0;
                        Hall_Speed_Cnt = 0;
                        Flag_Time_Point = 0;
        }

  }
}


void __interrupt [0x0C] ISR_TC0(void)         //10us
{



  if(FTC0IRQ)
  {
                 
                         if(Flag_Motor_Point)
                        {
                                FTC0IRQ=0;
                                Time_CNT++ ;
               
                                        if(Time_CNT >= Control_Speed)
                                        {
                                                 if(Time_CNT <= (Control_Speed + 20))
                                                {
                                               
                                                        Motor_Out = 1;
                                                }       
                                        else
                                                {
                                                        Motor_Out = 0;
                                                }
                                        }
                                        else
                                        {               
                                                        Motor_Out = 0;
                                       
                                        }
                                        if(Time_CNT == 200)
                                        {
                                                        Time_CNT = 0;
                                                        Flag_Motor_Point = 0;
                                        }
               
                        }
                        else
                        {       
                               
                                Motor_Out = 0;
                                Time_CNT = 0;
                       
                        }
  }


}

阿莫论坛20周年了!感谢大家的支持与爱护!!

一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。

出0入0汤圆

发表于 2016-5-9 09:57:40 | 显示全部楼层
愿闻其详,哈哈

出0入85汤圆

发表于 2016-5-9 10:10:06 | 显示全部楼层
把过零检测电路也贴出来吧

出0入0汤圆

 楼主| 发表于 2016-5-9 10:39:35 | 显示全部楼层
marshallemon 发表于 2016-5-9 10:10
把过零检测电路也贴出来吧

和这个电流图类似,芯片引脚调换一下就可以了。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入85汤圆

发表于 2016-5-9 15:21:22 | 显示全部楼层
我记得之前看过一篇文章,上面说感性负载的移相调压的过零检测部分和普通的稍有不同,貌似感性负载会对电网的波形产生影响

出0入0汤圆

 楼主| 发表于 2016-5-11 09:26:55 | 显示全部楼层
marshallemon 发表于 2016-5-9 15:21
我记得之前看过一篇文章,上面说感性负载的移相调压的过零检测部分和普通的稍有不同,貌似感性负载会对电网 ...

这个 问题 还没有去验证,不是很清楚!目前问题是无法稳速。要怎么破啊,我这个代码问题出在哪里!无法稳速啊!!!
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-29 05:04

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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