智能小车(二):超声波模块与蜂鸣器模块
星期二, 10月 15, 2024 | 5分钟阅读 | 更新于 星期日, 12月 8, 2024
历史回顾
概要
本节课关注于超声波模块的使用和蜂鸣器模块的使用。超声波模块在小车中可以用于前方障碍物的距离测算,蜂鸣器模块可以用于小车速度,到障碍物距离等变量到达边界值时的声音提醒。
安全须知
超声波模块
实例代码
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);
}
代码详解
- 变量定义和引脚设置
- 定义
ad
和dianya
变量用于存储电压值 - 将蜂鸣器模块连接到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);
}