第一次提交
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
#include "servo_motor.h"
|
||||
#include "stdlib.h"
|
||||
#include "memory.h"
|
||||
#include "bsp_log.h"
|
||||
uint8_t servo_angle_read[6]={0x55 ,0x55 ,0x04, 0x15 ,0x01 ,0x01 ,};
|
||||
uint8_t servo_angle_write[16]={0x55 ,0x55, 0x08, 0x03, 0x01 ,0xF4 ,0x01 ,0x01 ,0x20 ,0x03,0x55 ,0x55 ,0x04, 0x15 ,0x01 ,0x01 ,};
|
||||
uint8_t servo_unload[6]={0x55,0x55,0x04,0x14,0x01,0x01};
|
||||
|
||||
/*第二版*/
|
||||
static ServoInstance *servo_motor_instance[SERVO_MOTOR_CNT];
|
||||
static uint8_t servo_idx = 0; // register servo_idx,是该文件的全局舵机索引,在注册时使用
|
||||
static void DecodeServo();
|
||||
// 通过此函数注册一个舵机
|
||||
ServoInstance *ServoInit(Servo_Init_Config_s *Servo_Init_Config)
|
||||
{
|
||||
ServoInstance *servo = (ServoInstance *)malloc(sizeof(ServoInstance));
|
||||
memset(servo, 0, sizeof(ServoInstance));
|
||||
USART_Init_Config_s config;
|
||||
servo->servo_type = Servo_Init_Config->servo_type;
|
||||
switch (Servo_Init_Config->servo_type)
|
||||
{
|
||||
case Bus_Servo:
|
||||
config.module_callback = DecodeServo;
|
||||
config.recv_buff_size = Servo_MAX_BUFF;
|
||||
config.usart_handle = Servo_Init_Config->_handle;
|
||||
servo->usart_instance = USARTRegister(&config);
|
||||
break;
|
||||
case PWM_Servo:
|
||||
servo->pwm_instance = PWMRegister(&Servo_Init_Config->pwm_init_config);
|
||||
break;
|
||||
default:
|
||||
LOGERROR("Servo type error");
|
||||
break;
|
||||
}
|
||||
servo->servo_id = Servo_Init_Config->servo_id;
|
||||
servo_idx++;
|
||||
servo_motor_instance[servo->servo_id] = servo;
|
||||
|
||||
return servo;
|
||||
}
|
||||
//@todo PWM舵机的角度设置需要根据相应定时器PWM等参数进行计算(是否需要规范定时器PWM的初始化参数,以便于计算)
|
||||
void ServoSetAngle(ServoInstance *servo, float angle)
|
||||
{
|
||||
|
||||
switch (servo->servo_type)
|
||||
{
|
||||
case Bus_Servo:
|
||||
servo_angle_write[8] = (uint16_t)angle&0xff;
|
||||
servo_angle_write[9] = (uint16_t)angle>>8;
|
||||
USARTSend(servo->usart_instance, servo_angle_write, 16, USART_TRANSFER_DMA);
|
||||
// USARTSend(servo->usart_instance, servo_angle_read, 6, USART_TRANSFER_DMA);
|
||||
break;
|
||||
case PWM_Servo:
|
||||
servo->angle = angle;
|
||||
PWMSetDutyRatio(servo->pwm_instance, angle);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//@todo 只读取了角度 还有电压,动作是否完成等 且只支持一个串口
|
||||
static void DecodeServo()
|
||||
{
|
||||
for (uint8_t i = 0; i < servo_idx; i++)
|
||||
{
|
||||
if (servo_motor_instance[i]->servo_type == Bus_Servo)
|
||||
{
|
||||
if (servo_motor_instance[i]->usart_instance->recv_buff[0] == Servo_Frame_First && servo_motor_instance[i]->usart_instance->recv_buff[1] == Servo_Frame_Second)
|
||||
{
|
||||
if (servo_motor_instance[i]->usart_instance->recv_buff[3] == 21)
|
||||
{
|
||||
servo_motor_instance[i]->recv_angle = (servo_motor_instance[i]->usart_instance->recv_buff[7] << 8 | servo_motor_instance[i]->usart_instance->recv_buff[6]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
#ifndef SERVO_MOTOR_H
|
||||
#define SERVO_MOTOR_H
|
||||
|
||||
#include "main.h"
|
||||
#include "tim.h"
|
||||
#include <stdint-gcc.h>
|
||||
#include "bsp_pwm.h"
|
||||
#include "bsp_usart.h"
|
||||
|
||||
#define SERVO_MOTOR_CNT 7
|
||||
#define Servo_Frame_First 0x55
|
||||
#define Servo_Frame_Second 0x55
|
||||
#define Servo_MAX_BUFF 10
|
||||
#define SERVO_MOVE_CMD 0x03
|
||||
#define SERVO_UNLOAD_CMD 0x14
|
||||
#define SERVO_POS_READ_CMD 0x15
|
||||
typedef enum
|
||||
{
|
||||
Servo_None_Type = 0,
|
||||
Bus_Servo = 1,
|
||||
PWM_Servo = 2,
|
||||
}ServoType_e;
|
||||
|
||||
|
||||
/* 用于初始化不同舵机的结构体,各类舵机通用 */
|
||||
typedef struct
|
||||
{
|
||||
PWM_Init_Config_s pwm_init_config;
|
||||
ServoType_e servo_type;
|
||||
UART_HandleTypeDef *_handle;
|
||||
uint8_t servo_id;
|
||||
}Servo_Init_Config_s;
|
||||
typedef struct
|
||||
{
|
||||
uint8_t servo_id;
|
||||
float angle;
|
||||
uint16_t recv_angle;
|
||||
PWMInstance *pwm_instance;
|
||||
USARTInstance *usart_instance;
|
||||
ServoType_e servo_type;
|
||||
}ServoInstance;
|
||||
|
||||
ServoInstance *ServoInit(Servo_Init_Config_s *Servo_Init_Config);
|
||||
void ServoSetAngle(ServoInstance *servo, float angle);
|
||||
#endif // SERVO_MOTOR_H
|
||||
@@ -0,0 +1,23 @@
|
||||
##舵机的使用
|
||||
|
||||
<p align='left' >panrui@hnu.edu.cn</p>
|
||||
|
||||
> todo: 角度设置等需要规范化
|
||||
### 舵机基础知识
|
||||
|
||||
已最常见的SG90舵机为例,SG90舵机要求工作在频率为50HZ——周期为20ms的PWM波,且对应信号的高低电平在0.5ms - 2.5ms之间,对应的舵机转动角度如下表所示(当然也可以按照这个线性的对应关系去达到转动自己想要的角度,如想要转动60°,则高电平脉宽为大概为1.2ms,具体能不能转到特定的角度还和舵机的精度有关)
|
||||
|
||||
>0.5ms-------------0度; 2.5%
|
||||
>1.0ms------------45度; 5.0%
|
||||
>1.5ms------------90度; 7.5%
|
||||
>2.0ms-----------135度; 10.0%
|
||||
>2.5ms-----------180度; 12.5%
|
||||
|
||||
根据`<font color=black size=3>Tout = (PSC+1)* (ARR+1)/Tclk</font>`公式
|
||||
则我们需要产生50Hz的PWM波,则预分频的系数为 Prescaler = 168-1,自动重装载值 Counter Period = 20000-1,此时定时器产生的频率为 168Mhz/168/20000 = 50Hz。 当然这个值也可以自己设置,只要满足产生的频率为50Hz即可.
|
||||
`__HAL_TIM_SET_COMPARE(htim, Channel, compare_value);`
|
||||
这是设置占空比的函数
|
||||
eg:当初始占空比为1200/20000则为6%,根据20*6%=1.2ms (1.2-0.5)/(2.5-0.5)*180=63° 故舵机会转动63°
|
||||
为了方便通过上述eg我们将所需要的角度与PWM计数值对应关系封装成函数。需要在初始化的時候输入我们所需要的角度和相关定时器参数即可。这样我们就可以设置SG90为参数范围内(0~180°)任意度数。
|
||||
|
||||
---
|
||||
Reference in New Issue
Block a user