Responsive Altar

Concept

For Project 2, I decided to create a responsive altar that invites people walking by to come to share their feelings. There are three color options that each correlate to a different emotional state: red = desire, yellow = joy, blue = grief. It uses a distance sensor to recognize when a person is present. The close the person is the more candles light. They are arranged in 4 tiers that are triggered at different distance ranges. The distance also determines what appears on a p5 sketch. Once the person is 30 inches from the sensor all the lights remain on and the p5 sketch invites them to respond to one of the three emotion prompts. Once the person writes their response they submit it through a slot in the altar. This slot houses an RGB sensor that is meant to trigger a change in the sketch based on the color of the note. In this iteration, I did not have the RGB sensor fully set up. It was able to read the color and provide the R, G, and B values, but I was not able to figure out the parameters to consistently distinguish between the three colors.

Prototypes

Construction

Demo

In class demo of altar with sensors and P5 sketc

Code

Arduino Code

/*
  Candle Controller, flickering LEDs
  Used to Read MaxSonar MB1010
  Written for Arduino Nano
  Reading Pin3 output
  Started 11/03/21
*/

const int anPin = 0;
long anVolt, mm, inches;

void setup() {
  Serial.begin(9600);
  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
}

void loop() {
  read_sensor();
  approach();
  delay(100);

}

void read_sensor() {
  anVolt = analogRead(anPin);
  mm = anVolt * 5; //Takes bit count and converts it to mm
  inches = mm / 25.4; //Takes mm and converts it to inches
  delay(1);
}

void approach() {
  if (inches <= 30 ) {
    tier4();
  } else if (inches >= 30 && inches <= 54) {
    tier3();
  } else if (inches >= 54 && inches <= 96) {
    tier2();
  } else if (inches >= 96 && inches <= 120) { //10 feet
    tier1();
  } else {
    altarOff();
  }
}

void tier4() {
  Serial.print("tier4 on: ");
  Serial.println(inches);
  altarOn();
  Serial.write(inches);
  delay(1);
}

void tier3() {
  Serial.print("tier3 on: ");
  Serial.println(inches);
  digitalWrite(5, LOW); //bottom
  digitalWrite(4, HIGH);
  digitalWrite(3, HIGH);
  digitalWrite(2, HIGH); //top
  Serial.write(inches);
  delay(1);
}

void tier2() {
  Serial.print("tier2 on: ");
  Serial.println(inches);
  digitalWrite(5, LOW); //bottom
  digitalWrite(4, LOW);
  digitalWrite(3, HIGH);
  digitalWrite(2, HIGH); //top
  Serial.write(inches);
  delay(1);
}

void tier1() {
  Serial.print("tier1 on: ");
  Serial.println(inches);
  digitalWrite(5, LOW); //bottom
  digitalWrite(4, LOW);
  digitalWrite(3, LOW);
  digitalWrite(2, HIGH); //top
  Serial.write(inches);
  delay(1);
}

void altarOff() {
  Serial.print("altar off: ");
  Serial.println(inches);
  digitalWrite(2, LOW); //bottom
  digitalWrite(3, LOW);
  digitalWrite(4, LOW);
  digitalWrite(5, LOW); //top
  Serial.write(inches);
  delay(1);
}

void altarOn() {
  digitalWrite(2, HIGH); //bottom
  digitalWrite(3, HIGH);
  digitalWrite(4, HIGH);
  digitalWrite(5, HIGH); //top
}


// written based on code from: https://www.maxbotix.com/Arduino-Ultrasonic-Sensors-085/

p5.js Code

let serial;
let portName = '/dev/cu.usbmodem1421';
let distanceData;
let colorData;

let myFont;
let W, H, txtW, txtH;

function preload() {
  myFont = loadFont("TheNeue-Black.otf");
}

function setup() {
  serial = new p5.SerialPort();       // make a new instance of the serialport library
  serial.on('connected', serverConnected); // callback for connecting to the server
  serial.on('open', portOpen);        // callback for the port opening
  serial.on('data', serialEvent);     // callback for when new data arrives
  serial.on('error', serialError);    // callback for errors
  serial.on('close', portClose);      // callback for the port closing
 
  serial.list();                      // list the serial ports
  serial.open(portName);              // open a serial port
  
  createCanvas(windowWidth,windowHeight);
  rectMode(CENTER);
  textAlign(CENTER,TOP);
  W = width;
  H = height;
  txtW = width/2;
  txtH = height/2;
}

function draw() {
  
  if (distanceData <= 30 ) {
    instructions();
  } else if (distanceData >= 30 && distanceData <= 54) {
    question();
  } else if (distanceData >= 54 && distanceData <= 96) {
    hello();
  } else if (distanceData >= 96 && distanceData <= 120) { //10 feet
    screen();
  } else {
    screen();
  }
  
  emotion();
  
    //if (colorData == 1)
  //grief();
  //joy();
  //desire();
}

function emotion(){
  if (mouseX <= windowWidth/4 && mouseY > windowHeight-windowHeight/8){
    joy();
  } else if (mouseX >= windowWidth-windowWidth/4 && mouseY > windowHeight-windowHeight/8){
    desire();
  } else if (mouseX <= windowWidth/2 && mouseY > windowHeight-windowHeight/8){
    grief();
  }
}

function screen(){
  background(0);
}
  
function hello(){
  background(0);
  fill(204,229,255);
  textFont(myFont);
  textSize(W/10);
  text("Hello.", txtW, txtH+50, W, H);
}
  
function question(){
  background(0);
  fill(204,229,255);
  textFont(myFont);
  textSize(W/10);
  text("Hello.", txtW, txtH+50, W, H);
  fill(255,198,81);
    textSize(W/15);
  text("Would you like to leave an offering?", txtW, txtH+175, W, H);
}
  
  
  function instructions(){
  background(0);
  fill(204,229,255);
  textFont(myFont);
  textSize(W/10);
  text("Hello.", txtW, txtH+50, W, H);
  fill(255,198,81);
  textSize(W/15);
  text("Would you like to leave an offering?", txtW, txtH+175, W, H);
  fill(204,255,153);
  textSize(W/20);
  text("Choose one of the three. Write a message. Leave it with me.", txtW, txtH+400, W, H)
fill("yellow");
    text("joy", txtW-200, txtH+550, W, H);
    fill("blue");
    text("grief", txtW, txtH+550, W, H);
    fill("red");
    text("desire", txtW+200, txtH+550, W, H);
}

function grief(){
  background("blue");
  fill(0,0,0);
  textFont(myFont);
  textSize(W/10);
  text("Thank You for Your Sharing", txtW, txtH+25, W, height);
  fill(240,240,240);
  textFont('Futura');
  textSize(W/16);
  text("In this altar all feelings are cherished.", txtW, txtH+275, W, height); 
  text("Let this offering be a release from some of the aches your grief brings.", txtW, txtH+400, W, height);
}


function joy(){
  background("yellow");
  fill(255,128,0);
  textFont(myFont);
  textSize(W/10);
  text("Thank You for Your Sharing", txtW, txtH+25, W, height);

  fill(153,76,0);
  textFont('Futura');
  textSize(W/16);
  text("In this altar all feelings are cherished.", txtW, txtH+275, W, height); 
  text("Let this be a chance for you to feel the tangible comfort of your joy.", txtW, txtH+400, W, height);
}

function desire(){
  background("red");
  fill(255);
  textFont(myFont);
  textSize(W/10);
  text("Thank You for Your Sharing", txtW, txtH+25, W, height);
  fill(255,102,102);
  textFont('Futura');
  textSize(W/16);
  text("In this altar all feelings are cherished.", txtW, txtH+275, W, height); 
  text("Let this be a nonjudgemental acknowledgement of the desires you hold.", txtW, txtH+400, W, height);
}

  
  
  
function serverConnected() {
  console.log('connected to server.');
}
 
function portOpen() {
  console.log('the serial port opened.')
}
 
function serialEvent() {
  distanceData = Number(serial.read());
  //colorData = Number(serial.read());
}
 
function serialError(err) {
  console.log('Something went wrong with the serial port. ' + err);
}
 
function portClose() {
  console.log('The serial port closed.');
}

Sources:

Previous
Previous

Labs: Week 10

Next
Next

AR Animation