全志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/186956.shtml

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

相关文章

AIGC: 关于ChatGPT中API接口调用相关准备工作

ChatGPT之API接口相关 通过页面和GPT交流获取信息相比直接调用GPT的API而言是非常有限的 页面上的GPT是比较封闭的&#xff0c;而且只允许我们去输入文本的信息 我们需要借助GPT的API开发来激发AI工具的无限可能&#xff0c;实现更多个性化需求 1 &#xff09;使用API 使用A…

【LeetCode 0167】【数组】两数之和(2)

https://leetcode.com/problems/two-sum-ii-input-array-is-sorted/ 题解 二分查找O(nlogn)&#xff1a;有序自然想到二分查找&#xff0c;从左往右迭代数组每个元素num&#xff0c;在后面剩下的数组元素中二分查找到target-num var twoSum function(numbers, target) {con…

JavaWeb 项目 厉不厉害你鸡哥

来源 源码&#xff1a; <% page language"java" contentType"text/html; charsetUTF-8"pageEncoding"UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset"UTF-8"> <title>一起打篮球嘛</…

【WebSocket】通信协议基于 node 的简单实践和心跳机制和断线重连的实现

前后端 WebSocket 连接 阮一峰大佬 WebSocket 技术博客 H5 中提供的 WebSocket 协议是基于 TCP 的全双工传输协议。它属于应用层协议&#xff0c;并复用 HTTP 的握手通道。它只需要一次握手就可以创建持久性的连接。 那么什么是全双工呢&#xff1f; 全双工是计算机网络中的…

聊聊接口最大并发处理数

文章目录 前言并发和并行并发&#xff08;Concurrency&#xff09;并行&#xff08;Parallelism&#xff09;思考一下 前言 生活在 2023 年的互联网时代下&#xff0c;又是在国内互联网越发内卷的背景下&#xff0c;相信大家面试找工作、网上学习查资料时都了解过互联网系统设…

如何计算数据泄露的成本

现在&#xff0c;几乎所有类型的组织每天都在发生企业 IT 网络遭到破坏的情况。它们是任何合规官员最担心的问题&#xff0c;并且找出更好的方法来防止它们或从中恢复是合规官员永远不会远离的想法。 但数据泄露的实际成本是多少&#xff1f;该数字从何而来&#xff1f;当您获…

考试复习

选择20道 填空10道 判断10道 简答4-5道 编程题2道 一、选择题 1.js中更改一个input框的值&#xff1a; <input ida type"text" value"123456"> 通过a.value改变他的值 方法&#xff1a; 在script标签中通过id获得该输入框对象&#xff0c;然…

纯净版ISO镜像下载大全(Windows、Linux、mac)

目录 一、前言介绍 前言必读 介绍 二、获取ISO镜像方式 &#xff08;一&#xff09;官方镜像下载 &#xff08;二&#xff09;获取下载方式 ps&#xff1a;回复的内容都是小写的 Windows操作系统 1.windows XP系统 2.Windows 7系统 3.Windows10系统 4.Windows11系…

Flutter应用程序的加固原理

在移动应用开发中&#xff0c;Flutter已经成为一种非常流行的技术选项&#xff0c;可以同时在Android和iOS平台上构建高性能、高质量的移动应用程序。但是&#xff0c;由于其跨平台特性&#xff0c;Flutter应用程序也面临着一些安全风险&#xff0c;例如反编译、代码泄露、数据…

Python的正则表达式使用

Python的正则表达式使用 定义使用场景查替换分割 常用的正则表达符号查原字符英文状态的句号点 .反斜杠 \英文的[]英文的()英文的?加号 星号 *英文状态的大括号 {} 案例 定义 正则表达式是指专门用于描述或刻画字符串内在规律的表达式。 使用场景 无法通过切片&#xff0c;…

numpy知识库:深入理解numpy.resize函数和数组的resize方法

前言 numpy中的resize函数顾名思义&#xff0c;可以用于调整数组的大小。但具体如何调整&#xff1f;数组形状变了&#xff0c;意味着数组中的元素个数发生了变化(增加或减少)&#xff0c;如何确定resize后的新数组中每个元素的数值呢&#xff1f;本次博文就来探讨并试图回答这…

electron调用dll问题总汇

通过一天的调试安装&#xff0c;electron调用dll成功&#xff0c;先列出当前的环境&#xff1a;node版本: 18.12.0&#xff0c;32位的&#xff08;因为dll为32位的&#xff09; VS2019 python node-gyp 1、首先要查看报错原因&#xff0c;通常在某一行会有提示&#xff0c;常…

什么是基线和 x-height

前言 在排版和字体设计领域&#xff0c;了解和掌握基线&#xff08;baseline&#xff09;和 x 高度&#xff08;x-height&#xff09;的概念是至关重要的。这两个术语描述了字母在视觉上是如何对齐的&#xff0c;以及它们相对于其他字母的大小。通过对这两个概念的深入了解&…

elk+filebeat+kafka集群部署

EFK实验架构图&#xff1a; 实现高并发&#xff0c;无需指定logstash 3台esfile&#xff0c;3台kafka 20.0.0.10 esfile 20.0.0.20 esfile 20.0.0.30 esfile 20.0.0.11 kafka 20.0.0.12 kafka 20.0.0.13 kafka在es1主机上解压filebeat cd filebeat 安装nginx服务 vim /usr/loc…

无人机助力电力设备螺母缺销智能检测识别,python基于YOLOv7开发构建电力设备螺母缺销高分辨率图像小目标检测系统

传统作业场景下电力设备的运维和维护都是人工来完成的&#xff0c;随着现代技术科技手段的不断发展&#xff0c;基于无人机航拍飞行的自动智能化电力设备问题检测成为了一种可行的手段&#xff0c;本文的核心内容就是基于YOLOv7来开发构建电力设备螺母缺销检测识别系统&#xf…

软件设计师——计算机网络(一)

&#x1f4d1;前言 本文主要是【计算机网络】——软件设计师计算机网络的题目&#xff0c;如果有什么需要改进的地方还请大佬指出⛺️ &#x1f3ac;作者简介&#xff1a;大家好&#xff0c;我是听风与他&#x1f947; ☁️博客首页&#xff1a;CSDN主页听风与他 &#x1f304…

su与 su -导致邮箱收件异常

先贴代码 rootlocalhost postfix]# su - mail-user1 Last login: Thu Nov 30 17:07:14 CST 2023 on pts/0 [mail-user1localhost ~]$ mail Heirloom Mail version 12.5 7/5/10. Type ? for help. "/var/spool/mail/mail-user1": 3 messages > 1 root …

Arduino、ESP8266、HTML相关知识点记录

C代码 const char *ssid "********"; // 这里定义将要建立的WiFi名称。 const char *password "********"; // 这里定义将要建立的WiFi密码。 多WiFi连接&#xff1a; wifiMulti.addAP("**…

TypeScript 中声明类型的方法

1、使用:运算符来为变量和函数参数指定类型。例如&#xff1a; let num: number 5; function add(a: number, b: number): number {return a b; }2、使用 type 关键字来声明自定义类型别名。例如&#xff1a; type Point {x: number;y: number; };3、使用 interface 关键字…

element Tree 树形控件 高亮默认

需求&#xff1a; 1. 进入页面&#xff0c;默认选中需要的节点&#xff0c;并展开做出高亮效果&#xff0c;其他时候点击箭头图标才展开。 2. input框搜索树节点 代码&#xff1a; <el-asideclass"aside flex-shrink-0 bg-white"style"width:300px;height…