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

Arduino 控制的钢琴机器人:PiBot

组件和用品

Arduino 101
× 1
Texas Instruments 74HC595
× 11
IRFZ44N
N 通道 Mosfet
× 88
12V 电池
× 2
电容 100 µF
× 11
OpenBuilds 线缆 - 脚下
很多。
× 1
面包板(通用)
或通用原型板。几乎任何可以将事情组合在一起的东西。
× 11
8 脚 IC 插座
可选,如果你确信你不会烧掉这些昂贵的 595 中的任何一个
× 11
电阻 10k ohm
未用于此项目,但最好用于每个 mosfet
× 88
1N4007 – 高电压、高额定电流二极管
未用于此项目,但最好用于每个 mosfet
× 88

必要的工具和机器

热胶枪(通用)

应用和在线服务

处理
Python
二进制 MIDI 文件转文本

关于这个项目

如何开始:

许多年前,雅马哈推出了自动钢琴。年少无知的我,在一家乐器店的玻璃窗后面,看到了那架钢琴演奏的音乐。

闲聊够了,我开始这个项目真的没有什么大的理由,除了我只是想这么做。

概述:

一块 Arduino Mega 的单板成本约为 40 美元,需要两块板来控制 88 个螺线管。那相当昂贵。相反,获得一个便宜的 Arduino Uno 和 11 个移位寄存器。移位寄存器是一种用少量输出引脚控制许多输出(通常是 LED)的方法。本质上,它是一个带有 11 个移位寄存器和控制 88 个电磁阀的 Arduino。

由于我们使用移位寄存器,PC 将向 Arduino 而不是 MIDI com 发送一组位。 MIDI 文件将事先被翻译成一组比特。

硬件:

当我直接从中国拿到螺线管时,我发现这些螺线管的强度不足以推动钢琴键。当然,从最里面推钢琴键需要更大的力,但我认为这是不会损坏钢琴的最佳方法。最终,我通过 12V 螺线管推动了 24V 以获得足够的电力。

88 电磁阀耗电量大,因为买不起昂贵的电源,我决定用我爸爸的汽车电池。 (猜猜他现在哪儿也不去!)

这样一来,移位寄存器和 MOSFET 中的每一个都将安装在一个控制器板上。

595 右边有一个插座,以防我烧掉它。 (我做过一次。)电路图与此处的示例 2 完全相同。用 MOSFET 栅极替换 LED。如您所见,没有下拉电阻器,因为额外的电阻器会增加成本,并且将它们焊接在该板上会融化我的手指。从更严重的方面来说,这些 MOSFET 将在 5V 时打开并在 4V 左右时关闭。通过无数小时的测试证实了这一点。 (理论上不正确。不要听我的。)

最后,拿一块塑料板将螺线管粘在上面。考虑到它会变热,使用热胶和塑料板是一个坏主意,但这是我能负担得起的最好的。

然后将电磁线圈的一侧连接到电池的正极。

软件:

第一步是获取一个midi文件。

第二步,将midi转成文本形式。这可以在这个方便的网站上完成:http://flashmusicgames.com/midi/mid2txt.php。

为简单起见,忽略拍号、速度和标准杆。速度可以乘以稍后的时间。基本上你想要一个这样的文件:

现在,通过 Python 代码(附后)运行它,使用它创建 11 组 8 位数据随时间变化。

它们已准备好通过处理 COM 发送到 Arduino。

请参阅附件以了解处理如何发送这些数据以及 Arduino 如何处理它们。

*注意:我的编码习惯很差,可能很难阅读。处理从右向左发送数据,因为 Arduino 在物理钢琴上将数据向右推送。

这东西有效:

故障排除:

如果专业工程师看到这个帖子,他会认为整个系统会有很多问题。还有很多问题。

由于螺线管是热粘在板上的,因此螺线管过热和熔化热胶是一个大问题。解决方案是简单地将它们取下并用可承受高达 150C 的双面胶带替换。

代码

  • 用于翻译的 Python 代码
  • 处理向arduino发送数据
  • Arduino 代码
用于翻译的 Python 代码Python
获取文本化的 mifi 文件并将其转换为 11 组二进制文件供 arduino 获取。
output_file =open("translated.txt", "w")input_file =open("megalocania.txt")raw_input_data =input_file.read ()work_data =raw_input_data.splitlines()result =[]#output_file =open("result.txt", "w")def main():for a in work_data:temp_time =time_finder(a) if result ==[] :result.append(str(temp_time) + ",") if on_off_finder(a):result[-1] +=set_bit(True, note_finder(a)) elif not on_off_finder(a):result[-1] +=set_bit(True, note_finder(a)) elif time_finder_comm(result[-1]) ==temp_time:result[-1] =str(temp_time) + "," + set_bit_prev(on_off_finder(a), note_finder(a), - 1) elif time_finder_comm(result[-1]) !=temp_time:result.append(str(temp_time) + "," + set_bit_prev(on_off_finder(a), note_finder(a), -1)) for b in result:output_file .write(b) output_file.write("\n") output_file.close() def set_bit(On, note):#使用布尔值判断是否开启,以及注释编号。 #生成位 if(note>=21 and note <=28 and On):return str(2**(note - 21)) + ",0,0,0,0,0,0,0,0,0 ,0" elif(note>=29 and note <=36 and On):return "0," + str(2**(note - 29)) + ",0,0,0,0,0,0, 0,0,0" elif(note>=37 and note <=44 and On):return "0,0," + str(2**(note - 37)) + ",0,0,0,0 ,0,0,0,0" elif(note>=45 and note <=52 and On):return "0,0,0," + str(2**(note - 45)) + ",0, 0,0,0,0,0,0" elif(note>=53 and note <=60 and On):return "0,0,0,0," + str(2**(note - 53)) + ",0,0,0,0,0,0" elif(note>=61 and note <=68 and On):return "0,0,0,0,0,0," + str(2**( note - 61)) + ",0,0,0,0,0" elif(note>=69 and note <=76 and On):return "0,0,0,0,0,0," + str (2**(note - 69)) + ",0,0,0,0" elif(note>=77 and note <=84 and On):return "0,0,0,0,0,0, 0," + str(2**(note - 77)) + ",0,0,0" elif(note>=85 and note <=92 and On):return "0,0,0,0,0 ,0,0,0," + str(2**(note - 85)) + ",0,0" elif(note>=93 and note <=100 and On):return "0,0,0, 0,0,0,0,0,0," + str(2**(note - 93)) + ",0" elif(note>=101 and note <=108 and On):返回 "0,0,0,0,0,0,0,0,0,0," + str(2**(note - 101)) else:return "0,0 ,0,0,0,0,0,0,0,0,0"def set_bit_prev(On, note, index):#与 set_bit 相同,但之前知道 temp =result[index] temp =temp[(temp.find (",") + 1):] if(note>=21 and note <=28):local_temp =temp[0:temp.find(",")] if(On):return str(int(local_temp) + (2**(note - 21))) + temp[temp.find(","):] if(not On):return str(int(local_temp) - (2**(note - 21))) + temp[temp.find(","):] elif(note>=29 and note <=36):local_temp =temp[(temp.find(",") + 1):indexTh(temp, "," , 2)] if(On):return temp[0:temp.find(",") + 1] + str(int(local_temp) + (2**(note - 29))) + temp[indexTh(temp , ",", 2):] if(not On):return temp[0:temp.find(",") + 1] + str(int(local_temp) - (2**(note - 29))) + temp[indexTh(temp, ",", 2):] elif(note>=37 and note <=44):local_temp =temp[(indexTh(temp, ",", 2) + 1):indexTh(temp , ",", 3)] if(On):return temp[0:indexTh(temp, ",", 2) + 1] + str(int(local_temp) + (2**(note - 37))) + 温度[输入dexTh(temp, ",", 3):] if(not On):return temp[0:indexTh(temp, ",", 2) + 1] + str(int(local_temp) - (2**(note) - 37))) + temp[indexTh(temp, ",", 3):] elif(note>=45 and note <=52):local_temp =temp[(indexTh(temp, ",", 3) + 1 ):indexTh(temp, ",", 4)] if(On):return temp[0:indexTh(temp, ",", 3) + 1] + str(int(local_temp) + (2**(注意- 45))) + temp[indexTh(temp, ",", 4):] if(not On):return temp[0:indexTh(temp, ",", 3) + 1] + str(int(local_temp) ) - (2**(note - 45))) + temp[indexTh(temp, ",", 4):] elif(note>=53 and note <=60):local_temp =temp[(indexTh(temp, ",", 4) + 1):indexTh(temp, ",", 5)] if(On):return temp[0:indexTh(temp, ",", 4) + 1] + str(int(local_temp) ) + (2**(note - 53))) + temp[indexTh(temp, ",", 5):] if(not On):return temp[0:indexTh(temp, ",", 4) + 1] + str(int(local_temp) - (2**(note - 53))) + temp[indexTh(temp, ",", 5):] elif(note>=61 and note <=68):local_temp =temp[(indexTh(temp, ",", 5) + 1):indexTh(temp, ",", 6)] if(On):return temp[0:indexTh(temp, ",", 5) + 1 ] + str(int(local_temp) + (2**(note - 61))) + temp[indexTh(temp, ",", 6):] if(not On):return temp[0:indexTh(temp, ",", 5) + 1] + str(int(local_temp) - (2**(note - 61))) + temp[indexTh(temp, ",", 6):] elif(note>=69 and note <=76):local_temp =temp[(indexTh(temp, ",", 6) + 1):indexTh(temp, ",", 7)] if(On):return temp[0:indexTh(temp, ",", 6) + 1] + str(int(local_temp) + (2**(note - 69))) + temp[indexTh(temp, ",", 7):] if(not On):return temp[0:indexTh(temp, ",", 6) + 1] + str(int(local_temp) - (2**(note - 69))) + temp[indexTh(temp, ",", 7):] elif(note>=77 and note <=84):local_temp =temp[(indexTh(temp, ",", 7) + 1):indexTh(temp, ",", 8)] if(On):return temp[0:indexTh(temp, ",", 7) + 1] + str(int(local_temp) + (2**(note - 77))) + temp[indexTh(temp, ",", 8):] if(not On):return temp[0:indexTh(temp, ",", 7) + 1] + str(int(local_temp) - (2**(note - 77))) + temp[indexTh(temp) , ",", 8):] elif(note>=85 and note <=92):#error here local_temp =temp[(indexTh(temp, ",", 8) + 1):indexT h(temp, ",", 9)] if(On):return temp[0:indexTh(temp, ",", 8) + 1] + str(int(local_temp) + (2**(note - 85) ))) + temp[indexTh(temp, ",", 9):] if(not On):return temp[0:indexTh(temp, ",", 8) + 1] + str(int(local_temp) - (2**(note - 85))) + temp[indexTh(temp, ",", 9):] elif(note>=93 and note <=100):local_temp =temp[(indexTh(temp, ", ", 9) + 1):indexTh(temp, ",", 10)] if(On):return temp[0:indexTh(temp, ",", 9) + 1] + str(int(local_temp) + (2**(note - 93))) + temp[indexTh(temp, ",", 10):] if(not On):return temp[0:indexTh(temp, ",", 9) + 1] + str(int(local_temp) - (2**(note - 93))) + temp[indexTh(temp, ",", 10):] elif(note>=101 and note <=108):local_temp =temp [(indexTh(temp, ",", 10) + 1):] if(On):return temp[0:indexTh(temp, ",", 10) + 1] + str(int(local_temp) + (2) **(note - 101))) if(not On):return temp[0:indexTh(temp, ",", 10) + 1] + str(int(local_temp) - (2**(note - 101) )) def indexTh(in_string, find_this, th):#取字符串,要查找的字符串,以及要查找的字符串的顺序该顺序 #returns index order =1 last_index =0 while(True):temp =in_string.find(find_this, last_index) if(temp ==-1):return -1 if(order ==th):return temp order + =1 last_index =temp + 1def time_finder(in_string):#取一个字符串并找到时间,以int形式返回 time_end =in_string.index(" ") return int(in_string[0:time_end])def time_finder_comm(in_string):#取字符串求时间,以int逗号返回 time_end =in_string.index(",") return int(in_string[0:time_end]) def note_finder(in_string):#取字符串,查找n=,返回 n 值作为 int num_start =in_string.index("n=") + 2 num_end =in_string.index("v=") - 1 return int(in_string[num_start:num_end])def on_off_finder(in_string):#takes一个字符串,查找 On 或 Off,如果 On start =in_string.index(" ") + 1 end =in_string.index("ch=") - 1 if in_string[start:end] =="On",则返回 true: return True elif in_string[start:end] =="Off":return Falsemain()
向arduino发送数据的处理处理
读取翻译后的文本文件并将其发送到 arduino。
如果速度不同于 50000,则必须修改速度乘数。
反转字节,因为它从左向右移动。 (文本文件假设从右到左)
import processing.serial.*;Serial myPort;String[] inputLines;void setup(){ myPort =new Serial(this, "COM3", 9600); inputLines =loadStrings("translated.txt"); run();}void run(){ //使用数据方法读取时间并发送数据bt行 int lastTime =0; for(int i =0; i  
Arduino 代码Arduino
arduino 的简单代码。从串行获取输入。 888 和 999 为移位寄存器打开和关闭命令保留。
无预览(仅下载)。

示意图

不专业的画图请见谅。这是整个概念。除了 mosfet 之外,Arduino -ShiftOut 文档的图表之间没有区别。我也建议看那个。

制造工艺

  1. 通过蓝牙控制的树莓派机器人
  2. 使用 Arduino 和 Raspberry Pi 构建您的 Internet 控制的视频流机器人
  3. 使用 Raspberry Pi 的 Wifi 控制机器人
  4. Alexa 通过 Raspberry Pi 控制 LED
  5. 钢铁侠
  6. 找到我
  7. Arduino 加湿器控制
  8. 语音控制机器人
  9. MobBob:由 Android 智能手机控制的 DIY Arduino 机器人
  10. Arduino Joystick
  11. 计步器(Arduino 101)
  12. Arduino 混色器