搜索
bottom↓
回复: 6

mega16 控制步进电机调整调压器 从而控制电流

[复制链接]

出0入0汤圆

发表于 2006-5-12 23:12:17 | 显示全部楼层 |阅读模式
刚学 AVR不久 利用它改进了先前开发的一个控制系统,电路图  线路板  实物图随后给出



先贴点东西 以感谢网站的培育之恩!





/***********************************************

****             AVR 自动分解程序            ***

****                                               ***

**** 策划、整理与测试: 许汉武               ***

**** 代码编写:  xuhanwuAVR                  ***

**** 编译器:WINAVR20050214                  ***

**** TEL:13860186***                         ***

****          xuhw@lisheng-xm.com         2006.4.28       ***

***********************************************/





#include <avr/io.h>

#include <avr/delay.h>

#include <avr/signal.h>

#include <avr/interrupt.h>

#include <stdio.h>

//#include <avr/pgmspace.h>



#define uchar unsigned char

#define uint  unsigned int



//#define MAX2 PA2   //调压器2到达最大时该引脚被拉低

#define MAX1 !(PINA&_BV(PA2))     //一旦按下开始按键,该位1

//#define MIN2 PA3   //调压器1到达最小时该引脚被拉低

#define MIN1 !(PINA&_BV(PA3))     //一旦按下开始按键,该位1

//#define MAX1 PA4

#define MAX2 !(PINA&_BV(PA4))     //一旦按下开始按键,该位1

//#define MIN1 PA5

#define MIN2 !(PINA&_BV(PA5))     //一旦按下开始按键,该位1



#define LG   PA6  

#define LR   PA7

#define LG_ON()  PORTA&=~_BV(PA6)  //设置绿色的指示灯亮

#define LR_ON()  PORTA&=~_BV(PA7)  //设置红色的指示灯亮

#define LG_OFF() PORTA|=_BV(PA6)   //设置绿色的指示灯灭

#define LR_OFF() PORTA|=_BV(PA7)   //设置红色的指示灯灭

#define DIR2  PC0                  //步进电机2方向控制

#define PLS2  PC1                  //步进电机2脉冲输出

#define DIR1  PC2                  //步进电机1方向控制

#define PLS1  PC3                  //步进电机1脉冲输出

#define SET_DIR2()  PORTC|=_BV(DIR2)

#define CLR_DIR2()  PORTC&=~_BV(DIR2)



#define SET_PLS2()  PORTC|=_BV(PLS2)

#define CLR_PLS2()  PORTC&=~_BV(PLS2)



#define SET_DIR1()  PORTC|=_BV(DIR1)

#define CLR_DIR1()  PORTC&=~_BV(DIR1)



#define SET_PLS1()  PORTC|=_BV(PLS1)

#define CLR_PLS1()  PORTC&=~_BV(PLS1)



#define T_MAX PC4                  //温度上限控制

#define T_MIN PC5                  //温度下限控制

#define START !(PINC&_BV(PC6))     //一旦按下开始按键,该位1

#define AUTO  !(PINC&_BV(PC7))     //一旦按下开始按键,该位1

#define PIN_RXD PD0                //通讯口

#define PIN_TXD PD1                //通讯口

#define STOP  PD2                  //停止按键口,接至外部中断0

#define DE    PD4                  //DE输出为1时处于发送状?

#define SET_DE() PORTD|=_BV(DE)   

#define CLR_DE() PORTD&=~_BV(DE)



#define TEST_N 5                   //数模转换中值取样次数

#define INBUF_LEN 39               //用于存放所接收的分界参数

uchar inbuf[INBUF_LEN];            

uchar *str;

//uchar count_read;



//uint ADC0_Result;                     // ADC0转换结果

//uint ADC1_Result;                    // ADC1转换结果

volatile uchar g_bCount=0;

volatile uchar STOP_FLAG;

volatile uchar system_time;

//static

//分解参数

uchar cur_1;                       //分解电流1

uchar cur_2;

uchar cur_3;

uchar cur_4;

uchar cur_5;

uchar cur_6;

uchar cur_7;

uchar cur_8;

uchar cur_9;

uchar cur_10;

uchar cur_11;

uchar cur_12;

uchar cur_13;

uchar cur_14;

uchar cur_15;

uchar cur_time1;                   //分解时间1

uchar cur_time2;

uchar cur_time3;

uchar cur_time4;

uchar cur_time5;

uchar cur_time6;

uchar cur_time7;

uchar cur_time8;

uchar cur_time9;

uchar cur_time10;

uchar cur_time11;

uchar cur_time12;

uchar cur_time13;

uchar cur_time14;

uchar cur_time15;

uchar dcur_1;                  //激活电流1

uchar dcur_2;

uchar dcur_3;

uchar dcur_4;

uchar dcur_time1;            

uchar dcur_time2;

uchar dcur_time3;

uchar dcur_time4;







void Delay_1ms(uint count_delay);

uchar Wating_Start(void);         //等待启动键按下启动返回1,否则返回0

void init_USART(void);            //初始化串口

uchar usart_putchar(uchar c);      //发送一个字符

uchar usart_getchar(void);        //接收一个字符

uint read_adc(uchar adc_input);    //ADC转换,返回中值 0对应T1调压器

uchar get_decompose_data(void);   //获取分解参数,1表示接收成功,0表接收失败

void moto_go(uchar moto,uchar dire,uchar delay_time); //启动步进电机delay_time速度

                                                                                                //moto 电机

                                                                                                //dire 方向 1 正 0反

void Auto(uint I_input,uint time,uchar delay_time);  //I_input输入电流 time 分解时间

void InitialMotor(uchar delay_time);

void Activation(uchar I_input,uchar time);

void Activation_goback(uchar I_input,uchar time);



  







int main(void)

{

        uchar i;

        PORTA=0XFC;                //PA0 与PA1为电流传感器输入接口,取消上拉电阻

        PORTC=0XFF;  

        PORTD=0XFC;                     //PD0 PD1为串口输出,也取消上拉电阻

        DDRA=_BV(LG)|_BV(LR);          //LG 和 LR 为指示灯控制脚 故此设置为输出

        DDRC=_BV(DIR2)|_BV(PLS2)|_BV(DIR1)|_BV(PLS1);

        DDRD=_BV(DE);

        init_USART();



//****************************计时功能设置*******************************//



        ADCSRA=_BV(ADEN)|_BV(ADPS2)|_BV(ADPS1);        //使能ADC转换器,64分频

        TCNT0=0;                                        //计时功能 256次

        TCCR0=_BV(CS02)|_BV(CS00);                     //时钟1024分频



//**************************停止外部中断*********************************//



        MCUCR=_BV(ISC01);                        //INT0的下降沿产生异步中断请求

        GIFR=_BV(INTF0);                         //先写1清零中断标志为

        GICR=_BV(INT0);                          //使能中断功能

        sei();

        while(1)

        {

                STOP_FLAG=0;

                system_time=0;

                InitialMotor(8);

                LG_OFF();

                LR_OFF();

                while(!STOP_FLAG)

                {

                        system_time=0;

                        LG_ON();

                        while(!Wating_Start());

                        for(i=0;i<2;i++)

                                {

                                        moto_go(1,1,3);

                                        moto_go(2,1,3);

                                }

                        Auto(80,30,6);  // 第一位表示分解电流,第二位表示分解时间,第三位表示速度越大速度越慢

                        Auto(90,30,6);

                        Auto(100,50,6);

                        Auto(110,80,6);

                        Auto(120,90,6);

                        Auto(130,30,6);

                        Auto(90,2,6);

                        while((!Wating_Start())&&(!STOP_FLAG))

                        {

                                Delay_1ms(1000);

                                LG_OFF();

                                Delay_1ms(1000);

                                LG_ON();

                        }

                        Activation(190,2);

                        Activation(160,1);

                        Activation(190,2);

                        Auto(110,20,6);

                        InitialMotor(8);

                }

        }

}



void Delay_1ms(uint count_delay)

{

        uint i,j;

        for(i=0;i<count_delay;i++)

                for(j=0;j<9000;j++);

}





uchar Wating_Start(void)

{

        if(START)

        {

                Delay_1ms(10);                                    //延时消抖动

                if(START)

                {

                        loop_until_bit_is_set(PINC,PC6);             //等待按键释放

                        return 1;

                }

        }

        else return 0;

}





void init_USART(void)

{ //USART 9600 8, n,1



        UCSRB=_BV(TXEN)|_BV(RXEN); //使能接收中断,使能接收,使能发送  UBRRH=0;

        UBRRL=71;

        fdevopen(usart_putchar,usart_getchar,0);

}



uchar usart_getchar(void)

{

        CLR_DE();

        loop_until_bit_is_set(UCSRA,RXC);

        return UDR;

}







uchar usart_putchar(uchar c)

{

        SET_DE();

        if(c=='/n')

                usart_putchar('/r');

        loop_until_bit_is_set(UCSRA,UDRE);

        UDR=c;

        return 0;

}



uchar get_decompose_data(void)

{

        uchar checksum;

        uchar i;

        init_USART();       

        LG_OFF();

        LR_OFF();

       

        for(i=0;i<INBUF_LEN;i++)

        {

                inbuf[i-1]=usart_getchar();

                checksum=checksum^inbuf[i-1];  //校验 所接收的最后一个是 前38个的校验和,

                               

        }

        if(checksum!=0)

        {

                checksum=0;

                LR_ON();

                for(i=0;i<INBUF_LEN;i++)

                        {

                                inbuf[i-1]=0;

                       

                        }

                return 1;

        }

        else

        {

                LG_ON();

                //添加参识赋值

       

                return 0;

        }

}



uint read_adc(uchar adc_input)

{

        uint adc_value_buf[TEST_N];

        uint tmp;

        long tmp32;

       

        uchar adc_count,i,j;

       

       

        if(adc_input)

                ADMUX=0B01000001;

        else

                ADMUX=0B01000000;

        for(adc_count=0;adc_count<TEST_N;adc_count++)

        {

                ADCSRA|=_BV(ADSC);

                loop_until_bit_is_set(ADCSRA,ADIF);

                ADCSRA|=_BV(ADIF);

                adc_value_buf[adc_count]=ADC;

        }

        for(j=0;j<TEST_N-1;j++)                                //从小到大排列

                for(i=0;i<TEST_N-j;i++)

                {

                        if(adc_value_buf>adc_value_buf[i+1])

                        {       

                                tmp=adc_value_buf;

                                adc_value_buf=adc_value_buf[i+1];

                                adc_value_buf[i+1]=tmp;               //已经经过测试,正确!

                        }

                }

        tmp=adc_value_buf[(TEST_N-1)/2];                  //取中值

        tmp32=(long)tmp*600;                     //转换为0~600的数值,表示600mA

        tmp=(unsigned int)(tmp32/1024);         //ADC位10位精度,所以除于1024

        return tmp;

}







INTERRUPT(SIG_OVERFLOW0)                   //可以被其他中断所中断

{

        if(++g_bCount>42)                     //一秒钟

        {

                g_bCount=0;

                system_time++;                    //产生系统时钟,用来比较分解时间

        }

}







SIGNAL(SIG_INTERRUPT0)                          //屏蔽到所有的中断

{

        Delay_1ms(100);

        if(!(PIND&_BV(STOP)))

                {

                        LR_ON();                           //红灯亮表示程序停止

                        STOP_FLAG=1;                       //置位停止位,程序将从头开始

                        TIMSK&=~_BV(TOIE0);               //关闭计时功能

               

                }

        loop_until_bit_is_set(PIND,PD2);          //等待按键释放

        Delay_1ms(100);

}





void moto_go(uchar moto,uchar dire,uchar delay_time)

{

//************************电机1*****************************************//  

        if(moto==1)                    //如果是第一个电机,执行以下程序

        {

                if(dire==1)                //表示正转

                {

                        CLR_DIR1();            //选择正转方向

                        SET_PLS1();            //脉冲为低(经过一个非门),输出一个脉冲

                        _delay_us(5000);           //延时

                        Delay_1ms(delay_time);     //该delay_time决定电机速度,大反而慢

                        CLR_PLS1();                //脉冲为高(经过一个非门)

                        _delay_us(5000);           //控制脉冲宽度

                        Delay_1ms(delay_time);

                }

                else                           //表示反转

                {

                        SET_DIR1();                //选择反方向

                        SET_PLS1();                //同上

                        _delay_us(5000);

                        Delay_1ms(delay_time);

                        CLR_PLS1();

                        _delay_us(5000);

                        Delay_1ms(delay_time);

                }

        }

//************************电机2*****************************************//       

        else if(moto==2)                  //如果选择第二个电机,则执行以下程序

        {

                if(dire==1)                   //同上

                {

                        CLR_DIR2();

                        SET_PLS2();

                        _delay_us(5000);

                        Delay_1ms(delay_time);

                        CLR_PLS2();

                        _delay_us(5000);

                        Delay_1ms(delay_time);

                }

                else

                {

                        SET_DIR2();

                        SET_PLS2();

                        _delay_us(5000);

                        Delay_1ms(delay_time);

                        CLR_PLS2();

                        _delay_us(5000);

                        Delay_1ms(delay_time);

                }       

               

        }

}





void Auto(uint I_input,uint time,uchar delay_time)

{

        uchar adc_arrived_times=0;

        uchar timeout=0;

        uint adc0=0;

        uint adc1=0;



        while((timeout==0)&&(!(time==0))&&(!STOP_FLAG))  //如果停止则跳出循环

        {

        //如果分解时间达到;系统的分解时间为0;或者停止中断产生,跳出循环

       

//************************电机1*****************************************//



                adc0=read_adc(0);                          //获取T1的分解电流

                if((adc0<=(I_input-1))&&(!MAX1))      //将数值转换完成后再进行对比

                        moto_go(1,1,delay_time);

                else if(adc0>=(I_input+1))             //不用下限限制

                        moto_go(1,0,delay_time);

                       

//************************电机2*****************************************//



                adc1=read_adc(1);                       //获取T2的分解电流

                if((adc1<=(I_input-1))&&(!MAX2))      //将数值转换完成后再进行对比

                        moto_go(2,1,delay_time);

                else if(adc1>=(I_input+1))

                        moto_go(2,0,delay_time);



//************************计时程序***************************************//



                if((adc0==I_input)&&(adc1==I_input))      //一旦路都达到设定电流

                        adc_arrived_times++;                   //adc计数位加1

                if(adc_arrived_times==5)                  //连续5次达到,才开始计时

                        TIMSK=_BV(TOIE0);                     //计时中断使能,计时开始

                if(system_time>=time)                    //如果达到设定时间

                        {

                                TIMSK&=~_BV(TOIE0);            //关闭计时中断,停止计时

                                timeout=1;                     //标志超时,结束该自动分解程序

                                adc_arrived_times=0;           //清除adc计数位

                                system_time=0;                 //系统计时位清零

                        }

                       

//************************掉电测试***************************************//



                while(((adc0==0)|(adc1==0))&&(!STOP_FLAG))

                        {

                                TIMSK&=~_BV(TOIE0);             //掉电时暂停系统时间

                                adc0=read_adc(0);

                                adc1=read_adc(1);

                                if(adc0==0)              //如果是第一通道掉电,快速闪烁红灯

                                        {

                                                LR_ON();

                                                Delay_1ms(1000);

                                                LR_OFF();

                                                Delay_1ms(1000);

                                        }

                                else if(adc1==0)            //如果第二通道掉电,慢速闪烁红灯

                                        {

                                                LR_ON();

                                                Delay_1ms(5000);

                                                LR_OFF();

                                                Delay_1ms(5000);

                                        }

                                if(!AUTO)                    //一旦转换到手动,则

                                        {

                                                LR_ON();             //红色指示灯常亮

                                                LG_ON();             //绿色指示灯常亮

                                                InitialMotor(8);     //电机归位(归位后红灯继续闪)

                                        }                        //()中的数表示电机的速度

                                else if(START)  //在掉电状态中,按下启动键,则。。。

                                        {

                                                moto_go(1,1,3);         //强制电机走动2步

                                                moto_go(1,1,3);         //可以避开启动时的,电流为0

                                                moto_go(2,1,3);

                                                moto_go(2,1,3);

                                                LR_OFF();

                                                break;                 //跳出掉电循环程序,继续分解

                                        }

                        }

        }

}



void InitialMotor(uchar delay_time)//电机归位子程序

{

        while((!MIN1)||(!MIN2))

        {

//**************************电机1*************************************//

                if(!MIN1)

                        {       

                                SET_DIR1();

                                SET_PLS1();

                                _delay_us(200);

                                Delay_1ms(delay_time);

                                CLR_PLS1();

                                _delay_us(200);

                                Delay_1ms(delay_time);

                        }

       

//**************************电机2*************************************//

                else if(!MIN2)

                        {

                                SET_DIR2();

                                SET_PLS2();

                                _delay_us(200);

                                Delay_1ms(delay_time);

                                CLR_PLS2();

                                _delay_us(200);

                                Delay_1ms(delay_time);

                        }

        }

}





void Activation(uchar I_input,uchar time)

{

        uchar adc_arrived_times=0;

        uchar timeout=0;

        uint adc0=0;

        uint adc1=0;





        while((timeout==0)&&(!(time==0))&&(!STOP_FLAG))

        {

       

//*****************************电机1*************************************//



                adc0=read_adc(0);

                if((adc0<=(I_input-1))&&(!MAX1))      //将数值转换完成后再进行对比

                        moto_go(1,1,1);                    //激活时无需电机回调,防抖动



//*****************************电机2*************************************//



                adc1=read_adc(1);

                if((adc1<=(I_input-1))&&(!MAX2))      //将数值转换完成后再进行对比

                        moto_go(2,1,1);                    //激活时无需电机回调,防抖动



//******************************计时*************************************//



                if((adc0>=I_input)&&(adc1>=I_input))      //只要测试电流大于设定值

                        adc_arrived_times++;                        //就可以计时

                if(adc_arrived_times==2)

                        TIMSK=_BV(TOIE0);                      //计时中断使能

                if(system_time>=time)

                        {

                                TIMSK&=~_BV(TOIE0);

                                timeout=1;

                                adc_arrived_times=0;

                                system_time=0;

                        }

//************************掉电测试*************************************//

                while(((adc0==0)|(adc1==0))&&(!STOP_FLAG))

                        {

                                TIMSK&=~_BV(TOIE0);

                                adc0=read_adc(0);

                                adc1=read_adc(1);

                                if(adc0==0)

                                        {

                                                LR_ON();

                                                Delay_1ms(1000);

                                                LR_OFF();

                                                Delay_1ms(1000);

                                        }

                                if(adc1==0)

                                        {

                                                LR_ON();

                                                Delay_1ms(3000);

                                                LR_OFF();

                                                Delay_1ms(3000);

                                        }

                                if(!AUTO)

                                        {

                                                LR_ON();

                                                LG_ON();

                                                InitialMotor(8);

                                                }

                                else if(START)

                                        {

                                                moto_go(1,1,3);

                                                moto_go(1,1,3);

                                                moto_go(2,1,3);

                                                moto_go(2,1,3);

                                                LR_OFF();

                                                break;

                                        }

                        }

        }

}



void Activation_goback(uchar I_input,uchar time)

{

        uchar adc_arrived_times=0;

        uchar timeout=0;

        uint adc0=0;

        uint adc1=0;





        while((timeout==0)&&(!(time==0))&&(!STOP_FLAG))

        {

//************************电机1*************************************//

                        adc0=read_adc(0);

                        if(adc0>=(I_input+1))//&&MIN1)

                                moto_go(1,0,1);

//************************电机2*************************************//

                        adc1=read_adc(1);

                        if(adc1>=(I_input+1))//&&MIN1)

                                moto_go(2,0,1);

//************************计时*************************************//

                        if((adc0==I_input)&&(adc1==I_input))  //用于判断分解时间是否完成

                                adc_arrived_times++;

                        if(adc_arrived_times==2)

                                TIMSK=_BV(TOIE0); //计时中断使能

                        if(system_time>=time)

                        {

                                TIMSK&=~_BV(TOIE0);

                                timeout=1;

                                adc_arrived_times=0;

                                system_time=0;

                        }

//************************掉电测试*************************************//

                        while(((adc0==0)|(adc1==0))&&(!STOP_FLAG))

                                {

                                        TIMSK&=~_BV(TOIE0);

                                        adc0=read_adc(0);

                                        adc1=read_adc(1);

                                        if(adc0==0)

                                        {

                                                LR_ON();

                                                Delay_1ms(1000);

                                                LR_OFF();

                                                Delay_1ms(1000);

                                        }

                                        if(adc1==0)

                                        {

                                                LR_ON();

                                                Delay_1ms(3000);

                                                LR_OFF();

                                                Delay_1ms(3000);

                                        }

                                        if(!AUTO)

                                                {

                                                        LG_ON();

                                                        InitialMotor(8);

                                                }

                                                               

                                        else if(START)

                                                {

                                                        moto_go(1,1,3);

                                                        moto_go(1,1,3);

                                                        moto_go(2,1,3);

                                                        moto_go(2,1,3);

                                                        LR_OFF();

                                                        break;

                                                }

                                }

    }

}

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

曾经有一段真挚的爱情摆在我的面前,我没有珍惜,现在想起来,还好我没有珍惜……

出0入0汤圆

发表于 2006-5-13 08:16:59 | 显示全部楼层
呵呵,谢谢分享!

出0入0汤圆

发表于 2009-4-18 10:16:59 | 显示全部楼层
太感谢了

出0入0汤圆

发表于 2009-5-31 00:22:47 | 显示全部楼层
大哥请问怎么测试电流呢?

出0入0汤圆

发表于 2009-6-25 15:00:04 | 显示全部楼层
期待楼主的电路,非常好的资料

出0入0汤圆

发表于 2009-6-25 15:05:04 | 显示全部楼层
希望楼主提供更多资料。
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2024-8-15 10:01

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

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