切换到宽版
左右分栏
统计
基本信息
到访IP统计
管理团队
管理统计
在线会员
会员排行
版块排行
帖子排行
标签排行
帮助
日志
群组
热榜
分享
记录
用户名
密 码
记住登录
登录
找回密码
注册
快捷通道
关闭
您还没有登录,快捷通道只有在登录后才能使用。
立即登录
还没有帐号? 赶紧
注册一个
论坛
群组
火腿广场
手机客户端
帖子
用户
版块
帖子
搜索
PHPWIND
HELLOCQ
哈罗CQ火腿社区
>
卫星和空间通信
>
Re:从零开始的基于 ESP32 开发步进云台解码版
发帖
回复
返回列表
新帖
651
阅读
3
回复
Re:从零开始的基于 ESP32 开发步进云台解码版
[复制链接]
上一主题
下一主题
离线
叶浩轩
UID:453794
注册时间
2022-12-22
最后登录
2025-06-08
在线时间
5小时
发帖
36
搜Ta的帖子
精华
0
访问TA的空间
加好友
用道具
注册用户
关闭
个人中心可以申请新版勋章哦
立即申请
知道了
发帖
36
加关注
发消息
只看楼主
倒序阅读
0楼
发表于: 04-18
Re
:从零开始的基于
ESP32
开发步进云台解码版
本文约
2600字,撰写用时120分钟。
特别鸣谢:
BI6OPR
提供的思路与原始程序
本文遵循
CC BY-NC-SA 4.0
协议,保留著名权。
正文开始!
前言
笔者在筹建自己的射电天文望远镜,抛物面准备好了,但是发现旋转器真的贵得离谱。比如
Yaesu的G5500,一个就要到大几千,实在破不起这费。在圈内一些大佬的指引下,发现了一款解码板被拆了的重载步进云台,了解到BI6OPR大佬已经初步将其适配了Pelco-D协议,但是还不是很完善。笔者对编程略知一二,按照大佬和网上的资料摸爬滚打,终于在BI6OPR提供的原始程序的基础上做出了比较满意的Pelco-D解码。著此文章来分享一些我的拙见,希望可以给各位朋友提供一些这方面的思路。
硬件方面
笔者
考虑到自己的技术能力
,最终放弃
STM32而是选择了更加适合于物联网IoT的ESP32系列芯片。基本思路是通过ESP32芯片的IO引脚对云台进行方向控制以及PWM调速,使用ESP32芯片的TTL串口于电脑建立通讯,接收转向命令,并发送转向状态给电脑端。步进电机驱动器使用了24V交流大功率驱动板。
注:本文章主要分享固件代码部分,关于硬件部分请移步至
Github。
代码实现
由于使用了
ESP32系列芯片,在MicroPython和C++中选择了C++进行开发
(当然不是因为新版
Pycharm不兼容MicroPython而抛弃的它)
。
IDE采用了我们亲爱的VS
Code,搭配PlatformIO,开发起来还是比较舒服的。
我们现在代码开头引入
Arduino库,以便后续调用:
#include <Arduino.h>
ESP32是单片机,依靠循环来完成相应代码任务,即为循环loop()函数中的代码。基本思路是不断循环读取串口的数据,若读到相应命令,则进行转向控制后继续读取串口数据,若串口发来停止转动指令,或新的指令,则执行新的指令。
首先,让我们在
setup()函数中对单片机启动时进行初始化。
配置波特率为
9600
串口:
Serial.begin(9600);
初始化板载
LED
指示灯以及对于控制步进电机控制板的相关
IO
引脚:
//
设置
IO
输入输出
const int AZ_DIRECTION_PIN = 26;
const int EL_DIRECTION_PIN = 27;
pinMode(LED_MSG_PIN, OUTPUT);
pinMode(AZ_DIRECTION_PIN, OUTPUT);
pinMode(EL_DIRECTION_PIN, OUTPUT);
pinMode(AZ_SPEED_PUL_PIN, OUTPUT);
pinMode(EL_SPEED_PUL_PIN, OUTPUT);
//
初始化信号灯
digitalWrite(LED_MSG_PIN, LOW);
初始化用于控制云台转速的硬件级
PWM
输出端口:
const int PWM_FREQ = 10000; // PWM
频率(单位:
Hz
)
const int PWM_RESOLUTION = 8; //
分辨率(
8
位时,占空比范围
0-255
)
const int AZ_SPEED_PUL_PIN = 25;
const int EL_SPEED_PUL_PIN = 14;
ledcSetup(0 , PWM_FREQ, 8);
ledcAttachPin(AZ_SPEED_PUL_PIN, 0);
ledcSetup(1 , PWM_FREQ, 8);
ledcAttachPin(EL_SPEED_PUL_PIN, 1);
数据的读取:
在
setup()初始化完一切需要用到的东西后,我们就可以进行对串口发来的Pelco-D命令进行接收。
我们定义一个新的函数,名为
readSerialData()
,用于读取串口数据。
参阅
Pelco-D的开发手册,注意到标准Pelco-D消息由7个字节的16进制数据组成,其中要用到的是两个数据位以及最后一个校验位。
我们先用代码读取
7个字节的数据:
int rlen = Serial.readBytes(buf, 7);
然后利用校验位校验数据是否正确,若正确再做下一步拆解处理:
if (rlen == 7 && buf[0] == 0xFF && buf[1] == 0x01)
为了同一个数据被进行多次解析执行,还要添加判断数据是否于上一次读取到的不同,若不同,再执行。如果这个判读不做会出现转动一卡一卡的问题:
if (command != currentCommand) //
只有在接收到新的命令时才处理
{
handlePelcoDCommand(command);
currentCommand = command; //
更新当前命令
}
至此数据的读取与拆解完毕。
数据的执行:
我们定义一个函数
handlePelcoDCommand(int command)
用于解析读取的数据并进行对步进电机驱动板的控制。
其中传入的
int类型command变量是上文中分解到的最终控制命令,Pelco-D协议的基本转向命令分为停止、上、下、左、右,分别对应数据0、2、4、8、16,当然还有左上、右下之类的,这里不过多赘述。
我们先创建一个索引(其实官方名称我不确定是不是这个,
叫习惯了
)
switch (command)
,将所有命令放入这个索引中。
接下来我们以右转为例,首先右转对应的命令位
2,我们在索引中写入:
case 2:
这代表当传入的
command变量为2时执行接下来的代码块。
然后我们将控制水平的
Az驱动电机的引脚设置为高电平:
digitalWrite(AZ_DIRECTION_PIN, HIGH);
并设置
PWM调速命令执行的bool值为True:
is_azcontrol_stepper = true;
只有这样电机才会知道要按照什么速度转动,以上二者缺一不可。
这个
bool变量在下一章的PWM调速中会提及。
于是控制右转的完整代码块为:
case 2: //
右转
digitalWrite(AZ_DIRECTION_PIN, HIGH);
is_azcontrol_stepper = true;
Serial.println("0002.");
其中
Serial.println("0002.");
为向串口输出调试数据,用于程序的调试,可忽略不写。
loop()
函数以及
PWM
调速:
我们在上文提及,
ESP32系列芯片是在循环某个代码块以达到相应目的。
我们想让上面的函数执行起来,必须将他们加入至
loop()函数中
(
setup()函数除外)
,否则他们不会被执行。
我们在主程序中创建
loop()函数:
void loop()
{
....
这里放你的代码或函数
....
}
首先将我们上文写到的读取串口数据函数丢进去:
readSerialData();
然后要判断上文的
PWM调速的bool变量是否为True,如果为True,则启动PWM调速(这里可以另开一个函数,
我懒就直接丢
loop()里了
)
:
if (is_azcontrol_stepper)
{
ledcWrite(0, 128);
}
if (is_azcontrol_stepper == false)
{
ledcWrite(0, 0);
}
垂直方向的
El电机同理。
解释一下
ledcWrite(int
a, int b);
这条调用。其中
int
a代表了PWM输出通道,在前文setup()函数中我们将0通道指向了25号IO引脚,所以他就会在25号引脚输出方波PWM信号;int
b代表了输出信号的频率,通过调整这个变量可以调控相应电机的转动速度,0则为停止。
最后在
loop()里放入通过串口发送当前运行状态的函数:
printStatus();
这个函数下一章会详细阐述。
为了让这个函数不阻塞串口以及程序,我们对他加上一个定时器,定时执行:
if (currentMillis - previousMillis >= interval)
{
previousMillis = currentMillis;
printStatus();
}
状态回传函数:
为了在电脑端可以顺利了解云台运动状态,我们可以通过串口回传云台的相关状态。
我们定义一个
printStatus();
函数,用于存放状态回传的代码块。
其中代码就是将目前状态通过串口打印,不过多赘述:
Serial.print("Current Status - AZ Direction: ");
Serial.print(az_stepper_direction ? "Forward" : "Backward");
Serial.print(", EL Direction: ");
Serial.print(el_stepper_direction ? "Forward" : "Backward");
Serial.print(", AZ Control: ");
Serial.print(is_azcontrol_stepper ? "On" : "Off");
Serial.print(", EL Control: ");
Serial.println(is_elcontrol_stepper ? "On" : "Off");
具体包含了当前云台是否转动以及转向方向。
更进一步:
WIFI
控制
为了适配
DTrac等安卓APP,也为了更方便的控制,我们可以将从串口读取数据改为从网络通过TCP协议读取数据。由于ESP32模块自带WiFi,故不需要加装其他硬件便可实现。
因为要调用
WiFi模块,我们需要在代码开头导入WIFI库,以便后续调用:
#include <WiFi.h>
接下来要配置
WiFi接入点信息,在代码头部配置,不要放入函数中:
const char* ssid =
"
你的
WiFi
名
";
const char* password =
"
你的
WiFi
密码
";
对于
TCP协议,需要定义一个端口来通讯。我们使用80端口,在代码头部配置:
const int serverPort = 80;
接下来设置
TCP模块为服务器模式,在代码头部配置:
WiFiServer server(serverPort);
WiFiClient client;
接下来要在
setup()函数中初始化WiFi并进行连接操作:
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting to WiFi...");
}
Serial.println("Connected to WiFi");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
其中
Serial.println(WiFi.localIP());
语句会在串口输出
ESP32开发板的IP地址,也可以前往路由器后台获取。
接下来还是在
setup()函数中,启动TCP服务器:
server.begin();
Serial.println("TCP Server started");
由于我们已经不用串口读取数据,而是改为
WiFi读取,所以要将原来的
readSerialData()
函数改为
readWifiData()
函数,函数内代码如下,不过多赘述:
if (!client) { //
如果没有活跃的客户端
client = server.available(); //
检查新连接
if (client) {
Serial.println("New client connected");
}
} else { //
处理已连接的客户端
if (client.connected() && client.available() >= 7) {
int rlen = client.readBytes(buf, 7);
if (rlen == 7 && buf[0] == 0xFF && buf[1] == 0x01 && buf[3] != 0x53 && buf[3] != 0x51) {
int command = buf[3];
if (command != currentCommand) {
handlePelcoDCommand(command);
currentCommand = command;
}
这样就能成功从网络读取到
Pelco-D命令。
后记
感谢各位的阅读,本文在我的
个人博客
中发布,并搬运至各大论坛。若有不妥之处,请及时联系。笔者技术力有限,若有错误,敬请谅解。若喜欢这个项目,麻烦
Star~若有疑问,请前往Github创建issue。
共
条评分
回复
举报
分享到
淘江湖
新浪
QQ微博
QQ空间
开心
人人
豆瓣
网易微博
百度
鲜果
白社会
飞信
离线
bd4um
UID:367677
注册时间
2012-08-11
最后登录
2025-04-26
在线时间
429小时
发帖
160
搜Ta的帖子
精华
0
访问TA的空间
加好友
用道具
注册用户
发帖
160
加关注
发消息
只看该作者
1楼
发表于: 04-19
好资料,感谢分享,收藏学习!
共
条评分
DE BD4UM
回复
举报
离线
bg8st
UID:43553
注册时间
2007-05-29
最后登录
2025-06-16
在线时间
541小时
发帖
123
搜Ta的帖子
精华
0
访问TA的空间
加好友
用道具
注册用户
发帖
123
加关注
发消息
只看该作者
2楼
发表于: 05-07
楼主厉害,持续关注
共
条评分
回复
举报
离线
BH3NEK
UID:43885
注册时间
2007-06-08
最后登录
2025-05-21
在线时间
2410小时
发帖
1518
搜Ta的帖子
精华
0
访问TA的空间
加好友
用道具
注册用户
发帖
1518
加关注
发消息
只看该作者
3楼
发表于: 05-07
楼主厉害,持续关注
共
条评分
呼号:BH3NEK
直频:145.100MHz
中继: 439.125MHz-8 亚音103.5
147.925MHz-3.8 无亚音
APRS:144.640MHz
承德ham微信号:CDHAM01
QTH:河北承德开发区
回复
举报
发帖
回复
返回列表
https://www.hellocq.net/forum
访问内容超出本站范围,不能确定是否安全
继续访问
取消访问
隐藏
快速跳转
火腿资讯区
中国QSL卡片管理局
公告通知
各地火腿活动专题
火腿交流区
火腿神聊
新手培训班
莫尔斯电码 - CW
QSL卡展板
火腿技术区
DX通信
QRP and DIY
设备
天线和铁塔
V/UHF和移动通信
卫星和空间通信
APRS专题
业余无线电应急通信
火腿资源区
FlexRadio SDR收发机
现代通信
业余无线电器材信息
EchoLink/IRLP/远程电台及其他VoIP技术专区
火腿文化
ARDF - 业余无线电测向
计算机应用及数码产品
《电子制作》杂志
邻家火腿快讯
单片机与自动控制
HAM软件、HAM网站
业余无线电中文计划
HELLOCQ火腿社区版务工作室
关闭
关闭
选中
1
篇
全选