Twitter

We (Lizzie) managed a huge feat in accomplishing pushing the data of the Arduino and sound sensor to Twitter. This created an additional layer of interactivity and in encouraging the individual to engage in monitoring the sound environment that they experience.

You can view the feed for the data we collected during setup, test and presentation here.

Presentation Reflection

I think it went really well.

I was terrified it would stop working, even though I had tested it 4 times this morning, twice in the room and in the scarf, but technology is never reliable enough for an important presentation!

It didn’t though, we didn’t get high enough levels for the LEDs to be lit, but it was sending it’s data away happily to twitter, which I was so relieved about!! We didn’t get many questions, so I’m going to assume that’s because we explained everything well in the presentation 😉

One question that was interesting was whether we thought decibear really would change people’s behaviour. I’m not sure it would to be honest, but I have to say that just wearing something, even for testing, that I know is listening to ambient sounds, really did increase my awareness to them. Not sure it would be enough to change my route to uni on a cold day, but I definitely was more aware.

 

So, just one more lose end, here’s a link to the final code in the blog (slightly different from the last one copied to here): https://www.dropbox.com/s/93z4t59x4n7msc0/decibear_tweet.pde

 

Aaaaand we’re done!! So long Decibear, it’s been fun!

IMAG0781

Roles

I feel we’ve both worked really hard on this project, I hope the product shows that, but the blog definitely does!
I guess though that we have to split the project down into roles to help with marking, although it’s really difficult in our case as we’ve both done pretty much everything, so I’m listing us down as the lead, in that that person took the biggest role, but the other will have done some of it as well!

Lead Researcher – Karla
Lead Coder – Lizzie
Lead CD-compiler – Karla
Lead blog (site)-creator – Lizzie
Lead kit-babysitter – Karla
Lead optimist – Lizzie
Lead Saunders-negotiator – Karla
Lead swearer-at-computers – Lizzie

We both came up with the ideas together as a long process of bouncing the craziest things we can think of against our skill set. And also against Mike Blow, so thanks for some project ideas go to Mike too. And thanks to Will Skates for his midnight help with a php script to send stuff to twitter.

Tweet tweet

With the help of Will Skates writing a php script for me to send my values from the Arduino to, and send them on to twitter, it’s finally sending the sensor readings to twitter and flashing the lights.

I had to set this one up as a client to Will’s page instead of a server as before, but it’s all good.

// (Based on Ethernet's WebClient Example)

#include "WiFly.h"


#include "Credentials.h"


byte server[] = { 66, 249, 89, 104 }; // Google
int canConnect = 0;

int ledPin[] = {3,4,5};

int warningLevels[] = {200, 230, 270};
//int warningLevels[] = {20, 50, 100};

int sensorPin = A0;
int sensorValue = 0;

int readCount = 0;

int accumSound = 0;
int aveSound = 0;

int ledLit = 0;

//Client client(server, 80);

Client client(server, 80);

void setup() {
  
  Serial.begin(9600);

  WiFly.begin();
  
  Serial.println("associating");
  if (!WiFly.join(ssid, passphrase)) {
    Serial.println("Association failed.");
    while (1) {
      // Hang on failure.
    }
  }else{
    Serial.println("Association succeeded.");
  }  

  Serial.println("connecting...");

  if (client.connect()) {
    Serial.println("connected");
    canConnect = 1;
    client.println("GET /new?msg=openConn&pwd=(password) HTTP/1.1");
    client.println();
  } else {
    Serial.println("connection failed");
  }
  
}

void loop() {
  
  Serial.println("attempting request");
  
  
  delay(5000);
  
  //read sensor
  sensorValue = analogRead(sensorPin);
  //reread if values are not between our thresholds
  while(sensorValue == 0 || sensorValue > 350){
    sensorValue = analogRead(sensorPin); 
  }
  
  //add to readCount
  readCount ++;
          
  //add to accumulative sound
  accumSound += sensorValue;
  
  //work out average sound per minute
  aveSound = accumSound/readCount;
  
  //check against set levels
  for (int i=0; i<(sizeof(warningLevels)/2); i++){
    if (aveSound > warningLevels[i]){
      ledLit = i+1;
    }
  }
  
  //light LEDs
  for (int i=0; i<ledLit; i++){
    digitalWrite(ledPin[i], HIGH); 
  }
  
  client.stop();
  if (client.connect()) {
    String req = "GET /new?msg=";
    req += sensorValue;
    req += "&pwd=(password)";
    client.println(req);
    client.println();
  } else {
    Serial.println("connection failed");
  }

}

You can see the tweets here: https://twitter.com/decibear
Although now, being half 2am, I think it’s time for bed, which means no visualization, but we have a working blogject!

Code update so far

I’ve been working on the wifly stuff, and I’ve had some big issues, namely with the IP address, not being set from the router which is my phone. Finally fixed it now, so hopefully if I don’t change anything tonight on my phone or wiFly shield settings, it should work tomorrow!

This script still does the thing with the lights, but it also sends the information over the wiFly’s server, so I can read it on my phone while I’m out and about wearing the bear scarf!

The only real bug with this is that for some reason I can’t change the delay without messing up the client, so it’s currently reading every 10 ms rather than 30s, but I’m still working on that!

/*
 * Web Server
 *
 * (Based on Ethernet's WebServer Example)
 *
 * A simple web server that shows the value of the analog input pins.
 */

#include "WiFly.h"

char passphrase[] = "pass";
char ssid[] = "ssid";

int ledPin[] = {3,4,5};

int warningLevels[] = {200, 230, 270};
//int warningLevels[] = {20, 50, 100};

int sensorPin = A0;
int sensorValue = 0;

int readCount = 0;

int accumSound = 0;
int aveSound = 0;

int ledLit = 0;

Server server(80);

void setup() {
  
  for (int i=0; i<(sizeof(ledPin)/2); i++){
   pinMode(ledPin[i], OUTPUT); 
  }
  
  WiFly.begin();

  if (!WiFly.join(ssid, passphrase)) {
    while (1) {
      // Hang on failure.
    }
  }

  Serial.begin(9600);
  Serial.print("IP: ");
  Serial.println(WiFly.ip());
  
  server.begin();
}

void loop() {
  
  //read sensor
  sensorValue = analogRead(sensorPin);
  //reread if values are not between our thresholds
  while(sensorValue == 0 || sensorValue > 350){
    sensorValue = analogRead(sensorPin); 
  }
  
  //add to readCount
  readCount ++;
          
  //add to accumulative sound
  accumSound += sensorValue;
  
  //work out average sound per minute
  aveSound = accumSound/readCount;
  
  //check against set levels
  for (int i=0; i<(sizeof(warningLevels)/2); i++){
    if (aveSound > warningLevels[i]){
      ledLit = i+1;
    }
  }
  
  //light LEDs
  for (int i=0; i<ledLit; i++){
    digitalWrite(ledPin[i], HIGH); 
  }
  
  Client client = server.available();
  if (client) {
    // an http request ends with a blank line
    boolean current_line_is_blank = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        // if we've gotten to the end of the line (received a newline
        // character) and the line is blank, the http request has ended,
        // so we can send a reply
        if (c == '\n' && current_line_is_blank) {
          // send a standard http response header
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println();
          
          //output the sensor values
          client.print("sensor value: ");
          client.print(sensorValue);
          client.print("<br/><br/>");
          
          //output the accumulative values
          client.print("You have had ");
          client.print(accumSound);
          client.print(" over ");
          client.print(readCount);
          client.print(" minutes.");
          client.println("<br />");
          
          //output the average values
          client.print("This is an average of ");
          client.print(aveSound);
          client.print(" per minute");
          client.println("<br/><br/>");
          
          //warn if over final level
          if (ledLit == 3){
           client.print("This is over your recommended allowance by ");
           client.print(aveSound - warningLevels[2]);
           client.print("<br/>"); 
          } else {
           client.print("This is under your recommended allowance by ");
           client.print(warningLevels[2] - aveSound);
           client.print("<br/>");
          }
          
          break;
        }
        if (c == '\n') {
          // we're starting a new line
          current_line_is_blank = true;
        } else if (c != '\r') {
          // we've gotten a character on the current line
          current_line_is_blank = false;
        }
      }
    }
    // give the web browser time to receive the data
    delay(100);
    //delay(30000);
    client.stop();
  }
}

Now I’m at another stage where we could present if necessary, although I really would like to get it sending to twitter, or have some sort of visualization, or preferably both! I will keep working on it for a while, but I’ll need to get some sleep soonish as I barely slept last night, and tomorrow is the big day!

Sleepy-time

We were really hoping to be able to put the arduino to sleep and wake it up every 30 seconds or minute to scan for sound, then wake it up again, but it turns out this won’t be possible.

We thought it was a good idea in order to help make it more portable, in that the battery would last a lot longer, but according to everything I have managed to read about it, it seems that 8s is the longest you can put an arduino to sleep for without an external clock attached, which we have no hope of getting at this point.

Hopefully though, it won’t matter as we have already tested the system for 10 minutes off battery with a simple delay in, and it could have lasted even longer but I got bored!

Achievement reached!

We set ourselves goals to reach, so at each stage we would have something we could hand in, before we moved on to add the next part in. And today, finally, we reached our first goal, to read the sound data, and visualize it in a way to give instant feedback to the wearer.

The problem is, our sound sensor is still being a bit dodgy, so I’ve had to rig the code a little bit for testing purposes, but I still have the true science bit in (commented out) in case anybody asks!

Here’s the code:

int sensorPin = A0;
int ledPin[] = {3,4,5};

//int warningLevels[] = {200, 230, 270};
int warningLevels[] = {20, 50, 100};

int sensorValue = 0;

int accumSound = 0;
int readCount = 0;
int aveSound = 0;

int ledLit = 0;

void setup()
{
  Serial.begin(9600);
  //set up LEDs
  for (int i = 0; i<(sizeof(ledPin)/2); i++){
   pinMode(ledPin[i], OUTPUT); 
  }
}

void loop()
{
  //turn the lights off
  for (int i = 0; i<(sizeof(ledPin)/2); i++){
   digitalWrite(ledPin[i], LOW); 
  }
  ledLit = 0;

  //read sensor
  sensorValue = analogRead(sensorPin);
  //remove errors
  while(sensorValue == 0 || sensorValue > 350){
   Serial.println("reread...");
   sensorValue = analogRead(sensorPin); 
  }
  //trace
  Serial.print("sensorValue: ");
  Serial.println(sensorValue);

  //add to accumulative sound
  accumSound += sensorValue;
  //trace
  Serial.print("Accumulative Sound: ");
  Serial.println(accumSound);

  //add to readCount
  readCount++;

  //work out average sound per minute
  aveSound = accumSound/readCount;
  //trace
  Serial.print("Average Sound per min: ");
  Serial.println(aveSound);

  //check against our set levels
  for (int i=0; i<(sizeof(warningLevels)/2); i++){
   if (aveSound > warningLevels[i]){
    ledLit = i+1;
    Serial.print("Warning level breached: ");
    Serial.println(i);
   } 
  }

  ///light correct amount of LEDs
  for (int i=0; i<ledLit; i++){
   digitalWrite(ledPin[i], HIGH); 
  }

  Serial.println("------------------------------------------");

  //wait for 1 minute
  delay(30000);
}

I’ve done my best to comment it well, but incase you can’t work out what it does, basically it reads the sound every 30 secs, adds this to a accumulative score, works out the average sound you’ve been subjected to per minute from that, and lights the LEDs if you’ve had over the recommended limit per minute.

 

I’ll let Karla explain the science behind the recommended limits she came up with, but they’re basically 80,85 and 90 decibels, which we think should correspond to 200, 230, 270 from our sensor. However, these values are never hit, even if the sound sensor on Karla’s phone says we’re above those decibels, so I’ve added random levels in for testing.

 

I’ve currently been running it, with the wifly board in but not working, on battery for seven minutes and it’s still going strong.

Next up, we have a break for a dissertation seminar, then we’ll get the wifly working. We have a vague idea of sending the data to twitter, and pulling the feed from it to visualize it, but we’ll see how we go. At least now we have something to show if all else fails.

Time is running out….

Realtime is finally over, and I can now focus entirely on Everyware, although I’ve got the post-deadline illnesses as usual to fight through now!

We’re working on getting the scarf part set up today, I’d like to have the system take a reading from the sound sensor every 3 minutes, add this to the accumulative sound score, and light up LEDs if this score goes above certain levels.

I’ve started by looking into how to put the arduino into some sort of idle mode so it uses as little power as possible while it isn’t required to sense anything. Helpfully though, the arduino website is down until at least 3pm today, so I’m having to try and find clues on other websites.

I found this one on RocketScream which looks really promising, and really easy to use. I worked on top of their ‘powerDownWakePeriodically’ script to write my functionality, but I am still yet to get it to compile with the powerDown code in there. I guess we could do periodic readings with a delay or something, but it would be good to have lower power usage as we’re running off battery.

Karla and I have chosen some ‘safe’ accumulative sound levels to compare our readings to, so we plan to light up a red warning LED if you’ve been exposed to over 85db over an 8 hour period, because that’s really bad for your health, and then we’ll light up a few green ones at various stages on the way to that (probably 45db and 65db, seems nice and even!)

We need to do two things to this though, we need to work out how to translate the sounds we’ve taken over a certain time period to the 8hr time period for comparison, and work out how the sound numbers we’re getting from our sensor compare to decibels.

Karla has a sound app on her phone which works in decibels, so we’re comparing readings from that to work it out.

WiFly-ing high

We’d been having trouble with the WiFly shield for weeks, it was just hanging at the SPI UART begin function, which meant that it was unable to connect to the WiFly bit through the shield. We knew this, but after the mess up with the sound sensor (we had it wired wrongly!) we didn’t want to be the bad workmen blaming our tools again!

But this time, it turned out it was the tools; the WiFly shield isn’t compatible with the Arduino Mega. Damn.

Thankfully it was a relatively simple fix, although I think I’m in danger of death-by-Saunders, as I’ve had to bend the pins from the shield 😉

All you have to do is reroute the pins that are in different positions on the Mega, I followed this helpful tutorial (I know it’s for ethernet, but it worked just the same) http://mcukits.com/2009/04/06/arduino-ethernet-shield-mega-hack/

And this now means we can move one more step forward on our lovely project 🙂