【Arduino和高中通用技术】——八、一个“科技小制作”

【Arduino和高中通用技术】——八、一个“科技小制作”这是之前制作的一个小作业 音乐喷泉 喷泉的高低和喷射时间随着音符的高低长短而变化 配以随机的 RGB LED 灯光效果对于一个科技小制作来说还是很好的 一 硬件准备 1 Arduino uno 2 12V 水泵 即使你有 5V 的也要使用另外的 MOS 管模块等进行驱动 请查看 Arduino 各个引脚的最大电流 3

大家好,我是讯享网,很高兴认识大家。

        这是之前制作的一个小作业——音乐喷泉。喷泉的高低和喷射时间随着音符的高低长短而变化,配以随机的RGB LED灯光效果对于一个科技小制作来说还是很好的。

一、硬件准备

1、Arduino uno

2、12V水泵(即使你有5V的也要使用另外的MOS管模块等进行驱动,请查看Arduino各个引脚的最大电流)

3、三色LED灯(一般购买Arduino学习套件时都会带一个)

4、PWM开关控制模块(MOS管模块,当时手头没有,所以我使用的是L298N电机驱动模块)

5、蜂鸣器

6、超声波测距模块

7、杜邦线若干

8、12V电源

二、知识准备

1、阅读各模块的使用说明书


讯享网

2、全部GND连接在一起(Arduino的各个GND本身就是相通的)

三、编码

// toneConst.h #ifndef _TONECONST_h #define _TONECONST_h #if defined(ARDUINO) && ARDUINO >= 100 #include "arduino.h" #else #include "WProgram.h" #endif //节拍强度 #define NOTE_D1 37 #define NOTE_DS1 39 #define NOTE_E1 41 #define NOTE_F1 44 #define NOTE_FS1 46 #define NOTE_G1 49 #define NOTE_GS1 52 #define NOTE_A1 55 #define NOTE_AS1 58 #define NOTE_B1 62 #define NOTE_C2 65 #define NOTE_CS2 69 #define NOTE_D2 73 #define NOTE_DS2 78 #define NOTE_E2 82 #define NOTE_F2 87 #define NOTE_FS2 93 #define NOTE_G2 98 #define NOTE_GS2 104 #define NOTE_A2 110 #define NOTE_AS2 117 #define NOTE_B2 123 #define NOTE_C3 131 #define NOTE_CS3 139 #define NOTE_D3 147 #define NOTE_DS3 156 #define NOTE_E3 165 #define NOTE_F3 175 #define NOTE_FS3 185 #define NOTE_G3 196 #define NOTE_GS3 208 #define NOTE_A3 220 #define NOTE_AS3 233 #define NOTE_B3 247 #define NOTE_C4 262 #define NOTE_CS4 277 #define NOTE_D4 294 #define NOTE_DS4 311 #define NOTE_E4 330 #define NOTE_F4 349 #define NOTE_FS4 370 #define NOTE_G4 392 #define NOTE_GS4 415 #define NOTE_A4 440 #define NOTE_AS4 466 #define NOTE_B4 494 #define NOTE_C5 523 #define NOTE_CS5 554 #define NOTE_D5 587 #define NOTE_DS5 622 #define NOTE_E5 659 #define NOTE_F5 698 #define NOTE_FS5 740 #define NOTE_G5 784 #define NOTE_GS5 831 #define NOTE_A5 880 #define NOTE_AS5 932 #define NOTE_B5 988 #define NOTE_C6 1047 #define NOTE_CS6 1109 #define NOTE_D6 1175 #define NOTE_DS6 1245 #define NOTE_E6 1319 #define NOTE_F6 1397 #define NOTE_FS6 1480 #define NOTE_G6 1568 #define NOTE_GS6 1661 #define NOTE_A6 1760 #define NOTE_AS6 1865 #define NOTE_B6 1976 #define NOTE_C7 2093 #define NOTE_CS7 2217 #define NOTE_D7 2349 #define NOTE_DS7 2489 #define NOTE_E7 2637 #define NOTE_F7 2794 #define NOTE_FS7 2960 #define NOTE_G7 3136 #define NOTE_GS7 3322 #define NOTE_A7 3520 #define NOTE_AS7 3729 #define NOTE_B7 3951 #define NOTE_C8 4186 #define NOTE_CS8 4435 #define NOTE_D8 4699 #define NOTE_DS8 4978 //旋律 const int melody[] = { NOTE_G4,//5 NOTE_G4,//5 NOTE_A4,//6 NOTE_G4,//5 NOTE_C5,//1 NOTE_B4,//7 0, NOTE_G4,//5 NOTE_G4,//5 NOTE_A4,//6 NOTE_G4,//5 NOTE_D5,//2 NOTE_C5,//1 0, NOTE_G4,//5 NOTE_G4,//5 NOTE_G5,//5 NOTE_E5,//3 NOTE_C5,//1 NOTE_B4,//7 NOTE_A4,//6 0, NOTE_F5,//4 NOTE_F5,//4 NOTE_E5,//3 NOTE_C5,//1 NOTE_D5,//2 NOTE_C5,//1 0, }; //音符持续时间 const int noteDurations[] = { 8, 8, 4, 4, 4, 4, 4, 8, 8, 4, 4, 4, 4, 4, 8, 8, 4, 4, 4, 4, 2, 8, 8, 8, 4, 4, 4, 2, 4, }; #endif 

讯享网

这是一个头文件,它包含了很多音符的定义以及我们的歌曲——节拍和持续时间。

讯享网 #include "toneConst.h" const int TrigPin = 5; //超声波测距模块控制(输出) const int EchoPin = 6; //超声波测距模块输入 const int GNDPin = 7; //GND插满了,用一个引脚当GND。超声波测距模块电流只有2mA,小于引脚40mA。 const int tonePin = 11; //无源蜂鸣器VCC const int motorVCCPin = 9; //水泵VDD(L298N in3),该引脚输出PWM控制水泵功率,从而控制喷水高度. const int LedPin[3] = { A0,A1,A2 }; //RGB发光管GND const int motorBasicPWM = 128; //水泵最低PWM,维持水刚刚喷出喷头 const int motormaxPWM = 255; //水泵最大PWM,决定水的最大喷出高度 const int melodyMaxNOTE = NOTE_G5; //最高音值,用于将音符值映射到PWM,这里最高音是NOTE_G5; int curRGB[3] = { 0,0,0 }; //RGB发光管发出的颜色 const float LedVelRatio[3] = { 1.9 / 3.3,3.3 / 3.3,3.3 / 3.3 }; //RGB发光管各管脚电压(共阳极发光管,阳极接在3.3V上,用PWM输出) void setup() { //设置超声波测距模块引脚 pinMode(TrigPin, OUTPUT); pinMode(EchoPin, INPUT); pinMode(GNDPin, OUTPUT); digitalWrite(GNDPin, LOW); //设置蜂鸣器初始引脚 pinMode(tonePin, OUTPUT); //初始化LED输出引脚并拉高引脚值(拉高负极电压导致LED正负极电压相等,不发光) for (int i = 0; i < 3; i++) { pinMode(LedPin[i], OUTPUT); digitalWrite(LedPin[i], HIGH); } //设置水泵正负极引脚 pinMode(motorVCCPin, OUTPUT); } void loop() { if (TestDistance() < 100) { //当100厘米内有物体时播放一遍音乐,等待5秒以冷却L298N电机驱动。 PlaySound(); delay(5000); } else { //每隔1秒检测一次。 delay(1000); } } void PlaySound() { //每次播放前,将水泵正极(L298N in3)拉高1秒使水流达到出水口.否则,播放音乐时前几个音符不会出水. analogWrite(motorVCCPin, motormaxPWM); delay(50); analogWrite(motorVCCPin, motorBasicPWM); delay(1000); //循环每个音符 for (int thisNote = 0; thisNote < 29; thisNote++) { //节拍持续时间,这里节拍被统一拉长了2倍. int noteDuration = 2000 / noteDurations[thisNote]; //将节拍强弱映射为水流增高的高度[0,128) int notePWM = (float)melody[thisNote] / melodyMaxNOTE*(motormaxPWM - motorBasicPWM); //若不是空白,先输出一个50毫秒使得水流先增高一定高度,这样看起来就不会落后节拍很多. if (melody[thisNote] != 0) { analogWrite(motorVCCPin, motorBasicPWM + notePWM); delay(50); } //更改LED颜色 SetColor(notePWM); //播放当前节拍 tone(tonePin, melody[thisNote], noteDuration); //若不是空白,输出水流增高的高度 if (melody[thisNote] != 0) { analogWrite(motorVCCPin, motorBasicPWM + notePWM); } //延时达到节拍(去掉之前的50毫秒预输出) delay(noteDuration - 50); //维持水流与出水口同高 analogWrite(motorVCCPin, motorBasicPWM); //关闭蜂鸣器 noTone(tonePin); //节拍间的空白 delay(noteDuration / 4); } //播放完一次之后,关闭水泵 analogWrite(motorVCCPin, 0); //播放完一次之后,关闭LED CloseLed(); } void CloseLed() { //遍历LED每个管脚 for (int i = 0; i < 3; i++) { digitalWrite(LedPin[i], HIGH); } } void SetColor(int notePWM) { //遍历LED每个管脚 for (int i = 0; i < 3; i++) { //将水流增高高度随机化映射为颜色变化 curRGB[i] +=(float)random(0,255)/255 * notePWM; //截断高位使之保持在255以内 curRGB[i] &= 0xff; //将[0,255]PWM即[0,5V]电压映射到[0,vMax]以免烧毁LED,并在管脚上输出 analogWrite(LedPin[i], LedVelRatio[i]*(255 - curRGB[i])); } } unsigned long TestDistance() { //产生一个10us的高脉冲去触发TrigPin digitalWrite(TrigPin, LOW); delayMicroseconds(2); digitalWrite(TrigPin, HIGH); delayMicroseconds(10); digitalWrite(TrigPin, LOW); //检测脉冲宽度,并计算出距离 return pulseIn(EchoPin, HIGH) / 58.30; }

这就是整个的代码,这里涉及到一些问题需要说明一下:

1、因为没有进行转接所以GND不够用,此时模块的电流非常小所以“非常规”的使用了一个引脚作为GND,这并不规范

2、水泵并不是加电就会喷水,实际上电机也是这样的,当从静止开始加电需要PWM达到一定值才会转动,解决方法可以实测这个PWM作为最低值每次都从这个最低值启动,也可以每次启动时先以最大PWM短暂工作几十毫秒先让电机转动起来。

3、RGB发光管的电压是有限制的,实际上我们常用的LED都有一定的电压限制,并不是5V的,也不一定是3.3V,为了避免烧坏器件,请阅读你的说明书。

4、除非使用库进行编程,否则应在setup函数中初始化我们所使用的引脚。

5、在loop函数中,不要写太具体的函数内容——将功能模块化(这里就是封装成函数)而后进行调用,这样可以使得代码思路更清晰,这是一个初学者尤为需要注意的问题。

6、我所使用的驱动模块是L298N,它对PWM的相应并不十分出色,所以代码中的参数你都需要实际验证和调整。

7、距离测试函数结合超声模块的说明书进行阅读,也可以使用封装好的库去驱动超声模块。

最后,关于外壳,在制作外壳时,我是用SOLIDWORKS 2016 来设计模型,而后3D打印机进行打印。下一篇我们简单的介绍一下SOLIDWORKS 2016的基本用法。

小讯
上一篇 2025-03-23 19:27
下一篇 2025-03-21 17:50

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/124195.html