산업 제조
산업용 사물 인터넷 | 산업자재 | 장비 유지 보수 및 수리 | 산업 프로그래밍 |
home  MfgRobots >> 산업 제조 >  >> Manufacturing Technology >> 제조공정

스크랩 DVD 드라이브 L293D를 사용하여 미니 CNC 2D 플로터를 만드는 방법

구성품 및 소모품

Arduino UNO
기계의 두뇌
× 1
L293D 모터 실드
축의 스테퍼 모터 제어
× 1
Tower pro 서보 모터 9g
Zaxis 이동 펜 UP 및 펜 DOWN
× 1
스크랩 DVD 박사
기계적 X축 및 Y축
× 1
점퍼 와이어(일반)
× 1

앱 및 온라인 서비스

Arduino IDE
IDE 처리
잉크스케이프

이 프로젝트 정보

그림과 같이 두 개의 스크랩 DVD 드라이브를 정렬하십시오.

1. Arduino IDE 다운로드

2. 처리 IDE 다운로드

3. Arduino IDE를 열고 에서 다운로드한 코드를 로드합니다. 여기 .

4. 처리 IDE를 열고 에서 다운로드한 코드를 로드합니다. 여기 .

스크랩 DVD 드라이브를 열고 내부 이동 트레이를 제거합니다. 스테퍼 메커니즘이 있는 이 트레이는 X축 및 Y축 역할을 합니다. 기계를 조립하는 방법을 이해하려면 첨부된 사진을 참조하십시오. 빈 DVD 드라이브 케이스에 구멍을 뚫고 너트 볼트를 사용하여 각 DVD 케이스에 X축과 Y축을 장착합니다.

이제 서로 수직으로 놓습니다.

G 코드

이 CNC 기계와 호환되는 g-code 파일을 만들려면 Inkscape를 사용해야 합니다.

Inkscape는 Windows, Mac OS X 및 Linux에서 실행되는 전문적인 품질의 벡터 그래픽 소프트웨어입니다. 일러스트레이션, 아이콘, 로고, 다이어그램, 지도 및 웹 그래픽과 같은 다양한 그래픽을 만들기 위해 전 세계의 디자인 전문가와 애호가가 사용합니다. Inkscape는 W3C 개방형 표준 SVG(Scalable Vector Graphics)를 기본 형식으로 사용하며 무료 및 오픈 소스 소프트웨어입니다. 여기에서 Inkscape를 다운로드하여 설치하십시오.

(중요 :0.48.5 버전 다운로드) 이제 이미지를 g-code 파일로 내보낼 수 있는 애드온을 설치해야 합니다. 이 추가 기능은 설치 정보와 함께 여기에서 찾을 수 있습니다.

G-code 파일 생성 방법은 유튜브 영상을 참고해주세요.

<울>
  • 처리 IDE에 gctrl 파일을 업로드하고 처리 창에서 PLAY 버튼을 클릭합니다.
  • <울>
  • 먼저 'p'를 눌러 통신 포트를 선택하세요.
  • <울>
  • 원하는 경우 키보드에서 1,2 또는 3 버튼을 눌러 조그 속도를 설정할 수 있습니다.
  • <울>
  • 'g'를 눌러 G 코드 파일을 로드합니다.
  • <울>
  • G 코드 파일을 선택하여 Enter 키를 누르는 즉시 시스템이 플롯할 준비가 된 것입니다.
  • 이제 플로터가 준비되었습니다. 일부 준비된 G 코드 파일 다운로드 링크:

    <울>
  • https://www.dropbox.com/s/bazynxife4k1trv/Hisoka.gcode?dl=0
  • <울>
  • https://www.dropbox.com/s/h6bkdr5lhegbj6a/papay.gcode?dl=0
  • <울>
  • https://www.dropbox.com/s/ueku5ckt6m4cmg4/spong1.gcode?dl=0
  • 주목 해 주셔서 감사합니다! 완전한 그림을 보려면 이 링크를 방문하십시오.

    기계를 라이브로 볼 수 있는 비디오:

    <섹션 클래스="섹션 컨테이너 섹션 축소 가능" id="코드">

    코드

    <울>
  • Arduino CNC 코드
  • 코드 처리
  • Arduino CNC 코드Arduino
    이 코드를 Arduino에 업로드하십시오.
    #include #include #define LINE_BUFFER_LENGTH 512char STEP =MICROSTEP;// 상하 서보 위치 const int penZUp =95;const int penZDown =83; // PWM 핀 10번의 서보 const int penServoPin =10;// DVD 스테퍼에 적합해야 하지만 여기에서는 그다지 중요하지 않습니다. const int stepsPerRevolution =48; // 서보를 제어하기 위한 서보 객체 생성 Servo penServo; // L293D H-bridgeAF_Stepper용 Arduino 핀을 사용하여 X축 및 Y축용 스테퍼를 초기화합니다. myStepperY(stepsPerRevolution,1); AF_Stepper myStepperX(stepsPerRevolution,2); /* 구조체, 전역 변수 */struct point { float x; 플로트 y; 플로트 z; };// plotheadstruct point actuatorPos;// 도면 설정은 OK여야 합니다. 스케치를 테스트하여 100단계를 이동합니다. 선의 길이를 측정합니다. // mm당 걸음 수를 계산합니다. 여기에 입력하십시오.float StepsPerMillimeterX =100.0;float StepsPerMillimeterY =100.0;// 로봇 한계를 mm 단위로 그리기// 시작하는 것이 좋습니다. 잘 보정하면 최대 50mm까지 올라갈 수 있습니다. float Xmin =0;float Xmax =40;float Ymin =0;float Ymax =40;float Zmin =0;float Zmax =1;float Xpos =Xmin;float Ypos =Ymin;float Zpos =Zmax; // 디버그 출력을 얻으려면 true로 설정합니다.boolean verbose =false;// 해석 필요 // G1 이동// G4 P300(150ms 대기)// M300 S30(펜다운)// M300 S50(펜업)/ / (// 다른 명령을 모두 버리십시오!/********************** * void setup() - 초기화 ******* ****************/void setup() { // 설정 Serial.begin( 9600 ); penServo.attach(penServoPin); penServo.write(penZUp); delay(100); // 필요한 경우 감소 myStepperX.setSpeed(600); myStepperY.setSpeed(600); // 초기 기본 위치로 설정 및 이동 // 미정 // 알림!!! Serial.println("미니 CNC 플로터가 살아있고 킥! "); Serial.print("X 범위는 "); Serial.print(Xmin); Serial.print("에서 "); Serial.print(Xmax); Serial.println(" mm."); Serial. print("Y 범위는 "); Serial.print(Ymin); Serial.print("에서 "); Serial.print(Ymax); Serial.println(" mm."); }/***** ***************** * 무효 루프() - 메인 루프 ***********************/void 루프() { 지연(100); 문자 라인[ LINE_BUFFER_LENGTH ]; 문자 c; int 라인 인덱스; bool lineIsComment, lineSemiColon; 라인 인덱스 =0; 라인세미콜론 =거짓; lineIsComment =거짓; while (1) { // 직렬 수신 - 대부분 Grbl에서, 세미콜론 지원 추가 while ( Serial.available()>0 ) { c =Serial.read(); if (( c =='\n') || (c =='\r') ) { // 줄 끝에 도달함 if ( lineIndex> 0 ) { // 줄이 완료되었습니다. 그럼 실행! 라인[ lineIndex ] ='\0'; // 문자열 종료 if (verbose) { Serial.print( "Received :"); Serial.println(줄); } processIncomingLine( 라인, 라인 인덱스 ); 라인 인덱스 =0; } else { // 비어 있거나 주석 행. 블록 건너뛰기. } lineIsComment =거짓; 라인세미콜론 =거짓; Serial.println("확인"); } else { if ( (lineIsComment) || (lineSemiColon) ) { // 모든 주석 문자를 버립니다. if ( c ==')' ) lineIsComment =false; // 주석 끝. 이력서 라인. } else { if ( c <=' ' ) { // 공백 및 제어 문자를 버립니다. } else if ( c =='/' ) { // 블록 삭제가 지원되지 않습니다. 문자를 무시합니다. } else if ( c =='(' ) { // 주석 플래그를 활성화하고 ')' 또는 EOL 때까지 모든 문자를 무시합니다. lineIsComment =참; } else if ( c ==';' ) { lineSemiColon =true; } else if ( lineIndex>=LINE_BUFFER_LENGTH-1 ) { Serial.println( "오류 - lineBuffer 오버플로" ); lineIsComment =거짓; 라인세미콜론 =거짓; } else if ( c>='a' &&c <='z' ) { // 대문자 소문자 line[ lineIndex++ ] =c-'a'+'A'; } else { 라인[ lineIndex++ ] =c; } } } }} 무효 processIncomingLine( char* line, int charNB ) { int currentIndex =0; 문자 버퍼[ 64 ]; // 64가 1개의 매개변수에 충분하기를 바랍니다. struct point newPos; newPos.x =0.0; newPos.y =0.0; // 해석이 필요함 // 이동을 위한 G1 // G4 P300(150ms 대기) // G1 X60 Y30 // G1 X30 Y50 // M300 S30(펜다운) // M300 S50(펜업) // ( // 다른 모든 명령을 버리십시오! break; case 'G':buffer[0] =line[ currentIndex++ ]; // /!\ Dirty - 2자리 명령에서만 작동 // buffer[1] =line[ currentIndex++ ]; // buffer[2] =' \0'; buffer[1] ='\0'; switch ( atoi( buffer ) ){ // G 명령 선택 case 0:// G00 &G01 - 이동 또는 빠른 이동. 여기도 마찬가지 case 1:// /! \ Dirty - X가 Y 앞에 있다고 가정합니다. char* indexX =strchr( line+currentIndex, 'X' ); // 문자열에서 X/Y 위치를 가져옵니다(있는 경우) char* indexY =strchr( line+currentIndex, 'Y ' ); if ( indexY <=0 ) { newPos.x =atof( indexX + 1); newPos.y =액추에이터Pos.y; } else if ( indexX <=0 ) { newPos.y =atof( indexY + 1); newPos.x =액츄에이터Pos.x; } else { newPos.y =atof(인덱스Y + 1); indexY ='\0'; newPos.x =atof( indexX + 1); } drawLine(newPos.x, newPos.y); // Serial.println("확인"); 액츄에이터Pos.x =newPos.x; 액츄에이터Pos.y =newPos.y; 부서지다; } 부서지다; case 'M':buffer[0] =line[ currentIndex++ ]; // /!\ Dirty - 3자리 명령에서만 작동합니다. buffer[1] =line[ currentIndex++ ]; 버퍼[2] =라인[ 현재 인덱스++ ]; 버퍼[3] ='\0'; switch ( atoi( buffer ) ){ case 300:{ char* indexS =strchr( line+currentIndex, 'S' ); float Spos =atof( indexS + 1); // Serial.println("확인"); if (Spos ==30) { penDown(); } if (Spos ==50) { penUp(); } 부서지다; } case 114:// M114 - 보고 위치 Serial.print( "절대 위치 :X =" ); Serial.print(actuatorPos.x); Serial.print( " - Y =" ); Serial.println(actuatorPos.y); 부서지다; 기본값:Serial.print( "명령이 인식되지 않음 :M"); Serial.println(버퍼); } } }}/******************************** * (x0;y0)에서 ( x1;y1). * https://www.marginallyclever.com/blog/2013/08/how-to-build-an-2-axis-arduino-cnc-gcode-interpreter/의 Bresenham 알고리즘 * int (x1;y1) :시작 좌표 * int (x2;y2) :끝 좌표 **********************************/void drawLine(float x1 , float y1) { if (verbose) { Serial.print("fx1, fy1:"); Serial.print(x1); Serial.print(","); Serial.print(y1); Serial.println(""); } // 명령을 제한 내로 가져옵니다. if (x1>=Xmax) { x1 =Xmax; } if (x1 <=Xmin) { x1 =Xmin; } if (y1>=Ymax) { y1 =Ymax; } if (y1 <=Ymin) { y1 =Ymin; } if (자세한 정보) { Serial.print("Xpos, Ypos:"); Serial.print(Xpos); Serial.print(","); Serial.print(Ypos); Serial.println(""); } if (자세한 정보) { Serial.print("x1, y1:"); Serial.print(x1); Serial.print(","); Serial.print(y1); Serial.println(""); } // 좌표를 단계로 변환 x1 =(int)(x1*StepsPerMillimeterX); y1 =(int)(y1*StepsPerMillimeterY); float x0 =Xpos; float y0 =Ypos; // 좌표의 변화를 알아봅시다. long dx =abs(x1-x0); 긴 dy =abs(y1-y0); 정수 sx =x0 dy) { for (i=0; i=dx) { over-=dx; myStepperY.onestep(sy,STEP); } 지연(StepDelay); } } else { for (i=0; i=dy) { over-=dy; myStepperX.onestep(sx,STEP); } 지연(StepDelay); } } if (상세) { Serial.print("dx, dy:"); Serial.print(dx); Serial.print(","); Serial.print(dy); Serial.println(""); } if (verbose) { Serial.print("(")로 이동; Serial.print(x0); Serial.print(","); Serial.print(y0); Serial.println(")"); } // 다음 줄이 제출되기 전 지연 delay(LineDelay); // 위치 업데이트 Xpos =x1; Ypos =y1;}// penvoid penUp() { penServo.write(penZUp); 지연(펜지연); Zpos=Zmax; 디지털 쓰기(15, 낮음); 디지털 쓰기(16, 높음); if (verbose) { Serial.println("펜 업!"); } }// penvoid penDown() { penServo.write(penZDown); 지연(펜지연); Zpos=Zmin; 디지털 쓰기(15, 높음); 디지털 쓰기(16, 낮음); if (verbose) { Serial.println("펜 아래로."); } }
    처리 코드자바
    이 코드를 Processing IDE에 업로드합니다.
    import java.awt.event.KeyEvent;import javax.swing.JOptionPane;import processing.serial.*;Serial port =null;// 운영 체제에 적합한 라인을 선택하고 수정합니다. / 대화형 포트를 사용하려면 null로 둡니다(프로그램에서 'p' 누르기)String portname =null;//String portname =Serial.list()[0]; // Mac OS X//문자열 포트 이름 ="/dev/ttyUSB0"; // Linux//문자열 포트 이름 ="COM6"; // Windowsboolean 스트리밍 =false;float speed =0.001;String[] gcode;int i =0;void openSerialPort(){ if (portname ==null) return; if (포트 !=null) port.stop(); 포트 =새 직렬(이, 포트 이름, 9600); port.bufferUntil('\n');}void selectSerialPort(){ String result =(String) JOptionPane.showInputDialog(frame, "아두이노 보드에 해당하는 직렬 포트를 선택하세요.", "직렬 포트 선택", JOptionPane. QUESTION_MESSAGE, null, Serial.list(), 0); if (결과 !=null) { 포트 이름 =결과; 오픈시리얼포트(); }} 무효 설정(){ 크기(500, 250); openSerialPort();}무승부 그리기(){ 배경(0); 채우기(255); 정수 y =24, dy =12; text("지침", 12, y); y +=다이; text("p:직렬 포트 선택", 12, y); y +=다이; text("1:조그당 0.001인치(1mil)로 속도 설정", 12, y); y +=다이; text("2:조그당 0.010인치(10mil)로 속도 설정", 12, y); y +=다이; text("3:조그당 속도를 0.100인치(100mil)로 설정합니다.", 12, y); y +=다이; text("화살표 키:x-y 평면에서 조그", 12, y); y +=다이; text("페이지 업 &페이지 다운:z축으로 조그", 12, y); y +=다이; text("$:grbl 설정 표시", 12, y); y+=다이; text("h:집에 가세요", 12, y); y +=다이; text("0:0 머신(현재 위치로 홈 설정)", 12, y); y +=다이; text("g:g 코드 파일 스트리밍", 12, y); y +=다이; text("x:스트리밍 g-코드 중지(즉시 적용되지 않음)", 12, y); y +=다이; y =높이 - dy; text("현재 조그 속도:" + 속도 + " 단계당 인치", 12, y); y -=다이; text("현재 직렬 포트:" + 포트 이름, 12, y); y -=dy;}무효 keyPressed(){ if (key =='1') 속도 =0.001; if (키 =='2') 속도 =0.01; if (키 =='3') 속도 =0.1; if (!streaming) { if (keyCode ==LEFT) port.write("G91\nG20\nG00 X-" + 속도 + " Y0.000 Z0.000\n"); if (keyCode ==RIGHT) port.write("G91\nG20\nG00 X" + 속도 + " Y0.000 Z0.000\n"); if (keyCode ==UP) port.write("G91\nG20\nG00 X0.000 Y" + 속도 + " Z0.000\n"); if (keyCode ==DOWN) port.write("G91\nG20\nG00 X0.000 Y-" + 속도 + " Z0.000\n"); if (keyCode ==KeyEvent.VK_PAGE_UP) port.write("G91\nG20\nG00 X0.000 Y0.000 Z" + 속도 + "\n"); if (keyCode ==KeyEvent.VK_PAGE_DOWN) port.write("G91\nG20\nG00 X0.000 Y0.000 Z-" + 속도 + "\n"); if (키 =='h') port.write("G90\nG20\nG00 X0.000 Y0.000 Z0.000\n"); if (키 =='v') port.write("$0=75\n$1=74\n$2=75\n"); //if (키 =='v') port.write("$0=100\n$1=74\n$2=75\n"); if (키 =='') port.write("$3=10\n"); if (키 =='e') port.write("$16=1\n"); if (키 =='d') port.write("$16=0\n"); if (키 =='0') openSerialPort(); if (키 =='p') selectSerialPort(); if (키 =='$') port.write("$$\n"); } if (!스트리밍 &&키 =='g') { gcode =null; 나는 =0; 파일 파일 =null; println("파일 불러오기..."); selectInput("처리할 파일을 선택하세요:", "fileSelected", 파일); } if (key =='x') 스트리밍 =false;}void fileSelected(파일 선택) { if (selection ==null) { println("창이 닫혔거나 사용자가 취소를 눌렀습니다."); } else { println("사용자 선택" + selection.getAbsolutePath()); gcode =loadStrings(selection.getAbsolutePath()); if (gcode ==null) 반환; 스트리밍 =사실; 개울(); }}void stream(){ if (!streaming) return; while (true) { if (i ==gcode.length) { 스트리밍 =false; 반품; } if (gcode[i].trim().length() ==0) i++; 그렇지 않으면 휴식; } println(g코드[i]); port.write(gcode[i] + '\n'); i++;}무효 serialEvent(시리얼 p){ 문자열 s =p.readStringUntil('\n'); println(s.trim()); if (s.trim().startsWith("ok")) 스트림(); if (s.trim().startsWith("오류")) 스트림(); // XXX:정말요?}

    회로도

    그림과 같이 모든 구성 요소를 연결하십시오

    제조공정

    1. 집에서 DIY 숙제 작성 기계 만들기
    2. Arduino를 사용하여 모니터 Ambilight 만들기
    3. Arduino Uno를 사용한 인간 감지 로봇 시스템
    4. Raspberry Motor Shield를 사용한 Android 제어 장난감
    5. 사용자 정의 가능한 펀치 키보드 버튼을 만드는 방법
    6. Arduino를 사용하여 지구의 질량을 측정하는 방법
    7. PHP를 사용하여 Arduino와 통신하는 웹사이트를 만드는 방법
    8. Arduino로 음악을 만드는 방법
    9. Arduino 기반 자동 문 열림을 만드는 방법
    10. Arduino 및 Processing IDE를 사용하여 나침반을 만드는 방법