pwm波如何控制电机代码_PWM波控制720电机

详细方案四:pwm与720电机控制

电机硬件分析

什么是电机?

电机(俗称"马达")是指依据电磁感应定律实现电能转换或传递的一种电磁装置。它的主要作用是产生驱动转矩,作为用电器或各种机械的动力源。其中本四轴采用的电机是直流电机。直流电动机是将直流电能转换为机械能的电动机。因其良好的调速性能而在电力拖动中得到广泛应用。

d8c0c98fdef81a9de25f2e0911ba9733.gif
图1 直流电机图

那么是不是直接在电机两端加上电压就可以了?

直接在直流电机加上电压,确实能够使得电机转动而且转速完全能够满足四轴飞行的动力,但是这样的四轴没法控制电机的转速,加电后四轴只会朝天上飞而且没法控制。最后有可能炸机。

那怎么控制电机的转速?

直流电动机是将直流电能转换为机械能的电动机,也就是说只要控制住电流的话,就可以控制电机的转速了。那问题就变成了如何控制电流了。

电流怎样控制电机的转速?

我们想想,有电流电机就转,没电流电机就不转。那如果、10ms内,如果6ms电机有电流,4ms没电流。电机是前6ms转,后4ms不转?实际上是10ms电机都在转。前6ms电机有电流电机转,后4ms虽然没有电流但是由于惯性的作用电机依旧在转,只不过转速在不断的减少。如果将将10ms的周期不断的循环,不断认为地控制电流的导通的时间是不是就可以控制电机的转速了。其中这周期不能太大一般为ms或者ns级别的。

914eccdda48327bf6da24607c0fa38c7.gif
图2 电流控制电机

那么问题又来到了怎么控制电流上了

根据欧姆定律,在电阻不变的情况下,电压与电流成正比。高电平就是有电流流经电机,低电平就是电路断开没有电流流经电机。这个让电流能否流进电机就好像一个门阀且该门阀的开关的速度要达到ms和ns级别,那这门阀无疑MOS管是最佳人选。外加电压在MOS管在栅源极上如果大于MOS的开启电压MOS管内部就会导通,如果外加栅源极小于MOS的开启电压MOS管处于截止区,也就是该电路断开

最后的难题是电压

有什么电压能够在周期内输入稳定的高低电平到MOS管的栅源极?那就属PWM波最好了。

1109560ef99fa3e57960749477aa336a.png

图3 pwm波定义图

PWM波即是通过单片机在一个周期内,让单片机的IO口输出一段时间的高电平,一段时间的低电平。如上图所示为为一个方波的周期,其占空比为t/T。其调节高低电平过程如下图

5d861a1cf5161eae5acbd1858804b361.gif
图4 pwm波调制图

本四轴电机采用的是720空心杯电机。电机的驱动原理是通过STM32芯片IO口输出PWM波(调节高电平的占空比)然后经过NMOS管来驱动电机的转速其电路图如下:

b6c1949bb4cd69b0255f0144a3c34fa8.png
图5 电机原理图

电路分析:

单片机IO口输出PWM波给电路,后经过R8和R10分压(防止电压直接加载到NMOS导致击穿同时也保证了栅源电压大于开启电压)

如果此时的PWM波电压处于高电平那么NMOS管导通,此时电池提供的电压和电流经过电机接地。如果此时PWM波电压处于低电平NMOS管就会截止,电路断开没法接地电机转动的速度逐渐减少,只有等到下一个高电平来临的时候电机的转速才会提升。

电路中的电容的作用是去耦的作用,由于电机在转动的时候会产生磁场导致电机的电压上下波动,该电压有滤波的左右

此外在电机一旁并联二极管是因为电机在减速产生了电磁感应会有微弱的电流,防止它内流。二极管有分流消耗的作用。

软件分析

本四轴采用的是STM32F411单片机芯片。本次采用的是PWM1模式使用的时钟是TIM3

单片机该如何产生PWM波?

d25b89554d02a5c90b663a535f7d140c.png

图6 单片机产生pwm波定义图
  • 如上图所示,假设单片机某IO口是锯齿波。其中ARR是单片机计数器的上限。单片机首  先开启TIM3定时器从0计数到ARR后又从0重新开始计数到ARR不断的循环重复。
  • 在0到ARR的计数期间单片机内部存在一个CCRX的输入捕获比较器,里面装载着参考电压。用来比较锯齿波的电压是否大于参考电压。如果大于那么IO口输出高电平,低于参考电压则输出低电平。
  • 其中占空比就是高电平时间占据整个定时周期的时间,也就是
  • 所以要调节占空比直接调节CCRX的值就可以了。

单片机产生PWM波的工作过程

69092a0381fcf67f0211b007ba82b4d3.png

图7 单片机内部产生pwm结构图
  • 如上图所示,就是单片机产生pwm波的模式一,其中OCIM是控制pwm模式几的。
  • OCIM被配置为模式一计数模式是向上计数的时候,一旦TIMx CNT < CCR1时通道1为有效电平否则是无效电平。如果是向下计数模式的时候则是相反。
  • 输出的OC1ref有效电平到达CCIP寄存器前,则通过设计是否为1/0如果为1则说明有OC1ref输出是高电平有效,反之为低电平。
  • 最有CO1E是IO口中断输出使能,为1时信号能够输出,为0则禁止输出

8511eefdf007f18cc2004346301892fa.png

图8 pwm波计数图

上述的PWM波产生过程图的输入的CNT与CCR1的比较究竟是怎么回事?

  • CCR1其实是CCRx寄存器中的一个值,如上图所示如果CCRx等于4且为向上计数时。0-3的为有效电平,若OCREF为1则为高电平有效,剩下的低电平有效,CCxIF则相反。
  • 此外单片机的IO口输出为PWM输出功能,并非普通IO口所以在配置的时候要设置为复用的IO口输出,期间还有到了TIM1定时器,所以还要将TIM3的定时器功能映射到IO口上。

编程前的准备

编程需要的步骤

①四个电机定义

②电机最大最小速度定义

③使能定时器和IO口时钟

④初始化IO口为复用功能输出和GPIO复用映射到TIM3

⑤初始化定时器和输出比较参数

⑥使能定时器

编程代码

#include "stm32f4xx.h"
#include "motor.h"

#define Moto_PwmMax 1000
int16_t MOTO1_PWM = 0;
int16_t MOTO2_PWM = 0;
int16_t MOTO3_PWM = 0;
int16_t MOTO4_PWM = 0;

/******************************************************************************************
*函  数:void TIM3_GpioConfig(void)
*功  能:TIM3 PWM输出通道GPIO设置
*参  数:无
*返回值:无
*备  注:TIM3 CH1(PWM1) -> PA6
*        TIM3 CH2(PWM2) -> PA7
*        TIM3 CH3(PWM3) -> PB0
*        TIM3 CH4(PWM4) -> PB1
*******************************************************************************************/
void TIM3_GpioConfig(void){
  GPIO_InitTypeDef GPIO_InitStructure;

  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //TIM3 时钟使能

  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA|RCC_AHB1Periph_GPIOB, ENABLE); //GPIOA GPIOB 时钟使能 
  
  //GPIOB 配置: TIM3 CH1 (PA6), TIM3 CH2 (PA7), TIM3 CH3 (PB0) and TIM3 CH4 (PB2) 
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; //复用模式
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; //速度100M
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推完输出
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉输入
  //PA6 PA7 初始化 
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7 ;
  GPIO_Init(GPIOA, &GPIO_InitStructure); 
  //PB0 PB1 初始化
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 ;
  GPIO_Init(GPIOB, &GPIO_InitStructure); 

  //连接 TIM3 的通道到 AF2 
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_TIM3);
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_TIM3); 
  GPIO_PinAFConfig(GPIOB, GPIO_PinSource0, GPIO_AF_TIM3);
  GPIO_PinAFConfig(GPIOB, GPIO_PinSource1, GPIO_AF_TIM3); 
}

/******************************************************************************************
*函  数:void MOTOR_Init(void)
*功  能:输出PWM初始化
*参  数:无
*返回值:无
*备  注:TIMx_ARR  决定方波的周期
*        TIMx_CCRx 决定方波的占空比
*******************************************************************************************/
void MOTOR_Init(void){
  TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
  TIM_OCInitTypeDef TIM_OCInitStructure;
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
 
 
  TIM3_GpioConfig();
  //更新中断时间 Tout = (ARR-1)*(PSC-1)/CK_INT
  //TIM2~TIM5时钟来源于APB1*2
  TIM_TimeBaseStructure.TIM_Period = 1000-1; //自动重装载值
  TIM_TimeBaseStructure.TIM_Prescaler = 100-1; //预分频值
  TIM_TimeBaseStructure.TIM_ClockDivision = 0;
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
  TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
 
  //PWM1 模式配置 通道1
  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  TIM_OCInitStructure.TIM_Pulse = 0;
  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;

  TIM_OC1Init(TIM3, &TIM_OCInitStructure);
  TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable); //电机1
  TIM_OC2Init(TIM3, &TIM_OCInitStructure);
  TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable); //电机2
  TIM_OC3Init(TIM3, &TIM_OCInitStructure);
  TIM_OC3PreloadConfig(TIM3, TIM_OCPreload_Enable); //电机3
  TIM_OC4Init(TIM3, &TIM_OCInitStructure);
  TIM_OC4PreloadConfig(TIM3, TIM_OCPreload_Enable); //电机4
  //ARR 寄存器预装载
  TIM_ARRPreloadConfig(TIM3, ENABLE);

  //TIM_PrescalerConfig(TIM3, PrescalerValue, TIM_PSCReloadMode_Immediate);
 
  TIM_Cmd(TIM3,ENABLE); //使能TIM3
}

/*****************************************************************************
*函  数:void Moto_Pwm(int16_t MOTO1_PWM,int16_t MOTO2_PWM,int16_t MOTO3_PWM,int16_t MOTO4_PWM)
*功  能:电机要输出数值转换成PWM波形输出
*参  数:MOTO1_PWM 电机1
*        MOTO2_PWM 电机2
*        MOTO3_PWM 电机3
*        MOTO3_PWM 电机4
*返回值:无 
*备  注:无
*****************************************************************************/
void Moto_Pwm(int16_t MOTO1_PWM,int16_t MOTO2_PWM,int16_t MOTO3_PWM,int16_t MOTO4_PWM){  
 if(MOTO1_PWM>Moto_PwmMax) MOTO1_PWM = Moto_PwmMax;
 if(MOTO2_PWM>Moto_PwmMax) MOTO2_PWM = Moto_PwmMax;
 if(MOTO3_PWM>Moto_PwmMax) MOTO3_PWM = Moto_PwmMax;
 if(MOTO4_PWM>Moto_PwmMax) MOTO4_PWM = Moto_PwmMax;
 if(MOTO1_PWM<0) MOTO1_PWM = 0;
 if(MOTO2_PWM<0) MOTO2_PWM = 0;
 if(MOTO3_PWM<0) MOTO3_PWM = 0;
 if(MOTO4_PWM<0) MOTO4_PWM = 0;
 
 TIM3->CCR1 = MOTO1_PWM;
 TIM3->CCR2 = MOTO2_PWM;
 TIM3->CCR3 = MOTO3_PWM;
 TIM3->CCR4 = MOTO4_PWM;
}


78f92d498c515a2467c0fa0b3f01192b.png

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

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

相关文章

arduino使用oled代码_【惊不?】Arduino改造古董卡西欧计算器为作弊神器

一台朴实无华的计算器&#xff0c;卡西欧牌。看起来和千万学子们所使用的计算器一样&#xff0c;没什么特别的&#xff0c;还带着一些陈旧的使用痕迹。但如果你用磁铁碰一下&#xff1a;咦&#xff0c;简直像打开了探险电影里的神秘机关&#xff0c;右上角的太阳能电池板部分居…

python字符串数组_python将字符串转换成数组的方法

Python这篇文章主要介绍了Python __setattr__、 __getattr__、 __delattr__、__call__用法示例,本文分别对这几个魔法方法做了讲解,需要的朋友可以参考下 ... junjie4882019-11-22 Python这篇文章主要介绍了Python实现list反转的方法,实例总结了关于list的各种较为常见的操作技…

vsc写vue生成基本代码快捷键_基于vue2.X的webpack基本配置,教你手动撸一个webpack4的配置...

webpack说复杂也不复杂。不复杂&#xff0c;核心概念不外乎是entry, output, loader, plugins。webpack4还新增了optimization选项&#xff0c;用于代码分割和打包优化。现在webpack官网文档已经写的挺棒了。而当你真正开始手写一个webpack.config.js的时候&#xff0c;你就会发…

几款效率神器助你走上人生巅峰

一、背景 在我的工作和生活中&#xff0c;我一直都很注重效率工具的使用&#xff0c;这么些年下来也积累好几款很不错&#xff0c;但是又不为大多数人所熟知的软件工具&#xff0c;我用起来得心应手&#xff0c;很不错。那我就像在此给大家做个分享&#xff0c;希望你们都能多多…

macos下载的安装包在哪里_macbook任意降级,为您带来mac os完美降级教程

最近有许多用户反映升级了最新的系统出现了各种奇葩问题&#xff0c;更关键的是&#xff0c;很多常用&#xff08;专业&#xff09;软件不能使用了。因此有许多用户想要降级&#xff0c;现在macdown小编为您带来mac os完美降级教程&#xff0c;有需要的赶紧收藏啦&#xff01;第…

kodi刮削器 中文_教你PLEX插件播放4K不能使用KODI解码导致卡顿的解决办法

文章作者Hao4K用户nothero自从买了这个索尼9500g&#xff0c;三天两头的出问题&#xff0c;而且还经常重启&#xff0c;经常卡顿。大法的画质确实不错&#xff0c;但是这系统稳定性实在是不敢恭维...最近装了一个KODI-PLEX插件&#xff0c;安利安利{:4_96:}&#xff0c;画面实在…

玩下软工项目,第一轮--全局Context的获取,SQLite的建立与增删改查,读取用户通话记录信息...

项目的Github地址&#xff1a;https://github.com/ggrcwxh/LastTime 采用基于git的多人协作开发模式 软件采用mvc设计模式&#xff0c;前端这么艺术的事我不太懂&#xff0c;交给斌豪同学去头疼了。第一轮先实现查询通话记录返回对应号码上一次的通话时间。 真机测试下的效果图…

jvm垃圾回收机制_深入理解JVM的垃圾回收机制

​如何判断对象已“死”Java堆中存放着几乎所有的对象实例&#xff0c;垃圾回收器在堆进行垃圾回收前&#xff0c;首先要判断这些对象那些还存活&#xff0c;那些已经“死去”。判断对象是否已“死”有如下几种算法&#xff1a;1引用计数法引用计数法描述的算法为&#xff1a;给…

chown -r oracle:oinstall /oracle,CentOS7安装Oracle12c图文详解

root身份安装依赖包&#xff1a; yum -y install binutils compat-libcap1 compat-libstdc-33 compat-libstdc-33*.i686 elfutils-libelf-devel gcc gcc-c glibc*.i686 glibc glibc-devel glibc-devel*.i686 ksh libgcc*.i686 libgcc libstdc libstdc*.i686 libstdc-devel li…

在苹果笔记本如何使用python_mac下如何将python2.7改为python3

1.查看当前电脑python版本 python -V // 显示2.7.x 2.用brew升级python brew update python 3.如果安装成功&#xff0c;去系统目录下回看到两个版本的python cd usr/local/Cellar/ //到此目录下 cd python/ //进入python目录下 查看已安装的python版本&#xff0c;如果有2.x 和…

[BZOJ1834][ZJOI2010]network 网络扩容 最大流+费用流

1834: [ZJOI2010]network 网络扩容 Time Limit: 3 Sec Memory Limit: 64 MB Submit: 3330 Solved: 1739 [Submit][Status][Discuss]Description 给定一张有向图&#xff0c;每条边都有一个容量C和一个扩容费用W。这里扩容费用是指将容量扩大1所需的费用。求&#xff1a; 1、 …

python需要花钱下载吗_用Python下载知乎视频,非常实用

原标题&#xff1a;用Python下载知乎视频&#xff0c;非常实用Python下载知乎视频。 # -*- coding: utf-8 -*- """ 下载知乎视频&#xff1a; 依赖&#xff1a; pip install requests mac 安装 ffmpeg: brew install ffmpeg """ import re impor…

python相比于excel的优势_对照Excel使用Python进行数据分析,更快掌握

Excel和Python&#xff0c;作为数据分析的主流工具&#xff0c;在从效率提升到数据商业化的整个过程中&#xff0c;都起到了重要作用。不管是在Excel中通过鼠标点选实现&#xff0c;亦或是利用Python通过代码实现&#xff0c;数据分析中的很多基础功能都是相通的。 在数据量级大…

python二维图颜色函数_Python scipy的二维图像卷积运算与图像模糊处理操作示例

本文实例讲述了Python scipy的二维图像卷积运算与图像模糊处理操作。分享给大家供大家参考&#xff0c;具体如下&#xff1a; 二维图像卷积运算 一 代码 import numpy as np from scipy import signal, misc import matplotlib.pyplot as plt image misc.ascent()#二维图像数组…

linux命令行大全 笔记,《Linux命令行大全》读书笔记

8种机械键盘轴体对比本人程序员&#xff0c;要买一个写代码的键盘&#xff0c;请问红轴和茶轴怎么选&#xff1f;shell就是一个程序&#xff0c;它接受从键盘输入的命令&#xff0c;然后把命令传递给操作系统执行。当使用图像用户界面时&#xff0c;我们需要一个叫做终端仿真器…

dedecms 添加,编辑文章时 文章标题有字数限制的解决办法。

百度上说 解决方法有两步&#xff1a; 一、先要在系统参数下的其他选项中修改文档标题最大长度&#xff08;如修改为150&#xff09;&#xff0c; 后台系统 - 其它选项 - 文档标题最大长度 默认的是60改为150&#xff0c; 二、修改默认参数后&#xff0c;需要手工修改数据表。 …

python绘制散点图、如何选两列作为横坐标_在matplotlib散点图(水平杆图)中从x=0到数据点绘制水平线...

考虑以下情节&#xff1a;由此函数生成&#xff1a;def timeDiffPlot(dataA, dataB, savetoNone, legNone): labels list(dataA["graph"]) figure(figsizescreenMedium) ax gca() ax.grid(True) xi range(len(labels)) rtsA dataA["running"] / 1000.0…

python运行命令_Python中执行外部命令

有很多需求需要在Python中执行shell命令、启动子进程&#xff0c;并捕获命令的输出和退出状态码&#xff0c;类似于Java中的Runtime类库。 subprocess模块的使用&#xff1a; Python使用最广泛的是标准库的subprocess模块&#xff0c;用来替换os.system(),os.spawn*(),os.popen…

linux多选项菜单脚本,linux shell 编写菜单脚本事例

menu2文件代码&#xff1a;---#!/bin/sh#menu2#Main menu script#ignore ctrl-c and QUIT interruptstrap "" 2 3 15MYDATEdate %d/%m/%YTHIS_HOSThostname -sUSERwhoami#user level fileUSER_LEVELSpriv.user#hold fileHOLD1hold1.$$#colour functionfunction colou…

python简单爬虫入门一_Python爬虫快速入门:基本结构简单实例

本爬虫系列入门教程假设读者仅有一点点Python基础或者近乎为零的基础。如果是有Python基础的可以跳过一些对于Python基本知识的补充。 爬虫能干什么呢&#xff1f;一句话概括&#xff0c;正常通过浏览器可以获取的数据&#xff0c;爬虫都可以获取。这句话可以说是包罗万象。一是…