这次将为大家介绍一个使用Arduino制作的独特电子作品,将会分【前篇】和【后篇】两部分进行介绍。为我们介绍这个非常有趣的电子制作项目的是平原真先生,他是一位以事物之间的关系为主题进行探索的艺术家。平原先生同时也是大阪艺术大学的副教授,迄今为止,他使用计算机和电子器件制作了很多媒体艺术作品。在Device Plus上,平原先生也发表了一些极具意义的电子作品,例如“用Arduino制作的太阳能电池板供电数字生态箱”和“用Arduino和TOF距离传感器制作甜甜圈播放器”。下面,让我们来看看这次会是什么样作品。
前言
大家好!我叫平原。这个问题可能有点突然:您有没有玩过巨大的迷宫?这通常是一种景点,玩家进入一个由比人高的墙壁组成的迷宫,通过克服旋转门和岔路等重重关卡,最后到达终点。这种游戏在1980年代风靡日本全国,但现在貌似只剩下屈指可数的几处了。我在小时候曾经玩过,当时曾经想:“要是能从天上往下看就好了!”
这次我想制作一个能够实现这样的童年梦想的作品。希望制作出一个当实物迷宫倾斜时,屏幕中的迷宫也会倾斜并且小球会滚动的装置,玩家需要交互确认和比较实物迷宫和屏幕中的迷宫才能到达终点!
Rolling Ball Maze.mp4
※此链接为Youtube视频
本项目的组成
本项目共分为六个部分:
- 作品规划和制作准备
- 电子电路
- Arduino程序
- 制作迷宫外壳
- 创建迷宫的3D模型
- Unity程序
本文是前篇,将介绍1到3的内容,最后我们会测试电子电路的工作情况。在后篇中,我们将使用激光加工机制作迷宫外壳,并使用Unity完成3D迷宫游戏。
1. 作品规划和制作准备
整体规划
在这项作品中,如果您倾斜实物迷宫,屏幕中的迷宫也会倾斜,里面的小球也会随之滚动。这个项目的亮点在于,通过实物迷宫可以看到整个迷宫,但无法知道小球的位置,在屏幕上只能看到小球周围的区域,所以必须交互确认实物迷宫和屏幕中的迷宫。
盒子里面是包括用来检测倾斜的加速度传感器和微控制器开发板Arduino UNO,通过USB数据线连接到电脑。当您倾斜盒子时,倾斜数据会被发送到名为“Unity”的软件,该软件用来在电脑上显示运行的3D迷宫。Unity根据接收到的数据倾斜3D迷宫,小球会根据物理运算滚动。
另外,我还希望实现更换实物迷宫后3D迷宫也随之切换这一目标,这样可以使游戏更加富有妙趣。此外,当玩家成功到达终点时,还还需要通过振动来表示一下喜悦之情。
系统构成
下面,我们绘制一个实现整体规划所需设备的简图,并构思整体的设备构成。
首先,需要用加速度传感器来读取倾斜度。然后,还需要用来读取迷宫切换情况的反射式光电传感器和用来产生振动的振动电机。另外,还需要通过微控制器开发板Arduino来控制这些电子器件并与电脑进行通信。用USB数据线连接Arduino和电脑,在电脑上运行Unity,并与Arduino通信和显示迷宫。
接下来,需要根据电压、耗电量、所使用的引脚、通信方式、实物尺寸、作品的炫酷程度等因素,来选择具体部件。如果您从主要部件和选项较少的部件开始着手,会更容易理清思路。
加速度传感器
加速度传感器包括将加速度输出为电压的模拟类型,以及通过I2C等进行通信的数字类型。最近,数字型加速度传感器已成为主流。这次,我们将使用ROHM的加速度传感器模块“KX224-1053”和可以通过Arduino轻松使用的传感器扩展板“SHIELD-EVK-001”。
罗姆传感器评估套件
反射式光电传感器
反射式光电传感器是一种照射红外线并读取对象物反射光线的装置。在这里,我们利用光反射量会因对象物的颜色而变化这一特点,来读取迷宫的类型。如果有两个反射式光电传感器,那么就可以分辨出四种迷宫。这次我们将使用常用的“RPR-220”。
振动电机
振动电机是一种通过使偏心块旋转而产生振动的装置,也称为“偏心电机”。这次为了简化电路,我们将使用工作电压在2.0v 〜3.0v,工作电流在大约50mA、可直接通过Arduino控制的振动电机。
Serial Port Utility Pro
Unity与Arduino之间的通信仅通过标准功能也能实现,但这次我们将使用名为“Serial Port Utility Pro (SPUP)” 的工具。使用SPUP进行通信时,您可以不必担心运行环境的差异。这个工具在资源商店的售价为79美元,不过您可以从其官网下载试用版。试用版需要在通信量达到一定程度时重新启动Unity。我们可以在开发过程中使用试用版,在想长期使用时购买它。
迷宫外壳结构
根据整体规划和所需功能来考虑外壳的结构。比较有效率的做法是先手绘草图,等大框架定好后再用CAD等进行设计。这次是一个简单的盒子,所以我是用Illustrator设计的。
这次要考虑的要点是:适合用双手拿着的尺寸、可以更换迷宫、可以用反射式光电传感器读取迷宫的背面。我决定设计成盒状,将电路收纳在盒子中,将迷宫配置在盒盖上。在盒盖的背面做黑色和白色标记,用反射式光电传感器来读取标记。
材质采用椴木单板,用激光加工机切割,用木材专用胶粘合。如果想要看得见内部,也可以使用透明的亚克力板。请根据自己的喜好选择。
零部件清单
我在下面汇总了要使用的物料,价格和购买网址为截至撰写本文时的数据。运费另计。
分发文件
创建示例所需的数据请从以下链接下载。其中包括Arduino程序和用于切割椴木单板的形状数据等。
>> 数据下载(50.4MB)
- CutBox.ai
外壳盒体部分的激光加工用数据 - CutMaze.ai
外壳迷宫部分的激光加工用数据 - ArduinoApp
Arduino用程序 - UnityApp
Unity的项目 - BreadboadHolder.stl
用来提高面包板高度的部件 - MazeLv1.obj、MazeLv2.obj、MazeLv3-A.obj、MazeLv3-B.obj
迷宫的3D模型
2. 电子电路
布线图与电路图
我们需要一边确认电子部件的技术规格书一边设计电路。同时,在考虑实际物体的大小和位置关系的同时,还要考虑布线的长度等因素。
加速度传感器模块可以安装在传感器扩展板上并固定在Arduino UNO上面,因此布线很简单:将反射式光电传感器和振动电机配置在面包板上。
布线图
电路图是表示电气连接关系的图,布线图是考虑到表示实际尺寸和位置关系等因素而绘制的接线图。在您还不能熟练使用的阶段,完全按照布线图制作更容易一些,但是当您习惯于制作并能够自己绘制电路或嵌入他人的电路时,通过电路图进行思考更容易理解。
电路图
组装
下面我们组装电子电路。这次我没有采用焊接的方式,而是用跳线将其连接到面包板上,因此无需担心失败。在作业的时候,请对照布线图和照片进行。作业步骤如下:
- 加速度传感器模块和传感器扩展板
- 反射式光电传感器
- 振动电机
- 布线
步骤1:加速度传感器模块和传感器扩展板
传感器扩展板自带的插座可以安装共8个传感器模块。加速度传感器模块适用“I2C”的通信标准,因此请将其插入标有“I2C_1”的插座。请调整角度,使模块处于水平状态。
接下来,将传感器扩展板连接到Arduino UNO。请确保所有引脚都牢牢地插入内部,以便使加速度传感器模块处于水平状态。另外,请垂直施加力量,以防止长引脚弯曲。虽然后续也可以拔除,但由于长引脚容易弯曲,所以还请谨慎处理。
步骤2:反射式光电传感器
反射式光电传感器有4根引脚。由于4根引脚的长度不同,所以请按照最短的引脚切齐。用钳子切断时,切除掉的余脚的可能会飞溅,请注意防护。
将电阻器从根部弯曲成直角,并在距离根部约1厘米处切割。
接下来,请参考布线图将其插入面包板。注意反射式光电传感器按45度切割时的角度位置。如果切角在右上方,则反射式光电传感器的左半部分是红外LED,右半部分是光电晶体管。红外LED侧(左侧)的电阻为 150Ω,光电晶体管侧(右侧)的电阻为10kΩ。由于电阻器没有极性,因此它的朝向无所谓。跳线如果使用硬跳线,布局效果会给人清爽的感觉。跳线的颜色可以是任意颜色,但为了使布线图清晰易懂,通常电源(5V)用红色,地线(GND)用黑色。
步骤3:振动电机
将振动电机的引出线皮膜剥去约1厘米,然后将其插入面包板。如果导线很细而且难以插入,请将电阻引脚切掉的部分焊接到引出线上。用两面胶将振动电机牢固地固定在面包板上。这个振动电机的标准电压是3V,标准电流是55mA,电源是来自Arduino的5V电源,所以按照(5v-3v)/0.055A=36.4Ω,使用的电阻是39Ω。
步骤4:布线
用跳线连接配置在Arduino UNO上的传感器扩展板与面包板。如果在您将其放入盒子里时跳线造成干涉,将端部的引脚弯曲90度就可以整齐地收纳在盒子里面了。
3. Arduino程序
现在让我们看一下Arduino程序。这次的项目需要以下四个功能:
- 从加速度传感器模块读取值
- 读取反射式光电传感器的值
- 通过串行通信发送读取到的传感器值
- 接收和处理来自Unity的命令
在对每一个功能进行解说后,将会给出整个程序。
从加速度传感器模块读取值
为了与加速度传感器模块“KX224-1053”进行通信,需要使用专用的库。首先,请从产品介绍页面的软件部分下载ZIP文件。然后,从Arduino IDE菜单中选择 [Sketch] > [Include Library] > [Add .ZIP Library],并选择下载的ZIP文件。
另外,您也可以从这个页面下载产品手册供参考。
在Arduino程序中,首先加载I2C库和加速度传感器模块的库。
然后创建KX224类的对象(Object)。可以从该对象读取加速度传感器的值。
#include <Wire.h>//I2C库 #include <KX224_I2C.h>//加速度传感器库 KX224 kx224(KX224_DEVICE_ADDRESS_1E);//创建加速度传感器的对象
在setup函数中,启动I2C库并初始化KX224对象,如果失败,则通过串行通信发送消息。。
byte rc;//启动检查变量 Wire.begin();//I2C库启动 rc = kx224.init();//加速度传感器对象的初始化 if (rc != 0) {//加速度传感器对象的启动检测 Serial.println(F("KX224 initialization failed")); Serial.flush(); }
当将float数组传递给KX224对象的get_val函数时,传感器的值将会输入。如果返回值为0,则读取成功。
byte rc;//用于确认传感器读数。 float acc[3];// rc = kx224.get_val(acc);//将加速度代入acc,如果可以读取则返回 0。
读取反射式光电传感器的值
将反射式光电传感器连接到引脚A0和A1并通过analogRead函数读取。盒子背面的标记是白色和黑色的,通过Unity软件更改模拟读取阈值。
int photoRef1 = analogRead(A0);//读取反射式光电传感器 int photoRef2 = analogRead(A1);
通过串行通信发送读取到的传感器值
将加速度传感器的三个值和两个反射式光电传感器的值用逗号分隔并作为字符串发送。最后,发送换行代码。Unity将接收到的字符串以逗号分隔并返回到数组中使用。
Serial.print(acc[0]);//X轴 Serial.print(","); Serial.print(acc[1]);//Y轴 Serial.print(","); Serial.print(acc[2]);//Z轴 Serial.print(","); Serial.print(photoRef1);//反射式光电传感器1 Serial.print(","); Serial.print(photoRef2);//反射式光电传感器2 Serial.println("");
接收和处理来自Unity的命令
当来自Unity的命令发送过来时,将执行串行通信接收事件。连接接收到的字符串,当收到换行代码时,将接收完成标志设置为True。
void serialEvent() {//接收到串行通信的事件 while (Serial.available()) { char inChar = (char)Serial.read(); // 将接收到的数据转换为字符串 inputString += inChar; // 添加到inputString if (inChar == '\n') {// 当接收到换行代码时,设置接收完成标志。 stringComplete = true; } } }
检查loop函数中的接收完成标志,如果为True,则检查命令的内容并进行相应的处理。在这次的项目中,当字符串是“start”时,振动电机旋转,当字符串是“stop”时,则电机停止。
if (stringComplete) {//设置了接收完成标志时的处理 String is = inputString;//复制接收到的字符串 is.trim();//删除换行代码 if ( is.equals("start") ) //当收到start 时 { digitalWrite(2, HIGH);//使电机运转 } if ( is.equals("stop") ) //当接收到stop时 { digitalWrite(2, LOW);//使电机停止 } inputString = "";//清除接收到的字符串 stringComplete = false;//清除接收到的标志 }
整体草图
请在Arduino IDE中输入以下源代码并将其写入Arduino UNO
#include <Wire.h>///I2C库 #include <KX224_I2C.h>//加速度传感器库 KX224 kx224(KX224_DEVICE_ADDRESS_1E);//创建加速度传感器的对象 String inputString = "";//保存接收数据的变量 bool stringComplete = false; //判断接收是否完成的标志 void setup() { byte rc; Serial.begin(57600);//串行通信开始 while (!Serial); Wire.begin();//I2C库启动 rc = kx224.init();//加速度传感器对象的初始化 if (rc != 0) {//加速度传感器对象的启动检测 Serial.println(F("KX224 initialization failed")); Serial.flush(); } pinMode(2, OUTPUT); pinMode(A0, INPUT); pinMode(A1, INPUT); } void loop() { // ============================================ // 加速度传感器的读取和发送 // ============================================ byte rc;//用于确认传感器读数。 float acc[3];// int photoRef1 = analogRead(A0);//反射式光电传感器的读取 int photoRef2 = analogRead(A1); rc = kx224.get_val(acc);//将加速度代入acc,如果可以读取则返回 0。 if (rc == 0) { Serial.print(acc[0]);//X轴 Serial.print(","); Serial.print(acc[1]);//Y轴 Serial.print(","); Serial.print(acc[2]);//Z轴 Serial.print(","); Serial.print(photoRef1);//反射式光电传感器1 Serial.print(","); Serial.print(photoRef2);//反射式光电传感器2 Serial.println(""); } // ============================================ // 处理接收到的命令 // ============================================ if (stringComplete) {//设置了接收完成标志时的处理 String is = inputString;//复制接收到的字符串 is.trim();//删除换行代码 if ( is.equals("start") ) //当收到start 时 { digitalWrite(2, HIGH);//使电机运转 } if ( is.equals("stop") ) //当接收到stop时 { digitalWrite(2, LOW);//使电机停止 } inputString = "";//清除接收到的字符串 stringComplete = false;//清除接收到的标志 } delay(10); } // ============================================ // 串行通信的接收 // ============================================ void serialEvent() {//接收到串行通信的事件 while (Serial.available()) { char inChar = (char)Serial.read(); // 将接收到的数据转换为字符串 inputString += inChar; // 添加到inputString if (inChar == '\n') {// 当接收到换行代码时,设置接收完成标志。 stringComplete = true; } } }
工作测试
我们已经创建了电子电路和Arduino程序,现在让我们确认一下工作情况。用USB数据线连接Arduino UNO和电脑后,请打开Arduino IDE的串口监视器,将通信速度设置为57600bps。先会显示消息“KX224_WHO_AMI Register Value = 0x2B”,从下一行开始会出现用逗号分隔的五个数字。
前三个是加速度传感器模块的X、Y、Z值。当传感器模块水平放置时,X和Y输出0,Z输出1。当传感器模块倾斜时,值在-1~1的范围内变化。请倾斜Arduino UNO并确认值的变化情况。
后两个数值是反射式光电传感器得值。当附近没有任何东西时,输出个位数的值,当物体接近至距离5mm左右时,该值会超过500。请用手指等确认实际的反应情况。
接下来,确认接收命令后振动电机是否工作。在串口监控器的输入字段中输入“start”,然后按回车键。如果振动电机工作,则意味着成功了。如果电机不动,请确认面包板接线和接收程序命令的位置是否有错误。然后请键入“stop”来确认电机是否停止。
如果可以确认加速度传感器模块、反射式光电传感器、振动电机的工作都没问题,那么第一部分(前篇)就完成了。大家辛苦了!在后篇中,我们将完成实物迷宫的制作,并用Unity创建一个3D迷宫,敬请期待!
前篇:用Arduino和加速度传感器制作数字滚球迷宫(本章)
后篇:用Arduino和加速度传感器制作数字滚球迷宫