第1节 概述

智能硬件有意思,现在市场上有很多针对普通消费者的智能硬件。例如,智能灯泡、智能插座、智能电子秤,甚至无人飞行器。抛开这些智能设备实现的功能不谈,它们的实现原理都是大同小异:通过手机的蓝牙(或者wifi网络),连接智能硬件上的蓝牙模块,向蓝牙模块发送各种控制命令,让硬件工作起来。

也许你只是个普通的软件开发者,对硬件毫无概念,也不要着急,我们向纯软件开发者推荐一个很好的智能硬件入门平台Arduino,以此为基础,逐步熟悉智能硬件开发。

万事开头难,本章将从最简单的智能LED灯开始,向大家介绍一个智能硬件是如何设计并实现的。

当本章完成之后,大家将会得到一个按钮控制开启关闭的台灯。如下图的作品,

项目1  按钮台灯 - 图1

并且可以通过手机控制LED灯的明暗强弱。

在开始以前,假设做好如下准备:

  • Arduino开发板;
  • 一根连接电脑和Arduino开发板的数据线;
  • 一个LED显示灯;
  • 一个按钮开关;
  • 一个旋钮电位器;
  • 若干积木零件;
  • 完成基础课程中的部分内容,以及LED灯、按钮、旋钮电位器等外接传感器的基本使用方法;

1.1 功能定义

LED灯的功能很简单,

  1. LED灯有个实体的开关,能够打开关闭LED灯;
  2. LED灯上有一个旋钮,可以用它调节灯的亮度;
  3. LED灯的外观要简洁实用;

1.2 硬件功能

Arduino开发板有多种型号,这里我们选择Arduino UNO或者MEGA开发板作为智能硬件的控制板。

项目1  按钮台灯 - 图2


开发板外接的LED灯模块大同小异,都是3个引脚,需要将它们连接到Arduino开发板上。

项目1  按钮台灯 - 图3

如果使用的是其他类型的LED灯也没有关系,它们大同小异,观察下引脚就可以了。


开发板要外接一个按钮开关,用来控制LED灯的开关。

项目1  按钮台灯 - 图4


旋钮电位器用来调节LED灯的亮度,它可以检测旋转的角度,角度不同,输出的数值大小也不同,
项目1  按钮台灯 - 图5


为了在开发板上同时接入多个传感器器件,需要使用扩展板,

项目1  按钮台灯 - 图6

或者

项目1  按钮台灯 - 图7

1.3 硬件结构

硬件组装好以后,需要为它设计一个简洁实用的外壳,将开发板、连接线、LED灯包裹起来。

作为个人设计的智能硬件,一定是个性化的产品。开发者可以采用3D模型软件设计一个精巧的外形,然后通过3D打印机将它变成现实,再和我们之前的智能硬件组合起来。

项目1  按钮台灯 - 图8

但是3D建模也是需要花费一定时间和精力学习的。这里我们准备采用积木拼接的方式搭建一个LED灯的外部结构。积木颗粒众多,可以随意插入和拆卸,可定制性很高,各位开发者也可以根据自己的创意随意的修改外形,设计成世界上独一无二的智能LED灯。

项目1  按钮台灯 - 图9

第2节 硬件端的开发

现在,我们开始实现智能LED灯硬件相关部分的设计。

2.1 硬件连接

选择了Arduino开发板 、旋转电位器、LED灯模块和三引脚按钮开关以后,就需要把它们组合起来,为我们所用了。

因为同一个开发板要连接多个外接硬件,这时就需要Arduino扩展板出场了。

将Arduino开发板和扩展板上下插入后,引脚就扩展出来了,

项目1  按钮台灯 - 图10


LED灯模块有3个引脚需要与开发板连接。这里我们选择UNO板的D9引脚作为LED灯的PWM控制引脚(当然可以选择任何其它具有PWM功能的引脚),

扩展板引脚 连接 LED灯模块引脚
9组5V <—->
9组GND <—-> G
9组SIG <—-> S

项目1  按钮台灯 - 图11


旋转模块有3个引脚需要与开发板连接。这里我们选择UNO板的D4引脚作为调光输入的模拟引脚(当然可以选择任何其它模拟引脚),

扩展板引脚 连接 旋转按钮模块引脚
4组5V <—->
4组GND <—-> G
4组SIG <—-> S

项目1  按钮台灯 - 图12


最后,将按钮开关接入Arduino UNO开发板的D5引脚,

扩展板引脚 连接 按钮模块引脚
5组5V <—-> 中间未标注
5组GND <—-> -
5组SIG <—-> S

项目1  按钮台灯 - 图13


全部组装好后,如下图,

项目1  按钮台灯 - 图14

2.2 代码实现

  1. 初始化时,在setup()函数中,```cpp //定义按钮开关使用的引脚编号, //这里使用的是数字引脚5, const int BUTTON_PIN = 5;

//定义LED灯模块使用的引脚编号, //这里使用的是数字引脚9, //这是一个具有PWM功能的引脚 const int LED_PIN = 9;

//定义旋转电位器模块使用的引脚编号, //这里使用的是模拟引脚4, const int ROLLING_SWITCHER = 4;

//初始情况下,按钮是没有按下的,所以是HIGH电平 int oldButtonState = HIGH;

//初始情况下,灯是关闭的 bool isLightOn = false;

void setup() { Serial.begin(9600);

//设置按钮的引脚为输入 pinMode(BUTTON_PIN, INPUT); //设置旋转电位器的引脚为输入 pinMode(ROLLING_SWITCHER, INPUT); //设置LED灯的引脚为输出 pinMode(LED_PIN, OUTPUT); //设置LED灯的初始状态为关闭 isLightOn = false; }

  1. 2. 增加对按钮开关的逻辑控制,```cpp
  2. void loop() {
  3. int buttonState = digitalRead(BUTTON_PIN);
  4. if(buttonState == LOW && oldButtonState == HIGH)
  5. {
  6. // 当前被按下(LOW),之前没有被按下(HIGH),
  7. // 说明使用者按下了按钮
  8. Serial.println("button press down");
  9. oldButtonState = buttonState;
  10. }
  11. else if(buttonState == HIGH && oldButtonState == LOW)
  12. {
  13. //当前没有被按下(HIGH),之前被按下(LOW),
  14. //说明使用者松开了按钮
  15. //此时需要对灯灯开关状态做设置:以前是开启状态,说明要关闭;以前是关闭状态,说明要开启
  16. Serial.println("button press up");
  17. oldButtonState = buttonState;
  18. isLightOn = !isLightOn;
  19. Serial.println(isLightOn);
  20. }
  21. if(isLightOn) {
  22. //如果灯是开启的,那么需要从电位器获取数值,设置灯的亮度
  23. int value = analogRead(ROLLING_SWITCHER);
  24. value = map(value,0,1023,0,255);
  25. analogWrite(LED_PIN, value);
  26. } else {
  27. //如果灯是关闭的,直接这是亮度为0
  28. analogWrite(LED_PIN, 0);
  29. }
  30. }
  1. 将程序部署到Arduino UNO/MEGA开发板上。

第3节 LED灯的外形结构

设计外形结构的时候,可以选择3D建模,然后用3D打印机打印出来的设计方式,也可以简单的使用积木拼接。我们选择用拼接积木的方式,给LED灯搭建外形。

结构设计是一个很有意思的事情。给自己开发的智能硬件做一个个性化的外形十分的令人激动。

3.1 设计软件

LEGO Digital Designer是一款操作简单的、乐高积木设计软件。我们可以用它来进行智能硬件外观的设计,设计完成后把它拼接出来。

这是一款免费的软件,可以在乐高的官网这里根据自己使用的电脑操作系统下载。

3.2 软件使用

打开软件开始,创建新文件,开始设计外形,

项目1  按钮台灯 - 图15

拖动左边区域中的零件,摆放到右边底板上,开始模型到设计,

项目1  按钮台灯 - 图16

下图就是我们给出的一个可能的设计方案。

项目1  按钮台灯 - 图17

3.3 实际效果

如果你有兴趣自己设计,那么可以将它搭建成如下灯样子,

项目1  按钮台灯 - 图18
如果你更加喜欢自己设计台灯,可以使用更多的积木组件进行搭建。

第4节 改进方向

简单的LED按钮灯就设计完了。相信大家看到这个完全由自己打造的硬件玩具一定充满了成就感。

虽然这只是个功能上还比较阳春的智能硬件原型,但是你可以根据自己在实际使用中的感受,给它加入更多实用的功能。例如,

  1. 给它加上红色、绿色、蓝色的灯泡,让LED灯能呈现出更多的色彩;
  2. 同时增加手机端控制软件的功能,设定不同的场景,让LED灯能在不同的场景下变幻不同的灯光颜色和亮度;
  3. 使用声控开关,用声音来控制台灯的开启;
  4. 用积木拼出更多形状有特点的LED灯;

附件

整个项目的连线方式:
项目1  按钮台灯 - 图19

整个项目的代码:

  1. //定义按钮开关使用的引脚编号,
  2. //这里使用的是数字引脚5,
  3. const int BUTTON_PIN = 5;
  4. //定义LED灯模块使用的引脚编号,
  5. //这里使用的是数字引脚9,
  6. //这是一个具有PWM功能的引脚
  7. const int LED_PIN = 9;
  8. //定义旋转电位器模块使用的引脚编号,
  9. //这里使用的是模拟引脚4,
  10. const int ROLLING_SWITCHER = 4;
  11. //初始情况下,按钮是没有按下的,所以是HIGH电平
  12. int oldButtonState = HIGH;
  13. //初始情况下,灯是关闭的
  14. bool isLightOn = false;
  15. void setup() {
  16. Serial.begin(9600);
  17. //设置按钮的引脚为输入
  18. pinMode(BUTTON_PIN, INPUT);
  19. //设置旋转电位器的引脚为输入
  20. pinMode(ROLLING_SWITCHER, INPUT);
  21. //设置LED灯的引脚为输出
  22. pinMode(LED_PIN, OUTPUT);
  23. //设置LED灯的初始状态为关闭
  24. isLightOn = false;
  25. }
  26. void loop() {
  27. int buttonState = digitalRead(BUTTON_PIN);
  28. if(buttonState == LOW && oldButtonState == HIGH)
  29. {
  30. // 当前被按下(LOW),之前没有被按下(HIGH),
  31. // 说明使用者按下了按钮
  32. Serial.println("button press down");
  33. oldButtonState = buttonState;
  34. }
  35. else if(buttonState == HIGH && oldButtonState == LOW)
  36. {
  37. //当前没有被按下(HIGH),之前被按下(LOW),
  38. //说明使用者松开了按钮
  39. //此时需要对灯灯开关状态做设置:以前是开启状态,说明要关闭;以前是关闭状态,说明要开启
  40. Serial.println("button press up");
  41. oldButtonState = buttonState;
  42. isLightOn = !isLightOn;
  43. Serial.println(isLightOn);
  44. }
  45. if(isLightOn) {
  46. //如果灯是开启的,那么需要从电位器获取数值,设置灯的亮度
  47. int value = analogRead(ROLLING_SWITCHER);
  48. value = map(value,0,1023,0,255);
  49. analogWrite(LED_PIN, value);
  50. } else {
  51. //如果灯是关闭的,直接这是亮度为0
  52. analogWrite(LED_PIN, 0);
  53. }
  54. }