Introduction: Veilance

Veilance is an interactive wall decoration that senses the viewer’s touch and responds by morphing its form. Veilance can be played with a simple touch of a hand to one of the loops, an action which starts the upward and downward flows of the chains.

The project was conceived as a metaphor for one’s personal wall. In the post-election political climate where the regional, political, religious, ideological, and generational division of people had been highlighted, Manako wanted to explore ways to visualize the interaction in which one lifts an emotional barrier and connects with others. The capacitive sensor was chosen to represent this interaction through a physical touch, and ball chains were selected for the emotional barrier.

Step 1: Parts, Tools, Supplies

Here are the materials and tools to make this project.

Soldering iron & solder

Wire strippers

Ball chain

Arduino Uno

Adafruit Capacitive Sensor Shield

Alligator clips

Adafruit Motor Shield

12VDC Stepper Motor

1.5" wooden beam

Aluminum beam

Threaded rod

Screws, bolts, nuts, lock nuts

Eye screws or hooks

Hand drill and hand screw

Chop saw

Milling machine

Laser cutter

Acrylic sheet (1/4”)

    Step 2: Structure

    1. Use a hand drill and a milling machine on the aluminum beam to make 3 holes for the motor, 3 holes for screwing on to the wooden beam, and a channel for the larger gear.
    2. Cut the wooden beams in the desired lengths, and drill vertical holes for the threaded rods.
    3. Screw the aluminum onto the wooden beam.
    4. Insert the threaded rods in the wooden beams, and hold the beams with lock nuts. Screw in the eye screws on the top beam to hang from the ceiling.
    5. Design gears on geargenerator.com (it’s FREE!), download the SVG files, open them on Adobe Illustrator, and laser cut them.
    6. Bolt the motor and the gears in. Make sure to place a nut between the beam and the gear to hold it in place. After placing the gear, insert a spool and another gear. Hold them in place with a lock nut.

    Step 3: Code

    Use the capacitor shield code and motor shield code from Adafruit's library. And combine them.

    <p>#include <br>#include 
    #include "utility/Adafruit_MS_PWMServoDriver.h"
    #include "Adafruit_MPR121.h"</p><p>// Motor shield "Stepper Test"
    // Create the motor shield object with the default I2C address
    Adafruit_MotorShield AFMSBottom = Adafruit_MotorShield(); 
    // Or, create it with a different I2C address (say for stacking)
    Adafruit_MotorShield AFMSTop = Adafruit_MotorShield(0x61); </p><p>// Connect a stepper motor with 200 steps per revolution (1.8 degree)
    // to motor port #2 (M3 and M4)
    Adafruit_StepperMotor *myMotorOne = AFMSBottom.getStepper(200, 1);
    Adafruit_StepperMotor *myMotorTwo = AFMSBottom.getStepper(200, 2);
    Adafruit_StepperMotor *myMotorThree = AFMSTop.getStepper(200, 1);</p><p>// Capacitive shield "MPR121"
    // You can have up to 4 on one i2c bus but one is enough for testing!
    Adafruit_MPR121 cap = Adafruit_MPR121();</p><p>// Keeps track of the last pins touched
    // so we know when buttons are 'released'
    uint16_t lasttouched = 0;
    uint16_t currtouched = 0;
    uint16_t counterOne = 0;
    uint16_t counterTwo = 0;
    uint16_t counterThree = 0;
    //int CapZero = 6; // analog pin that capacitive touch sensor connected to </p><p>void setup() {
     // put your setup code here, to run once:</p><p>  Serial.begin(9600);
      Serial.println("Adafruit MPR121 Capacitive Touch sensor test"); </p><p>  //pinMode (CapZero, INPUT); // declare capacitive touch sensor's pin as an input? 
      
      // Default address is 0x5A, if tied to 3.3V its 0x5B
      // If tied to SDA its 0x5C and if SCL then 0x5D
      if (!cap.begin(0x5A)) {
        Serial.println("MPR121 not found, check wiring?");
        while (1);
      }
      Serial.println("MPR121 found!");</p><p>  Serial.println("Stepper test!");</p><p>  AFMSTop.begin();  // create with the default frequency 1.6KHz
      AFMSBottom.begin();
      //AFMS.begin(1000);  // OR with a different frequency, say 1KHz
      
      myMotorOne->setSpeed(80);  // 80 rpm
      myMotorTwo->setSpeed(80);  // 80 rpm
      myMotorThree->setSpeed(80);  // 80 rpm
    }</p><p>void loop() {
     // put your main code here, to run repeatedly:
     // Get the currently touched pads</p><p> //
      currtouched = cap.touched();
      //Serial.println(cap.touched());
      
      for (uint8_t i=0; i<12; i++) {
        // if it *is* touched and *wasnt* touched before, alert!
        // "uint" is all the crazy numbers that the sensor can detect. "i" is the pin for capacitive shield 
        //  _BV() is a macro that shifts 1 to left by the specified numnber
        if ((currtouched & _BV(i)) && !(lasttouched & _BV(i)) ) {
          if(i == 1){
            if(counterOne == 0){
              Serial.print(i); Serial.println(" touchedForward");
              //myMotorOne->step(2000, FORWARD, DOUBLE); 
            }
            if(counterOne == 1){
              Serial.print(i); Serial.println(" touchedBackward");
              //myMotorOne->step(2000, BACKWARD, DOUBLE); 
              counterOne = -1;
            }
            counterOne++;
          }
          if(i == 2){
            if(counterTwo == 0){
              Serial.print(i); Serial.println(" touchedForward");
              //myMotorTwo->step(2000, FORWARD, DOUBLE); 
            }
            if(counterTwo == 1){
              Serial.print(i); Serial.println(" touchedBackward");
              //myMotorTwo->step(2000, BACKWARD, DOUBLE); 
              counterTwo = -1;
            }
            counterTwo++;
          }
          if(i == 3){
                    if(counterThree == 0){
              Serial.print(i); Serial.println(" touchedForward");
              //myMotorThree->step(2000, FORWARD, DOUBLE); 
            }
            if(counterThree == 1){
              Serial.print(i); Serial.println(" touchedBackward");
              //myMotorThree->step(2000, BACKWARD, DOUBLE); 
              counterThree = -1;
            }
            counterThree++;
          
          }
        }</p><p>    // if it *was* touched and now *isnt*, alert!
        if (!(currtouched & _BV(i)) && (lasttouched & _BV(i)) ) {
          Serial.print(i); Serial.println(" released");
        }
      }</p><p>  // reset our state
      lasttouched = currtouched;</p><p> // comment out this line for detailed data from the sensor!
    return;
      
      // debugging info, what
      Serial.print("\t\t\t\t\t\t\t\t\t\t\t\t\t 0x"); Serial.println(cap.touched(), HEX);
      Serial.print("Filt: ");
      for (uint8_t i=0; i<12; i++) {
        Serial.print(cap.filteredData(i)); Serial.print("\t");
      }
      Serial.println();
      Serial.print("Base: ");
      for (uint8_t i=0; i<12; i++) {
        Serial.print(cap.baselineData(i)); Serial.print("\t");
      }
      Serial.println();
      
      // put a delay so it isn't overwhelming
      delay(100);</p><p>    }</p>

    Step 4: Circuit Construction

    1. Solder stacking pins on to the shield. Check out this Adafruit page for a step-by-step guide on how to stack motor shields.
    2. Connect wires from motors to the shield. Make sure to place the correct colors in the pins. For the stepper motor I used, the order was Pink, Orange, Red, Yellow, Blue.
    3. Stack the motor shields, and place the capacitive shield on top. Clip on the alligator clips to the capacitive shield.

    Step 5: Next Steps

    Unfortunately, this project failed in realizing what I intended for it to do because the ball chains which were supposed to act as capacitive sensors were too close to each other to detect the capacitance of each individual touch to the chain. Instead of detecting a human touch, the chains kept sensing each other, running on “auto-mode,” i.e. never stopping.

    Also, the stepper motor code that I used was a blocking code, and it did not activate a new chain to move until it completed the action of one chain.

    In a future iteration, I would like to use a different sensor (motion sensor, perhaps?) and rewrite the code so that each chain can be activated independently of each other. Please make suggestions for which sensor may work well with this system! Thank you!!