4g/5g信号远程遥控小车解决方案二

之前写过一篇关于4g/5g信号来远程控制小车的博客, 解决方案是安卓手机+FT311D, 对安卓进行扩展, 好处就是我写安卓代码就能控制嵌入式设备来驱动小车, 相当于隐藏了底层交互, 直接面对安卓编程即可, 但是FT311D的管脚有限, 只有4路pwm输出能驱动2个电机马达(一个用于小车的转向舵机, 一个用于前进后退), 而且利用的是手机的摄像头进行图传, 手机的安装位置是固定的, 不能随意转动, 限制了图传的效果.

现在有了另一个解决方案, 依然是安卓手机+FT311D, 另外再加上PCA9685 16路pwm输出控制模块, 相当于把FT311D的管脚进行了扩展, 两个模块使用I2C通信, 这样依然能保证面向安卓编程, 同时还可以扩展多路pwm信号输出, 可以在小车上安装2轴云台支架, 配合SG90舵机, 再使用可编程摄像头模块进行图传(此处手机的摄像头可以用于辅助图传), 而且手机不仅可以为摄像头模块提供wifi热点, 还能利用其自身的其他传感器扩展很多功能.

购买的PCA9685模块和2轴云台舵机已经在路上了, 再次准备动手搞起来, 后续情况我会更新到这篇博客里, 喜欢的小伙伴可以关注.

当然, 其实还有其他解决方案, 比如用树莓派或者Jetson+4g/5g网卡等等, 需要大家自己来探索了~

模块已经到了, 简单研究了下, 先上图:

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAcGhvZW5peDNr,size_20,color_FFFFFF,t_70,g_se,x_16

        clientB手机连接ft311d, 而ft311d通过i2c与pca9685进行通信, pca9685连接了SG90双轴舵机, 上图中clientB手机运行的是FTDI官方 提供的的 I2C Android代码, 但是目前与pca9685通信有一些障碍, 每次向pca9685的寄存器中写入数据后就会卡死, 在阅读了ft311d官方Android源码后大概判断为每次写入数据的参数中有一项是停止传输的操作, 后续将修改源码后再进行测试, 感兴趣的小伙伴可以留意我博客的更新~

        最近瞎忙, 没抽出时间更新博客, 但是这段时间我还是学习和吸收了一些新知识, 对于RC小车又有了新的改造想法, 前面提到的用pca9685来扩展IO口的想法被我再次推翻, 我这次沿用的方案还是安卓手机连接ft311d来控制小车, 至于ft311d的IO接口有限无法实现摄像头旋转的问题我想到了一个更好的解决方案, 这次我并不是用pca9685来粗暴的扩展IO口, 而是用esp32开发板来解决旋转摄像头的问题, 这里感谢王铭东老师, 他的视频给我的灵感的来源!!!

        简单介绍一下esp32开发板, 价格便宜二十几块钱, 牛逼之处是带板载wifi和蓝牙, 惊不惊喜, 意不意外?! 二十几块钱你还要啥自行车! 而且这块板子可以基于MicroPython来编程, 至于如何烧入使用这块板子我推荐各位小伙伴看下B站王铭东老师的esp32的视频, 非常不错, 这里我就不再赘述了.

        换句话说, 控制摄像头转动是独立一个小系统, 和之前已有的ft311d没有任何关系. esp32这块开发板我使用tcp协议与服务器通信, 当clientA发送控制摄像头转动的命令后, 直接控制esp32, esp32上连接着两轴舵机, 在esp32上使用的MiroPython编程, 可以非常轻松的控制舵机各角度的转动, 服务器端依然使用的是Nodejs, 在原有的基础上增加了tcp通信的部分, 因为esp32里不能使用socketIO, 所以转发控制命令就是用最原始的tcp通信, 先上一段服务器端新增的代码片段:

        

const app = require('express')();
const server = require('http').Server(app);
const io = require('socket.io')(server);

const net = require('net');
const HOST = 'xxx.xxx.xxx.xxx'; // 自己的服务器ip地址
const PORT = 7799; // 自己服务器的端口, 记得服务器防火墙要开放

// 统计连接客户端的个数
var count = 0;

// 创建slave_server服务
const slave_server = new net.createServer();
slave_server.setEncoding = 'UTF-8';

// 获得一个连接,该链接自动关联scoket对象
var tcp_sock = null;
slave_server.on('connection', sock => {
  tcp_sock = sock;
  sock.name = ++count
  console.log(`当前连接客户端数:${count}`);

  // 接收client发来的信息  
  sock.on('data', data => {
    console.log(`客户端${sock.name}发来一个信息:${data}`);

    // 回发该数据,客户端将收到来自服务端的数据
    sock.write(`服务端收到了你发送的一条信息:${data}`);
  });

  // 为socket添加error事件处理函数
  sock.on('error', error => { //监听客户端异常
    console.log('error' + error);
    sock.end();
  });

  // 服务器关闭时触发,如果存在连接,这个事件不会被触发,直到所有的连接关闭
  sock.on('close', () => {
    console.log(`客户端${sock.name}下线了`);
    count -= 1;
  });
})

// listen函数开始监听指定端口
slave_server.listen(PORT, HOST, () => {
  console.log(`服务器已启动,运行在:http://${HOST}:${PORT}`);
});

// 创建master_server
io.on("connection", (socket) => {
  console.log("来了一个人  " + socket.id + "-" + socket.request.connection.remoteAddress);

  // 监听客户端离线事件
  socket.on("disconnect", () => {
    console.log("对方下线了" + socket.id);
  });

  // 监听master发送的cmd命令
  socket.on('cmd', function(msg) {
    if (msg == "A:up") {
      console.log("up");

      // 需要向slave发送up控制指令
      if (tcp_sock != null) {
        tcp_sock.write('0');
      }
    }
    if (msg == "A:back") {
      console.log("back");

      // 需要向slave发送back控制指令
      if (tcp_sock != null) {
        tcp_sock.write('1');
      }
    }
    if (msg == "A:left") {
      console.log("left");

      // 需要向slave发送left控制指令
      if (tcp_sock != null) {
        tcp_sock.write('2');
      }
    }
    if (msg == "A:right") {
      console.log("right");

      // 需要向slave发送right控制指令
      if (tcp_sock != null) {
        tcp_sock.write('3');
      }
    }
    if (msg == "A:stop") {
      console.log("stop");
      
      // 需要向slave发送stop控制指令
      if (tcp_sock != null) {
        tcp_sock.write('4');
      }
    }
  });
});

server.listen(6666);

猜你喜欢

转载自blog.csdn.net/phoenix3k/article/details/123174974
今日推荐