FOC开环控制代码解读

这段代码实现了一个开环速度控制系统,用于控制电机转速。它通过PWM控制器输出电压信号,来驱动电机转动。具体来说,它在指定目标速度下,持续通过电压信号进行控制。下面是对该代码详细流程的逐步解析:

1. 宏定义与变量初始化

#define _constrain(amt,low,high) ((amt)<(low)?(low):((amt)>(high)?(high):(amt)))
  • 该宏定义用于限制一个值在一个指定的范围内。对于PWM占空比,它确保其值不会超过0到1的范围。

2. 全局变量

float voltage_power_supply=12.6;
float shaft_angle=0, open_loop_timestamp=0;
float zero_electric_angle=0, Ualpha, Ubeta=0, Ua=0, Ub=0, Uc=0, dc_a=0, dc_b=0, dc_c=0;
  • voltage_power_supply 表示电源电压,设为12.6V。
  • shaft_angle 是电机的机械角度。
  • open_loop_timestamp 用来存储上次控制的时间戳。
  • Ualpha, Ubeta, Ua, Ub, Uc 是三相电压和控制信号。
  • dc_a, dc_b, dc_c 是各个PWM通道的占空比。

3. setup() 函数

void setup() {Serial.begin(115200);pinMode(pwmA, OUTPUT);pinMode(pwmB, OUTPUT);pinMode(pwmC, OUTPUT);ledcAttachPin(pwmA, 0);ledcAttachPin(pwmB, 1);ledcAttachPin(pwmC, 2);ledcSetup(0, 30000, 8);ledcSetup(1, 30000, 8);ledcSetup(2, 30000, 8);Serial.println("完成PWM初始化设置");delay(3000);
}
  • setup()函数是Arduino中的初始化函数。它初始化串口通信、PWM输出引脚以及PWM频率和精度。
  • ledcAttachPin() 用于绑定引脚和PWM通道,ledcSetup() 设置了PWM的频率和精度。

4. _electricalAngle() 函数

float _electricalAngle(float shaft_angle, int pole_pairs) {return (shaft_angle * pole_pairs);
}
  • 计算电机的电角度。电机的电角度与机械角度的关系是:电角度 = 机械角度 * 极对数。这里假设极对数为7。

5. _normalizeAngle() 函数

float _normalizeAngle(float angle) {float a = fmod(angle, 2*PI);   return a >= 0 ? a : (a + 2*PI);  
}
  • 该函数将角度归一化到 0 的范围。fmod() 用于求余数,确保角度不超过

6. setPwm() 函数

void setPwm(float Ua, float Ub, float Uc) {dc_a = _constrain(Ua / voltage_power_supply, 0.0f , 1.0f );dc_b = _constrain(Ub / voltage_power_supply, 0.0f , 1.0f );dc_c = _constrain(Uc / voltage_power_supply, 0.0f , 1.0f );ledcWrite(0, dc_a*255);ledcWrite(1, dc_b*255);ledcWrite(2, dc_c*255);
}
  • 该函数将计算得到的电压值 Ua, Ub, Uc 转化为PWM信号的占空比。
  • ledcWrite() 将占空比输出到PWM通道。

7. setPhaseVoltage() 函数

void setPhaseVoltage(float Uq, float Ud, float angle_el) {angle_el = _normalizeAngle(angle_el + zero_electric_angle);Ualpha = -Uq*sin(angle_el); Ubeta = Uq*cos(angle_el);Ua = Ualpha + voltage_power_supply / 2;Ub = (sqrt(3) * Ubeta - Ualpha) / 2 + voltage_power_supply / 2;Uc = (-Ualpha - sqrt(3) * Ubeta) / 2 + voltage_power_supply / 2;setPwm(Ua, Ub, Uc);
}
  • 该函数负责将 UqUd(两相电压分量)转换为三相电压 Ua, Ub, Uc
  • 通过帕克变换将 Uq 转换为 UalphaUbeta
  • 再通过克拉克变换将这两个分量转换为三相电压输出,并调用 setPwm() 输出PWM信号。

8. velocityOpenloop() 函数

float velocityOpenloop(float target_velocity) {unsigned long now_us = micros();float Ts = (now_us - open_loop_timestamp) * 1e-6f;if (Ts <= 0 || Ts > 0.5f) Ts = 1e-3f;shaft_angle = _normalizeAngle(shaft_angle + target_velocity * Ts);float Uq = voltage_power_supply / 3;setPhaseVoltage(Uq, 0, _electricalAngle(shaft_angle, 7));open_loop_timestamp = now_us;return Uq;
}
  • 该函数是开环速度控制的核心部分。

    • 获取当前时间(单位为微秒),计算出每次调用的时间间隔 Ts
    • 根据目标速度 target_velocity 和时间间隔计算出新的轴角度 shaft_angle
    • 使用固定的 Uq 输出电压来驱动电机。
    • 调用 setPhaseVoltage() 计算三相电压并输出。

9. loop() 函数

void loop() {velocityOpenloop(5);
}
  • loop() 函数是Arduino中的主循环。它持续调用 velocityOpenloop() 函数,设定目标速度为 5 rad/s,从而保持电机以该速度运行。

总结流程:

  1. 初始化

    • 设置PWM引脚和通道。
    • 初始化串口通信。
  2. 电角度计算:通过机械角度和极对数计算电角度。

  3. 角度归一化:将角度转换到 0 之间。

  4. PWM控制

    • 计算电压值。
    • 计算对应的PWM占空比,并输出PWM信号到电机。
  5. 开环速度控制

    • 根据目标速度计算角度增量。
    • 输出固定电压,驱动电机转动。
  6. 主循环:每次循环更新电机转速,确保电机按目标速度运行。

优缺点分析:

  • 优点

    • 简单、易于理解,适用于无闭环反馈的开环控制系统。
    • 不需要传感器反馈,适合简单应用。
  • 缺点

    • 没有速度和位置反馈,无法纠正外部扰动或负载变化带来的误差。
    • 精度较低,适用于不需要高精度控制的场合。

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

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

相关文章

Ansible Playbook 调试与预演指南:从语法检查到连通性排查

1&#xff1a;调试 playbook 时&#xff0c;最该先看哪一段输出&#xff1f; 答&#xff1a;先查看ansible-navigator run的 PLAY RECAP 段落&#xff0c;它能一次性给出每台受管主机的 ok、changed、unreachable、failed、skipped、rescued、ignored 等计数&#xff0c;快速定…

深入探讨可视化技术如何实现安全监测

可视化在安全监测中的作用&#xff0c;远超越了“美观的图表”这一表层概念。它是将抽象、混沌的安全数据转化为直观、可理解的视觉信息的过程&#xff0c;其核心价值在于赋能人类直觉&#xff0c;大幅提升认知与决策效率&#xff0c;从而实现对安全态势的深度感知和快速响应。…

Scikit-learn Python机器学习 - Scikit-learn加载数据集

锋哥原创的Scikit-learn Python机器学习视频教程&#xff1a; 2026版 Scikit-learn Python机器学习 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili 课程介绍 本课程主要讲解基于Scikit-learn的Python机器学习知识&#xff0c;包括机器学习概述&#xff0c;特征工程(数据…

如何在实际应用中选择Blaze或Apache Gluten?

Blaze 与 Apache Gluten 深入研究报告&#xff1a;技术实现、性能对比与选型指南 一、项目背景与技术演进 1.1 大数据处理性能瓶颈与 Native 引擎兴起 随着大数据量处理需求的不断增长&#xff0c;基于 JVM 的 Spark 在 CPU 密集型场景下的性能瓶颈日益凸显。从 Spark 2.4 版本…

Mysql 学习感悟 Day 1 Mysql架构

Mysql 学习感悟 Day 1简介具体流程如下&#xff1a;Server 层连接器查询缓存分析器优化器执行器存储引擎层更新语句是怎么执行的例子日志redo logbinlogmysql事务的二段提交Mysql官网 mysql安装教程 Navicat免费安装亲测有用 简介 大体来说&#xff0c;MySQL 服务端可以分为…

企业为什么需要部署数据防泄露系统?

在数字化转型的浪潮中&#xff0c;企业核心数据已成为商业竞争的“生命线”。然而&#xff0c;数据泄露事件频发&#xff0c;不仅可能导致巨额经济损失&#xff0c;更会严重损害企业信誉。据IBM《2023年数据泄露成本报告》显示&#xff0c;全球平均数据泄露成本已攀升至445万美…

CPU的MBR寄存器和MDR寄存器

在学习计算机组成原理&#xff0c;特别是学到CPU时&#xff0c;寄存器是必须了解的一些器件&#xff0c;比如说程序计数器&#xff08;PC&#xff09;,指令寄存器&#xff08;IR&#xff09;等寄存器&#xff0c;同时&#xff0c;了解MDR和MBR这两个寄存器也是必要的&#xff1…

QWidget和QML模式下阻止槽调用的方法总结

目录 1.背景 2.QWidget中阻止槽函数调用的方法 2.1.临时阻塞信号发射&#xff08;blockSignals()&#xff09; 2.2.断开特定信号与槽的连接&#xff08;disconnect()&#xff09; 2.3.在槽函数内通过标志位过滤 2.4.重写信号发射函数&#xff08;针对自定义信号&#xff…

序列化,应用层自定义协议

我们发的是一个结构化的数据OS内部&#xff0c;协议全部都是传递结构体对象。可以直接发送二进制对象吗&#xff1f;因为CS双方都能认识这个结构体!!!可以直接发送二进制对象&#xff0c;但是不建议1. 客户端和服务器说属于不同的OS&#xff0c;不同的结构体&#xff0c;在不同…

序列化和反序列的学习

一&#xff1a;重谈协议1 理解网络协议&#xff0c;可以把它想象成网络世界里的“交通规则”和“通用语言”。它是一套预先定义好的规则、标准和约定&#xff0c;使得不同设备、不同系统之间能够顺利地进行通信和数据交换。我们从TCP协议上面理解一下&#xff0c;首先TCP服务是…

计算机毕业设计 java 在线学习系统 基于 Java 的在线教育平台 Java 开发的学习管理系统

计算机毕业设计 java 在线学习系统fk01a40i &#xff08;配套有源码 程序 mysql数据库 论文&#xff09;本套源码可以先看具体功能演示视频领取&#xff0c;文末有联xi 可分享传统学习模式受时空限制&#xff0c;互动性不足&#xff0c;难以满足个性化学习需求。为打破限制&…

淘宝利用商品关键词获取商品信息指南

一、核心API接口选择接口名称功能描述适用场景taobao.items.search通过关键词搜索商品&#xff0c;支持分页、排序&#xff0c;返回商品列表&#xff08;含标题、价格、销量、图片等&#xff09;普通商品搜索、竞品监控、数据分析taobao.tbk.item.get淘宝客API&#xff0c;返回…

红黑树下探玄机:C++ setmultiset 的幕后之旅

目录 一、关联式容器 二、键值对 三、set 四、set的构造 五、set的iterator 六、set的Operations 七、multiset 一、关联式容器 序列式容器 &#xff1a; 在初阶阶段&#xff0c;我们已经接触过STL中的部分容器&#xff0c;比如&#xff1a;vector、list、deque、forwa…

Spring : 事务管理

1. 基本概念 事务&#xff08;Transaction&#xff09;是一组不可分割的操作单元&#xff0c;这些操作要么全部成功执行&#xff0c;要么全部失败回滚&#xff0c;不存在部分成功的情况。 事务具有ACID特性&#xff1a; 原子性&#xff08;Atomicity&#xff09;&#xff1a;事…

C# 一个投资跟踪程序的设计与实现:面向对象与设计模式的深度解析

在现代金融应用开发中&#xff0c;如何高效、灵活地构建投资跟踪系统&#xff0c;是每一个金融软件工程师必须面对的挑战。本文将围绕一个投资跟踪程序的设计与实现过程&#xff0c;深入剖析其背后的设计理念、架构模式以及具体实现细节。我们将通过面向对象编程、设计模式&…

存储的未来之战:RustFS如何用ZK框架重构分布式协调?

本篇文章目录 一、导火索&#xff1a;当数据洪峰撞上分布式协调的天花板 二、技术密码&#xff1a;ZK框架的三大重构 2.1 一致性哈希环的量子级进化 2.2 动态负载均衡的"神经反射" 2.3 跨云数据同步的"时空折叠" 三、未来战争&#xff1a;2026年存储…

模拟实现STL中的list容器

list前言一、list的节点结构设计二、迭代器设计三、list类的实现3.1 类的成员变量和类型定义3.2 构造函数与析构函数3.3 元素访问与迭代器接口3.4 插入与删除操作3.5 其他常用操作四、总结每文推荐前言 在C STL中&#xff0c;list是一个非常常用的容器&#xff0c;它基于双向循…

Debug-039-el-date-picker组件手动输入时间日期的问题处理

图1-外输入框图2-内输入框图3问题描述&#xff1a;这两天在迭代功能的时候&#xff0c;基本上碰到的问题都是出自这个“时间日期选择框”&#xff0c;昨天的bug38也是解决这个组件。如上图1和2所示&#xff0c;可以把图1中的输入框叫外输入框&#xff0c;图2中的输入框叫内输入…

docker-runc not installed on system

问题 Docker build时Dockerfile有RUN命令执行报错shim error: docker-runc not installed on system&#xff0c;如下&#xff1a;解决方法 修改/etc/docker/daemon.json&#xff0c;添加正面内容 {"runtimes": {"docker-runc": {"path": "…

【秋招笔试】2025.08.27华为秋招研发岗真题

📌 点击直达笔试专栏 👉《大厂笔试突围》 💻 春秋招笔试突围在线OJ 👉 笔试突围在线刷题 bishipass.com 题目一:智能温控系统监测 1️⃣:使用滑动窗口技术维护有效温度区间 2️⃣:利用单调队列高效维护窗口内的最大值和最小值 3️⃣:动态调整窗口边界,确保满足温…