esp-12f单片机无线控制无刷电机,解锁BLHeli_S电调电机保护,BLHeli_S电调建立Keil工程。
由于项目上需要用到无刷电机,一般的无刷电机驱动器又大又不方便,所以最后选择了航模上使用的无刷电调,当时只是刚好看到BLHeli_S电调,就直接下单了。
使用电调控制无刷电机,最大的问题就是电机保护和油门行程校准。第一,单片机在控制电调驱动无刷电机的时候就需要跳过电机保护;第二,油门行程校准由于不同的协议没有具体的介绍,手上又没有遥控器和飞控,光靠单片机算法模拟一个值一个值来试是很难的。
一开始我是用单片机定时器试,后面买了个pwm测试电调的模块,完全适配BLHeli_S电调,用示波器发现调速很简单,就是50hz的1ms高电平3s左右就解锁电机保护,1-2ms高电平代表最小油门和最大油门。
一、让BLHeli_S电调控制无刷电机动起来
使用单片机连接BLHeli_S电调,白色PWM信号线,黑色为信号端接地校准。
电调连接电池和无刷电机,电调买的时候会介绍支持的电池,我的支持2S-6S(1S代表串联一块3.7V电池),我用的3S电池(11.1V),红接电池正极,黑接电池负极,无刷电机三相没有顺序随便接到电调。
因为需要用到无线功能,单片机我使用的是esp-12F和Arduino开发,代码如下,记得改WIFI名字和密码。其他的单片机也是一样的,都是模拟遥控器关闭电机保护控制电机。这里用的是定时器,换成20ms循环delayMicroseconds( us );//微秒级延时函数电机控制会更平滑,这主要是analogWrite(pin,i)//i在0-255之间,高电平时间对应数字大小从低到高,对于1-2ms需要千分度的油门来说调节精度不够,但是如果想单片机控制无刷电机又要做其他事情,就只能用这个定时器了。
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
#define motor0 2 //GPIO2
const char ssid[] = "Redmi K40"; // your network SSID (name)
const char pass[] = "12345679"; // your network password
WiFiUDP Udp;
unsigned int localPort = 2380;
char incomingPacket[255];
float rd = 0;
int Data_length;
void setup()
{
Wire.begin();
Serial.begin(115200);
WiFi.begin(ssid, pass);
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
Serial.print(".");
}
Serial.println(WiFi.localIP());
Udp.begin(localPort);//启动UDP监听本地端口
pinMode(motor0, OUTPUT);
digitalWrite(motor0, LOW);
analogWrite(motor0, 13);
}
void loop()
{
Data_length = Udp.parsePacket(); //获取接收的数据的长度
if (Data_length) //如果有数据那么Data_length不为0,无数据Data_length为0
{
int len = Udp.read(incomingPacket, 255); //读取数据,将数据保存在数组incomingPacket中
if (len > 0) //为了避免获取的数据后面乱码做的判断
{
incomingPacket[len] = 0;
}
Udp.beginPacket(Udp.remoteIP(), Udp.remotePort()); //准备发送数据到目标IP和目标端口
Udp.print("Receive data:"); //将数据receive data:放入发送的缓冲区
if (len == 1) { rd = int(incomingPacket[0]) - 48; }//一位数控制速度
Udp.println(rd); //将接收到的数据放入发送的缓冲区
Udp.endPacket(); //向目标IP目标端口发送数据
}
analogWrite(motor0, 13+rd);//13-25,13解锁,25最大速度
}
白线接GPIO2,黑线接GND。接好线后,需要先在Arduino标签栏->工具->串口监视器,看串口管理器的回复IP。
然后打开NetAssist(串口调试助手),连接同一WiFi,选择UDP协议,随便使用一个本地主机端口,打开端口,在远程主机里输入你刚刚看到的回复IP:2380,并且发送一个数字看能否收到回复。
收到回复后,在窗口发送的数字就是可以调节的50Hz的PWM波高电平时间。
默认高电平时间是1ms,因为解锁BLHeli_S电调的电机保护就是高电平1ms。
上电单片机后,连接电调,当听到嘀、嘀、嘀(3S电池响3声短),然后滴(短),滴~(稍长的一声),电机解锁成功。在窗口输入个位数1-9,电机就可以进入转速工作模式,输入0停止。
如果需要精确控制,下面这里代码控制速度更加精确。
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
#define motor0 2 //GPIO2
const char ssid[] = "Redmi K40"; // your network SSID (name)
const char pass[] = "12345679"; // your network password
WiFiUDP Udp;
unsigned int localPort = 2380;
unsigned int sendport = 2390;
char incomingPacket[255];
float rd = 0;
int Data_length;
void setup()
{
Wire.begin();
Serial.begin(115200);
WiFi.begin(ssid, pass);
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
Serial.print(".");
}
Serial.println(WiFi.localIP());
Udp.begin(localPort);//启动UDP监听本地端口
pinMode(motor0, OUTPUT);
digitalWrite(motor0, LOW);
analogWrite(motor0, 13);
}
void loop()
{
Data_length = Udp.parsePacket(); //获取接收的数据的长度
if (Data_length) //如果有数据那么Data_length不为0,无数据Data_length为0
{
int len = Udp.read(incomingPacket, 255); //读取数据,将数据保存在数组incomingPacket中
if (len > 0) //为了避免获取的数据后面乱码做的判断
{
incomingPacket[len] = 0;
}
Udp.beginPacket(Udp.remoteIP(), Udp.remotePort()); //准备发送数据到目标IP和目标端口
Udp.print("Receive data:"); //将数据receive data:放入发送的缓冲区
if (len == 1) { rd = int(incomingPacket[0]) - 48; }//一位数控制速度
Udp.println(rd); //将接收到的数据放入发送的缓冲区
Udp.endPacket(); //向目标IP目标端口发送数据
}
delayMicroseconds(19000-rd*100);
digitalWrite(motor0,LOW);//管脚写入函数
delayMicroseconds(1000+rd*100);
digitalWrite(motor0,HIGH);//管脚写入函数
}
二、Keil使用BLHeli_S电调工程
多次尝试之后,发现就使用航模的电调和自己的工程完全不匹配,如果不想自己做无刷驱动,又想直接用上无刷驱动电调,那就只能编程了。
在网上也搜了关于BLHeli_S电调的Keil工程,但是发现资料很少,这里主要参考此博主的文章,然后说一下自己遇到的坑。
原文链接:https://blog.csdn.net/qq_41100189/article/details/119832506
按照博主的内容,去keil官网填一下几个空,就可以下载软件C51V961.EXE,在github下载BLHeli_S工程源代码,BLHeli_S /SiLabs文件夹里所有文件就是源代码。
- keil官网:https://www.keil.com/demo/eval/c51.htm
- BLHeli固件开源地址:https://github.com/bitdump/BLHeli.git
Github下载代码时,压缩包解压总提示不可预料的压缩末端,下多次也是一样,没办法,新建文件BLHeli_S.asm用记事本把网页上的4000行代码全部粘贴进去,效果是一样的。
我看了自己电调芯片型号为EFM8BB21F16G,然后数了电调上引脚数20,那就是和博主一样的EFM8BB21F16G-QFN20。
至于引脚方案怎么确定是哪个?我是看了电调引脚接线和芯片引脚图的,我的电调接线方案就是J_,估计大部分BLHeli_S电调都是。
keil新建工程并选择此芯片,只导入了BLHeli_S.asm,按照博主更改代码取消3处注释,这里代码已经有区别了。
ESCNO EQU J_
MCU_48MHZ EQU 2
FETON_DELAY EQU 50
一点编译,很多错误。
看了一下代码,Github的代码已经更新了,和原来博主下载到的代码不一致,而找Github历史版本又不确定是哪一版,没办法自己改最新版代码的报错,最后如下导入5个文件,下载不了就新建文件复制代码保存效果一致。
由于只需要用到J.inc的引脚定义,删除所有其他硬件类型判断,例如
IF ESCNO == A_
$include (A.inc) ; Select pinout A
ENDIF
然后就可以编译成功。
小祥酒馆: 我的就只会上电滴三声,无论什么pwm都没反应,不知道是不是电调坏了
CSDN-Ada助手: 非常感谢您的分享,这篇博客让我了解到了如何限制相机移动范围。您的经验和技巧对我来说非常有帮助。希望您能够继续创作,分享更多有关Unity的技巧和经验。如果可能的话,我认为您可以尝试写一些关于Unity中不同组件的使用和优化技巧的文章。谢谢您的分享! 如何快速涨粉,请看该博主的分享:https://hope-wisdom.blog.csdn.net/article/details/130544967?utm_source=csdn_ai_ada_blog_reply5
CSDN-Ada助手: 非常棒的博客!感谢您分享如何使用WinForm制作重复文件查找器,并且还能够遍历子文件夹。这对于那些需要及时清理电脑垃圾的人来说非常有用。除此之外,我想提供一些扩展知识和技能,比如如何在程序中实现文件的删除和移动,以及如何使用多线程来提高程序的效率。希望这些能够对您有所帮助。再次感谢您的分享! 如何写出更高质量的博客,请看该博主的分享:https://blog.csdn.net/lmy_520/article/details/128686434?utm_source=csdn_ai_ada_blog_reply2
CSDN-Ada助手: 恭喜您又完成了一篇有价值的博客,涉及到Unity和WinForm通信问题,对于开发者来说是非常实用的知识点。建议您可以在未来的文章中,多探究一些实用技巧,或者分享一些自己的开发经验,让读者们受益更多。加油! CSDN 会根据你创作的前四篇博客的质量,给予优秀的博主博客红包奖励。请关注 https://bbs.csdn.net/forums/csdnnews?typeId=116148&utm_source=csdn_ai_ada_blog_reply4 看奖励名单。
CSDN-Ada助手: 非常感谢您分享这篇关于WinForm制作文件传输助手的博客,您的经验和技巧对广大读者非常有帮助。祝贺您持续创作,不断提高自己的技能和知识水平。作为下一步的创作建议,或许您可以考虑分享一些更加高级的技术和实践经验,以便更多读者能够受益于您的经验。再次感谢您的分享! CSDN 正在通过评论红包奖励优秀博客,请看红包流:https://bbs.csdn.net/?type=4&header=0&utm_source=csdn_ai_ada_blog_reply3,我们会奖励持续创作和学习的博主,请看:https://bbs.csdn.net/forums/csdnnews?typeId=116148&utm_source=csdn_ai_ada_blog_reply3