M360 触发限位角度设置
M361 原点偏移设置 (中心转轴相对机械臂原点的坐标位置)
G5 舵机角度控制 (G5 A角度 B角度 C角度)
G4 延迟 (G4 S时间(秒))
G28 回归所有轴(home)
G92 当前坐标设定(G92 X坐标 Y坐标 Z坐标把当前机械手的位置设置成想要的坐标)
G95 切换绝对/相对坐标(相对坐标就是控制单独一轴的角度,切换后一定要home)
M17 启动步进电机
M84 解锁步进电机
M92 设置步进电机脉冲数 (M92 X? Y? Z? E?)下同) M105 获取温度
M112 紧急停止
M114 获取当前坐标和角度
M119 获取限位开关状态
M201 设置最大打印速度
M202 设置最大移动速度
M203 设置电机最大速度
M204 设置默认加速度
M500 保存设置到EEPROM(使用G代码设置如果没有保存到EEPROM,下次连接机械手的时候不再有效)
M501 读取EEPROM中的配置
M502 恢复出厂设置
M503 读取出厂设置
1.连接
2.M502恢复出厂设置
3.G28 home,检查是否正常。
4.G95 切换到角度模式,再G28,检查角度模式是否正常。
5.G28,home M360 X0 Y180 先假定当前角度
6.分别移动XY轴到0角度,读取当前坐标(X轴0角度为主臂与平台平行,Y轴0角度为副臂与主臂成直线)
7.X轴限位角度即负的坐标值,Y即180减坐标值,用M360 X? Y?设置限位角度, M500保存
8.使用G95可以把机械手的任意位置设置成想要的坐标。G28,移动机械手到想要设置坐标的位置,G95 X0 Y0 Z0就把现在的位置设置成原点,如果再输入M500,此位置就永久地保存为原点,否则只对此次连接有效。
1.导入图片后生成G代码
2.用记事本把所有的M03替换成G1 Z0 M05换成 G1 Z2-5(提笔高度)
3.由于不同的笔高度不一,因此需使用G95设置Z轴的原点。home后下降Z轴,直至刚好接触纸面,G95 Z0,如果一直使用这把笔可以用M500保存,这样下次就不用设置了。
1.用cad绘制单线字体,由于不支持圆弧插补,所以要导出为图元文件(.sat)
2.导入到inkspace,使用插件里面的laser...(激光雕刻插件),页面中可以更改保存路径
3.找到保存的.nc文件,后续步骤同上。
1.设置合适位置为XYZ轴原点
2.用切片软件生成G代码,并用记事本把前面十几行中的G28去掉
001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020 021 022 023 024 025 026 027 028 029 030 031 032 033 034 035 036 037 038 039 040 041 042 043 044 045 046 047 048 049 050 051 052 053 054 055 056 057 058 059 060 061 062 063 064 065 066 067 068 069 070 071 072 073 074 075 076 077 078 079 080 081 082 083 084 085 086 087 088 089 090 091 092 093 094 095 096 097 098 099 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 | import processing.serial.*; float x,y,z =100,a=90; //储存xyz坐标,以及第四轴角度 float unit =10; //移动单位 boolean teach = false ; //示教模式 float e; //滚轮事件变量 String[] step = new String[1000]; String[] output; int i=0; Serial Port; void setup() { frameRate(15); String portName = Serial.list()[0]; Port = new Serial( this , portName, 115200); //串口 size(1000,650); //屏幕尺寸 smooth(); background(#FFFFFF); //背景色 fill(#DBDBDB); //提示栏颜色 noStroke(); rect(0,0,1000,50); fill(#FFFFFF); textSize(30); text( "MOVE_UNIT" ,10,35); //UI界面 //text("save",815,35); } void draw() { noStroke(); /*---------------------键盘事件------------------*/ if (keyPressed== true ) { if (key== 'h' ||key== 'H' ) //H键回零所有轴 { Port.write( "G28\r\n" ); x=y=0; z=100; } if (key== 'x' ||key== 'X' ) //X键回零X轴 { Port.write( "G28 X0\r\n" ); x=0; } if (key== 'y' ||key== 'Y' ) //Y键回零Y轴 { Port.write( "G28 Y0\r\n" ); y=0; } if (key== 'z' ||key== 'Z' ) //Z键回零Z轴 { Port.write( "G28 Z0\r\n" ); z=150; } if ((key== 'a' ||key== 'A' )&&a<=180+unit) //Z键回零Z轴 { a=a+unit; Port.write( "G5 A" +a+ "\r\n" ); if (teach== true ) { step[i]= "G5 A" +a; i++; } } if ((key== 'd' ||key== 'D' )&&a>=0+unit) //Z键回零Z轴 { a=a-unit; Port.write( "G5 A" +a+ "\r\n" ); if (teach== true ) { step[i]= "G5 A" +a; i++; } } if (key== 'w' ||key== 'W' ) //Z键回零Z轴 { Port.write( "G5 B60\r\n" ); if (teach== true ) { step[i]= "G5 B60" ; i++; } } if (key== 's' ||key== 'S' ) //Z键回零Z轴 { Port.write( "G5 B150\r\n" ); if (teach== true ) { step[i]= "G5 B150" ; i++; } } if (key==CODED) //编码键 { if (keyCode==ALT) //清空屏幕 { fill(#FFFFFF); noStroke(); rect(0,50,1000,600); } } } /*-----------------------------------------------*/ /*---------------------鼠标事件------------------*/ if (mouseButton==LEFT&&mouseY>50) //鼠标左键 { stroke(0,102); strokeWeight(3); line(mouseX,mouseY,pmouseX,pmouseY); x=mouseX/4; y=(height-mouseY)/4; if (teach== true ) //示教模式 { Port.write( "G1 X" +x+ 'Y' +y+ "F12000\r\n" ); //拖动鼠标移动并绘制 step[i]= "G1 X" +x+ 'Y' +y+ "F1200" ; i++; } else { Port.write( "G1 X" +x+ 'Y' +y+ "F12000\r\n" ); //拖动鼠标移动并绘制 } } /*-----------------------------------------------*/ if ((mouseX>900)&&(mouseX<1000)&&(mouseY>0)&&(mouseY<50)) //save { fill(#DBDBDB); rect(900,0,100,50); fill(#FFFFFF); text( "save" ,915,35); } } void mouseWheel(MouseEvent event) //滚轮事件,移动Z轴 { e = event.getCount(); if (e==1&&z>0+unit) z=z-unit; else if (e==-1&&z<150+unit) z=z+unit; Port.write( "G1 Z" +z+ "F1200\r\n" ); if (teach== true ) //示教模式 { step[i]= "G1 Z" +z+ "F1200" ; i++; } //println(z); } /*---------------------UI------------------*/ void mouseClicked() //UI按钮 { noStroke(); if ((mouseX>200)&&(mouseX<260)&&(mouseY>0)&&(mouseY<50)) { fill(#DBDBDB); rect(250,0,55,50); rect(300,0,55,50); rect(350,0,55,50); fill(#FFFFFF); text( "10" ,257,35); text( "1" ,315,35); text( "0.1" ,357,35); rect(200,0,55,50); fill(#DBDBDB); text( "20" ,207,35); unit=20; // 控制单位20 } if ((mouseX>250)&&(mouseX<310)&&(mouseY>0)&&(mouseY<50)) { fill(#DBDBDB); rect(200,0,55,50); rect(300,0,55,50); rect(350,0,55,50); fill(#FFFFFF); text( "20" ,207,35); text( "1" ,315,35); text( "0.1" ,357,35); rect(250,0,55,50); fill(#DBDBDB); text( "10" ,257,35); unit=10; //10 } if ((mouseX>300)&&(mouseX<360)&&(mouseY>0)&&(mouseY<50)) { fill(#DBDBDB); rect(200,0,55,50); rect(250,0,55,50); rect(350,0,55,50); fill(#FFFFFF); text( "20" ,207,35); text( "10" ,257,35); text( "0.1" ,357,35); rect(300,0,55,50); fill(#DBDBDB); text( "1" ,315,35); unit=1; //1 } if ((mouseX>350)&&(mouseX<410)&&(mouseY>0)&&(mouseY<50)) { fill(#DBDBDB); rect(200,0,55,50); rect(250,0,55,50); rect(300,0,55,50); fill(#FFFFFF); text( "20" ,207,35); text( "10" ,257,35); text( "1" ,315,35); rect(350,0,55,50); fill(#DBDBDB); text( "0.1" ,357,35); unit=0.1; //0.1 } if ((mouseX>800)&&(mouseX<900)&&(mouseY>0)&&(mouseY<50)) //示教模式切换 { teach=!teach; } if ((mouseX>900)&&(mouseX<1000)&&(mouseY>0)&&(mouseY<50)) //save { fill(#FFFFFF); rect(900,0,100,50); fill(#DBDBDB); text( "save" ,915,35); output = new String[i]; for ( int j=0;j<i;j++) { output[j]=step[j]; } saveStrings( "teach.gcode" ,output); } if (teach== false ) //绘制示教模式按钮 { fill(#DBDBDB); rect(800,0,100,50); fill(#FFFFFF); text( "teach" ,815,35); } else { fill(#FFFFFF); rect(800,0,100,50); fill(#DBDBDB); text( "teach" ,815,35); } /*-----------------------------------------------*/ //println(teach); println(a); } |
001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020 021 022 023 024 025 026 027 028 029 030 031 032 033 034 035 036 037 038 039 040 041 042 043 044 045 046 047 048 049 050 051 052 053 054 055 056 057 058 059 060 061 062 063 064 065 066 067 068 069 070 071 072 073 074 075 076 077 078 079 080 081 082 083 084 085 086 087 088 089 090 091 092 093 094 095 096 097 098 099 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 | import processing.serial.*; import processing.video.*; Serial Port; Capture cam; float [][] kernel ={{0.111,0.111,0.111}, {0.111,0.111,0.111}, {0.111,0.111,0.111} }; //卷积核 //中间像素的灰度值等于周围像素的红色分量减去蓝绿色分量的平均值 //从而使没有红色特征的像素灰度值变为零 //相当于滤镜的效果,修改卷积核的参数,可以达到不一样的效果 int sub_x=0,sub_y=0; //物体中心的像素坐标 float pre_x=0,pre_y=0; //前一帧物体中心的像素坐标 float tar_x=80,tar_y=80; //目标坐标,机械手的坐标 boolean event= false ; //坐标计算事件 int c=0; void setup() //初始化 { String portName = Serial.list()[0]; Port = new Serial( this , portName, 115200); //连接串口 size(640,480); //屏幕大小 String[] cameras = Capture.list(); printArray(cameras); //打印可使用的相机 cam = new Capture( this , cameras[0]); cam.start(); //启动相机 frameRate(30); //帧率 Port.write( "G5 B90\r\n" ); Port.write( "G28\r\n" ); Port.write( "G1 X80 Y80 Z40\r\n" ); Port.write( "G5 B50\r\n" ); //移动到初始位置 delay(6000); //延迟,避免摄像头刚打开时的波动 } void draw() //循环 { if (cam.available() == true ) { cam.read(); image(cam, 0, 0, width, height); cam.loadPixels(); int sum_x=0,sum_y=0; //所有红色像素坐标的和 int m=1; //红色像素的个数 for ( int y=1;y<cam.height-1;y++) //排除第一行、最后一行、第一列、最后一列像素(这几个地方周围的像素不完整) { for ( int x=1;x<cam.width-1;x++) //经过所有像素 { float sum=0; //最终的灰度值 for ( int ky =-1;ky<=1;ky++) { for ( int kx=-1;kx<=1;kx++) //周围9个像素(包括自身) { int pos =(y+ky)*cam.width+(x+kx); //将xy坐标换算成pixels[]数组中的位置,pixels[]数组是可以直接调用的储存像素的一维数组(从左到右从上到下) int R = (cam.pixels[pos]>> 16) & 0xFF; //取颜色分量,与red()功能相似 int G = (cam.pixels[pos] >> 8) & 0xFF; int B = cam.pixels[pos] & 0xFF; float val=0; switch (c) //顺序抓取红蓝绿色块 { case 0: val =R-1.5*B-1.5*G; break ; case 1: val =B-1.5*R-1.5*G; break ; case 2: val =G-0.5*B-1*R; break ; } //1.5为比例系数,改大可以让红色更突出 sum +=kernel[ky+1][kx+1]*val; //计算灰度值 } } if (sum>0) //新的灰度值非零 { sum_x=sum_x+x; sum_y=sum_y+y; //累加坐标 m=m+1; //计数 } } } pre_x=sub_x; pre_y=sub_y; //前一帧的物体中心 sub_x=sum_x/m; sub_y=sum_y/m; //取平均,计算出物体中心像素坐标 cam.updatePixels(); fill(#FF0000); } line(sub_x,0,sub_x,480); line(0,sub_y,640,sub_y); //作物体中心的两条交叉线 if ( abs (sub_x-pre_x)<5&& abs (sub_y-pre_y)<5&&sub_x>5&&sub_y>5) //判断是否在移动(波动小于5个像素即为静止),是否存在物体(没有物体时默认为0,为避免波动,这里设置成5) { if (event== true ) //如果物体存在,机械手静止,且事件被触发,则进行计算 { tar_x=tar_x-(0.0625*sub_x-20); tar_y=tar_y-(15-0.0625*sub_y); //把像素坐标转化成绝对坐标,根据实际比例 event= false ; //关闭计算事件,即只执行一次计算 Port.write( "G1 X" +tar_x+ " Y" +tar_y+ "\r\n" ); //移动到目标位置 delay(100); //延迟,减小波动 } } else //如果机械手在移动,触发计算事件,但不执行计算,为机械手静止时计算做准备 event= true ; /*由于机械手的通讯以及动作上有延迟,速度远赶不上摄像头对图像识别的速度, 所以仅让机械臂在静止时进行一次计算*/ if (sub_x<5&&sub_y<5) { if (c<3) c=c+1; else c=0; } float mx=tar_x; float my=tar_y+32; //手抓中心对的坐标,摄像头和手抓有32的y偏移量 if (sub_x>315&&sub_x<325&&sub_y>235&&sub_y<245) //当物体在画面中心时(+-5个像素) { //执行以下动作 Port.write( "G1 X" +mx+ 'Y' +my+ "Z12 F1200\r\n" ); delay(1500); //充分延时 for ( int i=50;i<=150;i+=5) { Port.write( "G5 B" +i+ "\r\n" ); delay(50); } delay(500); Port.write( "G1 Z30\r\n" ); delay(1000); switch (c) //顺序摆放红蓝绿色块 { case 0: Port.write( "G1 X150 Y120\r\n" ); break ; case 1: Port.write( "G1 X150 Y100\r\n" ); break ; case 2: Port.write( "G1 X150 Y80\r\n" ); break ; } delay(1500); Port.write( "G1 Z10\r\n" ); delay(500); for ( int j=150;j>=50;j-=5) { Port.write( "G5 B" +j+ "\r\n" ); delay(50); } delay(500); Port.write( "G1 X80 Y80 Z40\r\n" ); delay(1500); if (c<3) c=c+1; else c=0; } println(tar_x); println(tar_y); } |
联系客服