제조공정
| × | 1 | ||||
| × | 11 | ||||
| × | 88 | ||||
| × | 2 | ||||
| × | 11 | ||||
| × | 1 | ||||
| × | 11 | ||||
| × | 11 | ||||
| × | 88 | ||||
| × | 88 |
|
| ||||
| ||||
|
시작 방법:
몇 년 전 Yamaha는 자동 피아노를 도입했습니다. 어리고 순진한 나는 악기 가게 유리창 뒤에서 피아노가 연주하는 것을 보았습니다.
잡담은 그만하고, 정말 하고 싶었던 것 외에는 이 프로젝트를 시작한 큰 이유가 없습니다.
개요:
Arduino Mega의 단일 보드는 약 $40이며 88개의 솔레노이드를 제어하려면 2개가 필요합니다. 그것은 꽤 비싸다. 대신 저렴한 Arduino Uno와 11개의 시프트 레지스터를 구입하십시오. 시프트 레지스터는 적은 수의 출력 핀으로 많은 출력(보통 LED)을 제어하는 방법입니다. 기본적으로 11개의 시프트 레지스터와 88개의 솔레노이드를 제어하는 하나의 Arduino입니다.
시프트 레지스터를 사용하기 때문에 PC는 MIDI com 대신 Arduino에 비트 세트를 보냅니다. MIDI 파일은 미리 비트 세트로 변환됩니다.
하드웨어:
중국에서 직접 솔레노이드를 받았을 때 이 솔레노이드가 피아노 건반을 누르기에 충분히 강하지 않다는 것을 알았습니다. 물론 가장 안쪽에서 피아노 건반을 누르는 것이 더 힘이 들지만 피아노를 망가뜨리지 않는 최선의 방법이라고 생각했습니다. 결국 충분한 전력을 얻기 위해 12V 솔레노이드를 통해 24V를 밀어 넣었습니다.
88 솔레노이드는 전력을 많이 소모하고 비싼 PSU를 사러 갈 수 없어서 아버지의 자동차 배터리로 가기로 결정했습니다. (그는 이제 아무데도 가지 않을 것입니다!)
그렇게 하면 시프트 레지스터와 MOSFET 각각이 컨트롤러 보드에 들어갈 것입니다.
595 오른쪽에 소켓이 있어 태울 수 있습니다. (한 번 했습니다.) Circuit Diagram은 여기에서 예제 2와 정확히 동일합니다. LED를 MOSFET 게이트로 교체하십시오. 보시다시피 추가 저항으로 인해 비용이 증가하고 해당 보드에 납땜하면 손가락이 녹기 때문에 풀다운 저항이 없습니다. 좀 더 심각한 측면에서 이러한 MOSFET은 5V에서 열리고 4V 정도에서 닫힙니다. 수많은 테스트를 통해 확인했습니다. (이론적으로 정확하지 않습니다. 내 말을 듣지 마십시오.)
마지막으로 솔레노이드를 붙일 플라스틱 판을 얻습니다. 뜨거운 접착제와 플라스틱 판을 사용하는 것은 뜨거워질 수 있다는 점을 생각하면 좋지 않지만 제가 감당할 수 있는 최선입니다.
그런 다음 솔레노이드 전선의 한쪽을 배터리의 양극에 연결합니다.
소프트웨어:
가장 첫 번째 단계는 미디 파일을 얻는 것입니다.
두 번째 단계는 미디를 텍스트 형식으로 가져오는 것입니다. 이것은 이 편리한 웹사이트에서 할 수 있습니다:http://flashmusicgames.com/midi/mid2txt.php.
간단하게 하기 위해 박자표, 템포 및 파를 무시합니다. 템포는 나중에 시간을 곱할 수 있습니다. 기본적으로 다음과 같은 파일이 필요합니다.
이제 이를 파이썬 코드(첨부)를 통해 실행하여 시간에 따른 8비트 데이터 11세트를 생성합니다.
COM 처리를 통해 Arduino로 보낼 준비가 되었습니다.
처리 과정에서 이러한 데이터를 보내는 방법과 Arduino가 데이터를 처리하는 방법을 알아보려면 첨부 파일을 참조하세요.
*참고:제 코딩 습관이 좋지 않아 읽기 어려울 수 있습니다. Arduino가 실제 피아노에서 데이터를 오른쪽으로 밀어넣기 때문에 프로세싱은 데이터를 오른쪽에서 왼쪽으로 보냅니다.
작동하는 작업:
문제 해결:
전문 엔지니어가 이 글을 본다면 이 전체 시스템에 많은 문제가 있을 것이라고 생각할 것입니다. 그리고 많은 문제가 있습니다.
솔레노이드가 플레이트에 핫 글루로 접착되기 때문에 솔레노이드가 과열되어 핫 글루가 녹는 것이 큰 문제였습니다. 해결책은 단순히 그것들을 제거하고 150C까지 견딜 수 있는 양면 테이프로 교체하는 것이었습니다.
섹션> <섹션 클래스="섹션 컨테이너 섹션 축소 가능" id="코드">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():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(참고>=29 및 참고 <=36 및 켜짐):반환 "0," + str(2**(주 - 29)) + ",0,0,0,0,0,0, 0,0,0" elif(참고>=37 및 참고 <=44 및 켜기):반환 "0,0," + str(2**(참고 - 37)) + ",0,0,0,0 ,0,0,0,0" elif(참고>=45 및 참고 <=52 및 켜짐):"0,0,0," + str(2**(주 - 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(참고>=61 및 참고 <=68 및 켜짐):return "0,0,0,0,0," + str(2**( 참고 - 61)) + ",0,0,0,0,0" elif(참고>=69 및 참고 <=76 및 켜기):반환 "0,0,0,0,0,0," + str (2**(참고 - 69)) + ",0,0,0,0" elif(참고>=77 및 참고 <=84 및 켜기):"0,0,0,0,0,0, 0," + str(2**(참고 - 77)) + ",0,0,0" elif(참고>=85 및 참고 <=92 및 켜짐):"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**(참고 - 93)) + ",0" elif(참고>=101 및 참고 <=108 및 켜짐):"0,0,0,0,0,0,0,0,0,0,"을 반환합니다. + str(2**(참고 - 101)) else:"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(참고>=21 및 참고 <=28):local_temp =temp[0:temp.find(",")] if(On):return str(int(local_temp) + (2**(주 - 21)) + temp[temp.find(","):] if(not On):반환 str(int(local_temp) - (2**(주 - 21))) + temp[temp.find(","):] elif(참고>=29 및 참고 <=36):local_temp =temp[(temp.find(",") + 1):indexTh(temp, "," , 2)] if(On):반환 temp[0:temp.find(",") + 1] + str(int(local_temp) + (2**(참고 - 29))) + temp[indexTh(temp , ",", 2):] if(on이 아님):반환 temp[0:temp.find(",") + 1] + str(int(local_temp) - (2**(참고 - 29))) + temp[indexTh(temp, ",", 2):] elif(참고>=37 및 참고 <=44):local_temp =temp[(indexTh(temp, ",", 2) + 1):indexTh(temp , ",", 3)] if(On):반환 temp[0:indexTh(temp, ",", 2) + 1] + str(int(local_temp) + (2**(참고 - 37))) + 온도[in dexTh(temp, ",", 3):] if(not On):return temp[0:indexTh(temp, ",", 2) + 1] + str(int(local_temp) - (2**(참고) - 37))) + temp[indexTh(temp, ",", 3):] elif(참고>=45 및 참고 <=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**(참고 - 45))) + temp[indexTh(temp, ",", 4):] elif(참고>=53 및 참고 <=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**(참고 - 53))) + temp[indexTh(temp, ",", 5):] if(not On):반환 temp[0:indexTh(temp, ",", 4) + 1] + str(int(local_temp) - (2**(참고 - 53)) + temp[indexTh(temp, ",", 5):] elif(참고>=61 및 참고 <=68):local_temp =temp[(indexTh(temp, ",", 5) + 1):indexTh(temp, ",", 6)] if(On):반환 temp[0:indexTh(temp, ",", 5) + 1 ] + str(int(local_temp) + (2**(참고 - 61)) + temp[indexTh(temp, ",", 6):] if(not On):temp[0:indexTh(temp, ",", 5) + 1] + str(int(local_temp) - (2**(참고 - 61)) + temp[indexTh(temp, ",", 6):] elif(참고>=69 및 참고 <=76):local_temp =temp[(indexTh(temp, ",", 6) + 1):indexTh(temp, ",", 7)] if(On):반환 temp[0:indexTh(temp, ",", 6) + 1] + str(int(local_temp) + (2**(참고 - 69)) + temp[indexTh(temp, ",", 7):] if(not On):반환 temp[0:indexTh(temp, ",", 6) + 1] + str(int(local_temp) - (2**(참고 - 69))) + temp[indexTh(temp, ",", 7):] elif(참고>=77 및 참고 <=84):local_temp =temp[(indexTh(temp, ",", 7) + 1):indexTh(temp, ",", 8)] if(On):반환 temp[0:indexTh(temp, ",", 7) + 1] + str(int(local_temp) + (2**(참고 - 77))) + temp[indexTh(temp, ",", 8):] if(not On):return temp[0:indexTh(temp, ",", 7) + 1] + str(int(local_temp) - (2**(참고 - 77))) + temp[indexTh(temp , ",", 8):] elif(참고>=85 및 참고 <=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**(참고 - 85) ))) + temp[indexTh(temp, ",", 9):] if(not On):return temp[0:indexTh(temp, ",", 8) + 1] + str(int(local_temp) - (2**(참고 - 85))) + temp[indexTh(temp, ",", 9):] elif(참고>=93 및 참고 <=100):local_temp =temp[(indexTh(temp, ", ", 9) + 1):indexTh(temp, ",", 10)] if(On):반환 temp[0:indexTh(temp, ",", 9) + 1] + str(int(local_temp) + (2**(참고 - 93))) + temp[indexTh(temp, ",", 10):] if(not On):return temp[0:indexTh(temp, ",", 9) + 1] + str(int(local_temp) - (2**(참고 - 93))) + temp[indexTh(temp, ",", 10):] elif(참고>=101 및 참고 <=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):# 문자열, 찾을 문자열, 찾을 문자열을 찾는 순서를 취합니다. that order #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 반환 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=") - in_string[start:end] =="On"이면 1이면 true를 반환합니다. return True elif in_string[start:end] =="Off":Falsemain()을 반환
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; iArduino 코드Arduino
아두이노를 위한 간단한 코드. 직렬에서 입력을 가져옵니다. 888 및 999는 시프트 레지스터 열기 및 닫기 명령용으로 예약되어 있습니다.미리 보기 없음(다운로드 전용).섹션>회로도
전문적이지 않은 그림을 그려서 죄송합니다. 이것이 전체 개념입니다. 아두이노 -ShiftOut 문서의 다이어그램은 MOSFET을 제외하고는 차이가 없습니다. 그것도 보시는 걸 추천합니다.
제조공정
이 튜토리얼에서는 어떤 방향으로든 움직일 수 있는 Arduino Mecanum Wheels 로봇을 만드는 방법을 배울 것입니다. 로봇의 이러한 독특한 이동성은 메카넘 휠(Mecanum Wheels)이라는 특수한 유형의 바퀴를 사용하여 이루어집니다. 다음 비디오를 보거나 아래에 작성된 튜토리얼을 읽을 수 있습니다. 개요 저는 실제로 이 휠을 디자인하고 3D로 인쇄했습니다. 구매 비용이 조금 비쌀 수 있기 때문입니다. 그것들은 아주 잘 작동하고 나는 이 로봇 플랫폼을 운전하는 것이 매우 재미있다고 말해야 합니다. NRF24L01
이 튜토리얼에서는 Arduino hexapod를 구축하는 방법을 보여줍니다. 이름에서 알 수 있듯이 헥사포드에는 6개의 다리가 있지만 그 외에도 꼬리 또는 복부, 머리, 안테나, 하악 및 기능적인 눈도 있습니다. 이 모든 것이 헥사포드를 개미처럼 보이게 하므로 Arduino Ant Robot이라고도 부를 수 있습니다. 다음 비디오를 보거나 아래에 작성된 튜토리얼을 읽을 수 있습니다. 개요 로봇을 제어하기 위해 맞춤형 Android 애플리케이션을 만들었습니다. 앱에는 4개의 버튼이 있어 로봇에게 전진 또는 후진, 좌회전 또는 우