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

廉价的 Arduino 呼吸控制器(USB-MIDI)

组件和用品

Arduino Micro
你可以用克隆来降低成本,但我推荐原版。由于原生 USB 功能,只有 Micro (ATmega32U4) 可以工作。
× 1
无焊面包板半尺寸
× 1
MPS20N0040D-D 压力传感器
廉价且很容易找到。
× 1
LM358-N 运算放大器
我们将使用流行的 LM358 运算放大器来放大传感器的信号。
× 1
电阻 1M ohm
× 2
连接线套件,22 AWG
你当然不需要全套,只需要几厘米的实心线。
× 1
婴儿吸鼻器
是的,你没看错。我们将使用父母侧的吹嘴和婴儿侧的吸气器。周围有数十种相同类型的手动吸气器(例如 Physiomer Nasal Aspiring、Chicco Physioclean 等)。选择您觉得更舒服的吹嘴类型。
× 1
5mm 水族箱航空管
可选,如果吸气管不够长。标准的水族馆航空管就可以了。
× 1
三通气管接头
这个特定的中国 OEM 可以在不同名称的水族馆商店中轻松找到。它直接安装在传感器上。
× 1

必要的工具和机器

剥线钳和切割机,32-20 AWG / 0.05-0.5 mm² 实心和绞合线

应用和在线服务

Arduino IDE

关于这个项目

简介

在这个项目中,我们将构建一个简单的 USB MIDI 即插即用呼吸控制器。它的设计使用容易找到的廉价组件,因此总成本保持在可承受的范围内,并且远低于商业同类产品。这是只使用气压传感器的基本版本,但计划将来升级它以包括咬合和点头/倾斜传感器。

该项目假设了一些非常基本的电子学和 Arduino 知识,但即使是初学者也可以构建它,因为不涉及焊接。当然,更高级的用户可以在永久原型板上焊接所有东西。我不涉及 IDE/库的安装和上传代码的说明,因为互联网上有优秀的教程。

过采样用于平滑传感器的输入,效果非常好。您还可以根据自己的喜好调整范围,甚至可以拨入自定义曲线来调整控制器的行为。

由于传感器也可以测量负压,因此当您吸入空气而不是吹气时,会输出第二条控制器消息流。用户可以设置两种类型的消息。例如,您可以将打击设置为向上弯音,而将拉入设置为向下弯音。默认情况下,两者都设置为控制器编号。 2.

构建步骤

1. 将Arduino插入面包板,如图/示意图所示。

2. 将传感器和运放插入各自的位置,注意根据两侧小凹痕的方向。

3. 将电阻腿剪成合适的长度后插入。

4. 剪断/剥去实芯电缆并将它们放置在各自的位置。我用红色表示 5V,黑色表示接地,黄色表示信号,以便更容易理解,但您当然可以使用任何可用的。

5. 如图所示连接咬嘴、管子、三通接头和吸气器。您需要剪下一段用于“排气”的管子。

6. 按下 3 路连接器,使其适合传感器。它应该留在原地。

7. 安装 Arduino IDE 并从 Tools->Manage Libraries 安装所需的两个库(Oversampling 和 USB-MIDI)。使用 USB 电缆将 Arduino 连接到您的计算机。上传附加的代码。

8. 您应该已经设置好了,Arduino 现在应该在您的 DAW/音乐软件中显示为 MIDI 设备。启用它并将其与键盘一起路由到支持呼吸控制器的插件。

高级信息

这种设计的一个物理缺陷是唾液不可避免地会流入管中,并可能导致明显的气流波动。 3 路连接器用于通过将唾液路由到“排气”管来解决这个问题。为了尽量减少管中滞留的唾液,请通过调整管长度确保从咬嘴到 3 路连接器有一个连续的斜坡。如果管子悬挂在 3 路连接器水平面下方,唾液将被困在其较低点,从而导致波动。抽吸器的婴儿侧部分(包括其过滤器)连接到排气口,以最大程度地减少滴水和噪音,并增加进入传感器的空气流量。

在代码中,您可以根据自己的喜好调整一些值,包括自定义曲线。评论描述了如何做到这一点。如果您发现很难达到 127 点,请减小最大范围,或者如果太容易,则增加它。每当您更改值时,您都需要重新上传代码。

Arduino 启动后的前几个读数被平均以校准静止位置。请勿在连接/重置设备时向管内吹气。

您可以通过编辑 board.txt 文件来更改 MIDI 设备的名称(有关如何为每个平台执行此操作的信息可在 Internet 上找到)。

代码

  • 呼吸控制器代码
呼吸控制器代码Arduino
将此代码通过 Arduino IDE
/* Breath Controller*///Libraries used - install them from Tools->Manage Libraries#include #include //调试模式(取消注释启用)//#define DEBUG 1//创建USB MIDI接口USBMIDI_CREATE_DEFAULT_INSTANCE();//Oversampling initOversampling adc(10, 13, 6);// *********** ****** User Setup ***************** // 以 1 结尾的值对应吹气,以 2 结尾的值对应在空气中绘图 // Pin setupconst int sensorPin1 =A0; //为传感器/运算放大器输出选择Arduino输入引脚//范围校准。手动调整,这样你就可以达到最大值但不太容易。int sensorRange1 =800;int sensorRange2 =800;// 输出控制器编号。从下表中选择// 0-127:常规控制更改消息// 128:单声道触后// 129:向上弯音// 130:向下弯音 int controllerNumber1 =2; // 当吹气时发送控制器int controllerNumber2 =2; // 在空气中绘制时发送控制器// 输出控制器通道int controllerChannel1 =1;int controllerChannel2 =1;// 最低和最高值的安全阈值,以避免静止或最大值时的波动。 // 如果在静止时发送多条消息,则增加 lowThreshold。 // 如果在最大值时发送多条消息,则增加 highThreshold。 const int lowThreshold1 =5;const int lowThreshold2 =5;const int highThreshold1 =0;const int highThreshold2 =0;// 曲线定义。表可以具有等于或大于 2 的任何长度。值可以是 0-127 。表格应具有相同数量的元素,“输入”表格应按升序排列。// 转换是在读数级别完成的,因此定义的损失最小化。int in1[] ={0, 127};int out1[] ={0, 127};int in2[] ={0, 127};int out2[] ={0, 127};// 示例曲线(相应地修改传感器编号)//Soft//int in1[] ={ 0, 6,24,78,127};//int out1[] ={0,32,64,96,127};//缩小范围//int in1[] ={50, 100};//int out1[] ={50, 100};// 刷新周期(毫秒)。较低的值意味着在操作期间发送更多的消息。int refreshCycle =0;// ***************** 实现 *************** ** // 如果您不打算更改传感器的操作,请不要从这一点开始修改。// Sensorsint sensorValue1 的内部值 =0;int sensorValue2 =0;// 最小传感器值 int sensorMin1;int sensorMin2;// 输出控制器值int controllerValue1 =0;int controllerValue2 =0;// 用于避免重复相同消息的先前循环值int previousControllerValue1 =0;int previousControllerValue2 =0;// 范围转换变量initint outputRange1;int outputRange2;int sensorLow1; int sensorLow2;int sensorHigh1;int sensorHigh2;void setup() { MIDI.begin(1);#ifdef DEBUG Serial.begin (115200); //仅用于调试模式#endif// 通过对前 10 个值取平均值来校准传感器的静止点。启动设备时请勿使用传感器。 sensorMin1 =adc.read(sensorPin1); sensorMin2 =0;// 确定所选控制器的输出范围 outputRange1 =outputRange(controllerNumber1); outputRange2 =outputRange(controllerNumber2);}void loop() {// 从传感器读取值:sensorValue1 =adc.read(sensorPin1); // 吹气 sensorValue2 =sensorMin1 - sensorValue1; // 在空中绘制// 存储以前的值 previousControllerValue1 =controllerValue1;以前的控制器值 2 =控制器值 2; // 传感器上/下的可用范围限制 sensorLow1 =sensorMin1 + lowThreshold1; sensorLow2 =sensorMin2 + lowThreshold2; sensorHigh1 =sensorLow1 + sensorRange1 - highThreshold1; sensorHigh2 =min(sensorMin1,sensorRange2) - highThreshold2;// 使用“in”和“出”表。 controllerValue1 =map(mapToCurve(constrain(sensorValue1,sensorLow1,sensorHigh1),sensorLow1,sensorHigh1,in1,out1,sizeof(in1)/sizeof(int)),sensorLow1,sensorHigh1,0,outputRange1); controllerValue2 =map(mapToCurve(constrain(sensorValue2,sensorLow2,sensorHigh2),sensorLow2,sensorHigh2,in2,out2,sizeof(in2)/sizeof(int)),sensorLow2,sensorHigh2,0,outputRange2);// 发送 MIDI 消息 if ( controllerValue1 !=previousControllerValue1) sendSensorOutput(controllerNumber1, controllerValue1, controllerChannel1); if (controllerValue2 !=previousControllerValue2) sendSensorOutput(controllerNumber2, controllerValue2, controllerChannel2);// Debug#ifdef DEBUG// Sensor (input) values (uncomment for debug)// Serial.print (sensorValue1);// Serial.print (" ,");// Serial.print (sensorValue2);// Serial.print (","); // 控制器(输出)值 Serial.print (controllerValue1); Serial.print(","); Serial.println (controllerValue2);#endif // 停止程序  毫秒:delay(refreshCycle);}// 用于根据控制器编号发送 MIDI 消息的函数 void sendSensorOutput (int number, int value, int channel) { if (number <128) MIDI.sendControlChange(number, value, channel); else if (number ==128) MIDI.sendAfterTouch(value, channel); else if (number ==129) MIDI.sendPitchBend(value, channel); else if (number ==130) MIDI.sendPitchBend(-value, channel);}// 用于确定特定控制器范围的函数。这是因为弯音的范围比常规控制器更大。 int outputRange (int number) { if (number> 128) return 8191; else return 127;}// 用于创建曲线的修改后的 multiMap 函数。原作者 Rob Tillaart.int mapToCurve(int val, int sensorLow, int sensorHigh, int* _in, int* _out, uint8_t size){ // 注意值在范围内 // val =constrain(val, _in[0] , _in[size-1]); if (val <=map(_in[0],0,127,sensorLow,sensorHigh)) 返回 map(_out[0],0,127,sensorLow,sensorHigh); if (val>=map(_in[size-1],0,127,sensorLow,sensorHigh)) return map(_out[size-1],0,127,sensorLow,sensorHigh); // 搜索右区间 uint8_t pos =1; // _in[0] 已经测试过 while(val> map(_in[pos],0,127,sensorLow,sensorHigh)) pos++; // 将范围从 ..127 调整为传感器范围 int inPos =map(_in[pos],0,127,sensorLow,sensorHigh); int outPos =map(_out[pos],0,127,sensorLow,sensorHigh); int inPrv =map(_in[pos-1],0,127,sensorLow,sensorHigh); int outPrv =map(_out[pos-1],0,127,sensorLow,sensorHigh); // 这将处理 _in 数组中的所有精确“点” if (val ==inPos) return outPos; // 在右侧部分插入剩余的返回值 ((long)val - (long)inPrv) * ((long)outPos - (long)outPrv) / ((long)inPos - (long)inPrv) + (long) outPrv;}

示意图

Fritzing示意图 电路原理图

制造工艺

  1. 带有 Arduino 的用于飞行模拟器的 LCD 面板
  2. Web 操作的 DMX 控制器
  3. Arduino 游戏控制器
  4. Unopad - 带有 Ableton 的 Arduino MIDI 控制器
  5. 文本传送器
  6. 真空荧光显示控制器
  7. 由 Alexa 激活的 Arduino 家庭控制器
  8. 学校的智能温度监测
  9. Arduino 的 8 位 IO 端口库
  10. Arduino 的 64 键原型键盘矩阵
  11. Arduino 的隔离模拟输入
  12. 超酷室内导航机器人