🔧 Arduino开源硬件 - 课程16-32

本部分包含课程16至32,涵盖陀螺仪平衡训练器、超声波倒车雷达、烟雾传感器、射频卡身份识别、智能小车等项目。

📚 课程16:平衡训练器(MPU6050陀螺仪)

🎯 确定任务: 将传感器穿戴在手臂上,当手臂倾斜角度超过15度时,蜂鸣器响起提醒。
📊 程序流程图:
开始
  ↓
初始化MPU6050陀螺仪
  ↓
校准传感器(读取偏移量)
  ↓
┌─────────────────────────┐
│ 读取X、Y轴倾斜角度      │
│   ↓                    │
│ 角度 > 15度?          │
│   ↓是         ↓否      │
│ 蜂鸣器响    蜂鸣器静   │
│   ↓                    │
│ 短暂延时               │
└─────────────────────────┘
            
#include "MPU6050.h"
MPU6050 mpu;
int16_t ax, ay, az; float agx, agy;
void setup() { mpu.initialize(); }
void loop() {
  mpu.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
  agx = atan2(ay, az) * 180 / PI; // X轴角度
  agy = atan2(ax, az) * 180 / PI; // Y轴角度
  if(abs(agx) > 15 || abs(agy) > 15){
    tone(9, 440, 100); delay(100);
  }
}
📖 知识点详解:
陀螺仪(MPU6050): 包含3轴陀螺仪和3轴加速度计,可测量物体在X、Y、Z三个方向的旋转角速度。
姿态解算: 通过加速度计计算倾角公式:angle = atan2(ay, az) × 180/π。
卡尔曼滤波: 融合加速度计和陀螺仪数据,得到更平滑、准确的角度值。
应用: 平衡车、无人机姿态控制、体感游戏、姿势矫正器。

📚 课程17:倒车雷达(超声波+蜂鸣器)

🎯 确定任务: 当障碍物距离小于100cm时蜂鸣器报警,距离越近报警声越急促。
📊 程序流程图:
开始
  ↓
定义超声波测距函数
  ↓
┌─────────────────────────┐
│ 测量距离(cm)          │
│   ↓                    │
│ 距离 < 100cm?         │
│   ↓是                  │
│ 蜂鸣器响(频率随距离变化)│
│   ↓                    │
│ 等待(时间随距离变化)   │
└─────────────────────────┘
            
float getDistance(int trig, int echo){
  pinMode(trig,OUTPUT); digitalWrite(trig,LOW); delayMicroseconds(2);
  digitalWrite(trig,HIGH); delayMicroseconds(10); digitalWrite(trig,LOW);
  pinMode(echo,INPUT); return pulseIn(echo,HIGH,30000)/58.0;
}
void loop() {
  float d = getDistance(13,12);
  if(d < 100){
    tone(9, 440, 125); delay(125); delay(d/50*1000);
  }
}
📖 知识点详解:
超声波测距原理: 发射40kHz超声波,测量回声时间。距离 = 高电平时间 × 声速(340m/s) ÷ 2。
pulseIn()函数: 测量引脚高电平持续时间(微秒),超时可设。
声速与温度: 声速 v = 331.5 + 0.6×温度(℃),室温下约343m/s,转换为0.0343cm/μs。
报警逻辑: 距离越近,两次报警间隔越短,产生急促感。

📚 课程18:自动排烟器(MQ-2烟雾传感器)

🎯 确定任务: 当检测到烟雾(液化气、丁烷、丙烷、甲烷、酒精、氢气、烟雾等)时,自动启动排气扇。
📊 程序流程图:
开始
  ↓
初始化:A0为输入,13为输出
  ↓
┌─────────────────────────┐
│ 读取烟雾传感器值        │
│   ↓                    │
│ 值 > 阈值?            │
│   ↓是         ↓否      │
│ 启动排气扇   关闭排气扇 │
└─────────────────────────┘
            
void loop() {
  if(analogRead(A0) > 500) digitalWrite(13, HIGH);
  else digitalWrite(13, LOW);
}
📖 知识点详解:
MQ-2气体传感器: 检测多种可燃气体和烟雾,需预热1-2分钟。
灵敏度调节: 通过板载电位器调节阈值,顺时针增大灵敏度。
常见气体检测值: 液化气约200-400,烟雾约400-800,酒精约300-600(不同环境有差异)。
安全提示: 检测到烟雾时自动打开风扇排烟,可防止煤气泄漏事故。

📚 课程19:遥控闸机(红外遥控+舵机)

🎯 确定任务: 使用遥控器控制舵机(闸机),按开关键闸机打开,按关关键闸机关闭。
📊 程序流程图:
开始
  ↓
初始化红外接收、舵机
  ↓
┌─────────────────────────┐
│ 等待红外信号            │
│   ↓                    │
│ 接收到信号?           │
│   ↓是                  │
│ 解码按键值              │
│   ↓                    │
│ 判断:开关键?关关键?  │
│   ↓                    │
│ 舵机转到0度/90度       │
└─────────────────────────┘
            
#include <Servo.h> #include <IRremote.h>
Servo myservo; IRrecv irrecv(11); decode_results results;
void setup(){ myservo.attach(9); irrecv.enableIRIn(); }
void loop() {
  if(irrecv.decode(&results)){
    if(results.value==0x5826B924) myservo.write(90); // 开
    if(results.value==0x5926BABB) myservo.write(0); // 关
    irrecv.resume();
  }
}
📖 知识点详解:
舵机(Servo): 可精确控制角度(0-180度),内部有直流电机、减速齿轮和位置反馈电位器。
Servo库: write(角度)设置目标角度,attach(引脚)绑定舵机信号线。
红外学习: 使用IRrecvDemo示例读取遥控器按键值,替换程序中的编码。
闸机种类: 抬升式、平开式、拉伸式、推拉式,舵机适合小扭矩应用。

📚 课程20:防雨窗户(雨量传感器+舵机)

🎯 确定任务: 检测到下雨时,舵机带动窗户模型自动关闭,天晴时自动打开。
📊 程序流程图:
开始
  ↓
初始化:A0为输入,舵机引脚9
  ↓
┌─────────────────────────┐
│ 读取雨量传感器值        │
│   ↓                    │
│ 值 > 阈值(有雨)?     │
│   ↓是         ↓否      │
│ 舵机转到90度(关窗)    │
│               舵机转到0度(开窗)│
└─────────────────────────┘
            
#include <Servo.h>
Servo myservo;
void setup(){ myservo.attach(9); }
void loop() {
  if(analogRead(A0) > 500) myservo.write(90);
  else myservo.write(0);
}
📖 知识点详解:
雨量传感器: 板上有裸露的蛇形铜线,利用水的导电性,水滴使电路导通,电阻变小,ADC值变大。
排水设计: 传感器一般倾斜安装,让水能流走,恢复干燥状态。
雨量计历史: 中国南宋秦九韶发明“天池测雨”,是世界最早的雨量器。
应用: 智能晾衣架、自动关窗系统、农业大棚。

📚 课程21:温湿度显示仪(DHT11+OLED)

🎯 确定任务: 实时显示环境温度和湿度,数据每秒刷新一次。
📊 程序流程图:
开始
  ↓
初始化OLED屏和DHT11
  ↓
┌─────────────────────────┐
│ 读取温度和湿度          │
│   ↓                    │
│ 格式化显示到OLED        │
│   ↓                    │
│ 等待1秒                 │
└─────────────────────────┘
            
#include <DHT.h> #include <Adafruit_SSD1306.h>
DHT dht(3, DHT11); Adafruit_SSD1306 display(128,64,&Wire,4);
void setup(){ dht.begin(); display.begin(SSD1306_SWITCHCAPVCC,0x3C); }
void loop(){
  float t = dht.readTemperature(); float h = dht.readHumidity();
  display.clearDisplay(); display.setCursor(0,0);
  display.println("Temp: " + String(t) + " C");
  display.println("Hum: " + String(h) + " %");
  display.display(); delay(1000);
}
📖 知识点详解:
DHT11数字温湿度传感器: 单总线通信,温度范围0-50℃,湿度20-90%RH。
OLED屏(0.96寸): I2C接口(SDA→A4,SCL→A5),128x64分辨率,可显示图形和文字。
I2C地址: OLED屏常用地址0x3C或0x3D,可用I2C扫描程序获取。
华氏温标: ℉ = ℃ × 1.8 + 32,掌握换算关系。

📚 课程22:测距仪(超声波+OLED)

🎯 确定任务: 实时测量距离,显示在OLED屏幕上,单位厘米。
📊 程序流程图:
开始
  ↓
初始化OLED和超声波引脚
  ↓
┌─────────────────────────┐
│ 测量距离                │
│   ↓                    │
│ 显示距离值 + "cm"       │
│   ↓                    │
│ 等待0.2秒               │
└─────────────────────────┘
            
float getDistance(){ ... }
void loop(){
  float d = getDistance(13,12);
  display.clearDisplay(); display.setCursor(0,0);
  display.println("Distance:");
  display.println(String(d) + "cm");
  display.display(); delay(200);
}
📖 知识点详解:
自定义函数: 将测距代码封装为float getDistance()函数,方便调用。
浮点数显示: String(d)将浮点数转为字符串,可控制小数点位数如String(d,1)。
显示布局: setCursor(列,行)设置显示位置,行高根据字体大小决定。
应用: 倒车雷达、液位检测、机器人避障。

📚 课程23:随机出题机(10以内乘法)

🎯 确定任务: 按一下按键,OLED屏随机显示一道10以内乘法算式(如5×3=)。
📊 程序流程图:
开始
  ↓
初始化OLED,设置随机种子
  ↓
┌─────────────────────────┐
│ 生成两个0-9随机数       │
│   ↓                    │
│ 显示算式"a×b="         │
│   ↓                    │
│ 等待按键按下            │
│   ↓                    │
│ 检测按键释放            │
└─────────────────────────┘
            
void loop(){
  int a = random(0,9); int b = random(0,9);
  display.clearDisplay(); display.setCursor(0,0);
  display.println(String(a)+"x"+String(b)+"=");
  display.display();
  while(digitalRead(12)==0){} // 等待按键
  while(digitalRead(12)==1){} // 等待释放
}
📖 知识点详解:
randomSeed(): 用analogRead(0)等未连接引脚作为种子,让每次开机随机序列不同。
字符串拼接: String(a)+"x"+String(b)+"="生成完整算式。
按键等待: 两个while循环分别等待按下和释放,实现“按一下刷新一次”。
教育应用: 可扩展为加减乘除、英语单词、选择题等学习工具。

📚 课程24:单词宝(随机显示单词)

🎯 确定任务: 按一次按键,随机显示一个英文单词(可自定义单词库)。
📊 程序流程图:
开始
  ↓
定义单词数组 words[]
  ↓
┌─────────────────────────┐
│ 随机选取一个单词        │
│   ↓                    │
│ 显示到OLED              │
│   ↓                    │
│ 等待按键按下            │
└─────────────────────────┘
            
String words[]={"apple","banana","cat","dog","elephant","fish","green","happy","ice","jump"};
int wordCount = sizeof(words)/sizeof(words[0]);
void loop(){
  display.clearDisplay(); display.setCursor(0,0);
  display.println(words[random(wordCount)]);
  display.display();
  while(digitalRead(12)==0){} while(digitalRead(12)==1){}
}
📖 知识点详解:
数组定义: String words[] = {...}创建字符串数组,元素用逗号隔开。
sizeof运算符: sizeof(words)返回总字节数,sizeof(words[0])返回单个元素字节数,除法得到元素个数。
随机访问: words[random(wordCount)]随机选取一个单词。
扩展: 可增加音标、例句,或配合蜂鸣器拼读。

📚 课程25:反应速度测试仪

🎯 确定任务: 10秒内快速按键,计数总按键次数,测试反应速度。
📊 程序流程图:
开始
  ↓
倒计时3秒提示
  ↓
记录起始时间(millis)
  ↓
┌─────────────────────────┐
│ 当前时间-起始时间<10秒  │
│   ↓                    │
│ 等待按键按下→计数+1     │
│   ↓                    │
│ 等待按键释放            │
│   ↓                    │
│ 实时显示当前计数        │
└─────────────────────────┘
  ↓
10秒结束,显示总次数
            
int count=0; unsigned long startTime;
void setup(){ pinMode(12,INPUT); }
void loop(){
  count=0; delay(3000); // 倒计时
  startTime = millis();
  while(millis()-startTime < 10000){
    if(digitalRead(12)==0){ count++; while(digitalRead(12)==0){} }
    display显示count;
  }
  显示总次数; delay(5000);
}
📖 知识点详解:
millis()计时: 返回开机运行的毫秒数,不占用CPU,比delay精确。
防抖处理: 在检测到按键后,用while等待释放,避免一次按压多次计数。
实时刷新: 在循环中更新显示,让测试者看到当前已按次数。
数据分析: 反应速度越快,10秒内按键次数越多,可作为趣味比赛。

📚 课程26:身份识别器(RFID读卡)

🎯 确定任务: 刷卡时识别卡号,在OLED上显示对应的用户姓名。
📊 程序流程图:
开始
  ↓
初始化RFID模块和OLED
  ↓
┌─────────────────────────┐
│ 等待新卡靠近            │
│   ↓                    │
│ 读取卡号(4字节)       │
│   ↓                    │
│ 卡号转换为字符串        │
│   ↓                    │
│ 在数据库中查找对应姓名  │
│   ↓                    │
│ 显示姓名到OLED          │
└─────────────────────────┘
            
#include <MFRC522.h>
#define SS_PIN 10 #define RST_PIN 9
MFRC522 rfid(SS_PIN, RST_PIN);
void loop(){
  if(rfid.PICC_IsNewCardPresent() && rfid.PICC_ReadCardSerial()){
    String uid = "";
    for(byte i=0;i     if(uid=="2015824437") display.println("ZhangZiHong");
    else if(uid=="89824242") display.println("ZhangXinYuan");
    else display.println("Unknown");
    rfid.PICC_HaltA();
  }
}
📖 知识点详解:
RFID-RC522模块: 13.56MHz高频,读取MIFARE系列卡片(公交卡、门禁卡等)。
SPI接线: SDA→10, SCK→13, MOSI→11, MISO→12, RST→9, 3.3V/GND。
卡号获取: 先用串口输出uid,再填写到case语句中。
应用: 门禁系统、考勤机、借书系统、会员识别。

📚 课程27:刷卡闸机(RFID+舵机)

🎯 确定任务: 授权用户刷卡后,舵机转动打开闸门,3秒后自动关闭。
📊 程序流程图:
开始
  ↓
初始化RFID和舵机
  ↓
┌─────────────────────────┐
│ 等待刷卡                │
│   ↓                    │
│ 读取卡号                │
│   ↓                    │
│ 是否授权卡?           │
│   ↓是                  │
│ 舵机转动90度(开门)    │
│   ↓                    │
│ 延时3秒                │
│   ↓                    │
│ 舵机转动0度(关门)     │
└─────────────────────────┘
            
void loop(){
  if(卡号有效){
    myservo.write(90); delay(3000); myservo.write(0);
  }
}
📖 知识点详解:
舵机速度: 普通舵机转速约0.2秒/60度,从0到90度约0.3秒。
延时开门: 3秒足够行人通过,可根据实际情况调整。
防尾随: 可增加红外对射传感器,检测是否真正通过后关门。
安全设计: 断电时舵机保持当前位置,可添加手动解锁装置。

📚 课程28:刷卡锁(电磁铁+继电器)

🎯 确定任务: 授权用户刷卡后,电磁铁吸合(开锁),3秒后释放(关锁)。
📊 程序流程图:
开始
  ↓
初始化RFID和继电器引脚
  ↓
┌─────────────────────────┐
│ 等待刷卡                │
│   ↓                    │
│ 授权卡?               │
│   ↓是                  │
│ 继电器吸合(电磁铁工作) │
│   ↓                    │
│ 延时3秒                │
│   ↓                    │
│ 继电器释放(电磁铁停止) │
└─────────────────────────┘
            
void loop(){
  if(授权卡){
    digitalWrite(7, HIGH); delay(3000); digitalWrite(7, LOW);
  }
}
📖 知识点详解:
电磁铁: 通电产生磁力,可吸合铁片,断电磁力消失。
继电器: 用Arduino的小电流控制电磁铁的大电流(通常12V/1A),保护主板。
接线: COM接12V电源正,NO接电磁铁正极,电磁铁负极接GND。
应用: 电子门锁、储物柜、保险箱、自动售货机。

📚 课程29:往返小车(直流电机控制)

🎯 确定任务: 编写函数控制小车前进、后退、转向,让小车走正方形路线。
📊 程序流程图:
开始
  ↓
定义移动函数 movecar(power)
  ↓
前进3秒
  ↓
左转(左轮停,右轮转)
  ↓
前进3秒
  ↓
左转
  ↓
... 共4次,走正方形
            
void movecar(int power){ // power正值前进,负值后退
  if(power>0){ digitalWrite(7,1); analogWrite(6,power); digitalWrite(4,1); analogWrite(5,power); }
  else { digitalWrite(7,0); analogWrite(6,-power); digitalWrite(4,0); analogWrite(5,-power); }
}
void setup(){ pinMode(7,OUTPUT); pinMode(6,OUTPUT); pinMode(4,OUTPUT); pinMode(5,OUTPUT); }
void loop(){
  movecar(80); delay(3000); // 前进3秒
  movecar(0); delay(500); // 暂停
  movecar(80); delay(800); // 右转
}
📖 知识点详解:
L298N电机驱动: 可驱动两个直流电机,IN1/IN2控制左轮,IN3/IN4控制右轮,ENA/ENB控制速度。
差速转向: 左轮停、右轮转→左转;右轮停、左轮转→右转;两轮同速反向→原地旋转。
PWM调速: analogWrite(引脚,速度)控制电机转速,0-255。
小车结构: 底盘、两个驱动轮、一个万向轮,锂电池应放在驱动轮上方保证重心稳定。

📚 课程30:悬崖勒马小车(超声波防跌落)

🎯 确定任务: 小车前进中检测到前方距离大于10cm(悬崖)时立即停车。
📊 程序流程图:
开始
  ↓
初始化超声波传感器
  ↓
小车前进
  ↓
┌─────────────────────────┐
│ 测量前方距离            │
│   ↓                    │
│ 距离 > 10cm?          │
│   ↓是                  │
│ 停车                   │
└─────────────────────────┘
            
void setup() {
  movecar(80); // 前进
  while(getDistance(13,12) > 10){ } // 检测到悬崖
  movecar(0); // 停车
}
📖 知识点详解:
开环 vs 闭环: 本系统无反馈,属于开环控制。若加入测距反馈则为闭环。
悬崖检测: 超声波向下安装,检测地面距离。超出阈值说明前方是坑或悬崖。
实时性: 用while循环持续检测,确保第一时间发现危险。
扩展: 可改为红外避障传感器(开关量)检测深渊。

📚 课程31:巡线小车(灰度传感器)

🎯 确定任务: 小车沿着黑线行驶,灰度传感器检测到黑线时调整方向。
📊 程序流程图:
开始
  ↓
读取灰度传感器(数字输出)
  ↓
┌─────────────────────────┐
│ 检测到黑线?           │
│   ↓是         ↓否      │
│ 左转         右转       │
└─────────────────────────┘
            
void loop() {
  if(digitalRead(8)==1){ // 检测到黑线
    lt(0); rt(70); // 左转
  } else {
    lt(70); rt(0); // 右转
  }
}
📖 知识点详解:
灰度传感器: 利用红外反射,黑色吸光(反射弱)输出高电平,白色反光强输出低电平。
单传感器巡线: 简单但容易脱线,可以用2-3个传感器实现更精确控制。
PID控制: 更高级的巡线算法,根据偏差大小调整转向幅度。
巡线赛道: 黑色电工胶带贴在白色地板上,建议线宽1.5-2cm。

📚 课程32:遥控小车(PS2手柄)

🎯 确定任务: 使用PS2无线手柄控制小车前进、后退、左转、右转。
📊 程序流程图:
开始
  ↓
初始化PS2接收端
  ↓
┌─────────────────────────┐
│ 读取手柄按键状态        │
│   ↓                    │
│ 上键按下?→前进         │
│ 下键按下?→后退         │
│ 左键按下?→左转         │
│ 右键按下?→右转         │
│ 无按键?→停车           │
└─────────────────────────┘
            
#include <PS2X_lib.h>
PS2X ps2x; int error;
void setup(){
  error = ps2x.config_gamepad(13,11,10,12, false, false);
}
void loop(){
  ps2x.read_gamepad();
  if(ps2x.Button(PSB_PAD_UP)) { lt(100); rt(100); }
  else if(ps2x.Button(PSB_PAD_DOWN)) { lt(-100); rt(-100); }
  else if(ps2x.Button(PSB_PAD_LEFT)) { lt(-100); rt(100); }
  else if(ps2x.Button(PSB_PAD_RIGHT)) { lt(100); rt(-100); }
  else { lt(0); rt(0); }
}
📖 知识点详解:
PS2手柄: 2.4G无线通信,包括方向键(上/下/左/右)和动作键(X/□/○/▲/L1/L2/R1/R2)。
接线: DAT→13, CMD→11, CS→10, CLK→12, 供电5V/GND。
按键检测: Button(PSB_PAD_UP)检测上键,ButtonReleased检测释放,ButtonPressed检测按下。
扩展: 可增加R2/L2加速减速,SELECT键切换模式,实现不同速度等级。

📖 附录:常用电子元件与传感器

名称类型作用常用型号
LED输出发光指示5mm红/绿/蓝
电阻被动限流分压220Ω, 10kΩ
电位器输入调节电压10kΩ旋转式
光敏电阻输入检测光线5516/5528
按键输入开关信号轻触开关
超声波模块输入测距HC-SR04
人体红外输入检测人体HC-SR501
火焰传感器输入检测火焰远红外接收管
烟雾传感器输入检测烟雾/气体MQ-2
温湿度传感器输入测量温湿度DHT11
RFID模块输入/输出读卡识别RC522
舵机输出角度控制SG90, MG996R
直流电机输出旋转130/370电机
蜂鸣器输出发声有源/无源
WS2812灯带输出彩色LED5050 RGB
🎉 结业目标: 完成全部32课,你将能够: