智能小车(二):超声波模块与蜂鸣器模块

星期二, 10月 15, 2024 | 5分钟阅读 | 更新于 星期日, 12月 8, 2024

YuanFeng Xie

历史回顾

概要

本节课关注于超声波模块的使用和蜂鸣器模块的使用。超声波模块在小车中可以用于前方障碍物的距离测算,蜂鸣器模块可以用于小车速度,到障碍物距离等变量到达边界值时的声音提醒。

安全须知

    / [pdf]

超声波模块

实例代码

const int Trig = 11;                //设定超声波模块连接的Arduino引脚
const int Echo = 12;                //设定超声波模块连接的Arduino引脚
float Ultrasonic;                   //超声波测量的距离
void setup() {  
  pinMode(Trig, OUTPUT);
  pinMode(Echo, INPUT);
  Serial.begin(9600);
}
void checkdistance_Trig_Echo(void) {
  digitalWrite(Trig, LOW);                  //超声波发射引脚拉低
  delayMicroseconds(2);                     //等待2us
  digitalWrite(Trig, HIGH);                 //超声波发射引脚拉高
  delayMicroseconds(10);                    //等待10us
  digitalWrite(Trig, LOW);                  //超声波发射引脚拉低
  Ultrasonic = pulseIn(Echo, HIGH) / 58.00; //获得超声波模块数据,单位cm
  delay(10);                                //等待10ms
}
void loop() {
  checkdistance_Trig_Echo();
  Serial.print(Ultrasonic);
  Serial.println("cm");
  delay(500);
}

代码详解

  • 引脚定义和变量声明
  • 将超声波模块的Trig引脚连接到Arduino的11号引脚
  • 将超声波模块的Echo引脚连接到Arduino的12号引脚
  • 声明一个浮点型变量Ultrasonic用于存储测量的距离
  • setup()函数
    • 设置Trig引脚为输出模式
    • 设置Echo引脚为输入模式
    • 初始化串口通信,波特率设为9600
  • checkdistance_Trig_Echo()函数
    • 发送超声波信号:先将Trig引脚设为低电平,等待2微秒,将Trig引脚设为高电平,等待10微秒,再将Trig引脚设为低电平
    • 接收回波并计算距离:使用pulseIn()函数测量Echo引脚高电平持续时间,将测量数据除以58.00转换为厘米距离,等待10毫秒,为下次测量做准备
  • loop()函数
    • 调用checkdistance_Trig_Echo()函数进行距离测量
    • 通过串口输出测量的距离值,单位为厘米
    • 每次测量后等待500毫秒

问题

  • 为什么测量数据/58可以转换为实际的测量数据?请给出计算步骤

提示

pulseIn()函数返回的时间单位是微秒(μs), 测量的是超声波从发射到接收的总时间,即声波往返的时间, 声波在空气中的速度约为340米/秒(或34,000厘米/秒)

  • 请解释超声波引脚的设置,为什么先设置为LOW,为什么要设置延时

提示

信号传输是否需要时间? 复位的设置

蜂鸣器模块的使用

float ad;                           //电压
int Buzzerbin = 13;                 //设置控制蜂鸣器的数字IO脚
float dianya;
void setup() {
  pinMode(Buzzerbin, OUTPUT); //设置数字IO脚模式,OUTPUT为输出
  Serial.begin(9600);
}

void Beep(int count, int Frequency, int Time){
  for (int i = 0; i < count; i++){
    for (int q = 0; q < 500; q++){
      digitalWrite(Buzzerbin, HIGH); //发声音
      delayMicroseconds(Frequency);//延时1ms
      digitalWrite(Buzzerbin, LOW); //不发声音
      delayMicroseconds(Frequency);//延时ms
    }
    delay(Time);
  }
}
  
void loop() {
  //从A0口读取电压,模拟端口电压测量范围为0-5V,
  // 返回的值为0-1024
  int v = analogRead(A0);
  ad = v * (5.0 / 1024.0) * 2.97; //将返回值换算成电压
  dianya = ad;
  if (ad <= 5.5) {
    Beep(3, 160, 500);
    delay(2000);
  }
  Serial.print("电压:");
  Serial.println(dianya);
  delay(500);
}

代码详解

  • 变量定义和引脚设置
    • 定义addianya变量用于存储电压值
    • 将蜂鸣器模块连接到Arduino的13号引脚
  • setup()函数
    • 设置蜂鸣器引脚为输出模式
    • 初始化串口通信,波特率设为9600
  • Beep()函数
    • 接受三个参数:蜂鸣次数、频率和间隔时间
    • 通过快速切换引脚高低电平来产生声音
    • 外层循环控制蜂鸣次数,内层循环控制单次蜂鸣的持续时间
  • loop()函数
    • 从A0模拟口读取电压值
    • 将读取的值转换为实际电压
    • 如果电压低于5.5V,触发蜂鸣器报警
    • 通过串口输出当前电压值
    • 每次循环后等待500毫秒

问题

  • 为什么在Beep()函数中使用两个嵌套的for循环?这种设计的目的是什么?

提示

考虑声音的产生原理和蜂鸣器的工作方式。外层循环和内层循环分别控制什么?

  • 代码中的v * (5.0 / 1024.0) * 2.97是如何将模拟读数转换为实际电压的?请解释这个公式的每个部分。

提示

考虑Arduino模拟输入的工作原理,以及可能使用的电压分压器。

蜂鸣器扩展(王子传小组提供)

int BuzzerPin = 13; // 设置控制蜂鸣器的数字IO脚

// 定义音符频率(单位:赫兹)
#define NOTE_C4  262
#define NOTE_D4  294
#define NOTE_E4  330
#define NOTE_F4  349
#define NOTE_G4  392
#define NOTE_A4  440
#define NOTE_B4  494
#define NOTE_C5  523

// 小星星旋律
int melody[] = {
  NOTE_C4, NOTE_C4, NOTE_G4, NOTE_G4, NOTE_A4, NOTE_A4, NOTE_G4,
  NOTE_F4, NOTE_F4, NOTE_E4, NOTE_E4, NOTE_D4, NOTE_D4, NOTE_C4
};

// 音符持续时间(单位:四分之一音符的毫秒数)
int noteDurations[] = {
  4, 4, 4, 4, 4, 4, 2,
  4, 4, 4, 4, 4, 4, 2
};

void setup() {
  pinMode(BuzzerPin, OUTPUT); // 设置数字IO脚模式,OUTPUT为输出
  Serial.begin(9600);
}

void playTone(int tone, int duration) {
  for (long i = 0; i < duration * 1000L; i += tone * 2) {
    digitalWrite(BuzzerPin, HIGH);
    delayMicroseconds(tone);
    digitalWrite(BuzzerPin, LOW);
    delayMicroseconds(tone);
  }
}

void playMelody() {
  // 播放旋律中的每个音符
  for (int thisNote = 0; thisNote < sizeof(melody) / sizeof(melody[0]); thisNote++) {
    // 计算音符持续时间
    int noteDuration = 1000 / noteDurations[thisNote];
    playTone(melody[thisNote], noteDuration);

    // 为了区分连续的音符,设置一个短暂的延迟
    int pauseBetweenNotes = noteDuration * 1.30;
    delay(pauseBetweenNotes);
  }
}

void loop() {
  int v = analogRead(A0); // 从A0口读取电压,模拟端口电压测量范围为0-5V,返回的值为0-1024
  float ad = v * (5.0 / 1024.0); // 将返回值换算成电压
  if (ad <= 5.5) {
    playMelody(); // 播放旋律
    delay(2000); // 旋律播放完毕后等待2秒
  }
  Serial.print("电压:");
  Serial.println(ad);
  delay(1000); // 每次读取电压后等待1秒
}

倒车场景

  • 用超声波传感器和蜂鸣器模拟倒车雷达。超声波传感器检测到的距离越近,蜂鸣器发出的声音频率越高,间隔时间越短,警报声越急促
const int Trig = 11;                // 超声波发射引脚
const int Echo = 12;                // 超声波接收引脚
const int BuzzerPin = 13;           // 蜂鸣器引脚
float distance;                     // 存储超声波测量的距离

void setup() {
  pinMode(Trig, OUTPUT);            // 设置Trig引脚为输出模式
  pinMode(Echo, INPUT);             // 设置Echo引脚为输入模式
  pinMode(BuzzerPin, OUTPUT);       // 设置Buzzer引脚为输出模式
  Serial.begin(9600);               // 初始化串口通讯
}

void loop() {
  // 检测距离
  distance = measureDistance(); 
  
  // 根据距离调节蜂鸣器的频率和间隔时间
  if (distance <= 10) {
    beep(100, 50);  // 距离小于等于10cm,蜂鸣器发出急促的短声
  } else if (distance <= 20) {
    beep(200, 100); // 距离在10-20cm之间,蜂鸣器发出稍慢的警报声
  } else if (distance <= 30) {
    beep(300, 200); // 距离在20-30cm之间,蜂鸣器发出较慢的警报声
  } else {
    digitalWrite(BuzzerPin, LOW);   // 关闭蜂鸣器
  }

  delay(100);       // 每次循环延迟100毫秒
}

// 测量距离的函数
float measureDistance() {
  digitalWrite(Trig, LOW);
  delayMicroseconds(2);
  digitalWrite(Trig, HIGH);
  delayMicroseconds(10);
  digitalWrite(Trig, LOW);

  // 计算距离,单位为厘米
  float duration = pulseIn(Echo, HIGH);
  float distance = duration  / 58.00;
  return distance;
}

// 控制蜂鸣器发声的函数
void beep(int frequency, int interval) {
  for (int i = 0; i < 10; i++) {
    digitalWrite(BuzzerPin, HIGH);
    delayMicroseconds(frequency);
    digitalWrite(BuzzerPin, LOW);
    delayMicroseconds(frequency);
  }
  delay(interval);
}

© 2024 小谢同学的修行小屋

🌱 Powered by Hugo with theme Dream.

关于我

一名喜欢RUST的菜鸟程序员

教育背景(研二在读)

  • 2019.09 - 2023.06 天津大学 · 智能与计算学部 · 网络安全专业 · 全日制 · 本科
  • 2023.09 - 2026.06 天津大学 · 智能与计算学部 · 电子信息专业 · 全日制 · 硕士研究生
浏览器漏洞挖掘项目

V8引擎的模糊测试工具改进

时间:2021.09-2022.04

内容:聚焦于优化JavaScript引擎的测试方法。研究团队基于SOAT改进部署了V8引擎测试环境,并通过分析测例覆盖率和已知CVE,优化了测试流程。

成果:成功捕获了一个谷歌引擎的逻辑漏洞,获得了修复反馈

JS引擎WASM模块漏洞挖掘研究

时间:2023.11-2024.4

内容:阅读标准手动编写了WASM语法规则,调研了主流JS引擎的WASM支持情况,并基于V8构建了WASM二进制框架。

成果:语法规则、调研报告和二进制构建框架,成功捕获特性缺陷并得到修复

数据库缺陷研究项目

关系型数据库缺陷的实证研究

时间:2022.12-2023.11

内容:通过构建统一的数据库逻辑框架,系统收集并分析了大量数据库缺陷。对777个缺陷进行了深入分析,特别聚焦SQL数据类型问题,并据此改进了模糊测试方法。

成果:构建缺陷数据集, 开发SQLT测试框架

网络协议漏洞挖掘项目

基于 RFC的 SSL/TLS模糊测试

时间:2024.4 – today

内容:梳理TLS协议模糊测试的相关工作,关注基于状态机的网络协议模糊测试方法。复现历史漏洞,了解TLS报文结构,追溯相关漏洞代码。分析RFC文档,提取字段约束,构建状态转移范式,并据此完善了TLS协议的有限状态机模型。

成果:完成相关工作调研, 漏洞复现报告, 状态范式数据集