51单片机驱动mg995舵机实践讲解
舵机是一种位置(角度)伺服的驱动器,适用于那些需要角度不断变化并可以保持的控制系统。舵机的组成包括一个小型直流电机,加上传感器、控制芯片、减速齿轮组,装进一体化外壳。舵机能够通过输入信号(一般是PWM信号)控制旋转角度。
舵机的控制一般需要一个20ms左右的时基脉冲,该脉冲的高电平部分一般为0.5ms-2.5ms范围内的角度控制脉冲部分,总间隔为2ms。以 MG995舵机为例,其对应的控制关系是这样的:
0.5ms--------------0度;
1.0ms------------45度;
1.5ms------------90度;
2.0ms-----------135度;
2.5ms-----------180度;
PWM,即脉宽调制,控制方式就是对逆变电路开关器件的通断进行控制,使输出端得到一系列幅值相等的脉冲,用这些脉冲来代替正弦波或所需要的波形。也就是在输出波形的半个周期中产生多个脉冲,使各脉冲的等值电压为正弦波形,所获得的输出平滑且低次谐波少。按一定的规则对各脉冲的宽度进行调制,即可改变逆变电路输出电压的大小,也可改变输出频率。
我们学过51单片机后会知道,51单片机不能直接产生PWM信号。但我们了解了PWM的工作原理,我们就可以用51单片机中的定时器将PWM信号给模拟出来。
首先我们需要对51单片机的定时器初始化,设定定时器中端和定义模拟输出PWM信号的引脚。设定51单片机定时器周期为0.5ms,定义变量count统计计时时间,当计时达到20ms后重新计时,这样我们就得到了舵机的运行周期。
我们将编好的程序下载到51单片机中,连接好舵机,程序运行后我们会发现舵机的转动十分缓慢,这是什么原因导致的呢?
我们通过查阅手册可以知道,舵机的工作电压在4.8V—6V,51单片机输出电压为5V,在理论上肯定能带动舵机,但还是要以实际情况为准。根据编者自身实践经验来说,用51单片机驱动MG995舵机时还是选用3.3V工作电压较好,此时舵机能够正常转动而不会缓慢抖动。当然,选用3.3V电压驱动舵机仅限于编者自身实践的经验。如果在程序无错误的情况下用5V电压驱动MG995舵机,舵机不能正常运转时,不妨试一下用3.3V电压驱动舵机。
可控制992个舵机-PCA9685驱动分享
大家好,我是鼎!
PCA9685
PCA9685
PCA9685是一款基于IIC总线通信的12位精度16通道PWM波输出的芯片,该芯片最初由NXP推出时主要面向LED开关调光。
目前国内,Arduino在舵机控制领域使用的更广泛,底层驱动库十分完善的,但对于单片机用户来说,则需要自行根据用户手册编写底层的驱动。
优势
价格非常便宜,10+米。最多可62块板子同时使用,每一块棒子可以驱动多达12个舵机,最多可驱动多达992个舵机,相当可观的数量!地址误区讲解
其地址的分配是通过模块右上方的短接焊盘来确定的,从A0-A5表示地址的最低位到最高位,也就是最多可级联2^5=32个模块,地址为: 1+A5+A4+A3+A2+A1+A0+rw。如果不用短接的话Ax=0;短接的话Ax=1;rw为写的话rw=0;rw为读的话rw=1;所以默认地址应为1000 0000 =0x80,许多人包括淘宝商家误以为默认地址是0x40,是错误的!
IIC通信
可以利用模拟IIC总线通讯,方便移植,摆脱硬件的限制。
驱动 PCA9685.h
#ifndef __I2C_PCA9685_H__
#define__I2C_PCA9685_H__
/* 包含头文件 ----------------------------------------------------------------*/
#include "stm32f4xx_hal.h"
/* 类型定义 ------------------------------------------------------------------*/
/* 宏定义 --------------------------------------------------------------------*/
#define PCA9685_adrr 0x80
#define PCA9685_SUBADR1 0x2
#define PCA9685_SUBADR2 0x3
#define PCA9685_SUBADR3 0x4
#define PCA9685_MODE1 0x0
#define PCA9685_PRESCALE 0xFE
#define LED0_ON_L 0x6
#define LED0_ON_H 0x7
#define LED0_OFF_L 0x8
#define LED0_OFF_H 0x9
#define ALLLED_ON_L 0xFA
#define ALLLED_ON_H 0xFB
#define ALLLED_OFF_L 0xFC
#define ALLLED_OFF_H 0xFD
#define FINGLEMAX 25
#define FINGLEMIN 90
/* 扩展变量 ------------------------------------------------------------------*/
/* 函数声明 ------------------------------------------------------------------*/
void PCA9685_write(unsigned char reg,unsigned char data);
uint8_t PCA9685_read(unsigned char reg);
void setPWMFreq(uint8_t freq);
void setPWM(uint8_t num, uint16_t on, uint16_t off);
void begin();
void Angle(uint8_t num,float angle);
#endif /* __I2C_PCA9685_H__ */
/************************END OF FILE************************/
驱动PCA9685.C
/* 包含头文件 ----------------------------------------------------------------*/
#include "i2c/bsp_I2C.h"
#include "PCA9685/bsp_i2c_PCA9685.h"
#include "stm32f4xx_hal.h"
#include "i2c/bsp_I2C.h"
#include "math.h"
/* 私有类型定义 --------------------------------------------------------------*/
/* 私有宏定义 ----------------------------------------------------------------*/
/* 私有变量 ------------------------------------------------------------------*/
/* 扩展变量 ------------------------------------------------------------------*/
/* 私有函数原形 --------------------------------------------------------------*/
/* 函数体 --------------------------------------------------------------------*/
void PCA9685_Delay(void)
{
uint8_t i;
for (i = 0; i < 30; i++);
}
void PCA9685_write(uint8_t reg,uint8_t date)
{
I2C_Start();
I2C_SendByte(PCA9685_adrr); //PCA9685
I2C_WaitAck();
I2C_SendByte(reg);
I2C_WaitAck();
I2C_SendByte(date);
I2C_WaitAck();
I2C_Stop();
}
//从PCA9685读数据有返回值
uint8_t PCA9685_read(uint8_t reg)
{
uint8_t res;
I2C_Start();
I2C_SendByte(PCA9685_adrr); //PCA9685
I2C_WaitAck();
I2C_SendByte(reg);
I2C_WaitAck();
I2C_Start();
I2C_SendByte(PCA9685_adrr|0x01);
I2C_WaitAck();
res = I2C_ReadByte();
I2C_Stop();
return res;
}
//PCA9685复位
void reset(void)
{
PCA9685_write(PCA9685_MODE1,0x0);
}
void begin(void)
{
reset();
}
//PCA9685修改频率
/**
* 函数功能: 设置PWM频率
* 输入参数: 20MS设置50
* 返 回 值: 无
* 说 明:无
*/
void setPWMFreq(uint8_t freq)
{
uint8_t prescale,oldmode,newmode;
double prescaleval;
freq *= 0.92; // Correct for overshoot in the frequency setTIng
prescaleval = 25000000;
prescaleval /= 4096;
prescaleval /= freq;
prescaleval -= 1;
prescale = (uint8_t)floor(prescaleval + 0.5);
oldmode = PCA9685_read(PCA9685_MODE1);
newmode = (oldmode&0x7F) | 0x10; // sleep
PCA9685_write(PCA9685_MODE1,newmode); // go to sleep
PCA9685_write(PCA9685_PRESCALE,prescale); // set the prescaler
PCA9685_write(PCA9685_MODE1,oldmode);
HAL_Delay(2);
PCA9685_write(PCA9685_MODE1,oldmode|0xa1);
}
/*---------------------------------------------------------------
PCA9685修改角度函数
num:舵机PWM输出引脚0~15,on:PWM上升计数值0~4096,off:PWM下降计数值0~4096
一个PWM周期分成4096份,由0开始+1计数,计到on时跳变为高电平,继续计数到off时
跳变为低电平,直到计满4096重新开始。所以当on不等于0时可作延时,当on等于0时,
off/4096的值就是PWM的占空比。
----------------------------------------------------------------*/
/**
* 函数功能: 设置PWM占空比
* 输入参数: num:舵机PWM输出引脚0~15,on:PWM上升计数值0~4096,off:PWM下降计数值0~4096
一个PWM周期分成4096份,由0开始+1计数,计到on时跳变为高电平,继续计数到off时
跳变为低电平,直到计满4096重新开始。所以当on不等于0时可作延时,当on等于0时,
off/4096的值就是PWM的占空比。
* 返 回 值: 无
* 说 明:无
*/
void setPWM(uint8_t num, uint16_t on, uint16_t off)
{
PCA9685_write(LED0_ON_L+4*num,on);
PCA9685_write(LED0_ON_H+4*num,on>>8);
PCA9685_write(LED0_OFF_L+4*num,off);
PCA9685_write(LED0_OFF_H+4*num,off>>8);
}
uint16_t calculate_PWM(float angle){
return (int)(204.8*(0.5+angle*1.0/90));
}
/**
* 函数功能: 舵机角度
* 输入参数: num:舵机通道 angle:舵机角度
* 返 回 值: 无
* 说 明:无
*/
void Angle(uint8_t num,float angle)
{
uint16_t pwm = calculate_PWM(angle);
setPWM(num,0,pwm);
PCA9685_Delay();
}
/************************END OF FILE****/
main.c
I2C_InitGPIO();
begin();
setPWMFreq(50);
相关问答
怎么用51 单片机 控制 舵机 的?怎样编写程序啊?大哥帮帮忙-ZOL问答舵机是一种位置伺服的驱动器,适用于那些需要角度不断变化并可以保持的控制系统。其工作原理是:控制信号由接收机的通道进入信号调制芯片,获得直流偏置电压。它...
单片机 控制 舵机 自动来回不停转动程序?要实现单片机控制舵机自动来回不停转动,可以使用循环控制结构。首先,设置舵机初始位置,然后使用一个循环结构,让舵机从初始位置逐渐转动到一个极限位置,再返...
舵机 插在 单片机 哪里?舵机通常插在单片机的GPIO(通用输入输出)引脚上。舵机插在单片机的GPIO引脚上。舵机是一种电机,用于控制机械装置的角度。而单片机的GPIO引脚可以通过改变电平...
怎么用51 单片机 控制4个 舵机 工作,有程序的更好?模拟输出4路PWM即可网上程序很多搞清楚舵机的控制信号就行了舵机的控制信号为周期为20ms高电平时间为1ms-2ms(不同型号时间可能会有微小差别)的pwm信号...
各位朋友 请教一下,如何用51 单片机 控制伺服电机?伺服控制装...[回答]在伺服系统中控制机械元件运转的发动机,是一种补助马达间接变速装置。无线蓝牙串口透传模块,又叫蓝牙模块,是一种集成蓝牙功能的短距离无...无线蓝...
如何实现一块 单片机 (机器人),控制4个以上的伺服电机(单独运行)?要实现单独的4路舵机控制的话,我建议使用具有至少4路PWM的单片机。比如AVR系列的有Atmega128,可同时产生6路12位的PWM。51系列的有STC12C5410AD带4路PWM。具体...
单片机 智能小车pmw?不需要单独的PWM模块,仅靠单片机和电机驱动(L298N)足够了。具体是在程序中用单片机的IO口模拟出PWM信号来,也就是控制IO口输出的高低电平的时间,利用不同时...
学 单片机 可以接什么单?学习单片机可以搭建各种电子系统和项目,因此可以接很多不同的单元和硬件。以下是一些常见的单元和硬件,你可以使用单片机与其进行连接和控制:1.传感器:例如...
船用 舵机 不好用怎么办?1.电源电压不足:这个原因是最常见的情况,很多PIXHAWK爱好者希望外接一个舵机,发现遥控器映射好通道后,直接插上舵机是不转的,主要原因就是舵机的供电电压不足...
怎样用温度传感器来控制 舵机 左右摆动?温度传感器可以检测环境温度的变化并将其转化为电信号。可以将其与单片机或微控制器相连,通过编程控制舵机的左右摆动。例如,将温度传感器与Arduino连接并编...