这次为大家介绍的是一款使用Arduino制作的电子作品,将分【前篇】和【后篇】两部分进行介绍。为我们介绍这个独特的电子制作项目的是平原真先生,他是一位以事物之间的关系为主题进行探索的艺术家。平原先生同时也是日本大阪艺术大学的副教授,迄今为止,他使用电脑和电子元器件制作了很多媒体艺术作品。在Device Plus上,曾经为我们介绍过用Arduino制作的太阳能电池板供电数字养殖箱的制作。这次,我们请平原先生为大家介绍一款使用Arduino和TOF距离传感器制作的甜甜圈播放器。在前篇中,介绍到工作测试部分,在【后篇】中,将介绍完整个项目。究竟这款播放器能够播放出什么样的音色呢?我们拭目以待!
前言
大家好!我是平原。在前篇中,为您介绍到了甜甜圈播放器的工作测试部分,在后篇中将为您介绍从外装制作到最终完成的整个过程。最后,还会介绍用3D打印机制作的音乐甜甜圈,鼓励各位读者朋友尝试制作属于自己的原创音乐甜甜圈!
分发文件
请先下载创建作品实例所需的数据。其中包括Arduino草图、用于3D打印机输出的模型数据、以及用于切割椴木板的形状数据等。
- ArduinoSketch:Arduino草图
- MusicDonuts:音阶形甜甜圈模型数据
- SensorArm:感测臂(唱臂)部件的模型数据
- CutData:用激光加工机切割箱体等部件的数据
外装
完成效果图
外装方面,箱体由椴木板组合而成,在箱体顶板上安装电机、电位器、扬声器等部件。唱臂是由3D打印机打印的部件与铝管组合制成的,在唱臂头部安装传感器。转盘用椴木板做底座。
作业步骤
外装制作步骤如下:
- 使用3D打印机打印部件
- 切割铝管
- 组装唱臂
- 用激光加工机切割材料
- 在箱体顶板上安装电子零部件
- 组装面包板
第1步:使用3D打印机打印部件
我们用3D打印机来制作安装传感器的唱臂的铝管固定件、以及连接转盘和电机的部件。请先输出分发文件中的5个stl文件。请根据您所用的3D打印机来设置有无支撑材料和层压方向等。
SensorHead 固定传感器。
PipeJoint 以90度角连接铝管
PipeBase 将铝管固定在箱体顶板上。
PipeBaseNut 用来固定PipeBase的螺母。
TableJoint 连接转盘和电机。
第2步:切割铝管
将直径为10mm的铝管分别切割成130mm和50mm。您也可以使用金属切割锯切割铝管,不过用切管机就可以轻松利落地进行切割。
第3步:组装唱臂
将传感器地电线穿过铝管来组装唱臂。用螺丝将传感器固定在使用3D打印机制作的部件(SensorHead)上。用3D打印机制作的部件的孔中没有螺纹,但如果用M3螺丝的话,开一个直径3mm的孔,正好可以在拧入螺丝的过程中将树脂切出螺纹。
请按照SensorHead → 50mm铝管 → PipeJoint → 130mm铝管 → PipeBase的顺序,穿过传感器的电线。
使用测试仪的通电检测功能,找出穿过铝管的电线连接到传感器的哪个位置,并在线端贴上写有连接目标(5V、GND、SDA、SCL)的美纹纸胶带。
连接铝管和3D打印的部件。如果插入后仍有松动的情况,请用粘合剂固定。不过,由于130mm的铝管和PipeBase是用来调节高度的,所以请不要用粘合剂,请从侧面拧螺丝固定。
第4步:用激光加工机切割材料
使用分发文件中的CutData.ai,用激光加工机从4mm厚的椴木板上切割出所需形状。至于各形状之间的嵌入匹配,请您根据所用的激光加工机进行设置。
第5步:在箱体顶板上安装电子零部件
从面包板和Arduino UNO上暂且拆下开关、电位器x2、扬声器、电机和滚珠脚轮x3,并将它们安装在顶板上。
开关和电位器从外面插入,从里面用螺母固定。在左侧安装电机调速用的可调电阻(电路图中的VR1),在右侧安装扬声器所连接的可调电阻(电路图中的VR2)。将单独购买的旋钮装在电位器上。旋钮是影响设计的重要部件。如果是轴径(曲轴直径)为6mm的产品,那么是可以安装在可调电阻上的,请选择您自己喜欢的产品。
>> 可调电阻用旋钮一览
扬声器使用白色树脂支架,用M3x15mm的螺丝和M3螺母固定。
按照说明书将滚珠脚轮装为25mm的高度,并使用附带的螺丝和螺母将它们固定在顶板上。
电机从顶板外侧用M2x10mm的螺丝固定。
第6步:箱体组装
用木工胶粘合侧面、正面和底面的箱板,并用美纹纸胶带固定直至牢固粘合。背面暂且不要粘。
将装有传感器的唱臂从上方插入顶板,并用3D打印机制作的螺母(PipeBaseNut)夹住顶板固定。
第7步:接线
以与临时组装时相同的方式连接Arduino UNO和面包板。电线根数有很多,而且不容易看清箱体内部,所以请注意不要接错。
第8步:安装转盘
将M2x20mm的螺丝拧入电机曲轴孔内,用两个螺母固定,以防脱落。将3D打印的部件(TableJoint)插入转盘并固定。当将TableJoint放在曲轴上时,由滚珠脚轮承载重量,只有旋转力从曲轴传递给转盘。
草图/h2>
整体流程
草图的整体流程如下:
- 指定最低音、最高音和高度范围
- 使用TOF距离传感器测量距离并转换为频率
- 以指定的频率播放声音
- 根据调速旋钮的值控制电机
指定最低音、最高音和高度范围
通过频率指定甜甜圈的最低位置和最高位置的音高。另外,以毫米为单位确定甜甜圈的高度范围。在该实例中,最低音是C4“哆”,最高音是B4“西”,正好是一个八度。涵盖的声音范围越广,越容易被微小的噪音影响,声音越容易出现偏差。我将高度范围设置为50mm。由于传感器的分辨率为1mm,因此可以分50档读取高度值。
const int maxFreq = 494;//最高频率 “西”(B4)
const int heightRange = 50;//高度范围 50mm
使用TOF距离传感器测量距离并转换为频率
由于TOF距离传感器获取的数值单位是mm,所以可以直接作为距离使用。将传感器对准甜甜圈的最低位,按下原点设置按钮,将其高度转换为maxFreq(“哆”/C4/262Hz),将50mm转换为minFreq(“西”/B4/494Hz)。
float distance = sensor.readRangeSingleMillimeters();//TOF距離センサーの値を取得(単位:mm) bool offsetButtonState = digitalRead(ORIGIN_BUTTON); //原点設定ボタンの状態を取得 if ( offsetButtonState == 0 && prevButtonState == 1 )//原点設定ボタンが押されたら、 { origin = distance;//originを現在のdistanceに変更 } prevButtonState = offsetButtonState;//prevButtonStateを更新 float frequency = map(distance, origin, origin-heightRange, minFreq, maxFreq);//距離を周波数に変換
以指定的频率播放声音
向右转动音量旋钮,即可将开关打开。使用tone函数,用之前计算出来的频率播放声音。tone函数将输出引脚指定为第一个参数,将频率指定为第二个参数。调用noTone函数即可停止播放。
bool volumeSwitchState = digitalRead(VOLUME_SWITCH);//音量つまみスイッチの値を取得 if ( volumeSwitchState == 0 ) {//音量つまみスイッチがオンなら tone(SPEAKER, frequency );//TOF距離センサーからの距離に応じた周波数の音を鳴らす } else { noTone(SPEAKER);//スイッチがオフなら音を止める }
根据调速旋钮的值控制电机
用analogRead将调速旋钮得到的0~1023的值转换为40~255(即电机旋转的强度),命令电机以该转速旋转。
int motorSpeed = analogRead(MOTOR_SPEED);//速度調整つまみの値を取得 if ( motorSpeed > 10 )//つまみの値が一定以上なら { motorSpeed = map( motorSpeed, 10, 1023, 40, 255 );//つまみの値をスピードに変換 motor1.drive( motorSpeed );//指定したスピードでモーターを回す } else { motor1. brake();//つまみの値が一定以下ならモーターを止める }
整体草图
请将分发文件中的DonutPlayer写入Arduino UNO。
//ライブラリ #include //I2Cライブラリ #include //TOF距離センサーのライブラリ #include //モータードライバのライブラリ //センサー、サウンド関連 #define SPEAKER 8//スピーカーを接続したピン #define VOLUME_SWITCH 13//音量調整つまみのスイッチに接続する端子 VL6180X sensor;//TOF距離センサーのオブジェクト const int minFreq = 262;//最低の周波数 ド(C4) const int maxFreq = 494;//最高の周波数 シ(B4) const int heightRange = 50;//高さの範囲 50mm //モーター関連 #define AIN1 2//モータードライバのAIN1に接続するピン #define AIN2 4//モータードライバのAIN2に接続するピン #define PWMA 5//モータードライバのPWMAに接続するピン #define STBY 9//モータードライバのSTBYに接続するピン #define MOTOR_SPEED A0//モーターの速度調整つまみに接続するピン const int offsetA = 1;//回転方向の指定(1 or -1) Motor motor1 = Motor(AIN1, AIN2, PWMA, offsetA, STBY);//モータードライバのオブジェクト //原点設定関連 #define ORIGIN_BUTTON 11//原点設定ボタンに接続するピン bool prevButtonState = true;//原点設定ボタンの前の状態 int origin = 0;//原点の高さ void setup() { Serial.begin(9600);//シリアル通信を開始 pinMode(VOLUME_SWITCH, INPUT_PULLUP);//音量つまみスイッチのピンをプルアップの入力モードにする pinMode(ORIGIN_BUTTON, INPUT_PULLUP);//原点設定ボタンのピンをプルアップの入力モードにする Wire.begin();//I2Cを開始 sensor.init();//TOF距離センサーを初期化 sensor.configureDefault();//TOF距離センサーを標準的な値に設定 sensor.setTimeout(500);//タイムアウトを500msに設定 } void loop() { //------------------------------------------------------------ // TOF距離センサーで距離を測り、周波数に変換する //------------------------------------------------------------ float distance = sensor.readRangeSingleMillimeters();//TOF距離センサーの値を取得(単位:mm) bool offsetButtonState = digitalRead(ORIGIN_BUTTON); //原点設定ボタンの状態を取得 if ( offsetButtonState == 0 && prevButtonState == 1 )//原点設定ボタンが押されたら、 { origin = distance;//originを現在のdistanceに変更 } prevButtonState = offsetButtonState;//prevButtonStateを更新 float frequency = map(distance, origin, origin-heightRange, minFreq, maxFreq);//距離を周波数に変換 Serial.print("Distance:"); Serial.print(distance); Serial.print(" Frequency:"); Serial.print(frequency); Serial.println(); //---------------------------------------------------------------------- // 指定した周波数で音を鳴らす //---------------------------------------------------------------------- bool volumeSwitchState = digitalRead(VOLUME_SWITCH);//音量つまみスイッチの値を取得 if ( volumeSwitchState == 0 ) {//音量つまみスイッチがオンなら tone(SPEAKER, frequency );//スピーカーから距離に応じた周波数の音を鳴らす } else { noTone(SPEAKER);//スイッチがオフなら音を止める } //---------------------------------------------------------------------- // 速度調整つまみの値に応じてモーターをコントロールする //---------------------------------------------------------------------- int motorSpeed = analogRead(MOTOR_SPEED);//速度調整つまみの値を取得 if ( motorSpeed > 10 )//つまみの値が一定以上なら { motorSpeed = map( motorSpeed, 10, 1023, 40, 255 );//つまみの値をスピードに変換 motor1.drive( motorSpeed );//指定したスピードでモーターを回す } else { motor1. brake();//つまみの値が一定以下ならモーターを止める } }
工作确认
现在,终于要听到甜甜圈的声音了。
拔下USB数据线,将Arduino UNO和面包板放入箱体中。将AC适配器穿过背面箱板上的孔并将其与Arduino UNO连接。后续还可能要打开或关闭背面箱板,所以不要粘住背面箱板。
在将AC适配器插入电源插座之前,请先将两个旋钮逆时针旋转至听到“咔哒”的声音,以防止通电后突然发出很大的声音或转盘高速旋转导致甜甜圈飞出。
将AC适配器插入电源插座并将甜甜圈放在转盘上。调整唱臂,使传感器位于甜甜圈最低位的上方。按下原点设置按钮,设置基准高度。
转动右侧的旋钮可以将声音调大,转动左侧的旋钮可以控制转盘。
从视频中可以听到,第一个甜甜圈的音程根据甜甜圈的凸凹而高低起伏,听起来像是受到了朱古力糖针的影响而掺杂了噪声。第二个甜甜圈上比较平滑,所以播放出来的声音也比较流畅。第三个甜甜圈整体上是倾斜的,所以声音上下起伏较大。不同的甜甜圈播放出的声音也不同,鼓励您多多尝试不同的甜甜圈。
到这里就完成了这次项目“甜甜圈播放器”的作品实例。但是,我们花了那么多精力做成了能够根据高度播放声音的装置,还是希望它能播放乐曲的。那么接下来,我们来制作一个能够将音程转换为厚度的“音乐甜甜圈”。
制作音乐甜甜圈
作业步骤
制作音乐甜甜圈的步骤如下:
- 将乐曲音阶转换为高度
- 用3DCAD创建形状
- 用3D打印机制作原型
- 用食品级硅胶制作原型的模具
- 制作甜甜圈的面糊并倒入硅胶模具中
- 用烤箱烤制く
第1步:将乐曲音阶转换为高度
在这个作品实例中,我们将使用“青蛙合唱”的前四小节。太过复杂的乐曲很难读取,我们的作品比较适合播放简单的童谣。
使用的音符是从“哆” (C4) 到“西” (B4) 的一个八度。另外,表达甜甜圈声音的高度范围为50mm。从“哆”到“西”的频率差约为232Hz,因此每Hz的高度为0.215mm。
1个八度(C4~B4) | 232.257 | Hz |
音阶用的高度 | 50 | mm |
1Hz= | 0.215 | mm |
加上15mm底座高度后的各音程的高度如下表所示:
音阶 | 频率(Hz) | 与“哆”之间的差(Hz) | 高度(mm) | 含底座(mm) |
哆 | 261.626 | 0 | 0 | 15 |
哆♯ | 277.183 | 15.557 | 3 | 18 |
来 | 293.665 | 32.039 | 7 | 22 |
来♯ | 311.127 | 49.501 | 11 | 26 |
咪 | 329.628 | 68.002 | 15 | 30 |
发 | 349.228 | 87.602 | 19 | 34 |
发♯ | 369.994 | 108.368 | 23 | 38 |
索 | 391.995 | 130.369 | 28 | 43 |
索♯ | 415.305 | 153.679 | 33 | 48 |
拉 | 440 | 178.374 | 38 | 53 |
拉♯ | 466.164 | 204.538 | 44 | 59 |
西 | 493.883 | 232.257 | 50 | 65 |
第2步:用3DCAD创建形状
设计一个高度与乐曲音阶相匹配的甜甜圈形状。在这里,我将使用Fusion360的画面进行说明,不过您可以使用任何可以用3D打印机输出的软件。
绘制一个直径为100mm、孔径为40mm、底座高15mm、音阶用高度为50mm的草图。为了使其看起来像甜甜圈,拐角采用圆角。
这次的作品以四分音符为基础,将甜甜圈分成16个部分,这样就可以表达四个小节的四分音符了。使图块旋转360°/16=22.5°做成甜甜圈的基本形状单位,将16个图块拼成没有间隙的圆形。
根据音阶调整高度,并根据上表用“推拉”功能降低高度。由于转盘是顺时针旋转的,因此将表示声音的凸凹按照逆时针方向排列。最后将图块组合在一起。
完成的模型数据为分发文件MusicDounuts/frog.stl。这里面也有其他一些乐曲,大家可以试用自己喜欢的乐曲。
另外,用来对齐高度原点(哆,C4) 的夹具(Base.stl)) 数据也在同一文件夹中。只要达到厚度15cm、直径5cm以上的要求,也可以用其他物品代替。
第3步:用3D打印机制作原型
用3D打印机打印刚刚创建的形状和原点夹具。
第4步:用食品级硅胶制作原型的模具
用食品级硅胶制作甜甜圈模具。这次我使用了下面的产品:
EngravingJapan
【食品级硅胶】HTV-2000 硬度:柔软型
http://www.modelersstore.com/shopdetail/000000000336
有关硅胶的基本使用方法,请参考其产品说明书。
需要准备:
- A型硅胶
- B型硅胶
- 搅拌容器
- 模具容器
- 原型
- 电子称
- 搅拌用刮刀
- 胶带
- 塑料手套
由于3D打印机制作的原型是中空的,所以需要用胶带暂时贴在模具容器上,这样在浇注硅胶时它就不会漂浮起来。也可以用重物压住它。
将A型硅胶和B型硅胶混合,然后缓慢倒入模具容器中。
在室温23度的环境下其固化时间约为8小时。把它放在一边,让它保持静止不动。
等它固化后,取出原型,并让模具预干燥约2小时。
请注意,如果硅胶壁太厚,烤甜甜圈的时候热量就很难通过,所以如果太厚,请用刀具刮掉多余的硅胶。如果硅胶壁太薄,则容易变软变形。
第5步:制作甜甜圈的面糊并倒入硅胶模具中
使用自发粉制作甜甜圈。请根据模具大小调整自发粉用量。
需要准备:
- 自发粉 50g
- 马铃薯淀粉 50g
- 鸡蛋 1个
- 牛奶 50ml
- 色拉油 少许
- 硅胶模具
- 烤箱(180度)
- 微波炉
- 电子称
- 大碗
- 刮刀 等
将烤箱预热至180度。清洗硅胶模具并在其表面涂上一层薄薄的色拉油。
打鸡蛋并与牛奶搅拌均匀。加入自发粉和马铃薯淀粉,再次搅拌均匀,完成面糊制作。
将面糊倒入模具直至顶部边缘。在工作台上轻轻拍打模具以排除空气。
放入预热至180度的烤箱中烘烤40分钟。建议铺上铝箔纸或油纸以防止弄脏顶板。请根据具体情况调整烘烤时间。当表面呈黄色时,用牙签插一下,没有生面糊粘在上面,就表明烤制完成。
刚刚烤好后,甜甜圈还是软的,不要急于将其从模具中取出,先等待它冷却。将模具口朝下放在盘子上,可以保持形状。当充分冷却后,切掉突出的部分并将其从模具中取出来。
工作确认
现在,让我们听听音乐甜甜圈的声音吧。播放步骤如下:
- 在转盘上放好用来对准原点的夹具,使传感器位于其正上方。
- 上下调整唱臂,使传感器的高度比最高音高约1cm。由于测量范围从传感器向下呈圆锥形扩展,因此距离越近测量约准确。
- 按下原点设置按钮,其高度为“哆”(C4)。
- 将甜甜圈放在播放器转盘的中央。
- 调整传感器,使其位于甜甜圈平坦部位的上方。
- 转动右侧旋钮,调高音量。
- 转动左侧旋钮调节电机转速。
怎么样?用甜甜圈听到“青蛙唱歌”了吧?
结语
大家辛苦了!“甜甜圈播放器”和“音乐甜甜圈”的制作过程如何?后半部分感觉有些偏离“电子制作”了,大家也跟着做甜甜圈了吗?
这次我们使用了Arduino官方的tone函数,所以声音有点粗糙,如果使用声音合成库“Mozzi”,就能欣赏更丰富的音乐了。有没有勇气参考这篇文章亲自尝试一下呢?
>> 第20篇 在Arduino项目中使用组件和传感器~扬声器篇(其2)(日语原文)
希望了解更多有关传感器基础知识的读者朋友,欢迎访问ROHM官网的“电子小百科”!
本系列连载的内容
前篇:用Arduino和TOF距离传感器制作甜甜圈播放器
后篇:用Arduino和TOF距离传感器制作甜甜圈播放器(本文)