当前位置: 首页 > news >正文

STM32 驱动直流无刷电机(BLDC)发声

STM32驱动直流无刷电机(BLDC)发声


  • ✨需要注意,这是驱动直流无刷电机(BLDC)发出声音,不是直接驱动无刷电机转动。
  • 📍内容移植参考:ttps://github.com/AlkaMotors/AM32-MultiRotor-ESC-firmware
  • 📍Arduino平台BLDC Music开源工程:https://github.com/owennewo/tone-player
  • 🔖测试单片机:STM32L431、STM32F446.

在很多商业用的电调中,基本都带,在上电自检或设置以及输入信号检测时,电机会发出提示声音。BLDC电机在在PWM调制过程中,电机的绕组在不同开关频率下工作时,产生不同分贝的噪声。

📘基于AM32-MultiRotor-ESC-firmware实现发声的主要实现代码

  • 🌿sounds.c
/** sounds.c**  Created on: May 13, 2020*      Author: Alka*/#include "sounds.h"
#include "phaseouts.h"
#include "functions.h"
//#include "eeprom.h"
#include "targets.h"
#include "common.h"uint8_t beep_volume;//uint8_t blueJayTuneBuffer[128] = {};void pause(uint16_t ms) {TIM1->CCR1 = 0; // volume of the beep, (duty cycle) don't go above 25TIM1->CCR2 = 0;TIM1->CCR3 = 0;delayMillis(ms);TIM1->CCR1 = beep_volume; // volume of the beep, (duty cycle) don't go above 25 out of 2000蜂鸣声的音量(占空比)在2000中不超过25TIM1->CCR2 = beep_volume;TIM1->CCR3 = beep_volume;
}void setVolume(uint8_t volume) {if (volume > 11) {volume = 11;}if (volume < 0) {volume = 0;}beep_volume = volume * 2;           // volume variable from 0 - 11 equates to CCR value of 0-22
}void setCaptureCompare() {TIM1->CCR1 = beep_volume; // volume of the beep, (duty cycle) don't go above 25 out of 2000TIM1->CCR2 = beep_volume;TIM1->CCR3 = beep_volume;
}void playBJNote(uint16_t freq, uint16_t bduration) {       // hz and msuint16_t timerOne_reload = TIM1_AUTORELOAD;TIM1->PSC = 10;timerOne_reload = CPU_FREQUENCY_MHZ * 100000 / freq;TIM1->ARR = timerOne_reload;TIM1->CCR1 = beep_volume * timerOne_reload / TIM1_AUTORELOAD ; // volume of the beep, (duty cycle) don't go above 25 out of 2000TIM1->CCR2 = beep_volume * timerOne_reload / TIM1_AUTORELOAD;TIM1->CCR3 = beep_volume * timerOne_reload / TIM1_AUTORELOAD;delayMillis(bduration);
}uint16_t getBlueJayNoteFrequency(uint8_t bjarrayfreq) {return 10000000 / (bjarrayfreq * 247 + 4000);
}void playStartupTune() {__disable_irq();TIM1->ARR = TIM1_AUTORELOAD;setCaptureCompare();comStep(3);       // activate a pwm channelTIM1->PSC = 55;        // frequency of beepdelayMillis(200);         // duration of beepcomStep(5);TIM1->PSC = 40;            // next beep is higher frequencydelayMillis(200);comStep(6);TIM1->PSC = 25;         // higher again..delayMillis(200);allOff();                // turn all channels low againTIM1->PSC = 0;           // set prescaler back to 0.TIM1->ARR = TIMER1_MAX_ARR;__enable_irq();
}void playBrushedStartupTune() {__disable_irq();TIM1->ARR = TIM1_AUTORELOAD;setCaptureCompare();comStep(1);       // activate a pwm channelTIM1->PSC = 40;        // frequency of beepdelayMillis(300);         // duration of beepcomStep(2);       // activate a pwm channelTIM1->PSC = 30;        // frequency of beepdelayMillis(300);         // duration of beepcomStep(3);       // activate a pwm channelTIM1->PSC = 25;        // frequency of beepdelayMillis(300);         // duration of beepcomStep(4);TIM1->PSC = 20;         // higher again..delayMillis(300);allOff();                // turn all channels low againTIM1->PSC = 0;           // set prescaler back to 0.
//	signaltimeout = 0;TIM1->ARR = TIMER1_MAX_ARR;__enable_irq();
}void playDuskingTune() {setCaptureCompare();TIM1->ARR = TIM1_AUTORELOAD;comStep(2);       // activate a pwm channelTIM1->PSC = 60;        // frequency of beepdelayMillis(200);         // duration of beepTIM1->PSC = 55;            // next beep is higher frequencydelayMillis(150);TIM1->PSC = 50;         // higher again..delayMillis(150);TIM1->PSC = 45;        // frequency of beepdelayMillis(100);         // duration of beepTIM1->PSC = 50;            // next beep is higher frequencydelayMillis(100);TIM1->PSC = 55;         // higher again..delayMillis(100);TIM1->PSC = 25;         // higher again..delayMillis(200);TIM1->PSC = 55;         // higher again..delayMillis(150);allOff();                // turn all channels low againTIM1->PSC = 0;           // set prescaler back to 0.TIM1->ARR = TIMER1_MAX_ARR;
}void playInputTune2() {TIM1->ARR = TIM1_AUTORELOAD;__disable_irq();
//	LL_IWDG_ReloadCounter(IWDG);TIM1->PSC = 60;setCaptureCompare();comStep(1);delayMillis(75);TIM1->PSC = 80;delayMillis(75);TIM1->PSC = 90;
//	LL_IWDG_ReloadCounter(IWDG);delayMillis(75);allOff();TIM1->PSC = 0;
//	signaltimeout = 0;TIM1->ARR = TIMER1_MAX_ARR;__enable_irq();
}void playInputTune() {__disable_irq();TIM1->ARR = TIM1_AUTORELOAD;
//	LL_IWDG_ReloadCounter(IWDG);TIM1->PSC = 80;setCaptureCompare();comStep(3);delayMillis(100);TIM1->PSC = 70;delayMillis(100);TIM1->PSC = 40;delayMillis(100);allOff();TIM1->PSC = 0;
//	signaltimeout = 0;TIM1->ARR = TIMER1_MAX_ARR;__enable_irq();
}void playDefaultTone() {TIM1->ARR = TIM1_AUTORELOAD;TIM1->PSC = 50;setCaptureCompare();comStep(2);delayMillis(150);
//	LL_IWDG_ReloadCounter(IWDG);TIM1->PSC = 30;delayMillis(150);allOff();TIM1->PSC = 0;
//	signaltimeout = 0;TIM1->ARR = TIMER1_MAX_ARR;}void playChangedTone() {TIM1->ARR = TIM1_AUTORELOAD;TIM1->PSC = 40;setCaptureCompare();comStep(2);delayMillis(150);
//	LL_IWDG_ReloadCounter(IWDG);TIM1->PSC = 80;delayMillis(150);allOff();TIM1->PSC = 0;
//	signaltimeout = 0;TIM1->ARR = TIMER1_MAX_ARR;}void playBeaconTune3() {TIM1->ARR = TIM1_AUTORELOAD;__disable_irq();setCaptureCompare();for (int i = 119 ; i > 0 ; i = i - 2) {
//		LL_IWDG_ReloadCounter(IWDG);comStep(i / 20);TIM1->PSC = 10 + (i / 2);delayMillis(10);}allOff();TIM1->PSC = 0;TIM1->ARR = TIMER1_MAX_ARR;__enable_irq();
}
  • 🌿main测试代码:
int main(void)
{/* USER CODE BEGIN 1 *//* USER CODE END 1 *//* MCU Configuration--------------------------------------------------------*//* Reset of all peripherals, Initializes the Flash interface and the Systick. */HAL_Init();/* USER CODE BEGIN Init *//* USER CODE END Init *//* Configure the system clock */SystemClock_Config();/* USER CODE BEGIN SysInit *//* USER CODE END SysInit *//* Initialize all configured peripherals */MX_GPIO_Init();MX_COMP1_Init();MX_TIM1_Init();MX_TIM6_Init();MX_TIM16_Init();MX_USART2_UART_Init();// MX_IWDG_Init();MX_TIM7_Init();/* USER CODE BEGIN 2 */HAL_TIM_Base_Start(&htim6);HAL_TIM_Base_Start(&htim7);HAL_TIM_Base_Start(&htim16);HAL_TIM_GenerateEvent(&htim1, TIM_EVENTSOURCE_UPDATE);PWM_Init();TIMER1_MAX_ARR = map(35, 24, 48, TIM1_AUTORELOAD, TIM1_AUTORELOAD / 2);//24 - 48鑼冨洿// TIMER1_MAX_ARR = map(20, 12, 24, TIM1_AUTORELOAD * 2, TIM1_AUTORELOAD); //12 - 24鑼冨洿// TIMER1_MAX_ARR = map(10, 7, 16, TIM1_AUTORELOAD * 3, TIM1_AUTORELOAD / 2 * 3);//7 - 16鑼冨洿TIM1->ARR = TIMER1_MAX_ARR;setVolume(5);/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while(1) {/* USER CODE END WHILE *//* USER CODE BEGIN 3 */printf("from playInputTune Sound.\r\n");playInputTune();//这个几乎听不到声音LL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);HAL_Delay(2500);printf("from playInputTune2 Sound.\r\n");playInputTune2();LL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);HAL_Delay(2500);printf("from playInputTune3 Sound.\r\n");playBeaconTune3();LL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);HAL_Delay(2500);}/* USER CODE END 3 */
}
📚测试工程
  • 🔖STM32L431
链接:https://pan.baidu.com/s/1hdn-vaNXe4UvFgnPtAgJlA?pwd=ikvv 
提取码:ikvv

📘Arduino tone-player项目简介

  • 🔖工程基于VSCode platformio ,基于Arduino平台。直接使用VSCode打开,如果安装了STM32相关固件,会自动加载并安装相对应的库。(编译工程时,不要有中文路径名,否则会在最终生成文件时报错)
    在这里插入图片描述
  • 🛠上传支持:stlink cmsis-dap, jlink

-🌟 如果点击烧录时,OpenOCD上传报错,可以直接选择对应生成的.bin文件进行烧录。

Error: timed out while waiting for target halted
embedded:startup.tcl:1516: Error: ** Unable to reset target **
in procedure 'program' 
in procedure 'program_error' called at file "embedded:startup.tcl", line 1553
at file "embedded:startup.tcl", line 1516
*** [upload] Error 1
========================================= [FAILED] Took 194.56 seconds =========================================
  • 👉修改路径下:C:\Users\Administrator\.platformio\packages\tool-openocd\openocd\scripts\board相关型号对应的.cfg文件:
    在这里插入图片描述
  • 🔖将cfg里面的reset_config srst_only改为reset_config none.
  • 🔧工程依赖SimpleFOCSimpleFOCDrivers
  • 📄包含以下音乐内容:
  • RTTTL_CROATIA
  • RTTTL_FRANCE
  • RTTTL_WALES
  • RTTTL_USA
  • RTTTL_SIMPSONS
  • RTTTL_PINK_PANTHER
  • RTTTL_SUPER_MARIO_BROS
  • RTTTL_SUPER_MARIO_BROS_BASS
  • RTTTL_SUPER_MARIO_BROS_POLY
  • 🌿在运行时,串口2(PA2,PA3)会打印当前频率:
    在这里插入图片描述

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 使用Python编写文件重复检查器
  • ffmpeg-cavs识别广电流
  • OpenAI 取消为 ChatGPT 加水印计划,用户反应成关键因素|TodayAI
  • 1. protobuf学习
  • go语言flag库学习
  • 一个是生产打包的时候, 一个是本地测试启动的时候,maven如何配置?
  • 天地图按地名搜索+openlayer+vue3
  • 如何在IDEA上使用JDBC编程【保姆级教程】
  • 力扣第五十三题——最大子数组和
  • 如何开始学习Swift编程?
  • MySQL 实战 45 讲(01-05)
  • C# udp通信测试助手
  • 【数据分享】2024最新安徽省镇级行政区划矢量shp
  • 【面试经验】京东java京东young 一面80min
  • 电子元器件—三极管(一篇文章搞懂电路中的三极管)(笔记)(面试考试必备知识点)
  • #Java异常处理
  • 2018一半小结一波
  • android图片蒙层
  • 从重复到重用
  • 关于for循环的简单归纳
  • 欢迎参加第二届中国游戏开发者大会
  • 基于阿里云移动推送的移动应用推送模式最佳实践
  • 那些被忽略的 JavaScript 数组方法细节
  • 融云开发漫谈:你是否了解Go语言并发编程的第一要义?
  • 使用parted解决大于2T的磁盘分区
  • 与 ConTeXt MkIV 官方文档的接驳
  • # 利刃出鞘_Tomcat 核心原理解析(七)
  • #FPGA(基础知识)
  • #基础#使用Jupyter进行Notebook的转换 .ipynb文件导出为.md文件
  • (+4)2.2UML建模图
  • (13)DroneCAN 适配器节点(一)
  • (Mirage系列之二)VMware Horizon Mirage的经典用户用例及真实案例分析
  • (python)数据结构---字典
  • (附源码)springboot 基于HTML5的个人网页的网站设计与实现 毕业设计 031623
  • (附源码)计算机毕业设计ssm基于B_S的汽车售后服务管理系统
  • (附源码)计算机毕业设计SSM疫情社区管理系统
  • (论文阅读26/100)Weakly-supervised learning with convolutional neural networks
  • (三)SvelteKit教程:layout 文件
  • (十七)Flink 容错机制
  • (限时免费)震惊!流落人间的haproxy宝典被找到了!一切玄妙尽在此处!
  • .bat批处理(四):路径相关%cd%和%~dp0的区别
  • .NET 8 跨平台高性能边缘采集网关
  • .NET Framework杂记
  • .net websocket 获取http登录的用户_如何解密浏览器的登录密码?获取浏览器内用户信息?...
  • .NET/C# 将一个命令行参数字符串转换为命令行参数数组 args
  • .NET/C# 解压 Zip 文件时出现异常:System.IO.InvalidDataException: 找不到中央目录结尾记录。
  • .Net插件开发开源框架
  • .sh 的运行
  • /etc/fstab和/etc/mtab的区别
  • /etc/sudoers (root权限管理)
  • @Builder注释导致@RequestBody的前端json反序列化失败,HTTP400
  • @Documented注解的作用
  • @GlobalLock注解作用与原理解析
  • @ModelAttribute 注解
  • @property括号内属性讲解