373浏览
查看: 373|回复: 0

[入门教程] Arduino入门教程19--手势控制灯「DFR0100」

[复制链接]
本帖最后由 zoey不种土豆 于 2024-11-21 20:14 编辑

想象一下,仅需在空中挥挥手,就可以轻松控制灯的开关。这不仅为日常生活增添了便利,还为智能家居技术带来了更高的互动性和趣味性。手势识别的技术有很多种,在这个项目中,我们将利用两个光敏电阻,通过检测手在不同位置的光遮挡情况,实现手势控制。

元件清单
Arduino入门教程19--手势控制灯「DFR0100」图1

硬件连接
按如下连线图连接。
Arduino入门教程19--手势控制灯「DFR0100」图2
1 手势控制灯连线图
示例代码
样例代码:
  1. int ledPin = 13;       // 定义LED引脚为13  
  2. int lightSensor1 = 0; // 定义左侧光传感器引脚为A0  
  3. int lightSensor2 = 1; // 定义右侧光传感器引脚为A1  
  4.   
  5. int cali1 = 0;         // 左侧光传感器的校准变量  
  6. int cali2 = 0;         // 右侧光传感器的校准变量  
  7.   
  8. bool isOn = false;     // LED状态控制变量  
  9.   
  10. void setup() {  
  11.   Serial.begin(9600);       // 初始化串行通信  
  12.    
  13.   pinMode(ledPin, OUTPUT);  // 将LED引脚设置为输出  
  14.   
  15.   // 校准光传感器:读取10次数据并平均作为环境光基线  
  16.   for (int i = 0; i < 10; i++) {  
  17.     cali1 += analogRead(lightSensor1);  
  18.     cali2 += analogRead(lightSensor2);  
  19.     delay(500);  
  20.   }  
  21.   cali1 = (cali1 / 10);  
  22.   cali2 = (cali2 / 10);  
  23.   
  24.   Serial.print("环境光: ");  
  25.   Serial.print(cali1);  
  26.   Serial.print(" , ");  
  27.   Serial.println(cali2);  
  28.   
  29.   // 通过LED闪烁两次来指示程序的开始  
  30.   for (int i = 0; i < 2; i++) {  
  31.     digitalWrite(ledPin, HIGH);  
  32.     delay(1000);  
  33.     digitalWrite(ledPin, LOW);  
  34.     delay(1000);  
  35.   }  
  36.   
  37.   Serial.println("开始");  
  38. }  
  39. void loop() {  
  40.   int sensorVal1 = analogRead(lightSensor1);  
  41. // 读取左侧光传感器的值  
  42.   int sensorVal2 = analogRead(lightSensor2);  
  43. // 读取右侧光传感器的值  
  44.   int threshold = 30;  // 设置手势检测阈值  
  45.   Serial.print("L: ");  
  46.   Serial.print(sensorVal1);  
  47.   Serial.print("   R: ");  
  48.   Serial.println(sensorVal2);  
  49.   // 根据传感器值确定手势方向并控制LED  
  50.   if ((sensorVal1 > (cali1 + threshold)) && !(sensorVal2 > (cali2 + threshold))) {  
  51.     isOn = true;  
  52.   }  
  53.   if (!(sensorVal1 > (cali1 + threshold)) && (sensorVal2 > (cali2 + threshold))) {  
  54.     isOn = false;  
  55.   }  
  56.   if (isOn) {  
  57.     digitalWrite(ledPin, HIGH);  // 打开LED  
  58.     Serial.println("打开");  
  59.   } else {  
  60.     digitalWrite(ledPin, LOW);   // 关闭LED  
  61.     Serial.println("关闭");  
  62.   }  
  63.   delay(100);  // 延迟100毫秒以避免频繁读取  
  64. }
复制代码

请将装置放置在光线稳定且无阴影遮挡的环境中。上传程序后,将自动进行5秒钟的校准,检测当前光线值。校准完成后,LED会闪烁两次,指示程序启动。向左挥手可打开灯光,向右挥手可关闭灯光。如果效果不理想,可以参考串口打印的读数,调整阈值设置。

代码回顾
在程序开始时,定义LED和两个光敏电阻的引脚。然后,创建两个名为cali的变量来记录光敏电阻的初始读数。
  1. int cali1 = 0;
  2. int cali2 = 0;
复制代码

接下来,我们介绍一种新的变量类型,bool,它代表布尔变量。它只有两个可能的值:true(真)和false(假),通常用于表示条件的真实性或开关的状态。在这里,我们定义一个名为isOn的布尔变量来记录LED当前的开/关状态。
  1. bool isOn = false;
复制代码
光敏电阻的读数会根据其位置和一天中的时间而变化。因此,在程序的设置阶段,我们需要执行自动校准以获得传感器的基线读数。
  1. for (int i = 0; i < 10; i++) {
  2.     cali1 += analogRead(lightSensor1);
  3.     cali2 += analogRead(lightSensor2);
  4.     delay(500);
  5.   }
复制代码

在For循环中,光敏电阻的模拟值被读取了10次,每次读取之间间隔500毫秒,并将结果累加到变量cali1和cali2中。
具体来说,这个循环的目的是为了对光敏电阻进行校准,以获取在特定环境下(即程序开始时)它们的基础读数。通过多次读取并取平均值,可以减少因单次读数误差或环境光线的短暂变化而导致的误差。
之后,将累加得到的总读数除以10,即可得到两个光敏电阻的校准值(即基线读数),这些值将用于后续的比较和判断,以确定LED的开/关状态。
  1. cali1 = (cali1 / 10);
  2. cali2 = (cali2 / 10);
复制代码

循环结束后,计算左侧和右侧光敏电阻的平均值。这些平均值将作为后续光线比较和决策的校准基线值。
一旦完成校准,将平均值打印到串行监视器上,并闪烁LED两次以指示程序的开始。
在loop函数中,我们将比较光线的值并控制LED的开关。
首先,设置两个变量来记录光敏电阻的实时读数。
  1. int sensorVal1 = analogRead(lightSensor1);  
  2. int sensorVal2 = analogRead(lightSensor2);
复制代码

从之前关于光敏电阻的课程中,我们了解到较高的读数对应于较暗的光线条件。当手势发生时,投射到光敏电阻不同部分的阴影会导致其读数上升。因此,我们可以通过监控两侧光敏电阻读数的变化来区分左右挥手的手势。调整阈值变量可以让我们改进这个检测过程的灵敏度。
  1. int threshold = 30;
复制代码
当左侧光敏电阻的读数超过其基线值加上阈值时,表示左侧有遮挡物。
  1. if (sensorVal1 > (cali1 + threshold))
复制代码
然而,仅依赖左侧读数是不够的;它需要与右侧光敏电阻的读数相结合来进行准确评估。
当左侧被遮挡而右侧没有时,它表示一个从右向左挥动的手势。
  1. if ((sensorVal1 > (cali1 + threshold)) && !(sensorVal2 > (cali2 + threshold)))
复制代码
在这行代码中,! 作为逻辑非运算符,用于反转内部表达式的值。&& 作为逻辑与运算符,检查两个表达式是否同时为真。如果条件满足,isOn 被设置为 true,从而打开 LED。否则,isOn 被设置为 false。
  1. isOn = true;
复制代码
最后,我们使用 isOn 的当前值来决定是否打开或关闭 LED。在这里,if (isOn) 是 if (isOn == true) 的简写形式。
  1. if (isOn) {
  2.     digitalWrite(ledPin, HIGH);  
  3.     Serial.println("Turn On");
  4.   } else {
  5.     digitalWrite(ledPin, LOW);  
  6.     Serial.println("Turn Off");
  7.   }
复制代码

示例代码

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

为本项目制作心愿单
购买心愿单
心愿单 编辑
[[wsData.name]]

硬件清单

  • [[d.name]]
btnicon
我也要做!
点击进入购买页面
上海智位机器人股份有限公司 沪ICP备09038501号-4

© 2013-2024 Comsenz Inc. Powered by Discuz! X3.4 Licensed

mail