Project in progress
Provocation 3: Urban Encounters

Provocation 3: Urban Encounters

Urban 5x5x5x5x15

  • 798 views
  • 0 comments
  • 2 respects

Components and supplies

A000066 iso both
Arduino UNO & Genuino UNO
×2
LCD screen 16x2
×1
Resistors
×1
Green Acrylic
×1
XBee series 1
×2
XBee adapter
×2
SoftPot Membrane Potentiometer
×1
Tin foil
×1
Photo-resistor
×1
Tens70
9V battery (generic)
×2
Hero ipad family 2015 2x
Apple iPad
×1
Stretchy Fabric
×1
Elastic
×1

About this project

Description

Urban Encounters is our imagination of the future of interactive surfaces within our 5x5x5 site. The crosswalk "island" we chose at the corner of Shattuck and Center in downtown Berkeley promotes an interesting combination of isolation, stuck-ness and loneliness. To bring out these themes into the physical world, we decided to modify existing objects to support traditionally web-only interactions. The two we chose are missed connections, which are the moments where you feel a connection to someone but cannot stop to acknowledge it, and casual encounters, which are the personal ads you often hear about posted on sites like Craigslist. By molding these interactions and inputs/outputs into the objects of the site, we hope to show how one day, anything will be able to be transformed into a computing interface.

Panoramic View

Site Research

Location
  • Median strip of crosswalk on Center Street across Shattuck Ave. 
  • East of Downtown Berkeley BART station
  • One block west of University of California campus
  • Surrounded by restaurants, stores, company buildings
People
  • An estimated one million pedestrians pass between BART plaza and University of California campus
  • Over 18,000 people pass through BART plaza daily
Beautification
  • Downtown Berkeley Association in coordination with City planted decorative native grasses on median strip
Visible Landmarks
  • BART station main entrance rotunda
  • BART station plaza
  • Art sculpture on median strip
Art Sculpture
  • "Earth Song" by Pho Shu Want, native of China and Berkeley resident
  • Installed on January 2003
  • Deep red, slender, painted steel sculpture resembling tuning fork
  • Approximately 42 feet high with 14 inch wide base
  • Steel bell suspended around 3 feet above ground to stimulate interaction from passerby
  • Designed to tune to the oscillating frequency of the Earth, a low frequency outside of audible human range
  • Project of Berkeley Civics Arts Program
Renovation
  • Berkeley has received over $2 million to transform BART plaza and station
  • Rotunda landmark will be redesigned to look more transparent
  • BART plaza to be redesigned to invite more activity with dining area and seating
  • Construction scheduled to start in spring 2015

Renovation Concept

Plan and Section

Surface for tiled printout

Measured Metric: WiFi Signals

1. AT&T Wi-Fi

2. KIC_AP

3. Berkeleyjuiceappeal

4. DowntownFreeWiFi

5. d0710

6. 2WIRE631

7. 42 Guest

8. GUEST_CADENCE

9. ONETEAM

10. Sonic.net-938

11. TeaLeaf

12. ATT336

13. citysolve

14. Pollen IO

15. ATT432

16. ATT520

17. FiatLux

18. GMOGUEST

19. ATT184

19. jasonandmike

20. SNGWLANA01

WiFi Signal Strength

Video

https://drive.google.com/a/berkeley.edu/file/d/0B6l9o_Lvo__HaHNNb1JqWmlFMlE/edit

Instructions

Step 1: iPad App / Missed Connections

Create an iOS project and replace the default files with their corresponding files uploaded to Hackster. Add the skpsmtpmessage library from https://github.com/jetseven/skpsmtpmessage) (if using ARC: http://stackoverflow.com/questions/9551048/ios5-arc-errors-skpsmtpmessage). Follow the steps at http://dragonmobile.nuancemobiledeveloper.com/public/Help/DragonMobileSDKReference_iOS/Introduction.html to add the Dragon SDK. Upload code onto ipad. Attach to pole via velcro.

Step 2: Casual Encounters Form Factor

Laser cut two pieces of 1/16" plexi according to the cut file provided (one is for the Capacitive Sensor and one is for the LCD screen)


Cut out a circle of stretch jersey 1" larger than the diameter of the pole you plan to attach you device to.


Cut three rectangles. Two the same dimension as your plexi pieces and 1 very small for the aluminum foil. Make sure to leave the extra fabric attached so that you have room to hem the edge.


Hem the edge of your three rectangles using a sewing machine and sew a peice of elastic around the bottom. Make sure to use a zig zag stitch and stretch out the fabric and elastic as you sew them together (otherwise it will not stretch).


Stitch the plexi pieces into the device and attach the LCD and capacitive sensor.


Wire it up and you're ready to install.

Step 3: Casual Encounters Code

Import the CapacitiveSensor library from http://playground.arduino.cc/Main/CapacitiveSensor?from=Main.CapSense.


Upload the arduino code provided on hackster for both the pole attachment device and the crosswalk sensor.

Step 4: Casual Encounters Electronics

Configure Xbee radios to communicate (http://www.hughesy.net/wp/arduino/new-easier-xbee-for-mac-lion-os-x-10-7-with-arduino/).


Assemble electronics according to the fritzing diagrams.

- Adjust capacitive sensor analogRead threshold and/or resistors in circuit such that touch is detected. See http://playground.arduino.cc/Main/CapacitiveSensor for more info on how to set this up.

- Use long wires when connecting the photo-resistor so that it may be placed inside the crosswalk signal object.

- Adjust potentiometer to achieve the desired contrast in the lcd screen.

- Adjust photo-resistor analogRead threshold and/or resistor in circuit such that light and dark are detected reliably.

Step 5: Casual Encounters Form Factor 2 (Crosswalk Sensor)

Laser cut the box parts from the illustrator file provided on hackster.


Assemble the box around the electronics, with the photo-resistor going through the circular hole and the power switch going through the square.


Use your preferred type of adhesive to hold the box together (tape, hot glue, etc.)

Warning: embedding parts within the project story has been deprecated. To edit, remove or add more parts, go to the "Hardware" tab. To remove this list from the story, click on it to trigger the context menu, then click the trash can button (this won't delete it from the "Hardware" tab).
A000066 iso both
Arduino UNO & Genuino UNO
LCD screen 16x2
Resistors
Green Acrylic
XBee series 1
XBee adapter
SoftPot Membrane Potentiometer
Tin foil
Photo-resistor
Tens70
9V battery (generic)
Hero ipad family 2015 2x
Apple iPad
Stretchy Fabric
Elastic

Weekday/Weekend Photos

Five traces of unplanned time/use/wear

Five+ of the unexpected

2 minutes @ Berkeley bart crosswalk No. 1

2 minutes @ Berkeley bart crosswalk No. 2

Three 30-second Interviews

https://soundcloud.com/dennis-rong/sets/interviews-of-bart

None Physical Data - Movement Through Site

Initial Sketches for Casual Encounters & Missed Connections

Missed Connections iOS App Project

App Screenshots

Arduino Casual Encounters Code

Casual_Encounters.ino
Arduino Casual Encounters Code

Warning: Embedding code files within the project story has been deprecated. To edit this file or add more files, go to the "Software" tab. To remove this file from the story, click on it to trigger the context menu, then click the trash can button (this won't delete it from the "Software" tab).

#include <QueueArray.h>

#include <CapacitiveSensor.h>

#include <SoftwareSerial.h>

#include <LiquidCrystal.h>



// Initialize the library with the pins we're using.

// (Note that you can use different pins if needed.)

// See http://arduino.cc/en/Reference/LiquidCrystal

// for more information:



LiquidCrystal lcd(12,11,5,4,3,2);



const int SENSOR_PIN = 0;

CapacitiveSensor cs_8_9 = CapacitiveSensor(8,9);

SoftwareSerial xbeeSerial(6,7);



char previousXbeeByte = '1';

boolean previousTouchActivated = false;



const int SELECT_MODE = 0;

const int INPUT_SEX_MODE = 1;

const int INPUT_OPP_SEX_MODE = 2;

const int INPUT_AGE_MODE = 3;

const int INPUT_INTEREST_MODE = 4;

const int INPUT_NUMBER_MODE = 5;

const int INPUT_END_MODE = 69;

const int DISPLAY_MODE = 100;

const int DISPLAY_OFF_MODE = 101;



int menu_state = SELECT_MODE;

int current_selection_value = 0;



char phone_number[] = {'0','0','0','0','0','0','0','0','0','0'};

int phone_index = 0;



long displayStartTime;



struct CasualEncounter {

  boolean viewed;

  int sex_selection_value;

  int opp_sex_selection_value;

  int age_selection_value;

  int interest_selection_value;

  char phone_number[13];

};

CasualEncounter encounters [10]= { { false, 0, 1, 0, 0, "408-921-0322" }, { false, 1, 1, 1, 2, "408-215-1055" }, { false, 0, 0, 0, 1, "405-837-2910" }, { false, 1, 0, 1, 4, "384-924-0391" } };

int displayIndex;

int numEncounters = 4;

     

String mode_options [] = { "Input", "Display" };

String sex_options [] = { "Male", "Female", "Trans" };

String opp_sex_options [] = { "Male", "Female", "Either" };

String age_options [] = { "10-19", "20-29", "30-39", "40-49", "50-59", "60-69", "70-79", "80-89", "90-99", "100-109" };

String interest_options [] = { "Friendship", "Date", "Sex", "Chat", "Games", "Sports", "Event"};

String number_options [] = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" };     



void setup()

{

  // Tells Library this display has 2 lines of 16 characters

  lcd.begin(16, 2);



  // Data sent to the display will stay there until it's

  // overwritten or power is removed. This clears the LCD.

  lcd.clear();

  

  // Set up inputs

  cs_8_9.set_CS_AutocaL_Millis(0xFFFFFFFF);

  Serial.begin(9600);

  xbeeSerial.begin(9600);

  delay(1000);

  screen_mode(menu_state, current_selection_value);

  delay(200);

  Serial.println("setup");

}



void loop()

{

  // Read input values: xbee, capacitive sensor, potentiometer (pressure)

  boolean crosswalk_changed_to_stop = false;

  boolean crosswalk_changed_to_go = false;

  if (xbeeSerial.available()) { 

    char incomingXbeeByte = xbeeSerial.read();

    

    if (incomingXbeeByte != previousXbeeByte) {

      if (incomingXbeeByte == '1') {

        crosswalk_changed_to_stop = true;

      } else if (incomingXbeeByte == '0') {

        crosswalk_changed_to_go = true;

      }

    }



    // update previous value

    previousXbeeByte = incomingXbeeByte;

  }

  

  long capSenseTotal = cs_8_9.capacitiveSensor(30);

  boolean tappedCapacitiveSensor = previousTouchActivated && !touchActivated(capSenseTotal); // detects release

  // update previous value

  previousTouchActivated = touchActivated(capSenseTotal);

  

  int potentiometerValue = analogRead(SENSOR_PIN);

  Serial.println(potentiometerValue);



  if (100 < potentiometerValue && potentiometerValue < 450) {

    current_selection_value = (current_selection_value - 1 + selection_value_modulus(menu_state)) % selection_value_modulus(menu_state);

    screen_mode(menu_state, current_selection_value);

  }

 

  if (500 < potentiometerValue && potentiometerValue < 1000) {

    current_selection_value = (current_selection_value + 1) % selection_value_modulus(menu_state);

    screen_mode(menu_state, current_selection_value);

  }



  // State based behavior



  switch (menu_state) {

    case SELECT_MODE:

      if (tappedCapacitiveSensor) {

        if (current_selection_value == 0) {

          menu_state = INPUT_SEX_MODE;

        } else {

          menu_state = DISPLAY_MODE;

        }

        current_selection_value = 0;

        screen_mode(menu_state, current_selection_value);

      }

    break;

    

    case INPUT_SEX_MODE:

      if (tappedCapacitiveSensor) {

        encounters[numEncounters].sex_selection_value = current_selection_value;



        menu_state = INPUT_OPP_SEX_MODE;

        current_selection_value = 0;

        screen_mode(menu_state, current_selection_value);

      }

    break;



    case INPUT_OPP_SEX_MODE:

      if (tappedCapacitiveSensor) {

        encounters[numEncounters].opp_sex_selection_value = current_selection_value;



        menu_state = INPUT_AGE_MODE;

        current_selection_value = 0;

        screen_mode(menu_state, current_selection_value);

      }

    break;

    

    case INPUT_AGE_MODE:

      if (tappedCapacitiveSensor) {

        encounters[numEncounters].age_selection_value = current_selection_value;



        menu_state = INPUT_INTEREST_MODE;

        current_selection_value = 0;

        screen_mode(menu_state, current_selection_value);

      }

    break;

    

    case INPUT_INTEREST_MODE:

      if (tappedCapacitiveSensor) {

        encounters[numEncounters].interest_selection_value = current_selection_value;



        menu_state = INPUT_NUMBER_MODE;

        current_selection_value = 0;

        screen_mode(menu_state, current_selection_value);

      }

    break;

    

    case INPUT_NUMBER_MODE:

      if (tappedCapacitiveSensor) {

        phone_number[phone_index] = (char)(((int)'0')+current_selection_value);

        phone_index = phone_index + 1;



        if (phone_index == 10) {

          phone_index = 0;

          int phone_number_string_index = 0;

          for (int i = 0; i < 10; i++) {

            if (i==3) {

              encounters[numEncounters].phone_number[phone_number_string_index++] = '-';

            }

            if (i==6) {

              encounters[numEncounters].phone_number[phone_number_string_index++] = '-';

            }

            encounters[numEncounters].phone_number[phone_number_string_index++] = phone_number[i];

            Serial.print(phone_number[i]);

            phone_number[i] = '0';

          }

          encounters[numEncounters].phone_number[phone_number_string_index++] = 0;

          encounters[numEncounters].viewed = false;

          numEncounters++;



          menu_state = INPUT_END_MODE;

        }



        current_selection_value = 0;

        screen_mode(menu_state, current_selection_value);

      }

      lcd.setCursor(correctPhoneNumberCharIndex(phone_index), 1);

      lcd.cursor();

    break;

    

    case INPUT_END_MODE:

      lcd.noCursor();

      delay(2000);

      menu_state = DISPLAY_MODE;

      current_selection_value = 0;

      screen_mode(menu_state, current_selection_value);

    break;

    

    case DISPLAY_MODE:

     

      if (tappedCapacitiveSensor)

      {

        if (displayIndex == numEncounters) {

          menu_state = INPUT_SEX_MODE;

          current_selection_value = 0;

          screen_mode(menu_state, current_selection_value);

        } else {

          encounters[displayIndex].viewed = true;

          

          lcd.clear();

          lcd.setCursor(0,0);

          lcd.print(encounters[displayIndex].phone_number);

          delay(4000);

        }

      }



      if (millis() - displayStartTime > 2000) {

        do {

          displayIndex = (displayIndex + 1) % (numEncounters + 1);

        } while (encounters[displayIndex].viewed && displayIndex != numEncounters);

        if (displayIndex == numEncounters) {

          lcd.clear();

          lcd.setCursor(0,0);

          lcd.print("Tap to create");

          lcd.setCursor(0,1);

          lcd.print("New Encounter!");

        } else {

          displayEncounter(displayIndex);

        }

        displayStartTime = millis();

      }



      if (crosswalk_changed_to_go) {

        menu_state = DISPLAY_OFF_MODE;

        current_selection_value = 0;

        screen_mode(menu_state, current_selection_value);

      }



    break;



    case DISPLAY_OFF_MODE:

      if (crosswalk_changed_to_stop) {

        menu_state = DISPLAY_MODE;

        current_selection_value = 0;

        screen_mode(menu_state, current_selection_value);  

      }

    break;

  }

  

  // Need to delay, otherwise Arduino loop will add too quickly.

  delay(200);

  

  // TIP: Since the numeric data we're sending is always growing

  // in length, new values will always overwrite the previous ones.

  // However, if you want to display varying or decreasing numbers

  // like a countdown, you'll find that the display will leave

  // "orphan" characters when the new value is shorter than the

  // old one.



  // To prevent this, you'll need to erase the old number before

  // writing the new one. You can do this by overwriting the

  // last number with spaces. If you erase the old number and

  // immediately write the new one, the momentary erase won't 

  // be noticeable. Here's a typical sequence of code:



  // lcd.setCursor(0,1);   // Set the cursor to the position

  // lcd.print("       "); // Erase the largest possible number

  // lcd.setCursor(0,1);   // Reset the cursor to the original position

  // lcd.print(millis()/1000); // Print our value



  // Arduino also comes with a number of built-in examples

  // showing off the features of the LiquidCrystal library.

  // These are locted in the file/examples/LiquidCrystal menu.

}



void screen_mode(int stage, int selection_value)

{

  

  // Clear screen and set cursor to top left corner

  lcd.clear();

  lcd.setCursor(0,0);

  

  switch(stage)

  {

    case SELECT_MODE:

    {

      lcd.print("Select Mode");

      lcd.setCursor(0,1);

      lcd.print(mode_options[selection_value]);

      draw_arrows();

      break;

    }

    case INPUT_SEX_MODE:

    {

      lcd.print("Select your sex.");

      lcd.setCursor(0,1);

      lcd.print(sex_options[selection_value]); 

      draw_arrows();

      break;

    }

    case INPUT_OPP_SEX_MODE:

    {

      lcd.print("Looking for?");

      lcd.setCursor(0,1);

      lcd.print(opp_sex_options[selection_value]); 

      draw_arrows();

      break;

    }

    case INPUT_AGE_MODE:

    {

      lcd.print("Your age.");

      lcd.setCursor(0,1);      

      lcd.print(age_options[selection_value]);      

      draw_arrows();      

      break;

    }

    case INPUT_INTEREST_MODE:

    {

      lcd.print("Interested in?");

      lcd.setCursor(0,1);

      lcd.print(interest_options[selection_value]);

      draw_arrows();

      break;

    }

    case INPUT_NUMBER_MODE:

    {

      lcd.print("Phone Number");

      lcd.setCursor(0,1);

      for (int n = 0; n < 10; n++)

      {

        if (n==3) {

          lcd.setCursor(3, 1);

          lcd.write('-');

        }

       

        if (n==7) {

          lcd.setCursor(7,1);

          lcd.write('-');

        }

       

        lcd.setCursor(correctPhoneNumberCharIndex(n), 1);

        lcd.write(phone_number[n]);

      }

      lcd.setCursor(correctPhoneNumberCharIndex(phone_index), 1);

      lcd.print(number_options[selection_value]);

      draw_arrows();

      break;

    }

    case INPUT_END_MODE:

    {

      lcd.clear();

      lcd.setCursor(0,0);

      lcd.print("Thank you for");

      lcd.setCursor(0,1);

      lcd.print("Participating");

      break;

    }

    case DISPLAY_MODE:

    {

      displayIndex = 0;

      while (encounters[displayIndex].viewed && displayIndex != numEncounters) {

        displayIndex = (displayIndex + 1) % (numEncounters + 1);

      }

      displayEncounter(displayIndex);

      displayStartTime = millis();

      break;

    }

    case DISPLAY_OFF_MODE:

    {

      // lcd clear called at the beginning

      break;

    }

  }

}



int selection_value_modulus(int mode) {

  if (mode == SELECT_MODE) {

    return 2;

  } else if (mode == INPUT_SEX_MODE) {

    return 3;

  } else if (mode == INPUT_OPP_SEX_MODE) {

    return 3;

  } else if (mode == INPUT_AGE_MODE) {

    return 10;

  } else if (mode == INPUT_INTEREST_MODE) {

    return 7;

  } else if (mode == INPUT_NUMBER_MODE) {

    return 10;

  } else {

    return 1;

  }

}



//Draws arrows at the end of the second row.

void draw_arrows() {

  byte arrows[8] = { // set up arrow frame 3, look at the 0's and the 1's

      B00000, // ░░░░░

      B00000, // ░░░░░

      B01010, // ░█░█░

      B11011, // ██░██

      B01010, // ░█░█░

      B00000, // ░░░░░

      B00000, // ░░░░░

      B00000  // ░░░░░

      };



  lcd.createChar(0, arrows);

  lcd.setCursor(15, 1);

  lcd.write((byte) 0);

}



int touchActivated(long capSenseTotal) 

{

  if (capSenseTotal > 100) {

    return 1;

  } else {

    return 0;

  }

}



int correctPhoneNumberCharIndex(int index) 

{

  int correctIndex = index;



  if (index >= 3) {

    correctIndex = correctIndex + 1;

    if (index >= 6) {

      correctIndex = correctIndex + 1;

    }

  }

  

  return correctIndex;

}



void displayEncounter(int index) {

  CasualEncounter ce = encounters[index];

  char firstLine [17];

  int charIndex = 0;

  switch (ce.sex_selection_value) {

    case 0:

      firstLine[charIndex++] = 'M';

    break;

    case 1:

      firstLine[charIndex++] = 'F';

    break;

    case 2:

      firstLine[charIndex++] = 'T';

    break;

  }

  firstLine[charIndex++] = '4';

  switch (ce.opp_sex_selection_value) {

    case 0:

      firstLine[charIndex++] = 'M';

    break;

    case 1:

      firstLine[charIndex++] = 'F';

    break;

    case 2:

      firstLine[charIndex++] = 'M';

      firstLine[charIndex++] = '/';

      firstLine[charIndex++] = 'F';

    break;

  }

  firstLine[charIndex++] = ' ';

  switch (ce.age_selection_value) {

    case 0:

      firstLine[charIndex++] = '1';

      firstLine[charIndex++] = '0';

      firstLine[charIndex++] = '-';

      firstLine[charIndex++] = '1';

      firstLine[charIndex++] = '9';

    break;

    case 1:

      firstLine[charIndex++] = '2';

      firstLine[charIndex++] = '0';

      firstLine[charIndex++] = '-';

      firstLine[charIndex++] = '2';

      firstLine[charIndex++] = '9';

    break;

    case 2:

      firstLine[charIndex++] = '3';

      firstLine[charIndex++] = '0';

      firstLine[charIndex++] = '-';

      firstLine[charIndex++] = '3';

      firstLine[charIndex++] = '9';

    break;

    case 3:

      firstLine[charIndex++] = '4';

      firstLine[charIndex++] = '0';

...

This file has been truncated, please download it to see its full contents.

Arduino Casual Encounters Code (crosswalk sensor)

photodiode_prov4.ino
Arduino Casual Encounters Code (crosswalk sensor)

Warning: Embedding code files within the project story has been deprecated. To edit this file or add more files, go to the "Software" tab. To remove this file from the story, click on it to trigger the context menu, then click the trash can button (this won't delete it from the "Software" tab).

#include <SoftwareSerial.h>



const int sensorPin = 1;

int lightLevel, high = 0, low = 1023, time = 0, time2 = 0, darkLevel = 50;



SoftwareSerial mySerial = SoftwareSerial(2,3);

  

void setup() 

{

  Serial.begin(9600);

  mySerial.begin(9600);

}





void loop()

{

  time = millis();

  

  lightLevel = analogRead(sensorPin);

  // Serial.print(lightLevel);

  // Serial.print("\n");

  

  // dark for more than 2 seconds means "Walk" sign is on

  if ((lightLevel <= darkLevel) && ((time - time2) > 2000)) { 

    time2 = time;

    Serial.print("off \n");

    mySerial.print('0');

  } else if ((lightLevel > darkLevel) && ((time - time2) > 2000)) {

    time2 = time;

    Serial.print("on \n");

    mySerial.print('1');

  } else {

  }





}

Crosswalk Sensor Laser Cutter Box

Circuit Diagrams

Photos

Final Design

Code

Casual_Encounters.inoC/C++
Casual_Encounters.ino
#include <QueueArray.h>

#include <CapacitiveSensor.h>

#include <SoftwareSerial.h>

#include <LiquidCrystal.h>



// Initialize the library with the pins we're using.

// (Note that you can use different pins if needed.)

// See http://arduino.cc/en/Reference/LiquidCrystal

// for more information:



LiquidCrystal lcd(12,11,5,4,3,2);



const int SENSOR_PIN = 0;

CapacitiveSensor cs_8_9 = CapacitiveSensor(8,9);

SoftwareSerial xbeeSerial(6,7);



char previousXbeeByte = '1';

boolean previousTouchActivated = false;



const int SELECT_MODE = 0;

const int INPUT_SEX_MODE = 1;

const int INPUT_OPP_SEX_MODE = 2;

const int INPUT_AGE_MODE = 3;

const int INPUT_INTEREST_MODE = 4;

const int INPUT_NUMBER_MODE = 5;

const int INPUT_END_MODE = 69;

const int DISPLAY_MODE = 100;

const int DISPLAY_OFF_MODE = 101;



int menu_state = SELECT_MODE;

int current_selection_value = 0;



char phone_number[] = {'0','0','0','0','0','0','0','0','0','0'};

int phone_index = 0;



long displayStartTime;



struct CasualEncounter {

  boolean viewed;

  int sex_selection_value;

  int opp_sex_selection_value;

  int age_selection_value;

  int interest_selection_value;

  char phone_number[13];

};

CasualEncounter encounters [10]= { { false, 0, 1, 0, 0, "408-921-0322" }, { false, 1, 1, 1, 2, "408-215-1055" }, { false, 0, 0, 0, 1, "405-837-2910" }, { false, 1, 0, 1, 4, "384-924-0391" } };

int displayIndex;

int numEncounters = 4;

     

String mode_options [] = { "Input", "Display" };

String sex_options [] = { "Male", "Female", "Trans" };

String opp_sex_options [] = { "Male", "Female", "Either" };

String age_options [] = { "10-19", "20-29", "30-39", "40-49", "50-59", "60-69", "70-79", "80-89", "90-99", "100-109" };

String interest_options [] = { "Friendship", "Date", "Sex", "Chat", "Games", "Sports", "Event"};

String number_options [] = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" };     



void setup()

{

  // Tells Library this display has 2 lines of 16 characters

  lcd.begin(16, 2);



  // Data sent to the display will stay there until it's

  // overwritten or power is removed. This clears the LCD.

  lcd.clear();

  

  // Set up inputs

  cs_8_9.set_CS_AutocaL_Millis(0xFFFFFFFF);

  Serial.begin(9600);

  xbeeSerial.begin(9600);

  delay(1000);

  screen_mode(menu_state, current_selection_value);

  delay(200);

  Serial.println("setup");

}



void loop()

{

  // Read input values: xbee, capacitive sensor, potentiometer (pressure)

  boolean crosswalk_changed_to_stop = false;

  boolean crosswalk_changed_to_go = false;

  if (xbeeSerial.available()) { 

    char incomingXbeeByte = xbeeSerial.read();

    

    if (incomingXbeeByte != previousXbeeByte) {

      if (incomingXbeeByte == '1') {

        crosswalk_changed_to_stop = true;

      } else if (incomingXbeeByte == '0') {

        crosswalk_changed_to_go = true;

      }

    }



    // update previous value

    previousXbeeByte = incomingXbeeByte;

  }

  

  long capSenseTotal = cs_8_9.capacitiveSensor(30);

  boolean tappedCapacitiveSensor = previousTouchActivated && !touchActivated(capSenseTotal); // detects release

  // update previous value

  previousTouchActivated = touchActivated(capSenseTotal);

  

  int potentiometerValue = analogRead(SENSOR_PIN);

  Serial.println(potentiometerValue);



  if (100 < potentiometerValue && potentiometerValue < 450) {

    current_selection_value = (current_selection_value - 1 + selection_value_modulus(menu_state)) % selection_value_modulus(menu_state);

    screen_mode(menu_state, current_selection_value);

  }

 

  if (500 < potentiometerValue && potentiometerValue < 1000) {

    current_selection_value = (current_selection_value + 1) % selection_value_modulus(menu_state);

    screen_mode(menu_state, current_selection_value);

  }



  // State based behavior



  switch (menu_state) {

    case SELECT_MODE:

      if (tappedCapacitiveSensor) {

        if (current_selection_value == 0) {

          menu_state = INPUT_SEX_MODE;

        } else {

          menu_state = DISPLAY_MODE;

        }

        current_selection_value = 0;

        screen_mode(menu_state, current_selection_value);

      }

    break;

    

    case INPUT_SEX_MODE:

      if (tappedCapacitiveSensor) {

        encounters[numEncounters].sex_selection_value = current_selection_value;



        menu_state = INPUT_OPP_SEX_MODE;

        current_selection_value = 0;

        screen_mode(menu_state, current_selection_value);

      }

    break;



    case INPUT_OPP_SEX_MODE:

      if (tappedCapacitiveSensor) {

        encounters[numEncounters].opp_sex_selection_value = current_selection_value;



        menu_state = INPUT_AGE_MODE;

        current_selection_value = 0;

        screen_mode(menu_state, current_selection_value);

      }

    break;

    

    case INPUT_AGE_MODE:

      if (tappedCapacitiveSensor) {

        encounters[numEncounters].age_selection_value = current_selection_value;



        menu_state = INPUT_INTEREST_MODE;

        current_selection_value = 0;

        screen_mode(menu_state, current_selection_value);

      }

    break;

    

    case INPUT_INTEREST_MODE:

      if (tappedCapacitiveSensor) {

        encounters[numEncounters].interest_selection_value = current_selection_value;



        menu_state = INPUT_NUMBER_MODE;

        current_selection_value = 0;

        screen_mode(menu_state, current_selection_value);

      }

    break;

    

    case INPUT_NUMBER_MODE:

      if (tappedCapacitiveSensor) {

        phone_number[phone_index] = (char)(((int)'0')+current_selection_value);

        phone_index = phone_index + 1;



        if (phone_index == 10) {

          phone_index = 0;

          int phone_number_string_index = 0;

          for (int i = 0; i < 10; i++) {

            if (i==3) {

              encounters[numEncounters].phone_number[phone_number_string_index++] = '-';

            }

            if (i==6) {

              encounters[numEncounters].phone_number[phone_number_string_index++] = '-';

            }

            encounters[numEncounters].phone_number[phone_number_string_index++] = phone_number[i];

            Serial.print(phone_number[i]);

            phone_number[i] = '0';

          }

          encounters[numEncounters].phone_number[phone_number_string_index++] = 0;

          encounters[numEncounters].viewed = false;

          numEncounters++;



          menu_state = INPUT_END_MODE;

        }



        current_selection_value = 0;

        screen_mode(menu_state, current_selection_value);

      }

      lcd.setCursor(correctPhoneNumberCharIndex(phone_index), 1);

      lcd.cursor();

    break;

    

    case INPUT_END_MODE:

      lcd.noCursor();

      delay(2000);

      menu_state = DISPLAY_MODE;

      current_selection_value = 0;

      screen_mode(menu_state, current_selection_value);

    break;

    

    case DISPLAY_MODE:

     

      if (tappedCapacitiveSensor)

      {

        if (displayIndex == numEncounters) {

          menu_state = INPUT_SEX_MODE;

          current_selection_value = 0;

          screen_mode(menu_state, current_selection_value);

        } else {

          encounters[displayIndex].viewed = true;

          

          lcd.clear();

          lcd.setCursor(0,0);

          lcd.print(encounters[displayIndex].phone_number);

          delay(4000);

        }

      }



      if (millis() - displayStartTime > 2000) {

        do {

          displayIndex = (displayIndex + 1) % (numEncounters + 1);

        } while (encounters[displayIndex].viewed && displayIndex != numEncounters);

        if (displayIndex == numEncounters) {

          lcd.clear();

          lcd.setCursor(0,0);

          lcd.print("Tap to create");

          lcd.setCursor(0,1);

          lcd.print("New Encounter!");

        } else {

          displayEncounter(displayIndex);

        }

        displayStartTime = millis();

      }



      if (crosswalk_changed_to_go) {

        menu_state = DISPLAY_OFF_MODE;

        current_selection_value = 0;

        screen_mode(menu_state, current_selection_value);

      }



    break;



    case DISPLAY_OFF_MODE:

      if (crosswalk_changed_to_stop) {

        menu_state = DISPLAY_MODE;

        current_selection_value = 0;

        screen_mode(menu_state, current_selection_value);  

      }

    break;

  }

  

  // Need to delay, otherwise Arduino loop will add too quickly.

  delay(200);

  

  // TIP: Since the numeric data we're sending is always growing

  // in length, new values will always overwrite the previous ones.

  // However, if you want to display varying or decreasing numbers

  // like a countdown, you'll find that the display will leave

  // "orphan" characters when the new value is shorter than the

  // old one.



  // To prevent this, you'll need to erase the old number before

  // writing the new one. You can do this by overwriting the

  // last number with spaces. If you erase the old number and

  // immediately write the new one, the momentary erase won't 

  // be noticeable. Here's a typical sequence of code:



  // lcd.setCursor(0,1);   // Set the cursor to the position

  // lcd.print("       "); // Erase the largest possible number

  // lcd.setCursor(0,1);   // Reset the cursor to the original position

  // lcd.print(millis()/1000); // Print our value



  // Arduino also comes with a number of built-in examples

  // showing off the features of the LiquidCrystal library.

  // These are locted in the file/examples/LiquidCrystal menu.

}



void screen_mode(int stage, int selection_value)

{

  

  // Clear screen and set cursor to top left corner

  lcd.clear();

  lcd.setCursor(0,0);

  

  switch(stage)

  {

    case SELECT_MODE:

    {

      lcd.print("Select Mode");

      lcd.setCursor(0,1);

      lcd.print(mode_options[selection_value]);

      draw_arrows();

      break;

    }

    case INPUT_SEX_MODE:

    {

      lcd.print("Select your sex.");

      lcd.setCursor(0,1);

      lcd.print(sex_options[selection_value]); 

      draw_arrows();

      break;

    }

    case INPUT_OPP_SEX_MODE:

    {

      lcd.print("Looking for?");

      lcd.setCursor(0,1);

      lcd.print(opp_sex_options[selection_value]); 

      draw_arrows();

      break;

    }

    case INPUT_AGE_MODE:

    {

      lcd.print("Your age.");

      lcd.setCursor(0,1);      

      lcd.print(age_options[selection_value]);      

      draw_arrows();      

      break;

    }

    case INPUT_INTEREST_MODE:

    {

      lcd.print("Interested in?");

      lcd.setCursor(0,1);

      lcd.print(interest_options[selection_value]);

      draw_arrows();

      break;

    }

    case INPUT_NUMBER_MODE:

    {

      lcd.print("Phone Number");

      lcd.setCursor(0,1);

      for (int n = 0; n < 10; n++)

      {

        if (n==3) {

          lcd.setCursor(3, 1);

          lcd.write('-');

        }

       

        if (n==7) {

          lcd.setCursor(7,1);

          lcd.write('-');

        }

       

        lcd.setCursor(correctPhoneNumberCharIndex(n), 1);

        lcd.write(phone_number[n]);

      }

      lcd.setCursor(correctPhoneNumberCharIndex(phone_index), 1);

      lcd.print(number_options[selection_value]);

      draw_arrows();

      break;

    }

    case INPUT_END_MODE:

    {

      lcd.clear();

      lcd.setCursor(0,0);

      lcd.print("Thank you for");

      lcd.setCursor(0,1);

      lcd.print("Participating");

      break;

    }

    case DISPLAY_MODE:

    {

      displayIndex = 0;

      while (encounters[displayIndex].viewed && displayIndex != numEncounters) {

        displayIndex = (displayIndex + 1) % (numEncounters + 1);

      }

      displayEncounter(displayIndex);

      displayStartTime = millis();

      break;

    }

    case DISPLAY_OFF_MODE:

    {

      // lcd clear called at the beginning

      break;

    }

  }

}



int selection_value_modulus(int mode) {

  if (mode == SELECT_MODE) {

    return 2;

  } else if (mode == INPUT_SEX_MODE) {

    return 3;

  } else if (mode == INPUT_OPP_SEX_MODE) {

    return 3;

  } else if (mode == INPUT_AGE_MODE) {

    return 10;

  } else if (mode == INPUT_INTEREST_MODE) {

    return 7;

  } else if (mode == INPUT_NUMBER_MODE) {

    return 10;

  } else {

    return 1;

  }

}



//Draws arrows at the end of the second row.

void draw_arrows() {

  byte arrows[8] = { // set up arrow frame 3, look at the 0's and the 1's

      B00000, // 

      B00000, // 

      B01010, // 

      B11011, // 

      B01010, // 

      B00000, // 

      B00000, // 

      B00000  // 

      };



  lcd.createChar(0, arrows);

  lcd.setCursor(15, 1);

  lcd.write((byte) 0);

}



int touchActivated(long capSenseTotal) 

{

  if (capSenseTotal > 100) {

    return 1;

  } else {

    return 0;

  }

}



int correctPhoneNumberCharIndex(int index) 

{

  int correctIndex = index;



  if (index >= 3) {

    correctIndex = correctIndex + 1;

    if (index >= 6) {

      correctIndex = correctIndex + 1;

    }

  }

  

  return correctIndex;

}



void displayEncounter(int index) {

  CasualEncounter ce = encounters[index];

  char firstLine [17];

  int charIndex = 0;

  switch (ce.sex_selection_value) {

    case 0:

      firstLine[charIndex++] = 'M';

    break;

    case 1:

      firstLine[charIndex++] = 'F';

    break;

    case 2:

      firstLine[charIndex++] = 'T';

    break;

  }

  firstLine[charIndex++] = '4';

  switch (ce.opp_sex_selection_value) {

    case 0:

      firstLine[charIndex++] = 'M';

    break;

    case 1:

      firstLine[charIndex++] = 'F';

    break;

    case 2:

      firstLine[charIndex++] = 'M';

      firstLine[charIndex++] = '/';

      firstLine[charIndex++] = 'F';

    break;

  }

  firstLine[charIndex++] = ' ';

  switch (ce.age_selection_value) {

    case 0:

      firstLine[charIndex++] = '1';

      firstLine[charIndex++] = '0';

      firstLine[charIndex++] = '-';

      firstLine[charIndex++] = '1';

      firstLine[charIndex++] = '9';

    break;

    case 1:

      firstLine[charIndex++] = '2';

      firstLine[charIndex++] = '0';

      firstLine[charIndex++] = '-';

      firstLine[charIndex++] = '2';

      firstLine[charIndex++] = '9';

    break;

    case 2:

      firstLine[charIndex++] = '3';

      firstLine[charIndex++] = '0';

      firstLine[charIndex++] = '-';

      firstLine[charIndex++] = '3';

      firstLine[charIndex++] = '9';

    break;

    case 3:

      firstLine[charIndex++] = '4';

      firstLine[charIndex++] = '0';

...

This file has been truncated, please download it to see its full contents.
photodiode_prov4.inoC/C++
photodiode_prov4.ino
#include <SoftwareSerial.h>



const int sensorPin = 1;

int lightLevel, high = 0, low = 1023, time = 0, time2 = 0, darkLevel = 50;



SoftwareSerial mySerial = SoftwareSerial(2,3);

  

void setup() 

{

  Serial.begin(9600);

  mySerial.begin(9600);

}





void loop()

{

  time = millis();

  

  lightLevel = analogRead(sensorPin);

  // Serial.print(lightLevel);

  // Serial.print("\n");

  

  // dark for more than 2 seconds means "Walk" sign is on

  if ((lightLevel <= darkLevel) && ((time - time2) > 2000)) { 

    time2 = time;

    Serial.print("off \n");

    mySerial.print('0');

  } else if ((lightLevel > darkLevel) && ((time - time2) > 2000)) {

    time2 = time;

    Serial.print("on \n");

    mySerial.print('1');

  } else {

  }





}

Comments

Similar projects you might like

Provocation 3: aNonY

Project in progress by 5 developers

  • 609 views
  • 0 comments
  • 0 respects

AggroFox: Large-Scale and Urban Agriculture IoT Solution

Project tutorial by EdOliver and Victor Altamirano

  • 8,607 views
  • 1 comment
  • 32 respects

NoPro

Project tutorial by Team No Pro

  • 3,766 views
  • 12 comments
  • 5 respects

XBee Walkie Talkie

Project tutorial by Phillip Stevens

  • 12,028 views
  • 6 comments
  • 27 respects

Hot Water Solar Boiler Project

Project in progress by Pleemans

  • 6,762 views
  • 2 comments
  • 28 respects

Arduino Smart car

Project tutorial by Tony ZHANG

  • 28,289 views
  • 1 comment
  • 26 respects
Add projectSign up / Login