历史上的今天
返回首页

历史上的今天

今天是:2024年11月11日(星期一)

正在发生

2019年11月11日 | 直流有刷伺服控制系统(pic单片机,pid控制)

2019-11-11 来源:51hei

基于PIC18系列单片机的直流有刷伺控制系统:(来处于国外贴)
1:原理图(PDF)
2:原理图及PCB图(EAGLE)
3:带pid + 编码器的控制程序。main.c


电路原理图如下:

 

单片机源程序如下:

// Vertical motor driver code 

// Oringially made by Kevin Wolfe 2009-2011

// Modified by Matt Moses 2010-2011

// 


#include

//#include

//#include

//#include



#define counterToSpeedScalar 150

#define numCountsPerStep 1

#define maxSpeed 255

#define Kp 35.0

#define Kd 0.0

#define Ki 0.0

#define dt 0.01

#define speedStep 1

#define errorTol 1

#define tempADSpeed 255

#define stepHomeThreshold 500

#define upTorqueLimit 150

#define downTorqueLimit -120


#pragma config IESO = ON

#pragma config FSCM = ON

#pragma config OSC = INTIO2        

#pragma config PWRT = OFF

#pragma config BOR = OFF

#pragma config WDT = OFF

#pragma config MCLRE = OFF


/****** DISABLE LVP (LOW-VOLTAGE Programming) ******/

/* This allows RB5 to operate as an interuppt on change I/O pin */

#pragma config LVP = OFF

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


void low_isr (void);

void high_isr (void);

void set_motor_output (unsigned char desiredPWM, unsigned char desiredDirection);


#pragma code high_vector_section=0x8

void high_vector (void)

{

_asm GOTO high_isr _endasm

}

#pragma code


#pragma code low_vector_section=0x18

void low_vector (void)

{

_asm GOTO low_isr _endasm

}

#pragma code


volatile int stepHighCounter = 0;


volatile char stepPulses = 0;

//volatile int stepCounts;

volatile int currentCounter = 0;

//volatile unsigned char currentADvalue;

volatile unsigned char trigger = 0;

//volatile structPrevStates prevStates;

//volatile enum { DIR_CW = 0, DIR_CCW = 1 } direction;

volatile enum { LOW = 0, HIGH = 1} prevA = LOW;


// changeToggle is a varb used for debugging

volatile enum {LOW = 0, HIGH = 1} changeToggle;


#pragma interrupt high_isr

void high_isr(void)

{

        if ( INTCONbits.INT0IF ) //step pulse flag 

        {


                // reset stepTimerFoo

                stepHighCounter = 1;


                // do important stuff

                if ( PORTBbits.RB1 )    //Check direction pin

                {

                        stepPulses++;

                }

                else

                {

                        stepPulses--;

                }

        

                INTCONbits.INT0IF = 0; //reset step flag

        }


        if ( INTCONbits.RBIF ) //PORTB change interrupt

        {


//                // This is a little block for debugging - toggles A every time a change on PORTB

//        

//                if (changeToggle) {

//                        changeToggle = 0;

//                        PORTAbits.RA1 = 0;

//                }

//                else {

//                        changeToggle = 1;

//                        PORTAbits.RA1 = 1;

//                } 


                if ( PORTBbits.RB5^prevA )          //CW Rotation

                {

                        currentCounter++;

                        //PORTAbits.RA1 = 0;

                }

                else                                                //CCW Rotation

                {

                        currentCounter--;

                        //PORTAbits.RA1 = 1;

//                        if (changeToggle) {

//                                changeToggle = 0;

//                                PORTAbits.RA1 = 0;

//                        }

//                        else {

//                                changeToggle = 1;

//                                PORTAbits.RA1 = 1;

//                        } 

                }



                prevA = PORTBbits.RB4;

                PORTAbits.RA1 = PORTBbits.RB5;


                INTCONbits.RBIF = 0; //resetQuadFlag

        }

}


#pragma interruptlow low_isr

void low_isr(void)  //timer interupt

{

        trigger = 1;

        INTCONbits.TMR0IF = 0;                         // reset TMR0 interrupt flag

}



void set_motor_output(unsigned char desiredPWM, unsigned char desiredDirection)

{

        if ( desiredDirection )

        {

                PORTBbits.RB2 = 0;

                CCPR1L = desiredPWM;                          // This is the register for the 8 MSB of the PWM pin RB3.

        }

        else

        {

                PORTBbits.RB2 = 1;

                CCPR1L = (desiredPWM );          // This is the register for the 8 MSB of the PWM pin RB3.

        }

}


long abs(long i) 

        if (i < 0) 

                return -i; 

        else 

                return i; 


char sgn(long i)

{

        if (i < 0)

                return -1;

        else if (i > 0)

                return 1;

        else

                return 0;

}



void main (void)

{

        long prevCounter = 0;

        unsigned char tempTrigger = 0; 

        char tempStepPulses = 0;

        long tempCurrentCounter = 0;

        

        unsigned char currentADvalue = tempADSpeed;

        long desiredCounter = 0;

        long error = 0;

        long prevError = 0;


        long velocity = 0;


        float integral = 0.0;

        float derivative = 0.0;


        long output = 0;


        char testState = 0;

        long testCounter = 0;




        char homeFlag = 0;

    enum { LOW = 0, HIGH = 1} homeDir = LOW;


        /*************** SETUP INTERRUPTS ******************/

        INTCONbits.GIEH = 0;                 // Temporarily disable global interrupts

        INTCONbits.GIEL = 0;                 // Temporarily disable peripheral interrupts

        INTCONbits.TMR0IE = 1;                 // Enable TMR0 Overflow interrupt

        INTCONbits.INT0IE = 1;                 // Enable external interrupt on INT0/RB0

        INTCONbits.RBIE = 1;                 // Enable Port B change interrupt


        //INTCON2bits.RBPU = 0;                 // Enable Port B pull-ups

        INTCON2bits.RBPU = 1;                 // Disable Port B pull-ups

        INTCON2bits.INTEDG0 = 1;         // Interrupt on rising edge for INT0

        INTCON2bits.TMR0IP = 0;         // Set TMR0 interrupt priority to Low

        INTCON2bits.RBIP = 1;                 // Set Port B change interrupt to High

推荐阅读

史海拾趣

DDK公司的发展小趣事

DDK公司在发展过程中,不仅注重技术创新和品质提升,还非常注重市场布局的智慧。公司根据市场需求和竞争态势,灵活调整产品结构和市场策略,不断开拓新的市场领域。同时,DDK公司还积极与国内外知名企业合作,共同开发新产品、新技术,共同拓展市场份额。这种市场布局的智慧,让DDK公司在电子行业中始终保持领先地位。

Galaxy Microelectronics公司的发展小趣事

江苏飞翼智能科技有限公司成立于2023年,该公司迅速将无人机技术与大数据技术相结合,实现了从传统无人机表演企业向无人机应用型企业的转型。通过自主研发和技术创新,飞翼智能的无人机在地理测绘、土方开挖计算、三维建模等领域展现出强大实力。例如,在地理测绘领域,无人机通过镜头采集地面照片,结合后期处理,能够高效完成数据测绘,大大降低了人工用量,提高了工作效率。这一技术的成功应用,不仅为公司赢得了市场认可,也推动了无人机技术的智能化发展。

FRIWO公司的发展小趣事

为了更好地服务中国市场和亚太地区的客户,FRIWO在中国深圳设立了生产基地——飞煌德商科技(深圳)有限公司。该生产基地负责开发、生产、加工电源变换器、电源充电器等产品,并承担自产产品及同类商品的批发、佣金代理、进出口及相关配套业务。飞煌德商科技(深圳)有限公司的成立和发展,不仅增强了FRIWO在中国市场的竞争力,也为公司的全球化战略提供了有力支持。通过不断优化生产流程、提升产品质量和服务水平,飞煌德商科技(深圳)有限公司逐渐成为了FRIWO在全球供应链中的重要一环。

Hitano Enterprise Corp公司的发展小趣事

FRIWO公司自成立以来,始终在技术领域保持领先地位。从便携式收录机问世之初,FRIWO就凭借其先进的技术在该领域崭露头角。随后,随着技术的不断进步,FRIWO迅速将业务扩展到Atari计算机、摄影机等新兴领域,并成功成为这些领域的电源解决方案提供商。近年来,FRIWO更是专注于移动电话充电器市场,凭借其卓越的技术实力和创新能力,成为了世界上移动电话充电器的最主要供应商。这一系列的成功,彰显了FRIWO在电子行业中的技术领先地位和多元化发展战略。

歌普(GEPU)公司的发展小趣事

FRIWO公司一直将创新视为企业发展的核心驱动力。公司不断投入研发资金,引进高端人才,致力于新技术、新产品的开发和应用。通过持续的技术创新,FRIWO在电源变换器、电源充电器、开关式电源供应器等领域取得了多项技术突破和专利成果。这些技术成果不仅提升了FRIWO产品的性能和品质,也为客户提供了更加高效、可靠的电源解决方案。

Anvo-Systems公司的发展小趣事

Anvo-Systems深知人才是企业发展的核心动力。因此,公司一直注重与高校和研究机构的合作,共同开展电子技术的研发与创新。通过与高校合作开展科研项目、设立奖学金等方式,Anvo-Systems吸引了大批优秀的人才加入公司。同时,公司还建立了完善的培训体系,为员工的职业发展提供了有力支持。这些举措不仅提升了公司的研发实力,也为公司的未来发展储备了丰富的人才资源。

问答坊 | AI 解惑

菜鸟请教!多开关控制多个发光二极管C程序

  要求:按下开关灯亮,断开开关灯灭。 我用switch语句,按下开关灯亮了,可断开开关灯就是不灭,我改了n次了它还是不灭,我已经拿它没办法了,求哥哥们给个C语言的程序,谢谢!   比如:按k1,led1亮;按k2,led2与led3亮;按 ...…

查看全部问答>

74HC165应用

各位高手,谁用过74HC165 芯片,想用它结合51单片机,LED数码管做个计数器。 可不会应用此芯片。哪位高手,分享下经验。谢谢…

查看全部问答>

CE5下怎么基于现有BSP复制出一个新的BSP(名称不同),并且能够在新BSP上建立新的CE工程,要些改什么地方?

CE5下怎么基于现有BSP复制出一个新的BSP(名称不同),并且能够在新BSP上建立新的CE工程,要些改什么地方?…

查看全部问答>

页表问题

每个进程都有一个页表吗? 不是每个进程的系统空间【0x80000000-0xffffffff】都是同一物理地址吗? 页表在0xc00000000,每个进程页表不一样这里就不一样了,怎么回事啊? 头晕…

查看全部问答>

sqlite3如何建库,如何读?

从网上找了个sqlite3.exe,就这一个文件, 直接双击,就是sqlite> 在网上查了一下,建库有好多的方法,什么$,sqlite3 xxx.db等, 执行就报sql error。 直接create table .....OK。 insert .......OK。 .exit以后再打开sqlite3.exe时,刚才建 ...…

查看全部问答>

内存控制器和mmu问题

内存控制器和mmu有什么区别? 现在接触davinci系列处理器,其中包含arm926、vpss(主要用于视频处理)、dsp 这些东西都在内存控制器之下工作,而mmu只在arm端有,想问是内存控制器是在arm内还是另外在片内独立的一个东西,而mmu和内存控制器有什么 ...…

查看全部问答>

我的应急灯经验

我做的比较晚,现在才发表一下自己的见解。真的很感谢EEWORLD能提供这样的机会,让我们获得好多的知识。 在做应急灯的过程中,我主要能获得的就是在设计电路中自己的一点小小经验吧。 在到设计电路中,我都是拿一个集成模块,根据标准电路来设计 ...…

查看全部问答>

modelsim 6.5仿真遇到的问题

用modelsim 6.5仿真为什么会报下面的错误?请高手指教 vsim work.vtf_test# vsim work.vtf_test # Loading work.vtf_test(fast)# Loading work.modelsim_test(fast)# Loading work.maxii_io(fast)# Loading work.maxii_lcell(fast)# Loading work. ...…

查看全部问答>

IARSTM8-ServicePack1.10.4发布了

                                 IAR STM8 - Service Pack 1.10.4 发布了…

查看全部问答>

DDS如何实现

  (1)如何仅仅只用QuartusII软件实现DDS呢??不用MATLAB+Dspbuilder+quartus的模式,即不用在MATLAB的Simlink里面设计模型,仿真再直接由软件Dspbuilder生成代码,不需要手动写代码! (2)如果可输出三角波,方波,正弦波三种波形 幅度, ...…

查看全部问答>