【2412】CIE 机器人四级实操

总分:100分题数:1

一、填空题。 (共1题,共100分)

1.主题:红外遥控门栏

器件:Atmega328P主控板1块,LED灯模块1个,红外接收套件1套,舵机1个、超声波传感器1个、按键模块1个及相应辅件。以上模块也可使用分立器件结合面包板搭建。

任务要求:

通过舵机的转动模拟门栏的打开和关闭,门栏有两种功能模式:手动模式和自动感应模式。通过红外遥控控制门栏在两种功能模式之间切换。点击红外遥控器1键,门栏进入手动模式;点击红外遥控器2键,门栏进入自动感应模式。具体说明如下:

(1)当装置通电后,门栏默认处于自动感应模式;

(2)当门栏进入自动感应模式时,通过超声波传感器控制舵机的转动,当超声波传感器检测的距离大于5厘米时,舵机旋转至0度,表示门栏关闭。当超声波传感器检测的距离小于等于5厘米是,舵机旋转至90度,表示门栏打开;

(3)当门栏进入手动模式时,点击按键,舵机旋转至90度位置,表示门栏打开,门栏打开时长为3秒钟,然后舵机旋转至0度,门栏关闭。当按键没有被点击时,舵机处于0度位置,门栏处于关闭状态;

(4)当门栏打开时,LED灯闪烁,当门栏关闭时LED灯点亮;

(5)控制程序采用Arduino C/C++代码编写,不得使用图形化软件编写;

(6)未作规定处可自行处理,无明显与事实违背即可。

说明:请考生在考试结束前,按照如下要求提交相关文件。

(1)将程序放在一个文件夹中,压缩为1个“rar或zip”格式文件,并命名为:DJKS4_身份证号,大小5M以下;

(2)将程序文件通过“上传附件”按钮进行上传;

(3)程序编写过程中不得打开其它示例程序,不得使用图形化软件生成代码,如发现,实操成绩按照0分处理。

参考资料:

红外遥控提供示例供参考。

#include <IRremote.h>     
const int RECV_PIN = 12;  
IRrecv irrecv(RECV_PIN);  
decode_results results;   

void setup(){
  Serial.begin(9600);                       
  irrecv.enableIRIn();                      
}
void loop() {
  if (irrecv.decode(&results)) {        
    Serial.println(results.value, HEX);  
    irrecv.resume();                         
  }
  delay(100);
}

评分项:

1.器件及器件连接(20分

2.功能实现(80分)

(1)点击红外遥控器1键,切换到手动模式,当按键没有按下时,舵机处于0度位置;(10分)

(2)点击红外遥控器1键,切换到手动模式,实现当按键按下后,舵机旋转至90度位置,停留3秒后,舵机旋转至0度;(15分)

(3)点击红外遥控器2键,切换到自动感应模式,实行当超声波传感器检测的距离大于5厘米时,舵机处于0度位置;(15分)

(4)点击红外遥控器2键,切换到自动感应模式,实行当超声波传感器检测的距离不大于5厘米时,舵机处于90度位置;(15分)

(5)实现当舵机处于90度位置时,LED灯闪烁;(15分)

(6)实现当舵机处于0度位置时,LED灯点亮。(10分)

(100分)

4 条评论

  • @ 2025-6-14 16:07:15
    #include <IRremote.h>  // 引入红外遥控库
    #include <Servo.h>  // 引入舵机控制库
    
    Servo myServo;      // 创建舵机对象
    const int servoPin = 9;  // 定义信号引脚
    int angle = 0;      // 当前角度值
    
    const int RECV_PIN = 11;  // 定义红外接收引脚
    IRrecv irrecv(RECV_PIN);  // 创建红外接收对象
    decode_results results;   // 用于存储解码结果的对象
    
    // 定义超声波传感器引脚
    const int trigPin = A4;  // 触发引脚,用于发送超声波信号
    const int echoPin = A5;  // 回声引脚,用于接收反射的超声波信号
    
    const int keyPin = 2;  // 定义按钮连接的引脚
    double dis;  // 存储测量到的距离值
    
    const int LED_PIN = 3;  // 定义LED连接的引脚
    // 函数:测量距离
    float checkdistance() {
      // 触发超声波发送
      digitalWrite(trigPin, LOW);    // 先将触发引脚拉低,确保状态稳定
      delayMicroseconds(2);          // 保持2微秒
      digitalWrite(trigPin, HIGH);   // 发送10微秒的高电平触发脉冲
      delayMicroseconds(10);
      digitalWrite(trigPin, LOW);    // 触发脉冲结束
    
      // 测量回声时间并计算距离
      // pulseIn()函数返回高电平持续时间(微秒),即超声波往返时间
      // 距离计算公式:距离(厘米) = 时间(微秒) / 58.00
      // (声速约340m/s,转换为厘米/微秒:34000/1000000 = 0.034cm/μs
      //  往返距离 = 0.034 * 时间 → 单程距离 = 0.034 * 时间 / 2 ≈ 时间 / 58)
      float distance = pulseIn(echoPin, HIGH) / 58.00;
      delay(10);  // 短暂延时,避免传感器读数冲突
      return distance;  // 返回测量的距离值(厘米)
    }
    
    void setup() {
      Serial.begin(9600);     // 初始化串口通信
      irrecv.enableIRIn();    // 启用红外接收
      irrecv.blink13(true);   // 启用LED指示(可选)
      Serial.println("等待红外信号...");
      // 初始化变量和硬件
      dis = 0;                 // 初始化距离变量
      pinMode(trigPin, OUTPUT);  // 设置触发引脚为输出模式
      pinMode(echoPin, INPUT);   // 设置回声引脚为输入模式
      //Serial.begin(9600);        // 初始化串口通信,波特率9600
      myServo.attach(servoPin);  // 初始化舵机引脚连接
      pinMode(keyPin, INPUT);  // 将引脚设置为输入模式
      Serial.println("Hello from Arduino!");  // 提示信息
      pinMode(LED_PIN, OUTPUT);  // 将引脚设置为输出模式
      Serial.println("LED测试开始");
    }
    int x;  // 存储按钮状态的变量
    boolean flag = false;//false就是为自动感应模式
    //flag = true就是手动模式
    void loop() {
      if (flag == false) {
        dis = checkdistance();    // 调用函数测量当前距离
        Serial.println(dis);      // 通过串口输出距离值(单位:厘米)
        if (dis > 5) {
          myServo.write(0);  // 设置舵机角度
        } else {
          myServo.write(90);  // 设置舵机角度
          digitalWrite(LED_PIN, 1);
          delay(50);
          digitalWrite(LED_PIN, 0);
          delay(50);
        }
      } else {
        x = digitalRead(keyPin);
        if (x == true) {
          myServo.write(90);  // 设置舵机角度
          //delay(3000);
          for (int i = 1; i <= 30; i++) {
            digitalWrite(LED_PIN, 1);
            delay(50);
            digitalWrite(LED_PIN, 0);
            delay(50);
          }
          myServo.write(0);  // 设置舵机角度
        } else {
          myServo.write(0);  // 设置舵机角度
        }
      }
    
      if (irrecv.decode(&results)) {  // 尝试解码接收到的信号
        Serial.println(results.value, HEX);  // 以十六进制打印按键值
        if (results.value == 0xFF30cf) {
          flag = true;//就是c模式
          Serial.println("-------------手动------------------");
        }
        if (results.value == 0xFF18E7) {
          flag = false;
          Serial.println("==============自动=================");
        }
        irrecv.resume();  // 继续接收下一个信号
      }
      delay(20);
    }
    
    
    
    
    //  if (irrecv.decode(&results)) {  // 尝试解码接收到的信号
    //    Serial.println(results.value, HEX);  // 以十六进制打印按键值
    //    irrecv.resume();  // 继续接收下一个信号
    //  }
    //  delay(100);  // 短暂延时
    //
    //  // 主循环:重复测量并输出距离
    //  dis = checkdistance();    // 调用函数测量当前距离
    //  Serial.println(dis);      // 通过串口输出距离值(单位:厘米)
    //  // 循环会自动重复执行,持续测量并更新距离
    //  delay(200);
    //  myServo.write(angle);  // 设置舵机角度
    //  delay(15);             // 等待舵机转动到位
    //  x = digitalRead(keyPin);  // 读取按钮引脚状态
    //  Serial.println(x);  // 通过串口输出按钮状态
    //  delay(50);  // 延时50毫秒
    //  digitalWrite(LED_PIN, HIGH);  // 点亮LED
    //  Serial.println("LED亮");
    //  delay(1000);                  // 等待1秒
    //
    //  digitalWrite(LED_PIN, LOW);   // 熄灭LED
    //  Serial.println("LED灭");
    //  delay(1000);                  // 等待1秒
    //}
    
    
    
    • @ 2025-6-14 15:36:34

      以下是对该Arduino程序的解析:

      功能概述

      这个程序实现了一个基于Arduino的智能门栏控制系统,具有两种工作模式:

      • 自动感应模式:通过超声波传感器检测距离,当检测到的距离小于等于5厘米时,门栏自动打开(舵机旋转到90度);当距离大于5厘米时,门栏关闭(舵机旋转到0度)。
      • 手动模式:通过按键控制门栏的开关,按下按键后门栏打开并保持3秒,然后自动关闭。

      代码解析

      程序分为几个主要部分:

      1. 库和变量定义

      #include <IRremote.h>  // 引入红外遥控库
      #include <Servo.h>     // 引入舵机控制库
      
      Servo myServo;      // 创建舵机对象
      const int servoPin = 9;  // 定义舵机信号引脚
      int angle = 0;      // 当前舵机角度值
      
      const int RECV_PIN = 11;  // 定义红外接收引脚
      IRrecv irrecv(RECV_PIN);  // 创建红外接收对象
      decode_results results;   // 用于存储解码结果的对象
      
      // 定义超声波传感器引脚
      const int trigPin = A4;  // 触发引脚,用于发送超声波信号
      const int echoPin = A5;  // 回声引脚,用于接收反射的超声波信号
      
      const int keyPin = 2;  // 定义按钮连接的引脚
      double dis;  // 存储测量到的距离值
      const int LED_PIN = 3;  // 定义LED连接的引脚
      

      2. 超声波测距函数

      float checkdistance() {
        // 触发超声波发送
        digitalWrite(trigPin, LOW);    // 先将触发引脚拉低,确保状态稳定
        delayMicroseconds(2);          // 保持2微秒
        digitalWrite(trigPin, HIGH);   // 发送10微秒的高电平触发脉冲
        delayMicroseconds(10);
        digitalWrite(trigPin, LOW);    // 触发脉冲结束
      
        // 测量回声时间并计算距离
        float distance = pulseIn(echoPin, HIGH) / 58.00;
        delay(10);  // 短暂延时,避免传感器读数冲突
        return distance;  // 返回测量的距离值(厘米)
      }
      

      3. 初始化设置

      void setup() {
        Serial.begin(9600);     // 初始化串口通信
        irrecv.enableIRIn();    // 启用红外接收
        irrecv.blink13(true);   // 启用LED指示(可选)
        Serial.println("等待红外信号...");
        
        // 初始化变量和硬件
        dis = 0;                 // 初始化距离变量
        pinMode(trigPin, OUTPUT);  // 设置触发引脚为输出模式
        pinMode(echoPin, INPUT);   // 设置回声引脚为输入模式
        myServo.attach(servoPin);  // 初始化舵机引脚连接
        pinMode(keyPin, INPUT);    // 将按钮引脚设置为输入模式
        pinMode(LED_PIN, OUTPUT);  // 将LED引脚设置为输出模式
        
        Serial.println("系统初始化完成");
      }
      

      4. 主循环

      int x;  // 存储按钮状态的变量
      boolean flag = false;  // false表示自动感应模式,true表示手动模式
      
      void loop() {
        if (flag == false) {  // 自动感应模式
          dis = checkdistance();    // 测量当前距离
          Serial.print("距离: ");
          Serial.print(dis);
          Serial.println(" cm");
          
          if (dis > 5) {
            myServo.write(0);  // 距离大于5厘米,关闭门栏
            digitalWrite(LED_PIN, HIGH);  // 关闭状态LED常亮
          } else {
            myServo.write(90);  // 距离小于等于5厘米,打开门栏
            // 打开状态LED闪烁
            digitalWrite(LED_PIN, HIGH);
            delay(500);
            digitalWrite(LED_PIN, LOW);
            delay(500);
          }
        } else {  // 手动模式
          x = digitalRead(keyPin);  // 读取按钮状态
          
          if (x == HIGH) {  // 按钮被按下
            myServo.write(90);  // 打开门栏
            // 打开状态LED闪烁
            for (int i = 0; i < 6; i++) {  // 3秒内闪烁
              digitalWrite(LED_PIN, HIGH);
              delay(250);
              digitalWrite(LED_PIN, LOW);
              delay(250);
            }
            myServo.write(0);  // 3秒后关闭门栏
            digitalWrite(LED_PIN, HIGH);  // 关闭状态LED常亮
          } else {
            myServo.write(0);  // 按钮未按下,保持关闭状态
            digitalWrite(LED_PIN, HIGH);  // 关闭状态LED常亮
          }
        }
      
        // 红外遥控模式切换
        if (irrecv.decode(&results)) {  // 尝试解码接收到的信号
          Serial.print("红外按键值: 0x");
          Serial.println(results.value, HEX);  // 以十六进制打印按键值
          
          if (results.value == 0xFF30CF) {  // 红外遥控器1键
            flag = true;  // 切换到手动模式
            Serial.println("切换到手动模式");
          }
          if (results.value == 0xFF18E7) {  // 红外遥控器2键
            flag = false;  // 切换到自动感应模式
            Serial.println("切换到自动感应模式");
          }
          
          irrecv.resume();  // 继续接收下一个信号
        }
        
        delay(20);  // 短暂延时,稳定系统
      }
      

      功能实现说明

      1. 模式切换:通过红外遥控器的1键和2键切换工作模式,系统默认启动为自动感应模式。
      2. 自动感应模式
        • 超声波传感器持续检测前方距离
        • 距离>5cm时,舵机旋转到0度(门栏关闭),LED常亮
        • 距离≤5cm时,舵机旋转到90度(门栏打开),LED闪烁
      3. 手动模式
        • 按下按键,舵机旋转到90度(门栏打开),LED开始闪烁
        • 保持3秒后,舵机自动转回0度(门栏关闭),LED恢复常亮
        • 按键未按下时,舵机保持在0度,LED常亮

      评分项对应分析

      1. 器件及器件连接(20分):程序中正确定义了各器件引脚,符合要求。
      2. 功能实现(80分)
        • 手动模式舵机控制(10+15分):通过红外1键切换到手动模式,按键按下时舵机旋转到90度并保持3秒后转回0度,实现完整。
        • 自动感应模式舵机控制(15+15分):通过红外2键切换到自动模式,根据超声波距离控制舵机角度,逻辑正确。
        • LED闪烁控制(15+10分):门栏打开时LED闪烁,关闭时LED常亮,符合要求。

      这个程序完整实现了题目要求的所有功能,结构清晰,注释完善,能够正确响应红外遥控指令并根据环境条件控制舵机和LED状态。

      • @ 2025-6-14 15:34:12
        #include <IRremote.h>  // 引入红外遥控库
        #include <Servo.h>  // 引入舵机控制库
        
        Servo myServo;      // 创建舵机对象
        const int servoPin = 9;  // 定义信号引脚
        int angle = 0;      // 当前角度值
        
        const int RECV_PIN = 11;  // 定义红外接收引脚
        IRrecv irrecv(RECV_PIN);  // 创建红外接收对象
        decode_results results;   // 用于存储解码结果的对象
        
        // 定义超声波传感器引脚
        const int trigPin = A4;  // 触发引脚,用于发送超声波信号
        const int echoPin = A5;  // 回声引脚,用于接收反射的超声波信号
        
        const int keyPin = 2;  // 定义按钮连接的引脚
        double dis;  // 存储测量到的距离值
        const int LED_PIN = 3;  // 定义LED连接的引脚
        // 函数:测量距离
        float checkdistance() {
          // 触发超声波发送
          digitalWrite(trigPin, LOW);    // 先将触发引脚拉低,确保状态稳定
          delayMicroseconds(2);          // 保持2微秒
          digitalWrite(trigPin, HIGH);   // 发送10微秒的高电平触发脉冲
          delayMicroseconds(10);
          digitalWrite(trigPin, LOW);    // 触发脉冲结束
        
          // 测量回声时间并计算距离
          // pulseIn()函数返回高电平持续时间(微秒),即超声波往返时间
          // 距离计算公式:距离(厘米) = 时间(微秒) / 58.00
          // (声速约340m/s,转换为厘米/微秒:34000/1000000 = 0.034cm/μs
          //  往返距离 = 0.034 * 时间 → 单程距离 = 0.034 * 时间 / 2 ≈ 时间 / 58)
          float distance = pulseIn(echoPin, HIGH) / 58.00;
          delay(10);  // 短暂延时,避免传感器读数冲突
          return distance;  // 返回测量的距离值(厘米)
        }
        
        void setup() {
          Serial.begin(9600);     // 初始化串口通信
          irrecv.enableIRIn();    // 启用红外接收
          irrecv.blink13(true);   // 启用LED指示(可选)
          Serial.println("等待红外信号...");
          // 初始化变量和硬件
          dis = 0;                 // 初始化距离变量
          pinMode(trigPin, OUTPUT);  // 设置触发引脚为输出模式
          pinMode(echoPin, INPUT);   // 设置回声引脚为输入模式
          //Serial.begin(9600);        // 初始化串口通信,波特率9600
          myServo.attach(servoPin);  // 初始化舵机引脚连接
          pinMode(keyPin, INPUT);  // 将引脚设置为输入模式
          Serial.println("Hello from Arduino!");  // 提示信息
          pinMode(LED_PIN, OUTPUT);  // 将引脚设置为输出模式
          Serial.println("LED测试开始");
        }
        int x;  // 存储按钮状态的变量
        boolean flag = false;//false就是为自动感应模式
        //flag = true就是手动模式
        void loop() {
          if (flag == false) {
            dis = checkdistance();    // 调用函数测量当前距离
            Serial.println(dis);      // 通过串口输出距离值(单位:厘米)
            if (dis > 5) {
              myServo.write(0);  // 设置舵机角度
            } else {
              myServo.write(90);  // 设置舵机角度
            }
          } else {
            x = digitalRead(keyPin);
            if (x == true) {
              myServo.write(90);  // 设置舵机角度
              delay(3000);
              myServo.write(0);  // 设置舵机角度
            } else {
              myServo.write(0);  // 设置舵机角度
            }
          }
        
          if (irrecv.decode(&results)) {  // 尝试解码接收到的信号
            Serial.println(results.value, HEX);  // 以十六进制打印按键值
            if (results.value == 0xFF30cf) {
              flag = true;//就是手动模式
            }
            if (results.value == 0xFF18E7) {
              flag = false;
            }
            irrecv.resume();  // 继续接收下一个信号
          }
          delay(20);
        }
        
        
        
        
        //  if (irrecv.decode(&results)) {  // 尝试解码接收到的信号
        //    Serial.println(results.value, HEX);  // 以十六进制打印按键值
        //    irrecv.resume();  // 继续接收下一个信号
        //  }
        //  delay(100);  // 短暂延时
        //
        //  // 主循环:重复测量并输出距离
        //  dis = checkdistance();    // 调用函数测量当前距离
        //  Serial.println(dis);      // 通过串口输出距离值(单位:厘米)
        //  // 循环会自动重复执行,持续测量并更新距离
        //  delay(200);
        //  myServo.write(angle);  // 设置舵机角度
        //  delay(15);             // 等待舵机转动到位
        //  x = digitalRead(keyPin);  // 读取按钮引脚状态
        //  Serial.println(x);  // 通过串口输出按钮状态
        //  delay(50);  // 延时50毫秒
        //  digitalWrite(LED_PIN, HIGH);  // 点亮LED
        //  Serial.println("LED亮");
        //  delay(1000);                  // 等待1秒
        //
        //  digitalWrite(LED_PIN, LOW);   // 熄灭LED
        //  Serial.println("LED灭");
        //  delay(1000);                  // 等待1秒
        //}
        
        
        
        • @ 2025-6-9 19:32:01

          准备工作

          #include <IRremote.h>  // 引入红外遥控库
          #include <Servo.h>  // 引入舵机控制库
          
          Servo myServo;      // 创建舵机对象
          const int servoPin = 9;  // 定义信号引脚
          int angle = 0;      // 当前角度值
          
          const int RECV_PIN = 11;  // 定义红外接收引脚
          IRrecv irrecv(RECV_PIN);  // 创建红外接收对象
          decode_results results;   // 用于存储解码结果的对象
          // 定义超声波传感器引脚
          const int trigPin = A4;  // 触发引脚,用于发送超声波信号
          const int echoPin = A5;  // 回声引脚,用于接收反射的超声波信号
          const int keyPin = 2;  // 定义按钮连接的引脚
          double dis;  // 存储测量到的距离值
          const int LED_PIN = 3;  // 定义LED连接的引脚
          // 函数:测量距离
          float checkdistance() {
            // 触发超声波发送
            digitalWrite(trigPin, LOW);    // 先将触发引脚拉低,确保状态稳定
            delayMicroseconds(2);          // 保持2微秒
            digitalWrite(trigPin, HIGH);   // 发送10微秒的高电平触发脉冲
            delayMicroseconds(10);
            digitalWrite(trigPin, LOW);    // 触发脉冲结束
            
            // 测量回声时间并计算距离
            // pulseIn()函数返回高电平持续时间(微秒),即超声波往返时间
            // 距离计算公式:距离(厘米) = 时间(微秒) / 58.00
            // (声速约340m/s,转换为厘米/微秒:34000/1000000 = 0.034cm/μs
            //  往返距离 = 0.034 * 时间 → 单程距离 = 0.034 * 时间 / 2 ≈ 时间 / 58)
            float distance = pulseIn(echoPin, HIGH) / 58.00;
            delay(10);  // 短暂延时,避免传感器读数冲突
            return distance;  // 返回测量的距离值(厘米)
          }
          
          void setup() {
            Serial.begin(9600);     // 初始化串口通信
            irrecv.enableIRIn();    // 启用红外接收
            irrecv.blink13(true);   // 启用LED指示(可选)
            Serial.println("等待红外信号...");
            // 初始化变量和硬件
            dis = 0;                 // 初始化距离变量
            pinMode(trigPin, OUTPUT);  // 设置触发引脚为输出模式
            pinMode(echoPin, INPUT);   // 设置回声引脚为输入模式
            //Serial.begin(9600);        // 初始化串口通信,波特率9600
            myServo.attach(servoPin);  // 初始化舵机连接
            pinMode(keyPin, INPUT);  // 将引脚设置为输入模式
            Serial.println("Hello from Arduino!");  // 提示信息
            pinMode(LED_PIN, OUTPUT);  // 将引脚设置为输出模式
            Serial.println("LED测试开始");
          }
          int x;  // 存储按钮状态的变量
          void loop() {
            if (irrecv.decode(&results)) {  // 尝试解码接收到的信号
              Serial.println(results.value, HEX);  // 以十六进制打印按键值
              irrecv.resume();  // 继续接收下一个信号
            }
            delay(100);  // 短暂延时
          
            // 主循环:重复测量并输出距离
            dis = checkdistance();    // 调用函数测量当前距离
            Serial.println(dis);      // 通过串口输出距离值(单位:厘米)
            // 循环会自动重复执行,持续测量并更新距离
            delay(200);
            myServo.write(angle);  // 设置舵机角度
            delay(15);             // 等待舵机转动到位
            x = digitalRead(keyPin);  // 读取按钮引脚状态
            Serial.println(x);  // 通过串口输出按钮状态
            delay(50);  // 延时50毫秒
            digitalWrite(LED_PIN, HIGH);  // 点亮LED
            Serial.println("LED亮");
            delay(1000);                  // 等待1秒
            
            digitalWrite(LED_PIN, LOW);   // 熄灭LED
            Serial.println("LED灭");
            delay(1000);                  // 等待1秒
          }
          
          
          • 1