继 前面的可控硅电机调速贴-----代码篇
本人,从初次接触松翰单片机到现在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; //差值保存,给定值和反馈值的差
uchar8 uEkFlag; //符号,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 ;
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 = {0}; //中间变量
uint16 PostSum = 0; //正数和
uint16 NegSum = 0; //负数和
PID.iCurVal = Speed_Value; //测出来的实时值速度
PID.iSetVal = Set_Speed_Value; //设定值速度
if(PID.iSetVal > PID.iCurVal) //设定值与实际值比较
{
Temp = PID.iSetVal - PID.iCurVal ;//偏差值
PID.uEkFlag = 0; //为正数
PID.liEkVal = PID.liEkVal;
PID.liEkVal = PID.liEkVal;
PID.liEkVal = Temp;
if(PID.liEkVal > PID.liEkVal ) //E(k)>E(k-1) 这一时刻值 大于 上一时刻的值
{
Temp = PID.liEkVal - PID.liEkVal;
PID.uEkFlag = 0;
}
else //E(k)<E(k-1) 这一时刻值 小于 上一时刻的值
{
Temp = PID.liEkVal - PID.liEkVal;
PID.uEkFlag = 1;
}
Temp = 2 * PID.liEkVal; //2*E(k-1) 上一时刻的值 * 2
if((PID.liEkVal + PID.liEkVal) > Temp) //这一时刻的值 与 上上次值 的和大于 上一时刻的值 * 2
{
Temp = (PID.liEkVal + PID.liEkVal) - Temp;
PID.uEkFlag = 0;
}
else //这一时刻的值 与 上上次值 的和小于 上一时刻的值 * 2
{
Temp = Temp - (PID.liEkVal + PID.liEkVal);
PID.uEkFlag = 1;
}
Temp = (uint16)PID.uKP_Coe * Temp; // P 乘以 这一时刻值 和 上一时刻的值 的差值
Temp = (uint16)PID.uKI_Coe * PID.liEkVal; // I
Temp = (uint16)PID.uKD_Coe * Temp; // D
/* 正数项叠加,负数项叠加 */
if(PID.uEkFlag == 0)
PostSum += Temp; //正数和
else
NegSum += Temp; //负数和
/* ========= 计算KI*E(k)的值 ========= */
if(PID.uEkFlag == 0)
PostSum += Temp; //正数和
else
/* ========= 计算KD*的值 ========= */
if(PID.uEkFlag==0)
PostSum += Temp; //正数和
else
NegSum += Temp; //负数和
/* ========= 计算U(k) ========= */
PostSum += (uint16)PID.iPriVal;
if(PostSum > NegSum) //是否控制量为正数
{
Temp = PostSum - NegSum;
PID.iPriVal = (uint16)Temp;
Flag_Motor_Point = 1;
}
else //控制量输出为负数,则输出0(下限幅值输出)
{
Temp = NegSum - PostSum;
PID.iPriVal = (uint16)Temp;
Flag_Motor_Point = 1;
}
}
else
{
Temp =PID.iCurVal - PID.iSetVal ;//偏差值
PID.uEkFlag = 0; //为正数
PID.liEkVal = PID.liEkVal;
PID.liEkVal = PID.liEkVal;
PID.liEkVal = Temp;
if(PID.liEkVal > PID.liEkVal )//E(k)>E(k-1)
{
Temp = PID.liEkVal - PID.liEkVal;
PID.uEkFlag = 0;
}
else
{
Temp = PID.liEkVal - PID.liEkVal;
PID.uEkFlag = 1;
}
Temp = 2 * PID.liEkVal;
if((PID.liEkVal + PID.liEkVal) > Temp)
{
Temp = (PID.liEkVal + PID.liEkVal) - Temp;
PID.uEkFlag = 0;
}
else
{
Temp = Temp - (PID.liEkVal + PID.liEkVal);
PID.uEkFlag = 1;
}
Temp = (uint16)PID.uKP_Coe * Temp;
Temp = (uint16)PID.uKI_Coe * PID.liEkVal;
Temp = (uint16)PID.uKD_Coe * Temp;
/* 正数项叠加,负数项叠加 */
if(PID.uEkFlag == 0)
PostSum += Temp; //正数和
else
NegSum += Temp; //负数和
/* ========= 计算KI*E(k)的值 ========= */
if(PID.uEkFlag == 0)
PostSum += Temp; //正数和
else
/* ========= 计算KD*的值 ========= */
if(PID.uEkFlag==0)
PostSum += Temp; //正数和
else
NegSum += Temp; //负数和
/* ========= 计算U(k) ========= */
PostSum += (uint16)PID.iPriVal;
if(PostSum > NegSum) //是否控制量为正数
{
Temp = PostSum - NegSum;
PID.iPriVal = (uint16)Temp;
Flag_Motor_Point = 1;
}
else //控制量输出为负数,则输出0(下限幅值输出)
{
Temp = NegSum - PostSum;
PID.iPriVal = (uint16)Temp;
Flag_Motor_Point = 1;
}
}
}
void Speed_Solver(void)
{
Control_Speed = (PID.iPriVal / 256);
}
void IO_Setting(void)
{
P0M = 0x6E; //P0 Input-Output value0110 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 value10100111
P4UR = 0x58; //P4 pull up value 01011000
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 ISR_INT0(void)
{
if(FP00IRQ)
{
FP00IRQ=0;
Hall_Speed_Cnt++; //脉冲计数
}
}
void __interrupt 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 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;
}
}
} 愿闻其详,哈哈 把过零检测电路也贴出来吧 marshallemon 发表于 2016-5-9 10:10
把过零检测电路也贴出来吧
和这个电流图类似,芯片引脚调换一下就可以了。 我记得之前看过一篇文章,上面说感性负载的移相调压的过零检测部分和普通的稍有不同,貌似感性负载会对电网的波形产生影响 marshallemon 发表于 2016-5-9 15:21
我记得之前看过一篇文章,上面说感性负载的移相调压的过零检测部分和普通的稍有不同,貌似感性负载会对电网 ...
这个 问题 还没有去验证,不是很清楚!目前问题是无法稳速。要怎么破啊,我这个代码问题出在哪里!无法稳速啊!!!
页:
[1]