wasdpkj 发表于 2012-10-25 12:21:45

[求助]Arduino控制可控硅的程序(含过零检测)各位大神现身吧

本帖最后由 wasdpkj 于 2012-11-1 20:46 编辑

我自己搞定了!

这次主要是来求助程序的,可控硅是通过高低电平来控制其导通角达到目的,可过零检测这里我就纠结了,涉及到中断,c语言太烂是在无从下手。

上网搜了很久,没有arduino控制可控硅的例子,各位能否帮我看看程序如何写好。

最终目的是arduino控制220v市电电器的功率,用可控硅可以实现电压的无极调整,光耦则是安全考虑。

电路图:

电路图经测试是有效的,P1是控制端,P2是过零检测端



这里有个例子:
http://wenku.baidu.com/view/dc37c4eb998fcc22bcd10d13.html


以下是搜得的51单片机代码(c语言太烂,实在看不太懂)

#include <reg52.H>          
#include "intrins.h"

#define        _50msL_        50000*0.9216
#define        _50msH_        50000*0.9216
#define        _1ms_        922
#define        _10ms_        9216
#define        _50us        46    //50*0.9216

#define uchar unsigned char
#define uint unsigned int
void delaySTD_ms(uchar ms); // 延时毫秒@12M,ms最大值255
unsigned char scankey();


sbit PWM_PIN= P1^0;
sbit PWM_TESTLED= P1^2;
/*在
 /INT0为过零检测,36v,注意安全!! 外接了两个按键,用来调整占空比;

注意由于P1.1口也控制继电器,因此杜绝字节赋值,不要出现如P1=1;
 如果把 PWM 波形的频率提高,也可以用 LED 观察到渐亮渐暗的效果,目前看,只是闪烁的时间发生变化。
220v调光设定为1kHz@12M,每周期1000us,分为10次比较合理,每CELL为1000us!
*/
sbit    key1pressed= P1^5;
sbit    key2pressed= P1^6;
sbit    key3pressed= P1^7;


#define LEVEL0 0
#define LEVEL1 1
#define LEVEL2 2
#define LEVEL3 3
#define LEVEL4 4

#define GRADE 10//单位次,调光多少级?推荐10级,比较合理(实际只能显示7级,请加MAP映射处理!);20级的话到13级就会出现误判读!
//GRADE固定为10,以便完成9级调光!!!sw除开灭是8级调光,号称10级!
#define CELL(9216/GRADE)   //10为半个市电周期,一个波
//#define CELL10000//10000us,实际是9216
#define KEYPRESSTIME7//10ms,key bound delay time

int iShiftPoint;
int b; //b一定要有符号整型!
uint timemultiplex;
uint timemultiplex_maxvalue;
//------------------------------------------
void main()
{
        PWM_PIN = 0; //先关了PWM,免得一开始就给5V导通220V了!!安全考虑!!
timemultiplex_maxvalue=3;
timemultiplex=1;       
        //外部过零中断
        IT0 = 1; //1为边沿触发
        EX0 = 1;
        //开启定时中断
        TMOD = 0x01;               //T0定时方式1
    b =8;//初亮度调整
        iShiftPoint=b;
        TH0 = (65536-CELL*iShiftPoint) / 256;   //历史:50ms@12MHz,这里定时没意义,通过外中断过零定时
        TL0 = (65536-CELL*iShiftPoint) % 256;
        ET0 = 1;
        TR0 = 1;//TR0 = 1;定时只是为了计算延时时长!10ms即10000us,分成10种时长,由t1产生这10种时长
//定时器1初始化:
        TMOD |= 0x10;               //T1定时方式1
        TH1 = (65536-_50us) / 256;   
        TL1 = (65536-_50us) % 256;
        ET1 = 1;
        TR1 = 1;//TR0 = 1;定时只是为了计算延时时长!10ms即10000us,分成10种时长,由t1产生这10种时长

        EA = 1;


//调光级别从0到4共5级别 能调光级别811~910
#define MAXAA 998
#define MINAA 11
         while(1)
                {
                        unsigned char buf;

//以下为自动化按键测试
                        b =MINAA;
                        if (b>MAXAA)
                        {
                //        delaySTD_ms(500);
                //        delaySTD_ms(500);                       
                //        delaySTD_ms(500);
                //        delaySTD_ms(500);
                //                b=MINAA;
                        PWM_PIN=0;
                        EA=0;
                        }
                        if (b<MINAA)
                               b=MINAA;
                        b+=30;
                        delaySTD_ms(500);
                        continue;
//以上为自动化按键测试                       

       //while(1)
        //        {
        //                unsigned char buf;
                        buf=scankey();
                       if(buf==1)//调灭
                                {
                                        b++;
                                }
                       if(buf==2)
                                {//二键调亮。b--是亮,765,从灭到月牙到亮
                                        b--;
                                }
                       if(buf==3)
                                {//3键盘关闭继电器,同时也得关PWM灯才得灭;再按一次3键,则全亮
                                        PWM_PIN=!PWM_PIN;
                                }
                        if (b>(GRADE-1)) b=LEVEL4;//仍然最亮   //历史:在这里调整周期.不能无限增加
                        if (b<0)       b=LEVEL0;//必须设置为>20,<1,不能设置为>19,<0,否则最后亮了就熄灭一下
                        iShiftPoint=b;
                        //other while
/*
                        delaySTD_ms(500);
                        delaySTD_ms(500);                       
                        delaySTD_ms(500);
                        delaySTD_ms(500);
                        timemultiplex_maxvalue++;
                        if (timemultiplex_maxvalue>40) timemultiplex_maxvalue=40;
*/
                }
}

//------------------------------------------

void X0_INT(void) interrupt 0
{
//过零检测,来个中断就表过零了,过零时才能重新基准一次10ms。

   //   EA = 0;
        TR0=0;
        //        PWM_PIN = 0;       
                TH0 = (65536-CELL*iShiftPoint) / 256;   //1000ms@12MHz,这里定时没意义,只是个时间流逝。通过外中断过零定时
                TL0 = (65536-CELL*iShiftPoint) % 256;   
        TR0=1;
        //        EA = 1;
}

void time0(void) interrupt 1
{

/*
        TR0 = 0;
        TH0 = (65536-CELL*iShiftPoint) / 256;   //历史:50ms@12MHz,这里定时没意义,通过外中断过零定时
        TL0 = (65536-CELL*iShiftPoint) % 256;
        TR0 = 1;
*/
        int i;
        // 1次外部中断产生,其灭会等待CELL*iShiftPoint us之后就开pwm,直至下次过零点关掉 ;CELL*iShiftPoint us由定时器来计算
        PWM_PIN = 1;      

/*
//随便两语句延时
for (i=0;i<100;i++)
{
                           _nop_();
                        _nop_();
                        _nop_();
}
*/

        TR1 = 0;
        TH1 = (65536-_50us) / 256;   //历史:50ms@12MHz,这里定时没意义,通过外中断过零定时
        TL1 = (65536-_50us) % 256;
        TR1 = 1;
                //关要!
//                PWM_PIN = 0;//亮个4us关,效果比一直亮好

}
//------------------------------------------

void time1(void) interrupt 3
{
    timemultiplex++;
        if (timemultiplex==timemultiplex_maxvalue)
        {
                timemultiplex=0;
                //关要!
                PWM_PIN = 0;
        }
}


/*********************************************************/
// 延时子程序
/*********************************************************/
void delaySTD_ms(uchar ms)// 标准延时毫秒@12M,ms最大值255   
{   
    uchar i;   
    while(ms--)   
      for(i = 0; i < 124; i++);   
}

//那个键按下返回几
unsigned char scankey()
{
        if (key1pressed==0)
        {
                delaySTD_ms(KEYPRESSTIME);
                if (key1pressed==0)
                {
                        while(!key1pressed);
                        delaySTD_ms(KEYPRESSTIME);
                        return 1;
                }
        }
        if (key2pressed==0)
        {
                delaySTD_ms(KEYPRESSTIME);
                if (key2pressed==0)
                {
                        while(!key2pressed);
                        delaySTD_ms(KEYPRESSTIME);
                        return 2;
                }
        }
        if (key3pressed==0)
        {
                delaySTD_ms(KEYPRESSTIME);
                if (key3pressed==0)
                {
                        while(!key3pressed);
                        delaySTD_ms(KEYPRESSTIME);
                        return 3;
                }
        }

        return 0;//0表示没按键按下,更表示误按了快速弹起了。
}

太行摄狼 发表于 2012-10-25 23:22:18

好资料,你使用了吗?

wasdpkj 发表于 2012-10-26 12:34:47

太行摄狼 发表于 2012-10-25 23:22 static/image/common/back.gif
好资料,你使用了吗?

没使用,刚试了试,没加过零检测的话,风扇只能勉强转,无法很好地控制,我现在就是不会编程。。所以来求助,您能否帮忙看看程序怎么写
页: [1]
查看完整版本: [求助]Arduino控制可控硅的程序(含过零检测)各位大神现身吧