RoPlot -LOGI3
Click picture to see the movie.
This project is the answer to many e-mails we got around LOGI2. We got some inspiration from Benjamin ERWIN, Creative Projects with Lego Mindstorms, USA, 2001, ISBN 0-201-70895-7 . But building instructions for a performing plotter was not available. After some internet-surfing however we found a very interesting site called brickshelf, with a marvelous original Cartesian-plotter from LEGO No.8094. This design had of course to be transformed to fit for the RCX-purpose.
For instance we added the geared 9V motors instead of the ungeared to the main mobile body. Two LEGO rotation sensors were connected to the motor-power. The transmission was slightely changed by adding the Technic gear-box LEGO part. No. 9918. This part makes sure the worm-gear does not move back and forth every time the motor-direction is changed. Two touch-sensors were added for zero-point fixing. Because there was only one sensor-input left on the RCX, we used Mike Gasperi's input-expander. Finally an ungeared motor was fixed to the head in order to allow pen-up pen-down movements. Note that the 8094 building instructions may be followed up to No. 20. Here some details.
The RO-PLOT may be programmed by
LOGI3.
Download the program and the Delphi source files.
Here a screen-shot of the program.
Some advice for the use of LOGI3: Loop(2,5) |
Some explanations to the RCX-procedures which are incorporated into the LOGI3-body. First of all, the RO-PLOT has to recognize its zero-point. The main task orders the x-motor and the y-motor to bring the plotter-head back home. Then it waits for the t_event variable to be set to 1, e.a. both switches are pressed. The following task manages the input expander. You have to put attention to adjust the values if necessary. Check if the switches are well connected to the exander. The sensor-input must be set to No_TYPE. Use the on-board VIEW-button to check the values.
beginoftask(touch_event); setsensortype(sensor_2,no_type); //touch_sensor multiplexer used setvar(t_event,con,0); //clear t_event setvar(x_touch,con,0); //clear x_touch event setvar(y_touch,con,0); //clear y_touch event loop(con,forever); //wait until both events happened setvar(x_touch,con,0); setvar(y_touch,con,0); while_(senval,sensor_2,GT,con,990); //wait until touch_event endwhile(); wait(con,10); //wait transition time if_(senval,sensor_2,GT,con,860); //y_touch pressed setvar(x_touch,con,0); setvar(y_touch,con,1); else_(); if_(senval,sensor_2,GT,con,825); //only x_touch pressed setvar(x_touch,con,1); setvar(y_touch,con,0); else_(); setvar(x_touch,con,1); //both pressed setvar(y_touch,con,1); endif(); endif(); setvar(t_temp,var_iable,x_touch); //store temporary because of operation mulvar(t_temp,var_iable,y_touch); setvar(t_event,var_iable,t_temp); endloop(); endoftask(); |
The motion of a Cartesian plotter is very interesting. If both motors move the head positively, the plotter draws a 45° line. If only one motor is powered, either a 0° (180°) line or a 90° (270°) are drawn.
Quadrant | x-motor | y-motor |
I | + | + |
II | - | + |
III | - | - |
IV | + | - |
To draw lines at any angle, the head-position must be devided in 4 quadrants. At case 1 the y-motor moves quicker than the x-motor. At case 2 the inverse is true. To handle, the program first checks the quadrant, then the case. The tangens of the angle j always represents the speed-ratio of the motors. To make things simple, we used a trick to power the motors precisely without timing the motor through a wait or timer command, nor calculating the tangens of angles.
it
is possible to choose small integer values a and b, so that :
So, during the whole line-drawing period P = n . (a + b) , x-motor turns for the time n . a, and y-motor for the time n . b. We have:
For example: j = 21° --> a good approximation for LEGO-purpose is: a=3, b=8
//motor-control *********************************************** beginoftask(motor_x_control); loop(con,forever); if_(var_iable,phi,eq,con,0); if_(var_iable,case_,eq,con,2); on_(x_motor); endif(); else_(); if_(var_iable,phi,eq,con,45); on_(x_motor); else_(); loop(var_iable,motor_on); // is a in the explanation-text on_(x_motor); endloop(); loop(var_iable,motor_off); //is b in the explanation-text off(x_motor); endloop(); endif(); endif(); endloop(); endoftask(); |
The whole drawing period is determined by the readings of the rotation-sensors. The plotter is ready if the forward-argument :
argument = L = | ![]() |
Note that this RoPlot could easily work without rotation-sensor. The programs would only have to count the dx and dy values as n . a, resp. n . b . In this case you would not need the input expander. The precision could be improved, if another program-variant were able to cound a and b from the rotation-sensor readings, although the actual design is well calibrated.