快速学习Stm32舵机控制板控制多个舵机运动以及调速

2023-11-18

本次分享stm32对多个舵机的控制,之前讲解过单个舵机的控制。以及控制原理,定时器的使用和pwm的输出来控制一个舵机的角度转向。这次就和大家分享一下多个舵机的控制以及调速。利用单片机实现对 8 个舵机的同时控制,掌握多个舵机控制程序实现方法。从单个舵机控制到多个舵机控制,理解定时器的分时复用。为扩展控制 16 路,24 路舵机打下坚实的基础。

多个舵机控制如下图所示
16路舵机控制板子(维特智能)
在这里插入图片描述
多个舵机控制方案

利用单个定时器中断法。该方案的实现方法是将舵机 20ms 的周期分解成若干份(由于舵机控制信号的最大高电平时间为 2.5 毫秒,故一般分成 8 份以上), 每一份时间完成一个舵机的控制。以将 20ms 平均分解成 8 份为例进行说明:单片机上电初始化时,先将所有的 IO 端口电平拉低;当定时器产生第一次溢出中断时,在中断服务程序中对定时器计数寄存器重新赋值,所赋值为第一个受控舵机控制信号的高电平时间值,并将 IO 口拉高;当定时器产生第二次中断时,继续给寄存器重新赋值,此次所赋值为 2.5ms 减去高电平所得时间值;剩下的17.5ms 时间内重复七次上述操作,这样即可同时完成 8 个舵机的控制。

每20mm的周期,把每个周期分为8分,每份2.5mm 控制一个舵机,总共控制8个舵机

参考demo 本次使用stm32f103 c8t6

主函数

 int main(void)
{   
	SysTick_Init();		//系统滴答定时器初始化 		
	Servor_GPIO_Config();
	Timer_Init();
	Timer_ON();
	while (1)
	{	
		for(i=0;i<8;i++)           //每个舵机到0度
		{
			CPWM[i]=500; //给PWM舵机一个0.5ms的高电平脉冲,传入到定时器2 
		}
	
		Delay_ms(1000); 
		for(i=0;i<8;i++)           //每个舵机到180度
		{
			CPWM[i]=2500;//给PWM舵机一个2.5ms的高电平脉冲,传入到定时器2 
		} 
		Delay_ms(1000); 
	}
} 

初始化i/o口

void Servor_GPIO_Config(void)	
{
	GPIO_InitTypeDef GPIO_InitStructure;	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO|RCC_APB2Periph_GPIOA, ENABLE);
	GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable , ENABLE);
	GPIO_PinRemapConfig(GPIO_Remap_SWJ_Disable , ENABLE);
	GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_8|GPIO_Pin_15;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO|RCC_APB2Periph_GPIOB,ENABLE);
	GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_15;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	
}

GPIO电平反转函数

//整个周期20ms,把每个周期分为8分,每份2.5mm 控制一个舵机,总共控制8个舵机,2.5mm 分为两个动作去做,每两个动作控制一个舵机一共16个动作,就是分时复用法,把时间分成几份去做单独的控制。
void Flip_GPIO_One(void)
{
	switch(count1)								 //将20ms的舵机控制周期分成8份,每2.5ms控制一个舵机运转
	{  											      //每个定时器控制8路舵机运转,3个定时器控制24路舵机运转
		case 1: 
			 TIM2->ARR=CPWM[1];		//0.5ms		 //将第一个舵机脉冲宽度值赋值给定时器2			
    	 GPIO_SetBits(GPIOB,GPIO_Pin_15);  //同时拉高控制舵机1的引脚的电
				break;
		
		case 2:
   	    TIM2->ARR=MAXPWM-CPWM[1]; 	//2ms	 //将2.5ms减去PWM脉宽值的数据赋值定时器2
				GPIO_ResetBits(GPIOB,GPIO_Pin_15);//同时拉低控制舵机1引脚的电平 
				break;							 //控制舵机1的引脚在剩下20ms-CPM[0]时间内将一直保持低电平,舵机1按照CPWM值转动

		case 3:	
			TIM2->ARR=CPWM[2]; 
				GPIO_SetBits(GPIOA,GPIO_Pin_8);
				break;
		
		case 4:	
			TIM2->ARR=MAXPWM-CPWM[2];  
				GPIO_ResetBits(GPIOA,GPIO_Pin_8); 
				break;

		case 5:	
			TIM2->ARR=CPWM[3];  
				GPIO_SetBits(GPIOB,GPIO_Pin_5); 
				break;
		
		case 6:	
			TIM2->ARR=MAXPWM-CPWM[3];  
				GPIO_ResetBits(GPIOB,GPIO_Pin_5);	
				break;

		case 7:	
			 TIM2->ARR=CPWM[4];  
			  GPIO_SetBits(GPIOB,GPIO_Pin_4); 
				break;
		
		case 8:	
			 TIM2->ARR=MAXPWM-CPWM[4];  
				GPIO_ResetBits(GPIOB,GPIO_Pin_4);
				break;

		case 9:	
			TIM2->ARR=CPWM[5];  
				GPIO_SetBits(GPIOB,GPIO_Pin_3); 
				break;
		
		case 10:
			TIM2->ARR=MAXPWM-CPWM[5];  
				GPIO_ResetBits(GPIOB,GPIO_Pin_3);
				break;

		case 11:
			TIM2->ARR=CPWM[6];  
				GPIO_SetBits(GPIOA,GPIO_Pin_15); 
				break;
		
		case 12:
			TIM2->ARR=MAXPWM-CPWM[6];  
				GPIO_ResetBits(GPIOA,GPIO_Pin_15);
				break;

		case 13:
			TIM2->ARR=CPWM[7];  

				break;
		
		case 14:
			  TIM2->ARR=MAXPWM-CPWM[7];  

				break;

		case 15:
			TIM2->ARR=CPWM[8];  

				break;
		
		case 16:
			TIM2->ARR=MAXPWM-CPWM[8]; 
	
				count1=0; 
				break;
		default:break;
	}	
	//count1++;
}

舵机控制函数1

void Servo1(void)           //time2 中断里面去调用
{		
	count1++; 
	Flip_GPIO_One();						 //反转IO电平

}

控制舵机速度方案

脉冲细分法。改方案的具体实现操作位:将预期 PWM 值分解成若干 PWM 值,每个 PWM 值对应舵机一个角度,即让舵机从起始位置转动若干次后到达预期位置。由于舵机控制信号的周期为 20ms,忽略舵机的实际转动时间,每产生一次预期 PWM 值,舵机将转动 N 次,将需要 20*Nms 的时间,如此可达到调速的目的。

控制舵机从500-2500之间运行
每次脉宽控制到(2500-500)/n次=脉宽值
通过调整脉宽值进行平滑运行。

/***************************************************************************************************************
函 数 名:作业初位置,末尾置更新函数  
功能描述:从缓存中取一个新的目标位置替换原来的目标位置,原来的目标位置变为新的初位置,一次更替
		:有效的数据是插补增量,和插补次数,知道这两个量,和当前初位置即可
备    注: 先进先出,循环访问	
****************************************************************************************************************/	
 void change(void)
{	
	unsigned char s;
	if(point_aim==1)
		{
		   point_aim=0;
			 point_now=1;
    }
		else
		{
			 point_aim=1;
			 point_now=0;
		}
		n=pos[point_aim][0]/20;	//计算新的插补次数	

		for(s=1;s<9;s++)	//计算新的插补增量
		{
		 if(pos[point_aim][s]>pos[point_now][s])
			{
	   			dp=pos[point_aim][s]-pos[point_now][s];
			   	dp0[s]=dp/n;
			}
		    if(pos[point_aim][s]<=pos[point_now][s])
			{
				dp=pos[point_now][s]-pos[point_aim][s];
				dp0[s]=dp/n;
				dp0[s]=-dp0[s];
			}
			
	   }
		m=0;				  	//m清0

}
/***************************************************************************************************************
函 数 名:vpwm()  
功能描述:数据插补,插补时间间隔为20/12ms,由timer0控制,使舵机平滑实现速度控制
		:另一个功能是执行完一行后去更新下一行数据,即调用change()
备    注:
****************************************************************************************************************/	
void vpwm(void)		 
{
	unsigned char j=0;
	static unsigned char flag_Tover;
		m++;							//用来累加插补过的次数
		if(m==n)						//n是本行作业要插补的总次数
		{
		  flag_Tover=1;				//一行数据的执行时间已经完成
		}
		for(j=1;j<9;j++)
		{
			if(abs(CPWM[j]-pos[point_aim][j])<5)
			{						   	//检测靠近终点位置
			 //  how++;				   	//是,则累加一个
			   CPWM[j]=pos[point_aim][j];//并且直接过度到终点位置
			}	
			else						//不靠近终点,继续插补
			{
				CPWM[j]=pos[point_now][j]+m*dp0[j];
			}
		} 
			   												
		if(flag_Tover==1)
		{								//从插补次数,和脉宽宽度两方面都到达终点,本作业行完成
			 flag_Tover=0;
			 change();
		}
		
	//return;

}

总结
分时复用法
脉冲细分法

对于stm32针对单个舵机控制的原理上一次已经分享大家可以看一下上一期

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

快速学习Stm32舵机控制板控制多个舵机运动以及调速 的相关文章

  • RT-Thread 内核基础(五)

    使用static修饰全局变量作用 限制作用域 如果全局变量前面加上 static 关键字 那么该变量的作用域将被限制在声明它的源文件中 即它将成为一个文件作用域的静态变量 其它源文件无法访问这个变量 这对于控制变量的可见性和避免命名冲突是有
  • 毕设开题分享 单片机智能教室系统(智能照明+人数统计)

    1 简介 Hi 大家好 今天向大家介绍一个学长做的单片机项目 单片机智能教室系统 智能照明 人数统计 大家可用于 课程设计 或 毕业设计 项目分享 https gitee com feifei1122 simulation project
  • 我当年自学黑客(网络安全)的一些心得!(内附学习笔记)

    前 言 写这篇教程的初衷是很多朋友都想了解如何入门 转行网络安全 实现自己的 黑客梦 文章的宗旨是 1 指出一些自学的误区 2 提供客观可行的学习表 3 推荐我认为适合小白学习的资源 大佬绕道哈 文末有福利 一 自学网络安全学习的误区和陷阱
  • The Planets:Venus

    靶场下载 The Planets Venus VulnHub 信息收集 arp scan l Interface eth0 type EN10MB MAC 00 0c 29 43 7c b1 IPv4 192 168 1 60 Starti
  • STM32F4XX的12位ADC采集数值超过4096&右对齐模式设置失败

    文章目录 一 前言 二 问题1 数值超过4096 三 问题1的排错过程 四 问题2 右对齐模式设置失败 五 问题2的解决方法 5 1 将ADC ExternalTrigConv设置为0 5 2 使用ADC StructInit 函数 一 前
  • 【CTF必看】从零开始的CTF学习路线(超详细),让你从小白进阶成大神!

    最近很多朋友在后台私信我 问应该怎么入门CTF 个人认为入门CTF之前大家应该先了解到底 什么是CTF 而你 学CTF的目的又到底是什么 其次便是最好具备相应的编程能力 若是完全不具备这些能力极有可能直接被劝退 毕竟比赛的时候动不动写个脚本
  • 【计算机毕业设计】精品课程在线学习系统

    如今社会上各行各业 都喜欢用自己行业的专属软件工作 互联网发展到这个时候 人们已经发现离不开了互联网 新技术的产生 往往能解决一些老技术的弊端问题 因为传统精品课程学习信息管理难度大 容错率低 管理人员处理数据费工费时 所以专门为解决这个难
  • 2024年网络安全十10大发展趋势发布

    2023年网络安全十10大发展趋势发布 近日 中国计算机学会 CCF 计算机安全专委会中 来自国家网络安全主管部门 高校 科研院所 大型央企 民营企业的委员投票评选出2023年网络安全十大发展趋势 福利 趋势一 数据安全治理成为数字经济的基
  • 利用CHAT写实验结论

    问CHAT 通过观察放置在玻璃表面上的单个水滴 人们可以观察到水滴充当成像系统 探究这样一个透镜的放大倍数和分辨率 CHAT回复 实验报告标题 利用玻璃表面的单一水滴观察成像系统的放大倍数和分辨率 一 实验目的 通过对比和测量 研究和探索玻
  • 【GRNN-RBFNN-ILC算法】【轨迹跟踪】基于神经网络的迭代学习控制用于未知SISO非线性系统的轨迹跟踪(Matlab代码实现)

    欢迎来到本博客 博主优势 博客内容尽量做到思维缜密 逻辑清晰 为了方便读者 座右铭 行百里者 半于九十 本文目录如下 目录 1 概述 2 运行结果 2 1 第1部分 2 2 第2部分
  • 特殊寄存器

    特殊寄存器 文章目录 前言 一 背景 二 2 1 2 2 总结 前言 前期疑问 STM32特殊寄存器到底是什么 特殊寄存器怎么查看和调试代码 本文目标 记录和理解特殊寄存器 一 背景 最近在看ucosIII文章是 里面提到特殊寄存器 这就进
  • 【GRNN-RBFNN-ILC算法】【轨迹跟踪】基于神经网络的迭代学习控制用于未知SISO非线性系统的轨迹跟踪(Matlab代码实现)

    欢迎来到本博客 博主优势 博客内容尽量做到思维缜密 逻辑清晰 为了方便读者 座右铭 行百里者 半于九十 本文目录如下 目录 1 概述 2 运行结果 2 1 第1部分 2 2 第2部分
  • systick定时器

    systick定时器 文章目录 前言 一 前期疑惑 二 解答 1 关于systick是阻塞的吗 2 非阻塞 三 软件编写 总结 前言 这边记录systick相关知识点 一 前期疑惑 在学习systick志气啊 其实对于systick还是一脸
  • 为什么这么多人自学黑客,但没过多久就放弃了(掌握正确的网络安全学习路线很重要)

    网络安全是一个 不断发展和演变 的领域 以下是一个 网络安全学习路线规划 旨在帮助初学者快速入门和提高自己的技能 基础知识 网络安全的 基础知识 包括 网络结构 操作系统 编程语言 等方面的知识 学习这些基础知识对理解网络安全的原理和技术至
  • 手把手教你使用HarmonyOS本地模拟器

    我们通过下面的动图来回顾下手机本地模拟器的使用效果 本期 我们将为大家介绍HarmonyOS本地模拟器的版本演进 并手把手教大家使用HarmonyOS本地模拟器 一 本地模拟器的版本演进 2021年12月31日 经过一个版本的迭代优化 随D
  • 项目文章 | IF=8.4&转录因子Egr-1是脑膜炎型大肠杆菌引起的血脑屏障损伤的关键调节因子

    2024年1月17日华中农业大学动科动医学院陈焕春院士 王湘如教授团队在期刊 Cell Communication and Signaling IF 8 4 发表了题为 Egr 1 is a key regulator of the blo
  • 嵌入式 C++11 代码 — 我需要 volatile 吗?

    采用 Cortex M3 MCU STM32F1 的嵌入式设备 它具有嵌入式闪存 64K MCU固件可以在运行时重新编程闪存扇区 这是由闪存控制器 FMC 寄存器完成的 所以它不像a b那么简单 FMC 获取缓冲区指针并将数据刻录到某个闪存
  • 移动数组中的元素

    我需要一点帮助 我想将数组中的元素向上移动一个元素 以便新位置 1 包含位置 1 中的旧值 new 2 包含 old 1 依此类推 旧的最后一个值被丢弃 第一个位置的新值是我每秒给出的新值 我使用大小为 10 的数组 uint32 t TE
  • stm32l0: 执行MI命令失败。使用 vFlashErase 数据包擦除闪存时出错

    我正在使用 Nucleo STM32L031 和 AC6 STM32 工作台 eclipse 我编写应用程序并进入调试模式 一切正常 直到我在应用程序中添加另一个功能 我注意到当我删除 评论 新函数 软件可以再次进入调试模式 但是当我添加
  • GCC 变量映射和 MISRA-C

    我主要知道两种使用 GCC 声明内存映射寄存器的方法 有许多变体 使用双字段 每个外设的数据结构等 要么使用初始化为正确地址的指针 例如volatile uint32 t pMyRegister uint32 t 0xDEADBEEFUL

随机推荐

  • Allegro如何导出和导入设计规则操作指导

    Allegro如何导出和导入设计规则操作指导 当需要借用另外一款PCB的设计规则时候 Allegro支持把PCB设计规则导入到另外一块PCB中 如下图 具体操作如下 打开规则管理器 打开后如下图
  • 黑马程序员mysql笔记--索引基本操作部分

    视频链接 https www bilibili com video BV1iF411z7Pu 1 3 1 索引的基本操作 1 3 1 1 索引概述 索引是什么 索引是通过某种算法 构建出一个数据模型 用于快速找出在某个列中有一特定值的行 不
  • 《A Metric Learning Reality Check》笔记

    1 是 metric learning 的一篇学术打假文 回顾了 deep metric learning 领域两个经典工作 contrastive loss triplet loss 和近年来 2017 2019 见文中 Table 6
  • DC-DC电源管理

    BUCK电源芯片的使用与选择 BUCK电路降压原理 在开关S闭合时 对电感L与电容C进行充电同时也对负载R供电 在开关S断开时储能元器件L与C继续对R进行供电并通过D1形成回路 输出电压Vo Vi Ton Ton Toff Ton 开关S闭
  • 【C语言】实现一个通讯录:通讯录可以用来存储1000个人的信息,每个人的信息包括: 姓名、性别、年龄、电话、住址

    先写一个只能录固定人数的通讯录 不能增容 不能保存 通讯录可以用来存储1000个人的信息 每个人的信息包括 姓名 性别 年龄 电话 住址 实现功能 1 添加联系人信息 2 删除指定联系人信息 3 查找指定联系人信息 4 修改指定联系人信息
  • Linux 压缩解包命令讲解

    tar命令使用讲解 压缩 tar命令 c 生成档案文件 v 列出归档解档的详细过程 f 指定档案文件名称 t 列出档案在包含的文件 x 解开档案文件 打包 tar cvf a tar txt tar cf a tar txt 解包 tar
  • mysql split函数用逗号分隔的实现方法

    本文主要介绍了mysql split函数用逗号分隔的实现 文中通过示例代码介绍的非常详细 对大家的学习或者工作具有一定的参考学习价值 需要的朋友们下面随着小编来一起学习学习吧 1 定义存储过程 用于分隔字符串 1 2 3 4 5 6 7 8
  • 服务端推送SSE技术

    SSE Server Sent Events 是一种用于实现服务器主动向客户端推送数据的技术 也被称为 事件流 Event Stream 它基于 HTTP 协议 利用了其长连接特性 在客户端与服务器之间建立一条持久化连接 并通过这条连接实现
  • 杂学日记

    glob函数的使用 glob库函数用于Linux文件系统中路径名称的模式匹配 即查找文件系统中指定模式的路径 注意 这不是正则表达式匹配 虽然有些相似 但还是有点差别 glob函数原型 include
  • 快速提升代码能力(7)sort(a,a+n);

    从零起步看算法 第七天 4 12 q9 交叉排序 算是一道水题了 1 花点时间看一下样例 就可以理解题意了 2 本题唯一知识点 用sort 实现 数组的从大到小排序 很简单的操作 https blog csdn net jimmy lee1
  • python 字典中 get 和 [] 的区别

    在Python中 get和 是用来访问字典 dict 或字典样的对象 例如defaultdict 中的元素的两种常见方式 它们有一些区别 使用get方法时 如果指定的键不存在于字典中 它会返回一个默认值 默认为None 也可以自定义 而不会
  • ConceptFusion 论文翻译

    ConceptFusion 论文翻译 本文仅仅是本人在英语水平不够的情况下对原论文的翻译 如果有错烦请指正 原始论文地址参见 https arxiv org pdf 2302 07241 pdf 下面开始正式翻译 摘要 构建三维环境地图对于
  • Wireshark网络抓包工具下载和安装(2023)

    一 Wireshark的下载 下载网址 https www wireshark org download html 也可以阿里网盘自取 wiresharkhttps www aliyundrive com s c4qeGBQMfwj提取码
  • 实现 Java 平台的三种方式

    广泛地说 只要能执行 Java bytecode 者 就可以称为 Java 平台 Java platform 大致上 实现 Java 平台的方式有三种 分别是 Java 虚拟机器 Java Virtual Machine JVM Java
  • Java实现企业微信上传临时文件获取media_id

    目录 1 上传临时素材API 2 测试代码 3 测试完成 4 遇到的问题 4 1 文件类型无法解析 1 上传临时素材API 调试工具 素材上传得到media id 该media id仅三天内有效 media id在同一企业内应用之间可以共享
  • Qt之:QProcess使用总结

    1 主程序 初始化及设定信号槽 process new QProcess connect process SIGNAL started SLOT started connect process SIGNAL finished int QPr
  • 02-线性结构3 Reversing Linked List(25 point(s)) 【链表】

    02 线性结构3 Reversing Linked List 25 point s Given a constant K and a singly linked list L you are supposed to reverse the
  • Oracle 19c RAC安装时遇到 INS-06006 错误

    1 错误现象 通过执行 gridSetup sh 配置 19c grid infrastructure 的时候 在 SSH connectivity 步骤 发生如下错误 INS 06006 Passwordless SSH connecti
  • 银行利率bp是什么意思,基准利率bp是什么意思

    银行bp是什么意思 在银行业里bp是指基点 是衡量利率的度量单位 1个基点等于0 01 100基点就是1 比如存款利率从5 下降到4 就是下调了100个bp 在银行业里 通常用bp来表示某个金融工具的利率变动幅度 或者两种利率之间的差价 此
  • 快速学习Stm32舵机控制板控制多个舵机运动以及调速

    本次分享stm32对多个舵机的控制 之前讲解过单个舵机的控制 以及控制原理 定时器的使用和pwm的输出来控制一个舵机的角度转向 这次就和大家分享一下多个舵机的控制以及调速 利用单片机实现对 8 个舵机的同时控制 掌握多个舵机控制程序实现方法