Arduino硬件设计(一)|利用Arduino UNO R3制作手机蓝牙遥控小车---02

概述:

      本篇文章主要讲述在第一篇中代码程序的详细解释,包含各段代码的功能及作用,以方便大家能够更好的了解并分析代码的用途。

上篇链接:Arduino硬件设计(一)|利用Arduino UNO R3制作手机蓝牙遥控小车---01-优快云博客icon-default.png?t=N7T8https://blog.youkuaiyun.com/2301_80771046/article/details/136463793?spm=1001.2014.3001.5502

一.总代码程序

// 定义左右轮脉冲计数器和时间标记
int leftCounter = 0, rightCounter = 0;
unsigned long time = 0, old_time = 0;       // 时间标记,用于计算速度
unsigned long time1 = 0;                    // 时间标记,用于其他计时功能
float lv, rv;                               // 左、右轮速度
 
// 定义运动控制命令
#define STOP        0
#define FORWARD     1
#define BACKWARD    2
#define TURNLEFT    3
#define TURNRIGHT   4
#define CHANGESPEED 5
 
// 定义电机引脚
int leftMotor1 = 2;
int leftMotor2 = 3;
int rightMotor1 = 4;
int rightMotor2 = 5;
bool speedLevel = 0; // 速度档位,0表示低速,1表示高速
 
// 定义PWM引脚
int leftPWM = 9;
int rightPWM = 10;
 
void setup() {
  // 初始化串口通信,波特率为9600
  Serial.begin(9600);
  // 设置外部中断0,当引脚0电平从高到低变化时触发RightCount_CallBack函数
  attachInterrupt(0, RightCount_CallBack, FALLING);
  // 设置外部中断1,当引脚1电平从高到低变化时触发LeftCount_CallBack函数
  attachInterrupt(1, LeftCount_CallBack, FALLING);
 
  // 设置电机引脚为输出模式
  pinMode(leftMotor1, OUTPUT);
  pinMode(leftMotor2, OUTPUT);
  pinMode(rightMotor1, OUTPUT);
  pinMode(rightMotor2, OUTPUT);
  // 设置PWM引脚为输出模式
  pinMode(leftPWM, OUTPUT);
  pinMode(rightPWM, OUTPUT);
}
 
void loop() {
  // 调用速度检测函数
  SpeedDetection();
 
  // 如果串口有数据可读
  if (Serial.available() > 0) {
    // 读取蓝牙模块发送到串口的数据
    int cmd = Serial.read();
    // 如果接收到的数据不是换行符,则进行控制
    if (cmd != 10) {
      // 打印接收到的命令
      Serial.print(cmd - 48);
      // 根据命令控制小车运动
      motorRun(cmd - 48);
    }
    // 如果当前是高速档位
    if (speedLevel) {
      // 设置左右轮PWM值为120,对应较低速度
      analogWrite(leftPWM, 120);
      analogWrite(rightPWM, 120);
    } else {
      // 设置左右轮PWM值为250,对应较高速度
      analogWrite(leftPWM, 250);
      analogWrite(rightPWM, 250);
    }
  }
}
 
// 速度计算函数
bool SpeedDetection() {
  // 获取当前时间(毫秒)
  time = millis();
  // 如果计时时间达到1秒
  if (abs(time - old_time) >= 1000) {
    // 关闭外部中断0和1
    detachInterrupt(0);
    detachInterrupt(1);
    // 计算左右轮转速(转/分钟),并打印到串口
    lv = (float)leftCounter * 60 / 20;
    rv = (float)rightCounter * 60 / 20;
    Serial.print("left:");
    Serial.print(lv);
    Serial.print("     right:");
    Serial.println(rv);
    // 重置左右轮脉冲计数器,记录当前时间,重新开启外部中断0和1
    leftCounter = 0;
    rightCounter = 0;
    old_time = millis();
    attachInterrupt(0, RightCount_CallBack, FALLING);
    attachInterrupt(1, LeftCount_CallBack, FALLING);
    return 1;
  } else {
    return 0;
  }
}
 
// 右轮编码器中断服务函数,当引脚0电平从高到低变化时触发,增加右轮脉冲计数器
void RightCount_CallBack() {
  rightCounter++;
}
 
// 左轮编码器中断服务函数,当引脚1电平从高到低变化时触发,增加左轮脉冲计数器
void LeftCount_CallBack() {
  leftCounter++;
}
 
// 小车运动控制函数,根据命令控制小车运动状态
void motorRun(int cmd) {
  switch (cmd) {
    case FORWARD:
      Serial.println("FORWARD");
      // 设置电机引脚电平,使小车前进
      digitalWrite(leftMotor1, HIGH);
      digitalWrite(leftMotor2, LOW);
      digitalWrite(rightMotor1, HIGH);
      digitalWrite(rightMotor2, LOW);
      break;
    case BACKWARD:
      Serial.println("BACKWARD");
      // 设置电机引脚电平,使小车后退
      digitalWrite(leftMotor1, LOW);
      digitalWrite(leftMotor2, HIGH);
      digitalWrite(rightMotor1, LOW);
      digitalWrite(rightMotor2, HIGH);
      break;
    case TURNLEFT:
      Serial.println("TURN LEFT");
      // 设置电机引脚电平,使小车左转
      digitalWrite(leftMotor1, HIGH);
      digitalWrite(leftMotor2, LOW);
      digitalWrite(rightMotor1, LOW);
      digitalWrite(rightMotor2, HIGH);
      break;
    case TURNRIGHT:
      Serial.println("TURN RIGHT");
      // 设置电机引脚电平,使小车右转
      digitalWrite(leftMotor1, LOW);
      digitalWrite(leftMotor2, HIGH);
      digitalWrite(rightMotor1, HIGH);
      digitalWrite(rightMotor2, LOW);
      break;
    case CHANGESPEED:
      Serial.println("CHANGE SPEED");
      // 切换速度档位
      if (speedLevel)
        speedLevel = 0;
      else
        speedLevel = 1;
      break;
    default:
      Serial.println("STOP");
      // 停止所有电机
      digitalWrite(leftMotor1, LOW);
      digitalWrite(leftMotor2, LOW);
      digitalWrite(rightMotor1, LOW);
      digitalWrite(rightMotor2, LOW);
  }
}

二.代码分段解释

   1.第一段

// 定义左右轮脉冲计数器和时间标记
int leftCounter = 0, rightCounter = 0;
unsigned long time = 0
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

孟俊宇-MJY

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值