首页 > 其他分享 >从0开始玩转机械臂----认识总线舵机(一)

从0开始玩转机械臂----认识总线舵机(一)

时间:2024-09-25 22:24:15浏览次数:11  
标签:USART 舵机 总线 ---- 玩转 串口 GPIO USART2

目录

一、总线舵机简介

二、总线舵机工作原理

三、总线舵机接线

三、上位机调试

上位机正常界面

上位机基本使用教程

1.配置舵机id号

2.读取舵机角度

四、stm32读取舵机角度

1、接线图

2、实现代码

最近在搞机械臂机械视觉的项目,想着写篇博客来记录一下自己的成长和记录自己踩过的一些坑,方便以后复习,也希望自己的博客可以帮助到更多人读者。本人能力有限,过程如有不对,希望大家不吝指教。

一、总线舵机简介

图一:总线舵机

总线舵机是一种集成了电机、减速齿轮组、控制电路和通信接口的智能执行器。它的主要功能是接收来自控制器的指令(常见的是接受单片机串口传输的指令),并通过精确控制电机的转动来实现特定角度的输出。常在应用机械人和机械臂上,大家如果去淘宝上买那种组装好的机械臂大多都是由总线舵机组成的。

二、总线舵机工作原理

总线舵机通过特定的通信总线(如 CAN 总线、串口通信等)与控制器进行通信。控制器可以发送指令给舵机,包括设定目标角度、速度、运行时间等参数。因为舵机内部带有一块主控芯片, 内部已经完成 PWM 的控制。我们只需一条命令即可实现舵机的控制。(这里只简单述如何控制,不深究原理)。下图是众灵科技的总线舵机命令:

图二:总线舵机常见控制指令

总线舵机通过读取上位机或者单片机传输的指令来完成对应的任务。例如:单片机给他传输#000P1500T1000!  (最常用)

# 和 !是固定的英文格式。# 和 !可以看做串口通信的帧头和帧尾,有这些总线舵机才可以正常设别你的指令,000代表ID(范围0-254),必须为 3位,不足补0。比如3号舵机为“003”而不能为“3”。1500代表PWM脉冲宽度调制(P)(范围500-2500), 必须为4位,不足补0。比如PWM为800,则必须为“P0800”。1000代表TIME时间(T)(范围0-9999,代表完成这个动作的时间,越短越快),同样必须为 4位,不足补0,单位ms。比如TIME为500,则必须为“T0500。

该指令可以叠加同时控制多个舵机。多个指令同时使用时(2个或2个以上叠加)需要在整条指令前后加“{}”,比如:{G0000#000P1602T1000!#001P2500T0000!#002P1500T1000!} 

三、总线舵机接线

图3 :总线舵机接线端口

图4:舵机控制板

通过上图不难看出,总线舵机只有3 条线(信号线,正负极)。因为总线舵机通过半双工协议进行数据表的发送和接受(半双工是指不能同时接收发送),所以我们得通过舵机控制板才能正确的给舵机发送和接受数据,舵机控制板里会有对应的信号转换电路,用于将串口通信的全双工信号转换为半双工信号。

三、上位机调试

通过商家给的上位机,我们可以更直观的控制舵机旋转以及读取舵机现在的状态。

在使用上位机前,要正确的给总线舵机和舵机控制板以及电脑接线。(电池电压要确认在规定范围内,电压太小无法驱动机械臂,太大emmmm会炸)

图5:舵机控板与电脑接线

上位机正常界面

图6:上位机正常界面

如果出现下面那种字体缩在一起的情况,右击属性,点击兼容性更改dpi为系统执行。更改后就可正常显示。

图7:上位机不正常界面

图8:解决方法

上位机基本使用教程

1.配置舵机id号

首先给总线舵机配置自己的编号,上位机可以给255个总线舵机配置自己的id号,用于后面通信,首先点击配置,选择总线配置,然后确认自己usb线的串口号和波特率(默认115200)

图9:未连接界面

连接上后,连接设备会变成绿色

图10:正确连接界面

 点击“写” 修改设备 ID 号, 比如 000 改为 001 是将设备原本的 ID 000 改为 001,
在不知道 ID 的情况下就写 255 改成 XXX, 当前设备 ID 号就被修改成了 XXX, 255 是广播 ID,
所有总线设备都会响应这个指令; “ 读” 和“ 写” 类似, 点击时, 会发送一个读 ID 指令,
一般用来检测 ID 是否修改成功或者查看当前设备 ID

读写id号的时候最好只连接一个总线舵机,不要串联

图11:舵机写数据


图12:舵机读数据

2.读取舵机角度

点击高级的“高级配置”,点击全部释力(让舵机释放扭力,不释放掰不动)ps:我是已经点击过了才会出现全部恢复

图13:读取总线舵机角度

然后调整舵机的角度,点击依次回读,就会返回你舵机的角度(不过是pwm数值的形式,不掰舵机默认1500度),舵机的pwm值会在(500-2500)之间,500对应0度,2500对应实际的270 度

图14:读总线舵机角度

由此可得旋转一度,pwm会增加(2500-500)/270=7.0407.....这样就可以通过对比前后2次pwm值的差值,来计算出舵机旋转的角度。

四、stm32读取舵机角度

1、接线图

stm32与舵机控制板和舵机接线(一定要接对,不对舵机不会动的)

图15:舵机控制板与stm32接线

2、实现代码

经过上面的解释,大家应该也都知道了,发送对应的命令,总线舵机就会执行对应的命令,那么怎么在stm'32里面实现呢,直接上代码(我这里是stm32f4)

首先配置串口

usatrt2.c

#include "sys.h"
#include "usart.h"	
extern u8 Start;
// 	
//如果使用ucos,则包括下面的头文件即可.
#if SYSTEM_SUPPORT_OS
#include "includes.h"					//ucos 使用  
#endif

#if 1  //如果使能了接收
//串口2中断服务程序
//注意,读取USARTx->SR能避免莫名其妙的错误   	
u8 USART2_RX_BUF[USART_REC_LEN];     //接收缓冲,最大USART_REC_LEN个字节.
//接收状态
//bit15,	接收完成标志
//bit14,	接收到0x0d
//bit13~0,	接收到的有效字节数目
u16 USART2_RX_STA=0;       //接收状态标记	

//初始化IO 串口2 
//bound:波特率
void uart2_init(u32 bound)
{
   //GPIO端口设置
  GPIO_InitTypeDef GPIO_InitStructure;
  USART_InitTypeDef USART_InitStructure;
  NVIC_InitTypeDef NVIC_InitStructure;
    
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD,ENABLE); //使能GPIOD时钟
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);//使能USART2时钟
 
  //串口2对应引脚复用映射
  GPIO_PinAFConfig(GPIOD,GPIO_PinSource5,GPIO_AF_USART2); //GPIOD5复用为USART2
  GPIO_PinAFConfig(GPIOD,GPIO_PinSource6,GPIO_AF_USART2); //GPIOD6复用为USART2
    
  //USART2端口配置
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6; //GPIOD5与GPIOD6,5TX,6RX
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;	//速度50MHz
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽复用输出
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉
  GPIO_Init(GPIOD,&GPIO_InitStructure); //初始化PD5,PD6

   //USART2 初始化设置
  USART_InitStructure.USART_BaudRate = bound;//波特率设置
  USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
  USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
  USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
  USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
  USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;	//收发模式
  USART_Init(USART2, &USART_InitStructure); //初始化串口2
    
  USART_Cmd(USART2, ENABLE);  //使能串口2 
    
  //USART_ClearFlag(USART2, USART_FLAG_TC);
    
  #if 1 
  USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);//开启相关中断

  //Usart2 NVIC 配置
  NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;//串口2中断通道
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3;//抢占优先级3
  NVIC_InitStructure.NVIC_IRQChannelSubPriority =3;		//子优先级3
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能
  NVIC_Init(&NVIC_InitStructure);	//根据指定的参数初始化VIC寄存器、

  #endif
    
}

void usart2_send_str(u8 *Data)
{
	while(*Data) {
		USART_SendData(USART2, *Data++);
		while(USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET); 
	}
	return;
}




void USART2_IRQHandler(void)                	//串口3中断服务程序
{
  u8 Res;

  #if SYSTEM_SUPPORT_OS 		//如果SYSTEM_SUPPORT_OS为真,则需要支持OS.
    OSIntEnter();    
  #endif
  if(USART_GetITStatus(USART2, USART_IT_RXNE)!= RESET)  //接收中断()
  {
	USART_ClearITPendingBit(USART6, USART_IT_RXNE);
}

  #if SYSTEM_SUPPORT_OS 	//如果SYSTEM_SUPPORT_OS为真,则需要支持OS.
    OSIntExit();  											 
  #endif
} 
#endif	

usart2.h

#ifndef __USART2_H
#define __USART2_H
#include "stdio.h"	
#include "stm32f4xx_conf.h"
#include "sys.h" 

//	 
//本程序只供学习使用,未经作者许可,不得用于其它任何用途
//Mini STM32开发板
//串口1初始化		   
//正点原子@ALIENTEK
//技术论坛:www.openedv.csom
//修改日期:2011/6/14
//版本:V1.4
//版权所有,盗版必究。
//Copyright(C) 正点原子 2009-2019
//All rights reserved
//********************************************************************************
//V1.3修改说明 
//支持适应不同频率下的串口波特率设置.
//加入了对printf的支持
//增加了串口接收命令功能.
//修正了printf第一个字符丢失的bug
//V1.4修改说明
//1,修改串口初始化IO的bug
//2,修改了USART_RX_STA,使得串口最大接收字节数为2的14次方
//3,增加了USART_REC_LEN,用于定义串口最大允许接收的字节数(不大于2的14次方)
//4,修改了EN_USART1_RX的使能方式
// 	
#define USART_REC_LEN  			200  	//定义最大接收字节数 200
#define EN_USART2_RX 			1		//使能(1)/禁止(0)串口1接收
	  	
extern u8  USART2_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.末字节为换行符 
extern u16 USART2_RX_STA;         		//接收状态标记	
//如果想串口中断接收,请不要注释以下宏定义
void uart2_init(u32 bound);
void usart2_send_str(u8 *Data);
#endif


给舵机发送读取角度字符串,函数,依次传入参数,在自己主函数里面调用即可

void set_servo(int index, int pwm, int time)//依次传不同的舵机要转到的角度和时间进去
{

	jxb_control[index].aim = pwm;
	jxb_control[index].time = time;
	jxb_control[index].inc = (jxb_control[index].aim -  jxb_control[index].cur) / (jxb_control[index].time/20.000);
	sprintf((char *)cmd_return, "#%03dP%04dT%04d!\r\n", index, pwm, time); //合并字符串
	usart2_send_str(cmd_return);										   //自定义usart2的发送字符串函数,在usart2.c里面
}

标签:USART,舵机,总线,----,玩转,串口,GPIO,USART2
From: https://blog.csdn.net/Fhfgbyv/article/details/142531679

相关文章

  • 01 面向过程编程
    1、面向过程编程#面向过程编程user_input=input('请输入角色:')ifuser_input=='管理员':importsmtplibfromemail.mime.textimportMIMETextfromemail.utilsimportformataddrmsg=MIMEText('管理员,我想演男一号,你想怎么着都行。','plain......
  • TS系列(2):类型声明、类型推断和类型总览
    你好,我是沐爸,欢迎点赞、收藏、评论和关注。昨天分享了 TS系列(1):TS是什么?如何使用?今天咱们接着上回继续唠。四、类型声明使用:来对变量或函数形参,进行类型声明:leta:string//变量a只能存储字符串letb:number//变量b只能存储数值letc:boolean//变量c只能存......
  • Java中的序列化和反序列化
    Java中序列化和反序列化的区别序列化和反序列化的定义序列化(Serialization)与反序列化(Deserialization)是编程中常见的两个概念,他们主要涉及到将数据结构或对象状态转换为可以存储或传输的格式,以及将存储或传输的格式转换回原始的数据结构或对象状态的过程。这两个过程在数据持久......
  • c++模板,STL
                                            C++提高编程模板函数模板语法:template用法://自动类型推导mySwap(a,b);//显示指定类型mySwap<int>(a,b);注意事项自动类型推导,必须推导出 一致 的数据类型T,才可......
  • 03 函数基本结构
    3、对于函数编程本质:将N行代码拿到别处并给他起个名字,以后通过名字就可以找到这段代码并执行。场景:代码重复执行。代码量特别多超过一屏,可以选择通过函数进行代码的分割。3、函数的基本结构#函数的定义def函数名():#函数内容pass#函数的执行函数名()......
  • MySQL高阶1965-丢失信息的雇员
    目录题目准备数据分析数据实现题目编写解决方案,找到所有 丢失信息 的雇员id。当满足下面一个条件时,就被认为是雇员的信息丢失:雇员的 姓名 丢失了,或者雇员的 薪水信息 丢失了返回这些雇员的id employee_id , 从小到大排序 。准备数据CreatetableIfNot......
  • 02 函数编程案例 邮件发送
    2、函数式编程-邮件发送defsend_email(): importsmtplibfromemail.mime.textimportMIMETextfromemail.utilsimportformataddrmsg=MIMEText('老板,我想演男一号,你想怎么着都行。','plain','utf-8')msg['From']=formataddr......
  • 【Linux探索学习】第一弹——Linux的基本指令(上)——开启Linux学习第一篇
    前言:在进入Linux学习之前,我们首先要先做好以下两点:1、已经基本掌握C语言或C++,2、已经配置好了Linux的环境,做完以上两点后我们就开始Linux的学习,今天我们首先要学习的就是Linux中最基础的操作:基础指令,由于本人也是现学现卖,所以在文中多多少少会有讲解不到位或出错的地方,如果你......
  • 求最大公约数的三种算法
    #include<iostream>#include<vector>#include<algorithm>usingnamespacestd;intgcdByBruteForce(inta,intb){for(inti=min(a,b);i>0;--i){if(a%i==0&&b%i==0){returni;......
  • android仿录音机通知
    在Android中,为了模拟一个录音机应用的通知,你需要创建一个持久的通知,当录音开始时显示出来,并且在录音过程中一直存在,直到录音结束。下面是如何实现这一点的步骤:1.创建通知渠道对于AndroidOreo(8.0)及更高版本,你需要创建一个通知渠道。privatevoidcreateNotificationChannel(){......