For coding samples, please visit the following link to our Google Drive. If you don't have LabView on your computer, take a look at this alternative page with pictures of our code. A description of how it all works can be seen below.
We loved the idea of a portable printer right off the bat, but we were struggling to come up with ideas of how we could code it. We were pretty close to giving up and using a two-link arm to control it using inverse kinematics, but then we made an important realization. If we used a nested 'for' loop to sort through an array of pixels, it would do so in a precise order - all we had to do to get our printer to move to the proper pixel at the correct time was to move it across the paper the same way a nested 'for' loop sorts through an array - from top left to bottom right, going row by row. Once we realized we could do this, we decided the portable printer would be our final design.
The code essentially has three main VIs that make the whole project work, with several Sub VIs built into them for modularity. The first VI is the ‘Image Processing’ VI. This takes in a 1000 x 1000 pixel image (uploaded from a computer), crops it down to a 25 x 25 pixel image (using the ‘Pixellator’ Sub VI to find the average color value of 40 x 40 pixel squares and convert all pixels to that average color), and then converts all the pixels to one of four colors that we found to be the most present in an average human portrait (these colors can easily be changed on the block diagram of the ‘Second Difference in Color Value’ Sub VI). To do this, we used code similar to the solution for the first midterm problem, which takes in four color boxes, extracts their RGB values (in the ‘Second Difference in Color Value’ Sub VI), adds them up, and finds the minimum difference between the color of the pixel in question and those color boxes (in the ‘Difference in Color Value’ Sub VI). Once the Image Processing VI has been run, the user now has a 25 x 25 pixel image of four different colors that can be used to run the printer.
The second VI is the ‘Rotator Reset’ VI. This VI is run just to reset the printer to its starting position, so that it doesn’t jerk or spin at the beginning of its motion and throw itself off course. This VI simply sends duty cycles to the rotator motor to set it at the starting angle, and sends cycles to the three pen motors to set them at their raised position.
The final VI, and the one that actually runs the robot, is the ‘Printer Mover’ VI. This VI takes in the 25 x 25 array of color-converted pixel indexes from the Image Processor VI and results in the printer moving through the entire image and drawing the correct colored points. The logic the VI follows is detailed below:
And there you have it! That’s the outline of how we got our robot to ‘paint’ an image of a face! What we love about our code is that it’s extremely modular, and thus was easy to test and calibrate for our hardware implementation. Another great aspect is that it’s repeatable, and can draw any image you send it! (if the image isn’t 1000 x 1000 pixels, all you have to do is edit a few numbers in the Image Processing VI to turn it into the desired size image). In fact, given more time and resources with which to improve the hardware, we believe the code for our Rover Writer will allow us to reproduce any image back on paper with pristine accuracy!