Pump-Casso is a color creation device that samples pixels from a camera input and replicates the color in focus into a dye. The camera captures an image and provides a color preview via RGB LEDs. Once the color selection is confirmed by the user, Pump-Casso determines the proper ratio of cyan, magenta, yellow, and black (CMYK) pigments in order to recreate that color in real life. Pigment-dyed water is pumped from four reservoirs into a central container. The container is then gently mixed to produce a true-to-life color.


The purpose of this device is to try to produce a paint color by sampling real-world colors. Primarily with artists and graphic designers in mind, Pump-Casso will allow the user to find the perfect color blend to recreate the desired color without having to mix paints together by hand through trial-and-error. Pump-Casso takes the guesswork out of mixing colors so that designers can spend more time doing what they love: designing!


Following our design methodology from the milestone, we decided to go with a top-down approach for our design. Starting with a block diagram, we progressively integrated downward to achieve our final design. Shown below is a picture of our final design setup as well as a schematic for the design.


The heart of our device is the Arduino Uno running custom firmware. There are four ADC channels in use (channels 0:3 on the Uno) of which each water level sensor is hooked up to one channel. The RGB sensor is wired directly to the Uno’s SCL and SDA pins in the PD bank of IO pins; the RGB sensor development board has onboard pullup resistors. The button is wired to pin 9 and is polled on each loop of the code. Pins 2, 4, 7, and 8 are wired to the gates of 4 FETs which switch on the pumps and are triggered one at a time (we actually had 3 NMOS and 1 PMOS on hand which is what our final implementation used). The RGB LED was connected to the timer channels 0A, 1A, and 2B.

There are two primary modes of operation for Pump-Casso: capture and creation modes. In capture mode, the device is polling the RGB sensor for data and receiving interrupts from the ADC when water level sensor readings are available. Once it gets a reading from an ADC channel, it will increment to wait for the next pin and loop around the 4 channels (i.e. read 0, read 1, read 2, read 3, read 0, read 1, … , etc.). As it gets new readings from the RGB sensor, it also updates the RGB preview by changing the OCR values in each of the timers. Each of the PWM channels were configured for phase-correct PWM where the TOP value is 0xFF. Prescalers on the timers were adjusted accordingly so that each of the channels operate at the same frequency. This mode loops indefinitely until the user presses a button, whose state is also polled on each loop.

In creation mode, Pump-Casso takes in the latest RGB sensor value and does a simple conversion from RGB to CMYK[1]. Once a CMYK value is determined, the software initiates each pump in order so that no two pumps are running simultaneously. The CMYK values represent the relative time that each pump is running for. For example, a ‘C’ value of 35 is interpreted as the pump being turned on for 35% of one second. Our software uses a “scalar” to increase the amount of dye produced at the end due to how slow the pumps ran. After finishing the creation of a dye, the device returns back to capture mode where the cycle repeats.

Components Used

  • 4x water pumps to control primary dye dispensary
  • 1x RGB sensor to provide input color data
  • 1x momentary pushbutton to signal MCU to begin generating dye
  • 1x RGB LED to give the user feedback as to what color they can expect to be printed
  • 4x water level sensors to detect if the system is low on any colors
  • 4x canisters to hold dyes
  • Silicone tubing to route dyes to mixing bowl
  • 1x canister to hold dye mixture


Our final project was overall similar to our initial design. The largest difference was the use of an RGB sensor in place of the camera module. The camera module proved to be too poorly documented and even after configuration the color values were constantly being adjusted by the camera’s corrective features. We switched to an RGB sensor and the result was much better. We were thankfully able to reuse all the I2C code from the Camera for the RGB Sensor. We also decided to remove the plan for a turntable to mix the resulting liquid after we implemented everything else due to time constraints and the lack of suitable parts. We forgot to order a suitable, low-speed DC motor for this feature and the ones we had on hand were not suitable for our application as they rotated too quickly.

Additionally, the design for the pumps diverged from our original design. Our original plan was to conserve PWM channels by using a single PWM output entering a 1-to-4 demultiplexer circuit, allowing us to route the PWM channel to one of four pumps using two GPIO pins. This was to be constructed from the AND gates and inverters on the breadboard. Once we plugged in the pumps to their primary voltage rail (+12V), we quickly found that the flow rate for the pumps were slow enough to the point that PWM was unnecessary. The datasheet for the parts indicated that the maximum flow rate was 100mL per minute, which is relatively slow for our application. The plan to use PWM to modulate the pumps was scrapped once we realized that there would be no need to slow the pumps down further.

Beyond those two changes, the project’s goals and results are in line with what we envisioned. Due to the dyes used, the colors were a bit lighter than expected. We also realized that the use of the black dye in the printing process is used primarily for correcting the combination of the Cyan, Magenta, and Yellow inks creating more of a muddy green than a pure black. By removing the black component from the colors generated, we were able to get much closer to the expected colors, although a bit lighter. There is some additional consideration for transferring the CMYK principles from paper ink to water dyes.

Final Thoughts

For the project as a whole, we learned that our approach of starting at a high-level to create the idea and then building from the bottom-up worked very effectively. We started out this project with a block diagram laying out all of our functional blocks and the different interconnects that we imagined that we’d be using (e.g. GPIO, I2C, ADC, etc.). From here, we were able to easily determine what our resource limitations were on the Arduino Uno for planning purposes. The integration of all components went relatively smoothly and presented minimal roadblocks to implementation. We started by writing code to get the proper functionality for each of the sensors working as we wanted them to, then continued stitching everything together and testing as we went along. In the end the system actually did what we wanted it to do! Placing objects on the RGB sensor and seeing the pumps output the correct colors was very exciting. The coordination between all the sensors and the pumps was well executed. Seeing our final product work as well as it did was incredibly rewarding and allowed us to showcase what we’d learned in the class. This experience gave us more insight into the practical applications of embedded systems; resources are constrained, datasheets must be thoroughly read, and much planning needs to be done to build an efficient system.

Though our final approach differed from our initial design, the final product still functioned in a similar fashion. Firstly, the camera was changed to be an RGB sensor. This substitution was made because the camera module was not behaving as expected and there was no simple way to verify the image data. The design would have been salvaged by having a way to save image data and export from the MCU to either a display or to an SD card for viewing on a computer. Due to the fact that the camera is a very visual sensor, it is hard to test and verify without an image. The pumps used were the same ones as in our design, but the speed was far slower than expected. Because of this, we did not need to use a PWM signal to control the pumps. This would have been avoided if we shopped around for more pumps or better understood the characteristics of the pump. However, in the end this does not modify the final result of the system. If we could go back in time, we would have spent more time researching the sensors, especially the camera sensor. It may have been better to get a more featured-rich camera module with an LCD display simply for the testing advantage.

As with every project, ours was not without some roadblocks along the way. The largest issue we faced was properly communicating with the I2C interface. The RGB sensor would reply as expected but sending an ACK when concluding a read would cause the entire I2C bus to fail on the next start condition. The source of this was never found, but a solution was to simply never ACK a read and send the stop condition to cause the sensor to conclude its transmission. This resulted in no errors from the microcontroller side, so the solution was used. There are a few future modifications for the project that we would make, starting with testing the system with proper CMYK inks. The resulting dye mixture for our test cases would come out similar to the color on the RGB sensor, however there was definitely room for improvement. Implementing this would require a more powerful pump and access to enough dye to make several test runs. Next, we would also like to add a feature that lets the user specify how much dye (in mL) to disperse for a given run. The amount of dye dispersed was statically defined in our source code and would always produce a similar amount of dye. Lastly, we would clean up the design as a whole by creating an enclosure to house all of the electronics, hold all of the dye canisters, and mount the pumps to the enclosure.

We had a lot of fun creating Pump-Casso and learned a lot about the ATMega328p in the process!

Built With

  • atmega328p
  • c
Share this project: