All posts by fabiola

Final Project

ThesisFinalKeynote09.001

CONCEPT

My thesis is inspired by my personal experiences witnessing and taking care of my mother for years as she has been going through a tedious physical rehabilitation plan after an injury that has made her bedridden. Through the process, I have realized that more so than usual, physical rehabilitation requires constant action. If we where to think of this as an algorithm, time always works against you and deconstructs what you have been working so hard on constructing.

Deconstruction > Construction is a telerehabilitation aid with sculptural qualities that helps outpatients in isolation better cope with and stay consistent with their physical rehabilitation plans.

Conceptually this piece brings up questions about motivation and self-efficacy, how medical devices have traditionally been designed with aesthetics and empathy secondary to functionality, and how that relates to psychology and wellbeing.

When speaking to healthcare practitioners, proper form, time interval and motivation to do the exercises in the first place is the most common problem. Over 18 million people have immobility issues, making them the second largest minority, and almost 40% of people aged over 65 have some sort of immobility issue. This is the fastest growing segment of the American population, expected to double in the year 2050. Most common conditions causing disability: arthritis, rheumatism, stroke and spinal cord injuries. 11,000 people sustain a spinal cord injury every year, and 88% are rehabilitating in the home, and only about half are getting health insurance. So we can evidently see how struggling to rehabilitate in isolation in the home becomes a problem at a greater scale.

PRECEDENTS

ThesisFinalKeynote09.005

Lygia Clark has served as an inspiration in terms of her psychotherapeutic methodologies using art as a vehicle to connect the body and mind.

Thad Starner’s Mobile Music Touch is a step forward in taking advantage of the brains ability to heal quicker through passive haptic feedback in combination with visual queues.

Current telerehabilitation devices are exceedingly focused on screen based interaction and are typically big and aesthetically unpleasing. Moreover, they only tackle one muscle group at a time.

There is a clear lack of telerehabilitation and exercise aids that are small, aesthetically pleasing and can help cater to more than one are of the body. Hence, my prototype below aimed to explore how this one object can be functional in multiple ways. 

PROCESS

This class has provided me to work on my physical computing skills to be able to build the foundation for a product that is able to help with these issues. This semester I have mainly focused on functionality, and below are the results of my final prototype for this phase.

My aim is to bring this prototype to the rehabilitation clinic where my mother currently resides, in order to nail down the functionality and test the experience with my target user over a longer period of time. This would allow me to start next semester by working on form and how I can incorporate more sculptural qualities.

By incorporating an accelerometer, and giving the user visual feedback through LED’s, the user can know how to hold proper form. Moreover, haptic feedback lets the user know if they have done their sets within the right time frame.  This time, vibrations where used only when the user needed to improve (see code below).

Functionality

– Range of motion exercises using an infrared proximity sensor.

– Arduino Yun to collect data online through socket connections and Mongo DB.

Triple axis accelerometer for tracking the form and giving the user visual feedback.

– Vibration motor and LED’s for output.

Qi charger and receiver for wireless charging with a Lipo charger and 3.7V 1200 mAh battery.

I saw this as an exercise in 3D modeling, and tried several different designs in different programs before landing on my final simplified version. As expected, 3D printing is a tedious process, and I learnt a lot in terms of how to fabricate with the right thickness as well as which software to use. I found Maya to be an awful program to work with, and finally settled on Blender. I am happy I went through all this as I plan to add kinetic movement in my design next semester, and will probably need smaller custom parts printed.

Screen Shot 2014-11-28 at 5.06.11 PM

makerbot

Screen Shot 2014-12-12 at 4.07.21 PM

I soldered all the connections on to a shield for stability. I would have made my own circuit, but needed to use the Arduino Yun anyway for the online connection.

Screen Shot 2014-12-12 at 4.06.25 PM

If you ever decide to get this wireless Qi receiver, be very careful as you solder the wires as it is extremely fragile. Below, you can see how one of the plates fell off when moving the wires a bit, probably because of a little too much heat.

Screen Shot 2014-12-12 at 4.12.34 PM

In order to test if the weight would fluctuate with the use of angular momentum, precise measurements where crucial. I had to take several trips to the metal shop and use some new tools to polish the surfaces for a flat measuring area and balanced surface.

Screen Shot 2014-12-12 at 4.07.00 PM

Screen Shot 2014-12-12 at 4.06.43 PM

Below I am pushing the data to the server through socket connections with node.js.

Screen Shot 2014-12-12 at 3.20.08 AM

————————————————————————————-

Arduino Code:

#include <Bridge.h>
#include <YunClient.h>

YunClient client;
float distance;

#define SERVER_ADDRESS “10.0.1.13”
#define SERVER_PORT 5000

unsigned long postingInterval = 50; //delay between server updates
unsigned long lastPost = 0; // when you last made a request
unsigned long currTime = 0; //what time is it right now

String incomingDataString = “”; //this will hold raw incoming data string
boolean serverResponded = false;

// Accelorometer
const int groundpin = 18; // analog input pin 4 — ground
const int powerpin = 19; // analog input pin 5 — voltage
const int xpin = A3; // x-axis of the accelerometer
const int ypin = A2; // y-axis
const int zpin = A1; // z-axis (only on 3-axis models)
int yVal = 0;

//Distance sensor
int IRpin = A4;
int IRVal = 0;

//Vib Motor
int vibration = 11;

//LED’s
int ledPin = 9;
int ledPin2 = 10;
int ledPin4 = 6;
int ledPin6 = 5;

//Counter
int counter = 0;
int timer;
int startTime;
int endTime;
int trainTime;

//Data sent only if true
bool sent = false;
bool sentRom = false;

bool UPcurl = false;
bool DOWNcurl = false;

void setup() {
pinMode(vibration, OUTPUT);
pinMode(groundpin, OUTPUT);
pinMode(powerpin, OUTPUT);
digitalWrite(groundpin, LOW);
digitalWrite(powerpin, HIGH);
Serial.begin(9600);
pinMode(ledPin, OUTPUT);

Bridge.begin();
Console.begin();

client.connect(SERVER_ADDRESS, SERVER_PORT);
}

int count = 0;
int upCurl = 0;
int rom = 0;

void loop() {

Console.print(“yVal: “);
Console.print(yVal);
Console.print(“\t”);
Console.print(“distance: “);
Console.print(distance);
Console.print(“\t”);
Console.print(counter);
yVal = analogRead(ypin);

if (yVal > 490) {
DOWNcurl = true;
} else
{
DOWNcurl = false;
}

if (yVal < 360) {
upCurl = 1;
UPcurl = true;
if (client.connected() && sent == false) {
client.print(1);
sent = true;
}

} else {
upCurl = 0;

UPcurl = false;
sent = false;
}

if (UPcurl == true) {
if (counter == 0) {
startTime = millis();
}

counter = counter + 1;

if (counter > 9) {
analyze();
counter = 0;
}
analogWrite(ledPin, 255);
analogWrite(ledPin2, 255);
analogWrite(ledPin4, 255);
analogWrite(ledPin6, 255);
delay(500);
analogWrite(ledPin, 0);
analogWrite(ledPin2, 0);
analogWrite(ledPin4, 0);
analogWrite(ledPin6, 0);
}

if (DOWNcurl == true) {
analogWrite(ledPin, 255);
analogWrite(ledPin2, 255);
analogWrite(ledPin4, 255);
analogWrite(ledPin6, 255);
delay(500);
analogWrite(ledPin, 0);
analogWrite(ledPin2, 0);
analogWrite(ledPin4, 0);
analogWrite(ledPin6, 0);
}

// Distance calculation
float volts = analogRead(IRpin) * 0.0048828125;
distance = 65 * pow(volts, -1.10);

if (distance > 25 && distance < 35) {
rom = 1;
if (client.connected() && sentRom == false) {
client.print(2);
sentRom = true;
}
if (counter == 0) {
startTime = millis();
}
Serial.println(counter);
counter = counter + 1;

analogWrite(ledPin, 255);
analogWrite(ledPin2, 255);
analogWrite(ledPin4, 255);
analogWrite(ledPin6, 255);
//delay(500);

} else {
rom = 0;
sentRom = false;

analogWrite(ledPin, 0);
analogWrite(ledPin2, 0);
analogWrite(ledPin4, 0);
analogWrite(ledPin6, 0);
}

//check if it’s time to post an update to the server
currTime = millis();

if (currTime – lastPost >= postingInterval) {
if (client.connected()) {
String data = String(upCurl) + “,” + String(rom) + “\n”;
count++;
} else {
//no connection, try to make one again:
Console.println(“\nattempting to connect to server”);
client.connect(SERVER_ADDRESS, SERVER_PORT);
delay(2000); //delay 2 seconds before trying another server reconnect
}
lastPost = currTime;
}

if (serverResponded) {
Console.print(“received from server: “);
Console.println(incomingDataString);
incomingDataString = “”; //clear out our data string for next server message
serverResponded = false; //start this at false after server request
}
}

void motor(int valueLong) {
digitalWrite(vibration, HIGH);
delay(valueLong);
digitalWrite(vibration, LOW);
}

void analyze() {
endTime = millis();
trainTime = endTime – startTime;

// IF YOU DID THE EXERCISES TOO FAST, GIVE A LOONG VIBRATION TO TELL YOU TO SLOW DOWN
if (trainTime <= 13000) {
motor(3000);
}

// IF YOU DID THE EXERCISES TOO SLOWLY, GIVE A SHORT VIBRATION TO TELL YOU TO SPEED UP
if (trainTime > 25000) {
motor(500);
}
}

————————————————————————————-

For the future, I plan to build a communication platform that can be used with physical therapists in order to facilitate the monitoring of progress with patients. This platform will also be used to calibrate the device. First steps include pushing the data online, which I have done here.

One of the ways in which more functionality could be added was to use angular momentum in order to fluctuate the weight. However, this is much more difficult in practice than in theory. After have done multiple tests, I realized that in order to make the resistance high enough, you will need a strong and quick stop. This is difficult to achieve without custom high quality mechanics, as the nature of stopping such a strong force needs an even stronger resistance. The example below is a good demonstration of this.

Moreover, the vibrations that built up was difficult to control, even though I measured it as precise as I could, and built a custom holding. In order to minimize the friction and get as little resistance as possible (and so also vibration) you would need to use custom spring loaded ball bearings. Using angular momentum to fluctuate a weight is theoretically possible, but not with the resources we have here at school – unfortunately. Nevertheless, this could serve as a proof of concept for further explorations, and has been a good learning experience.

Final Project Proposal

For my final project I would like to work on prototype 0.4 for my thesis. I am developing a weight for this prototype that would allow me to further test the effectiveness of my ideas over the winter break and serve as a proof of concept.

Components

PRECEDENTS / INSPIRATION

My thesis is mainly inspired by my personal experiences with my mother as a tetraplegic and the hardships that she and fellow patients have had to go through to recover. In terms of methodology, Lygia Clark serves as a great inspiration as she balances fine art and psychotherapeutic practices. My goal is for the end product to be both very functional and practical as well as therapeutic in it’s use. Currently there are not any products that serve the tracking functionality as well as being in the form of a weight that can be part of your interior decoration, but the KettleBug is a prototype that allows you to track your progress on an external device. For additional resources and material that has lead me to this idea, please see my reading list.

 

Audio-Fabilicious / Listening to Music through Bone Conduction

Today we had a great class making our own circuit designs with chemical etching which allows for a creative, cheap and effective way of making your own circuits.

Steps:

1) We started by sketching out our designs on a piece of paper and then transferring them to a copper board with a sharpie pen.

image

2) Then we let the plates bathe in ferric chloride for about 20 minutes, allowing the chemicals to etch away the copper in a subtractive manufacturing process. The plates are dipped in alcohol to remove the acid. See the image above for the resulting circuit.

image

3) The final step is to solder the components on the circuit: two resistors, one capacitor, an audio amplifier, audio jack, battery holder and vibrational motor.

image

Kinetic Object Test / Thesis Exploration

This object is an extension of my midterm, this time testing the effectiveness of kinetic feedback to a greater extent than the origami. The design is generic purposefully in order for the user to be able to focus more on the movement. A series of user tests will be conducted as soon as possible, and the results would be able to inform the design of future iterations.

Questions I am asking are the following:

-Can an abstract object stimulate mirror neurons?

– What type of movement is the most gratifying for this specific type of exercise?

– How strongly is kinetic movement associated with the notion of life? To what extent does this object feel anthropomorphic?

– What is too much motion as feedback, when does it get annoying rather than gratifying?

Please see the circuit from the midterm, as it is the same except for the servo motors.

image

#include <Servo.h>

Servo myservo;
Servo myservo2;
Servo myservo3;

int pos = 0;

int vibration = 3;
int sensorValue = A2;
int flex = 2; //flexSensor
int counter = 0;
int timer;
int startTime;
int endTime;
int trainTime;

void setup()
{
pinMode(vibration, OUTPUT);

myservo.attach(9);
myservo2.attach(8);
myservo3.attach(7);

myservo.write(0);
myservo2.write(0);
myservo3.write(0);

Serial.begin(9600);
}

void loop() {

// read the input on analog pin 0:
sensorValue = analogRead(flex);
Serial.println(sensorValue);
// print out the value you read:

delay(1); // delay in between reads for stability

// if (sensorValue > 240 && sensorValue < 245)
if (sensorValue < 400) {
if (counter == 0) {
startTime = millis();
}

Serial.println(counter);

counter = counter + 1;

delay(1000);

if (counter > 9) {
analyze();
//motor();
//Serial.println(“moootooor”);
counter = 0;
}
}
}

void analyze(){
endTime = millis();
trainTime = endTime – startTime;
Serial.println(trainTime);
if(trainTime <= 4000){
motor(3000);
Serial.println(“FLEEEXINOOOL”);

for (pos = 0; pos <= 180; pos += 1)
{
myservo.write(pos);
myservo3.write(pos);
delay(5);
}
for (pos = 180; pos >= 0; pos -= 1)
{
myservo.write(pos);
myservo3.write(pos);
delay(5);
}
}

if(trainTime > 4000 && trainTime < 5000){
motor(1000);
delay(1000);
motor(1000);
Serial.println(“FLEEEXINOOOL”);

for (pos = 0; pos <= 180; pos += 1)
{
myservo.write(pos);
myservo2.write(pos);
myservo3.write(pos);
delay(20);
}
for (pos = 180; pos >= 0; pos -= 1)
{
myservo.write(pos);
myservo2.write(pos);
myservo3.write(pos);
delay(20);
}

for (pos = 0; pos <= 180; pos += 1)
{
myservo.write(pos);
myservo2.write(pos);
myservo3.write(pos);
delay(20);
}
}
if(trainTime > 5000){
motor(100);
delay(1000);
motor(100);
Serial.println(“FLEEEXINOOOL”);

for (pos = 0; pos <= 180; pos += 1)
{
myservo.write(pos);
delay(25);
}
for (pos = 180; pos >= 0; pos -= 1)
{
myservo.write(pos);
delay(25);
}
}
}
void motor(int valueLong) {
digitalWrite(vibration, HIGH);
delay(valueLong);
digitalWrite(vibration, LOW);
}

 

 

 

 

 

 

Midterm / Haptic Feedback + Visual Feedback User Test For Physical Rehabilitation

CONCEPT

The machines designed for motor rehabilitation are aesthetically unpleasant and often not engaging or stimulating to the patient. I am interested in exploring the areas of healthcare and rehabilitation through art and new technologies in order to five people with motor challenges better health through inclusive design and interactive experiences. Rehabilitation is a slow and boring process, so how can the algorithm behind the interaction I am creating suggest a more engaging process?

I am currently researching the domains of motivation, agency and especially self-efficacy. What would keep my user from loosing interest? How is kinetic movement rewarding? How does externalization affect stress? How can haptic feedback be utilized to enhance muscle memory? My entire concept is grounded in my users experience, practically approaching the problems that people with disabilities face. I am particularly focusing on people that are very physically restrained – to the extent that even jumping on a wheelchair is exhausting.

For my midterm, I needed to prototype the experience with my peers in order to send out a package to different healthcare facilities in order to consult a specialist and ideally work with them for future prototyping. I conducted a short User Test Questionnaire in conjunction with the test, and below are some of my key insights:

  • Vibrational feedback needs to be more clear, not using time but rather number of vibrations to indicate if you have done the exercises too slow/fast.
  • People generally found the feedback to be helpful/rewarding/important, and would like to see this as a developed product.
  • People did not pay so much attention to the visual feedback, and where more focused and grateful for the haptic feedback.

PROTOTYPE

The piece is based on a simple exercise routine: the bicep curl. Often times, it is difficult for people to stay with their routines, especially when highly disabled and check-ins with physical therapists are scarce. In this instance, haptic feedback lets you know if you have done the basic routine of ten bicep curls within the right time frame by giving you one long vibration. Two short tells you that you’ve done them too fast, and two long ones too slow. The origami works as a supplement in lifting all of it’s legs if you have done it right, and only some of them if wrong, simply to test the viability of visual stimuli in a simple way.

HapticFeedback

Screen Shot 2014-10-24 at 12.19.07 PM

Screen Shot 2014-10-24 at 12.19.55 PM

Screen Shot 2014-10-24 at 12.18.46 PM

Screen Shot 2014-10-24 at 12.18.31 PM

 

/*
VIBRATIONAL FEEDBACK BASED ON IF YOU HAVE DONE YOUR BICEP ROUTINES CORRECTLY. MOREOVER, YOU WILL SEE ORIGAMI MOVE AS FEEDBACK.
BY FABIOLA EINHORN FALL 2014 FOR THESIS AND PHYSICAL COMPUTING
*/

int vibration = 6;
int sensorValue = 0;
int flex = A3;
int counter = 0;
int timer;
int startTime;
int endTime;
int trainTime;
int flexinolA = 2;
int flexinolB = 3;
int flexinolC = 4;
int flexinolD = 5;

void setup() {
pinMode(vibration, OUTPUT);
pinMode(flexinolA, OUTPUT);
pinMode(flexinolB, OUTPUT);
pinMode(flexinolC, OUTPUT);
pinMode(flexinolD, OUTPUT);

Serial.begin(9600);
}

void loop() {
//Serial.println(sensorValue);
sensorValue = analogRead(flex);

delay(1); // delay in between reads for stability

if(sensorValue == 300){
if(counter == 0){
startTime = millis();
}

Serial.println(counter);
Serial.println(sensorValue);

counter = counter + 1;

delay(1000);

}

if(counter > 3){
analyze();
counter = 0;
}
}

void analyze(){
endTime = millis();
trainTime = endTime – startTime;
Serial.println(trainTime);

// IF YOU DID THE EXERCISES TOO FAST, GIVE TWO SHORT VIBRATIONS

if(trainTime <= 15000){
motor(500);
delay(1000);
motor(500);
Serial.println(“FLEEEXINOOOL”);

digitalWrite(flexinolA, HIGH);
delay(2000);
digitalWrite(flexinolA, LOW);

digitalWrite(flexinolC, HIGH);
delay(2000);
digitalWrite(flexinolC, LOW);
}

// IF YOU DID THE EXERCISES CORRECTLY, GIVE ONE LONG VIBRATION

if(trainTime > 15000 && trainTime < 25000){
motor(2000);
Serial.println(“FLEEEXINOOOL”);

digitalWrite(flexinolA, HIGH);
delay(2000);
digitalWrite(flexinolA, LOW);

digitalWrite(flexinolB, HIGH);
delay(2000);
digitalWrite(flexinolB, LOW);

digitalWrite(flexinolC, HIGH);
delay(2000);
digitalWrite(flexinolC, LOW);

digitalWrite(flexinolD, HIGH);
delay(2000);
digitalWrite(flexinolD, LOW);
}
// IF YOU DID THE EXERCISES TOO SLOWLY, GIVE TWO LONG VIBRATIONS
if(trainTime > 25000){
motor(2000);
delay(1000);
motor(2000);
Serial.println(“FLEEEXINOOOL”);

digitalWrite(flexinolC, HIGH);
delay(2000);
digitalWrite(flexinolC, LOW);

digitalWrite(flexinolD, HIGH);
delay(2000);
digitalWrite(flexinolD, LOW);
}

}

void motor(int valueLong) {
digitalWrite(vibration, HIGH);
delay(valueLong);
digitalWrite(vibration, LOW);
}

 

 

Dust Sensor Output LOL Shield

I decided to use the dust sensor again to question how a more emotional visual feedback using the LOL shield could potentially change behavior over time. As I was thinking of doing a dust painting originally for my thesis, this serves as a good prototype testing the validity of that idea. Sending data from one Yun to another allows you to separate the  dustsensor and the LED display so that a friend can monitor your smoking habits or alternatively you can monitor another room and place the sensor where you think it best fits. A sad face signifies levels over 400, meaning there is someone smoking in the room. A normal face means that you could improve by cleaning, a happy face means great values. I plan to encase this (unfortunately the laser cutting lab was fully booked the moment I realized the idea) and give it as a birthday present to my friend that has asthma. She has roommates that never clean and is now able to use these values to communicate to them better. She is also trying to quit smoking.

The code below reads the dust values and outputs a 0, 1 or 2 depending on the parameters. This was needed as Arduino does not understand the char and only reads in ints.

#include <Bridge.h>
#include <HttpClient.h>
// set up net client info:
const unsigned long postingInterval = 10; //delay between updates to sparkfun and xively.com
unsigned long lastRequest = 0; // when you last made a request
String dataString = “”;

int dustPin = 0;
int dustVal = 0;
int redVal = 0;
int blueVal = 0;
int greenVal = 0;

#define RED 3
#define GREEN 5
#define BLUE 6

int ledPower = 2;

int delayTime = 280;

int delayTime2 = 40;

float offTime = 9680;
void setup() {
// start serial port:
Bridge.begin();
Console.begin();
// Do a first update immediately
updateData();
sendData();
lastRequest = millis();

Serial.begin(9600);

pinMode(GREEN, OUTPUT);
pinMode(BLUE, OUTPUT);
pinMode(RED, OUTPUT);
digitalWrite(GREEN, HIGH);
digitalWrite(BLUE, HIGH);
digitalWrite(RED, HIGH);
pinMode(ledPower, OUTPUT);
pinMode(4, OUTPUT);
}

void loop() {

// get a timestamp so you can calculate reading and sending intervals:
long now = millis();

// if the sending interval has passed since your
// last connection, then connect again and send data:
if (now – lastRequest >= postingInterval) {
updateData();
sendData();
lastRequest = now;
}

digitalWrite(BLUE, 255); // turn the LED off by making the voltage LOW
digitalWrite(GREEN, 255); // turn the LED off by making the voltage LOW
digitalWrite(RED, 255); // turn the LED off by making the voltage LOW

// ledPower is any digital pin on the arduino connected to Pin 3 on the sensor

if (dustVal < 224) {
digitalWrite(BLUE, 0);
delay(1000); // wait for a second
}

if (dustVal > 225 && dustVal < 500) {
digitalWrite(GREEN, LOW); // turn the LED off by making the voltage LOW
delay(1000);
}

if (dustVal > 501) {
digitalWrite(RED, 0);
delay(1000); // wait for a second
}

digitalWrite(ledPower, LOW); // power on the LED
delayMicroseconds(delayTime);
dustVal = analogRead(dustPin); // read the dust value via pin 5 on the sensor
delayMicroseconds(delayTime2);
digitalWrite(ledPower, HIGH); // turn the LED off
delayMicroseconds(offTime);

delay(150);

Serial.println(dustVal);

}

void updateData() {
// convert the readings to a String to send it:
dataString = “dustval=”;
dataString += dustVal;
// dataString += random(0-600);
}
// this method makes a HTTP connection to the server:
void sendData() {
// form the string for the API header parameter:
// form the string for the URL parameter:
String url = “”;
Console.println(dustVal);
if (dustVal < 300) {
url = “http://technoshaman.noip.me:3000/input/eqR0gB1wPXHGlzePZQDqt7El4VZ?private_key=WEoGXwZORrUV3XaL6lNbixNEY5r&dustval=0″;
}if (dustVal >= 300 && dustVal < 400) {
url = “http://technoshaman.noip.me:3000/input/eqR0gB1wPXHGlzePZQDqt7El4VZ?private_key=WEoGXwZORrUV3XaL6lNbixNEY5r&dustval=1″;
} if(dustVal >= 400) {
url = “http://technoshaman.noip.me:3000/input/eqR0gB1wPXHGlzePZQDqt7El4VZ?private_key=WEoGXwZORrUV3XaL6lNbixNEY5r&dustval=2″;
}

//url += dustVal;
// Send the HTTP GET request

HttpClient client;
HttpClient client2;
//Process xively;
//Console.print(“\n\nSending data… “);
//Console.println(url);
client.get(url);

delay(1000);
// If there’s incoming data from the net connection,
// send it out the Console:
while (client.available()) {
char c = client.read();
//Console.println(c);
}
Console.flush();

// Serial.println(dustVal);

}

The code below receives the data and outputs it with Chalieplexing. Unfortunately the delays needed for an animation slowed down the communication significantly over the server, so I was only able to do static animations.

#include <Bridge.h>
#include <HttpClient.h>
#include <Console.h>
#include <Charliplexing.h>
byte line = 0; //Row counter
char buffer[10];
int value;

void setup() {
pinMode(13, OUTPUT);
digitalWrite(13, LOW);
Bridge.begin();
digitalWrite(13, HIGH);
LedSign::Init();
//Serial.begin(9600);
Console.begin();
}

void loop() {
HttpClient client;
client.get(“http://technoshaman.noip.me:3000/output/eqR0gB1wPXHGlzePZQDqt7El4VZ/dustval/latest.csv”);

while (client.available()) {
char c = client.read() ;
//drawBitmapOk();
Console.write(c);
if (c == ‘0’) {
drawBitmapSmile();
}if (c == ‘1’) {
drawBitmapOk();
}if(c == ‘2’) {
drawBitmapSad();
}
Console.flush();
delay(1000);
}
}

void DisplayBitMap(int lineint)
{
//int data[9] = {95, 247, 123, 511, 255, 1, 5, 31, 15};
//for(line = 0; line < 9; line++) {
for (byte led = 0; led < 14; ++led) {
if (lineint & (1 << led)) {
LedSign::Set(led, line, 1);
} else {
LedSign::Set(led, line, 0);
}
}
line++;
if (line >= 9) line = 0;
}

void drawBitmapOk() {
delay(100);
DisplayBitMap(0);
DisplayBitMap(816);
DisplayBitMap(816);
DisplayBitMap(816);
DisplayBitMap(0);
DisplayBitMap(0);
DisplayBitMap(2040);
DisplayBitMap(0);
DisplayBitMap(0);
}
void drawBitmapSad() {
delay(100);
DisplayBitMap(0);
DisplayBitMap(816);
DisplayBitMap(816);
DisplayBitMap(816);
DisplayBitMap(0);
DisplayBitMap(0);
DisplayBitMap(1008);
DisplayBitMap(1032);
DisplayBitMap(0);
}
void drawBitmapSmile() {
delay(100);
DisplayBitMap(0);
DisplayBitMap(816);
DisplayBitMap(816);
DisplayBitMap(816);
DisplayBitMap(0);
DisplayBitMap(1032);
DisplayBitMap(528);
DisplayBitMap(480);
DisplayBitMap(0);
}

 

Sensor Data Online

For this week, since I already used a sensor, I wanted to transfer the data online in order to track the data for the air quality headphones that we are building. The goal is to be able to map where the air quality is the best through your smartphone. Below you can see a UX chart of the product outcome as well as a preliminary technical diagram.

UXdiagram

Signal-Chain

I used the Arduino Yun to get the data online, which was easy as I just needed to transfer it to the other board. What took time was getting the Yun connected to the internet (it’s a little janky) and tweaking the code for it to get the values online via Sparkfun.  Now you can see the values in my stream.

#include <Bridge.h>
#include <HttpClient.h>
#include “passwords.h”

// set up net client info:
const unsigned long postingInterval = 10; //delay between updates to sparkfun and xively.com
unsigned long lastRequest = 0; // when you last made a request
String dataString = “”;

int dustPin = 0;
int dustVal = 0;
int redVal = 0;
int blueVal = 0;
int greenVal = 0;

#define RED 3
#define GREEN 5
#define BLUE 6

int ledPower = 2;

int delayTime = 280;

int delayTime2 = 40;

float offTime = 9680;
void setup() {
// start serial port:
Bridge.begin();
Console.begin();

while (!Console); // wait for Network Serial to open
Console.println(“data.sparkfun client”);

// Do a first update immediately
updateData();
sendData();
lastRequest = millis();
Serial.begin(9600);

pinMode(GREEN, OUTPUT);
pinMode(BLUE, OUTPUT);
pinMode(RED, OUTPUT);
digitalWrite(GREEN, HIGH);
digitalWrite(BLUE, HIGH);
digitalWrite(RED, HIGH);
pinMode(ledPower, OUTPUT);
pinMode(4, OUTPUT);
}

void loop() {

// get a timestamp so you can calculate reading and sending intervals:
long now = millis();

// if the sending interval has passed since your
// last connection, then connect again and send data:
if (now – lastRequest >= postingInterval) {
updateData();
sendData();
lastRequest = now;
}

digitalWrite(BLUE, 255); // turn the LED off by making the voltage LOW
digitalWrite(GREEN, 255); // turn the LED off by making the voltage LOW
digitalWrite(RED, 255); // turn the LED off by making the voltage LOW

// ledPower is any digital pin on the arduino connected to Pin 3 on the sensor

if (dustVal < 224) {
digitalWrite(BLUE, 0);
delay(1000); // wait for a second
}

if (dustVal > 225 && dustVal < 500) {
digitalWrite(GREEN, LOW); // turn the LED off by making the voltage LOW
delay(1000);
}

if (dustVal > 501) {
digitalWrite(RED, 0);
delay(1000); // wait for a second
}

digitalWrite(ledPower, LOW); // power on the LED
delayMicroseconds(delayTime);
dustVal = analogRead(dustPin); // read the dust value via pin 5 on the sensor
delayMicroseconds(delayTime2);
digitalWrite(ledPower, HIGH); // turn the LED off
delayMicroseconds(offTime);

delay(150);

Serial.println(dustVal);

}

void updateData() {
// convert the readings to a String to send it:
dataString = “dustval=”;
dataString += dustVal;
// dataString += random(0-600);
}
// this method makes a HTTP connection to the server:
void sendData() {
// form the string for the API header parameter:
// form the string for the URL parameter:
String url = “http://data.sparkfun.com/input/”;
url += FEEDID;
url += “?private_key=”;
url += APIKEY;
url += “&”;
url += dataString;

// Send the HTTP GET request

HttpClient client;
//Process xively;
Console.print(“\n\nSending data… “);
Console.println(url);
client.get(url);
Console.println(“done!”);

// If there’s incoming data from the net connection,
// send it out the Console:
while (client.available()) {
char c = client.read();
Console.print(c);
}
Console.flush();

}

Blink Homework / Fabiola

I decided to hook up the Sharp optical dust sensor that I bought from Sparkfun last week, to visualize the invisible through a wonderful little LED. This might lead to a “dust painting” that I wanted to make so that people with asthma can in a more aesthetically pleasing way be aware of their air quality in the home and get motivated to keep their space clean. However, through my exploration, I realized that it’s very difficult to motivate though a passive object that lives separately from you. So why not bring it closer to the body? If I succeed in miniaturizing the electronics, I would love to develop this into some sort of dust earring that lights up when the air around you is poor, in the form factor of a water drop in glass.

The sensor did not come with the appropriate cables, so order them as well if you are thinking about using the device. The output surface is very small, and although I could solder it, I was afraid to destroy the device so copper tape became my temporary solution.

Screen Shot 2014-09-11 at 11.38.06 PM

I started by looking at the spec sheet, but it didn’t give a rookie too much information so scattered the internet for a good tutorial. I ended up following this one,  and had some problems following the schematic at first, but with some help it became apparent that some of the symbols in the schematic are not universal.

For the schematics below I used a placeholder for the dust sensor since it is not available in Fritzing, and neither could I find a download.

Screen Shot 2014-09-24 at 4.46.38 PM

Screen Shot 2014-10-31 at 3.20.35 PM

Screen Shot 2014-10-31 at 3.22.22 PM

As you can see I’m using a different connector in place of the dust sensor. The image below will give you a better understanding of how to hook it up.

Dust

Below is a test with the sensor in D12, set to blink every time the value hits over 225.

I was surprised by the accuracy actually, and found this article comparing a pretty advanced system with good results. I also discovered that D12 has much better air quality than my apartment.

Update: Now the RGB LED works! Blue equals best air quality (0-225), green equals ok quality (225-500) and red equals bad quality (500 and above). Below I’m blowing smoke over it.

// Code slightly modified from this tutorial.

int dustPin=0;
int dustVal=0;
int redVal = 0;
int blueVal = 0;
int greenVal = 0;

#define RED 3
#define GREEN 5
#define BLUE 6

int ledPower=2;

int delayTime=280;

int delayTime2=40;

float offTime=9680;
void setup(){
Serial.begin(9600);

pinMode(GREEN, OUTPUT);
pinMode(BLUE, OUTPUT);
pinMode(RED, OUTPUT);
digitalWrite(GREEN, HIGH);
digitalWrite(BLUE, HIGH);
digitalWrite(RED, HIGH);
pinMode(ledPower,OUTPUT);
pinMode(4, OUTPUT);
}

void loop(){

digitalWrite(BLUE, 255); // turn the LED off by making the voltage LOW
digitalWrite(GREEN, 255); // turn the LED off by making the voltage LOW
digitalWrite(RED, 255); // turn the LED off by making the voltage LOW

// ledPower is any digital pin on the arduino connected to Pin 3 on the sensor

if (dustVal < 224) {
digitalWrite(BLUE, 0);
delay(1000); // wait for a second
}

if (dustVal > 225 && dustVal < 500) {
digitalWrite(GREEN, LOW); // turn the LED off by making the voltage LOW
delay(1000);
}

if (dustVal > 501) {
digitalWrite(RED, 0);
delay(1000); // wait for a second
}

digitalWrite(ledPower, LOW); // power on the LED
delayMicroseconds(delayTime);
dustVal=analogRead(dustPin); // read the dust value via pin 5 on the sensor
delayMicroseconds(delayTime2);
digitalWrite(ledPower,HIGH); // turn the LED off
delayMicroseconds(offTime);

delay(150);

Serial.println(dustVal);
}

 

Introduction / Fabiola Einhorn

10173596_10154030595790061_467752050_n

Fabiola here, originally from Sweden with a background in creative strategy, I got my BFA in San Francisco and later moved to NYC for a job in advertising. As the whole selling thing got a little boring (although I love the cultural research and respect the craft of advertising), I needed room for more creative tinkering, which brought me here. I have recently been enjoying p-comp a lot, and aim to develop products that benefit rehabilitation through art for my thesis.

I have most recently been inspired by Lygia Clark, who did a series of pioneering propositions related to psychotherapy and art. Her methodologies relate to my thesis research in that I would like my end products to be both artistic and therapeutic or semi-utilitarian in some aspects. She recently had a retrospective at the MOMA that I unfortunately missed. If anyone went to it, please let me know and we can have a chat!

Máscaras Sensorias (1967)

b464c4e136c6d002af743b7221b42157