Sleep Tracker by Leroy Tellez & Sam Wander

SVA Interaction Design Midterm: Sleep Tracker

After exploring new sensors we’d not encountered yet in class, we decided to use a 3-axis accelerometer (ADXL335) to monitor sleep patterns, and represent sleep in a physical way (as opposed to on screen). We would use Servo motors to control wooden dowels, with their position related to the depth of sleep. The more restless the sleeper, the more the accelerometer would move, representing lighter sleep. The vice versa would also be true, representing deep sleep.

initial_circuit

Before determining the physical form, we experimented with the sensor, motors and code. The challenge was to capture movement over time, and map this to the Servo angle. We would need to monitor time since the Arduino program was started, and progress from one Servo to another as each hour passed (we used a variable to make an hour pass in just 30 seconds for demo purposes).

With the code mostly complete and proven, we began building the wooden box from plywood. We would house the Arduino and a PCB board, onto which we would migrate the circuit from the breadboards, under a shelf. The motors would go on the shelf, with dowels pointing vertically through the roof.

pcb

PCB2

wooden_box

building_the_box

Here’s a diagram of the board:

PCB_Schematic

We recognized a small design problem. On waking, you wouldn’t know the length of your sleep as the dowels would have to be in one position or another. If the seventh and eighth dowel were at 90 degrees, this could mean moderate sleep or that the program had not reached those motors yet. We added LEDs to gently uplight the currently moving dowel, so if the fifth dowel was lit you’d be in the fifth hour since the program began.

The project was mostly successful. Unfortunately the small Servos have a tendency to vibrate or make noise, which is clearly undesirable for something that should sit quietly and stably on your night stand. We also had a lot of wires to squeeze below the shelf, we could perhaps have managed the space a little better. The project validated the concept of a physical sleep sensor, as a prototype, but it would be good – if we were to progress further – to refine the physical form.

Arduino Code:

    #include <Servo.h>
    
    // Set Shift Register pins
    
    int latchPin = 2;
    int clockPin = 1;
    int dataPin = 0;
    
    byte leds = 0;
    
    // Set Servo pin array to cycle through
    
    int noOfServos = 8;
    int servoPinArray[] = {4,5,6,7,8,9,10,11};
    
    // Array to correct reset pins to 90 degrees (compensating for Servo inaccuracy)
    int offsetArray[] = {83,90,84,81,87,101,99,96};
    
    Servo myservo;  // create servo object to control a servo
    
    // Acceleromator
    
    int sensorPinX = A0; // set X-acceleromator to A0
    
    // Time variables
    
    long previousMillis = 0;
    long interval = 1000;
    
    int s; // variable to count secs
    int h; // variable to count hours
    int hourLength = 30; // should be set to 3600 for full hour
    
    // Motion
    
    int prevReading = 0; // will get one false reading
    int threshold = 1; // tolerance for motion
    
    int motionCounter; // motion count (beyond threshold)
    
    void setup() {
    
    Serial.begin(9600);
    
    pinMode(latchPin, OUTPUT); // shift register
    pinMode(dataPin, OUTPUT);  // shift register
    pinMode(clockPin, OUTPUT); // shift register
    
    // reset all dowels to 90 degrees
    
    for (int i = 0; i < noOfServos; i++) {
    myservo.attach(servoPinArray[i]);
    myservo.write(offsetArray[i]);
    delay(350);
    myservo.detach();
    }
    
    myservo.attach(servoPinArray[0]);
    
    // Switch on first LED
    
    leds = 0;
    bitSet(leds, h);
    updateShiftRegister();
    
    }
    
    void loop() {
    
    unsigned long currentMillis = millis();
    int m; // used for moving Servo
    
    // Count seconds
    
    if(currentMillis - previousMillis > interval) {
    previousMillis = currentMillis;
    s++;
    Serial.print("Seconds : ");
    Serial.println(s);
    
    // Count movement via hasMoved function
    
    motionCounter += hasMoved();
    Serial.print("Motion count: ");
    Serial.println(motionCounter);
    
    // Map to Servo position and move
    
    m = map(motionCounter,0,30,125,45);
    Serial.print("Servo position: ");
    Serial.println(m);
    Serial.println("n");
    myservo.write(m);
    }
    
    // When an hour is reached, progress to next Servo and next LED
    
    if(s == hourLength) {
    s = 0;
    h++;
    Serial.print("Hours : ");
    Serial.println(h);
    
    bitSet(leds, h);
    bitClear(leds, h-1);
    updateShiftRegister();
    
    motionCounter = 0;
    
    myservo.detach();
    myservo.attach(servoPinArray[h]);
    myservo.write(125);
    Serial.println("Next Servo");
    }
    
    }
    
    // Function for counting movement
    
    int hasMoved() {
    int reading = analogRead(sensorPinX);
    int dif = abs(reading- prevReading);
    prevReading = reading; // set current reading to be previous
    if (dif > threshold) {
    return 1;
    Serial.println("1");
    }
    else {
    return 0;
    Serial.println("0");
    }
    }
    
    // Switch on lights
    
    void updateShiftRegister()
    {
    digitalWrite(latchPin, LOW);
    shiftOut(dataPin, clockPin, LSBFIRST, leds);
    digitalWrite(latchPin, HIGH);
    }

Student Blogs:
http://tellezsva.wordpress.com/
http://blog.samwander.com/

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

Create a website or blog at WordPress.com

Up ↑

%d bloggers like this: