嵌入式入门教程
一 蜂鸣器
1.1 简介
蜂鸣器是一种常见的电子元件,用于产生声音信号:
结构:蜂鸣器通常由一个振膜和一个驱动电路组成。振膜是蜂鸣器的声音产生器,而驱动电路则控制振膜的振动。
工作原理:蜂鸣器通过电压驱动振膜振动,从而产生声音。振膜在电压变化时会产生振动,进而产生声音。声音的频率取决于振膜的振动频率,而声音的响度取决于电压的大小。
类型:蜂鸣器主要分为两种类型:压电式和电磁式。压电式蜂鸣器利用压电效应产生声音,而电磁式蜂鸣器则通过驱动电磁线圈产生声音。
用途:蜂鸣器广泛应用于各种电子设备和电路中,如警报系统、计时器、门铃、电子游戏等。它们用于产生声音信号以提醒用户、发出警报或指示特定的事件。
连接:蜂鸣器通常通过引脚连接到电路中。在连接蜂鸣器时,通常一个引脚连接到电源,另一个引脚连接到控制信号,以及可能的地线。
特性:蜂鸣器的特性包括声音的频率、响度、功耗以及尺寸等。这些特性影响着蜂鸣器的使用场景和性能表现。
总的来说,蜂鸣器是一种常用的电子元件,用于产生声音信号。它们在各种电子设备和项目中扮演着重要的角色,提供了一种简单而有效的方法来传达声音信息。
有源蜂鸣器:
有源蜂鸣器通常包括一个振荡器、放大器、以及共振腔等元件。与无源蜂鸣器不同的是,有源蜂鸣器内置驱动电路,可以直接通过DC电源进行驱动,无需外接交流信号。在Arduino中,有源蜂鸣器连接到数字或模拟输出引脚,通过改变输出的高低电平来控制蜂鸣器发声。
Arduino中的有源蜂鸣器通常需要外接一个可调节直流电源,如5V,用于驱动内部驱动电路。与无源蜂鸣器不同的是,在控制蜂鸣器时,将引脚输出设置为低电平(0V)即可打开蜂鸣器,将引脚输出设置为高电平(5V)即可关闭蜂鸣器。
无源蜂鸣器:
无源蜂鸣器通常由一个压电陶瓷薄片、振荡电路以及共振腔组成。在Arduino中,无源蜂鸣器连接到数字或模拟输出引脚,通过改变输出的高低电平来控制蜂鸣器发声。
Arduino中的无源蜂鸣器需要外接一个交流信号,利用交流电信号来驱动压电陶瓷薄片产生声音。在控制蜂鸣器时,将引脚输出设置为高电平(5V)即可打开蜂鸣器,将引脚输出设置为低电平(0V)即可关闭蜂鸣器。
对于UNO和大多数其他常用板,可以产生的最小频率是31Hz,可以产生的最大频率是65535Hz。但是,我们人类只能听到2000Hz至5000 Hz之间的频率。
tone()
函数可以在特定的引脚上生成特定的频率。如果需要,还可以提及持续时间。
noTone()函数 可以停止播放音符。
tone (pinName:引脚, Note Value:音调, Note Duration:持续时间);
noTone(pin:引脚);
1.2 基本使用
案例一:蜂鸣器发声
const int buzzerPin = 8; // 蜂鸣器连接的引脚
int frequency = 1000; // 初始频率设置为1000Hz
void setup() {
pinMode(buzzerPin, OUTPUT); // 设置蜂鸣器引脚为输出模式
}
void loop() {
// 产生声音
tone(buzzerPin, frequency); // 参数:引脚号,频率(Hz)
// 延时一段时间
delay(500); // 500毫秒
// 递增频率
frequency += 100; // 每次递增100Hz
// 如果频率超过2000Hz,重置为1000Hz
if (frequency > 2000) {
frequency = 1000;
}
}
案例二:使用电位器控制蜂鸣器声音
案例三: DIY钢琴 7键 7音
案例四:生日歌
const int buzzerPin = 8; // 蜂鸣器连接的引脚
// 生日歌音符数组(C调)
int melody[] = {
392, 392, 440, 392, 523, 494,
392, 392, 440, 392, 587, 523,
392, 392, 659, 622, 523, 494,
440, 698, 698, 659, 523, 587,
392, 392, 440, 392, 523, 494,
392, 392, 440, 392, 587, 523
};
// 生日歌音符持续时间数组(单位:毫秒)
int noteDurations[] = {
4, 4, 4, 4, 4, 2,
4, 4, 4, 4, 4, 2,
4, 4, 4, 4, 4, 2,
4, 4, 4, 4, 4, 2,
4, 4, 4, 4, 4, 2,
4, 4, 4, 4, 4, 2
};
void setup() {
pinMode(buzzerPin, OUTPUT); // 设置蜂鸣器引脚为输出模式
}
void loop() {
// 演奏生日歌
for (int i = 0; i < sizeof(melody) / sizeof(melody[0]); i++) {
int noteDuration = 1000 / noteDurations[i]; // 计算音符持续时间
tone(buzzerPin, melody[i], noteDuration); // 播放当前音符
delay(noteDuration * 1.3); // 等待一段时间,略长于音符持续时间
noTone(buzzerPin); // 停止播放音符
}
delay(2000); // 播放完毕后等待2秒再重复
}
**案例五:**四首音乐播放
// C++ code
//
#define NOTE_B0 31
#define NOTE_C1 33
#define NOTE_CS1 35
#define NOTE_D1 37
#define NOTE_DS1 39
#define NOTE_E1 41
#define NOTE_F1 44
#define NOTE_FS1 46
#define NOTE_G1 49
#define NOTE_GS1 52
#define NOTE_A1 55
#define NOTE_AS1 58
#define NOTE_B1 62
#define NOTE_C2 65
#define NOTE_CS2 69
#define NOTE_D2 73
#define NOTE_DS2 78
#define NOTE_E2 82
#define NOTE_F2 87
#define NOTE_FS2 93
#define NOTE_G2 98
#define NOTE_GS2 104
#define NOTE_A2 110
#define NOTE_AS2 117
#define NOTE_B2 123
#define NOTE_C3 131
#define NOTE_CS3 139
#define NOTE_D3 147
#define NOTE_DS3 156
#define NOTE_E3 165
#define NOTE_F3 175
#define NOTE_FS3 185
#define NOTE_G3 196
#define NOTE_GS3 208
#define NOTE_A3 220
#define NOTE_AS3 233
#define NOTE_B3 247
#define NOTE_C4 262
#define NOTE_CS4 277
#define NOTE_D4 294
#define NOTE_DS4 311
#define NOTE_E4 330
#define NOTE_F4 349
#define NOTE_FS4 370
#define NOTE_G4 392
#define NOTE_GS4 415
#define NOTE_A4 440
#define NOTE_AS4 466
#define NOTE_B4 494
#define NOTE_C5 523
#define NOTE_CS5 554
#define NOTE_D5 587
#define NOTE_DS5 622
#define NOTE_E5 659
#define NOTE_F5 698
#define NOTE_FS5 740
#define NOTE_G5 784
#define NOTE_GS5 831
#define NOTE_A5 880
#define NOTE_AS5 932
#define NOTE_B5 988
#define NOTE_C6 1047
#define NOTE_CS6 1109
#define NOTE_D6 1175
#define NOTE_DS6 1245
#define NOTE_E6 1319
#define NOTE_F6 1397
#define NOTE_FS6 1480
#define NOTE_G6 1568
#define NOTE_GS6 1661
#define NOTE_A6 1760
#define NOTE_AS6 1865
#define NOTE_B6 1976
#define NOTE_C7 2093
#define NOTE_CS7 2217
#define NOTE_D7 2349
#define NOTE_DS7 2489
#define NOTE_E7 2637
#define NOTE_F7 2794
#define NOTE_FS7 2960
#define NOTE_G7 3136
#define NOTE_GS7 3322
#define NOTE_A7 3520
#define NOTE_AS7 3729
#define NOTE_B7 3951
#define NOTE_C8 4186
#define NOTE_CS8 4435
#define NOTE_D8 4699
#define NOTE_DS8 4978
/*
The themes given below were converted from the piano sheet music
Code by : B.Aswinth Raj
Dated: 15-06-2017
Website: CircuitDigest.com
*/
//##############**"HE IS A PIRATE" Theme song of Pirates of caribbean**##############//
int Pirates_note[] = {
NOTE_D4, NOTE_D4, NOTE_D4, NOTE_D4, NOTE_D4, NOTE_D4, NOTE_D4, NOTE_D4,
NOTE_D4, NOTE_D4, NOTE_D4, NOTE_D4, NOTE_D4, NOTE_D4, NOTE_D4, NOTE_D4,
NOTE_D4, NOTE_D4, NOTE_D4, NOTE_D4, NOTE_D4, NOTE_D4, NOTE_D4, NOTE_D4,
NOTE_A3, NOTE_C4, NOTE_D4, NOTE_D4, NOTE_D4, NOTE_E4, NOTE_F4, NOTE_F4,
NOTE_F4, NOTE_G4, NOTE_E4, NOTE_E4, NOTE_D4, NOTE_C4, NOTE_C4, NOTE_D4,
0, NOTE_A3, NOTE_C4, NOTE_B3, NOTE_D4, NOTE_B3, NOTE_E4, NOTE_F4,
NOTE_F4, NOTE_C4, NOTE_C4, NOTE_C4, NOTE_C4, NOTE_D4, NOTE_C4,
NOTE_D4, 0, 0, NOTE_A3, NOTE_C4, NOTE_D4, NOTE_D4, NOTE_D4, NOTE_F4,
NOTE_G4, NOTE_G4, NOTE_G4, NOTE_A4, NOTE_A4, NOTE_A4, NOTE_A4, NOTE_G4,
NOTE_A4, NOTE_D4, 0, NOTE_D4, NOTE_E3, NOTE_F4, NOTE_F4, NOTE_G4, NOTE_A4,
NOTE_D4, 0, NOTE_D4, NOTE_F4, NOTE_E4, NOTE_E4, NOTE_F4, NOTE_D4
};
int Pirates_duration[] = {
4, 8, 4, 8, 4, 8, 8, 8, 8, 4, 8, 4, 8, 4, 8, 8, 8, 8, 4, 8, 4, 8,
4, 8, 8, 8, 8, 4, 4, 8, 8, 4, 4, 8, 8, 4, 4, 8, 8,
8, 4, 8, 8, 8, 4, 4, 8, 8, 4, 4, 8, 8, 4, 4, 8, 4,
4, 8, 8, 8, 8, 4, 4, 8, 8, 4, 4, 8, 8, 4, 4, 8, 8,
8, 4, 8, 8, 8, 4, 4, 4, 8, 4, 8, 8, 8, 4, 4, 8, 8
};
//###########End of He is a Pirate song#############//
//##############**"Crazy Frog" song of Crazy frog album**##############//
int CrazyFrog_note[] = {
NOTE_D4, 0, NOTE_F4, NOTE_D4, 0, NOTE_D4, NOTE_G4, NOTE_D4, NOTE_C4,
NOTE_D4, 0, NOTE_A4, NOTE_D4, 0, NOTE_D4, NOTE_AS4, NOTE_A4, NOTE_F4,
NOTE_D4, NOTE_A4, NOTE_D5, NOTE_D4, NOTE_C4, 0, NOTE_C4, NOTE_A3, NOTE_E4, NOTE_D4,
0, NOTE_D4, NOTE_D4
};
int CrazyFrog_duration[] = {
8, 8, 6, 16, 16, 16, 8, 8, 8,
8, 8, 6, 16, 16, 16, 8, 8, 8,
8, 8, 8, 16, 16, 16, 16, 8, 8, 2,
8, 4, 4
};
//###########End of Crazy Frog#############//
//##############**"Mario underworld" **##############//
int MarioUW_note[] = {
NOTE_C4, NOTE_C5, NOTE_A3, NOTE_A4, NOTE_AS3, NOTE_AS4, 0, 0,
NOTE_C4, NOTE_C5, NOTE_A3, NOTE_A4, NOTE_AS3, NOTE_AS4, 0, 0,
NOTE_F3, NOTE_F4, NOTE_D3, NOTE_D4, NOTE_DS3, NOTE_DS4, 0, 0,
NOTE_F3, NOTE_F4, NOTE_D3, NOTE_D4, NOTE_DS3, NOTE_DS4, 0,
0, NOTE_DS4, NOTE_CS4, NOTE_D4,
NOTE_CS4, NOTE_DS4, NOTE_DS4, NOTE_GS3, NOTE_G3, NOTE_CS4,
NOTE_C4, NOTE_FS4, NOTE_F4, NOTE_E3, NOTE_AS4, NOTE_A4,
NOTE_GS4, NOTE_DS4, NOTE_B3, NOTE_AS3, NOTE_A3, NOTE_GS3, 0, 0, 0
};
int MarioUW_duration[] = {
12, 12, 12, 12, 12, 12, 6, 3,
12, 12, 12, 12, 12, 12, 6, 3,
12, 12, 12, 12, 12, 12, 6,
3, 12, 12, 12, 12,
12, 12, 6, 6, 18, 18, 18,
6, 6, 6, 6, 6, 6,
18, 18, 18, 18, 18, 18, 10, 10, 10,
10, 10, 10, 3, 3, 3
};
//###########End of Mario underworld#############//
//##############**"Titanic" **##############//
int Titanic_note[] = {
NOTE_E4, NOTE_B4, NOTE_E5, NOTE_E5, NOTE_E5, NOTE_B4, NOTE_E4, NOTE_E4, NOTE_B4, NOTE_E5, NOTE_E5, NOTE_E5, NOTE_B4, NOTE_E4, NOTE_E4, NOTE_B4, NOTE_E5, NOTE_E5, NOTE_E5, NOTE_B4, NOTE_E4,
NOTE_E4, NOTE_B4, NOTE_E5, NOTE_E5, NOTE_E5, NOTE_D5, NOTE_E4, NOTE_B4, NOTE_E5, NOTE_E5, NOTE_E5, NOTE_B4, NOTE_E4, NOTE_E4, NOTE_B4, NOTE_E5, NOTE_E5, NOTE_E5, NOTE_B4, NOTE_F5,
NOTE_E4, NOTE_B4, NOTE_E5, NOTE_E5, NOTE_E5, NOTE_B4, NOTE_E4,
NOTE_E4, NOTE_B4, NOTE_E5, NOTE_E5, NOTE_E5, NOTE_D5, NOTE_E5, NOTE_E4, NOTE_E4, NOTE_E4, NOTE_D4, NOTE_B3, NOTE_E4, NOTE_E4, NOTE_E4, NOTE_B3, NOTE_E4,
NOTE_D4, NOTE_E4, NOTE_F4, NOTE_G4, NOTE_F4, NOTE_E4, NOTE_E4, NOTE_E4, NOTE_E4
};
int Titanic_duration[] = {
8, 8, 8, 8, 8, 8, 4, 8, 8, 8, 8, 8, 8, 4, 8, 8, 8, 8, 8, 8, 4, 8, 8, 8, 8, 4, 4, 8, 8, 8, 8, 8, 8, 4, 8, 8, 8, 8, 8, 8, 4, 8, 8, 8, 8, 8, 8, 1,
8, 8, 8, 8, 4, 4, 4, 8, 4, 4, 8, 8, 8, 8, 4, 8, 8, 4, 8, 4, 8, 8, 4, 8, 4, 1
};
//###########End of Titanic#############//
void Play_Pirates()
{
for (int thisNote = 0; thisNote < (sizeof(Pirates_note)/sizeof(int)); thisNote++) {
int noteDuration = 1000 / Pirates_duration[thisNote];//convert duration to time delay
tone(8, Pirates_note[thisNote], noteDuration);
int pauseBetweenNotes = noteDuration * 1.05; //Here 1.05 is tempo, increase to play it slower
delay(pauseBetweenNotes);
noTone(8); //stop music on pin 8
}
}
void Play_CrazyFrog()
{
for (int thisNote = 0; thisNote < (sizeof(CrazyFrog_note)/sizeof(int)); thisNote++) {
int noteDuration = 1000 / CrazyFrog_duration[thisNote]; //convert duration to time delay
tone(8, CrazyFrog_note[thisNote], noteDuration);
int pauseBetweenNotes = noteDuration * 1.30;//Here 1.30 is tempo, decrease to play it faster
delay(pauseBetweenNotes);
noTone(8); //stop music on pin 8
}
}
void Play_MarioUW()
{
for (int thisNote = 0; thisNote < (sizeof(MarioUW_note)/sizeof(int)); thisNote++) {
int noteDuration = 1000 / MarioUW_duration[thisNote];//convert duration to time delay
tone(8, MarioUW_note[thisNote], noteDuration);
int pauseBetweenNotes = noteDuration * 1.80;
delay(pauseBetweenNotes);
noTone(8); //stop music on pin 8
}
}
void Play_Titanic()
{
for (int thisNote = 0; thisNote < (sizeof(Titanic_note)/sizeof(int)); thisNote++) {
int noteDuration = 1000 / Titanic_duration[thisNote];//convert duration to time delay
tone(8, Titanic_note[thisNote], noteDuration);
int pauseBetweenNotes = noteDuration * 2.70;
delay(pauseBetweenNotes);
noTone(8); //stop music on pin 8
}
}
void setup() {
pinMode(2, INPUT_PULLUP); //Button 1 with internal pull up
pinMode(3, INPUT_PULLUP); //Button 2 with internal pull up
pinMode(4, INPUT_PULLUP); //Button 3 with internal pull up
pinMode(5, INPUT_PULLUP); //Button 4 with internal pull up
Serial.begin(9600);
}
void loop() {
if (digitalRead(2)==0)
{ Serial.println("Selected -> 'He is a Pirate' "); Play_Pirates(); }
if (digitalRead(3)==0)
{ Serial.println("Selected -> 'Crazy Frog' "); Play_CrazyFrog(); }
if (digitalRead(4)==0)
{ Serial.println("Selected -> 'Mario UnderWorld' "); Play_MarioUW(); }
if (digitalRead(5)==0)
{ Serial.println("Selected -> 'Titanic' "); Play_Titanic(); }
}
二 倾斜传感器
2.1 简介
倾斜传感器是一种用于检测物体相对于重力的倾斜角度的装置。它们可以在许多应用中提供精确的倾斜测量,例如水平仪、自动平衡系统、姿态控制:
- 工作原理:
- 倾斜传感器通常基于 MEMS(微电子机械系统)技术,其中包含微小的机械结构和传感器元件。
- 最常见的倾斜传感器是加速度计,它可以测量物体相对于重力的加速度,从而间接地确定倾斜角度。
- 倾斜传感器也可以是基于惯性导航原理的陀螺仪或倾斜开关等。
- 类型:
- 根据工作原理和测量范围的不同,倾斜传感器可以分为多种类型,包括单轴和双轴倾斜传感器、数字倾斜传感器、模拟倾斜传感器等。
- 另外,有些倾斜传感器还具有防水、防尘、耐高温等特性,适用于恶劣环境下的使用。
- 应用:
- 倾斜传感器在许多领域中得到广泛应用,包括建筑工程、航空航天、汽车工业、工程测量、医疗设备等。
- 在建筑工程中,倾斜传感器用于测量建筑物的倾斜角度,确保建筑结构的稳定性和垂直度。
- 在汽车工业中,倾斜传感器用于车辆的动态稳定控制系统,如车辆的自动驾驶、车身稳定控制等。
- 在医疗设备中,倾斜传感器用于测量患者的体位、床位倾斜角度等,以便进行康复治疗或手术操作。
- 优势和特点:
- 倾斜传感器具有高精度、快速响应、稳定可靠、易于集成和使用等优点。
- 它们可以实时监测倾斜角度,并根据需要进行自动控制和调整,提高工作效率和安全性。
2.2 基本使用
- 检测震动和倾斜的传感器:
const int tiltSensorPin = A0; // 倾斜传感器连接的模拟输入引脚
void setup() {
Serial.begin(9600); // 初始化串口通信,波特率为 9600
}
void loop() {
// 读取传感器数据
int sensorValue = analogRead(tiltSensorPin);
// 将传感器数据转换为倾斜角度(示例中假设倾斜传感器输出的是模拟电压值)
float tiltAngle = map(sensorValue, 0, 1023, -90, 90); // 将模拟值映射到 -90 到 90 度之间
// 打印倾斜角度到串口
Serial.print("Tilt Angle: ");
Serial.println(tiltAngle);
delay(1000); // 等待一段时间后重复读取数据
}
-
当作开关,通过滚珠的滚动 控制电路开关
#define InclinePin 2 void setup(){ Serial.begin(9600); pinMode(InclinePin ,OUTPUT); } void loop(){ digitalWrite(InclinePin,HIGH); }
2.3 报警器
const int tiltSensorPin = A0; // 倾斜传感器连接的模拟输入引脚
const int buzzerPin = 8; // 蜂鸣器连接的数字输出引脚
int threshold = 1000; // 设置倾斜传感器的阈值,根据实际情况调整
void setup() {
Serial.begin(9600); // 初始化串口通信,波特率为 9600
pinMode(tiltSensorPin, INPUT); // 设置倾斜传感器引脚为输入模式
pinMode(buzzerPin, OUTPUT); // 设置蜂鸣器引脚为输出模式
}
void loop() {
int sensorValue = analogRead(tiltSensorPin); // 读取倾斜传感器的值
// 如果倾斜传感器的值超过阈值,触发报警
if (sensorValue > threshold) {
digitalWrite(buzzerPin, HIGH); // 打开蜂鸣器
delay(1000); // 持续响铃1秒钟
digitalWrite(buzzerPin, LOW); // 关闭蜂鸣器
delay(1000); // 停止1秒钟
}
}
三 土壤湿度传感器
3.1 介绍
土壤湿度传感器是一种用于测量土壤中水分含量的传感器。它们通常用于农业、园艺和植物生长监测等应用中,帮助确定何时需要灌溉或浇水。以下是土壤湿度传感器的基本信息:
- 工作原理:
- 土壤湿度传感器通常利用两个电极之间的电阻变化来测量土壤的湿度。
- 当土壤湿度增加时,土壤的电导率增加,导致电极之间的电阻减小;相反,当土壤干燥时,电导率减小,导致电极之间的电阻增加。
- 类型:
- 土壤湿度传感器可分为模拟型和数字型。
- 模拟型土壤湿度传感器输出一个模拟电压信号,其大小与土壤湿度成正比。
- 数字型土壤湿度传感器通过数字接口输出湿度值,通常具有更高的精度和稳定性。
- 应用:
- 农业灌溉:土壤湿度传感器可用于监测土壤湿度,以确定何时需要灌溉或浇水,从而节省水资源并提高农作物的产量和质量。
- 园艺和植物生长监测:在园艺和植物种植中,土壤湿度传感器可以帮助确定适当的浇水频率和量,以促进植物生长。
- 实验室和研究:土壤湿度传感器也常用于实验室研究和学术研究中,用于土壤湿度的定量分析和监测。
- 优势和特点:
- 土壤湿度传感器具有响应迅速、易于使用、精度高、可靠性好等优点。
- 它们可以在实时监测土壤湿度的同时,帮助减少浪费并提高土壤水分的利用效率。
连接土壤湿度传感器到 Arduino 很简单,一般来说,土壤湿度传感器有两个或三个引脚:VCC(电源)、GND(地)、以及一个 AO(模拟输出)引脚(有些传感器可能会有数字输出引脚)。
以下是如何连接一个典型的土壤湿度传感器到 Arduino 的示例:
- 连接到电源和地:
- 将传感器的 VCC 引脚连接到 Arduino 板上的 5V 引脚。
- 将传感器的 GND 引脚连接到 Arduino 板上的 GND 引脚。
- 连接到模拟输入引脚(可选):
- 将传感器的 AO 引脚连接到 Arduino 板上的模拟输入引脚(如 A0)。
- 连接到数字输入引脚(可选):
- 如果您的传感器有数字输出引脚,您可以将其连接到 Arduino 板上的数字输入引脚。
这就是基本的连接方式。接下来,编写 Arduino 代码来读取传感器的值,并据此进行相应的操作,比如监测土壤湿度并在需要时灌溉植物。如果您有具体的传感器型号,可以参考其 datasheet 获取更详细的连线说明。
3.2 基本使用
const int soilMoisturePin = A0; // 土壤湿度传感器连接的模拟输入引脚
void setup() {
Serial.begin(9600); // 初始化串口通信,波特率为 9600
}
void loop() {
int soilMoistureValue = analogRead(soilMoisturePin); // 读取土壤湿度传感器的模拟输出值
Serial.print("Soil Moisture: ");
Serial.println(soilMoistureValue); // 打印土壤湿度值到串口监视器
delay(1000); // 延迟一秒钟
}
3.3 绿植湿度检测
const int soilMoisturePin = A0; // 土壤湿度传感器连接的模拟输入引脚
const int greenLedPin = 2; // 绿色 LED 灯连接的数字输出引脚
const int yellowLedPin = 3; // 黄色 LED 灯连接的数字输出引脚
const int redLedPin = 4; // 红色 LED 灯连接的数字输出引脚
void setup() {
pinMode(greenLedPin, OUTPUT); // 设置绿色 LED 引脚为输出模式
pinMode(yellowLedPin, OUTPUT); // 设置黄色 LED 引脚为输出模式
pinMode(redLedPin, OUTPUT); // 设置红色 LED 引脚为输出模式
}
void loop() {
int soilMoistureValue = analogRead(soilMoisturePin); // 读取土壤湿度传感器的模拟输出值
// 根据土壤湿度水平点亮不同颜色的 LED 灯
if (soilMoistureValue >= 700) { // 湿度严重不足
digitalWrite(redLedPin, HIGH);
digitalWrite(yellowLedPin, LOW);
digitalWrite(greenLedPin, LOW);
} else if (soilMoistureValue >= 400 && soilMoistureValue < 700) { // 湿度较低
digitalWrite(redLedPin, LOW);
digitalWrite(yellowLedPin, HIGH);
digitalWrite(greenLedPin, LOW);
} else { // 湿度正常
digitalWrite(redLedPin, LOW);
digitalWrite(yellowLedPin, LOW);
digitalWrite(greenLedPin, HIGH);
}
delay(1000); // 每隔一秒钟检测一次土壤湿度
}
四 LCD
1.1 简介
LCD 16x2 是一种常用的字符型液晶显示器,它可以显示两行每行最多显示 16 个字符。这种液晶显示器通常用于各种嵌入式系统、Arduino 项目以及其他电子设备中,用于显示文本信息和简单的图形。
以下是关于 LCD 16x2 的基本信息:
结构:
- LCD 16x2 由 16 列和 2 行字符构成,总共可以显示 32 个字符。
- 它通常由一个字符型液晶屏和一个背光板组成,字符型液晶屏包含显示字符的像素阵列。
特性:
- LCD 16x2 具有显示字符型文本的功能,可以显示字母、数字、符号等。
- 通常具有背光功能,可以在暗处或者光线较暗的环境下提供良好的可视性。
- 可以通过电子控制器(如 HD44780)来控制 LCD 的操作,实现显示、清除、光标控制等功能。
使用:
- 使用 LCD 16x2 需要连接到微控制器或者其他控制器上,例如 Arduino、树莓派等。
- 通过设置控制器的输出信号,可以控制 LCD 显示内容、光标位置等。
- 可以通过调用相应的库函数或者直接发送命令来控制 LCD 的操作,例如显示字符、清除屏幕、移动光标等。
应用:
-
LCD 16x2 可以用于各种嵌入式系统中,用于显示系统状态、用户界面等信息。
-
在 Arduino 项目中,LCD 16x2 可以用于显示传感器数据、计时器、计数器等实时信息。
-
在电子设备中,LCD 16x2 可以用于显示设备的名称、参数、警告信息等。
1.2 使用
-
引脚介绍
引脚 | 连接 |
---|---|
PIN1或VSS | 接地 |
PIN2或VDD或VCC | + 5v电源 |
PIN3或VEE或V0 | 对比度调整,接地(为初学者提供最大对比度),接正极时对比度最弱 |
PIN4或RS(寄存器选择) | ARDUINO UNO的PIN0,1数据寄存器(DR),0指令寄存器(IR) |
PIN5或RW(读/写) | RW为读写信号线,高电平(1)时进行读操作,低电平(0)时进行写操作。接地(将LCD置于读模式可简化用户的通信) |
PIN6或E(启用) | ARDUINO UNO的PIN1 ,高电平读取信息,负跳变时执行指令 |
PIN11 or D4 | PIN8 of ARDUINO UNO |
PIN12 or D5 | PIN9 of ARDUINO UNO |
PIN13 or D6 | PIN10 of ARDUINO UNO |
PIN14 or D7 | PIN11 of ARDUINO UNO |
PIN15 或 BLA 或A | 背光正极,可选,可以直接接3.3V或接5V添加10KΩ电阻 |
PIN16或BLK 或K | 背光负极,可选 |
LCD 16x2 液晶显示器 | Arduino |
---|---|
VSS | GND |
VCC | 5V |
VO | GND |
RS | 数字引脚 12 |
RW | GND |
E | 数字引脚 11 |
D4 | 数字引脚 5 |
D5 | 数字引脚 4 |
D6 | 数字引脚 3 |
D7 | 数字引脚 2 |
A | 5V (背光正极) |
K | GND (背光负极) |
-
LiquidCrystal库介绍
LiquidCrystal是一个1602的IIC库,使用IIC协议可以极大节约用线数量,十分方便。当然,前提是1602要使用LCD1602 I2C模块。
-
常用函数
LiquidCrystal() //构造函数 c++ 构造函数,创建一个LiquidCrystal的实例(LiquidCrystal是一个类)。可使用4线或8线方式作为数据线(请注意,还需要指令线).若采用四线方式,将d0-d3悬空不连接.RW引脚可接地而不用接在Arduino的某个引脚上;如果这样接,省略在函数中的rw参数. LiquidCrystal(rs, enable, d4, d5, d6, d7) LiquidCrystal(rs, rw, enable, d4, d5, d6, d7) LiquidCrystal(rs, enable, d0, d1, d2, d3, d4, d5, d6, d7) LiquidCrystal(rs, rw, enable, d0, d1, d2, d3, d4, d5, d6, d7) rs: rs连接的Arduino的引脚编号 rw: rw连接的Arduino的引脚编号 enable:enable连接的Arduino的引脚编号 d0, d1, d2, d3, d4, d5, d6, d7: 连接的Arduino的引脚编号 #include <LiquidCrystal.h> LiquidCrystal lcd(12, 11, 10, 5, 4, 3, 2); void setup() { lcd.print("hello, world!"); } print()函数 将文本显示在LCD上 lcd.print(data) //针对字符串 lcd.print(data, BASE) data:要显示的数据,可以是char, byte, int, long或者string类型的 BASE (optional): 数制(可选),BIN,DEC,OCT,HEX分别将数字以二进制,十进制,八进制,十六进制方式显示 出来. 返回值: byte //这个返回值通常是用不到的 begin()函数 内容: 指定显示屏的尺寸(宽度和高度)。 lcd.begin(cols, rows) cols: 显示器可以显示的列数(1602是16列) rows: 显示器可以显示的行数(1602是2行) clear() 清除LCD屏幕上内容,并将光标置于左上角。 home() 将光标定位在屏幕左上角. 就是说,接下来的字符从屏幕左上角开始显示.如果同时要清除屏幕上的内容,请使用 clear()函数代替. setCursor() 将光标定位在特定的位置。 lcd.setCursor(col, row) lcd:LiquidCrystal类的对象 col: 你要显示光标的列 (从0开始计数) row: 你要显示光标的行 (从0开始计数) write() (在光标处)显示一个字符 你要显示的字符(仅限英文、数字和自定义字符)。 void setup() { Serial.begin(9600); } void loop() { if (Serial.available()) { lcd.write(Serial.read()); } } Serial.available()函数在Arduino模拟器中的作用是返回串口缓冲区中当前剩余的字符个数。 这个函数通常用于判断串口的缓冲区是否有数据。当Serial.available()的值大于0时,说明串口接收到了数据,可以进行读取。Serial.read()函数则用于从串口的缓冲区中取出并读取一个字节的数据。这种机制使得Arduino能够有效地处理通过串口发送的数据,无论是从外部设备还是通过模拟器接收到的数据。 cursor() 显示光标(就是一个下划线) noCursor() 不显示光标 blink() 光标闪烁(和8,9一起使用时不保证效果) noBlink() 光标不闪烁 noDisplay() 关闭显示,但不会丢失内容 display() (使用noDisplay后)恢复显示 scrollDisplayLeft() 将显示的内容向左滚动一格 scrollDisplayRight() 将显示的内容向右滚动一格 autoscroll() 打开自动滚动 打开液晶显示屏的自动滚动,将会使得当一个字符输出到LCD时,令先前的文本移动一个位置.如果当前写入方向为由左到右(默认方向),文本向左滚动.反之,文本向右滚动.它的功能可以理解为,当输出单个字符时,会使得字符总是输出在LCD上的同一个位置. noAutoscroll() 关闭自动滚动 leftToRight() 从左向右显示内容(默认) rightToLeft() 从右向左显示内容 createChar() 创造字符 byte smiley[8] = { //1表示亮,0表示不亮,此例显示一个笑脸 B00000, B10001, B00000, B00000, B10001, B01110, B00000, }; void setup() { int x=1; //x可以为0~7的任何数字 lcd.createChar(x , smiley); //将x号字符设置为smiley数组表示的样子 lcd.begin(16, 2); lcd.write(x); } void loop() {}
-
-
接线
#include <LiquidCrystal.h>
// 初始化 LCD 对象,参数依次是 RS、E、D4、D5、D6、D7 引脚
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
void setup() {
// 设置 LCD 显示的列数和行数
lcd.begin(16, 2);
// 在 LCD 的第一行显示“Hello, World!”
lcd.setCursor(0, 0);
lcd.print("Hello, World!");
// 在 LCD 的第二行显示“你好世界”
lcd.setCursor(0, 1);
lcd.print("hello China!");
}
void loop() {
// 代码只在setup()中运行一次,loop()函数可以为空
}
1.3 跑马灯
#include <LiquidCrystal.h>
// 初始化 LCD 对象,参数依次是 RS、E、D4、D5、D6、D7 引脚
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
void setup() {
// 设置 LCD 显示的列数和行数
lcd.begin(16, 2);
}
void loop() {
// 从左到右滚动显示 "Hello"
for (int i = 0; i <= 11; i++) {
lcd.clear();
lcd.setCursor(i, 0);
lcd.print("Hello");
delay(300);
}
// 从右到左滚动显示 "Hello"
for (int i = 11; i >= 0; i--) {
lcd.clear();
lcd.setCursor(i, 0);
lcd.print("Hello");
delay(300);
}
}
五 温度传感器
2.1 简介
温度传感器是一种用于测量环境温度的设备,它能够将温度转换为电信号或数字信号输出。常见的温度传感器有许多种,包括模拟型和数字型传感器,以及不同的工作原理和接口类型。以下是关于温度传感器的基本信息:
结构和工作原理:
- 模拟型温度传感器:模拟型温度传感器通过改变其 内部的电阻、电压或电流来反映环境温度的变化。这些传感器通常使用热敏电阻(thermistor)、热敏电阻(RTD)或半导体温度传感器等技术。
- 数字型温度传感器:数字型温度传感器通过内部的数字电路直接将温度转换为数字信号输出。常见的数字型温度传感器包括数字温度传感器(DS18B20)、集成温度传感器(LM35)等。
- 工作原理:温度传感器根据物体温度对其内部电学特性的影响,将温度转换为电压、电阻或数字信号输出。这些信号可以通过电路进行处理,最终转换为人们可以理解的温度值。
类型和接口:
- 模拟型接口:模拟型温度传感器输出模拟信号,通常需要使用模拟输入引脚连接到微控制器或模拟输入设备上。
- 数字型接口:数字型温度传感器通过数字接口(如I2C、SPI、OneWire等)直接与微控制器或其他数字设备通信,输出数字信号。
应用领域:
- 工业自动化:用于监测生产过程中的温度变化,保证生产环境的稳定性和安全性。
- 环境监测:用于测量气候条件,如室内外温度、湿度等,以便进行环境监测和调控。
- 消费电子:用于智能手机、电脑、家电等设备中,以提供温度监测和保护功能。
2.2 基本使用
// 定义温度传感器引脚
const int temperaturePin = A0;
void setup() {
// 初始化串口通信
Serial.begin(9600);
}
void loop() {
// 读取模拟型温度传感器的值
int sensorValue = analogRead(temperaturePin);
Serial.println(sensorValue);
// 转换传感器读数为摄氏温度 0~5v 0-1024
float voltage = sensorValue * (5.0 / 1023.0); // 将模拟读数转换为电压
float temperatureC = (voltage - 0.5 ) * 100.0; // 根据传感器的输出电压计算摄氏温度
// 在串口上显示温度值
Serial.print("Temperature (C): ");
Serial.println(temperatureC);
// 延时一段时间后再次读取温度
delay(1000);
}
在Arduino中,模拟输入引脚返回的值是一个0到1023之间的数字,对应着传感器的电压值。
要将传感器输出的模拟值转换为电压值,可以使用以下公式:
voltage
=
sensorValue
1023
×
Vref
v
o
l
t
a
g
e
=
1023
s
e
n
s
o
r
V
a
l
u
e
×
V
r
e
f
\text{voltage} = \frac{\text{sensorValue}}{1023} \times \text{Vref}voltage=1023sensorValue×Vref
voltage=1023sensorValue×Vrefvoltage=1023sensorValue×Vref
其中,sensorValue 是传感器输出的模拟值,Vref 是Arduino的参考电压。在大多数情况下,Vref 是Arduino的供电电压,通常为5V。
所以,对于您的情况,可以使用以下代码来将传感器的模拟值转换为电压值:
float voltage = sensorValue * (5.0 / 1023.0);
这将确保您得到的电压值在0到5V之间。然后,您可以根据传感器的特性将电压值转换为温度或其他需要的物理量。
2.3 温度显示LCD
#include <LiquidCrystal.h>
// 模拟型温度传感器引脚连接
const int tempSensorPin = A0; // 模拟输入引脚连接到模拟型温度传感器的输出
// LCD 引脚连接
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
void setup() {
// 初始化 LCD
lcd.begin(16, 2);
// 显示初始消息到 LCD
lcd.print("Temperature:");
}
void loop() {
// 读取模拟型温度传感器的输出值
int sensorValue = analogRead(tempSensorPin);
// 将传感器输出值转换为摄氏温度
float voltage = sensorValue * (5.0 / 1023.0); // 将模拟读数转换为电压
float temperatureC = (voltage - 0.5) * 100.0; // 根据传感器的输出电压计算摄氏温度
// 清除原始的温度显示
lcd.setCursor(0, 1);
lcd.print(" "); // 清除原始温度显示
// 显示温度到 LCD
lcd.setCursor(0, 1);
lcd.print(temperatureC, 1); // 显示温度值,保留一位小数
// 延时一段时间,以便观察温度值变化
delay(1000);
}
V。
所以,对于您的情况,可以使用以下代码来将传感器的模拟值转换为电压值:
float voltage = sensorValue * (5.0 / 1023.0);
这将确保您得到的电压值在0到5V之间。然后,您可以根据传感器的特性将电压值转换为温度或其他需要的物理量。
2.3 温度显示LCD
[外链图片转存中…(img-Cao95xiI-1720531889490)]
#include <LiquidCrystal.h>
// 模拟型温度传感器引脚连接
const int tempSensorPin = A0; // 模拟输入引脚连接到模拟型温度传感器的输出
// LCD 引脚连接
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
void setup() {
// 初始化 LCD
lcd.begin(16, 2);
// 显示初始消息到 LCD
lcd.print("Temperature:");
}
void loop() {
// 读取模拟型温度传感器的输出值
int sensorValue = analogRead(tempSensorPin);
// 将传感器输出值转换为摄氏温度
float voltage = sensorValue * (5.0 / 1023.0); // 将模拟读数转换为电压
float temperatureC = (voltage - 0.5) * 100.0; // 根据传感器的输出电压计算摄氏温度
// 清除原始的温度显示
lcd.setCursor(0, 1);
lcd.print(" "); // 清除原始温度显示
// 显示温度到 LCD
lcd.setCursor(0, 1);
lcd.print(temperatureC, 1); // 显示温度值,保留一位小数
// 延时一段时间,以便观察温度值变化
delay(1000);
}
作业 : 温度警报器