🔧 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 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/π。
• 卡尔曼滤波: 融合加速度计和陀螺仪数据,得到更平滑、准确的角度值。
• 应用: 平衡车、无人机姿态控制、体感游戏、姿势矫正器。
• 陀螺仪(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);
}
}
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。
• 报警逻辑: 距离越近,两次报警间隔越短,产生急促感。
• 超声波测距原理: 发射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);
}
if(analogRead(A0) > 500) digitalWrite(13, HIGH);
else digitalWrite(13, LOW);
}
📖 知识点详解:
• MQ-2气体传感器: 检测多种可燃气体和烟雾,需预热1-2分钟。
• 灵敏度调节: 通过板载电位器调节阈值,顺时针增大灵敏度。
• 常见气体检测值: 液化气约200-400,烟雾约400-800,酒精约300-600(不同环境有差异)。
• 安全提示: 检测到烟雾时自动打开风扇排烟,可防止煤气泄漏事故。
• 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 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示例读取遥控器按键值,替换程序中的编码。
• 闸机种类: 抬升式、平开式、拉伸式、推拉式,舵机适合小扭矩应用。
• 舵机(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);
}
Servo myservo;
void setup(){ myservo.attach(9); }
void loop() {
if(analogRead(A0) > 500) myservo.write(90);
else myservo.write(0);
}
📖 知识点详解:
• 雨量传感器: 板上有裸露的蛇形铜线,利用水的导电性,水滴使电路导通,电阻变小,ADC值变大。
• 排水设计: 传感器一般倾斜安装,让水能流走,恢复干燥状态。
• 雨量计历史: 中国南宋秦九韶发明“天池测雨”,是世界最早的雨量器。
• 应用: 智能晾衣架、自动关窗系统、农业大棚。
• 雨量传感器: 板上有裸露的蛇形铜线,利用水的导电性,水滴使电路导通,电阻变小,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);
}
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,掌握换算关系。
• 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);
}
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(列,行)设置显示位置,行高根据字体大小决定。
• 应用: 倒车雷达、液位检测、机器人避障。
• 自定义函数: 将测距代码封装为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){} // 等待释放
}
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循环分别等待按下和释放,实现“按一下刷新一次”。
• 教育应用: 可扩展为加减乘除、英语单词、选择题等学习工具。
• 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){}
}
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)]随机选取一个单词。
• 扩展: 可增加音标、例句,或配合蜂鸣器拼读。
• 数组定义: 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);
}
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秒内按键次数越多,可作为趣味比赛。
• 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();
}
}
#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
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语句中。
• 应用: 门禁系统、考勤机、借书系统、会员识别。
• 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);
}
}
if(卡号有效){
myservo.write(90); delay(3000); myservo.write(0);
}
}
📖 知识点详解:
• 舵机速度: 普通舵机转速约0.2秒/60度,从0到90度约0.3秒。
• 延时开门: 3秒足够行人通过,可根据实际情况调整。
• 防尾随: 可增加红外对射传感器,检测是否真正通过后关门。
• 安全设计: 断电时舵机保持当前位置,可添加手动解锁装置。
• 舵机速度: 普通舵机转速约0.2秒/60度,从0到90度约0.3秒。
• 延时开门: 3秒足够行人通过,可根据实际情况调整。
• 防尾随: 可增加红外对射传感器,检测是否真正通过后关门。
• 安全设计: 断电时舵机保持当前位置,可添加手动解锁装置。
📚 课程28:刷卡锁(电磁铁+继电器)
🎯 确定任务: 授权用户刷卡后,电磁铁吸合(开锁),3秒后释放(关锁)。
📊 程序流程图:
开始
↓
初始化RFID和继电器引脚
↓
┌─────────────────────────┐
│ 等待刷卡 │
│ ↓ │
│ 授权卡? │
│ ↓是 │
│ 继电器吸合(电磁铁工作) │
│ ↓ │
│ 延时3秒 │
│ ↓ │
│ 继电器释放(电磁铁停止) │
└─────────────────────────┘
void loop(){
if(授权卡){
digitalWrite(7, HIGH); delay(3000); digitalWrite(7, LOW);
}
}
if(授权卡){
digitalWrite(7, HIGH); delay(3000); digitalWrite(7, LOW);
}
}
📖 知识点详解:
• 电磁铁: 通电产生磁力,可吸合铁片,断电磁力消失。
• 继电器: 用Arduino的小电流控制电磁铁的大电流(通常12V/1A),保护主板。
• 接线: COM接12V电源正,NO接电磁铁正极,电磁铁负极接GND。
• 应用: 电子门锁、储物柜、保险箱、自动售货机。
• 电磁铁: 通电产生磁力,可吸合铁片,断电磁力消失。
• 继电器: 用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); // 右转
}
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。
• 小车结构: 底盘、两个驱动轮、一个万向轮,锂电池应放在驱动轮上方保证重心稳定。
• 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); // 停车
}
movecar(80); // 前进
while(getDistance(13,12) > 10){ } // 检测到悬崖
movecar(0); // 停车
}
📖 知识点详解:
• 开环 vs 闭环: 本系统无反馈,属于开环控制。若加入测距反馈则为闭环。
• 悬崖检测: 超声波向下安装,检测地面距离。超出阈值说明前方是坑或悬崖。
• 实时性: 用while循环持续检测,确保第一时间发现危险。
• 扩展: 可改为红外避障传感器(开关量)检测深渊。
• 开环 vs 闭环: 本系统无反馈,属于开环控制。若加入测距反馈则为闭环。
• 悬崖检测: 超声波向下安装,检测地面距离。超出阈值说明前方是坑或悬崖。
• 实时性: 用while循环持续检测,确保第一时间发现危险。
• 扩展: 可改为红外避障传感器(开关量)检测深渊。
📚 课程31:巡线小车(灰度传感器)
🎯 确定任务: 小车沿着黑线行驶,灰度传感器检测到黑线时调整方向。
📊 程序流程图:
开始
↓
读取灰度传感器(数字输出)
↓
┌─────────────────────────┐
│ 检测到黑线? │
│ ↓是 ↓否 │
│ 左转 右转 │
└─────────────────────────┘
void loop() {
if(digitalRead(8)==1){ // 检测到黑线
lt(0); rt(70); // 左转
} else {
lt(70); rt(0); // 右转
}
}
if(digitalRead(8)==1){ // 检测到黑线
lt(0); rt(70); // 左转
} else {
lt(70); rt(0); // 右转
}
}
📖 知识点详解:
• 灰度传感器: 利用红外反射,黑色吸光(反射弱)输出高电平,白色反光强输出低电平。
• 单传感器巡线: 简单但容易脱线,可以用2-3个传感器实现更精确控制。
• PID控制: 更高级的巡线算法,根据偏差大小调整转向幅度。
• 巡线赛道: 黑色电工胶带贴在白色地板上,建议线宽1.5-2cm。
• 灰度传感器: 利用红外反射,黑色吸光(反射弱)输出高电平,白色反光强输出低电平。
• 单传感器巡线: 简单但容易脱线,可以用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); }
}
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键切换模式,实现不同速度等级。
• 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灯带 | 输出 | 彩色LED | 5050 RGB |
🎉 结业目标: 完成全部32课,你将能够:
- ✅ 熟练使用数字/模拟输入输出、PWM、中断、串口通信
- ✅ 掌握各种传感器(超声波、红外、温湿度、火焰、烟雾、RFID、陀螺仪等)的使用方法
- ✅ 能够独立设计制作智能小车、智能家居、互动游戏等创客项目
- ✅ 具备参加青少年科技创新大赛的基本能力