|
本帖最后由 LooksSoYaung 于 2020-6-22 07:57 编辑
这楼讲讲程序吧,建议看不懂的直接跳过!
使用arduino系统进行处理,编程方便快捷多了(相较于51单片机),不过由于系统固有特性,会导致出现某些匪夷所思的问题,接下来会有提到。
以前用arduino接收遥控信号都是用pulseIn函数,读取接收机pwm信号引脚的高电平脉冲时长,但这个函数会死等每次信号脉冲结束,在此期间无法做别的事,因此读取信号的路数越多整体运行就越卡,通常三路以上就能明显感受,所以这并不是个好办法。
然后就把注意力集中在接收机的sbus信号引脚上,它这一个信号就能解读出所有通道的数据。经过学习,发现所谓的sbus其实是一种串口通信方式,不过比较**的一点是它是负逻辑,需要接一个电平反向电路才能让单片机正常通信,还好三个元件能搞定
,其次,接收机Sbus的数据帧格式总共25个字节,包含1个起始位 ,8个数据位,1个奇偶校验位, 两个终止位1,波特率100000,以上这些决定了它只能被接在arduino的硬件串口上,只有这才能被准确设置,软件串口除了设置波特率啥也调不了
解决了信号读取,还得搞信号处理,sbus把每个通道的数据分段组合在一个个数据段中,需要用数学方法重新分解还原,网上有教程(不过给arduino的少之又少)。
需要特别提醒的是软件串口和舵机控制函数不能同时开启!他俩的定时器调用有冲突,会导致舵机运行时有莫名其妙的跳动。我程序里的软件串口是用来检查读取到的信号用的(需要外接一个USB转TTL下载器传到电脑串口助手显示),当真正用作接收机时就打上双斜杠屏蔽掉。
通过软件串口我获知我这遥控器的中位信号值是1000而不是1500(其实可以搞一个初始化程序让arduino记住遥控器各通道的中位值和最大最小值)。油门通道要特别注意不管是往前还是往后打杆都是要增加电机驱动的占空比,而且发动机风门也都是要逐渐开大,唯一不同的是倒车时倒车继电器会启动,使通过驱动电机的电流反向;转向时内侧履带占空随杆量增大而减小,反正都算是数学逻辑问题啦。

#include <stdio.h>
#include <Servo.h>
//#include <SoftwareSerial.h>
//SoftwareSerial mySerial(10,9);
volatile int pos[16];//16路舵机
Servo servo_3;
Servo servo_4;
Servo servo_5;
int Speed,l_speed,r_speed,L_speed,R_speed=0;//
int fangxiang=90;//瞄准方向
void setup(){
Serial.begin(100000,SERIAL_8E2);//设置串口
servo_3.attach(3);//油门舵机
servo_4.attach(4);//俯仰舵机
servo_5.attach(5);//方向舵机
servo_5.write(90);//方向舵机初始角度
pinMode(2, OUTPUT);//接开炮继电器
pinMode(7, OUTPUT);//接发动机启动继电器
pinMode(12, OUTPUT);//接倒车继电器
pinMode(13, OUTPUT);//接倒车继电器
//mySerial.begin(115200);
}
void loop(){
SBUS();
if(900<pos[0]&&pos[0]<1100)/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
{l_speed=0;
r_speed=0;}
if(pos[0]>1100)//左拐
{
l_speed=(map(pos[0], 1100, 2000, 0, 255));
r_speed=0;
}
if(pos[0]<900)//右拐
{
r_speed=(map(pos[0], 900, 1, 0, 255));
l_speed=0;
}
if(900<pos[1]&&pos[1]<1100)//静止********************************************************************************************************
{Speed=0;
digitalWrite(12,LOW);
digitalWrite(13,LOW);
}
if(pos[1]>1100)//前进
{servo_3.write((map(pos[1], 1100, 2000,135,45)));
Speed=(map(pos[1], 1100, 2000, 50, 255));
digitalWrite(12,LOW);
digitalWrite(13,LOW);
}
if(pos[1]<900)//后退
{servo_3.write((map(pos[1], 900, 1, 135,45)));
Speed=(map(pos[1], 900, 1, 50, 255));
digitalWrite(12,HIGH);//倒车继电器启动
digitalWrite(13,HIGH);
}
L_speed=Speed-l_speed;
if(L_speed<0){L_speed=0;}
R_speed=Speed-r_speed;
if(R_speed<0){R_speed=0;}
analogWrite(11,(constrain(L_speed, 0, 255)));//速度输出*************************************************************************
analogWrite(6,(constrain(R_speed, 0, 255)));
servo_4.write((map(pos[2], 1, 2100, 60, 160)));//俯仰舵机映射
if(pos[3]>1200)//方向瞄准*************************************
{fangxiang--;
delay(20);
if(fangxiang<25)fangxiang=25;
}
if(pos[3]<800)
{fangxiang++;
delay(20);
if(fangxiang>155)fangxiang=155;
}
servo_5.write(fangxiang);
if(pos[5]<1500)//fire**********************************************************************************************************************************************
{ digitalWrite(2,HIGH);
delay(200);
digitalWrite(2,LOW);
delay(1000);
}
else digitalWrite(2,LOW);
if(pos[6]>1500)//启动发动机***************************************************************************************************************************************
{ digitalWrite(7,HIGH);
}
else digitalWrite(7,LOW);
}
//---Start--//SBUS信号处理代码开始
int sublowbit(byte data,int flags){//取任意设定位数二进制低位
int rdata=0,bitdata=0;
for (int i=0;i<flags;i++){
bitdata=bitRead(data,i);
rdata=rdata+(bitdata<<i);
}
return(rdata);
}
int subhightbit(byte data,int flags){//取任意设定位数二进制高位
int rdata=0,bitdata=0;
int h=flags;
for (int i=7;i>=(8-flags);i--){
bitdata=bitRead(data,i);
rdata=rdata+(bitdata<<(--h));
}
return(rdata);
}
void SBUS(){
byte SBUS_date[25];
if (Serial.available()>0)
{
if(Serial.peek()==0x0F)//判断数据包头文件
{
Serial.readBytes(SBUS_date,25);
pos[0]=(sublowbit(SBUS_date[2],3)<<8)+subhightbit(SBUS_date[1],8);
pos[1]=(sublowbit(SBUS_date[3],6)<<5)+subhightbit(SBUS_date[2],5);
pos[2]=(sublowbit(SBUS_date[5],1)<<10)+(sublowbit(SBUS_date[4],8)<<2)+subhightbit(SBUS_date[3],2);
pos[3]=(sublowbit(SBUS_date[6],4)<<7)+subhightbit(SBUS_date[5],7);
pos[4]=(sublowbit(SBUS_date[7],7)<<4)+subhightbit(SBUS_date[6],4);
pos[5]=(sublowbit(SBUS_date[9],2)<<9)+(sublowbit(SBUS_date[8],8)<<1)+subhightbit(SBUS_date[7],1);
pos[6]=(sublowbit(SBUS_date[10],5)<<6)+subhightbit(SBUS_date[9],6);
pos[7]=(sublowbit(SBUS_date[11],8)<<3)+subhightbit(SBUS_date[10],3);
pos[8]=(sublowbit(SBUS_date[13],3)<<8)+subhightbit(SBUS_date[12],8);
pos[9]=(sublowbit(SBUS_date[14],6)<<5)+subhightbit(SBUS_date[13],5);
}
while(Serial.read()>=0){
for(int i=0; i<25; i++){
SBUS_date=00000000;
}
}
}
}
//---End---//SBUS信号处理代码结束


这是我目前的底盘驱动程序,修改自从别人那弄来的sbus接收程序,源程序埋了一些坑,比如没必要的延时程序导致系统响应缓慢,没有舵机驱动等等,只有真正理解了运作机理才能对别人的程序做出合理的修改。
|
欢迎继续阅读楼主其他信息
|