云台由两个无刷电机分别控制摄像头的 yaw,pitch。
无刷电机由SimpleFOC库驱动,由esp32作为控制器,drv8313为无刷电机驱动器最大输出电流2.5a,对于云台电机已经足够了。
下面是驱动板的原理图,可以驱动两个云台电机,板载了一个5v-5a线性稳压芯片 可以给外部设备供电
无刷电机需要位置反馈,这里使用了as5600磁编码器,下面是原理图
simplefoc基于arduino环境,vscode安装platformlo插件,然后board选择 espressif esp32 dev module,framework选择 arduino就可以自动下载arduino环境了。然后在libraries中选择simplefoc就可以自动下载了。自带了各种实例由于使用了arduino框架,所以使用非常的简单
。官网地址/
下面代码可以控制一个电机且通过串口对电机进行控制
#include <SimpleFOC.h>MagneticSensorI2C sensor = MagneticSensorI2C(AS5600_I2C);
TwoWire I2Cone = TwoWire(0);
BLDCMotor motor = BLDCMotor(7); //根据选用电机的极对数,修改此处BLDCMotor()的值
BLDCDriver3PWM driver = BLDCDriver3PWM(32, 33, 25, 22);//修改pwm接口
Commander commander = Commander(Serial);void onMotion(char* cmd){ ion(&motor,cmd); }
void onMotor(char* cmd){ (&motor,cmd); }void setup(){Serial.begin(115200);I2Cone.begin(19, 18, 400000); sensor.init(&I2Cone);//修改i2c口motor.linkSensor(&sensor);driver.voltage_power_supply = 12;//电机供电电压这里是12vdriver.init();motor.linkDriver(&driver);motor.foc_modulation = FOCModulationType::ller = MotionControlType::angle;//闭环角度控制/控制参数/// motor.PID_velocity.P = 0.05;//每个电机的pid参数不同,需要自己修改 motor.PID_velocity.I = 1;motor.P_angle.P = 10;motor.voltage_limit = 1.5; motor.LPF_velocity.Tf = 0.01;motor.velocity_limit = 20;motor.init();motor.initFOC();///打印参数//itor_variables = _MON_TARGET | _MON_VEL | _MON_ANGLE; itor_downsample = 1000;//1s打印一次可以修改单位msmotor.useMonitoring(Serial);commander.add('T',onMotion,"motion control");commander.add('M',onMotor,"full motor config");
}void loop(){motor.loopFOC();itor();ve();commander.run();
}
不同的电机pid参数不同,使用串口命令修改参数,下图是命令的格式
比较常用的一些命令
D - D current PID controller & LPF (see pid and lpf for commands)
V - Velocity PID controller & LPF (see pid and lpf for commands)
A - Angle PID controller & LPF- (see pid and lpf for commands)
S - Sensor offsets
M - sensor offset
E - sensor electrical zero
M - Monitoring control
D - downsample monitoring
C - clear monitor
S - set monitoring variables
G - get variable value
C - Motion control type config - see motion control
D - downsample motion loop
0 - torque
1 - velocity
2 - angle
3 - velocity_openloop
4 - angle_openloop
E - Motor status (enable/disable) - see motion control
0 - enable
1 - disable
MMG0 get variable - target
MMG6 get variable - angle
普通的图传在低空或者有遮挡的情况下性能会变得非常差,依靠4g网络就可以解决这个问题。
现在手机的4g5g网络都支持ipv6,开启热点后连接它的设备也都会分配ipv6地址,并且这个地址是公网可以访问的,这个地址不是固定的,重启网络就会变
当然也可以淘宝购买4g模块,就可以将设备联网了
使用ifconfig查看本机ipv6地址,ipv6地址是冒分十六进制表示法,格式如“ABCD:CCDD:…”一共128位
电信网络ipv6是240e开头的,移动是2409开头的,联通是2408开头的。将这个地址记录下来,可以使用ping命令看看网络是否连通。
这里用EC600S模块为数据的发送端和接收端
首先安装驱动
uname -r #查看内核版本安装相近的驱动
cd v5.6.11 #进入驱动目录
sudo make
sudo make install
报错了,需要安装头文件可以参考
安装好linux头文件就可以顺利安装了,安装号后需要重启
此时在/dev中将会多ttyUSB0 ttyUSB1 ttyUSB2设备
使用minicom打开usb1
sudo apt-get install minicom
minicom -D /dev/ttyUSB1
为了使用方便先设置串口的设置
将模块插到usb口查看USB端口信息,使用KERNELS作为标识
udevadm info --attribute-walk --name=/dev/ttyUSB1 |grep KERNELSKERNELS=="ttyUSB1"KERNELS=="2-1:1.3"KERNELS=="2-1"KERNELS=="usb2"KERNELS=="fc880000.usb"KERNELS=="platform"
创建映射文件
sudo vim /etc/udev/rules.d/×××.rules
在新建的*.rules文件中添加刚刚获取的设备id
KERNEL=="ttyUSB*", KERNELS=="2-1:1.3", MODE:="0777", SYMLINK+="my_network"
重启生效,可以查看创建成功了
ll /dev/ | grep ttyUS*
lrwxrwxrwx 1 root root 7 Sep 5 15:38 myNetwork -> ttyUSB1
sudo minicom -s
在Serial port setup设置 Serial Device 为/dev/my_network,然后Save setup as dfl 就可以了
按ctrl+a q就能退出minicom了
使用at指令创建sock,依靠UDP传输数据
at指令可以参考官方的手册Quectel_EC200x&EG912Y&EC600S系列_TCP(IP)_应用指导_V1.2
下面的python代码可以把两块EC600S模块设置为udp的服务端与客户端,并互发消息
服务端
import serial
import time
import threadingclass UDPOperate:def __init__(self):self.uartAT = serial.Serial(port='/dev/ttyUSB1', baudrate=115200,timeout=5)self.initSock()self.radioIp = Noneself.radioPort = '1081adDate = ''readThread = threading.Thread(targetad)readThread.start()while True:self.write('hello')time.sleep(2)def read(self):while True:rec = adline().decode().strip()if rec:if rec.startswith('+'): #获取从机ip格式+QIACT: 1,1,3,"10.122.217.145","240E:440:100C:9D5:177C:665F:1D69:E883"temp = rec.split() ip = temp[1].split(',')[3] self.radioIp = ip.strip('"')if not (rec.startswith('SEND') or rec.startswith('>') or rec.startswith('+')):#乎略adDate = recprint('read: ',adDate)def write(self,data):if not self.radioIp is None:l = len(data)cmd = 'AT+QISEND=0,' + str(l) + ',' + self.radioIp + ',' + self.radioPort + 'rn'self.uartAT.de())time.sleep(0.005)self.uartAT.de())else:print('now do not rec target ip ')def initSock(self):print('now ')time.sleep(1)cmd0 = b'ATE1rn'#显示回显cmd1 = b'AT+QICLOSE=0rn' #关闭存在的sockcmd2 = b'AT+QIOPEN=1,0,"UDP SERVICE",":::1",0,1080,1rn'cmd3 = b'AT+QIACT?rn'#获取ipcmd4 = b'ATE0rn' #关闭回显self.sendCmd(cmd0)self.sendCmd(cmd1)self.sendCmd(cmd2)self.sendCmd(cmd3)self.sendCmd(cmd4)def sendCmd(self,cmd):self.uartAT.write(cmd)rec = ad_until(b'OK').decode().strip()time.sleep(0.3)print(rec)
udp = UDPOperate()
客户端
import serial
import time
import threading
# AT+CSQ
# 是查询信号的,如果注册网络成功,会有信号产生,最大 31,如果信号小于 10,说明当前网络信号不佳
# AT+CGATT?
# 是查询注册网络情况,如果注册成功,会返回 1,如果失败,返回 0
class UDPOperate:def __init__(self):adDate = ''self.serialIP = '240E:440:100C:9D5:177C:665F:1D69:E883'self.uartAT = serial.Serial(port='/dev/ttyUSB1', baudrate=115200,timeout=5)self.initSock()readThread = threading.Thread(targetad)readThread.start()cnt = 0while True:cnt = cnt+1self.write('a' + str(cnt))time.sleep(2)def read(self):while True:rec = adline().decode().strip()if rec:if not (rec.startswith('SEND') or rec.startswith('>')):if not rec.startswith('+'):adDate = recprint('rec',adDate)def write(self,data):l = len(data)cmd = 'AT+QISEND=0,' + str(l) + 'rn'self.uartAT.de())time.sleep(0.005)self.uartAT.de())def initSock(self):print('now ')time.sleep(1)cmd0 = b'ATE1rn'#显示回显cmd1 = b'AT+QICLOSE=0rn' #关闭存在的sockcmd2 = 'AT+QIOPEN=1,0,"UDP",' + self.serialIP + ',1080,1081,1rn'cmd3 = b'AT+QIACT?rn'#获取ipcmd4 = b'ATE0rn' #关闭回显self.sendCmd(cmd0)self.sendCmd(cmd1)self.de())self.sendCmd(cmd3)self.sendCmd(cmd4)def sendCmd(self,cmd):self.uartAT.write(cmd)rec = ad_until(b'OK').decode().strip()time.sleep(0.3)print(rec)
udp = UDPOperate()
下面就可以依靠udp来做更加有意义的事情了
gst-launch-1.0 v4l2src device=/dev/video10 ! video/x-raw,width=640,height=480,framerate=30/1 ! x264enc speed-preset=1 tune=zerolatency ! udpsink host=240e:440:1002:17db:39f2:c71f:6eb2:7f36 port=4951
如果有硬件编码器可以修改一下
gst-launch-1.0 v4l2src device=/dev/video0 ! video/x-raw,width=640,height=480,framerate=30/1 ! mpph264enc ! queue ! udpsink host=240e:440:1002:17db:39f2:c71f:6eb2:7f36 port=4951
接收端用mpv播放器
mpv -v --geometry=115:0 --no-border --profile=low-latency --untimed udp://[::1]:4951
可以显示实时画面,几乎看不到延迟。当然这个视网络情况有差异。
这样使用4g模块和simpleFOC库就搭建好了低成本的图数传,并且在4g网络覆盖的区域无限距离传输。
本文发布于:2024-02-02 17:53:35,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/170686761345455.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |