看一下舵机控制器主芯片旁边的双排针,使用RS232来控制的时候是有条线帽的,您要使用Arduino控制需要将条线帽拆除,用四根杜邦线连接内侧的排针和UNO控制器,连接之前将程序导入到UNO控制器中,接线顺序为:TX-RX,RX-TX,+接电源正,-接GND然后给舵机供电,就可以使用UNO控制器来控制32路舵机控制器了。
//12MHz
#include <reg51h>
void InitTimer0(void)
{
TMOD = 0x01;
TH0 = 0x0B1;
TL0 = 0x0E0;
EA = 1;
ET0 = 1;
TR0 = 1;
}
void delay(void) //误差 0us 延时1ms 此处可以修改高电平周期
//修改此处的延时可以更改舵机转的角度 ,45度具体是多少 你可以试试
{
unsigned char a,b,c;
for(c=1;c>0;c--)
for(b=142;b>0;b--)
for(a=2;a>0;a--);
}
void main(void)
{
InitTimer0();
P1_2=0;
while(1);
}
void Timer0Interrupt(void) interrupt 1
{
//20ms中断
TH0 = 0x0B1;
TL0 = 0x0E0;
P1_2=1;
delay();
P1_2=0;
}
//配置 回中
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO| RCC_APB2Periph_GPIOA
| RCC_APB2Periph_TIM1, ENABLE);
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/ TIM pin configuration /
GPIO_InitStructureGPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructureGPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructureGPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
void TIM_Configuration(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
/ Time base configuration /
TIM_TimeBaseStructureTIM_Period =19999;
TIM_TimeBaseStructureTIM_Prescaler = 71;
TIM_TimeBaseStructureTIM_ClockDivision = 0;
TIM_TimeBaseStructureTIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
/ TIM1 PWM1 Mode configuration: Channel 1,2/
TIM_OCInitStructureTIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructureTIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructureTIM_Pulse = 1499;
TIM_OCInitStructureTIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC1Init(TIM1, &TIM_OCInitStructure);
TIM_OC2Init(TIM1, &TIM_OCInitStructure);
}
//改变角度500——-90,2500——90
TIM_SetCompare1(TIM1, Compare1);
TIM_SetCompare2(TIM1, Compare1);
定时器0表示的是脉冲总周期20ms,定时器1表示的是正脉冲宽度(如pwm_value = 1500时表示正脉冲宽度为15ms), 而while循序只是为了改变正脉冲宽度。运行过程是:定时器0和定时器,1同时开启,此时pwm = 1,定时器1的时间到了之后pwm = 0,并关闭定时器1,等待脉冲总周期达到20ms即定时器0中断,在定时器0的中断服务中又将pwm赋值为1并开启定时器1……以这样的方式循环就可以控制舵机转动了!
首先开明白你的舵机控制原理,它要求输入的脉冲期是20ms,其中高电平在15ms时舵臂在0位
在20ms时舵臂在右90度位 在15ms时舵臂在左90度位 舵机有3根线,一根线是电源正,另一根电源负,还有一根(一般为白线)是控制线,就是输入的脉冲信号的
程序中可以用两个定时器,一个定时20ms,另外一个定时1到2ms可变,就可以让舵机动作
下面程序供参考,先不考虑按键问题,能让舵机动作就 成功一大半
/双定时器产生PWM波,控制舵机
//定时器0负责置高电平和控制定时器1的开停,定时器1负责置低电平
#include<STC12C5AH>
#define uchar unsigned char
#define uint unsigned int
sbit PWM=P3^7;//经试验,此引脚信号可以直接送舵机不用放大
uchar b=1500;//定时15ms的初值
void Delay1ms(uint i) //1ms延时程序
{
uint j;
for(;i>0;i--)
{
for(j=0;j<125;j++)
{;}
}
}
void main()
{
b=1500;
TMOD=0X11;
TH0=(65536-20000)/256;
TL0=(65536-20000)%256;
TH1=(65536-b)/256;
TL1=(65536-b)%256;
ET0=1;
EA=1;
TR0=1;
PWM=1;
P1M0=0X0F; //低4位配置为推挽输出 ,普通51单片机无此寄存器
P1M1=0X00;
while(1)
{
P1=0; //这是让行走电机正向转动的,用的是L298N模块
b=1500;Delay1ms(2000);//直行
b=1000;Delay1ms(1000);//左转
b=1500;Delay1ms(2000);//直行
b=2000;Delay1ms(1000);//右转
b=1500;Delay1ms(2000);//直行
P1=0x05;//这是让行走电机反向转动的
b=1500;Delay1ms(2000);//后退
b=1000;Delay1ms(1000);//后左转
b=1500;Delay1ms(2000);//后退
b=2000;Delay1ms(1000);//后右转
b=1500;Delay1ms(2000);//后退
}
}
void timer0()interrupt 1//定时器0中断
{
TH0=(65536-20000)/256;
TL0=(65536-20000)%256;
PWM=1;
TR1=1;
ET1=1;
}
void timer1()interrupt 3//定时器1中断
{
TH1=(65536-b)/256;//改变b的值就可转向
TL1=(65536-b)%256;
PWM=0;
TR1=0;
ET1=0;
}
这个应该是通过串口发送数据信息的,发送和接收在一根信号线上,手上没有现成的程序,你看看这个在其他网上的行不行,
最好根据手册自己写
#include <avr/ioh>
#include <util/delayh>
void InitUart0(void)
{
UCSR0A = 0x02; // 设置为倍速模式
UBRR0H = 0;
UBRR0L = 1;
UCSR0B = (1<<RXEN)|(1<<TXEN);// 接收器与发送器使能
UCSR0C = (3<<UCSZ0);
DDRE &= ~_BV(PE0); // 初始化RX 端口默认方向为输入
PORTE &= ~_BV(PE0); // 初始化RX 端口默认状态为高阻
DDRE |= _BV(PE1); // 初始化TX 端口默认方向为输出
PORTE |= _BV(PE1); // 初始化TX 端口默认状态为高电平
DDRA |= _BV(PA0); // 初始化使能端口状态方向为输出
PORTA &= ~_BV(PA0); // 初始化使能端口状态为RX 状态
DDRA |= _BV(PA1); // 初始化使能端口状态方向为输出
PORTA |= _BV(PA1); // 初始化使能端口状态方为TX 状态
}
void SendUart0Byte(unsigned char data)
{
while ( !( UCSR0A & (1<<UDRE)) );// 等待发送缓冲器为空
UDR0 = data;/ 将数据放入缓冲器,发送数据/
}
void SetServoLimit(unsigned char id, unsigned short int cw_limit, unsigned short int ccw_limit)
{
unsigned short int temp_ccw = 0; // 临时速度,用于进行方向判别
unsigned short int temp_cw = 0;
unsigned char temp_ccw_h = 0; // 待发送数据h 位
unsigned char temp_ccw_l = 0; // 待发送数据l 位
unsigned char temp_cw_h = 0;
unsigned char temp_cw_l = 0;
unsigned char temp_sum = 0; // 校验和寄存变量
if (ccw_limit > 1023)
{
temp_ccw = 1023; // 限制速度值在可用范围内
}
else
{
temp_ccw = ccw_limit;
}
if (cw_limit > 1023)
{
temp_cw = 1023;
}
else
{
temp_cw = cw_limit;
}
temp_ccw_h = (unsigned char)(temp_ccw >> 8);
temp_ccw_l = (unsigned char)temp_ccw; // 将16bit 数据拆为2个8bit 数据
temp_cw_h = (unsigned char)(temp_cw >> 8);
temp_cw_l = (unsigned char)temp_cw; // 将16bit 数据拆为2个8bit 数据
PORTA &= ~_BV(PA1);
PORTA |= _BV(PA0); // 使总线处于主机发送状态
UCSR0A |= (1<<TXC0); // 清除UART0写完成标志
SendUart0Byte(0xFF); // 发送启动符号0xFF
SendUart0Byte(0xFF); // 发送启动符号0xFF
SendUart0Byte(id); // 发送id
SendUart0Byte(7); // 发送数据长度为参数长度+2,参数长度为3
SendUart0Byte(0x03); // 命令数据为“WRITE DATA”
SendUart0Byte(0x06); // 舵机控制寄存器首地址
SendUart0Byte(temp_cw_l); // 发送顺时针位置限制低位
SendUart0Byte(temp_cw_h); // 发送顺时针位置限制高位
SendUart0Byte(temp_ccw_l); // 发送逆时针位置限制低位
SendUart0Byte(temp_ccw_h); // 发送逆时针位置限制高位
temp_sum = id + 7 + 0x03 + 0x06 + temp_cw_l + temp_cw_h + temp_ccw_l + temp_ccw_h;
temp_sum = ~temp_sum; // 计算校验和
SendUart0Byte(temp_sum); // 发送校验和
while ( !( UCSR0A & (1<<TXC0)) ) // 等待发送完成
{ // (Waiting for finishing sending)
;
}
PORTA |= _BV(PA1);
PORTA &= ~_BV(PA0); // 使总线处于主机接收状态
_delay_ms(2); //送完成后,总线会被从机占用,反馈应答数据,所以进行延时
}
void SetServoPosition(unsigned char id, unsigned short int position, unsigned short int
velocity)
{
unsigned short int temp_velocity = 0; // 临时速度,用于进行方向判别
unsigned short int temp_position = 0;
unsigned char temp_velocity_h = 0; // 待发送数据h 位
unsigned char temp_velocity_l = 0; // 待发送数据l 位
unsigned char temp_position_h = 0;
unsigned char temp_position_l = 0;
unsigned char temp_sum = 0; // 校验和寄存变量
if (velocity > 1023)
{
temp_velocity = 1023; // 限制速度值在可用范围内
}
else
{
temp_velocity = velocity;
}
if (position > 1023)
{
temp_position = 1023;
}
else
{
temp_position = position;
}
temp_velocity_h = (unsigned char)(temp_velocity >> 8);
// 将16bit 数据拆为2个8bit 数据
temp_velocity_l = (unsigned char)temp_velocity;
temp_position_h = (unsigned char)(temp_position >> 8);
// 将16bit 数据拆为2个8bit 数据
temp_position_l = (unsigned char)temp_position;
PORTA &= ~_BV(PA1);
PORTA |= _BV(PA0); // 使总线处于主机发送状态
UCSR0A |= (1<<TXC0); // 清除UART0写完成标志
SendUart0Byte(0xFF); // 发送启动符号0xFF
SendUart0Byte(0xFF);
SendUart0Byte(id); // 发送id
SendUart0Byte(7); // 发送数据长度为参数长度+2,参数长度为3
SendUart0Byte(0x03); // 命令数据为“WRITE DATA”
SendUart0Byte(0x1E); // 舵机控制寄存器首地址
SendUart0Byte(temp_position_l); // 发送速度数据低位
SendUart0Byte(temp_position_h); // 发送速度数据高位
SendUart0Byte(temp_velocity_l); //发送位置低字节
SendUart0Byte(temp_velocity_h); // 发送位置高字节
temp_sum = id + 7 + 0x03 + 0x1E + temp_position_l + temp_position_h + temp_velocity_l +
temp_velocity_h;
temp_sum = ~temp_sum; // 计算校验和
SendUart0Byte(temp_sum); // 发送校验和 (Send the checksum)
while ( !( UCSR0A & (1<<TXC0)) ) // 等待发送完成
{ // (Waiting for finishing sending)
;
}
PORTA |= _BV(PA1);
PORTA &= ~_BV(PA0); // 使总线处于主机接收状态
_delay_ms(2); // 发送完成后,总线会被从机占用,反馈应答数据,所以进行延时
}
void SetServoVelocity(unsigned char id, signed short int velocity)
{
unsigned char temp_sign = 0; // 临时符号,用于进行方向判别
unsigned short int temp_velocity = 0; // 临时速度,用于进行方向判别
unsigned char temp_value_h = 0; // 待发送数据h 位
unsigned char temp_value_l = 0; // 待发送数据l 位
unsigned char temp_sum = 0; // 校验和寄存变量
if (velocity < 0)
{
temp_velocity = -velocity; // 如果为负数,则取绝对值
temp_sign = 1; // 设置负数符号标志
}
else
{
temp_velocity = velocity;
temp_sign = 0; // 设置正数符号标志
}
if (temp_velocity > 1023)
{
temp_velocity = 1023; // 限制速度值在可用范围内
}
temp_velocity |= (temp_sign << 10);
temp_value_h = (unsigned char)(temp_velocity >> 8);
// 将16bit 数据拆为2个8bit 数据
temp_value_l = (unsigned char)temp_velocity;
PORTA &= ~_BV(PA1);
PORTA |= _BV(PA0); // 使总线处于主机发送状态
UCSR0A |= (1<<TXC0); // 清除UART0写完成标志
SendUart0Byte(0xFF); // 发送启动符号0xFF
SendUart0Byte(0xFF); // 发送启动符号0xFF
SendUart0Byte(id); // 发送id
SendUart0Byte(5); // 发送数据长度为参数长度+2,参数长度为3
SendUart0Byte(0x03); // 命令数据为“WRITE DATA”
SendUart0Byte(0x20); // 舵机控制寄存器首地址
SendUart0Byte(temp_value_l); // 发送速度数据低位
SendUart0Byte(temp_value_h); // 发送速度数据高位
temp_sum = id + 5 + 0x03 + 0x20 + temp_value_l + temp_value_h;
temp_sum = ~temp_sum; // 计算校验和
SendUart0Byte(temp_sum); // 发送校验和
while ( !( UCSR0A & (1<<TXC0)) ) // 等待发送完成
{
;
}
PORTA |= _BV(PA1);
PORTA &= ~_BV(PA0); // 使总线处于主机接收状态
_delay_ms(2); // 发送完成后,总线会被从机占用,反馈应答数据,所以进行延时
}
int main(void)
{
InitUart0();
SetServoLimit(2,0,1023);
while(1)
{
_delay_ms(1000); //延时1s
SetServoPosition(2, 1000, 500); //控制舵机以500的速度运动到1000的位置
_delay_ms(1000); //延时1s
SetServoPosition(2, 200, 100); //控制舵机以100的速度运动到200的位置
}
}
以上就是关于按钮控制舵机的arduino程序全部的内容,包括:按钮控制舵机的arduino程序、单片机控制舵机程序、求教使stm32控制两个舵机完整程序等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)