FOC电机驱动开发踩坑记录

关键技术

  • SVPWM电机磁场控制
  • 电流采样
  • park变换和Clark变换
  • 滑膜观测器(无感FOC)

SVPWM电机磁场控制

SVPWM主要思想是通过精确的对UVW三相电流的分时控制,来控制转子的合成力矩,达到目标方向,常用的是6分区的设计,SVPWM是一种通过工程设计出来的处理程序,不是算法,主要参考实现的博客:
https://blog.csdn.net/qlexcel/article/details/74787619
示例代码:

// 使用查找表来替代三角函数的计算(示例,需要根据实际需要生成表格)
#define SIN_TABLE_SIZE 720 // 假设我们使用720项的查找表
float sinTable[SIN_TABLE_SIZE]; // 预先计算的正弦表
float cosTable[SIN_TABLE_SIZE]; // 预先计算的余弦表

// 初始化正弦和余弦查找表
void initTrigTables() {
    for (int i = 0; i < SIN_TABLE_SIZE; ++i) {
        sinTable[i] = sinf((TWO_PI * i) / SIN_TABLE_SIZE);
        cosTable[i] = cosf((TWO_PI * i) / SIN_TABLE_SIZE);
    }
}

void SVPWM(float Uq, float Ud, float angle) {
	if (Uq>0){
		angle = normalizeAngle(angle);
	}else{
		angle = normalizeAngle(angle);
	}
    // 使用查找表获取正弦和余弦表
   int index = (int)((angle / TWO_PI) * SIN_TABLE_SIZE) % SIN_TABLE_SIZE;
   float sin_angle = sinTable[index]; // sinf(angle_el);
   float cos_angle = cosTable[index]; // cosf(angle_el);
    float ua, ub;
    inverse_park_transform(Ud, Uq, &ua, &ub, cos_angle, sin_angle);
    float ts = 1.0;
    float udc = voltage_supply;
    float u1, u2, u3;
    inverse_clark_transflorm(ua, ub, &u1, &u2, &u3);

    int A = u1 > 0 ? 1 : 0;
    int B = u2 > 0 ? 1 : 0;
    int C = u3 > 0 ? 1 : 0;

    int N = 4 * A + 2 * B + C;
    int sector = 0;
    int sector_map[7] = {0, 6, 4, 5, 2, 1, 3}; // 0 index not used
    sector = sector_map[N];
    float K = SQRT3_OVER_2 * ts / udc;
    float t1, t2, t3, t4, t5, t6, t7, k;

    switch (sector) {
        case 1:
            t4 = u3 * K;
            t6 = u1 * K;
            if (t4 + t6 > ts) {
                k = ts / (t4 + t6);
                t4 *= k;
                t6 *= k;
            }
            t7 = (ts - t4 - t6) / 2.0;
            ta = t4 + t6 + t7;
            tb = t6 + t7;
            tc = t7;
            break;
        case 2:
            t2 = -u3 * K;
            t6 = -u2 * K;
            if (t2 + t6 > ts) {
                k = ts / (t2 + t6);
                t2 *= k;
                t6 *= k;
            }
            t7 = (ts - t2 - t6) / 2.0;
            tb = t2 + t6 + t7;
            ta = t6 + t7;
            tc = t7;
            break;
        case 3:
            t2 = u1 * K;
            t3 = u2 * K;
            if (t2 + t3 > ts) {
                k = ts / (t2 + t3);
                t2 *= k;
                t3 *= k;
            }
            t7 = (ts - t2 - t3) / 2.0;
            tb = t2 + t3 + t7;
            tc = t3 + t7;
            ta = t7;
            break;
        case 4:
            t1 = -u1 * K;
            t3 = -u3 * K;
            if (t1 + t3 > ts) {
                k = ts / (t1 + t3);
                t1 *= k;
                t3 *= k;
            }
            t7 = (ts - t1 - t3) / 2.0;
            tc = t1 + t3 + t7;
            tb = t3 + t7;
            ta = t7;
            break;
        case 5:
            t1 = u2 * K;
            t5 = u3 * K;
            if (t1 + t5 > ts) {
                k = ts / (t1 + t5);
                t1 *= k;
                t5 *= k;
            }
            t7 = (ts - t1 - t5) / 2.0;
            tc = t1 + t5 + t7;
            ta = t5 + t7;
            tb = t7;
            break;
        case 6:
            t4 = -u2 * K;
            t5 = -u1 * K;
            if (t4 + t5 > ts) {
                k = ts / (t4 + t5);
                t4 *= k;
                t5 *= k;
            }
            t7 = (ts - t4 - t5) / 2.0;
            ta = t4 + t5 + t7;
            tc = t5 + t7;
            tb = t7;
            break;
        default:
            ta = tb = tc = 0.0;
            break;
    }
	__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, (uint32_t)(ta/ts*MAX_DUTY_CYCLE));
	__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_2, (uint32_t)(tb/ts*MAX_DUTY_CYCLE));
	__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_3, (uint32_t)(tc/ts*MAX_DUTY_CYCLE));
}

电流采样

电机的三相电流采样有3种采样的方法,1种是3相电流全部采样,好处是能采到三相的实时真实电流,缺点是成本是最高的;第二种是2相电流采样,通过3相电流之和为0可以算出第3相的电流,好处是降低了一些成本,缺点是精度没有3相的高;第三种是在总的电路上采样总电流,通过算法算出3相电流的值,好处是成本是最低的,缺点是精度也是最差的;
电机的电流采样电阻的采样位置有3种:1. 输出电流采样,优点是能够实时采到三相电流,缺点是对于采样器件例如INI181的电压耐受范围有要求,电压承受能力不够可能会导致器件损坏;2. 低压区域采样,优点是对应器件的电压承受能力要求低,缺点是需要精确控制采样的时间,采样时间必须在H桥的下臂导通时进行采样,否则采样不到正确的电流;3. 母线电流采样,仅在有效矢量时刻进行电流采样,同样存在采样盲区。

park变换和Clark变换

park变换和Clark变换为经典的变换,可以从很多博客上看原理,代码示例如下:

 #include "main.h"
#include "tools.h"
#define SQRT3_OVER_2 0.866

void clark_transform(float u1, float u2, float u3, float *ualpha, float *ubeta){
	*ualpha = 0.66666*(u1 - 0.5*u2 - 0.5*u3);
	*ubeta = 0.6666*(u2*SQRT3_OVER_2 - SQRT3_OVER_2 * u3);
}

void inverse_clark_transflorm(float ualpha, float ubeta, float *u1, float *u2, float *u3){
	*u1 = ualpha;
	*u2 = -0.5*ualpha + SQRT3_OVER_2 * ubeta;
	*u3 = -0.5*ualpha - SQRT3_OVER_2 * ubeta;
}
void park_transform(float ialpha, float ibeta, float cos_angle, float sin_angle, float *id, float *iq){
	*id = ialpha * cos_angle + ibeta * sin_angle;
	*iq = -ialpha * sin_angle + ibeta *cos_angle;
}
void inverse_park_transform(float id, float iq, float *ialpha, float *ibeta, float cos_angle, float sin_angle){
	*ialpha = id * cos_angle - iq * sin_angle;
	*ibeta = id * sin_angle + iq * cos_angle;
}

滑膜观测器

通过使用上面的技术和代码,可以做到有感FOC的控制了,但是想要不使用转子位置传感器的话还要在控制时使用一些算法。常用的无感FOC控制算法有滑膜控制器、龙博格观测器,基本都是靠观测器加锁相环来实现对转子角度位置的估计,但是都会有一些问题,滑膜控制器的问题是可能会出现电机震荡,可以通过调整参数的大小来降低震荡的幅度但一定会有。滑膜变阻器的MATLAB仿真图如下:
在这里插入图片描述

踩坑记录

  • park变换与反变换和clark变换与反变换要对应好,SVPWM中的变换必须和电流采样时的每条线的顺序都相同;
  • 电流采样时使用的是下桥采样,需要控制好采样时间,采样时间要在下桥臂导通的时候采样;
  • 使用中心对称的PWM模式;

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

浅谈汽车智能座舱如何实现多通道音频

一、引言 随着汽车智能座舱的功能迭代发展&#xff0c;传统的 4 通道、6 通道、8 通道等音响系统难以在满足驾驶场景的需求&#xff0c;未来对于智能座舱音频质量和通道数会越来越高。接下来本文将浅析目前智能座舱如何实现音频功放&#xff0c;以及如何实现多路音频功放方案。…

C语言+单片机

今天内容有点水哈哈&#xff08;忙着练焊铁技术了嘻嘻&#xff09; C语言 简单学习了while语言以及其与for语言的区别和适用方法 .循环结构&#xff1a; 初始化语句条件判断句条件控制句 for语句 for(int1;i<100;i){执行条件} for (int i 1; i < 100; i) {printf(&quo…

leetcode每日一题day22(24.10.2)——准时到达的列车最小时速

思路&#xff1a;这种在有约束条件情况下&#xff0c;求最值或最符合要求的情况&#xff0c;首先是很容易想到&#xff0c;从时速为1开始往后找找到满足条件就输出&#xff0c;但这无疑工程量很大&#xff0c;每种可能的速度都要对列车数组进行遍历&#xff0c; 时间复杂度为C…

Stable Diffusion绘画 | 来训练属于自己的模型:LoRA模型验收

我们每次训练出来的模型&#xff0c;一般都会生成 20-30 个&#xff0c;至于哪个模型符合要求&#xff0c;较为理想呢&#xff1f; 接下来需要对每个 LoRA模型 进行逐一对比测试。 为了测试模型的泛化性&#xff0c;可选择使用一些较为特殊的提示词&#xff0c;看看各个模型对…

828华为云征文 | 云服务器Flexus X实例:向量数据库 pgvector 部署,实现向量检索

目录 一、什么是向量数据库 pgvector &#xff1f; 二、pgvector 部署 2.1 安装 Docker 2.2 拉取镜像 2.3 添加规则 三、pgvector 运行 3.1 运行 pgvector 3.2 连接 pgvector 3.3 pgvector 常见操作 四、总结 本篇文章通过 云服务器Flexus X实例 部署向量数据库 pgve…

安卓13默认使用大鼠标 与配置分析 andriod13默认使用大鼠标 与配置分析

总纲 android13 rom 开发总纲说明 文章目录 1.前言2.问题分析3.代码分析4.代码修改5.彩蛋1.前言 android13里面的鼠标貌似比以前版本的鼠标小了,有些客户想要把这个鼠标改大。这个功能,android有现成的,就在这里,设置 =》无障碍 =》色彩和动画 =》 大号鼠标指针。 我们通过…

Spring注解系列 - @Autowired注解

文章目录 使用总结注入原理Autowired 注入过程InjectionMetadataInjectedElement依赖注入查找过程findAutowireCandidates 缓存注入信息 Resource 注解 使用总结 Autowired注解可以自动将所需的依赖对象注入到类的属性、构造方法或方法中&#xff0c;从而减少手动注入依赖的代…

ubuntu 设置静态IP

一、 ip addresssudo nano /etc/netplan/50-cloud-init.yaml 修改前&#xff1a; 修改后&#xff1a; # This file is generated from information provided by the datasource. Changes # to it will not persist across an instance reboot. To disable cloud-inits # ne…

【重学 MySQL】五十、添加数据

【重学 MySQL】五十、添加数据 使用INSERT INTO语句添加数据基本语法示例插入多行数据注意事项 使用LOAD DATA INFILE语句批量添加数据其他插入数据的方式注意事项 在MySQL中&#xff0c;添加数据是数据库操作中的基本操作之一。 使用INSERT INTO语句添加数据 使用 INSERT IN…

单链表的增删改查(数据结构)

之前我们学习了动态顺序表&#xff0c;今天我们来讲一讲单链表是如何进行增删改查的 一、单链表 1.1、单链表概念 概念&#xff1a;链表是⼀种物理存储结构上⾮连续、⾮顺序的存储结构&#xff0c;数据元素的逻辑顺序是通过链表中的指针链接次序实现的。 1.2、链表与顺序表的…

python的几个基本数据类型及其相关操作(字符串str,元组tuple,列表list,字典dict)

一、str及其相关操作 1、字符串的基本方法 字符串的索引、获取字符串长度、利用index获取索引位置&#xff0c;统计某字符在字符串中出现的次数。用法如下方代码。 python的变量在创建时不需要声明其数据类型&#xff0c;他会自动识别变量后的数据类型&#xff0c;所以创建一…

(undone) 阅读 MapReduce 论文笔记

参考&#xff1a;https://pdos.csail.mit.edu/6.824/papers/mapreduce.pdf 摘要&#xff1a;简单介绍了 MapReduce 是在大型分布式系统上工作的 Introduction 的内容总结&#xff1a; 1.介绍背景&#xff1a;为什么我们需要分布式系统&#xff1f;MapReduce 的意义是哪些 2.简…

运动耳机哪个牌子的好?5大质量不凡的运动耳机测评力荐!

在快节奏的生活中&#xff0c;无论是晨跑、健身还是户外探险&#xff0c;音乐都成了许多人不可或缺的陪伴。运动耳机&#xff0c;作为一种专为运动场景设计的音频设备&#xff0c;旨在提供高质量音频体验的同时&#xff0c;保证佩戴的舒适度和运动的安全性。 &#xff08;上图为…

YOLOv11改进 | 主干篇 | YOLOv11引入MobileNetV4

1. MobileNetV4介绍 1.1 摘要&#xff1a; 我们推出了最新一代的 MobileNet&#xff0c;称为 MobileNetV4 (MNv4)&#xff0c;具有适用于移动设备的通用高效架构设计。 在其核心&#xff0c;我们引入了通用倒瓶颈&#xff08;UIB&#xff09;搜索块&#xff0c;这是一种统一且…

小川科技携手阿里云数据库MongoDB:数据赋能企业构建年轻娱乐生态

随着信息技术的飞速发展&#xff0c;企业在处理海量数据时所面临的挑战日益严峻。特别是在年轻娱乐领域&#xff0c;用户行为的多样性和数据量的激增对数据存储与分析技术提出了更高的要求。在此背景下&#xff0c;小川凭借其前瞻性的技术视野&#xff0c;选择了MongoDB作为其数…

AlmaLinux 9 安装mysql8.0.38

文件下载 https://cdn.mysql.com//Downloads/MySQL-8.0/mysql-8.0.39-linux-glibc2.12-x86_64.tar 选择合适系统版本 下载后解压 tar -xvf mysql-8.0.39-linux-glibc2.12-x86_64.tar解压后里面有三个文件夹 使用mysql-8.0.39-linux-glibc2.12-x86_64.tar.xz即可&#xff0c…

Redis中String类型的常用命令(append,getrenge,setrange等命令)

Redis----String命令 前言.常见的String存储类型. 常见命令1. set 命令2. get 命令3. mget命令与mset命令4. setnx命令5. setex与psetex命令6. incr与incrby与incrbyfloat命令7. decr与decrby命令8. append命令9. getrange和setrange命令10. strlen命令. 前言. 常见的String存…

【Kubernetes】常见面试题汇总(四十五)

目录 102.使用 Kubernetes 时可以采取的最佳安全措施是什么&#xff1f; 103.什么是联合集群&#xff1f; 特别说明&#xff1a; 题目 1-68 属于【Kubernetes】的常规概念题&#xff0c;即 “ 汇总&#xff08;一&#xff09;~&#xff08;二十二&#xff09;” 。 题目…

高中教辅汇总【35GB】

文章目录 一、资源概览二、资源亮点三、获取方式 一、资源概览 这份教辅资源汇总&#xff0c;精心搜集了高中各学科的海量教辅资料&#xff0c;总容量高达35GB&#xff0c;覆盖了语文、数学、英语、物理、化学、生物、历史、地理、政治等所有必修及选修科目。从基础知识点到难…

插槽slot在vue中的使用

介绍 在 Vue.js 中&#xff0c;插槽&#xff08;slot&#xff09;是一种用于实现组件内容分发的功能。通过插槽&#xff0c;可以让父组件在使用子组件时自定义子组件内部的内容。插槽提供了一种灵活的方式来组合和复用组件。 项目中有很多地方需要调用一个组件&#xff0c;比…