STM32单片机智能小车一PWM方式实现小车调速和转向

目录

1. 电机模块开发

2. 让小车动起来

3. 串口控制小车方向

4. 如何进行小车PWM调速

5. PWM方式实现小车转向


1. 电机模块开发

L9110s概述

接通VCC,GND 模块电源指示灯亮, 以下资料来源官方,具体根据实际调试

IA1输入高电平,IA1输入低电平,【OA1 OB1】电机正转;

IA1输入低电平,IA1输入高电平,【OA1 OB1】电机反转;

IA2输入高电平,IA2输入低电平,【OA2 OB2】电机正转;

IA2输入低电平,IA2输入高电平,【OA2 OB2】电机反转;

接线参考:

B-1A -- PA0

B-1B -- PB1

A-1A -- PA1

A-1B -- PB10 

2. 让小车动起来

代码实现:

motor.c

#include "motor.h"
void goForward(void)
{// 左轮HAL_GPIO_WritePin(GPIOB, GPIO_PIN_2, GPIO_PIN_SET);HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_RESET);// 右轮HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_SET);HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_RESET);
}
void goBack(void)
{// 左轮HAL_GPIO_WritePin(GPIOB, GPIO_PIN_2, GPIO_PIN_RESET);HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_SET);// 右轮HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_RESET);HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_SET);
}
void goLeft(void)
{// 左轮HAL_GPIO_WritePin(GPIOB, GPIO_PIN_2, GPIO_PIN_RESET);HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_RESET);// 右轮HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_SET);HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_RESET);
}
void goRight(void)
{// 左轮HAL_GPIO_WritePin(GPIOB, GPIO_PIN_2, GPIO_PIN_SET);HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_RESET);// 右轮HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_RESET);HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_RESET);
}
void stop(void)
{// 左轮HAL_GPIO_WritePin(GPIOB, GPIO_PIN_2, GPIO_PIN_SET);HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_SET);// 右轮HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_RESET);HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_RESET);
}

motor.h

#ifndef __MOTOR_H__
#define __MOTOR_H__
#include "main.h"
void goForward(void);
void goBack(void);
void goLeft(void);
void goRight(void);
void stop(void);
#endif

main.c

#include "motor.h"//main函数的while循环部分:
while (1)
{goForward();HAL_Delay(1000);goBack();HAL_Delay(1000);goLeft();HAL_Delay(1000);goRight();HAL_Delay(1000);stop();HAL_Delay(1000);
}

3. 串口控制小车方向

  • 串口分文件编程进行代码整合——通过现象来改代码
  • 接入蓝牙模块,通过蓝牙控制小车
  • 添加点动控制,如果APP支持按下一直发数据,松开就停止发数据(蓝牙调试助手的自定义按键不 能实现),就能实现前进按键按下后小车一直往前走的功能

代码实现:

usart.c

#include "usart.h"#include "string.h"
#include "stdio.h"
#include "motor.h"//串口接收缓存(1字节)
uint8_t buf=0;//定义最大接收字节数 200,可根据需求调整
#define UART1_REC_LEN 200// 接收缓冲, 串口接收到的数据放在这个数组里,最大UART1_REC_LEN个字节
uint8_t UART1_RX_Buffer[UART1_REC_LEN];//  接收状态
//  bit15,      接收完成标志
//  bit14,      接收到0x0d
//  bit13~0,    接收到的有效字节数目
uint16_t UART1_RX_STA=0;#define SIZE 12char buffer[SIZE];// 接收完成回调函数,收到一个数据后,在这里处理
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{// 判断中断是由哪个串口触发的if(huart->Instance == USART1){// 判断接收是否完成(UART1_RX_STA bit15 位是否为1)if((UART1_RX_STA & 0x8000) == 0){// 如果已经收到了 0x0d (回车),if(UART1_RX_STA & 0x4000){// 则接着判断是否收到 0x0a (换行)if(buf == 0x0a){// 如果 0x0a 和 0x0d 都收到,则将 bit15 位置为1UART1_RX_STA |= 0x8000;// 灯控指令if(!strcmp(UART1_RX_Buffer, "M1"))goForward();else if(!strcmp(UART1_RX_Buffer, "M2"))goBack();else if(!strcmp(UART1_RX_Buffer, "M3"))goLeft();else if(!strcmp(UART1_RX_Buffer, "M4"))goRight();elsestop();memset(UART1_RX_Buffer, 0, UART1_REC_LEN);UART1_RX_STA = 0;}else// 否则认为接收错误,重新开始UART1_RX_STA = 0;}else	// 如果没有收到了 0x0d (回车){//则先判断收到的这个字符是否是 0x0d (回车)if(buf == 0x0d){// 是的话则将 bit14 位置为1UART1_RX_STA |= 0x4000;}else{// 否则将接收到的数据保存在缓存数组里UART1_RX_Buffer[UART1_RX_STA & 0X3FFF] = buf;UART1_RX_STA++;// 如果接收数据大于UART1_REC_LEN(200字节),则重新开始接收if(UART1_RX_STA > UART1_REC_LEN - 1)UART1_RX_STA = 0;}}}// 重新开启中断HAL_UART_Receive_IT(&huart1, &buf, 1);}
}int fputc(int ch, FILE *f)
{      unsigned char temp[1]={ch};HAL_UART_Transmit(&huart1,temp,1,0xffff);  return ch;
}

4. 如何进行小车PWM调速

原理

全速前进是LeftCon1A = 0; LeftCon1B = 1;

完全停止是LeftCon1A = 0;LeftCon1B = 0;

那么单位时间内,比如20ms, 有15ms是全速前进,5ms是完全停止, 速度就会比5ms全速前进,15ms完全停止获得的功率多,相应的速度更快!

开发:借用PWM的舵机控制代码

将控制车轮的4个 GPIO 口配置修改如下,否则小车动不起来。

原因:L9110每个控制口需要一高一低才可以动起来,如果PWM有效电平为高电平,则另一个 GPIO口则需要输出低电平才可以驱动轮子。

代码实现:

main.c

// main函数里
HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_1);
HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_2);
while (1)
{__HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_1, 8);__HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_2, 8);HAL_Delay(1000);__HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_1, 10);__HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_2, 10);HAL_Delay(1000);__HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_1, 15);__HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_2, 15);HAL_Delay(1000);
}

5. PWM方式实现小车转向

右转原理:

左轮速度大于右轮

左转原理:

右轮速度大于左轮

左右轮各自调速代码实现:

// main函数里
while (1)
{__HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_1,8);__HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_2,15);HAL_Delay(1000);__HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_1,15);__HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_2,8);HAL_Delay(1000);
}

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

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

相关文章

视频分辨率/帧率/码率选择参考

1. 视频码率与分辨率的参考表 1080*720的分辨率,用5000K左右; 720*576的分辨率,用3500K左右; 640*480的分辨率,用1500K左右。 2. 计算公式 基本算法:码率(kb…

3.1每日一题(定积分求压力问题)

公式: (1) 压力等于压强乘以面积 (2) 压强等于ρgh(即密度,重力加速度,水的深度) 注:题目表面不一样,实际的原理都一样,做透一道题等于做懂一类题

论文阅读——InstructGPT

论文:Training_language_models_to_follow_instructions_with_human_feedback.pdf (openai.com) github:GitHub - openai/following-instructions-human-feedback 将语言模型做得更大并不能从本质上使它们更好地遵循用户的意图。例如,大型语…

光学仿真|优化汽车内部照明体验

当我们谈论优化人类感知的内部照明时,我们实际上指的是两个重点领域:安全性和驾驶员体验。如果内部照明可以提供尽可能最佳的体验,驾驶员则能够更好地应对颇具挑战性或意外的驾驶状况,并且减轻疲劳感。除了功能优势外,…

Vue 3 响应式对象:ref 和 reactive 的使用和区别

🎉🎉欢迎来到我的CSDN主页!🎉🎉 🏅我是尘缘,一个在CSDN分享笔记的博主。📚📚 👉点击这里,就可以查看我的主页啦!👇&#x…

【深度学习】吴恩达课程笔记(二)——浅层神经网络、深层神经网络

笔记为自我总结整理的学习笔记,若有错误欢迎指出哟~ 笔记链接 【深度学习】吴恩达课程笔记(一)——深度学习概论、神经网络基础 吴恩达课程笔记——浅层神经网络、深层神经网络 四、浅层神经网络1.双层神经网络表示2.双层神经网络的前向传播第一层前向传播第二层前…

Java进阶(Set)——面试时Set常见问题解读 结合源码分析

前言 List、Set、HashMap作为Java中常用的集合,需要深入认识其原理和特性。 本篇博客介绍常见的关于Java中Set集合的面试问题,结合源码分析题目背后的知识点。 关于List的博客文章如下: Java进阶(List)——面试时L…

mac电脑怎么永久性彻底删除文件?

Mac老用户都知道在我们查看Mac内存时都会发现有一条“其他文件”占比非常高,它是Mac储存空间中的“其他”数据包含不可移除的移动资源,如,Siri 语音、字体、词典、钥匙串和 CloudKit 数据库、系统无法删除缓存的文件等。这些“其他文件”无用…

frp-内网穿透部署-ubuntu22服务器-windows server-详细教程

文章目录 1.下载frp2.配置服务器2.1.配置frps.ini文件2.2.设置服务文件2.3.设置开机自启和服务操作2.4.后台验证2.5.服务器重启 3.配置本地window3.1.frpc配置3.2.添加开机计划启动3.3.控制台启动隐藏窗口 4.centos防火墙和端口3.1.开放端口3.2.查看端口 5.关闭进程5.1.杀死进程…

Elasticsearch:标量量化 101 - scalar quantization 101

作者:BENJAMIN TRENT 什么是标量量化以及它是如何工作的? 大多数嵌入模型输出 float32 向量值。 虽然这提供了最高的保真度,但考虑到向量中实际重要的信息,这是浪费的。 在给定的数据集中,嵌入永远不需要每个单独维度…

一体化模型图像去雨+图像去噪+图像去模糊(图像处理-图像复原-代码+部署运行教程)

本文主要讲述了一体化模型进行去噪、去雨、去模糊,也就是说,一个模型就可以完成上述三个任务。实现了良好的图像复原功能! 先来看一下美女复原.jpg 具体的: 在图像恢复任务中,需要在恢复图像的过程中保持空间细节…

vue使用百度富文本

🔥博客主页: 破浪前进 🔖系列专栏: Vue、React、PHP ❤️感谢大家点赞👍收藏⭐评论✍️ 1、下载UEditor 链接已放到文章中了 2、上传到项目目录中 一般上传到public下,方便到时候打包进去,以免…

Ubuntu学习---跟着绍发学linux课程记录(第4部分)

第3部份内容记录在:Ubuntu学习—跟着绍发学linux课程记录(第3部分) 文章目录 14 ubuntu服务器上的java14.1 Java的安装14.2 运行java程序14.3 Java启动脚本 15 ubuntu服务器上的tomcat15.1 Tomcat服务器15.2 Tomcat的配置15.3 Tomcat启动日志…

加速度中标云尖信息「电子元器件商城」开发项目——加速度jsudo

深圳市加速度软件开发有限公司在电子元器件和工业品行业有着多年得商城开发经验,服务过半导体、元器件、工业品行业的多家上市公司或实力工厂。选择加速度合作的60%的客户,或多或少都有踩坑的经历,这一次他们在选择商城开发商的时候格外谨慎&…

Spring@Lazy是如何解决构造函数循环依赖问题

Spring实例化源码解析之循环依赖CircularReference这章的最后我们提了一个构造函数形成的循环依赖问题,本章就是讲解利用Lazy注解如何解决构造函数循环依赖和其原理。 准备工作 首先创建两个构造函数循环依赖的类,TestA和TestB,代码如下&am…

qt-C++笔记之在两个标签页中按行读取两个不同的文件并且滚动条自适应滚动范围高度

qt-C笔记之在两个标签页中按行读取两个不同的文件并且滚动条自适应滚动范围高度 code review! 文章目录 qt-C笔记之在两个标签页中按行读取两个不同的文件并且滚动条自适应滚动范围高度1.运行2.文件结构3.main.cc4.main.pro5.a.txt6.b.txt7.上述代码中QVBoxLayout&#xff0c…

世界前沿技术发展报告2023《世界航空技术发展报告》(四)无人机技术

(四)无人机技术 1.无人作战飞机1.1 美国空军披露可与下一代战斗机编组作战的协同式无人作战飞机项目1.2 俄罗斯无人作战飞机取得重要进展 2.支援保障无人机2.1 欧洲无人机项目通过首个里程碑2.2 美国海军继续开展MQ-25无人加油机测试工作 3.微小型无人机…

TextureView和SurfaceView

1、Surface Surface对应了一块屏幕的缓冲区,每一个window对应一个Surface,任何View都是画在Surface上的,传统的View共享一块屏幕缓冲区,所有的绘制都必须在UI线程上进行。 2、SurfaceView 顾名思义就是Surface的View,…

NSS刷题 js前端修改 os.path.join漏洞

打算刷一遍nssweb题(任重道远) 前面很简单 都是签到题 这里主要记录一下没想到的题目 [GDOUCTF 2023]hate eat snake 这里 是对js的处理 有弹窗 说明可能存在 alert 我们去看看js 这里进行了判断 如果 getScore>-0x1e9* 我们结合上面 我觉得是6…

RabbitMQ基础

目录 RabbitMQ的可靠性投递 确保消息正确地发送至 RabbitMQ 确保消息接收方消费了消息 流程分析 1.生产者发送消息给Broker 2.交换机路由消息到队列 3.消息存储在队列 4.消费者订阅并消费消息 三个重要概念 RabbitMQ集群模式 RabbitMQ的可靠性投递 在 RabbitMQ 中&a…