1 Makeblock XY-Plotter Robot Kit V2.0 (No Electronics). This include all mechanical parts, two step motors (control position of pen), 1 servo motor (control pen up/down) and four touch sensors (detect the top, bottom, left and right border reach).
1 PHPoC blue (Provide web interface and control two step motors via PHPoC Motor Controller)
2 PHPoC Step Motor Controller (control to two step motors to move the pen )
How it works
When a finger touches to the drawing area in webpage, the XY coordinate of touching point is sent to PHPoC. After scaling the coordinate, PHPoC will move two step motors to locate the pen to that coordinate. During moving period, PHPoC continuously send trajectory of the pen to web app, the web app draw the trajectory on the canvas.
Wiring
Stack two step motor controllers on PHPoC
Connect to servo motor
Connect to limit switches.
This project use two motors and two step motor controllers;
One step motor and one step motor controller control left-right direction (X-axis). This step motor controller needs to connect to two limit switches attached on left and right side of XY-Plotter. Left-switch to SW#1, right-switch to SW#0
One step motor and one step motor controller control up-down direction (Y-axis). This step motor controller needs to connect to two limit switches attached on top and bottom side of XY-Plotter. Bottom-switch to SW#1, top-switch to SW#0
Note that: we only use SW#0 and SW#1. We don't use SW#2 and SW#3 as in image
Source code
Main task (task0.php):
Receiving the command from webpage and do task according to command.
CMD_MOVE: move pen to a position by controlling two step motor
CMD_PEN_UP: raise the pen by changing the angle of servo motor
CMD_PEN_DOWN: lower the pen by changing the angle of servo motor
Continuously read the current position of pen and send to webpage
Web interface (index.php)
Providing the user interface
Handling the user event and send command with coordinate to PHPoC
Receiving the trajectory from PHPoC and draw it on webpage
This is server side code which is running in infinite loop on PHPoC, This code receive command from a websocket client and control motor based on that command.
<?phpinclude_once"/lib/sd_340.php";include_once"/lib/sd_spc.php";include_once"/lib/sn_tcp_ws.php";define("PWM_PERIOD",20000);// (20ms)define("WIDTH_MIN",600);define("WIDTH_MAX",2450);define("SID_X",13);define("SID_Y",14);define("MAX_X",3421);define("MAX_Y",4296);define("TOUCH_OFFSET",0);define("PEN_UP",0);define("PEN_DOWN",1);define("CMD_PEN_UP",0);define("CMD_PEN_DOWN",1);define("CMD_MOVE",2);define("SPEED_X_COEF",20);define("SPEED_Y_COEF",20);define("SPEED_X_OFFSET",50);define("SPEED_Y_OFFSET",50);define("SPEED_X_MAX",5000);define("SPEED_Y_MAX",5000);define("ACCEL_X_COEF",1500);define("ACCEL_Y_COEF",1000);define("ACCEL_X_OFFSET",0);define("ACCEL_Y_OFFSET",0);define("ACCEL_X_MAX",20000);define("ACCEL_Y_MAX",20000);define("STATE_X_LOCK",1);define("STATE_X_RUN",2);define("STATE_Y_LOCK",4);define("STATE_Y_RUN",8);functionstep_cmd($sid,$cmd){$resp=spc_request($sid,4,$cmd);if($resp){$resp=explode(",",$resp);if((int)$resp[0]!=200){echo"step_cmd : '$cmd' request error ",$resp[0],"\r\n";returnfalse;}if(count($resp)>1)return$resp[1];elsereturn"";}elsereturnfalse;}functionspc_check_did($sid,$did){$resp=spc_request_csv($sid,0,"get did");if($resp===false){echo"spc_check_did: sid$sid - device not found\r\n";returnfalse;}if($resp[1]!="40012403"){echo"spc_check_did: unknown device ",$resp[2],"\r\n";returnfalse;}returntrue;}functionpen_up(){$angle=110;$width=WIDTH_MIN+(int)round((WIDTH_MAX-WIDTH_MIN)*$angle/180.0);if(($width>=WIDTH_MIN)&&($width<=WIDTH_MAX))ht_pwm_width(2,$width,PWM_PERIOD);}functionpen_down(){$angle=180;$width=WIDTH_MIN+(int)round((WIDTH_MAX-WIDTH_MIN)*$angle/180.0);if(($width>=WIDTH_MIN)&&($width<=WIDTH_MAX))ht_pwm_width(2,$width,PWM_PERIOD);}functionxy_goto($x,$y){if($x<TOUCH_OFFSET)$x=TOUCH_OFFSET;if($x>(MAX_X-TOUCH_OFFSET))$x=MAX_X-TOUCH_OFFSET;if($y<TOUCH_OFFSET)$y=TOUCH_OFFSET;if($y>(MAX_Y-TOUCH_OFFSET))$y=MAX_Y-TOUCH_OFFSET;$x0=(int)step_cmd(SID_X,"get pos");$y0=(int)step_cmd(SID_Y,"get pos");$delta_x=$x-$x0;$delta_y=$y-$y0;if($delta_x==0&&$delta_y==0)return;$speed_x=SPEED_X_COEF*abs($delta_x)+SPEED_X_OFFSET;$speed_y=SPEED_Y_COEF*abs($delta_y)+SPEED_Y_OFFSET;if($speed_x>SPEED_X_MAX)$speed_x=SPEED_X_MAX;if($speed_y>SPEED_Y_MAX)$speed_y=SPEED_Y_MAX;$accel_x=ACCEL_X_COEF*$speed_x+ACCEL_X_OFFSET;$accel_y=ACCEL_Y_COEF*$speed_y+ACCEL_Y_OFFSET;if($accel_x>ACCEL_X_MAX)$accel_x=ACCEL_X_MAX;if($accel_y>ACCEL_Y_MAX)$accel_y=ACCEL_Y_MAX;if($delta_x==0){step_cmd(SID_Y,"goto $y$speed_y$accel_y");}elseif($delta_y==0){step_cmd(SID_X,"goto $x$speed_x$accel_x");}else{step_cmd(SID_X,"goto $x$speed_x$accel_x");step_cmd(SID_Y,"goto $y$speed_y$accel_y");}}functionxy_state(){$ret_val=0;$x_state=(int)step_cmd(SID_X,"get state");$y_state=(int)step_cmd(SID_Y,"get state");if($x_state==1)// motor is locked$ret_val|=STATE_X_LOCK;elseif($x_state>1)// motor is running$ret_val|=STATE_X_RUN;if($y_state==1)// motor is locked$ret_val|=STATE_Y_LOCK;elseif($y_state>1)// motor is running$ret_val|=STATE_Y_RUN;return$ret_val;}functionxy_wait(){while(xy_state()&(STATE_X_RUN|STATE_Y_RUN))usleep(1);}functionxy_init(){$width=WIDTH_MIN+(int)round((WIDTH_MAX-WIDTH_MIN)*110/180.0);ht_pwm_setup(2,$width,PWM_PERIOD);pen_up();spc_reset();spc_sync_baud(460800);if(!spc_check_did(SID_X,"40012403"))return;if(!spc_check_did(SID_Y,"40012403"))return;step_cmd(SID_X,"set vref stop 3");step_cmd(SID_X,"set vref drive 14");step_cmd(SID_X,"set mode half");step_cmd(SID_X,"set rsnc 120 250");step_cmd(SID_Y,"set vref stop 3");step_cmd(SID_Y,"set vref drive 14");step_cmd(SID_Y,"set mode half");step_cmd(SID_Y,"set rsnc 120 250");// move pen to (0, 0)step_cmd(SID_X,"goto -sw1 1600 20000");step_cmd(SID_Y,"goto -sw1 1600 20000");xy_wait();step_cmd(SID_X,"reset");step_cmd(SID_Y,"reset");xy_goto(TOUCH_OFFSET,TOUCH_OFFSET);xy_wait();// uncomment this block for the first run and change the value in line 45 of index.php/* // check max steps step_cmd(SID_X, "goto +sw0 1600 20000"); step_cmd(SID_Y, "goto +sw0 1600 20000"); xy_wait(); // change this value in line 45 of index.php: var MAX_X = 3421, MAX_Y = 4296; echo "Max X:", step_cmd(SID_X, "get pos"), "\r\n"; echo "Max Y:", step_cmd(SID_Y, "get pos"), "\r\n"; */}functionsend_position($pen_state){$x=(int)step_cmd(SID_X,"get pos");$y=(int)step_cmd(SID_Y,"get pos");$wbuf="[$x, $y, $pen_state]";ws_write(0,$wbuf);}ws_setup(0,"xy_plotter","csv.phpoc");xy_init();$pre_x=0;$pre_y=0;$cur_x=0;$cur_y=0;$rbuf="";$pen_state=CMD_PEN_UP;$x_is_unlock=false;$y_is_unlock=false;while(1){if(ws_state(0)==TCP_CONNECTED){$rlen=ws_read_line(0,$rbuf);if($rlen){$data=explode(" ",$rbuf);$cmd=(int)$data[0];switch($cmd){caseCMD_PEN_DOWN:$x=(int)$data[1];$y=(int)$data[2];xy_goto($x,$y);xy_wait();pen_down();$pen_state=PEN_DOWN;send_position($pen_state);break;caseCMD_PEN_UP:pen_up();$pen_state=PEN_UP;send_position($pen_state);break;caseCMD_MOVE:$x=(int)$data[1];$y=(int)$data[2];xy_goto($x,$y);//xy_wait();break;}}}$cur_x=(int)step_cmd(SID_X,"get pos");$cur_y=(int)step_cmd(SID_Y,"get pos");if(abs($pre_x-$cur_x)>10||abs($pre_y-$cur_y)>10){$pre_x=$cur_x;$pre_y=$cur_y;send_position($pen_state);}$xy_state=xy_state();if(($xy_state&STATE_X_LOCK)&&($x_is_unlock==false)){step_cmd(SID_X,"unlock");$x_is_unlock=true;}elseif(($xy_state&STATE_X_RUN)){step_cmd(SID_X,"eio set 0 mode lock");step_cmd(SID_X,"eio set 1 mode lock");$x_is_unlock=false;}if(($xy_state&STATE_Y_LOCK)&&($y_is_unlock==false)){step_cmd(SID_Y,"unlock");$y_is_unlock=true;}elseif(($xy_state&STATE_Y_RUN)){step_cmd(SID_Y,"eio set 0 mode lock");step_cmd(SID_Y,"eio set 1 mode lock");$y_is_unlock=false;}}?>
Web interface (index.php)
HTML
This code is client side code. When receiving any request from a webclient (ex. Web browser), PHPoC will load index.php and run PHP script in side it, and then returns html and javascript to Web browser. Web browser will compile these two languages scripts. If this file contains a javascript-coded "websocket client", Web browser will acts as "websoket client" and connect to "websocket server"
Comments
Please log in or sign up to comment.