Holly PasquinelliChris WojnarowskiTyler Heng
Published © GPL3+

LoT305: Productivity and Library Usage

How to measure productivity in the library and its busiest times. Ultrasonic sensor, sound detector, particle photon.

IntermediateFull instructions provided5 hours606
LoT305: Productivity and Library Usage

Things used in this project

Hardware components

Jumper wires (generic)
Jumper wires (generic)
×1
Breadboard (generic)
Breadboard (generic)
×1
Photon
Particle Photon
×1
SparkFun Sound Detector
×1
Ultrasonic Sensor - HC-SR04
SparkFun Ultrasonic Sensor - HC-SR04
×1

Software apps and online services

fritzing
particle
Google Sheets
Google Sheets

Hand tools and fabrication machines

Laser cutter (generic)
Laser cutter (generic)
Hot glue gun (generic)
Hot glue gun (generic)
xacto knife

Story

Read more

Custom parts and enclosures

Final Cut

This is the file we used to laser cut the final product after settling on dimensions and making sure that the breadboard fit inside.

Schematics

Planning

This is what our design looked like on paper, our first step in visualizing the final product.

BreadBoard

After weeks working on the project, this is a complete breadboard functioning with the sound and Ultra-sonic sensors.

Sound Sensor

This is our sound sensor which we placed strategically to one side in order for it to stick out and capture noise in the desired environment.

Ultra-sonic Sensor

This is our ultra-sonic sensor placed opposite of the sound sensor in order to be used to measure how many times people enter the library.

Final Product

This is our final product powered via USB port. All sides are secured by t-slots.

Prototype

working with cardboard to prototype

Prototype

original file for box

Proto

finished proto

original wired breadboard

first attempt at wiring the breadboard

Code

Final Code

Arduino
combined phant library, source code, code for sound and ultrasonic sensors
// This #include statement was automatically added by the Particle IDE.
#include <SparkFunPhant.h>

// This #include statement was automatically added by the Particle IDE.
// Don’t forget to delete this line and add the library via Particle’s library tab.
const int TRIG_PIN = 2;

const int ECHO_PIN = 6;


// Anything over 400 cm (23200 us pulse) is "out of range"
const unsigned int MAX_DIST = 5800;

double value1 = 0; 
double value2 = 0; 

const char server[] = "data.sparkfun.com"; // Phant destination server
const char publicKey[] = "wpg7MYjq9EhEXqLWQZgE"; // Phant public key - HAS TO BE CHANGED
const char privateKey[] = "wzqgGMEW10UD6GpwZbkD"; // Phant private key  - HAS TO BE CHANGED
Phant phant(server, publicKey, privateKey); // Create a Phant object

const int POST_RATE = 3000; // Time between posts, in ms.
unsigned long lastPost = 0; // global variable to keep track of last post time


////////sound
const long sample_rate = 50; // time between samples (in miliseconds)
const int array_size = 1200; // 1000/50=20 * 60=1200
int snd_array[array_size] = {};
int snd_max = 0 ;
int snd_min = 4096 ;
double snd_avg = 0;
double distance = 0;

const int blink_thresh = 3000;

unsigned long broadcast_interval = 1000;
unsigned long last_broadcast = 0;
unsigned long lastSample = 0 ;
unsigned long lastReset = 0 ;



/////sound
void averageReading(int value) 
{
    unsigned long now = millis();

    if((now - lastSample) > sample_rate) 
    {
        // Shift all the values right by 1
        for(int i = array_size-1; i >= 1; i--) 
        {
            snd_array[i] = snd_array[i-1]; 
            if((snd_array[i] < snd_min) && (snd_array[i] > 0))
            {
                snd_min = snd_array[i];
            }
            if(snd_array[i] > snd_max)
            {
                snd_max = snd_array[i];
                
            }
        }
    
        snd_array[0] = value; 
    
        // Average of all non-zero elements in the array
        double avg_sum = 0; 
        int size = 0 ;
        for (int a=0; a < array_size; a++) 
        {
            if(snd_array[a] > 0)
            {
                size++ ;
                avg_sum += snd_array[a];
            }
        }
        snd_avg = avg_sum / size;
        
        lastSample = now ;
    }
}

//blink the onboard LED (D7) if reading is louder than threshold
void blinkMic(int reading) 
{
    if(reading > blink_thresh) 
    {
        digitalWrite(D7, HIGH);
    } 
    else 
    {
        digitalWrite(D7, LOW);
    }
}

//check to see if we should reset min and max
void checkReset() 
{
    unsigned long now = millis();
    
    //if it has been one minute since resetting min and max, reset
    if((now - lastReset) >= 60000) 
    {
        snd_max = 0 ;
        snd_min = 4095 ;
        lastReset = now ;

    }
}

//print out the values of avg, min and max to terminal
void broadcast() 
{
    unsigned long now = millis();
    if((now - last_broadcast) > broadcast_interval) {
        Serial.print("Avg: "); Serial.println(snd_avg);
        Serial.print("Min: "); Serial.println(snd_min);
        Serial.print("Max: "); Serial.println(snd_max);

        last_broadcast = now;
    }
}


////////


void setup() {
    Serial.begin(9600);
     // The Trigger pin will tell the sensor to range find
  pinMode(TRIG_PIN, OUTPUT);
  digitalWrite(TRIG_PIN, LOW);

  // We'll use the serial monitor to view the sensor output

    pinMode(A0, INPUT); // mic AUD connected to Analog pin 0
    pinMode(D7, OUTPUT); // flash on-board LED
    Particle.variable("avg",snd_avg);
    Particle.variable("min",snd_min);
    Particle.variable("max",snd_max);
    Particle.variable("dis",distance);

}

void loop() {
    ///////////sound
     int mic_reading = analogRead(0); //Serial.println(mic_reading);
    blinkMic(mic_reading) ;
    averageReading(mic_reading) ; 
    broadcast() ;
    
    //this will reset the min and max, but keep in mind that those
    //large and small values will remain in the array for up to one
    //minute depending on the sample_rate
    checkReset() ;


///phant

    boolean somethingHappened = false;
    
     Serial.print("test");
  unsigned long t1;
  unsigned long t2;
  unsigned long pulse_width;
  float cm;
  float inches;

  // Hold the trigger pin high for at least 10 us
  digitalWrite(TRIG_PIN, HIGH);
  delayMicroseconds(10);
  digitalWrite(TRIG_PIN, LOW);

  // Wait for pulse on echo pin
  while ( digitalRead(ECHO_PIN) == 0 );

  // Measure how long the echo pin was held high (pulse width)
  // Note: the micros() counter will overflow after ~70 min
  t1 = micros();
  while ( digitalRead(ECHO_PIN) == 1);
  t2 = micros();
  pulse_width = t2 - t1;

  // Calculate distance in centimeters and inches. The constants
  // are found in the datasheet, and calculated from the assumed speed 
  //of sound in air at sea level (~340 m/s).
  cm = pulse_width / 58.0;
  inches = pulse_width / 148.0;

  // Print out results
  if ( pulse_width > MAX_DIST ) {
    Serial.println("Out of range");
  } else {
    Serial.print(cm);
    Serial.print(" cm \t");
    Serial.print(inches);
    Serial.println(" in");
  }
  distance = inches;
  
  // Wait at least 60ms before next measurement
  delay(60);
    
    if(inches < 48)
    {
        somethingHappened = true;
        value1 = inches;
    }
    

    //Replace the if statement below with whatever your trigger is
    
    if (somethingHappened)
    {
        postToPhant();
    }
    
    
}

int postToPhant()
{    
    // Use phant.add(<field>, <value>) to add data to each field.
    // Phant requires you to update each and every field before posting,
    // make sure all fields defined in the stream are added here.
    phant.add("motion", value1);
   
        	
    TCPClient client;
    char response[512];
    int i = 0;
    int retVal = 0;
    
    if (client.connect(server, 80)) // Connect to the server
    {
		// Post message to indicate connect success
        Serial.println("Posting!"); 
		
		// phant.post() will return a string formatted as an HTTP POST.
		// It'll include all of the field/data values we added before.
		// Use client.print() to send that string to the server.
        client.print(phant.post());
        delay(1000);
		// Now we'll do some simple checking to see what (if any) response
		// the server gives us.
        while (client.available())
        {
            char c = client.read();
            Serial.print(c);	// Print the response for debugging help.
            if (i < 512)
                response[i++] = c; // Add character to response string
        }
		// Search the response string for "200 OK", if that's found the post
		// succeeded.
        if (strstr(response, "200 OK"))
        {
            Serial.println("Post success!");
            retVal = 1;
        }
        else if (strstr(response, "400 Bad Request"))
        {	// "400 Bad Request" means the Phant POST was formatted incorrectly.
			// This most commonly ocurrs because a field is either missing,
			// duplicated, or misspelled.
            Serial.println("Bad request");
            retVal = -1;
        }
        else
        {
			// Otherwise we got a response we weren't looking for.
            retVal = -2;
        }
    }
    else
    {	// If the connection failed, print a message:
        Serial.println("connection failed");
        retVal = -3;
    }
    client.stop();	// Close the connection to server.
    return retVal;	// Return error (or success) code.
    
   
}

Credits

Holly Pasquinelli

Holly Pasquinelli

1 project • 0 followers
Chris Wojnarowski

Chris Wojnarowski

1 project • 0 followers
Lane Tech
Tyler Heng

Tyler Heng

1 project • 0 followers
ICL

Comments