鱼香ROS社区
    • 版块
    • 最新
    • 未解决
    • 已解决
    • 群组
    • 注册
    • 登录
    紧急通知:禁止一切关于政治&VPN翻墙等话题,发现相关帖子会立马删除封号
    提问前必看的发帖注意事项: 社区问答规则(小鱼个人)更新 | 高质量帖子发布指南

    ROS 2机器人自动回充之红外法(附源码原理图)

    已定时 已固定 已锁定 已移动
    文档资料
    noreplay ros2 回充 机器人
    1
    1
    436
    正在加载更多帖子
    • 从旧到新
    • 从新到旧
    • 最多赞同
    回复
    • 在新帖中回复
    登录后回复
    此主题已被删除。只有拥有主题管理权限的用户可以查看。
    • 小鱼小
      小鱼 技术大佬
      最后由 小鱼 编辑

      ROS 2机器人自动回充之红外法(附源码原理图)

      前言

      大家好,我是爱学习的小鱼,今天接着昨天的回充,不过今天使用的是红外回充方法。红外方法比较简单,其原理就像遥控器和空调之间的关系一样,机器人类似于空调,装有两个接收头,机器人充电桩上则装有两个红外发射灯,两个灯会发送不同的波,通过接收到的波的信号不同,则可以区分出充电桩的位置。我手拙花了个简单示意图。

      2e26d539-42f7-473e-91eb-59a46760bab2-image.png

      只有机器人上的接收头朝向充电桩的时候,两个接收头才能分别都接收到两个发射头的信号,否则根据情况旋转机器人朝向充电桩即可。

      1. 发射与接收电路设计

      发射和接收电路设计如下:

      • 发射端:两个红外发射灯,分别连接到微控制器的两个输出引脚。

      5e7afc7d-99d8-4320-a792-9e9333686efe-image.png

      • 接收端:两个红外接收头,分别连接到微控制器的输入引脚。

      7b455091-ea82-4e1f-beec-47c9e964928f-image.png

      2. 发射代码

      下面是用于控制红外发射灯的Arduino代码。它通过定时器中断产生两个不同宽度的红外信号。

      #include <Arduino.h>
      
      #define IR1IO 18
      #define IR2IO 19
      
      hw_timer_t * timer = NULL;  // 声明一个定时器
      #define digitalToggle(x) digitalWrite(x, !digitalRead(x))
      
      bool openir1 = false;
      bool openir2 = false;
      
      void IRAM_ATTR onTimer() {  // 中断函数
        if(openir1){
          digitalToggle(IR1IO);
        }
        if(openir2){
          digitalToggle(IR2IO);
        }
      }
      
      void setup() {
        Serial.begin(115200);
        Serial.println("loop----------------------------------------");
        timer = timerBegin(0, 80, true);                // 初始化
        timerAttachInterrupt(timer, &onTimer, true);    // 调用中断函数
        timerAlarmWrite(timer, 13, true);               // 设置定时器报警
        timerAlarmEnable(timer);                        // 定时器使能
        pinMode(IR1IO, OUTPUT); // 18
        pinMode(IR2IO, OUTPUT); // 19
      }
      
      void loop() {
        openir1 = true;
        delay(7);
        openir1 = false;
        delay(25);
        openir1 = true;
        delay(1);
        openir1 = false;
        delay(67);
      
        openir2 = true;
        delay(7);
        openir2 = false;
        delay(36);
        openir2 = true;
        delay(1);
        openir2 = false;
        delay(56);
      }
      

      3. 接收代码

      下面是用于接收和处理红外信号的Arduino代码。它通过检测红外信号的脉冲宽度来判断信号的来源。

      struct IRData {
        uint8_t d0 : 1;
        uint8_t d1 : 1; // A
        uint8_t d2 : 1; // B
        uint8_t d3 : 1;
        uint8_t d4 : 1;
        uint8_t d5 : 1; // A
        uint8_t d6 : 1; // B
        uint8_t d7 : 1;
      } __attribute__((packed));
      
      struct IRData irdata;
      
      uint16_t ir1_low_tick;
      uint16_t ir1_low_tickf7;
      bool ir1recv7ms = false;
      uint16_t ir1_last25;
      uint16_t ir1_last36;
      
      uint16_t ir2_low_tick;
      uint16_t ir2_low_tickf7;
      bool ir2recv7ms = false;
      uint16_t ir2_last25;
      uint16_t ir2_last36;
      
      void IRAM_ATTR onTimer() {  // 中断函数
        ir1_last25++;
        ir1_last36++;
        ir2_last25++;
        ir2_last36++;
      
        if (digitalRead(IR1IO) == 1) {
          ir1_low_tick = 0;
          ir1_low_tickf7 += 1;
        } else {
          if (ir1recv7ms) {
            ir1recv7ms = 0;
            if (ir1_low_tickf7 == 25) {
              irdata.d2 = 1;
              ir1_last25 = 0;
            } else if (ir1_low_tickf7 == 36) {
              irdata.d1 = 1;
              ir1_last36 = 0;
            }
          }
          ir1_low_tick += 1;
        }
        if (ir1_low_tick == 7) {
          ir1recv7ms = true;
          ir1_low_tickf7 = 0;
        }
        if (ir1_last25 > 400) {
          irdata.d2 = 0;
        }
        if (ir1_last36 > 400) {
          irdata.d1 = 0;
        }
      
        if (digitalRead(IR2IO) == 1) {
          ir2_low_tick = 0;
          ir2_low_tickf7 += 1;
        } else {
          if (ir2recv7ms) {
            ir2recv7ms = 0;
            if (ir2_low_tickf7 == 25) {
              irdata.d6 = 1;
              ir2_last25 = 0;
            } else if (ir2_low_tickf7 == 36) {
              irdata.d5 = 1;
              ir2_last36 = 0;
            }
          }
          ir2_low_tick += 1;
        }
        if (ir2_low_tick == 7) {
          ir2recv7ms = true;
          ir2_low_tickf7 = 0;
        }
        if (ir2_last25 > 400) {
          irdata.d6 = 0;
        }
        if (ir2_last36 > 400) {
          irdata.d5 = 0;
        }
      }
      

      总结

      通过以上的设计和代码实现,我们可以通过红外线实现机器人自动回充。这个方法的原理和实现都相对简单,但实际应用时需要根据环境进行调试和优化,希望这篇文章能对大家有所帮助。如果有任何问题或者建议,欢迎在评论区留言,我们一起探讨学习。

      新书配套视频:https://www.bilibili.com/video/BV1GW42197Ck/

      1 条回复 最后回复 回复 引用 0
      • 第一个帖子
        最后一个帖子
      皖ICP备16016415号-7
      Powered by NodeBB | 鱼香ROS