HAL STM32F1 通过查表方式实现SVPWM驱动无刷电机测试

HAL STM32F1 通过查表方式实现SVPWM驱动无刷电机测试


  • 📍相关篇《基于开源项目HAL STM32F4 +DSP库跑SVPWM开环速度测试》
  • ✨针对STM32F1系列,没有专门的可依赖的DSP库,为了实现特定函数的浮点运算快速计算,通过查表方式来实现,以空间换速度的方式。
  • 📍硬件电路和项目参考,立创开源广场:https://oshwhub.com/shadow27/tai-yang-neng-wu-ren-chuan
  • 📌 采用6路驱动控制,可以参考个人的相关篇《自制无感无刷电机驱动板》

📘实现核心代码

  • 📑svpwm.c
#include "tim.h"

#include "svpwm.h"
 #include "stdio.h"
 
#define PWM_Period 4800

float voltage_power_supply=12; //母线电压12V
float sensor_offset=0;
float zero_electric_angle=0;

float _normalizeAngle(float angle)// 标准化角度 [0,2PI]
{
  float a = fmod(angle, _2PI);                     //fmod()对浮点数取模
  return a >= 0 ? a : (a + _2PI);
}
//把0~Π/2的正弦值分成200份
const int sine_array[200] = {0,79,158,237,316,395,473,552,631,710,789,867,946,1024,1103,1181,1260,1338,1416,1494,
	1572,1650,1728,1806,1883,1961,2038,2115,2192,2269,2346,2423,2499,2575,2652,2728,2804,2879,2955,3030,
	3105,3180,3255,3329,3404,3478,3552,3625,3699,3772,3845,3918,3990,4063,4135,4206,4278,4349,4420,4491,
	4561,4631,4701,4770,4840,4909,4977,5046,5113,5181,5249,5316,5382,5449,5515,5580,5646,5711,5775,5839,
	5903,5967,6030,6093,6155,6217,6279,6340,6401,6461,6521,6581,6640,6699,6758,6815,6873,6930,6987,7043,
	7099,7154,7209,7264,7318,7371,7424,7477,7529,7581,7632,7683,7733,7783,7832,7881,7930,7977,8025,8072,
	8118,8164,8209,8254,8298,8342,8385,8428,8470,8512,8553,8594,8634,8673,8712,8751,8789,8826,8863,8899,
	8935,8970,9005,9039,9072,9105,9138,9169,9201,9231,9261,9291,9320,9348,9376,9403,9429,9455,9481,9506,
	9530,9554,9577,9599,9621,9642,9663,9683,9702,9721,9739,9757,9774,9790,9806,9821,9836,9850,9863,9876,
	9888,9899,9910,9920,9930,9939,9947,9955,9962,9969,9975,9980,9985,9989,9992,9995,9997,9999,10000,10000};

//0~360°的正弦值,函数通过使用固定大小的数组来逼近正弦计算
float _sin(float a){//a的值最大为2Π,即6.28318530718
  if(a < _PI_2){//a<1.57079632679
    //return sine_array[(int)(199.0*( a / (_PI/2.0)))];
    //return sine_array[(int)(126.6873* a)];           // 浮点数组优化
    return 0.0001*sine_array[_round(126.6873* a)];      // int数组优化
  }else if(a < _PI){//1.57079632679<=a<3.14159265359
    // return sine_array[(int)(199.0*(1.0 - (a-_PI/2.0) / (_PI/2.0)))];
    //return sine_array[398 - (int)(126.6873*a)];          // float array optimized
    return 0.0001*sine_array[398 - _round(126.6873*a)];     // int array optimized
  }else if(a < _3PI_2){//3.14159265359<=a<4.71238898038
    // return -sine_array[(int)(199.0*((a - _PI) / (_PI/2.0)))];
    //return -sine_array[-398 + (int)(126.6873*a)];           // float array optimized
    return -0.0001*sine_array[-398 + _round(126.6873*a)];      // int array optimized
  } else {//4.71238898038<=a<6.28318530718
    // return -sine_array[(int)(199.0*(1.0 - (a - 3*_PI/2) / (_PI/2.0)))];
    //return -sine_array[796 - (int)(126.6873*a)];           // float array optimized
    return -0.0001*sine_array[796 - _round(126.6873*a)];      // int array optimized
  }
}

//0~360°的余弦值,函数逼近余弦计算使用固定大小的数组
float _cos(float a){
  float a_sin = a + _PI_2;
  a_sin = a_sin > _2PI ? a_sin - _2PI : a_sin;
  return _sin(a_sin);
}

//近似开根号函数
float _sqrtApprox(float number) {//low in fat
  long i;
  float y;
  // float x;
  // const float f = 1.5F; // better precision

  // x = number * 0.5F;
  y = number;
  i = * ( long * ) &y;
  i = 0x5f375a86 - ( i >> 1 );
  y = * ( float * ) &i;
  // y = y * ( f - ( x * y * y ) ); // better precision
  return number * y;
}

 // 输入参数0.0f ~ 1.0f,输出3路PWM
//void Set_PWM(float _CCR1, float _CCR2, float _CCR3)
//{
//	__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, _CCR1 * PWM_ARR);
//	__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_2, _CCR2 * PWM_ARR);
//	__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_3, _CCR3 * PWM_ARR);
//}


//FOC核心函数:输入Ud、Uq和电角度,输出PWM
void setPhaseVoltage(float Uq, float Ud, float angle_el)
{
	float Uref;
	uint32_t sector;
	float T0,T1,T2;
	float Ta,Tb,Tc;
	float U_alpha,U_beta;

	angle_el =_normalizeAngle(angle_el); //电角度标准化在【0,2pi】

	U_alpha=Ud*_cos(angle_el)-Uq*_sin(angle_el); //反park变换
	U_beta=Ud*_sin(angle_el)+Uq*_cos(angle_el);

	Uref=_sqrtApprox(U_alpha*U_alpha + U_beta*U_beta) / voltage_power_supply;

	if(Uref> 0.577)Uref= 0.577; //六边形的内切圆(SVPWM最大不失真旋转电压矢量赋值)根号3/3
	if(Uref<-0.577)Uref=-0.577;

	if(Uq>0)
	  angle_el =_normalizeAngle(angle_el+_PI_2); //加90度后是参考电压矢量的位置
	else
		angle_el =_normalizeAngle(angle_el-_PI_2);

	sector = (angle_el / _PI_3) + 1; //扇区判断

	//每个扇区中两个相邻电压矢量Uref作用时间
	T1 = _SQRT3*sin(sector*_PI_3 - angle_el) * Uref;
	T2 = _SQRT3*sin(angle_el - (sector-1.0)*_PI_3) * Uref;

	//零矢量作用时间
	T0 = 1 - T1 - T2;

	switch(sector) //计算各相的作用时间
	{
    case 1:
			Ta = T1 + T2 + T0/2;
			Tb = T2 + T0/2;
			Tc = T0/2;
			break;
		case 2:
			Ta = T1 +  T0/2;
			Tb = T1 + T2 + T0/2;
			Tc = T0/2;
			break;
		case 3:
			Ta = T0/2;
			Tb = T1 + T2 + T0/2;
			Tc = T2 + T0/2;
			break;
		case 4:
			Ta = T0/2;
			Tb = T1+ T0/2;
			Tc = T1 + T2 + T0/2;
			break;
		case 5:
			Ta = T2 + T0/2;
			Tb = T0/2;
			Tc = T1 + T2 + T0/2;
			break;
		case 6:
			Ta = T1 + T2 + T0/2;
			Tb = T0/2;
			Tc = T1 + T0/2;
			break;
		default:  //其他情况关闭上管,打开下管,即刹车
			Ta = 0;
			Tb = 0;
			Tc = 0;
	}
	//printf("[Ta,Tb,Tc]:%f,%f,%f\r\n", Ta, Tb, Tc);
	__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, Ta*PWM_Period); //输出U相PWM,配置占空比
	__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_2,Tb*PWM_Period);   //输出V相PWM,配置占空比
	__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_3, Tc*PWM_Period);  //输出W相PWM,配置占空比

}

  • 📄svpwm.h
#ifndef __SVPWM_H__
#define __SVPWM_H__



#include <math.h>

#define _sign(a) ( ( (a) < 0 )  ?  -1   : ( (a) > 0 ) )
#define _round(x) ((x)>=0?(long)((x)+0.5):(long)((x)-0.5))
#define _constrain(amt,low,high) ((amt)<(low)?(low):((amt)>(high)?(high):(amt)))
#define _sqrt(a) (_sqrtApprox(a))
#define _isset(a) ( (a) != (NOT_SET) )

#define _2_SQRT3 1.15470053838
#define _SQRT3 1.73205080757
#define _1_SQRT3 0.57735026919
#define _SQRT3_2 0.86602540378
#define _SQRT2 1.41421356237
#define _120_D2R 2.09439510239
#define _PI 3.14159265359
#define _PI_2 1.57079632679
#define _PI_3 1.0471975512
#define _2PI 6.28318530718
#define _3PI_2 4.71238898038
#define _PI_6 0.52359877559


//FOC核心函数:输入Ud、Uq和电角度,输出PWM
void setPhaseVoltage(float Uq, float Ud, float angle_el);

#endif /* __SVPWM_H__ */



  • 🌿在滴答回调函数中,每隔2毫秒执行一次
void HAL_SYSTICK_Callback(void)
{

  //  Sys_Tick_Count_1ms();
  Count++;
  if (Count >= vtaskms)
  {
    Count = 0;
		//Uq和电角度增加值需要自己调,每个电机都不一样
    setPhaseVoltage(0.5,0.0,angle_el);  //空载的时候尽量让uq<2。Uq越大电机的电流越大,扭力约大
	angle_el +=0.64;  //估计电角度,电角度增加的越快,电机转的越快。电角度减小则电机反向旋转0.18 0.36 0.54 0.62
  }
}

🎉在电机能转动的情况下,可以逐步增大电角度(angle_el)数值,以提高转动的速度。在电机能提速的情况下,电流相对会减少。这个速度也不是不限增加的,当程序设定的角度电机执行完,正好与下一次循环设定的角度接近重合时,达到最佳的运转效果。

个人使用2204电机测试,在电角度参数和电机运转步进接近的状态下,空载下运转,电流只有60毫安左右,长时间运转,电机都没有感受发热。

  • 🌿3路PWM驱动波形及参数
    在这里插入图片描述

  • 🌿三相驱动桥,下端电流采样波形
    在这里插入图片描述

📚测试工程

  • 🌿基于3路PWM控制。(EG2133)
    在这里插入图片描述
链接:https://pan.baidu.com/s/1H_5o-4v7Z8x4XBi8RtVU1A?pwd=rcv6 
提取码:rcv6
  • 🌿基于3路互补PWM输出控制。
    在这里插入图片描述
链接:https://pan.baidu.com/s/13mFTlaAbvnjr1eh-rdLQSQ?pwd=2fr7 
提取码:2fr7

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

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

相关文章

搭建多平台比价软件你必须知道的几大知识板块

为了搭建一个多平台比价系统并使其发挥作用&#xff0c;你需要考虑以下几个关键的平台支持方面&#xff1a; 数据API采集平台&#xff1a; 电商平台&#xff1a;如亚马逊、淘宝、京东等&#xff0c;这些平台提供了丰富的商品信息和价格数据。旅行服务平台&#xff1a;如携程、…

git凭证

默认是manager # 将凭证缓存到内存中&#xff0c;默认缓存15分钟 git config --global credential.helper cache# 将凭证存储到磁盘上的纯文本文件中 git config --global credential.helper store# 使用 Git 凭证管理器 git config --global credential.helper manager-core查…

红队神器Evil-winrm的使用

前言 Evil-winrm 工具最初是由 Hackplayers 团队开发的。开发该工具的目的是尽可能简化渗透测试&#xff0c;尤其是在 Microsoft Windows 环境中。 Evil-winrm 使用 PowerShell 远程协议 (PSRP)&#xff0c;且系统和网络管理员经常使用Windows Remote Management 协议进行上传和…

C++基础四:C++模板编程

目录 一:函数模板 二:类模板 空间配置器allocator 一:函数模板 模板代码只能同一实现,不能先声明,再在另一文件实现,模板代码都是放在头文件当中的,在头文件中直接实现 二:类模板 template<typename T=int> class SeqStack // 模板名称+类型参数列表 = 类名称…

2024 年最全的 21 款数据恢复工具软件汇总

使用其中任何一款免费数据恢复工具&#xff0c;您都可以找回那些您认为已经永远消失的文件。我根据这些程序对我而言的易用性和它们提供的功能对这些程序进行了排名。 这些应用程序从您的硬盘、USB 驱动器、媒体卡等恢复文档、视频、图像、音乐等。我建议每个计算机所有者都安装…

list模拟与实现(附源码)

文章目录 声明list的简单介绍list的简单使用list中sort效率测试list的简单模拟封装迭代器insert模拟erase模拟头插、尾插、头删、尾删模拟自定义类型迭代器遍历const迭代器clear和析构函数拷贝构造&#xff08;传统写法&#xff09;拷贝构造&#xff08;现代写法&#xff09; 源…

C盘满了怎么办,Windows11的C盘没有磁盘清理选项怎么办,一次搞定

问题&#xff1a; 太久没清电脑了&#xff0c;满的跟垃圾堆一样。。。C盘红色看上去很不妙。 一. C盘满了怎么办&#xff1a; 1. 删除临时文件 找到 C:\Windows\Temp&#xff0c;进入Temp资料夹&#xff0c;选中所有文件夹和文件&#xff0c;按下ShiftDelete键&#xff0c;彻…

张宇1000和李林880究竟哪个更难?

24李林跌落神坛&#xff0c;张宇一战封神&#xff01; 张宇1000和李林880&#xff0c; 谁的基础篇更“超纲”&#xff1f; 谁覆盖的知识点更多&#xff1f; 谁的概念题更多&#xff1f; 谁的“强化难度”题更难&#xff1f; 基础篇里为什么有“跨专题”的题&#xff0c;都…

SpringBoot Elasticsearch07-以黑马商场为例-黑马程序员学习笔记

06篇已经导入了大量数据到elasticsearch中&#xff0c;实现了商品数据的存储。不过查询商品数据时依然采用的是根据id查询&#xff0c;而非模糊搜索。 接下来研究下elasticsearch的数据搜索功能。Elasticsearch提供了基于JSON的DSL&#xff08;Domain Specific Language&#…

简单通用的系统安装、备份、还原方法,支持 ARM 系统【Ventory+FirePE+DiskGenius】

文章目录 0. 简介1. 制作 Ventory 启动盘1.1. 下载 Ventory1.2. 制作 Ventory 启动盘 2. 添加 FirePE 等系统镜像到启动盘2.1. 下载 FirePE2.2. 导出 .iso 系统镜像文件2.3. .iso 系统镜像文件添加至启动盘 3. 启动 FirePE 等系统镜像3.1. 在 bios 中选择启动盘启动3.2. 启动系…

“安全生产月”专题报道:AI智能监控技术如何助力安全生产

今年6月是第23个全国“安全生产月”&#xff0c;6月16日为全国“安全宣传咨询日”。今年全国“安全生产月”活动主题为“人人讲安全、个个会应急——畅通生命通道”。近日&#xff0c;国务院安委会办公室、应急管理部对开展好2024年全国“安全生产月”活动作出安排部署。 随着科…

本地部署GLM-4-9B清华智谱开源大模型方法和对话效果体验

GLM-4-9B是清华大学和智谱AI推出的最新一代预训练模型GLM-4系列中的开源版本。在语义、数学、推理、代码和知识等多方面的数据集测评中&#xff0c;GLM-4-9B及其人类偏好对齐的版本GLM-4-9B-Chat均表现出较高的性能&#xff0c;其通用能力评测结果甚至超越了Llama-3-8B开源大模…

MPC控制简化版

MPC控制算法简化版 模型预测控制&#xff08;Model Predictive Control&#xff0c;MPC&#xff09;是一种先进的控制策略&#xff0c;广泛应用于人形机器人的运动控制。具体实现过程中&#xff0c;还需结合机器人的实际动力学模型和更多的物理约束条件。以下是一个人形机器人…

银河麒麟操作系统通过首批软件供应链安全能力认证

麒麟软件产品供应链安全能力获双重肯定&#xff01;5月30日&#xff0c;经北京赛迪认证中心评估&#xff0c;银河麒麟高级服务器操作系统V10和银河麒麟桌面操作系统V10成为首批获得软件供应链安全能力认证产品&#xff0c;并在操作系统类产品中名列前茅。 软件供应链安全能力评…

2024年【R2移动式压力容器充装】考试技巧及R2移动式压力容器充装复审考试

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 R2移动式压力容器充装考试技巧参考答案及R2移动式压力容器充装考试试题解析是安全生产模拟考试一点通题库老师及R2移动式压力容器充装操作证已考过的学员汇总&#xff0c;相对有效帮助R2移动式压力容器充装复审考试学…

什么是助听器呢?

助听器是一种用于改善听力障碍患者听觉能力的装置。它通过放大声音&#xff0c;使原本听不到或听不清的声音能够被听力受损者感知&#xff0c;从而提高其交流能力和生活质量。 助听器的基本工作原理是&#xff0c;将声音转化为电信号&#xff0c;经过内部电路处理后&#xff0c…

FPGA SPI采集ADC7606数据

一,SPI总线的构成及信号类型 SPI总线只需四条线(如图1所示)就可以完成MCU与各种外围器件的通讯: 1)MOSI – Master数据输出,Slave数据输入 2)MISO – Master数据输入,Slave数据输出 3)SCK – 时钟信号,由Master产生 4)/CS – Slave使能信号,由Master控制。 在一个SPI时…

C# 异步方法async / await 任务超时处理

一、需求 如果调用一个异步方法后&#xff0c;一直不给返回值结果怎么办呢&#xff1f;这就涉及到怎么取消任务了。 二、Task取消任务 static CancellationTokenSource source new CancellationTokenSource();static void Main(string[] args){Task.Run(() >{for (int i …

C++ | Leetcode C++题解之第132题分割回文串II

题目&#xff1a; 题解&#xff1a; class Solution { public:int minCut(string s) {int n s.size();vector<vector<int>> g(n, vector<int>(n, true));for (int i n - 1; i > 0; --i) {for (int j i 1; j < n; j) {g[i][j] (s[i] s[j]) &…

Android Ble低功耗蓝牙开发

一、新建项目 在Android Studio中新建一个项目&#xff0c;如下图所示&#xff1a; 选择No Activity&#xff0c;然后点击Next 点击Finish&#xff0c;完成项目创建。 1、配置build.gradle 在android{}闭包中添加viewBinding&#xff0c;用于获取控件 buildFeatures {viewB…