STM32外设系列—L298N

news2024/9/21 0:51:41

文章目录

  • 一、L298N简介
  • 二、L298N电路图
  • 三、L298N使用方法
  • 四、L298N驱动电机实例
    • 4.1 麦克纳姆轮简介
    • 4.2 定时器PWM配置
    • 4.3 智能车行驶控制
  • 五、拓展应用

一、L298N简介

L298N是SGS公司生产的一款通用的电机驱动模块。其内部包含4路逻辑驱动电路,有两个H桥的高电压大电流全桥驱动器,接收TTL逻辑电平信号,一个模块可同时驱动两个直流电机工作,具有反馈检测和过热自断功能。利用L298N驱动电机时,主控芯片只需通过I/O口输出控制电平即可实现对电机转向的控制,编程简单,稳定性好。

L298N

二、L298N电路图

L298N的电路图如下

L298N电路图

OUT1、OUT2、OUT3和OUT4之间分别接两个电机。IN1、IN2、IN3和IN4引脚接STM32单片机,用来接收单片机发送来的控制电平,控制电机的转动方向,ENA和ENB为使能端。

三、L298N使用方法

L298N通常用于电机驱动,控制电机的转向,转速。电机转向通过IN1,IN2,IN3和IN4的逻辑电平控制,转向通过给输入引脚输入的PWM占空比控制。L298N控制电机转动状态的逻辑功能表如下

L298N控制电机转动状态逻辑功能表

正如上面所说,电机的调速可以通过单片机给输入引脚发送PWM信号来实现。电机的转速与电机两端PWM信号的占空比成正比,占空比越大,电机转速越快。

四、L298N驱动电机实例

一个L298N可以驱动两个电机,博主使用时L298N用12V航模电池供电,L298N输出的5V给单片机供电。这里以利用两个L298N,驱动四个电机,搭配麦克纳姆轮实现车的前进,后退,平移和自转为例,展示一下L298N的配置和使用流程。同时,也对麦克纳姆轮做一个简单介绍。

4.1 麦克纳姆轮简介

麦克纳姆轮与传统轮胎相比可以实现全向移动,能够在较为狭小的空间内任意行进,更加灵活。虽然麦克纳姆轮相比于传统轮胎也有许多缺点,比如麦克纳姆轮的能耗高,成本也高,而且还容易受到地形限制,但是对于机器人大赛以及一些工业生产用的智能车来说,麦克纳姆轮的全向移动优势就表现得十分突出,避障时麦克纳姆轮小车可直接平移,无需提前预留转弯角度,也无需其他传感器辅助,编写程序时更加简洁,所以最终我选择使用麦克纳姆轮来实现小车的全向移动。

麦克纳姆轮

麦克纳姆轮主要是由轮毂和辊子两部分组成,辊子轴线和轮毂轴线夹角为45°,有互为镜像的A/B轮两种,安装时所有轮子辊子的轴线方向都要指向小车的中心,这是因为麦轮的全向移动是通过力的合成和分解来实现的,如果A/B轮混用或者没有按照上述要求安装会导致小车没法正常行驶。

4.2 定时器PWM配置

使用TIM2和TIM3的四个PWM通道(共8路PWM)来控制车速,这里配置了固定的预分频系数和自动重装载值。对于定时器的内容,可见博主STM32速成笔记的定时器介绍部分。TIM2和TIM3初始化程序如下

/*
 *==============================================================================
 *函数名称:TIM2_PWM_Init
 *函数功能:初始化定时器2的PWM
 *输入参数:无
 *返回值:无
 *备  注:预分频系数和自动重装载值固定
 *==============================================================================
 */
void TIM2_PWM_Init (void)
{
	// 结构体定义
	GPIO_InitTypeDef GPIO_InitStructure;
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	TIM_OCInitTypeDef TIM_OCInitStructure;

	// 开启时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO
                       	| RCC_APB1Periph_TIM2,ENABLE);

	// 配置GPIO
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;   // 复用推挽输出
	GPIO_Init(GPIOA,&GPIO_InitStructure);
	
	// 配置TIM2
	TIM_TimeBaseInitStructure.TIM_Period = 899;
	TIM_TimeBaseInitStructure.TIM_Prescaler = 0;
	TIM_TimeBaseInitStructure.TIM_ClockDivision = 0;
	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInit(TIM2, & TIM_TimeBaseInitStructure);


	// 配置PWM通道1
  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
  TIM_OCInitStructure.TIM_Pulse = 899;
  TIM_OC1Init(TIM2 , &TIM_OCInitStructure);
  TIM_OC1PreloadConfig(TIM2 , TIM_OCPreload_Enable);
  
  // 配置PWM通道2
  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
  TIM_OCInitStructure.TIM_Pulse = 899;
  TIM_OC2Init(TIM2 , &TIM_OCInitStructure);
  TIM_OC2PreloadConfig(TIM2 , TIM_OCPreload_Enable);
  
  // 配置PWM通道3
  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
  TIM_OCInitStructure.TIM_Pulse = 899;
  TIM_OC3Init(TIM2 , &TIM_OCInitStructure);
  TIM_OC3PreloadConfig(TIM2 , TIM_OCPreload_Enable);
  
  // 配置PWM通道4
  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
  TIM_OCInitStructure.TIM_Pulse = 899;
  TIM_OC4Init(TIM2 , &TIM_OCInitStructure);
  TIM_OC4PreloadConfig(TIM2 , TIM_OCPreload_Enable);
  
	// 使能TIM2
  TIM_Cmd(TIM2 , ENABLE);
}
/*
 *==============================================================================
 *函数名称:TIM3_PWM_Init
 *函数功能:初始化定时器3的PWM
 *输入参数:无
 *返回值:无
 *备  注:预分频系数和自动重装载值固定
 *==============================================================================
 */
void TIM3_PWM_Init (void)
{
	// 结构体定义
  GPIO_InitTypeDef GPIO_InitStructure;
  TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
  TIM_OCInitTypeDef TIM_OCInitStructure; 
	
	// 开启时钟
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO
	                       | RCC_APB1Periph_TIM3, ENABLE);
	
	// 配置GPIO
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;   // 复用推挽式输出
  GPIO_Init(GPIOA, &GPIO_InitStructure);   
  
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;	
  GPIO_Init(GPIOB, &GPIO_InitStructure);   
  
	// 配置TIM3
  TIM_TimeBaseStructure.TIM_Period = 899;
  TIM_TimeBaseStructure.TIM_Prescaler = 0;
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
  TIM_TimeBaseStructure.TIM_ClockDivision = 0;
  TIM_TimeBaseInit(TIM3 , &TIM_TimeBaseStructure);
  
  // 配置PWM通道1
  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
  TIM_OCInitStructure.TIM_Pulse = 900;
  TIM_OC1Init(TIM3 , &TIM_OCInitStructure);
  TIM_OC1PreloadConfig(TIM3 , TIM_OCPreload_Enable);
  
  // 配置PWM通道2
  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
  TIM_OCInitStructure.TIM_Pulse = 900;
  TIM_OC2Init(TIM3 , &TIM_OCInitStructure);
  TIM_OC2PreloadConfig(TIM3 , TIM_OCPreload_Enable);
  
  // 配置PWM通道3
  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
  TIM_OCInitStructure.TIM_Pulse = 900;
  TIM_OC3Init(TIM3 , &TIM_OCInitStructure);
  TIM_OC3PreloadConfig(TIM3 , TIM_OCPreload_Enable);
  
  // 配置PWM通道3
  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
  TIM_OCInitStructure.TIM_Pulse = 900;
  TIM_OC4Init(TIM3 , &TIM_OCInitStructure);
  TIM_OC4PreloadConfig(TIM3 , TIM_OCPreload_Enable);
  
	// 使能TIM3
  TIM_Cmd(TIM3 , ENABLE);
}

4.3 智能车行驶控制

这里简单阐述一下麦克纳姆轮的全向移动原理。

麦克纳姆轮受力分析

图中实线为车轮转动产生的摩擦力,虚线是分力,合成后可知左侧智能车向前移动,右侧智能车向右移动。其他的移动操作,如自转、平移等原理与之相同,就不再赘述。下面列一下不同行驶状态下,各个电机的旋转状态

运动状态与电机转向对应表

下面是控制程序

// 差值决定快慢,差值越大越快
// 1、2差值代表左后轮和右前轮的速度;3、4差值代表左前轮和右后轮的速度
// 1-2为正代表正转,为负代表反转,差值代表速度
/*
 *==============================================================================
 *函数名称:Med_Motor_CarGo
 *函数功能:智能车前进
 *输入参数:无
 *返回值:无
 *备  注:无
 *==============================================================================
 */
void Med_Motor_CarGo (void)
{
	TIM_SetCompare1(TIM2 , 899); 
  TIM_SetCompare2(TIM2 , 300);
  TIM_SetCompare3(TIM2 , 899);  
  TIM_SetCompare4(TIM2 , 300);
	
  TIM_SetCompare1(TIM3 , 899); 
  TIM_SetCompare2(TIM3 , 300);
  TIM_SetCompare3(TIM3 , 899);  
  TIM_SetCompare4(TIM3 , 300);	
}
/*
 *==============================================================================
 *函数名称:Med_Motor_CarStop
 *函数功能:智能车停止
 *输入参数:无
 *返回值:无
 *备  注:无
 *==============================================================================
 */
void Med_Motor_CarStop (void)
{
	TIM_SetCompare1(TIM2 , 0); 
  TIM_SetCompare2(TIM2 , 0);
  TIM_SetCompare3(TIM2 , 0);  
  TIM_SetCompare4(TIM2 , 0);
	
  TIM_SetCompare1(TIM3 , 0);
  TIM_SetCompare2(TIM3 , 0);
  TIM_SetCompare3(TIM3 , 0);	
  TIM_SetCompare4(TIM3 , 0);
}
/*
 *==============================================================================
 *函数名称:Med_Motor_CarBack
 *函数功能:智能车后退
 *输入参数:无
 *返回值:无
 *备  注:无
 *==============================================================================
 */
void Med_Motor_CarBack (void)
{
	TIM_SetCompare1(TIM2 , 300);
  TIM_SetCompare2(TIM2 , 899);
  TIM_SetCompare3(TIM2 , 300);	
  TIM_SetCompare4(TIM2 , 899);
	
  TIM_SetCompare1(TIM3 , 300);
  TIM_SetCompare2(TIM3 , 899);
  TIM_SetCompare3(TIM3 , 300);	
  TIM_SetCompare4(TIM3 , 899);
}
/*
 *==============================================================================
 *函数名称:Med_Motor_CarLe
 *函数功能:智能车向左平移
 *输入参数:无
 *返回值:无
 *备  注:无
 *==============================================================================
 */
void Med_Motor_CarLeft (void)
{
	TIM_SetCompare1(TIM2 , 899);
  TIM_SetCompare2(TIM2 , 300);
  TIM_SetCompare3(TIM2 , 899);	
  TIM_SetCompare4(TIM2 , 300);
	
  TIM_SetCompare1(TIM3 , 300);
  TIM_SetCompare2(TIM3 , 899);
  TIM_SetCompare3(TIM3 , 300);
  TIM_SetCompare4(TIM3 , 899);
}
/*
 *==============================================================================
 *函数名称:Med_Motor_CarRight
 *函数功能:智能车向右平移
 *输入参数:无
 *返回值:无
 *备  注:无
 *==============================================================================
 */
void Med_Motor_CarRight (void)
{
	TIM_SetCompare1(TIM2 , 300);
  TIM_SetCompare2(TIM2 , 899);
  TIM_SetCompare3(TIM2 , 300);	
  TIM_SetCompare4(TIM2 , 899);
	
  TIM_SetCompare1(TIM3 , 899);
  TIM_SetCompare2(TIM3 , 300);
  TIM_SetCompare3(TIM3 , 899);
  TIM_SetCompare4(TIM3 , 300);
}
/*
 *==============================================================================
 *函数名称:Med_Motor_ClockwiseRotate
 *函数功能:智能车顺时针自转
 *输入参数:无
 *返回值:无
 *备  注:无
 *==============================================================================
 */
void Med_Motor_ClockwiseRotate (void)
{
	TIM_SetCompare1(TIM2 , 300);
  TIM_SetCompare2(TIM2 , 899);
  TIM_SetCompare3(TIM2 , 899);	
  TIM_SetCompare4(TIM2 , 300);
	
  TIM_SetCompare1(TIM3 , 300);
  TIM_SetCompare2(TIM3 , 899);
  TIM_SetCompare3(TIM3 , 899);
  TIM_SetCompare4(TIM3 , 300);
}
/*
 *==============================================================================
 *函数名称:Med_Motor_CounterClockwiseRotate
 *函数功能:智能车逆时针自转
 *输入参数:无
 *返回值:无
 *备  注:无
 *==============================================================================
 */
void Med_Motor_CounterClockwiseRotate (void)
{
	TIM_SetCompare1(TIM2 , 899);
  TIM_SetCompare2(TIM2 , 300);
  TIM_SetCompare3(TIM2 , 300);	
  TIM_SetCompare4(TIM2 , 899);
	
  TIM_SetCompare1(TIM3 , 899);
  TIM_SetCompare2(TIM3 , 300);
  TIM_SetCompare3(TIM3 , 300);
  TIM_SetCompare4(TIM3 , 899);
}

五、拓展应用

知道了L298N的控制和调速方法,我们就能做许多事情。比如利用蓝牙来调整智能车行驶速度。实际原理就是通过蓝牙给配置占空比的函数传入数值,改变占空比,从而达到遥控调节车速的目的。这个在后续的实战项目系列中会有相关介绍。

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

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

相关文章

java并发编程 3:synchronized与锁(重点)

目录 共享问题synchronized锁及使用synchronized代码块synchronized 修饰成员方法synchronized 修饰静态方法 变量的线程安全分析成员变量和静态变量是否线程安全局部变量是否线程安全常见线程安全类 synchronized底层原理Java对象头Monitor管程字节码看原理 锁状态及转换四种锁…

vscode 快速修复(quick fix) 快捷键(Ctrl + .)被占用问题解决方法

vscode 快速修复(quick fix) 快捷键(Ctrl .)被占用 微软拼音的中/英文标点切换的快捷键为Ctrl .,与 vscode 快速修复(quick fix)快捷键冲突。修复方法如下: 切换到微软拼音,在输入法中或英字上,点击右键。 再点设置 - 按键。 …

MTK平台WLAN的Roaming机制和案例log解析

一 、WLAN漫游简介 [百度百科]:当网络环境存在多个相同SSID的AP,且它们的微单元互相有一定范围的重合时,无线用户可以在整个WLAN覆盖区内移动,无线网卡能够自动发现附近信号强度最大的AP,并通过这个AP收发数据,保持不间断的网络连接,这就称为无线漫游。 简单来说:WLA…

Flink中时间和窗口

文章目录 一、时间定义二、水位线(Watermark)1、概念2、水位线特征3、生成水位线3.1 水位线生成策略(Watermark Strategies)3.2 Flink 内置水位线生成器3.3 自定义水位线策略 4、水位线的传递 三、窗口(Window)1、概念2、窗口分类2.1 驱动类型分类2.2 窗…

chatgpt赋能python:Python输入之后的运行过程

Python输入之后的运行过程 在Python中,输入是必不可少的一部分,它使我们能够更加交互和动态地使用这门语言。在本篇文章中,我们将介绍Python输入的运行过程,包括如何读取和处理输入以及输入与程序运行的交互方式。 什么是Python…

ZLMediaKit 的安装及使用介绍

ZLMediaKit 介绍 ZLMediaKit是一个基于C开发的开源流媒体服务器。它提供了高性能的音视频处理能力,支持常见的流媒体协议,如RTSP、RTMP、HLS和HTTP-FLV,并且具有低延迟和高并发处理能力。 开源地址:https://github.com/xia-chu/…

抖音seo账号矩阵系统源码代开发组件

一.开发矩阵系统的项目背景: 目录 一.开发矩阵系统的项目背景: 二.短视频矩阵系统SaaS模板组件通常包含以下几个方面的内容: 三.抖音SEO账号矩阵系统源码的技术搭建过程可以分为几个步骤: 1.确定系统的需求和目标&#xff0c…

DFS深度优先搜索

目录 一、DFS的概念DFS的定义DFS的搜索方式DFS采用的数据结构DFS的特点 二、DFS的实战应用1.排列数字2.n-皇后问题 一、DFS的概念 DFS的定义 DFS(Depth-First Search)深度优先搜索,是一种常用的图遍历算法,用于在图或树数据结构…

金蝶云星空财务软件被locked勒索病毒攻击后如何更快解密数据库数据?

金蝶云星空财务软件是一款广泛应用于企业财务管理领域的软件,然而,近期很多企业的金蝶云星空财务软件遭受到了locked勒索病毒的攻击,导致数据库数据被加密。而这次的locked勒索病毒采用了新的加密形式,它不仅能够扫描出各种软件系…

数据结构--顺序表VS链表

数据结构–顺序表VS链表 逻辑结构 存储结构 顺序表: 优点:支持随机存取、存储密度高 缺点:大片连续空间分配不方便,改变容量不方便 链表: 优点:离散的小空间分配方便,改变容量方便 缺点:不可随机存取,存储密度低 基本…

从零开始 Spring Boot 49:Hibernate Entity Lifecycle

从零开始 Spring Boot 49:Hibernate Entity Lifecycle 图源:简书 (jianshu.com) 本文将介绍 Hibernate 的 Session 接口,以及如何用 Session 的相关 API 转换实体(Entity)的生命周期状态。 如果缺少的 JPA 和 Hiberna…

ubuntu18.04 ros报错Command ‘roscore‘ not found

问题描述 git clone https://github.com/ros/catkin.gitcd catkingit branch melodic-develgit checkout melodic-develmkdir buildcd buildcmake …make -j8 && sudo make installcd .. sudo python2 setup.py installsudo python3 setup.py install出现问题 hua…

ADB命令(app自动化测试底层技术)

一、adb相关知识体系 1,adb的使用场景 操作手机设备 app自动化测试2,adb测试体系 app自动化测试-appium 遍历测试-appcrawier app性能测试 app专项测试 STF设备管理平台 云测平台 兼容性测试 二、adb 基础 1,什么是adb Adb是用来操作Andro…

spark、pyspark 常用的模版 demo 网址

1、我自己有时候用百度或者其他的搜索出来的spark 常用案例,质量有的好有的差有时候就很烦。特地分享一个我常用的质量高的网站地址 https://sparkbyexamples.com/pyspark/pyspark-collect/

进阶2:JVM 启动参数

目录 jvm启动参数 参数分类 系统属性 功能解析 运行模式 jvm有两种运行模式 堆内存 设置堆内存 GC相关 GC 日志相关的参数 分析诊断 指定垃圾收集器相关参数 JavaAgent 什么是Java agent 常见问题 视频 前言 这堂课程不用过多的记忆,自身有印象即可…

Vue中Object.defineProperty

放到Object.defineProperty中比直接写在person对象中更灵活&#xff0c;可以设置的属性更多 <script>let person{name:张三,age:男}Object.defineProperty(person,age,{value:18,enumerable:true, //控制属性是否可以被枚举&#xff0c;默认值是falsewritable:true, //控…

无人机动力测试台-15公斤级-Flight Stand 15

Flight Stand 15测试台通过测量电机和螺旋桨的拉力、扭矩、转速、电流、电压、温度、螺旋桨效率和电机效率来精准地描述和评估无人机动力系统的性能。 产品应用 Flight Stand 15测试台可以用于以下方向&#xff1a; 实时动态测试 FS15 Pro的1000 Hz采样率使测试成为可能&…

Chrome 插件开发覆写xhr请求

这几天搞chrome谷歌浏览器插件遇到个问题 我想拦截网页请求&#xff0c;并把数据传递到下一个子窗口。获取responsebody内容 background.js 单纯靠sendmessage实现不了通讯 chrome.runtime.sendMessage({data: e.data.responseText,type:ajaxResponse}); 最开始的时候想用chr…

基于matlab使用自动要素匹配查找图像旋转和缩放(附源码)

一、前言 此示例演示如何自动确定一对图像之间的几何变换。当一个图像因旋转和缩放而相对于另一个图像失真时&#xff0c;请使用 和 查找旋转角度和比例因子。然后&#xff0c;您可以转换扭曲的图像以恢复原始图像。 二、步骤 1&#xff1a;读取图像 将映像引入工作区。 三、…

Bean的基础配置

问题1&#xff1a;在<bean>标签上如何配置别名&#xff1f; 问题2&#xff1a;Bean的默认作用范围是什么&#xff1f;如何修改&#xff1f; 1. Bean基础配置【重点】 类型描述名称bean类型标签所属beans标签功能定义Spring核心容器管理的对象格式 <beans> …