如何使用废旧 DVD 驱动器 L293D
制作迷你 CNC 2D 绘图仪
组件和用品
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 |
应用和在线服务
| ||||
| ||||
|
关于这个项目
如图排列两个废DVD驱动器
1.下载 Arduino IDE
2.下载处理IDE
3.打开Arduino IDE并加载从下载的代码 这里 .
4.打开Processing IDE并加载从下载的代码 这里 .
打开废弃的 DVD 驱动器并移除内部移动托盘。这个带有步进机构的托盘将作为我们的 X 轴和 Y 轴。浏览所附图片以了解如何组装您的机器。在空的 DVD 驱动器盒上打孔,借助螺母螺栓将 X 轴和 Y 轴安装到相应的 DVD 盒上。
现在将它们相互垂直放置。
G代码
要制作与此 CNC 机器兼容的 g 代码文件,您必须使用 Inkscape。
Inkscape 是一款专业品质的矢量图形软件,可在 Windows、Mac OS X 和 Linux 上运行。全世界的设计专业人士和爱好者都使用它来创建各种各样的图形,例如插图、图标、徽标、图表、地图和 Web 图形。 Inkscape 使用 W3C 开放标准 SVG(可缩放矢量图形)作为其原生格式,并且是免费的开源软件。从这里下载并安装 Inkscape。
(重要 :下载 0.48.5 版本) 现在您需要安装一个附加组件,可以将图像导出为 g 代码文件。可以在此处找到此附加组件以及安装说明。
请按照 YouTube 上的视频了解如何创建 G 代码文件。
- 将 gctrl 文件上传到处理 IDE,然后在处理窗口中单击“播放”按钮。
- 首先按“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
感谢您的关注!访问此链接以获取完整说明。
视频看机器直播:
代码
- Arduino CNC 代码
- 处理代码
Arduino CNC 代码Arduino
将此代码上传到 Arduino#include#include #define LINE_BUFFER_LENGTH 512char STEP =MICROSTEP;// 上下伺服位置 const int penZUp =95;const int penZDown =83; // PWM 引脚上的伺服 10const int penServoPin =10;// 应该适用于 DVD 步进器,但在这里不太重要const int stepsPerRevolution =48; // 创建伺服对象来控制伺服伺服 penServo; // 使用此 Arduino 引脚为 L293D H-bridgeAF_Stepper myStepperY(stepsPerRevolution,1); 初始化 X 轴和 Y 轴的步进器; AF_Stepper myStepperX(stepsPerRevolution,2); /* 结构,全局变量 */struct point { float x;浮动 y;浮动 z; };// plotheadstruct点actuatorPos的当前位置;//绘图设置,应该是OKfloat StepInc =1;int StepDelay =0;int LineDelay =0;int penDelay =50;//电机步进1毫米。//使用测试草图走 100 步。测量线的长度。 // 计算每毫米的步数。在此处输入。float StepsPerMillimeterX =100.0;float StepsPerMillimeterY =100.0;// 绘制机器人限制,单位为毫米// 可以开始。如果校准得当,可以达到 50 毫米。浮动 Xmin =0;浮动 Xmax =40;浮动 Ymin =0;浮动 Ymax =40;浮动 Zmin =0;浮动 Zmax =1;浮动 Xpos =Xmin;浮动 Ypos =Ymin;浮动 Zpos =Zmax; // 设置为 true 以获得调试输出。boolean verbose =false;// 需要解释 // G1 进行移动// G4 P300(等待 150 毫秒)// M300 S30(下笔)// M300 S50(上笔)/ / 丢弃任何带有 (// 丢弃任何其他命令!/********************** * void setup() - 初始化 ******* ****************/void setup() { // Setup Serial.begin(9600); penServo.attach(penServoPin); penServo.write(penZUp); delay(100); // 必要时减小 myStepperX.setSpeed(600); myStepperY.setSpeed(600); // 设置并移动到初始默认位置 // 待定 // 通知!!! Serial.println("Mini CNC Plotter alive and kicking! "); Serial.print("X range is from "); Serial.print(Xmin); Serial.print(" to "); Serial.print(Xmax); Serial.println(" mm."); Serial. print("Y 范围从"); Serial.print(Ymin); Serial.print(" to "); Serial.print(Ymax); Serial.println(" mm."); }/***** ***************** * void loop() - 主循环 ***********************/void循环(){延迟(100);字符线[LINE_BUFFER_LENGTH];字符 c; int lineIndex; bool lineIsComment, lineSemiColon;线索引 =0; lineSemiColon =false; lineIsComment =false; while (1) { // 串行接收 - 主要来自 Grbl,添加分号支持 while ( Serial.available()>0 ) { c =Serial.read(); if (( c =='\n') || (c =='\r') ) { // 到达行尾 if ( lineIndex> 0 ) { // 行完成。然后执行!行[行索引] ='\0'; // 终止字符串 if (verbose) { Serial.print( "Received :"); Serial.println(行); } processIncomingLine( line, lineIndex );线索引 =0; } else { // 空行或注释行。跳过块。 } lineIsComment =false; lineSemiColon =false; Serial.println("ok"); } else { if ( (lineIsComment) || (lineSemiColon) ) { // 丢弃所有注释字符 if ( c ==')' ) lineIsComment =false; // 评论结束。续行。 } else { if ( c <=' ' ) { // 丢弃空格和控制字符 } else if ( c =='/' ) { // 不支持块删除。忽略字符。 } else if ( c =='(' ) { // 启用注释标志并忽略所有字符,直到 ')' 或 EOL。 lineIsComment =true; } else if ( c ==';' ) { lineSemiColon =true; } else if ( lineIndex>=LINE_BUFFER_LENGTH-1 ) { Serial.println( "ERROR - lineBuffer overflow"); lineIsComment =false; lineSemiColon =false; } else if ( c>='a' &&c <='z' ) { // 大写小写 line[ lineIndex++ ] =c-'a'+'A'; } else { line[ lineIndex++ ] =c; } } } } }}void 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(等待 150 毫秒) // G1 X60 Y30 // G1 X30 Y50 // M300 S30(下笔)// M300 S50(上笔)// 丢弃任何带有( // 丢弃任何其他命令!while( currentIndex =Xmax) { x1 =Xmax; } if (x1 <=Xmin) { x1 =Xmin; } if (y1>=Ymax) { y1 =Ymax; } if (y1 <=Ymin) { y1 =Ymin; } if (verbose) { Serial.print("Xpos, Ypos:"); Serial.print(Xpos); Serial.print(","); Serial.print(Ypos); Serial.println(""); } if (verbose) { Serial.print("x1, y1:");串行打印(x1); Serial.print(","); Serial.print(y1); Serial.println(""); } // 将坐标转换为步长 x1 =(int)(x1*StepsPerMillimeterX); y1 =(int)(y1*StepsPerMillimeterY);浮动 x0 =Xpos;浮动 y0 =Ypos; // 让我们找出坐标的变化 long dx =abs(x1-x0);长 dy =abs(y1-y0); int 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 (verbose) { Serial.print("dx, dy:");串行打印(dx); Serial.print(","); Serial.print(dy); Serial.println(""); } if (verbose) { Serial.print("Going to ("); 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("Pen up!"); } }// 降低 penvoid penDown() { penServo.write(penZDown);延迟(笔延迟); Zpos=Zmin;数字写入(15,高);数字写入(16,低); if (verbose) { Serial.println("Pen down."); } }
处理代码Java
将此代码上传到 Processing IDEimport java.awt.event.KeyEvent;import javax.swing.JOptionPane;import processing.serial.*;Serial port =null;// 为您的操作系统选择并修改适当的行/ / 留空使用交互式端口(在程序中按'p')String portname =null;//String portname =Serial.list()[0]; // Mac OS X//String portname ="/dev/ttyUSB0"; // Linux//String portname ="COM6"; // Windowsboolean streaming =false;float speed =0.001;String[] gcode;int i =0;void openSerialPort(){ if (portname ==null) return; if (port !=null) port.stop();端口 =新串口(这个,端口名,9600); port.bufferUntil('\n');}void selectSerialPort(){ String result =(String) JOptionPane.showInputDialog(frame, "Select the serial port that对应你的Arduino board.", "Select serial port", JOptionPane. QUESTION_MESSAGE, null, Serial.list(), 0);如果(结果!=null){端口名=结果; openSerialPort(); }}无效设置(){大小(500,250); openSerialPort();}void draw(){ background(0);填充(255); int y =24, dy =12;文本(“指令”,12,y); y +=dy; text("p:选择串口", 12, y); y +=dy; text("1:设置速度为 0.001 英寸 (1 mil) per jog", 12, y); y +=dy; text("2:设置速度为 0.010 英寸 (10 mil) per jog", 12, y); y +=dy; text("3:设置速度为 0.100 英寸 (100 mil) per jog", 12, y); y +=dy; text("方向键:在 x-y 平面上慢跑", 12, y); y +=dy; text("向上翻页和向下翻页:在 z 轴上点动", 12, y); y +=dy; text("$:显示 grbl 设置", 12, y); y+=dy; text("h:回家", 12, y); y +=dy; text("0:零机(设为当前位置)", 12, y); y +=dy; text("g:流式传输 g 代码文件", 12, y); y +=dy; text("x:停止流式传输 g 代码(这不是立即的)", 12, y); y +=dy; y =高度 - dy; text("当前慢跑速度:" + 速度 + " 每步英寸", 12, y); y -=dy; text("当前串口:" + portname, 12, y); y -=dy;}void keyPressed(){ if (key =='1') speed =0.001; if (key =='2') 速度 =0.01; if (key =='3') 速度 =0.1; if (!streaming) { if (keyCode ==LEFT) port.write("G91\nG20\nG00 X-" + speed + " Y0.000 Z0.000\n"); if (keyCode ==RIGHT) port.write("G91\nG20\nG00 X" + speed + " Y0.000 Z0.000\n"); if (keyCode ==UP) port.write("G91\nG20\nG00 X0.000 Y" + speed + " Z0.000\n"); if (keyCode ==DOWN) port.write("G91\nG20\nG00 X0.000 Y-" + speed + " Z0.000\n"); if (keyCode ==KeyEvent.VK_PAGE_UP) port.write("G91\nG20\nG00 X0.000 Y0.000 Z" + speed + "\n"); if (keyCode ==KeyEvent.VK_PAGE_DOWN) port.write("G91\nG20\nG00 X0.000 Y0.000 Z-" + speed + "\n"); if (key =='h') port.write("G90\nG20\nG00 X0.000 Y0.000 Z0.000\n"); if (key =='v') port.write("$0=75\n$1=74\n$2=75\n"); //if (key =='v') port.write("$0=100\n$1=74\n$2=75\n"); if (key =='s') port.write("$3=10\n"); if (key =='e') port.write("$16=1\n"); if (key =='d') port.write("$16=0\n"); if (key =='0') openSerialPort(); if (key =='p') selectSerialPort(); if (key =='$') port.write("$$\n"); } if (!streaming &&key =='g') { gcode =null;我 =0;文件文件=空; println("正在加载文件..."); selectInput("选择要处理的文件:", "fileSelected", file); } if (key =='x') streaming =false;}void fileSelected(File selection) { if (selection ==null) { println("窗口被关闭或用户点击取消。"); } else { println("用户选择" + selection.getAbsolutePath()); gcode =loadStrings(selection.getAbsolutePath());如果(gcode ==null)返回;流媒体=真;溪流(); }}void stream(){ if (!streaming) return; while (true) { if (i ==gcode.length) { streaming =false;返回; } if (gcode[i].trim().length() ==0) i++;否则休息; } println(gcode[i]); port.write(gcode[i] + '\n'); i++;}void serialEvent(Serial p){ String s =p.readStringUntil('\n'); println(s.trim()); if (s.trim().startsWith("ok")) stream(); if (s.trim().startsWith("error")) stream(); // XXX:真的吗?}
示意图
如图所示连接所有组件制造工艺