当前位置: 首页 > news >正文

SOPC之NIOS Ⅱ实现电机转速PID控制(调用中断函数)

        通过FPGA开发板上的NIOS Ⅱ搭建电机控制的硬件平台,包括电机正反转、编码器的读取,再通过软件部分实现PID算法对电机速度进行控制,使其能够渐近设定的编码器目标值。

一、问题与改进

SOPC之NIOS Ⅱ实现电机转速PID控制_STATEABC的博客-CSDN博客

        在前面用PID实现了基于NIOS Ⅱ的电机转动控制,但是由于用的usleep()函数精度不够,所以会导致有时读取的编码器值不准确,最终发生PID产生振荡现象。

        因此采用中断函数的方式,每10ms调用一次中断服务函数,再中断函数中实现PID控制,从而达到更大的精确度,减少振荡。

二、硬件设计

硬件设计同之前不变

三、软件设计

3.1 中断函数初始化

 void MPU_INT_INIT(void){IOWR_ALTERA_AVALON_PIO_EDGE_CAP(MPU_INT_BASE,0x00);#ifdef ALT_ENHANCED_INTERRUPT_API_PRESENTif ((alt_ic_isr_register(MPU_INT_IRQ_INTERRUPT_CONTROLLER_ID,MPU_INT_IRQ,MPU_INT_ISR,NULL,NULL)!= 0))#elseif((alt_irq_register(MPU_INT_IRQ,NULL, MPU_INT_ISR  )!= 0))#endif{printf("register irt failed\r\n");}IOWR_ALTERA_AVALON_PIO_IRQ_MASK(MPU_INT_BASE,0x01);}

3.2 中断函数

#ifdef ALT_ENHANCED_INTERRUPT_API_PRESENT //nios2 91 edition or later
void MPU_INT_ISR(void *contex)
#else //before nios2 91 edition
void MPU_INT_ISR(void * contex, alt_u32 id)
#endif
{if(!IORD_ALTERA_AVALON_PIO_EDGE_CAP(MPU_INT_BASE)){return;}else{IOWR_ALTERA_AVALON_PIO_EDGE_CAP(MPU_INT_BASE,0x00);IOWR_ALTERA_AVALON_PIO_IRQ_MASK(MPU_INT_BASE,0x00);// 测量当前编码器计数//Car.Get_Encode();//int currentCountsL = Car.Encode_L;//int currentCountsR = abs(Car.Encode_R);// 执行插值步骤for (int currentstep = 0; currentstep < step; currentstep++) {Car.Get_Encode();int currentCountsL = Car.Encode_L;interpolatedTarget= currentCountsL + (targetDistance - currentCountsL) * currentstep / step;
/*			if(interpolatedTarget<=currentCountsL){interpolatedTarget= currentCountsL + (targetDistance - currentCountsL) * currentstep / step;}*/// 计算误差error = interpolatedTarget - currentCountsL;// 计算 PID 控制输出float controlOutput = calculatePID(error, integral, prev_error);// 将控制输出限制在电机速度范围内float speed = initialSpeed + controlOutput;speed = fmaxf(-100, fminf(speed, 100));// 更新下次迭代的前一次误差和积分prev_error = error;integral  += error;if (integral >  8000) integral =  8000;if (integral < -8000) integral = -8000;Car.SetSpeed(speed, 0);}}IOWR_ALTERA_AVALON_PIO_IRQ_MASK(MPU_INT_BASE,0x01);
}

3.3 主程序

int main()
{Car.Stop();Car.Start();MPU_INT_INIT();while(1){printf("Enter targetDistance");scanf("%d", &targetDistance);}return 0;
}

四、实验结果

每10ms调用一次中断函数,这样也就保证了采样的精度,结果也比之前好了很多,但是还是会有稍微的振荡现象。

http://www.lryc.cn/news/148188.html

相关文章:

  • ElasticSearch安装为Win11服务
  • ransac拟合平面,代替open3d的segment_plane
  • Docker技术--Docker镜像管理
  • 生态环境保护3D数字展厅提供了一个线上环保知识学习平台
  • OPENCV实现计算描述子
  • Android View动画之LayoutAnimation的使用
  • 低代码与低代码平台的概念解析
  • 玩转Mysql系列 - 第8篇:详解排序和分页(order by limit),及存在的坑
  • Django实现音乐网站 ⒂
  • 爬虫逆向实战(二十八)--某税网第一步登录
  • 【Dots之003】SystemAPI.Query相关基础笔记
  • vue v-for 例子
  • 206.Flink(一):flink概述,flink集群搭建,flink中执行任务,单节点、yarn运行模式,三种部署模式的具体实现
  • 科技探究之旅--亲子研学活动
  • 华为云Stack的学习(三)
  • 大数据平台三大优势详解-行云管家
  • 智慧景区方案:AI与视频融合技术如何助力景区监管智能化升级?
  • HTML基础--Form表单--内联元素
  • 【月度刷题计划同款】常规状压 DP 启发式搜索
  • C#: Json序列化和反序列化,集合为什么多出来一些元素?
  • Docker教程-centos快速安装和配置Docker
  • three.js(四):react + three.js
  • IDEA全局统一设置Maven
  • CSS中的margin与padding
  • 匿名内部类、Lambda、方法引用 的总结
  • 本地docker registry 搭建
  • 阿里云将关停代销业务
  • 【ES6】JavaScript的Proxy:理解并实现高级代理功能
  • [Pandas] 求百分比并添加百分(%)号
  • 《算法竞赛·快冲300题》每日一题:“凑二十四”