亿迅智能制造网
工业4.0先进制造技术信息网站!
首页 | 制造技术 | 制造设备 | 工业物联网 | 工业材料 | 设备保养维修 | 工业编程 |
home  MfgRobots >> 亿迅智能制造网 >  >> Manufacturing Technology >> 制造工艺

盒子里的怪物

组件和用品

木箱/盒子
× 1
Arduino UNO
× 1
Adafruit Wave Shield
× 1
SainSmart 4 通道中继模块
× 1
挡风玻璃雨刷电机
× 1
红色 LED 圣诞灯 (100)
× 1
烟雾机
× 1
有源放大器/扬声器
× 1

关于这个项目

*** 更新到第 4 版 ***

我最近为这个项目重写了 Arduino 代码。以下是更改摘要:

  • 主循环现在作为状态机实现
  • 现在所有时间都基于事件时间与当前时间评估

- 时间不再依赖于帧

- 允许在主循环中删除 delay()

- 消除了连接到 Arduino IDE 时的“端口繁忙”问题

  • 中继现在使用常开连接而不是常闭连接*** 更新您的中继连接!!! ***
  • 添加了运动检测 LED
  • 添加了准备唤醒 LED
  • 添加了暂停的 LED
  • 移除了动作触发开关
  • 增加了为红灯和烟雾增加额外时间的功能

- 允许这些效果比盖子弹跳器运行的时间更长

  • 添加了大量评论

你会在 github 上找到所有最新的代码

盒子里的怪物

我喜欢万圣节道具,并且看过和读过一些很棒的盒子里的怪物 去年建造并决定我应该建造自己的。这个想法很简单:创造一种错觉,即某种类型的容器正在容纳一个即将逃跑的危险怪物。这种错觉可以通过运动、声音、光线、烟雾,当然还有惊喜的任意组合来创造。

盒子里有什么!?!?

你想要一个足够大的盒子,它看起来能够装下一些又大又吓人的东西。如果盒子看起来很旧,磨损严重,并且可能只是足够坚固以防止怪物进入,它也会增加错觉。起初,我在旧货店和网上购物,但从来没有我喜欢的东西,所以我建立了自己的。难度不大。

我使用 Home Depot 的 15 个 6 英尺松木栅栏桩制作了一个大约 3 英尺 x 2.5 英尺 x 2.5 英尺的盒子。我用台锯将所有木板切割成一定长度,并使用气动 18 号布拉德钉枪组装盒子。这似乎工作得很好,但后来我意识到由于所有的撞击和弹跳,brads 不够坚固,无法将盒子固定在一起。为了加强盒子,我后来用 1 英寸干壁螺钉将它拧在一起(从里到外,这样它们就不会露出来)。

建成后,我通过使用红茶、醋和钢丝绒的工艺使木材老化。然后我用我在网上找到和/或创建和打印的模板和标签装饰它。

脑筋急转弯!!!

该道具有 2 个操作状态“睡眠”和“唤醒”。睡觉时,盒子相对平静,只会发出鼾声和轻微的咆哮声。当不给糖就捣蛋的人绊倒运动传感器时,怪物就会醒来。当怪物被唤醒时,怪物会咆哮,喷出烟雾,弹开盖子,盒子内部会发出红色的光。

我使用了一个 Arduino Uno 以及一个 WaveShield 和一个中继模块来协调这个道具的行为。 WaveShield 加载了一小部分睡眠和咆哮的声音。 PIR 运动传感器为 Arduino 提供输入以在“睡眠”和“唤醒”模式之间切换盒子。在唤醒模式下,Arduino 激活继电器通道以运行盖子电机、红灯和烟雾发生器。并在 WaveShield 上播放声音。我添加的另一个功能是暂停按钮。这让我可以在年幼的孩子来临时让怪物沉默。

活该!

盖子升降器是一种可以快速升高和降低盖子以使其爆炸和弹跳的装置,就像怪物试图逃跑一样。有几种方法可以做到这一点,最流行的似乎是气动执行器和旋转凸轮。虽然我认为电子控制的气动执行器可以让我使盖子的运动更加随机,但我还是决定使用旋转凸轮,因为它似乎是更简单和最便宜的选择。

我以 15 美元的价格从当地的废料场购买了一台用过的汽车挡风玻璃雨刮器电机。有点好笑。我走进去要了一个马达。当我说“我不在乎”时,柜台后面的那个人问“要什么牌子和型号的车”,他的头稍微偏向一边,并给了我一点侧眼。在我解释了我在做什么之后,他想建立一个 :)

这些电机,无论品牌/型号如何,都以 12 伏电压运行,以合理的速度旋转并具有很大的扭矩:完美!笔记。当你得到一个确保它有一些旧的线束时,它会让你更容易地将电线连接到它上面。还要确保它有曲柄臂和偏置柱。如果主电机柱是您必须使用凸轮的唯一物理连接,则可能会打滑。

将电机安装在盒子内的某处。我把我的放在一面墙上。请记住,将有一个大型旋转凸轮连接到它,它需要能够自由旋转并清除您要放入盒子中的任何和所有物品,尤其是电线。 YouTube 上有几个关于如何使用这些电机的好教程。

我从一块 1/2 层的木板上切下了一个 12 英寸直径的凸轮。首先我切了一个完美的圆。我将它安装在电机上,并用它来确定电机在盒子中所需的高度。我只希望盖子抬高约 2 英寸。完成此拟合后,我使用曲线锯将“牙齿”随机切入凸轮,尽我所能保持它们的宽度和深度随机。

最后,我使用 2 个金属 L 支架、一个 1 英寸尼龙垫片和一个马车螺栓将一个滚轮安装到盖子的下侧。滚子正好位于凸轮上方,以便它沿着凸轮的齿运行。

我使用 ATX 电源的 12 伏轨通过 Arduino 控制的继电器为电机供电。是的,让一切都对齐确实需要一些反复试验。重新定位滚轮一两次后......好吧三次......一切都排好,盖子开始按计划弹跳!

火焰之息:烟与光

我使用了便宜的 400 瓦烟雾发生器来制作烟雾效果。开箱即用,这是无线电控制的。为了用 Arduino 控制它,我打开接收器并将两条引线焊接到触发按钮垫上。这为我提供了连接到 Arduino 控制的中继通道的线路。这是我通过观看一些 YouTube 视频学到的简单技巧。我还添加了一个旧的真空吸尘器软管,以引导烟雾从盖子下方以水流的形式流出。我喜欢这种视觉效果,它有助于减少盒子内电子设备上的蒸汽凝结。

对于灯,我简单地剪断了一根轻型延长线并将其连接到中继通道。然后,Arduino 可以打开和关闭连接到它的 100 个红色 LED 灯串。

使用您的外部声音

WaveShield 有一个 1/8 英寸耳机插孔和输出 - 以及用于直接连接的 2 个 I/O 引脚。我使用 1/8 英寸跳线连接到我从练习室借来的 30 瓦低音吉他放大器。任何数量的放大扬声器都可以工作 - 包括 PC 扬声器。但是使用具有稳定低端的东西绝对是一个加分项。

链接起来

我从万圣节商店购买了一些塑料链,并 3D 打印了一个挂锁。将这些包裹在板条箱上增加了幻觉的深度和感觉。

万圣节!!!

将板条箱放在院子里,并将运动传感器藏在附近的灌木丛中。我使用了很长一段扬声器线来连接传感器,这样我就可以尝试定位,这样当有人靠近(大约 5 英尺)到板条箱时,怪物就会醒来。

随着夜色越来越深,我意识到板条箱外面的所有细节都变得难以看清。最后我用频闪泛光灯照亮它,对效果非常满意。

当不给糖就捣蛋的人走上车道时,他们注意到了咆哮的盒子:有些人好奇,有些人实际上害怕它。当他们靠近并且怪物咆哮起来时,他们会站起来,尖叫起来,甚至有人鼓掌。这是一个巨大的打击。

增强功能

我厌倦了寻找将我的运动传感器隐藏在灌木丛中的方法,所以我将一个热胶粘在一只塑料老鼠的肚子里,我可以把它放在车道沿线或附近灌木丛的某个地方。我还在盒子的背面安装了一个 RJ11 电话插孔,这样我就可以使用 50 英尺的电话线连接老鼠运动传感器 - 这比我以前使用的两股扬声器线要好得多。

您会注意到我还在那个新板上添加了一个开关和一些 LED 指示灯。开关暂停盒子上的所有功能,而无需关闭电源。我的主要终止开关是内部的电源板,使用起来很麻烦,而且这个外部开关上只使用信号电压 (5v)。对于年轻的不给糖就捣蛋的人和其他要求在万圣节之夜偷看里面的人来说,这个开关非常适合阻止怪物。

哦!我将塑料链挂在盒子上以获得效果,有时它们可​​能很笨重。特别是如果我需要在晚上进入盒子。为了使这更容易,我用拉链将黑色弹簧登山扣系在链条的末端。这让我可以快速解开/钩住我拧入盒子下角的孔眼的末端。技术含量不高,但很有帮助。

未来

有一些事情我想在未来添加。也许是遥控控制,这样我就可以在远处暂停或触发怪物。我还将向盖子升降器添加某种类型的反馈,以便 Arduino 可以“知道”盖子何时打开或关闭。升降机有几次停在周期的高点,这使得盒子的“内脏”可见,直到下一个唤醒周期。最后,我可以将外部照明/闪光灯连接到 Arduino 以允许它们由程序和/或遥控钥匙控制。

GitHub 存储库

你会在 GitHub 上找到最新的代码和接线图

代码

  • 盒子里的怪物草图
  • MonsterSounds.h
  • MonsterSounds.ino
盒子里的怪物草图C/C++
/* Wave Shield Pins in Use:2, 3, 4, 5, 10, 11, 12 &13Pins 13, 12, 11 总是被 SD 卡使用(它们是唯一具有高速 SPI 的引脚界面)。然后还有其他 5 个引脚用于与 DAC 和 SD 卡通信,但可以将它们设置为连接到任何 arduino 引脚。但是,默认情况下,库配置为使用引脚 10(用于 SD 卡)和引脚 2、3、4 和 5 用于 DAC。要更改这些引脚需要修改库 - 引脚由它们的“硬件”引脚名称(即 PORTD 等)引用,而不是由 arduino 引脚引用。这意味着引脚 6、7、8、9 和 6 个模拟输入引脚(也称为数字 I/O 引脚 14-20)可用。https://learn.adafruit.com/adafruit-wave-shield-audio- shield-for-arduino/faq*/#include "MonsterSounds.h"#define RESERVED_00 0 // 为串行 RX 保留#define RESERVED_01 1 // 为串行 TX 保留#define RESERVED_02 2 // 为 Wave Shield 保留#define RESERVED_03 3 // 为波屏蔽保留#define RESERVED_04 4 // 为波屏蔽保留#define RESERVED_05 5 // 为波屏蔽保留#define FOG_MACHINE 6 // 将Arduino 上的数字引脚连接到继电器模块#define RED_LEDS 7 // 连接数字引脚Arduino 到继电器模块#define LID_BOUNCER 8 // 将 Arduino 上的数字引脚连接到继电器模块#define RESERVED_09 9 // 将 Arduino 上的数字引脚连接到继电器模块#define RESERVED_10 10 // 为波屏蔽保留#define RESERVED_11 11 // 保留用于波屏蔽#define RESERVED_12 12 // 为波屏蔽保留#define RESERVED_13 13 // 为波屏蔽保留#define PIR_SENSOR A 0 // PIR Input#define MOTION_LED A1 // LED:检测到运动时亮(无论暂停/睡眠/唤醒状态)#define PAUSED_LED A2 // LED:系统暂停时亮#define READY_LED A3 // LED:亮当怪物处于 READY_TO_WAKE 状态时#define PAUSE_BUTTON A4 // 暂停开关输入#define DEBUG_BUTTON A5 // 调试开关输入// 效果计时器设置 - 以秒为单位(编辑这些)#define WAKE_DELAY 30 //“唤醒”之间的最短时间发生秒数#define WAKE_DELAY_DEBUG 10 // 当 DEGUB 开关接合时 WAKE_DELAY 覆盖#define SLEEP_SOUND_DELAY 1 // 尝试触发下一个“睡眠”声音之间等待的秒数#define WAKE_MIN 3 //“唤醒”时间的最小量以秒为单位#define WAKE_MAX 5 // 以秒为单位的最大“清醒”时间#define RED_LIGHT_EXTRA_TIME 1 // 如果需要,允许红灯运行时间比盖子弹跳器长一点#define SMOKE_EXTRA_TIME 2 // 允许烟雾运行如果需要,比盖子弹跳器长一点 // 效果定时器设置 - 以毫秒为单位(不编辑这些)的#define WAKE_DELAY_MILLIS WAKE_DELAY * 1000#定义WAKE_DELAY_DEBUG_MILLIS WAKE_DELAY_DEBUG * 1000#定义SLEEP_SOUND_DELAY_MILLIS SLEEP_SOUND_DELAY * 1000#定义WAKE_MIN_MILLIS WAKE_MIN * 1000#定义WAKE_MAX_MILLIS WAKE_MAX * 1000#定义RED_LIGHT_EXTRA_TIME_MILLIS RED_LIGHT_EXTRA_TIME * 1000#定义SMOKE_EXTRA_TIME_MILLIS SMOKE_EXTRA_TIME * 1000MonsterSounds 声音;静态无符号长时间SinceLastSnore=0;静态无符号长唤醒允许定时器=0;静态无符号长lidBounceTimer =0;静态无符号长lidBounceDuration =0;静态无符号长smoothTimer =0;静态无符号长静态无符号长时间=0 redLightTimer =0;static unsigned long redLightDuration =0;enum States { STATE_INITIALIZE, // 仅在运行 setup() 和第一次进入 loop() STATE_PAUSED, // 关闭所有声音和效果 STATE_SLEEPING, // 没有效果,睡眠声音, 不允许唤醒被触发 STATE_READY_TO_WAKE, // 否效果,睡眠声音,允许唤醒被触发 STATE_AWAKE}; // 触发效果和怪物唤醒声音States state =STATE_INITIALIZE;void setup() { // 初始化串行通信:Serial.begin(9600); // 设置所有继电器引脚 pinMode(LID_BOUNCER, OUTPUT); pinMode(RED_LEDS,输出); pinMode(雾机,输出); pinMode(PAUSED_LED,输出); pinMode(MOTION_LED,输出); pinMode(READY_LED,输出); // 强制所有效果关闭 stopAllEffects(); pinMode(PIR_SENSOR,输入); pinMode(PAUSE_BUTTON, INPUT_PULLUP); pinMode(DEBUG_BUTTON, INPUT_PULLUP);声音初始化(); // 怪物声音 sound.playSystemReady();延迟(1000); Serial.println(); Serial.print("*** 系统就绪 ***"); Serial.println(); }/* * 注意:所有按钮都使用上拉,因此低意味着按钮被按下 * 请记住,上拉意味着开关逻辑被反转。 * 打开时变高,按下时变低。 * * PIR 运动传感器不会以这种方式运行。*//* * 主处理循环 * - 管理怪物的状态机 */void loop() { boolean pauseSwitchClosed =digitalRead(PAUSE_BUTTON) ==LOW; boolean motionDetected =digitalRead(PIR_SENSOR) ==HIGH;数字写入(MOTION_LED,数字读取(PIR_SENSOR)); switch (state) { case STATE_INITIALIZE:if (pauseSwitchClosed) { goToPause(); } else { goToSleep(); } 休息; case STATE_PAUSED:if (!pauseSwitchClosed) { goToSleep();数字写入(PAUSED_LED,低); } else { digitalWrite(PAUSED_LED, HIGH); } 休息; case STATE_SLEEPING:if (pauseSwitchClosed) { goToPause(); } else if ( isAllowedToWake() ) { goToReadyToWake(); } else { processSleeping(); } 休息; case STATE_READY_TO_WAKE:if (pauseSwitchClosed) { goToPause();数字写入(READY_LED,低); } else if (motionDetected) { goToAwake();数字写入(READY_LED,低); } else { processSleeping(); } 休息; case STATE_AWAKE:if (pauseSwitchClosed){ goToPause(); } else if ( processAwakeAnimation() ) { goToSleep(); } // processAwakeAnimation() 当所有动画完成时返回true break;默认值:Serial.println("未知状态");休息; // 我们不应该到达这里 } }/* * 转换到暂停状态 */inline void goToPause() { Serial.println("PAUSED");状态 =STATE_PAUSED; stopAllEffects(); sound.stopAll();}/* * 转换到睡眠状态 */inline void goToSleep() { Serial.println("GOING TO SLEEP");状态 =STATE_SLEEPING; wakeAllowedTimer =millis();}/* * 转换到准备唤醒状态 * 这是睡眠状态的一个特例 */inline void goToReadyToWake() { Serial.println("READY TO WAKE");状态 =STATE_READY_TO_WAKE; }/* * 转换到唤醒状态 * - 唤醒怪物并处理效果和声音 */inline void goToAwake() { Serial.println("AWAKE");状态 =STATE_AWAKE; wakeMonster();}/* * 处理 SLEEP 活动的一个周期 * - 运行睡眠声音 * - 更新睡眠定时器 */inline void processSleeping() { if ((millis() - timeSinceLastSnore)> SLEEP_SOUND_DELAY_MILLIS) { sound.playSnore( ); timeSinceLastSnore =毫秒(); }}/* * 判断此时是否允许怪物苏醒。 * - 检查调试开关,如果它关闭,我们使用较短的唤醒允许定时器 * - 怪物必须在预定义的最短时间睡眠才能被唤醒 * - 当它准备好被唤醒时点亮 LED */inline boolean isAllowedToWake( ) { boolean isDebug =digitalRead(DEBUG_BUTTON) ==LOW; unsigned long requiredDelay =WAKE_DELAY_MILLIS; if ( isDebug ) { requiredDelay =WAKE_DELAY_DEBUG_MILLIS;布尔 isAllowed =(millis() - wakeAllowedTimer )> requiredDelay; if (isAllowed ) { digitalWrite(READY_LED, HIGH); } return isAllowed;}/* * Wake Monster * 启动唤醒动画 * 播放唤醒声音 * * 调用一次以启动唤醒状态。 */voidwakeMonster() { int activityDuration =random(WAKE_MIN_MILLIS, WAKE_MAX_MILLIS); // 这是怪物活跃的时间 Serial.print(" wake duration:"); Serial.print(activityDuration); Serial.println("毫秒");弹跳盖(活动持续时间); flashRedLight(activityDuration + RED_LIGHT_EXTRA_TIME_MILLIS); activateSmoke(activityDuration + SMOKE_EXTRA_TIME_MILLIS); sound.playRoar();} /* * 管理 AWAKE 动画的进度 * 在 AWAKE 状态期间调用此 EVERY CYCLE。 * 当所有动画完成时返回 TRUE */boolean processAwakeAnimation(){ printTimersToLog();布尔值 done1 =false;布尔值 done2 =false;布尔值 done3 =假;如果(millis()-lidBounceTimer>lidBounceDuration){bounceLid(0);完成 1 =真; } if (millis() - redLightTimer> redLightDuration ) { flashRedLight(0); done2 =真; } 如果(millis()-smoothTimer>smokeDuration){ activateSmoke(0); done3 =真; } return done1 &&done2 &&done3;}/* * 管理效果:弹回盒盖 * - diration 是效果应该运行的毫秒数 * - 持续时间为 0 表示应该停止效果 */inline voidounceLid(unsigned长持续时间){ 如果 (持续时间 <=0) { energizeRelay(LID_BOUNCER);盖子弹跳持续时间 =0; } else { // 启动盖子弹跳 de_energizeRelay(LID_BOUNCER); LidBounceTimer =毫秒();盖子弹跳持续时间 =持续时间; }}/* * Manage Effect:Flash Red Lights * - diration 是效果应该运行的毫秒数 * - 持续时间 0 表示应该停止效果 */inline void flashRedLight(unsigned long duration){ if (duration <=0) { energizeRelay(RED_LEDS);红光持续时间 =0; } else { // 启动灯闪烁 de_energizeRelay(RED_LEDS); redLightTimer =毫秒(); redLightDuration =持续时间; } }/* * Start/Stop Effect:Activate Smoke * - diration 是效果应该运行的毫秒数 * - 持续时间为 0 表示应该停止效果 */ inline void activateSmoke(unsigned long duration) { // '按下烟雾按钮 // 持续时间应该是机器响应动作所需的固定时间 // 设置超时以在持续时间后停止 if (duration <=0) { energizeRelay(FOG_MACHINE);烟雾持续时间 =0; } else { // 启动灯闪烁 de_energizeRelay(FOG_MACHINE);吸烟定时器 =毫秒();烟雾持续时间 =持续时间; } }/* * 停止所有的效果 * - 这有效地关闭了怪物 */inline void stopAllEffects(){ounceLid(0);闪红灯(0); activateSmoke(0);}/* * 每秒将唤醒动画计时器打印到日志中 */inline void printTimersToLog() { static unsigned long timeofLastTimerLog =0; if (millis() - timeofLastTimerLog>=1000) { Serial.print("lid:"); Serial.print( (millis()-lidBounceTimer)> LidBounceDuration ? 0 :(lidBounceDuration -(millis()-lidBounceTimer) ) ); Serial.print(" 灯:"); Serial.print( (millis()-redLightTimer)> redLightDuration ? 0 :(redLightDuration -(millis()-redLightTimer) ) ); Serial.print(" 烟雾:"); Serial.println((millis()-smokeTimer)>smokeDuration ? 0 :(smokeDuration -(millis()-smokeTimer) ) ); timeofLastTimerLog =毫秒(); }}/* * 通电继电器 * 将常开 (NO) 端子设置为 OPEN * 常闭将变为关闭 */ inline void energizeRelay(int channel) { digitalWrite(channel, HIGH); }/* * 断电继电器 * 将常开 (NO) 端子设置为 CLOSED。 * 常闭将变为 OPEN */ inline void de_energizeRelay(int channel) { digitalWrite(channel, LOW); }
MonsterSounds.hC/C++
用于怪物声音库的 Arduino 标头
/* 关于 ARDUINO 引脚的注意事项 * SD 卡始终使用引脚 13、12、11(它们是唯一具有高速 SPI 接口的引脚)。 * 然后还有 5 个其他引脚用于与 DAC 和 SD 卡通信,但可以将它们设置为连接到任何 arduino 引脚。 * 但是,默认情况下,库配置为使用引脚 10(用于 SD 卡)和引脚 2、3、4 和 5 用于 DAC。 * 要更改这些引脚需要修改库 - 引脚由它们的“硬件”引脚名称(即 PORTD 等)引用,而不是由 arduino 引脚引用。 * 这意味着引脚 6、7、8、9 和 6 个模拟输入引脚(也称为数字 I/O 引脚 14-20)可用。 * */ #include #include #include #include  static const char roar0[] ="ROAR0000.wav"; static const char roar1[] ="ROAR0001.wav"; static const char roar2[] ="ROAR0002.wav"; static const char * const roarSounds[] ={roar0, roar1, roar2}; static const char sleep0[] ="SNORE000.wav"; static const char sleep1[] ="SNORE001.wav"; static const char sleep2[] ="SNORE002.wav"; static const char * const sleepSounds[] ={sleep0, sleep1, sleep2}; int previousRoarSound =-1; class MonsterSounds { 私有:SdReader 卡; // 该对象保存卡片 FatVolume vol 的信息; // 这保存了卡 FatReader 根上分区的信息; // 这包含卷根目录 FatReader 文件的信息; // 该对象代表短语 WaveHC 波形的 WAV 文件; // 单个波形对象——一次只播放一个声音 void playfile(char *name);公共:无效初始化(); void playSystemReady(); void playRoar(); void playSnore(); void stopAll();};
MonsterSounds.inoC/C++
用于怪物声音库的 Arduino 代码
/* 关于 ARDUINO 引脚的注意事项 * SD 卡始终使用引脚 13、12、11(它们是唯一具有高速 SPI 接口的引脚)。 * 然后还有 5 个其他引脚用于与 DAC 和 SD 卡通信,但可以将它们设置为连接到任何 arduino 引脚。 * 但是,默认情况下,库配置为使用引脚 10(用于 SD 卡)和引脚 2、3、4 和 5 用于 DAC。 * 要更改这些引脚需要修改库 - 引脚由它们的“硬件”引脚名称(即 PORTD 等)引用,而不是由 arduino 引脚引用。 * 这意味着引脚 6、7、8、9 和 6 个模拟输入引脚(也称为数字 I/O 引脚 14-20)可用。 * */ void MonsterSounds::initialize(){ Serial.println("初始化声音..."); if(!card.init()) Serial.println(F("卡片初始化失败!")); if(!vol.init(card)) Serial.println(F("没有分区!")); if(!root.openRoot(vol)) Serial.println(F("无法打开目录")); Serial.println(F("找到文件:"));根.ls(); randomSeed(analogRead(0));}void MonsterSounds::playSystemReady(){ this->playfile("WELCOME0.WAV");}void MonsterSounds::playRoar(){ int index =random(3); // 0, 1, 2 while (index ==previousRoarSound) { index =random(3); } previousRoarSound =index; this->playfile(roarSounds[index]);}void MonsterSounds::playSnore(){ if (!wave.isplaying) // 不要打鼾打断现有的声音 { int index =random(3); // 0, 1, 2 this->playfile(sleepSounds[index]); }}void MonsterSounds::stopAll(){ wave.stop(); // 停止任何当前播放的 WAV}// --------------------------------------- ------------------------------// playfile() // 打开并开始播放 WAV 文件// ------ -------------------------------------------------- -----------void MonsterSounds::playfile(char *name) { PgmPrint("播放声音:"); Serial.println(name); if (wave.isplaying) {// 已经在播放一些东西,所以停止它!波。停止(); // 停止它 } if (!file.open(root, name)) { PgmPrintln("File not found ");返回; } if (!wave.create(file)) { PgmPrintln("Not a valid WAV");返回; } // 可以玩了! wave.play();}

定制零件和外壳

Monstersounds_7vLZD3NU4t.zip

示意图


制造工艺

  1. 脑电图机
  2. 果汁盒
  3. 自动售货机
  4. 更换机器
  5. 缝纫机
  6. 连裤袜
  7. 在家制作 DIY 作业书写机
  8. Giftduino - 完美的 Arduino 礼品盒
  9. 使用 ARDUINO 的超声波悬浮机器
  10. Arduino + ESP 气象箱
  11. 使用有限状态机在 Arduino 上的数字手表
  12. 数控机床