[XR806开发板试用] XR806——基于FreeRTOS下部署竞技机器人先进模糊控制器

前言

  • 很荣幸参与到由“极术社区和全志在线联合组织”举办的XR806开发板试用活动。
  • 本人热衷于各种的开发板的开发,同时更愿意将其实现到具体项目中。
  • 秉承以上原则,发现大家的重心都放在开发中的环境构建过程,缺少了不少实际应用场景的运用,虽然环境搭建确实痛苦。本文主要使用XR806的FreeRTOS到实际的机器人控制应用中,并实现部署模糊控制器。
  • 环境搭建本文简要略写,大家可以看社区其它优秀的文章。
  • 文章中应用到的无线控制和多维状态机两个重要的开发应用,会在后面的文章中陆续更新。

使用环境

1.本人使用window10+VMware+ubuntu 18.04 这里不多阐述
2.按照官方文档移植XR806的FreeRTOS

项目介绍

基于XR806——FreeRTOS为项目主控,部署先进模糊控制器,实现对于竞技机器人的机构控制和定位控制等。

在这里插入图片描述

渲染图
在这里插入图片描述

实物图

软硬件框架

在这里插入图片描述

控制部署

继电推理

在封装好电机驱动电流环时,实现对电机的控制,相当于建立了一种
继电特性的非线性控制,此时使用继电整定法的Z-N临界比例度法去建立模糊域。
根据以下临界系数表,整定求出模糊域。

控制器类型KPTnTvKiKd
P0.5*Kμ
PD0.8*Kμ0.12*TμKP*Tn
PI0.45*Kμ0.85*TμKP/Tn
PID0.6*Kμ0.5*Tμ0.12*TμKP/ TnKP*Tn

模糊推理

模糊推理的核心就是计算出E和EC的隶属度。同时把E和EC分为多种子集情况:负最大NB,负中NM,负小NS,零ZO,正小PS,正中PM,正大PB等七种情况。然后计算E/EC种子集的隶属度。

清晰化

进行模糊推理后,可以根据计算的隶属度,建立模糊规则表,实现对输出值的清晰化。对应到应用层的输出函数,实现控制输出。
例图:

在这里插入图片描述

FOC控制

在这里插入图片描述

仿真效果

在这里插入图片描述
在这里插入图片描述

代码实现

以下提供部分代码:

自动整定
void PID_AutoTune_Task(void)
{if(pid.AutoRegurating_Status != START) return;/*定义临界Tc*/float Tc = 0.0;static int start_cnt;  //记录最大值出现的时间static int end_cnt;    //记录周期结束时的时间值 static uint16_t cool_cnt = 0; static uint16_t heat_cnt = 0;//	pid.Autotune_Cnt ++; //计数if((pid.Pv_position == UP) && (pid.Pv < pid.Sv)) {cool_cnt ++;if(cool_cnt >= 3) //连续三次都越过,则说明真的越过了{pid.Pv_position = DOWN; //标记当前在下方了pid.Zero_Across_Cnt ++;	//标记穿越一次cool_cnt = 0;}}else if((pid.Pv_position == DOWN)&&(pid.Pv > pid.Sv))//刚才在下方,现在在上方{heat_cnt++;if(heat_cnt >= 3) //连续三次都越过,则说明真的越过了{pid.Pv_position = UP;   //标记当前在下方了pid.Zero_Across_Cnt ++;	//标记穿越一次heat_cnt = 0;}		}/*****************开始计算强行振荡的周期****************************/	if((pid.Zero_Across_Cnt == 2)&&(start_cnt == 0)){start_cnt = pid.Autotune_Cnt;printf("start_time = %d\r\n", start_cnt);}else if((pid.Zero_Across_Cnt == 4)&&(end_cnt == 0)){end_cnt = pid.Autotune_Cnt;printf("start_time = %d\r\n", end_cnt);}if(pid.Zero_Across_Cnt == 4){	/*计算一个震荡周期的时间*/if(start_cnt > end_cnt)Tc = (start_cnt-end_cnt)/2;  elseTc = (end_cnt-start_cnt)/2;  /*计算Kp,Ti和Td*/pid.Kp = 0.6*pid.Kp;pid.Ti = Tc*0.5;   pid.Td = Tc*0.12;  /*PID参数整定完成,将各项数据清0*/heat_cnt 	= 0;cool_cnt 	= 0;	pid.Autotune_Cnt = 0;start_cnt	= 0;end_cnt		= 0;	pid.SEk   = 0;pid.Zero_Across_Cnt 			= 0;					pid.AutoRegurating_EN 		= OFF;pid.AutoRegurating_Status = OVER; //开始运行使用新的参数后的PID算法pid.Sv   = pid.BKSv;    }
}	
模糊控制
/*模糊规则表*/
int KpRule[7][7]= {  /*NB, NM,  NS, ZO, PS, PM, PB -EC*/{1,   1,   1,  1,  1,  1,  1}, //NB 0~-10{0,   0,   0,  1,  2,  3,  4}, //NM 0~10{0,   0,   0,  1,  2,  3,  4}, //NS 10~20   {0,   0,   1,  1,  2,  3,  4}, //20~30{1,   1,   1,  1,  2,  3,  4}, //30~40{1,   1,   1,  1,  2,  3,  4}, //40 ~50{6,   6,   6,  6,  6,  6,  6}, //50~60       
};
static float fuzzy_kp(float err, float errchange) 
{                 volatile float Kp_calcu;  volatile uint8_t num,pe,pec;   volatile float eFuzzy[2]={0.0,0.0};      //隶属于误差E的隶属程度  volatile float ecFuzzy[2]={0.0,0.0};     //隶属于误差变化率EC的隶属程度  float KpFuzzy[7]={0.0,0.0,0.0,0.0,0.0,0.0,0.0}; //隶属于Kp的隶属程度  /*****误差E隶属函数描述*****/ if(err<eRule[0])         {   eFuzzy[0] =1.0;    pe = 0;  }  else if(eRule[0]<=err && err<eRule[1])  {   eFuzzy[0] = (eRule[1]-err)/(eRule[1]-eRule[0]);   pe = 0;  }  else if(eRule[1]<=err && err<eRule[2])  {   eFuzzy[0] = (eRule[2] -err)/(eRule[2]-eRule[1]);   pe = 1;  }  else if(eRule[2]<=err && err<eRule[3])  { eFuzzy[0] = (eRule[3] -err)/(eRule[3]-eRule[2]);   pe = 2;  }     else if(eRule[3]<=err && err<eRule[4])     {   eFuzzy[0] = (eRule[4]-err)/(eRule[4]-eRule[3]);         pe = 3;     }  else if(eRule[4]<=err && err<eRule[5])  {   eFuzzy[0] = (eRule[5]-err)/(eRule[5]-eRule[4]);   pe = 4;  }  else if(eRule[5]<=err && err<eRule[6])  {   eFuzzy[0] = (eRule[6]-err)/(eRule[6]-eRule[5]);   pe = 5;  }  else  {   eFuzzy[0] =	0.0;   pe =	6;  }    eFuzzy[1] =1.0 - eFuzzy[0];  /*****误差变化率EC隶属函数描述*****/       if(errchange<ecRule[0])         {   ecFuzzy[0] =1.0;   pec = 0;  }  else if(ecRule[0]<=errchange && errchange<ecRule[1])  {   ecFuzzy[0] = (ecRule[1] - errchange)/(ecRule[1]-ecRule[0]);   pec = 0 ;  }  else if(ecRule[1]<=errchange && errchange<ecRule[2])  {   ecFuzzy[0] = (ecRule[2] - errchange)/(ecRule[2]-ecRule[1]);   pec = 1;  }  else if(ecRule[2]<=errchange && errchange<ecRule[3])  {   ecFuzzy[0] = (ecRule[3] - errchange)/(ecRule[3]-ecRule[2]);   pec = 2 ;  } else if(ecRule[3]<=errchange && errchange<ecRule[4])     {   ecFuzzy[0] = (ecRule[4]-errchange)/(ecRule[4]-ecRule[3]);         pec=3;     }  else if(ecRule[4]<=errchange && errchange<ecRule[5])     {   ecFuzzy[0] = (ecRule[5]-errchange)/(ecRule[5]-ecRule[4]);         pec=4;     }  else if(ecRule[5]<=errchange && errchange<ecRule[6])     {   ecFuzzy[0] = (ecRule[6]-errchange)/(ecRule[6]-ecRule[5]);         pec=5;     }  else  {   ecFuzzy[0] =0.0;   pec = 5;  }  ecFuzzy[1] = 1.0 - ecFuzzy[0];   /*********查询模糊规则表*********/     num =	KpRule[pe][pec];  KpFuzzy[num] += (eFuzzy[0]*ecFuzzy[0]); num =	KpRule[pe][pec+1];   KpFuzzy[num] += (eFuzzy[0]*ecFuzzy[1]);  num =KpRule[pe+1][pec];  KpFuzzy[num] += (eFuzzy[1]*ecFuzzy[0]);  	num =	KpRule[pe+1][pec+1];  KpFuzzy[num] += (eFuzzy[1]*ecFuzzy[1]); /*********加权平均法解模糊*********/    Kp_calcu	=	KpFuzzy[0]*kpRule[0] +KpFuzzy[1]*kpRule[1]+ \KpFuzzy[2]*kpRule[2] +KpFuzzy[3]*kpRule[3]+ \KpFuzzy[4]*kpRule[4] +KpFuzzy[5]*kpRule[5]+ \+KpFuzzy[6]*kpRule[6];   printf(" %f,%f,%d,%d,kp = %f\r\n", err, errchange, pe, pec, Kp_calcu);return(Kp_calcu); 
} 

实物展示

无刷电机控制

https://www.bilibili.com/video/BV1FN4y1C7fY/?aid=874778769&cid=1302701130&page=null

整体定位控制

https://www.bilibili.com/video/BV1NN411t7Fy/?aid=492262076&cid=1302702003&page=null

以上,就是本文分享的全部内容了,感谢各位

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/237545.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【PostgreSQL】从零开始:(二十二)数据类型-枚举类型

概述 什么是枚举 枚举&#xff0c;又称为列举、举例或列举法&#xff0c;是一种通过逐一列举、点明或列举的方法来表达、阐述、说明或论述某个问题、观点或概念的过程。在数学、逻辑学和哲学中&#xff0c;枚举被用于证明、论证或说明某个命题、定理或理论的正确性或错误性。…

数据仓库-数据治理小厂实践

一、简介 数据治理贯穿数仓中数据的整个生命周期&#xff0c;从数据的产生、加载、清洗、计算&#xff0c;再到数据展示、应用&#xff0c;每个阶段都需要对数据进行治理&#xff0c;像有些比较大的企业都是有自己的数据治理平台或者会开发一些便捷的平台&#xff0c;对于没有平…

鸿蒙-HarmonyOS之初见

鸿蒙初识&#xff0c;此事能成&#xff01;&#xff01; 自己安装工具、配置环境并运行成功&#xff0c;流程记录。 一、首先官网下载开发工具 官网地址&#xff1a;https://developer.huawei.com/consumer/cn/ 当前最新的版本3.1 &#xff0c;windows和Mac&#xff0c;Mac又…

oppo 手机刷机流程

一、操作步骤&#xff1a; 一&#xff09;解锁BootLoader 以下是一种常见的方法&#xff0c;可以尝试获取OPPO手机的Root权限&#xff08;以参考信息为准&#xff0c;具体步骤可能因设备型号和系统版本而有所不同&#xff09;&#xff1a; 11). 解锁Bootloader&#xff1a;首…

【Python百宝箱】优化Python开发体验:日志记录、错误监控与高级调试

标题&#xff1a;“Python开发者的调试与性能优化大全” 前言 在软件开发的旅程中&#xff0c;调试和性能优化是每位开发者都需要掌握的关键技能。Python提供了丰富的工具和库&#xff0c;以应对开发中的各种挑战。本文将深入探讨logging、loguru、sentry、pdb、py-spy和debu…

js中的Array.from()和Array.of()方法的用法详情

&#x1f601; 作者简介&#xff1a;一名大四的学生&#xff0c;致力学习前端开发技术 ⭐️个人主页&#xff1a;夜宵饽饽的主页 ❔ 系列专栏&#xff1a;JavaScript小贴士 &#x1f450;学习格言&#xff1a;成功不是终点&#xff0c;失败也并非末日&#xff0c;最重要的是继续…

Android 12 (InputMethodManagerService) 替换默认输入法为Pinyin输入法

1.问题场景 由于系统自带的Latin输入法不支持遥控器操作&#xff0c;需要替换为RK的拼音输入法。 2. 替换步骤 1&#xff09;将LatinIME从mk中删除&#xff0c;让系统编译的时候不编译该apk --- a/Android/build/make/target/product/handheld_product.mkb/Android/build/m…

VScode安装C/C++编译器步骤

一、安装C/C插件 二、安装 MinGW-w64 工具链 使用国内源 git clone https://gitee.com/cuihongxi/ubuntu2-mac.git 下载后进入到VScode文件夹下&#xff0c;点击msys2-x86_64-20231026.exe进行安装 完成后&#xff0c;确保选中“立即运行 MSYS2”框&#xff0c;然后选择“完…

stable diffusion工作原理

目录 序言stable diffusion能做什么扩散模型正向扩散逆向扩散 如何训练逆向扩散 Stable Diffusion模型潜在扩散模型变分自动编码器图像分辨率图像放大为什么潜在空间可能存在&#xff1f;在潜在空间中的逆向扩散什么是 VAE 文件&#xff1f; 条件化(conditioning)文本条件化&am…

深信服技术认证“SCSA-S”划重点:命令执行漏洞

为帮助大家更加系统化地学习网络安全知识&#xff0c;以及更高效地通过深信服安全服务认证工程师考核&#xff0c;深信服特别推出“SCSA-S认证备考秘笈”共十期内容&#xff0c;“考试重点”内容框架&#xff0c;帮助大家快速get重点知识~ 划重点来啦 *点击图片放大展示 深信服…

前端验收测试驱动开发

我们听说过很多关于测试驱动开发&#xff08;TDD&#xff09;的内容。那么什么是ATDD&#xff1f; ATDD代表验收测试驱动开发&#xff0c;这是一种定义验收标准并创建自动化测试来验证是否满足这些标准的软件开发方法。ATDD是一种协作方法&#xff0c;涉及客户、开发人员和测试…

Python算法例21 交错正负数

1. 问题描述 给出一个含有正整数和负整数的数组&#xff0c;将其重新排列成一个正负数交错的数组。 2. 问题示例 给出数组[-1&#xff0c;-2&#xff0c;-3&#xff0c;4&#xff0c;5&#xff0c;6]&#xff0c;重新排序之后&#xff0c;变成[-1&#xff0c;5&#xff0c;-…

docker 部署kafka

随笔记录 目录 1. 安装zookeeper 2. 安装Kafka 2.1 拉取kafka image 2.2 查询本地docker images 2.3 查看本地 容器&#xff08;docker container&#xff09; 2.3.1 查看本地已启动的 docker container 2.3.2 查看所有容器的列表&#xff0c;包括已停止的容器。 2.4 …

个人财务工具、密钥管理平台、在线会计软件、稍后阅读方案 | 开源专题 No.51

gethomepage/homepage Stars: 10.1k License: GPL-3.0 这个项目是一个现代化、完全静态的、快速且安全的应用程序仪表盘&#xff0c;具有超过 100 种服务和多语言翻译的集成。 快速&#xff1a;网站在构建时以静态方式生成&#xff0c;加载时间飞快。安全&#xff1a;所有对后…

五分钟学完DBSCAN算法

基础概念 邻1个核心思想&#xff1a;基于密度&#xff0c;依据密度的连通性分析增长聚类 2个算法参数&#xff1a;邻域半径R和最少点数目minpoints 这两个算法参数实际可以刻画什么叫密集——当邻域半径R内的点的个数大于最少点数目minpoints时&#xff0c;就是密集。 3种点的…

SQL Error:1064,SQLState:42000

SQL Error 1064 是一个常见的 SQL 错误&#xff0c;通常表示 SQL 语句存在语法错误或不符合数据库的规范。SQLState 42000 是表示通用语法错误的 SQL 状态码。要解决 SQL Error 1064&#xff0c;需要检查的 SQL 语句&#xff0c;确保它们符合数据库管理系统的语法规则。 引起错…

油猴脚本教程案例【长按元素】- 哔哩哔哩一键三连

文章目录 1. 元数据2. 编写函数2.1 关键函数2.2 完整代码 3. 验证和调试3.1 效果演示 4. 可能遇到的问题和解决方法5. 结语 1. 元数据 在编写油猴脚本时&#xff0c;首先需要设置一些元数据&#xff0c;包括脚本的名称、命名空间、版本、描述等信息。以下是本脚本的元数据部分…

.NET core 自定义过滤器 Filter 实现webapi RestFul 统一接口数据返回格式

之前写过使用自定义返回类的方式来统一接口数据返回格式&#xff0c;.Net Core webapi RestFul 统一接口数据返回格式-CSDN博客 但是这存在一个问题&#xff0c;不是所有接口会按照定义的数据格式返回&#xff0c;除非每个接口都返回我们自定义的类&#xff0c;这种实现起来不…

7. ASP.NET Core Blazor 官网文档

官方文档地址&#xff1a;https://learn.microsoft.com/zh-cn/aspnet/core/blazor/?viewaspnetcore-8.0 Blazor 是一种 .NET 前端 Web 框架&#xff0c;在单个编程模型中同时支持服务器端呈现和客户端交互性&#xff1a; 使用 C# 创建丰富的交互式 UI。共享使用 .NET 编写的…

web前端javaScript笔记——(5)原型对象和垃圾回收

原型对象 原型对象prototype 我们所创建的每一个函数&#xff0c;机械其都会向函数中添加一个属性prototype 这个属性对应着一个对象&#xff0c;这个对象就是我们所谓的原型对象 function Person(){} console.log(Person.prototype);//Object 如果函数作为普通函数调用pr…