[Maker]不握遥控器?Arduino+电调控制四轴飞行器电机
今天我们来论如何上天。
也许我们想飞得更高,看得更远
或是打造一款澎湃动力的电动漂移板:
那我们总离不开用单片机控制电机。
那么,arduino控制电机跟arduino通过电调控制电机区别在哪儿呢?
前者,控制小电机是比较容易的。然而对于四轴和电动滑板,电压太高烧主板!
由于电池电压过高(四轴无人机电压14.1V,电动漂移板28.8V),若是直接连接单片机,会烧坏。
这个时候便需要连接电调(speed controler)作为中转桥梁。
问题就是,电机连上电调后,就不受单片机直接控制了。电调就像是一位机场的安检员,只有“说服”安检员,让安检员传话给电机,电机才会动。
那怎么样用Arduino “说服” 电调呢?
Arduino控制高电压的四轴电机需要电调,然而坑爹的是电调默认校准方式是实体遥控器校准,电调说明书上并没写关于单片机与软件控制的方法,且目前网上搜集到的这方面教程比较散乱。
因此这篇文章的目的就是,一条龙解决Arduino连接电调控制电机。也就是让这小家伙通过Arduino而不是实体遥控器转起来,这样可以为自己用手机app遥控(一个实体遥控器几百呢)、电脑控制和以后其自主编程控制提供方便。
claim:standing on the shoulders of the giants
接下来以四轴无人机电机为例,电动滑板轮毅电机同理
要点:
1.电路连接方式
2.PWM控制
3.电调初始化
4.转速的有效信号区间查找
5.Wifi遥控时Arduino中 Serial.read() 的char转换为 速度的 int
5.过渡与渐变
材料 | |
---|---|
四轴20A电调 | 1 |
四轴2212电机 | 1 |
4S电池或直流电源 | 1 |
连接 | 若干 |
若电机有报障声音,请参考电调故障申明
值得注意的是,声音是从电机上发出来的,并不是电调。
其次,电机的声音能给我们提供非常多的反馈信息。
准备就绪后,电机没有声音又没有转动,说明电路未连接正确或电压不够(要大于7V)。
1.连接方式
电路连接方式
总的来说,就是:电源连电调,电调的电源线连电机+电调的信号线连arduino(接有“~”标记的7)
一张图搞定(只不过这里的接收机为Arduino):
电调与arduino连接时,因为电调有自动低压保护措施,记得要保证电源电压大于7V,才能正常激活电调!否则什么反应都没有。
有电池的同学用电池,当然电池什么的相比,还是可直接调压的直流电源更方便。
7V以上电压才能激活2.电调初始化
这电调可高级了,内置独立的程序和连接马达的报错程序。
最关键的是,电调首次使用,没调制好油门行程,也是不能驱动电机的。想要首次激活电调,就要在Arduino上说一样的“暗号”,也就是模仿实体遥控器的程序走一遍。
说明书上关于实体遥控器校准的方法是这样的:
于是,我们需要模拟设置油门行程。
模拟设置油门行程代码如下,直接刷入Arduino等待几秒,若电调发出滴滴声音后开始转动,表示已激活(正常使用时只需要激活一遍,当然重复激活也不影响):
int sp1=9;//定义舵机接口数字接口7
int pulsewidth;//定义脉宽变量
int val;
int val1;
int myangle1;
//下面是servopulse函数部分(此函数意思:也就是說每次都是0.5ms高電平 1.98ms低電平 然後再0.52ms低電平 17ms延時也是低電平)
void servopulse(int sp1,int val1)//定义一个脉冲函数
{
myangle1=map(val1,0,180,500,2480);
digitalWrite(sp1,HIGH);//将舵机接口电平至高
delayMicroseconds(myangle1);//延时脉宽值的微秒数
digitalWrite(sp1,LOW);//将舵机接口电平至低
delay(20-val1/1000);
}
//servopulse函数部分到此结束
void setup()
{
pinMode(sp1,OUTPUT);//设定舵机接口为输出接口
//设置两组串口波特率
Serial.begin(9600);
Serial.println("servu=o_seral_simple ready" ) ;
//看电调说明书,设置油门行程时,一开始需要把遥控器打到最高点。i<=110大概是2杪多
for(int i=0;i<=110;i++)
{
servopulse(sp1,150);//引用脉冲函数
}
//等电机发出B-B两声后(就是两秒后,大概就是这里了)把油门打到最低点
for(int i=0;i<=55;i++)
{
servopulse(sp1,20);//引用脉冲函数
}
//后面提示后,就可以控制电机转动了
for(int i=0;i<=150;i++)
{
servopulse(sp1,150);//引用脉冲函数
}
Serial.println("hello world" ) ;
}
void loop()
{
Serial.print(val1,DEC);
Serial.println();
for(int i=0;i<=50;i++)//给予舵机足够的时间让它转到指定角度
{
servopulse(sp1,val1);//set the speed
}
}
}
设置好了之后,电机终于转起来了!若是正常使用,以后就不需要再次校准了。
但是,我们若在初始速度信号不等于0时启动了电机,电调就会报错,我们需要重新刷入这个程序进行一遍校准。
3.寻找速度的有效信号区间
校准后,我们就想控制速度了。下面刷入正式的代码,以调速:
int sp1=9;//定义舵机接口数字接口7
int pulsewidth;//定义脉宽变量
int val;
int val1;
int speed1=0;
int myangle1;
//下面是servopulse函数部分(此函数意思:也就是說每次都是0.5ms高電平 1.98ms低電平 然後再0.52ms低電平 17ms延時也是低電平)
void servopulse(int sp1,int val1)//定义一个脉冲函数
{
myangle1=map(val1,0,180,500,2480);
digitalWrite(sp1,HIGH);//将舵机接口电平至高
delayMicroseconds(myangle1);//延时脉宽值的微秒数
digitalWrite(sp1,LOW);//将舵机接口电平至低
delay(20-val1/1000);
}
//servopulse函数部分到此结束
void setup()
{
pinMode(sp1,OUTPUT);//设定舵机接口为输出接口
//设置两组串口波特率
Serial.begin(9600);
Serial.println("servu=o_seral_simple ready" ) ;
Serial.println("hello world" ) ;
}
void loop()
{
String inchars="";
while(Serial.available()>0)
{
char inchar=Serial.read();
if(isDigit(inchar))
{
inchars+=inchar;
}
speed1=inchars.toInt();
}
Serial.println(speed1);
for(int i=0;i<=50;i++)//给予舵机足够的时间让它转到指定角度
{
servopulse(sp1,speed1);//引用脉冲函数
}
}
我们知道,arduino的PMW功能其实是通过构造不同电压和时间,利用W=P*T来调控功率(速度)的。
我们首先来看一下这个脉冲函数的构造:
电调PMW信号构造Arduino可以发出的PMW的范围是非常宽的,高达over 2000Hz,而我手上这款电调最高只能识别600,因此会被电调识别为无信号输入,产生报警。我们需要不断设置电调速度值,探索出有效信号区域。
于是,构造电调可以识别的PMW信号,代码如下:
int sp1=9;//定义舵机接口数字接口7
int pulsewidth;//定义脉宽变量
int val;
int val1;
int speed1=0;
int myangle1;
void servopulse(int sp1,int val1)//定义一个脉冲函数
{
myangle1=map(val1,0,180,500,2480);
digitalWrite(sp1,HIGH);//将舵机接口电平至高
delayMicroseconds(myangle1);//延时脉宽值的微秒数
digitalWrite(sp1,LOW);//将舵机接口电平至低
delay(20-val1/1000);
}
构造好后,开始试探出识别的有效区间。简单来说,用二分法,在电压7V以上的条件下,找出min和max。
一般来说,min<50,max<200。我的电调很快通过二分法试出有效信号范围是[27,163];
这个时候,我们通过改变speed1的值,加上这条命令
servopulse(sp1,speed1);//set the speed
就已经可以改变电机速度了。
直流电源上电压缓缓调高Hhh,小心螺旋桨割到手,打开Arduino的Serial.命令台,输入一个有效区间内的速度,比如31,电源电压调起,感受风声吧~
4.Wifi遥控中读取到的String型速度转换为int型
可以改变速度后,我们想着怎样遥控接收更改的速度值。不论是蓝牙还是wifi遥控,都离不开Arduino中Serial.available 和Serial.read() 帮助我们获取和读取我们输入的速度值。问题就是,我们接收到的是String,是不能够speed=(int)String的
这个时候,我么需要把String转化为int。可是怎么转化呢,由于获取信号这个本身就涉及到函数调用,在调用过程中试图改变类型是非常难的,于是我们从result想办法。找了很久终于找到了:
将接收到的速度信号转化为int值 代码有:
void loop()
{
String inchars="";
while(Serial.available()>0)
{
char inchar=Serial.read();
if(isDigit(inchar))
{
inchars+=inchar;
}
speed1=inchars.tolnt();
}
记得清空 String要在每一个loop之前,而赋值要等到有新值输入后。
转化为int后,就可以设置电调速度了
speed1=inchars.tolnt();
servopulse(sp1,speed1);//set the speed
这个时候,我们已经具备了电脑、手机遥控电机速度的能力,甚至乎可以自己写app或用已有的app进行控制,如TCP连接;
6.平滑速度变化(可选)
我们改变电机速度的值,比如从10%到90%的时候,若是太快,电机会来不及变化,产生暴增或暴减,后果就是 无人机忽上忽下,或是电动滑板加速太快人仰马翻;若是太慢,会出现控制迟缓。因此,我们需要平滑速度变化。
延时函数
线性速度增长函数。
曲线函数
想要速度变得更加平滑的,比如先慢后快,可以用数学建模 弄一个过渡函数,比如(ax^2+bx+cx) or (a^x),然后再把值赋给speed1.
好,至此为止,我们已经能够用Arduino连接电调控制无刷电机,甚至通过wifi进行遥控
这意味着我们具备了arduino驱动电机的基础,加上自己编写或应用手机软件,将在四轴无人机飞行和电动滑板上大显神通。
最后,愿大家都能做出像航模协会大神那样DIY的成品:
Good luck!_
欢迎关注/交流讨论~
参考资料:
2.Arduino 编程入门到实战(PWM部分)