基于MSP430f5529 编码电机测速 接收脉冲数 PWM调速 CCS编译器 代码分析

发布者:皮球最新更新时间:2022-10-20 来源: csdn关键字:MSP430f5529  脉冲数  PWM调速  CCS编译器 手机看文章 扫描二维码
随时随地手机看文章

前言:2022年TI杯大学生电子设计竞赛,小车跟随行驶系统(C题)要求:设计一套小车跟随行驶系统,采用TI的MCU,由一辆领头小车和一辆跟随小车组成,要求小车具有循迹功能,且速度在0.3~1m/s可调......本文着重介绍速度在0.3~1m/s可调的一种实现方式。


正文:


一、首先了解编码电机测速的原理(移步下方链接,不过多赘述)


霍尔增量式编码器左右车轮线速度的计算_许你一世阳光yyds的博客-CSDN博客


二、获取关键参数,及oled使用


由此我们得知,我们需要获取的关键数据为编码电机  轮子转动一个脉冲走过的距离(m/脉)  这个参数可以是 1. 从你所购买电机的店铺获得;2. 自己做实验测出来。下面我们从2展开。


要测这个参数最起码,你的单片机要能够读取到编码电机A相或B相在旋转时所发出的脉冲,然后通过使用CCS debug功能看变量的值,或者直接显示在oled上。


四针oled显示:把下面链接的文件除了main.c( main.c用 三、里的 )都复制到你的工程文件里面


msp430f5529——OLED屏显示文字与图片_会动的栗子的博客-CSDN博客_msp430oled显示


三、获取 脉冲数 代码(注释的内容可完全删除也不会影响)


原理:定时器中断(连续计数模式),配置上升沿捕获,我在完整代码上注释了 X_1=0;X_2=0; (将这两个变量定时清0)的语句,此时的代码只能进行获取 脉冲总数 的实验,并不能获得当前速度。


main.c


#include

#include "oled.h"

#include "type.h"

#include "bmp.h"

//#include "motor.h"  这是我自己写的电机控制代码,无关紧要,对应的是下面 调试电机转向

 

//num代表每个定时器周期内(也就是0.4619989秒内)的脉冲数,X代表从单片机开始工作时记录的脉冲总数

int num1=0;   //对应P2.0引脚

int num2=0;   //对应P2.4

int X_1=0;    //对应P2.0

int X_2=0;    //对应P2.4

 

float PID_calc(float Set_Temp , float V_1) //PID算法子程序   输入:(目标值,当前值)

{

 

  float P=0.800,I=0.15,D=800.0;//初始化P,I,D,当前值,设置值 常数

 

 

  float PID_OUT=0,PWM_Duty=0;    //PID输出

  float P_OUT=0,I_OUT=0,D_OUT=0;    //比例输出,积分输出,微分输出

  float Current_Error=0, Last_Error=0;    //当前误差  最后误差

  float Sum_Error=0,Prev_Error=0;     //误差积分

  float Gain=1.2,PID_I_MAX=100.0,PID_I_MIN=-100.0,V_DATA_MAX=100,V_DATA_MIN=0;

 

  float Rate;//误差变化率

  Current_Error = Set_Temp - V_1;//当前误差

  Sum_Error +=Current_Error;//误差积分

  Prev_Error = Last_Error;//存储误差积分

  Last_Error = Current_Error;//存储误差分析

  Rate = Current_Error-Last_Error;//变化速率计算

 

 

  if(Rate>10)//不让ta大于5也不让ta小于5

    Rate = 10;

  if(Rate<-10)

    Rate = -10;

 

  P_OUT = P*Gain*Current_Error;//比列项

  I_OUT = I*Gain*Sum_Error;//积分项

 

  //积分限幅处理

  if( I_OUT>PID_I_MAX )  I_OUT = PID_I_MAX;//不能超过最大值不能低于最小值

  if( I_OUT 

  //微分输出处理

  D_OUT = D*Gain*Rate;

  PID_OUT =  P_OUT  +  I_OUT  +  D_OUT ;

  //if ( PID_OUT >= V_DATA_MAX )  PID_OUT = V_DATA_MAX;

  //if ( PID_OUT <= V_DATA_MIN )  PID_OUT = V_DATA_MIN;

  return PID_OUT;

}

 

float speed1(int num)//金属电机  下面的0.000556906就是我测得我电机 m/脉 的参数

{

    float v;

    //v = (num * 0.000556906) / 0.4619989;//这里把测得的 m/脉 取代0.000556906算出来的是m/s

    v = num * 1.2054271124;//mm/s 这句我为了方便单片机计算,自己已经算好了系数然后转化为mm/s

    return v;

}

 

float speed2(int num)//小蓝电机   如果你只是做一辆小车,就写一个speed计算函数就好了

{

    float v;

    //v = (num * 0.00037109091) / 0.4619989;

    v = num * 0.8032289903;//mm/s

    return v;

}

 

void TIME()//配置编码电机接口

{

    TA2CTL   |= TASSEL_2+MC_2+TAIE+TACLR+ ID_3;//SMCLK,连续计数,中断允许,计数器清零

    TA1CTL   |= TASSEL_2+MC_2+TAIE+TACLR+ ID_3;//SMCLK,连续计数,中断允许,计数器清零

    TA2CCTL1 |= CAP+CM_1+CCIS_0+CCIE;  //捕获模式,上升沿捕获,CCI1A输入,同步捕获,中断允许

    TA1CCTL1 |= CAP+CM_1+CCIS_0+CCIE;  //捕获模式,上升沿捕获,CCI1A输入,同步捕获,中断允许

    P2DIR &=~ BIT4;               //初始化捕获IO口

    P2SEL |=  BIT4;

    P2DIR &=~ BIT0;               //初始化捕获IO口

    P2SEL |=  BIT0;

}

 

int main(void)

{

    WDTCTL = WDTPW | WDTHOLD;   // stop watchdog timer

    OLED_Init();    //初始化

    OLED_Clear();   //清屏

    TIME();

    //motor_IO_int();

    __bis_SR_register(GIE);

    float v1;

    float v2;

    //X_1  p2.0

    //X_2  p2.4

    //front();

 

    float a1=0, b1=0;

    int a2=0, b2=0;

    while(1)

    {   

        /*v1=speed2(num1);

        v2=speed2(num2);

        a1 = v1 ;  //左电机 接的是p2.0

        b1 = v2 ;  //右

        a1 = a1 + PID_calc(294 , a1);

        b1 = b1 + PID_calc(303 , b1);*/

          

        OLED_ShowNum(1,1,num1,3,20);//oled第一行显示P2.0引脚捕获的脉冲数

        OLED_ShowNum(1,2,num2,3,20);//第二行显示p2.4

        //__delay_cycles(1600000);//1s延时

 

        //a2 = a1 * 0.3;

        //b2 = b1 * 0.3;

 

        //mv_go(a2,b2);

        //front();

 

        //OLED_ShowNum(1,1,v1,3,20);

        //OLED_ShowNum(1,2,v2,3,20);

    }

    /*

      调试电机转向

      mv_go(90,90);

    __delay_cycles(1600000*2);

    mv_back(90,90);

    __delay_cycles(1600000*2);

    mv_L(90,90);

    __delay_cycles(1600000*2);

    mv_R(90,90);*/

}

 

#pragma vector=TIMER2_A1_VECTOR  //Timer_A捕获中断向量 p2.4

__interrupt void Timer_A2(void)

{

  switch(TA2IV)

  {

    case 2 : X_2++; break;

 

    default:

        num2=X_2 ; 

        //X_2=0; 注释这里,代码只能实现测 m/脉 去掉注释则只能测速度

            break;

  }

}

 

#pragma vector=TIMER1_A1_VECTOR  //Timer_A捕获中断向量 p2.0

__interrupt void Timer_A1(void)

{

  switch(TA1IV)

  {

    case 2 : X_1++; break;

    default:

        num1=X_1 ; 

        //X_1=0; 同X_2

            break;

  }

}


通过上面的代码,自己用手转动车轮一周记录数值变化,多测几次取平均值,然后依据 一、自己算 m/脉 然后替换掉speed1或2里的公式.


四、匀速0.3m/s总代码 main.c + motor.h + motor.c 参考


main.c


#include

#include "oled.h"

#include "type.h"

#include "bmp.h"

#include "motor.h"  

 

//num代表每个定时器周期内(也就是0.4619989秒内)的脉冲数,X代表从单片机开始工作时记录的脉冲总数

int num1=0; //对应P2.0引脚

int num2=0; //对应P2.4

int X_1=0;    //对应P2.0

int X_2=0;    //对应P2.4

 

float PID_calc(float Set_Temp , float V_1) //匀速PID算法子程序   输入:(目标值,当前值)

{

 

  float P=0.800,I=0.15,D=800.0;//初始化P,I,D,当前值,设置值 常数

 

 

  float PID_OUT=0,PWM_Duty=0;    //PID输出

  float P_OUT=0,I_OUT=0,D_OUT=0;    //比例输出,积分输出,微分输出

  float Current_Error=0, Last_Error=0;    //当前误差  最后误差

  float Sum_Error=0,Prev_Error=0;     //误差积分

  float Gain=1.2,PID_I_MAX=100.0,PID_I_MIN=-100.0,V_DATA_MAX=100,V_DATA_MIN=0;

 

  float Rate;//误差变化率

  Current_Error = Set_Temp - V_1;//当前误差

  Sum_Error +=Current_Error;//误差积分

  Prev_Error = Last_Error;//存储误差积分

  Last_Error = Current_Error;//存储误差分析

  Rate = Current_Error-Last_Error;//变化速率计算

 

 

  if(Rate>10)//不让ta大于5也不让ta小于5

    Rate = 10;

  if(Rate<-10)

    Rate = -10;

 

  P_OUT = P*Gain*Current_Error;//比列项

  I_OUT = I*Gain*Sum_Error;//积分项

 

  //积分限幅处理

  if( I_OUT>PID_I_MAX )  I_OUT = PID_I_MAX;//不能超过最大值不能低于最小值

  if( I_OUT 

  //微分输出处理

  D_OUT = D*Gain*Rate;

  PID_OUT =  P_OUT  +  I_OUT  +  D_OUT ;

  //if ( PID_OUT >= V_DATA_MAX )  PID_OUT = V_DATA_MAX; 如果你有加速度存在限制的需求,则启用这两句

  //if ( PID_OUT <= V_DATA_MIN )  PID_OUT = V_DATA_MIN;

  return PID_OUT;

}

 

float speed1(int num)//金属电机

{

    float v;

    //v = (num * 0.000556906) / 0.4619989;

    v = num * 1.2054271124;//mm/s

    return v;

}

 

float speed2(int num)//小蓝电机

{

    float v;

    //v = (num * 0.00037109091) / 0.4619989;

    v = num * 0.8032289903;//mm/s

    return v;

}

 

void TIME()//配置编码电机接口

{

    TA2CTL   |= TASSEL_2+MC_2+TAIE+TACLR+ ID_3;//SMCLK,连续计数,中断允许,计数器清零

    TA1CTL   |= TASSEL_2+MC_2+TAIE+TACLR+ ID_3;//SMCLK,连续计数,中断允许,计数器清零

    TA2CCTL1 |= CAP+CM_1+CCIS_0+CCIE;  //捕获模式,上升沿捕获,CCI1A输入,同步捕获,中断允许

    TA1CCTL1 |= CAP+CM_1+CCIS_0+CCIE;  //捕获模式,上升沿捕获,CCI1A输入,同步捕获,中断允许

    P2DIR &=~ BIT4;               //初始化捕获IO口

    P2SEL |=  BIT4;

    P2DIR &=~ BIT0;               //初始化捕获IO口

    P2SEL |=  BIT0;

}

 

int main(void)

{

    WDTCTL = WDTPW | WDTHOLD;   // stop watchdog timer

    OLED_Init();    //初始化

    OLED_Clear();   //清屏

    TIME();//接编码电机引脚初始化

    motor_IO_int();//接线l298n的引脚初始化

    __bis_SR_register(GIE);

    float v1;

    float v2;

    //X_1  p2.0

    //X_2  p2.4

    front();

 

    float a1=0, b1=0;

    int a2=0, b2=0;

    while(1)

    {

        v1=speed2(num1); //自己写哪个speed函数就改成哪个

        v2=speed2(num2);

 

        a1 = v1 ;  //左电机

        b1 = v2 ;

        a1 = a1 + PID_calc(300 , a1);

        //这里的用法是我希望速度在300mm/s,用增量式计算出a1(pwm输出)当前的值

        /*但是这里的a1还不是pwm输出值,具体看下方a2,由于摩擦力的存在,设300mm/s不一定就是0.3m/s,具体看oled上,如果显示290,那可以设成(310,a1)具体多少自己调*/

        b1 = b1 + PID_calc(300 , b1);//与a1同理

        OLED_ShowNum(1,3,a1,3,20);

        OLED_ShowNum(1,4,b1,3,20);

        //__delay_cycles(1600000);//1s延时

 

        a2 = a1 * 0.3;//设置好速度和pwm的比例转换

       /*经实验,我的motor.c中TA0CCR0设置为100,我的电机在pwm输出90时速度大致为0.3m/s,90(下方调试电机转向的第一句)与300(mm/s)数字比例为0.3*/

[1] [2]
关键字:MSP430f5529  脉冲数  PWM调速  CCS编译器 引用地址:基于MSP430f5529 编码电机测速 接收脉冲数 PWM调速 CCS编译器 代码分析

上一篇:基于MSP430F5529的红外循迹小车,
下一篇:msp430f5529——OLED屏显示文字与图片

推荐阅读最新更新时间:2024-10-31 03:13

MSP430F5529-定时器介绍
开发板有两个定时器:定时器A和定时器B。因为定时器B和定时器A差不多,所以就介绍一下定时器A。 定时器A一共有三个,定时器B有一个。其中定时器A分为Timer0_A,Timer1_A,Timer2_A。定时器A支持多重捕获/比较,PWM输出和定时功能,具备中断函数,可以通过定时器溢出或者捕获/比较触发。 这里介绍定时器A的定时器功能和输出PWM功能。其他没涉及的不做介绍。 下面介绍定时器A0相关的寄存器: 1.TA0CTL 寄存器是定时器A的总控制寄存器,可以通过写入宏定义好的单词来配置相关位 2.TA0CCTL0 寄存器是定时器A下第一个捕获/比较器的控制寄存
[单片机]
MSP430F5529-定时器介绍
01:点亮LED 【MSP430F5529
一:电路图 开发板为TI的MSP-EXP430F5529LP LED1:P1.0 LED2:P4.7 LED负极接地,输入为高电平,则点亮。输入低电平,则熄灭。 二:端口初始化 LED1的初始化 /*LED1~P1.0 初始化*/ P1DIR |= BIT0; //初始化LED1的IO口P1.0,设置为输出 P1OUT &= ~BIT0; //设置P1.0初始为低电平 LED2的初始化 /*LED2~P4.7 初始化*/ P4DIR |= BIT7; //初始化为输出 P4OUT &= ~BIT0; //初始化低电平 三:点亮/熄灭
[单片机]
01:点亮LED 【<font color='red'>MSP430F5529</font>】
MSP430F5529与LCD1602显示模块(上)
LCD1602介绍 外观 主要技术参数 显示容量: 16X2个字符 芯片工作电压: 4.5~5.5V 工作电流: 2.0mA(5.0V) 模块最佳工作电压: 5.0V 字符尺寸: 2.95X4.35(WXH)mm 接口说明 并口传输模式 VSS 电源地 VDD 电源正极(5V) V0 液晶显示偏压信号 RS 数据/命令选择端(H/L) RW 读/写选择端(H/L) E 使能信号 D0 Data I/O D1 Data I/O D2 Data I/O D3 Data I/O D4 Data I/O D5 Data I/O D6 Data I/O D7 Da
[单片机]
<font color='red'>MSP430F5529</font>与LCD1602显示模块(上)
基于51单片机的pwm直流电机调速
仿真原理图如下 单片机源程序如下: #include reg52.h /********************************************* * 定时器初值 *********************************************/ #define T0HIGH 0xec #define T0LOWW 0x8a /********************************************* * *********************************************/ typedef unsigned char u8; typed
[单片机]
基于51单片机的<font color='red'>pwm</font>直流电机<font color='red'>调速</font>
msp430f5529 MCP4725程序
//************************************** //I2C起始信号 //************************************** void I2C_Start() { SDAOUT; //数据线设为输出方向 SDA1; //拉高数据线 SCL_OUT; //时钟线设为输出方向 SCL1; //拉高时钟线 delayus(5); //延时 SDA0; //产生下降沿 delayus(5); //延时 SCL0; /
[单片机]
MSP430F5529 GPIO 按键LED灯
按下P2.1开发板上的红绿灯就会同时亮 #include msp430f5525.h void main(void) { WDTCTL = WDTPW | WDTHOLD; // stop watchdog timer关闭看门狗 P1DIR |= BIT0; //P1.0 P4DIR |= BIT7; //输出方向P4.7 P1OUT &= ~BIT0; //1.0 P4OUT &= ~BIT7; //4.7置成低 P2DIR &= ~BIT1; //输入方向P2.1 P2REN |= BIT1; //2.1上下拉电阻 P2OUT |= BIT1; //2.1输出寄存器 P2IE
[单片机]
MSP430F5529基于CCS库函数开发——软件安装与库函数配置
前言 通过MSP430官方的函数库进行开发,开发工具使用CCS。主要步骤如下: 1、下载并安装CCS 2、下载函数库 3、部署函数库 1、下载并安装CCS CCS是由美国德州仪器公司(Texas Instrument,TI)出品的代码开发和调试套件,具体的可以自行去百度,直接到官网下载安装即可。 下载完成后解压即可,右击以管理员身份运行其中的可执行文件。 安装就是傻瓜式安装就不贴出来了。 安装完成后首先选择自己的一个工作空间,可以理解为放代码的仓库地址。 新建CCS项目 选择芯片型号,填写工程名称,选择main模板 这样就创建好了默认的工程文件 2、下载函数库 直接进入官网下载即可,同时可以下载一下指南 解压
[单片机]
<font color='red'>MSP430F5529</font>基于<font color='red'>CCS</font>库函数开发——软件安装与库函数配置
等面积PWM调制在变频调速系统的实现
引言   随着电力电子全控型开关器件的出现和发展,脉宽调制技术( PWM )在电力电子变流技术中获得了广泛的应用。相比较于硬件实现方法,采用软件计算的实时 PWM 控制策略已被接受,并出现了许多不同的 PWM 波的发生方法,如采样S PWM 法、谐波注入 PWM 法、均值 PWM 法、等面积 PWM 法等。更有将逆变器与负载作为整体建立 PWM 控制策略的方法,如电动机 变频调速 领域常用的基于电动机气隙磁通轨迹最圆的磁通轨迹法 PWM 控制、基于电动机电磁转矩自调整的 PWM 控制、基于状态方程和输出反馈信号推算的无差拍 PWM 控制等 。   文献 推导了基于整流器网侧电流矢量推导出同步旋转坐标系下 PWM 整流器的数学模
[工业控制]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved