ECE 4180 Final Project

Field Programmable Water Array (FPWA)

Introduction

This notebook details the design and implementation of a programmable water curtain. The idea was inspired by a Cirque du Soleil show that implemented a waterfall onstage as shown in the video below. Our design uses an mbed microcontroller and an array of solenoids to create artistic effects in water flow. The user is able to choose the pattern of water flow.


Components

Our design uses the following parts:

  • mbed Microcontroller (LPC1768)
  • Uxcell a14092600ux0438 Open Frame Actuator Linear Mini Push Pull Solenoid
  • I2C Capacitive Touchpad
  • 3-D printed water reservoir and plugs

3-D printed water reservoir.
/media/uploads/azhang84/reservoir_KL0COgC.jpg

Design

Water flow out of the water reservoir is controlled by plugs that allow water to flow in desired patterns. The plugs are attached to solenoids that pull the plugs away from their resting position to allow the release of water. The mbed sends control signals to the MOSFETS that drive the solenoids.

The capacitive touchpad allows users to determine the desired patter of water flow. Touchpad keys 9-12 select pre-dfined bit patterns while keys 1-8 correspond to individual solenoids that can be used to implement any desired pattern.

Flow diagram of design with all components. /media/uploads/azhang84/final_project_diagram.png

3-D printed reservoir with openings sealed by 3-D printed plugs and fitted solenoids.
/media/uploads/azhang84/reservoir_filled.jpg
/media/uploads/azhang84/solenoids.jpg

Wiring

mbedComponentPin
p9Touch KeypadSDA
p10Touch KeypadSCL
p26Touch KeypadIRQ
VoutTouch KeypadVcc
p13 - p20MOSFETJP2-Control
PowerMOSFETSolenoid
gndJP2-gnd
5VJP2-RAW
JP1-1Solenoid
JP1-2Solenoid

Entire circuit setup.
/media/uploads/azhang84/circuit.jpg

Code

main.cpp

#include <vector>
#include "mbed.h"
#include "mpr121.h"

// Create the interrupt receiver object on pin 26
InterruptIn interrupt(p26);
I2C i2c(p9, p10);
BusOut solenoids(p13,p14,p15,p16,p17,p18,p19,p20);
Mpr121 mpr121(&i2c, Mpr121::ADD_VSS);
 volatile int value = 0;
float waittime = 1.0;

 // Key hit/release interrupt routine

void fallInterrupt()
{
    value = mpr121.read(0x00);
    value += mpr121.read(0x01)<<8;
}

// Function for Bernoulli distribution to control water flow pattern
vector<bool> f(double p, int n){
    vector<bool> my_vector;
    for(int i = 0; i<n; ++i){            
        my_vector.push_back((rand() %100 < 100*p));
    }    
    return my_vector;
}

int main()

{

    // setting up the interrupt
    interrupt.mode(PullUp);
    wait(.01);
    interrupt.fall(&fallInterrupt);

     while (1) { // individual solenoid control
        solenoids[7]= value & 0x01;
        solenoids[6]=(value>>1) & 0x01;
        solenoids[5]=(value>>2) & 0x01;
        solenoids[4]=(value>>3) & 0x01;
        solenoids[3]=(value>>4) & 0x01;
        solenoids[2]=(value>>5) & 0x01;
        solenoids[1]=(value>>6) & 0x01;
        solenoids[0]=(value>>7) & 0x01; 

        if ((value>>8) & 0x01) {

            // pattern 1
            solenoids[0] = 1;
            wait(waittime);
            solenoids[1] = 1;
            wait(waittime);
            solenoids[2] = 1;
            wait(waittime);
            solenoids[3] = 1;
            wait(waittime);
            solenoids[4] = 1;
            wait(waittime);
            solenoids[5] = 1;
            wait(waittime);
            solenoids[6] = 1;
            wait(waittime);
            solenoids[7] = 1;
            wait(waittime);

            solenoids[7] = 0;
            wait(waittime);
            solenoids[6] = 0;
            wait(waittime);
            solenoids[5] = 0;
            wait(waittime);
            solenoids[4] = 0;
            wait(waittime);
            solenoids[3] = 0;
            wait(waittime);
            solenoids[2] = 0;
            wait(waittime);
            solenoids[1] = 0;
            wait(waittime);
            solenoids[0] = 0;
            wait(waittime);

            // end of pattern 1
        }

        if ((value>>9) & 0x01) {

            // pattern 2
            solenoids[0] = 1;
            solenoids[7] = 1;
            wait(waittime);
            solenoids[1] = 1;
            solenoids[6] = 1;
            wait(waittime);
            solenoids[2] = 1;
            solenoids[5] = 1;
            wait(waittime);

            solenoids[3] = 1;
            solenoids[4] = 1;
            wait(waittime);
            solenoids[0] = 0;
            solenoids[7] = 0;
            wait(waittime);
            solenoids[1] = 0;
            solenoids[6] = 0;
            wait(waittime);
            solenoids[2] = 0;
            solenoids[5] = 0;
            wait(waittime);
            solenoids[3] = 0;
            solenoids[4] = 0;
            wait(waittime);

            // end of pattern 2

        }

        if ((value>>10) & 0x01) {

            // pattern 3
            solenoids[0] = 1;
            solenoids[1] = 1;
            solenoids[2] = 1;
            solenoids[3] = 1;
            solenoids[4] = 1;
            solenoids[5] = 1;
            solenoids[6] = 1;
            solenoids[7] = 1;
            wait(waittime);

            solenoids[0] = 0;
            wait(waittime);
            solenoids[7] = 0;
            wait(waittime);
            solenoids[1] = 0;
            wait(waittime);
            solenoids[6] = 0;
            wait(waittime);
            solenoids[2] = 0;
            wait(waittime);
            solenoids[5] = 0;
            wait(waittime);
            solenoids[3] = 0;
            wait(waittime);
            solenoids[4] = 0;
            wait(waittime);

            // end of pattern 3

        }

         if ((value>>11) & 0x01) {

            // pattern 4

            solenoids[0] = 1;
            wait(waittime);
            solenoids[0] = 0;
            solenoids[1] = 1;
            wait(waittime);
            solenoids[1] = 0;
            solenoids[2] = 1;
            wait(waittime);
            solenoids[2] = 0;
            solenoids[3] = 1;
            wait(waittime);
            solenoids[3] = 0;
            solenoids[4] = 1;
            wait(waittime);
            solenoids[4] = 0;
            solenoids[5] = 1;
            wait(waittime);
            solenoids[5] = 0;
            solenoids[6] = 1;
            wait(waittime);
            solenoids[6] = 0;
            solenoids[7] = 1;
            wait(waittime);
            solenoids[7] = 0;

            // end of pattern 4
        }
    }
}

 

Video

Demonstration of water curtain working with capacitive touch-pad inputs and pre-programmed pattern.

Results

In this project, we demonstrated mbed's capability to interface between hardware inputs and outputs. The inputs to the program are used to control the output water pattern.

We encountered challenges in managing water flow out of the reservoir without leaking. We tried several designs in configuring the solenoid with the plug to stop water flow as seen below. The final design uses rubber-tipped plugs held in place by rubber bands to minimize the leaking. Additionally, it was challenging to ensure that the water flowing out did not interact with any of the electronic components. We took extra caution to ensure that water did not harm any of the electronic devices. /media/uploads/azhang84/designs.jpg

Future work to build on this current design includes stopping all water leakage and adding additional user features. For example, playing music in-sync to the water pattern and implementing water patterns by parsing text files with ASCII characters representing the desired pattern are the next features we would like to implement.


Please log in to post comments.