搜索代码

第29/31课:汽车-7 使用遥控器控制SunFounder智能车 | Robojax

第29/31课:汽车-7 使用遥控器控制SunFounder智能车 | Robojax

在本课中,我们将使用红外(IR)遥控器将您的SunFounder智能车改装为一辆遥控车辆。您将学习如何将标准红外遥控器上的按键映射到车辆的运动控制——前进、后退、转向,甚至斜向移动——以及实时调整其速度,而不是依赖有线连接或智能手机应用。本项目是在学习电机控制和红外通信基础知识后的完美下一步,因为它将两者结合到一个交互式系统中。

这里的实际价值在于理解如何为机器人平台创建稳健、用户友好的控制界面。您将学到的原理可直接应用于各种项目,例如:

  • 为家庭自动化任务构建遥控机器人,例如小型送货机器人。
  • 为教育机器人竞赛创建可编程车辆。
  • 为相机滑轨或云台机构开发自定义遥控器。
  • 为更大、更复杂的自动化系统原型设计用户界面。

硬件与组件

本项目基于SunFounder 3合1 Arduino套件。要跟随操作,您需要以下列出的组件。接线很简单,从课程之前的课程中延伸而来。

  • SunFounder 3合1 Arduino套件:包括智能车底盘、电机驱动板和Arduino板。
  • 红外遥控器:套件附带的标配遥控器。
  • 红外接收模块:用于解码遥控器信号的传感器。
  • LED和330欧姆电阻:用作视觉指示器,以确认按键已被按下。(视频中04:08处)
  • 跳线:用于在面包板上进行必要的连接。

接线指南

car_9_lesson_29_wriing_for_IR

在深入代码之前,让我们确保硬件连接正确。红外接收器和电机驱动器的接线与本系列前几课保持一致。为了使项目更具交互性,我们还将一个外部LED连接到引脚13作为视觉反馈指示器。

以下是连接的分步指南:

  1. 红外接收器:红外接收器有三个引脚。正极引脚连接到面包板上的5V电源轨。接地引脚连接到GND电源轨。信号引脚(即最后一个引脚)连接到Arduino板上的数字引脚11。(视频中05:29处)
  2. 外部LED:将330欧姆电阻的一端连接到Arduino上的数字引脚13。将电阻的另一端连接到LED的较长(阳极)引脚。LED的较短(阴极)引脚应连接到面包板上的GND电源轨。(视频中04:08处)
  3. 电机驱动器:电机驱动器的四个引脚(A_1B、A_1A、B_1B、B_1A)分别连接到Arduino上的引脚5、6、9和10。此设置已在之前的课程中介绍过。(视频中06:44处)

有关这些连接的视觉参考,请参阅下面的接线图。

代码解释

此项目的代码设计为直观易懂。它使用IRremote库来处理解码红外信号的复杂任务。让我们分解您可能希望为自己的项目调整的用户可配置部分。

在草图的顶部,您会找到引脚定义。如果您将组件连接到与本示例中使用的引脚不同的引脚,这些是您应首先检查的内容。

const int IR_RECEIVE_PIN = 12;  // 定义红外传感器的引脚号
const int A_1B = 5;
const int A_1A = 6;
const int B_1B = 9;
const int B_1A = 10;
  • IR_RECEIVE_PIN:此常量定义连接到红外接收器信号引脚的数字引脚。如果您将其连接到不同的引脚,则需要在此处更改编号。
  • A_1BA_1AB_1BB_1A:这些常量映射到电机驱动器上的四个控制引脚。它们控制左右电机的速度和方向。

接下来,您会找到一个控制车辆行为的关键变量。

int speed = 150;
  • speed:此变量设置车辆的初始速度。该值范围可以从0到255。在此项目中,您可以使用遥控器上的“+”和“-”键来更改它。代码还包含逻辑以防止速度超过255或低于0。(视频中09:22处)

遥控的核心逻辑在loop()函数中处理。当按下某个键时,decodeKeyValue()函数将原始红外代码转换为简单的字符串,例如“2”表示前进或“+”表示加速。这使得后续的if语句非常易于阅读和修改。(视频中07:58处)

moveForward()turnRight()moveLeft()这样的自定义函数是电机控制发生的地方。每个函数都将当前的speed作为参数。例如,moveForward(speed)会以指定速度驱动两个电机向前。 “转弯”和“移动”之间的关键区别在于,转弯会使两个轮子以相反方向旋转,从而使汽车原地旋转,而移动则只旋转一个轮子,使汽车围绕静止的轮子弧线行驶。(视频中10:14处)

现场项目演示

代码上传且汽车通电后,遥控器便成为你的主要操作界面。视频中的演示突出了几个关键行为:

  • 速度控制:按下“+”键会将速度增加50,而“-”键则会降低速度。速度上限为255,下限为0,以保护电机。(视频中11:56处)
  • 瞬时移动:当你按下方向键如“2”(前进)或“8”(后退)时,汽车会移动一秒钟然后自动停止。这是代码中内置的安全功能。(视频中13:09处)
  • 转弯与操控:遥控器上呈十字形排列的按键作用类似于操纵杆。按下“4”或“6”会使汽车原地左转或右转。按下对角线按键如“1”或“3”,则会执行“左移”或“右移”,这是一种更急的转弯,其中一个轮子保持静止。(视频中16:42处)

你可能会注意到,汽车并不总是沿直线行驶。这通常是由于电机之间的微小差异或汽车组装时的张力不同造成的,这是这些套件的常见且正常的特点。(视频中15:14处)

章节

  • [00:00] 智能车红外遥控介绍
  • [01:15] 先决条件和所需的前置课程
  • [01:56] 项目文档概述
  • [02:29] 了解遥控器按键功能
  • [03:29] 红外接收器和LED的分步接线指南
  • [05:51] 打开并加载项目代码
  • [07:41] 代码解释:循环、按键解码和动作
  • [09:22] 代码中的限速和安全功能
  • [10:08] 电机移动功能说明
  • [11:49] 现场演示:测试速度控制和LED闪烁
  • [13:27] 现场演示:前进、后退和转弯
  • [14:31] 带电源和移动的整车演示

图像

Car 9 lesson 29 wiring for IR
Car 9 lesson 29 wiring for IR
896-Lesson 29/31: Car-7 Controlling SunFounder Smart Car using Remote Controller
语言: C++
/*
Lesson 29/31: Car-7 Controlling SunFounder Smart Car using Remote Controller
Get this code and watch video Download and resource page https://robojax.com/RJT612

*/
#include <IRremote.h>

const int IR_RECEIVE_PIN = 12;  // Define the pin number for the IR Sensor

const int A_1B = 5;
const int A_1A = 6;
const int B_1B = 9;
const int B_1A = 10;


int speed = 150;

void setup() {
  Serial.begin(9600);

  //motor
  pinMode(A_1B, OUTPUT);
  pinMode(A_1A, OUTPUT);
  pinMode(B_1B, OUTPUT);
  pinMode(B_1A, OUTPUT);

  //IR remote
  IrReceiver.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK);  // Start the IR receiver // Start the receiver
  Serial.println("REMOTE CONTROL START");

}

void loop() {

  if (IrReceiver.decode()) {
    //    Serial.println(results.value,HEX);
    String key = decodeKeyValue(IrReceiver.decodedIRData.command);
    if (key != "ERROR") {
      Serial.println(key);

      if (key == "+") {
        speed += 50;
      } else if (key == "-") {
        speed -= 50;
      } else if (key == "2") {
        moveForward(speed);
        delay(1000);
      } else if (key == "1") {
        moveLeft(speed);
      } else if (key == "3") {
        moveRight(speed);
      } else if (key == "4") {
        turnLeft(speed);
      } else if (key == "6") {
        turnRight(speed);
      } else if (key == "7") {
        backLeft(speed);
      } else if (key == "9") {
        backRight(speed);
      } else if (key == "8") {
        moveBackward(speed);
        delay(1000);
      }

      if (speed >= 255) {
        speed = 255;
      }
      if (speed <= 0) {
        speed = 0;
      }
      delay(500);
      stopMove();
    }

    IrReceiver.resume();  // Enable receiving of the next value
  }
}

void moveForward(int speed) {
  analogWrite(A_1B, 0);
  analogWrite(A_1A, speed);
  analogWrite(B_1B, speed);
  analogWrite(B_1A, 0);
}

void moveBackward(int speed) {
  analogWrite(A_1B, speed);
  analogWrite(A_1A, 0);
  analogWrite(B_1B, 0);
  analogWrite(B_1A, speed);
}

void turnRight(int speed) {
  analogWrite(A_1B, speed);
  analogWrite(A_1A, 0);
  analogWrite(B_1B, speed);
  analogWrite(B_1A, 0);
}

void turnLeft(int speed) {
  analogWrite(A_1B, 0);
  analogWrite(A_1A, speed);
  analogWrite(B_1B, 0);
  analogWrite(B_1A, speed);
}

void moveLeft(int speed) {
  analogWrite(A_1B, 0);
  analogWrite(A_1A, speed);
  analogWrite(B_1B, 0);
  analogWrite(B_1A, 0);
}

void moveRight(int speed) {
  analogWrite(A_1B, 0);
  analogWrite(A_1A, 0);
  analogWrite(B_1B, speed);
  analogWrite(B_1A, 0);
}

void backLeft(int speed) {
  analogWrite(A_1B, speed);
  analogWrite(A_1A, 0);
  analogWrite(B_1B, 0);
  analogWrite(B_1A, 0);
}

void backRight(int speed) {
  analogWrite(A_1B, 0);
  analogWrite(A_1A, 0);
  analogWrite(B_1B, 0);
  analogWrite(B_1A, speed);
}

void stopMove() {
  analogWrite(A_1B, 0);
  analogWrite(A_1A, 0);
  analogWrite(B_1B, 0);
  analogWrite(B_1A, 0);
}


String decodeKeyValue(long result)
{
  switch(result){
    case 0x16:
      return "0";
    case 0xC:
      return "1"; 
    case 0x18:
      return "2"; 
    case 0x5E:
      return "3"; 
    case 0x8:
      return "4"; 
    case 0x1C:
      return "5"; 
    case 0x5A:
      return "6"; 
    case 0x42:
      return "7"; 
    case 0x52:
      return "8"; 
    case 0x4A:
      return "9"; 
    case 0x9:
      return "+"; 
    case 0x15:
      return "-"; 
    case 0x7:
      return "EQ"; 
    case 0xD:
      return "U/SD";
    case 0x19:
      return "CYCLE";         
    case 0x44:
      return "PLAY/PAUSE";   
    case 0x43:
      return "FORWARD";   
    case 0x40:
      return "BACKWARD";   
    case 0x45:
      return "POWER";   
    case 0x47:
      return "MUTE";   
    case 0x46:
      return "MODE";       
    case 0x0:
      return "ERROR";   
    default :
      return "ERROR";
    }
}

资源与参考

文件📁

Arduino 库(zip 格式)