CONCEPT:
Masks Off is a project that investigates the proxy face or, in other words, the face upon the face. The masks that are constructed as a result of this investigation juxtapose the abstracted face of the wearer’s partner on top of that of the wearer and the partner’s environment upon the wearer. The mask takes data from the partner’s environment in order to activate the masks. In the case of Elise’s mask, the position of Anishwar’s head while wearing his mask sends data to Elise’s mask in order to activate the pneumatic and speaker of the Bluefruit. Anishwar’s mask is activated by the level of darkness in Elise’s environment which causes the pneumatic in his mask to inflate and the speaker on his Bluefruit to play tones.
The team decided to explore the concept of the proxy face and the juxtaposition of distant people and environments on another because they were interested in analyzing the significance and implications of the remote digital communication that has become popularized during the Covid-19 pandemic through the symbol of the mask which has taken on a new prominence and significance during this time period.
EXECUTION:
We decided to overlap tulle over fabric since the embroidery was much easier on the tulle. Elise stitched the designs into the tulle to create the faces and attached the tulle to the fabric underneath. For Anishwar, we used the lace ‘sheet’ that Elise sewed together. For Elise, we used the stretchy metallic fabric. The masks were pretty jarring in imagery and interesting at the same time.
PROCESS:
Our process begin with experimenting on what we wanted the masks to incorporate and how might they look. Anishwar drew sketches of ideas and the one below was what we ultimately went with. The idea was to create a proxy face on top of our own and involve lights and noise when reacting to the other’s environment. Our final tweaked those processes.
The idea for the masks came from the runway, looking at the work of John Galliano. You can see the influence in our work as we used tulle and bold colors as well as the black thread detailing in Anishwar’s mask. Elise’s mask also used embroidery detailing and tulle but in a red thread.
After gathering the basic idea, we chose to look at the working parts. We experimented with pneumatics before we got the motor pump. Once we got the motor, we also made sure to add holes to that the inflatables could relax between pumping cycles. The final inflatables were smaller round bladders.
We also experimented with the design aspects, looking at embroidery and the fabric that we could use. When making the final mask, the embroidery foot on the sewing machine was eating up the tulle and making holes, so we chose to do hand-stitching with embroidery floss when making the faces.
After we figured out our working parts, we combined our efforts to create the final masks. We had a lot of trouble getting the code to work over the bridge and that took a lot of our time. The final masks also used a double layer of fabric, one with embroidery and the other to give more structure and color. The pneumatics were placed under the masks, either with elastic around the head or attached to the inside of the mask.
ANISHWAR’S CODE:
# cpb_pump_control.py # Demonstrate control of an air pump based on a DC motor driven via a MOSFET # transistor driver circuit *or* a DRV8833 motor driver in a single-ended mode. # # 1. The driver PWM input connects to A2 # 2. The battery ground line connects to GND # Related documentation: # https://circuitpython.readthedocs.io/en/latest/shared-bindings/pwmio/index.html#module-pwmio # https://circuitpython.readthedocs.io/projects/motor/en/latest/api.html#module-adafruit_motor.servo # ---------------------------------------------------------------- # Import standard Python modules. import time, math, sys # Import the board-specific input/output library. from adafruit_circuitplayground import cp # Import the low-level hardware libraries. import board import pwmio import supervisor # ---------------------------------------------------------------- # Initialize hardware. # Create a PWMOut object on pad A2 to generate control signals. pwm = pwmio.PWMOut(board.A3, duty_cycle=0, frequency=20000) # ---------------------------------------------------------------- # Initialize global variables for the main loop. phase_angle = 0.0 cycle_duration = 12 # seconds per cycle phase_rate = 2*math.pi / cycle_duration # radians/second next_pwm_update = time.monotonic_ns() next_status_update = time.monotonic_ns() toneCheck = True nextSound = time.monotonic_ns() pitch = 329 pitchTwo = 293 nextPrint = time.monotonic_ns() tokens = [] motionDuration = 0 soundDuration = 0 soundDurationTwo = 0 lastNow = time.monotonic_ns() # ---------------------------------------------------------------- # Enter the main event loop. while True: # Read the current integer clock. #print (pitch) now = time.monotonic_ns() soundNow = time.monotonic_ns() elapsedTime = now - lastNow lastNow = now x,y,z = cp.acceleration if now >= nextPrint: print(pwm.duty_cycle) nextPrint = now + 2000000000 if x > 1 or y < 0: print("start") if x >= 1.25: print("go") elif y < 0: print("onward") if supervisor.runtime.serial_bytes_available: line = sys.stdin.readline() tokens = line.split() if line.startswith("begi"): motionDuration = 7050000000 if line.startswith("now"): soundDuration = 500000000 if line.startswith("geronimo"): soundDurationTwo = 500000000 # If the time has arrived to update the servo command signal: if soundDuration > soundDurationTwo: soundDurationTwo = 0 elif soundDurationTwo > soundDuration: soundDuration = 0 if motionDuration > 0: if now >= next_pwm_update: next_pwm_update += 20000000 # 20 msec in nanoseconds (50 Hz update) pwm_level = 0.5 + 0.5 * math.sin(phase_angle) # convert a unit-range (0 to 1) pwm_level to a 16-bit integer representing a fraction new_duty_cycle = min(max(int(pwm_level * 2**16), 0), 2**16-1) # If the new value is less than a reasonable minimum, clamp to zero. # The pump motor will stall if the PWM fraction is too low; this turns # it off instead. if new_duty_cycle < 48000: pwm.duty_cycle = 0 else: pwm.duty_cycle = new_duty_cycle phase_angle = (phase_angle + phase_rate * 0.01) % (.5 * math.pi) # If either button is pressed, override the generated servo signal and run the motor. if cp.button_a or cp.button_b: pwm.duty_cycle = 2**16-1 # If the time has arrived to display the status: if now >= next_status_update: next_status_update += 500000000 # 0.5 sec in nanoseconds (2 Hz update) motionDuration -= elapsedTime else: pwm.duty_cycle = 0 if soundDuration > 0: if soundNow >= nextSound: if pitch == 329: pitch = 493 cp.stop_tone() cp.start_tone(pitch) nextSound = soundNow + 500000000 elif pitch == 493: pitch = 329 cp.stop_tone() cp.start_tone(pitch) nextSound = soundNow + 500000000 soundDuration -= elapsedTime elif soundDurationTwo > 0: if soundNow >= nextSound: if pitchTwo == 293: pitchTwo = 466 cp.stop_tone() cp.start_tone(pitchTwo) nextSound = soundNow + 500000000 elif pitchTwo == 466: pitchTwo = 293 cp.stop_tone() cp.start_tone(pitchTwo) nextSound = soundNow + 500000000 soundDurationTwo -= elapsedTime else: cp.stop_tone()
ELISE’S CODE:
# https://circuitpython.readthedocs.io/en/latest/shared-bindings/pwmio/index.html#module-pwmio # https://circuitpython.readthedocs.io/projects/motor/en/latest/api.html#module-adafruit_motor.servo import time, math, sys from adafruit_circuitplayground import cp import board import pwmio import supervisor pwm = pwmio.PWMOut(board.A3, duty_cycle=0, frequency=20000) phase_angle = 0.0 cycle_duration = 12 # seconds per cycle phase_rate = 2*math.pi / cycle_duration # radians/second next_pwm_update = time.monotonic_ns() next_status_update = time.monotonic_ns() toneCheck = True nextSound = time.monotonic_ns() pitch = 329 pitchTwo = 293 nextPrint = time.monotonic_ns() motionDuration = 0 soundDuration = 0 soundDurationTwo = 0 lastnow = time.monotonic_ns() while True: # Read the current integer clock. #print(cp.light) now = time.monotonic_ns() soundNow = time.monotonic_ns() elapsed_time = now - lastnow lastnow = now if now >= nextPrint: nextPrint = now + 2000000000 if cp.light < 100: print("begi") if cp.light < 81 and cp.light >= 21: print("now") elif cp.light < 20: print("geronimo") else: print("bright") if supervisor.runtime.serial_bytes_available: line = sys.stdin.readline() #print(line) #tokens = line.split() if line.startswith("start"): motionDuration = 9000000000 if line.startswith("go"): soundDuration = 5000000000 if line.startswith("onward"): soundDurationTwo = 5000000000 # If the time has arrived to update the servo command signal: if motionDuration > 0: if now >= next_pwm_update: next_pwm_update += 20000000 # 20 msec in nanoseconds (50 Hz update) pwm_level = 0.5 + 0.5 * math.sin(phase_angle) # convert a unit-range (0 to 1) pwm_level to a 16-bit integer representing a fraction new_duty_cycle = min(max(int(pwm_level * 2**16), 0), 2**16-1) # If the new value is less than a reasonable minimum, clamp to zero. # The pump motor will stall if the PWM fraction is too low; this turns # it off instead. if new_duty_cycle < 48000: pwm.duty_cycle = 0 else: pwm.duty_cycle = new_duty_cycle phase_angle = (phase_angle + phase_rate * 0.020) % (1 * math.pi) # If either button is pressed, override the generated servo signal and run the motor. if cp.button_a or cp.button_b: pwm.duty_cycle = 2**16-1 # If the time has arrived to display the status: if now >= next_status_update: next_status_update += 500000000 # 0.5 sec in nanoseconds (2 Hz update) #print(pwm.duty_cycle) motionDuration -= elapsed_time else: pwm.duty_cycle = 0 cp.stop_tone() if soundDuration > soundDurationTwo: soundDurationTwo = 0 elif soundDurationTwo > soundDuration: soundDuration = 0 if soundDuration > 0 and soundDurationTwo == 0: if soundNow >= nextSound: if pitch == 329: pitch = 493 cp.stop_tone() cp.start_tone(pitch) nextSound = soundNow + 500000000 elif pitch == 493: pitch = 329 cp.stop_tone() cp.start_tone(pitch) nextSound = soundNow + 500000000 soundDuration -= elapsed_time elif soundDurationTwo > 0 and soundDuration == 0: if soundNow >= nextSound: if pitchTwo == 293: pitchTwo = 466 cp.stop_tone() cp.start_tone(pitchTwo) nextSound = soundNow + 500000000 elif pitchTwo == 466: pitchTwo = 293 cp.stop_tone() cp.start_tone(pitchTwo) nextSound = soundNow + 500000000 soundDurationTwo -= elapsed_time else: cp.stop_tone()
REFLECTION:
If there was more time, the team would have liked to make more masks and potentially create an installation with multiple of these masks being animated and producing sound together. It would have been interesting to explore this current iteration of the project in different contexts. The primary location for testing the final version of this project was the College of Fine Arts building; however, it would be interesting to see how the masks would be affected if used outside or in vastly more distant locations.
Leave a Reply
You must be logged in to post a comment.