四足机器人——舵机控制

目录

1、51定时器控制单个舵机

2、51定时器控制多路舵机

3、stm32控制舵机

4、pca9685驱动模块


1、51定时器控制单个舵机

舵机的控制一般需要一个20ms左右的时基脉冲,该脉冲的高电平部分一般为0.5ms~2.5ms范围内的角度控制脉冲部分,总间隔为2ms,比如说180度伺服角度,对应的关系如下。

PWM信号控制舵机的原理

void main(void)
{

	InitTimer0();	//定时器0初始化
	EA = 1;			//开总中断
	while(1)		//大循环
	{	
		Servo0PwmDuty = 500;		//脉冲宽度在500微秒,对应-90°
		DelayMs(1000);		//延时1秒
		Servo0PwmDuty = 1000;	//脉冲宽度在1000微秒,对应-45°
		DelayMs(1000);
		Servo0PwmDuty = 1500;
		DelayMs(1000);
		Servo0PwmDuty = 2000;
		DelayMs(1000);
		Servo0PwmDuty = 2500;
		DelayMs(1000);
	}
}

2、51定时器控制多路舵机

void main(void)
{
	uint8 i;
	InitTimer0();	//定时器0初始化
	EA = 1;			//开总中断
	while(1)		//大循环
	{	
		for(i = 0;i<8;i++)
			ServoPwmDuty[i] = 500;		//脉冲宽度在500微秒,对应-90°
		DelayMs(1000);					//延时1秒
		for(i = 0;i<8;i++)
			ServoPwmDuty[i] = 1000;		//脉冲宽度在1000微秒,对应-45°
		DelayMs(1000);
		for(i = 0;i<8;i++)
			ServoPwmDuty[i] = 1500;		//脉冲宽度在1500微秒,对应0°
		DelayMs(1000);					//延时1秒
		for(i = 0;i<8;i++)
			ServoPwmDuty[i] = 2000;		//脉冲宽度在2000微秒,对应45°
		DelayMs(1000);
		for(i = 0;i<8;i++)
			ServoPwmDuty[i] = 2500;		//脉冲宽度在2500微秒,对应90°
		DelayMs(1000);					//延时1秒
	}
}

3、stm32控制舵机

PWM就是脉冲宽度调制,也就是占空比可变的脉冲波形.

pwm的占空比,就是指高电平保持的时间,与该pwm时钟周期时间之比。

在应用中就是通过调节pwm占空比来控制,也就是一个周期中高电平所占的百分比来控制舵机的转角的。

在代码中要特别注意的是时基结构体的TIM_Period(自动重装载寄存器值,简称arr)和TIM_Prescaler(预分频寄存器值,简称psc),因为这两个决定了输出PWM信号的周期。具体的周期计算公式为:周期=(arr+1)*(psc+1)/CLK。其中CLK为计数器的时钟频率,我的是72MHZ,也就是72000000。最后计算结果单位为秒,结果为0.02s,也就是20ms。这样的配置就是为了让输出的PWM信号达到前面说到的舵机要求的20ms周期。

int main(void)
{
	int delay_time;
	delay_init(); //延时函数初始化
	TIM_Init(); //定时器初始化
	while(1)
	{
		delay_ms(1000);
		TIM_SetCompare1(TIM1, 175); //对应180度
        delay_ms(1000);
		TIM_SetCompare1(TIM1, 180); //对应135度
        delay_ms(1000);
		TIM_SetCompare1(TIM1, 185); //对应90度
        delay_ms(1000);
		TIM_SetCompare1(TIM1, 190); //对应45度
        delay_ms(1000);
		TIM_SetCompare1(TIM1, 195); //对应0度
	}
}

4、pca9685驱动模块

stm32驱动程序:

#include "pca9685.h"
#include "myiic.h"
#include "delay.h"
#include "math.h"

void pca_write(u8 adrr,u8 data)
{ 
	IIC_Start();
	
	IIC_Send_Byte(pca_adrr);
	IIC_Wait_Ack();
	
	IIC_Send_Byte(adrr);
	IIC_Wait_Ack();
	
	IIC_Send_Byte(data);
	IIC_Wait_Ack();
	
	IIC_Stop();
}

u8 pca_read(u8 adrr)
{
	u8 data;
	IIC_Start();
	
	IIC_Send_Byte(pca_adrr);
	IIC_Wait_Ack();
	
	IIC_Send_Byte(adrr);
	IIC_Wait_Ack();
	
	IIC_Start();
	
	IIC_Send_Byte(pca_adrr|0x01);
	IIC_Wait_Ack();
	
	data=IIC_Read_Byte(0);
	IIC_Stop();
	
	return data;
}


void pca_setfreq(float freq)
{
		u8 prescale,oldmode,newmode;
		double prescaleval;
		freq *= 0.92; 
		prescaleval = 25000000;
		prescaleval /= 4096;
		prescaleval /= freq;
		prescaleval -= 1;
		prescale =floor(prescaleval + 0.5f);

		oldmode = pca_read(pca_mode1);
	
		newmode = (oldmode&0x7F) | 0x10; // sleep
	
		pca_write(pca_mode1, newmode); // go to sleep
	
		pca_write(pca_pre, prescale); // set the prescaler
	
		pca_write(pca_mode1, oldmode);
		delay_ms(2);
	
		pca_write(pca_mode1, oldmode | 0xa1); 
}
void pca_setpwm(u8 num, u32 on, u32 off)
{
		pca_write(LED0_ON_L+4*num,on);
		pca_write(LED0_ON_H+4*num,on>>8);
		pca_write(LED0_OFF_L+4*num,off);
		pca_write(LED0_OFF_H+4*num,off>>8);
}
void Servo_Init(float hz,u8 angle)
{
	u32 off=0;                    
	IIC_Init();
	pca_write(pca_mode1,0x0);
	pca_setfreq(hz);              
	off=(u32)(145+angle*2.4);
	pca_setpwm(0,0,off);
	pca_setpwm(1,0,off);
	pca_setpwm(2,0,off);
	pca_setpwm(3,0,off);
	pca_setpwm(4,0,off);
	pca_setpwm(5,0,off);
	pca_setpwm(6,0,off);
	pca_setpwm(7,0,off);
	pca_setpwm(8,0,off);
	pca_setpwm(9,0,off);
	pca_setpwm(10,0,off);
	pca_setpwm(11,0,off);
	pca_setpwm(12,0,off);
	pca_setpwm(13,0,off);
	pca_setpwm(14,0,off);
	pca_setpwm(15,0,off);
	delay_ms(500);
}
void Servo_angle(u8 num,u8 angle)
{
	u32 off = 0;
  off = (u32)(158+angle*2.2);
	pca_setpwm(num,0,off);
}


stm32主函数:

int main(void)
{	
	delay_init();//延时函数初始化
	Servo_Init(50,90);//初始化舵机驱动
	delay_ms(1000);
	uart_init(9600);
	Servo_angle(0,90);
	printf("this is a drill");
}

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码
< <上一篇
下一篇>>