Sunday, June 13, 2010

Reflective Statement

During the initial concept development, I was interested in the opportunity to take advantage of the ability offered by Pachube to access data from various external locations. Where I initially had no specific ideas as to what I wanted to create, I was wanting to experiment with creating a system that took passive input rather than direct input from a moving point (i.e. attached to a person) and taking the data to describing and analyze a situation related to the movement and then making decisions based on the available data to control some aspect of a fixed point.

Our final concept in the end was related to ideas around conservation and energy, simply, theoretically there wasn't enough power for all four of us to have our lights switched on so you were penalized for the amount of time you had your light on and how bright it was. It has a lot more validity when taken into the context of modern day society where the commodities which are the source of power and electricity are so highly sought after. Many people in third world countries and even lower socio economic communities often have to go without the simple things we take for granted, such as, flipping on a light switch.

I was involved in this project in the conceptual development, programming, planning of the construction of the physical housing and the undertaking of the project itself. I had a hands on role in programming, specifically in trying to get Processing, Arduino and Patchube to communicate. I found I had enough knowledge from learning Arduino this year and Processing this year to be able to confidently approach problems and devise methods of troubleshooting.

Where we had devised two methods of trying to control the servo with Processing, I was working with Seamus to develop the method using serial communication. Towards the end, we were experimenting with both variations and it was good that we had explored both avenues as we were able to see which one worked more successfully. I felt we all learnt more this way as we were able to achieve twice as much.

Our final result wasn't fully resolved but was a fair representation of what we were trying to achieve. The first time I had my light switched off, it was a shock that it was actually real; the concept of having your light switched on and off, out of your control, was very different from it actually physically happening. There are many aspects of both the physical construction and programming aspects that could still be improved but the concept itself I definitely feel came across.

I've learnt a lot during this project, not just in technical skills but in having to adapt to the limitations of our technical skills, budget and available information in order to stick to our concept and what could be defined as , a 'smart' system. I feel we were able to tap into the potential of Patchube, even where our physical components were fairly simple. All the elements, physical and digital, we integrated into our final product I feel were relevant and it took a real team effort to bring it all together.

Saturday, June 12, 2010

Light Sharing

Another Saturday at uni and we were aiming to finish up our coding. It was decided that we needed a way to 'opt out' or 'log out' of the system in such a way that it continued running with three people. So the button came back into our system.

It seemed fairly simple, implemented on a local level inside the Arduino sketch. The Arduino reads the button state (digital input 1 or 0) and the button state determines what it send to the serial monitor.

if (offSwitch==1){
Serial.println(timer);
} else {
Serial.println(0);
}

If your button is pushed (button state 1), you're in the system and it sends your penalty / timer / LDR value to serial as usual.

If your button is not pushed (button state 0), you've opted out of the system so it sends back a zero. Hence, your value will always be lower than everyone else's, effectively removing you from the system.

By the time Sunday evening rolled around for the final system, we were using a final hybrid code of both methods we'd worked with, individualized for each user.

import processing.serial.*;
import eeml.*;
import cc.arduino.*;
import pachuino.*;

Pachuino p;
DataOut dOut;

float timer, scaledLDR;
float on_off;
float lastUpdate;
float jacquesLDR;
float tapaniLDR;
float seamusLDR;
float juditLDR;

PImage img;


void setup()
{
p = new Pachuino(this, Arduino.list()[0], 57600);
p.manualUpdate("http://www.pachube.com/api/7584.xml");
p.setKey("API");

dOut = new DataOut(this, "http://www.pachube.com/api/feeds/7584.xml",
"API");
dOut.addData(2,"CombinedLDR");

p.addRemoteSensor("http://www.pachube.com/api/7339.xml", 2); // tapani ldr
p.addRemoteSensor("http://www.pachube.com/api/7472.xml", 2); // seamus ldr
p.addRemoteSensor("http://www.pachube.com/api/7344.xml", 2); // jacques ldr

p.addLocalSensor("analog", 1, "ldr");
p.addLocalSensor("digital", 2, "on_off");

size(600,581);
background(255);
}


void draw()
{
juditLDR = p.localSensor[0].value;
on_off = p.localSensor[1].value;
tapaniLDR = p.remoteSensor[0].value;
seamusLDR = p.remoteSensor[1].value;
jacquesLDR = p.remoteSensor[2].value;

dOut.update(0, timer);
int response = dOut.updatePachube();

if ((millis() - lastUpdate) > 5000)
{
lastUpdate = millis();
if (on_off > 10)
{
timer = timer + 1;
scaledLDR = juditLDR/100;
timer = timer + scaledLDR;
delay(1000);
if (timer > seamusLDR && timer > tapaniLDR && timer > jacquesLDR)
{
img = loadImage("judit.jpg");
image (img,0,0);
println("judit = " + timer);
println("seamus = " + seamusLDR);
println("tapani = " + tapaniLDR);
println("jacques = " + jacquesLDR);
p.analogWrite(9, 1);
println("off");
delay(500);
p.analogWrite(9, 0);
}
else if (seamusLDR > timer && seamusLDR > tapaniLDR && seamusLDR > jacquesLDR)
{
img = loadImage("mus.jpg");
image (img,0,0);
println("judit = " + timer);
println("seamus = " + seamusLDR);
println("tapani = " + tapaniLDR);
println("jacques = " + jacquesLDR);
p.analogWrite(9, 250);
println("on");
delay(500);
p.analogWrite(9, 0);
}
else if (jacquesLDR > timer && juditLDR > tapaniLDR && juditLDR > seamusLDR)
{
img = loadImage("jaak.jpg");
image (img,0,0);
println("judit = " + timer);
println("seamus = " + seamusLDR);
println("tapani = " + tapaniLDR);
println("jacques = " + jacquesLDR);
p.analogWrite(9, 250);
println("on");
delay(500);
p.analogWrite(9, 0);
}
else if (tapaniLDR > timer && tapaniLDR > jacquesLDR && tapaniLDR > seamusLDR)
{
img = loadImage("tap.jpg");
image (img,0,0);
println("judit = " + timer);
println("seamus = " + seamusLDR);
println("tapani = " + tapaniLDR);
println("jacques = " + jacquesLDR);
p.analogWrite(9, 250);
println("on");
delay(500);
p.analogWrite(9, 0);
}
else
{
println("judit = " + timer);
println("seamus = " + seamusLDR);
println("tapani = " + tapaniLDR);
println("jacques = " + jacquesLDR);
p.analogWrite(9, 250);
println("on");
delay(500);
p.analogWrite(9, 0);
}
}
else
{
println("judit = " + 0);
println("seamus = " + seamusLDR);
println("tapani = " + tapaniLDR);
println("jacques = " + jacquesLDR);
p.analogWrite(9, 1);
println("off");
delay(500);
p.analogWrite(9, 0);
}
}
}


void onReceiveEEML(DataIn d)
{
p.updateRemoteSensors(d);
}

Essantially, each user uploads to a seperate Pachube feed their 'penalty' value which is accrued based on a calculation of how long they've had their light on and how bright the light. The other users' penalty values are read from the feeds and compared locally on each user's computer. If ones local value is greater than all the external values, the local servo physically switches the light switch off.

Time came to run everything offsite. I successfully managed to attach my device to my light switch so that the servo was able to flip the switch.

Once we were all online, we communicated via Skype conference and let the program run.

We ran a few tries and overall, I would say that it worked successfull. The first time my light got switched off, it was both a shock and a thrill. It was an incredible feeling that what we'd been planning and envisaging was actually physically occuring. I was actually sitting in the dark with no control over what had just happened. It was amazing.

Inevitably we did encounter problems. From the very first trial, it was evident that Jacques penalty value was racing ahead. After ruling out the more obvious potential causes such as minor multiplication errors in the coding or faulty wiring, we took it as a malfunctioning LDR and he replaced it with another, smaller, LDR.

The biggest issue we encountered was still with the delay in update times. Even though with the confidence of being whitelisted for higher data usage allowance on Pachube, it wasn't until the third trial we set the data update time from 5 seconds down to 1 second. The issue here was that where our local data was updating every second, often the data being updated from Pachube wasn't perfectly up to date so sometimes we would have multiple people with their lights off. This was caused by a leapfrogging effect when values were very close together, at times my light would be switched on an off several times in the space of a few seconds.

This was most evident when we began using webcams to commmunicate and could actually see who had their light on or off. However, I argue that if this system were applied over a longer period of time and we weren't actually in direct communication with each other, all we would be aware of is our own light. In fact, the system actually worked more successfully with a slightly longer update time, such as 2.5 seconds.

One important part of the coding which had gotten left out somehow was that you weren't supposed to accrue value when your light was off. This also contributed to the leapfrogging effect as users were still accruing penalty points when their light was off. We tried to fix this on the fly by setting a threshold for minimum amount of light required to accrue value.

We ran the code several times by between about 8pm-9:30 and it was amazing that it had all actually come together and, on the whole, worked as we had intended.

Wednesday, June 9, 2010

Construction

For our actual physical device, we'd envisaged a cowling made from the housing of an actual light switch which could sit over any existing switch. It would block physical access to the switch itself so that the position of the switch could only be altered by the servo which was controlled by the system.

Where we were originally going to have a second switch inside this housing (as an input to the system) it has now been replaced simply with the LDR. It is imporant we all use the same LDRs so our values are consistent.

We experiemented with possible attachment onto the servos we were using so it would be physically possible to flip the switch. We had a look through the components of Lego Mindstorm NXT kits, thinking we could possibly use the wheels but these proved to be too big. A bottle cap actually was the right sort of shape and size but it was difficult to attach it to the servo in a way that was solid and stable enough.

The image below on the right shows the protoype as viewed from the back - the side that would be sitting flush with the wall / the existing light switch. When the servo turns, it physically flips the switch, hence switching the light off or on. The front of the housing where normally a switch would sit was the right size for a larger LDR so aesthetically it looked neat and covered up the mechanism, making it a bit more mysterious.



Unfortunately there wasn't enough room to contain the Arduino as well but in any case we still have to have it plugged into the laptop so it can upload to Pachube so we willl need to have wires running out of the housing in any case. Potentially if we were to ever revisit and develop this, we could build a housing which could contain the Arduino and a power supply as well, wirelessly transmit data via bluetooth or WiFi.

Monday, June 7, 2010

Penalties

After another round of discussion and brainstorm, we finally seemed to have found a feasible solution. Combining the successful mechanism and serial communication achieved by myself and Seamus (bypassing the use of Firmata using the Handshake method) and the successful protocol of comparing LDR readings figured out by Tapani and Jacques, it suddenly started to make sense.



Use of the button had become redundant so we removed it completely, hence the system would be completely autonomous making decisions for itself based on a combination of LDR readings and time. Essentially, each user receives a penalty for how much light they have and how long they've had it on for. For example:


- Seamus has quite a dim light reading around 300 so each second he has his light on, he receives a penalty of 1, plus a 1% value of his LDR reading. So each second, he accumulates 1.3 points.

- Tapani has a really bright light reading around 1000 so each second his light is on, he received a penalty of 1, plus a 1% value of his LDR reading. So each second, he accumulates 2 points.

These penalty values from each user are uploaded to a Pachube feed and each other users' values are retrieved. The values are compared locally and whoever has the highest penalty points has their light switched off.

Furthermore, Jacques had his light switched off so his LDR reading is below a set minimum threshold of 100 so he stops accruing penalty points.


So, essentially:


The process of sending & receiving from Pachube is taken from the method we tried using Pachuino but using instead a further adaptation of the handshake code.

Arduino takes care of the penalty calculation and timer which it then sends to serial:

/*
Sensor Reader
Language: Wiring/Arduino

Reads two analog inputs and one digital input
and outputs their values.
Connections:
analog sensors on analog input pins 0 and 1
switch on digital I/O pin 2
*/

float timer, LDRvalue, scaledLDR;

int sensorValue = 0; // reading from the sensor
int servoControl;

#include
Servo myservo;
//int pos = 0;

void setup() {
// configure the serial connection:
Serial.begin(9600);
// configure the digital input:

myservo.attach(9);

establishContact();
}


void loop() {

// read the sensor:
LDRvalue = analogRead(1);

if (LDRvalue > 100){
scaledLDR = LDRvalue/100;
timer = timer + scaledLDR;
delay(1000);

}


if (Serial.available() > 0) {
// read the incoming byte:
int inByte = Serial.read();
Serial.println(timer);

if(inByte == 66){
myservo.write(180);
}

if(inByte == 67){
myservo.write(0);
}
}
}

void establishContact() {
while (Serial.available() <= 0) { Serial.println("hello"); // send a starting message delay(300); } }


Processing reads the value from serial as a string, converts it to an integer and then uploads it to Pachube. Simultaneously it also reads the value from the three other feeds and compares the value. Once it has compared the values, it adjusts the state of the servo by sending back to Arduino through serial a 'B' or a 'C'.

/*
Serial String Reader
Language: Processing

Reads in a string of characters from a serial port until
it gets a linefeed (ASCII 10). Then splits the string into
sections separated by commas. Then converts the sections to ints,
and prints them out.

Original code by Tom Igoe
*/

import processing.serial.*; // import the Processing serial library
Serial myPort; // The serial port

boolean firstContact = false; // Whether we've heard from the microcontroller
boolean controlServo = false;

//setup for pachube recieving
import eeml.*;
DataIn dIn;
float myVariable;

//setup for pachube sending
DataOut dOut;
float lastUpdate;
int buttonState =0;


void setup() {

// List all the available serial ports
println(Serial.list());
myPort = new Serial(this, Serial.list()[0], 9600);
myPort.bufferUntil('\n');


dIn = new DataIn(this,"http://www.pachube.com/api/feeds/7472.xml",
"API", 7000);


dOut = new DataOut(this, "http://www.pachube.com/api/feeds/7584.xml",
"7495f20ef1f5da0b1a40dae277c042c33018cf26cb16c33a3be4e3cf789d9c39");
dOut.addData(2,"button");

}

void draw() {
background(255);
}



void serialEvent(Serial myPort) {
// read the serial buffer:
String myString = myPort.readStringUntil('\n');
// if you got any bytes other than the linefeed:
if (myString != null) {

myString = trim(myString);

// if you haven't heard from the microncontroller yet, listen:
if (firstContact == false) {
if (myString.equals("hello")) {
myPort.clear(); // clear the serial port buffer
firstContact = true; // you've had first contact from the microcontroller
myPort.write('A'); // ask for more
//println(firstContact);
}
}
// if you have heard from the microcontroller, proceed:
else {

float recievedData = new Float(myVariable);
float myData = new Float(myString);

//println(recievedData);
//println(myData);
if (myData > recievedData){
myPort.write("B");
println("Judit");
} else {
myPort.write("C");
println("Seamus");
}


//send data to pachube
if ((millis() - lastUpdate) > 7000){


println("ready to POST: ");
dOut.update(0, myString); // update the datastream
int response = dOut.updatePachube(); // updatePachube() updates by an authenticated PUT HTTP request
println(response); // should be 200 if successful; 401 if unauthorized; 404 if feed doesn't exist
lastUpdate = millis();
}
}
}


// when you've parsed the data you have, ask for more:
myPort.write("A");
}

void onReceiveEEML(DataIn d){
myVariable = d.getValue(4); // get the value of the stream 1

}

When we set this up with two of us, it seemed to work so the next step is to set it up with all four of us. If this too runs successfully, we are ready to run it off site.

Finally, the other obstacle we've had to overcome has been in regards to API usage. The limits of Pachube only enable data to be accessed (sent or received) 50 times every 3 minutes (on average once every 3.6 seconds). We felt extremely limited by this as it meant that the more feeds we were accessing, the longer delay we'd have to implement. Many times we received warnings that we'd exceeded this limit so we sent a request to be whitelisted to allow for greater usage allowance. Amazingly, this was granted!

Friday, June 4, 2010

Ifs and Loops

The biggest issue we face now in our intended Smart Systems is configuring a complicated series of loops / 'if' statements that would decide and determine whose light was on and off.

Our original protocol was that if three people had lights on and the fourth person wanted light too, the person who had the most amount of light in their environment (determined by value of LDR) would have their light switched off.


Alternatively, the person whose light had been on for the longest amount of time. We had known from the start that this would be a difficult system to program but decided to pursue it. I devised a diagram to figure out what possible combination of light were possible (15 in total) and wrote a very simple sketch in processing where two ellipses could be made to appear and disappear using the letters 'a' and 's' and only one could be visible at a time.

boolean v1, v2, v3, v4;

void setup(){
background(255);

frameRate(6);

v1=false;
v2=false;
v3=false;
v4=false;

}

void draw (){


if(keyPressed) {

if (key == 'a' || key == 'A') {
if (v1==false) {
v1=true;
v2=false;

} else {
v1=false;
}
}



if (key == 's' || key == 'S') {
if (v2==false) {
v2=true;

v1=false;
} else {
v2=false;
}
}

if (key == 'd' || key == 'D') {

if (v3==false) {
v3=true;
v1=false;

} else {
v3=false;

}
}


if (key == 'f' || key == 'F') {
if (v3==false) {

v4=true;
v1=false;
} else {
v4=false;
}

}

drawEllipse();
}
}

void drawEllipse(){

if (v1==true){
fill(0);
ellipse(30,50,10,10);
} else {
fill(255);
ellipse(30,50,10,10);

}

if (v2==true){
fill(0);
ellipse(50,50,10,10);

} else {
fill(255);
ellipse(50,50,10,10);
}

if (v3==true){
fill(0);

ellipse(70,50,10,10);
} else {

fill(255);
ellipse(70,50,10,10);
}

if (v4==true){
fill(0);

ellipse(90,50,10,10);
} else {
fill(255);
ellipse(90,50,10,10);
}

}

It was only when I tried to implement a third and fourth ellipse I found myself getting a little more confused.

Another stupidly obvious issue we'd overlooked was that if, for example, I switched my dummy switch on then would trigger the servo to switch my real light switch. But if it was my turn to have my light switched off and hence the servo would return the real light switch to an off position, my dummy switch would still remain in the 'on' position, hence messing up the system. We discussed many possible systems we could implement that still incorporated some sensor by which it made as decision as to who would have their lights on or off, hence ensuring it was still a smart system.

The main ideas we were trying to incorporate were use of an LDR to determine level of light an / or a timer to determine how long you've had your light on.

We debate the idea of a shared decision making process where you would push your button if you wanted your light on but it would only send out your 'request' for light if the existing level of light was below a certain threshold. Then a yes / no majority voting system would determine whether you got your light switched on. This was a fairly weak idea as it wasn't particularly 'smart' and again would involve a complicated series of programming loops.


Finally, we scaled it down completely. A very simple idea built from our funadmenta
l idea and mechanics - simple loop where each person reads one other person's feed and their lights is adjusted accordingly, as illustrated below.
It is a simple method based on the idea of only three lights on at one time but it is a fall back which we know more or less is feasible. After setting it up in practice, it went mostly as expected. The only issue we experiences was realising we would need to configure the button to not only send out the data to the feed, but to also control it's own servo so as to actually switch on the light when requested, and even then at the same time, reading the feed to control the servo. A small modification of the code made this possible.

Another alternate method Tapani and Jacques started exploring was implementing use of the Pachuino, a library which makes use of Pachube to provide real time remote sensor data while still sharing local sensor data. They found a different way to approach our idea and their resulting code is as follows:

import eeml.*;
import processing.serial.*;
import cc.arduino.*;
import pachuino.*;


Pachuino p;

float lastUpdate;
float jacquesBtn;
float jacquesLdr;
float tapaniBtn;
float tapaniLdr;
float seamusBtn;

float seamusLdr;
float juditBtn;
float juditLdr;

void setup()
{
p = new Pachuino(this, Arduino.list()[0], 57600);
p.manualUpdate("http://www.pachube.com/api/7584.xml");
p.setKey("API");

p.addRemoteSensor("http://www.pachube.com/api/7344.xml", 0); // jacques button
p.addRemoteSensor("http://www.pachube.com/api/7344.xml", 1); // jacques ldr
p.addRemoteSensor("http://www.pachube.com/api/7339.xml", 0); // tapani button
p.addRemoteSensor("http://www.pachube.com/api/7339.xml", 1); // tapani ldr
p.addRemoteSensor("http://www.pachube.com/api/7472.xml", 0); // seamus button
p.addRemoteSensor("http://www.pachube.com/api/7472.xml", 1); // seamus ldr
p.addRemoteSensor("http://www.pachube.com/api/7584.xml", 0); // judit button
p.addRemoteSensor("http://www.pachube.com/api/7584.xml", 1); // judit ldr

p.addLocalSensor("digital", 0, "button");
p.addLocalSensor("analog", 1, "ldr");
//p.addLocalSensor("digital", 9, "servo");
}

void draw()
{
jacquesBtn = p.remoteSensor[0].value;
jacquesLdr = p.remoteSensor[1].value;
tapaniBtn = p.remoteSensor[2].value;
tapaniLdr = p.remoteSensor[3].value;

seamusBtn = p.remoteSensor[4].value;
seamusLdr = p.remoteSensor[5].value;
juditBtn = p.remoteSensor[6].value;
juditLdr = p.remoteSensor[7].value;

if ((millis() - lastUpdate) > 10000)
{
if (juditBtn == 1.0)

{
p.analogWrite(9, 1);
println("off");
delay(500);
p.analogWrite(9, 0);
lastUpdate = millis();
}
else if (juditBtn == 0.0)
{

if (juditLdr <= jacquesLdr || juditLdr <= tapaniLdr || juditLdr <= seamusLdr) { p.analogWrite(9, 180); println("on"); delay(500); p.analogWrite(9, 0); lastUpdate = millis(); } else { println ("Sorry mate. You've got too much light already."); l astUpdate = millis(); } } else { println ("none"); } } } void onReceiveEEML(DataIn d) { p.updateRemoteSensors(d); } Essentially, it still performs the same operations of reading sensor data and sending it while simultaneously reading data and implementing it. The way they approached the protocol however was that if you pressed your button to try switch your light on, it would then read and compare the other users' LDR readings with their own and if the local LDR value was the greatest, the light would be switched off or remain off.



In theory, it worked. In practise, we encountered lots of error messages which we spent an afternoon trying to trouble shoot. One big issue was the frequency with which we try trying to access and upload data from Pachube, quickly maxing out our API usage allowance.

With time running out, it was coming time to make a decision, find a solution, and actually build the physical component.

Monday, May 31, 2010

Serial Communication


We began experimenting using serial communication as a means of bypassing using Firmata and the technical issues we'd been having with it. I adapted a code implementing the 'handshake method' which works by sending one set of values at a time, rather than repeatedly. The receiving program has to request new data every time it finishes reading what it's got. We didn't need to do much to the original code, it was a matter of making telling Processing what to send back to Arduino and then telling Arduino how to respond to that. We implemented this simply at first communication within one computer.


The modified code is as follows:

Arduino Code:

/*
Sensor Reader
Language: Wiring/Arduino

Reads two analog inputs and one digital input
and outputs their values.

Connections:
analog sensors on analog input pins 0 and 1
switch on digital I/O pin 2
*/

int analogOne = 0; // analog input

int analogTwo = 1; // analog input
int digitalOne = 2; // digital input

int sensorValue = 0; // reading from the sensor
int servoControl;

#include
Servo myservo;
//int pos = 0;


void setup() {
// configure the serial connection:

Serial.begin(9600);
// configure the digital input:
pinMode(digitalOne, INPUT);

myservo.attach(9);

establishContact();
}




void loop() {

if (Serial.available() > 0) {
// read the incoming byte:
int inByte = Serial.read();

// read the sensor:

sensorValue = analogRead(analogOne);
// print the results:

Serial.print(sensorValue, DEC);
Serial.print(",");

// read the sensor:
sensorValue = analogRead(analogTwo);
// print the results:

Serial.print(sensorValue, DEC);

Serial.print(",");

// read the sensor:
sensorValue = digitalRead(digitalOne);

// print the last sensor value with a println() so that
// each set of four readings prints on a line by itself:
Serial.println(sensorValue, DEC);


if(inByte == 66){
myservo.write(180);
}


if(inByte == 67){

myservo.write(0);
}

}
}


void establishContact() {
while (Serial.available() <= 0) {
Serial.println("hello"); // send a starting message
delay(300);
}
}



Processing Code:

/*
Serial String Reader
Language: Processing

Reads in a string of characters from a serial port until
it gets a linefeed (ASCII 10). Then splits the string into
sections separated by commas. Then converts the sections to ints,
and prints them out.

Adapted from original code by Tom Igoe
*/

import processing.serial.*; // import the Processing serial library
Serial myPort; // The serial port

//float bgcolor; // Background color

boolean firstContact = false; // Whether we've heard from the microcontroller

boolean controlServo = false;


void setup() {


// List all the available serial ports
println(Serial.list());

// I know that the first port in the serial list on my mac
// is always my Arduino module, so I open Serial.list()[0].
// Change the 0 to the appropriate number of the serial port
// that your microcontroller is attached to.
myPort = new Serial(this, Serial.list()[0], 9600);

// read bytes into a buffer until you get a linefeed (ASCII 10):
myPort.bufferUntil('\n');
}

void draw() {


}

// serialEvent method is run automatically by the Processing applet
// whenever the buffer reaches the byte value set in the bufferUntil()
// method in the setup():

void serialEvent(Serial myPort) {
// read the serial buffer:
String myString = myPort.readStringUntil('\n');

// if you got any bytes other than the linefeed:

if (myString != null) {

myString = trim(myString);

// if you haven't heard from the microncontroller yet, listen:
if (firstContact == false) {
if (myString.equals("hello")) {

myPort.clear(); // clear the serial port buffer
firstContact = true; // you've had first contact from the microcontroller

myPort.write('A'); // ask for more
println(firstContact);

}
}
// if you have heard from the microcontroller, proceed:
else {
// split the string at the commas

// and convert the sections into integers:
int sensors[] = int(split(myString, ','));

// print out the values you got:

for (int sensorNum = 0; sensorNum <>
print("Sensor " + sensorNum + ": " + sensors[sensorNum] + "\t");

}
// add a linefeed after all the sensor values are printed:
println();

if (sensors.length > 1) {
if (sensors[2] == 1){

myPort.write("B");
} else {
myPort.write("C");

}
}
}
// when you've parsed the data you have, ask for more:

myPort.write("A");
}
}


Following this, we went back to our first set up with me at one computer and Seamus on another one. We modified his code to, rather send the button state back to the Arduino to send it to his Pachube feed. We modified my code to rather than take the button data from my Arduino, to read his feed and send that value back to the servo on my Arduino, something like this:


It was a bit fiddly to paste the right pieces of code in the right place but we were successful after a few minor syntax errors. From here, we just did the same thing again but setting up both codes to send and receive data, something like this:



This is where we were a bit concerned about encounter clashes as we had when we were using Firmata but it all worked as we had hoped; my button controlled his servo and visa versa. Celebrations all around. The final code for processing (Arduino code remains unchanged) is as follows:

Processing Code:

/*
Serial String Reader
Language: Processing

Reads in a string of characters from a serial port until
it gets a linefeed (ASCII 10). Then splits the string into
sections separated by commas. Then converts the sections to ints,
and prints them out.

Adapted from original code by Tom Igoe
*/

import processing.serial.*; // import the Processing serial library
Serial myPort; // The serial port

boolean firstContact = false; // Whether we've heard from the microcontroller

boolean controlServo = false;

//setup for pachube recieving
import eeml.*;
DataIn dIn;
float myVariable;

//setup for pachube sending
DataOut dOut;
float lastUpdate;
int buttonState =0;


void setup() {

// List all the available serial ports
println(Serial.list());

// I know that the first port in the serial list on my mac
// is always my Arduino module, so I open Serial.list()[0].
// Change the 0 to the appropriate number of the serial port
// that your microcontroller is attached to.
myPort = new Serial(this, Serial.list()[0], 9600);

// read bytes into a buffer until you get a linefeed (ASCII 10):
myPort.bufferUntil('\n');

// set up DataIn object; indicate the URL you want, your Pachube API key, and how often you want it to update

// e.g. every 15 seconds
dIn = new DataIn(this,"FEED BEING READ",
"API KEY", 7000);

// set up DataOut object; requires URL of the EEML you are updating, and your Pachube API key
dOut = new DataOut(this, "FEED BEING POSTED TO",
"API KEY");

dOut.addData(2,"button");

}

void draw() {
background(255);
}

// serialEvent method is run automatically by the Processing applet
// whenever the buffer reaches the byte value set in the bufferUntil()
// method in the setup():

void serialEvent(Serial myPort) {
// read the serial buffer:
String myString = myPort.readStringUntil('\n');
// if you got any bytes other than the linefeed:
if (myString != null) {


myString = trim(myString);

// if you haven't heard from the microncontroller yet, listen:
if (firstContact == false) {
if (myString.equals("hello")) {
myPort.clear(); // clear the serial port buffer
firstContact = true; // you've had first contact from the microcontroller
myPort.write('A'); // ask for more
println(firstContact);
}
}

// if you have heard from the microcontroller, proceed:
else {
// split the string at the commas
// and convert the sections into integers:
int sensors[] = int(split(myString, ','));

// print out the values you got:
for (int sensorNum = 0; sensorNum <>
// print("Sensor " + sensorNum + ": " + sensors[sensorNum] + "\t");
}
// add a linefeed after all the sensor values are printed:
//println();
if (sensors.length > 1) {


if (myVariable == 1){
myPort.write("B");
} else {
myPort.write("C");
}

//send data to pachube
if ((millis() - lastUpdate) > 7000){

println("ready to POST: ");
dOut.update(0, sensors[2]); // update the datastream
int response = dOut.updatePachube(); // updatePachube() updates by an authenticated PUT HTTP request

println(response); // should be 200 if successful; 401 if unauthorized; 404 if feed doesn't exist
lastUpdate = millis();

}
}
}

// when you've parsed the data you have, ask for more:
myPort.write("A");
}
}

void onReceiveEEML(DataIn d){
myVariable = d.getValue(2); // get the value of the stream 2

println(myVariable);
}

From here, we finally had the base mechanisms of our Smart System operational. With about two weeks left until deadline, we were forced to start considering exactly was was feasibly achievable to build and code with this. We had to starting considering the very real possibility of having to scale it back and having to figure out such a way to do it that wouldn't compromise what we were trying to achieve and show.


Thursday, May 27, 2010

Back and Forth

We begun to set up an advancement on our previous setup where both Arduinos could send data to separate Pachube feeds via a digital input (a button) while reading the other ones input and using it to determine the position of a servo.


Where this seemed a simple enough advancement, this is where we began to encounter major problems. The coding itself seemed fairly straightforward to simply amalgamate the send and the receive ones used last time:

// Code was adapted from eeml_manual_button example combined with eeml_auto_request_arduino
// This code sends a value of 0 or 1 from a digital input attached to pin 2 and uploads to a Pachube feed every 5 seconds.
// Simultaneously it also reads a seprate feed from another Arduino sending out a digital input and uses this to determine the position of a servo.

import eeml.*;
import processing.serial.*;
import cc.arduino.*;
Arduino arduino;

float myVariable;

DataOut dOut;
float lastUpdate;
int buttonState =0;



//int servoPin = 10; // Control pin for servo motor

DataIn dIn;

void setup(){
size (180, 50);

// set up DataIn object; indicate the URL you want, your Pachube API key, and how often you want it to update
// e.g. every 15 seconds
dIn = new DataIn(this,"LINK TO FEED BEING READ",
"API", 5000);

arduino = new Arduino(this, Arduino.list()[0]);
arduino.pinMode(10, Arduino.OUTPUT);

//*****************************************

dOut = new DataOut(this, "LINK TO FEED BEING POSTED TO",
"API CODE HERE");

// and add and tag a datastream
dOut.addData(2,"button");
arduino = new Arduino (this, Arduino.list()[0],57600);
arduino.pinMode(2,arduino.INPUT);



}

void draw()
{
if (myVariable == 0.0) { // Button is off.
arduino.analogWrite(10, 0); // Set servo position to 0 degrees.
println("off");
} else { //Button is on.
println("on");
arduino.analogWrite(10, 180); // Set servo position to 180 degrees.

}

// update once every 5 seconds (could also be e.g. every mouseClick)
if ((millis() - lastUpdate) > 5000){
buttonState=arduino.digitalRead(2);

println("ready to POST: ");
dOut.update(0, buttonState); // update the datastream
int response = dOut.updatePachube(); // updatePachube() updates by an authenticated PUT HTTP request
println(response); // should be 200 if successful; 401 if unauthorized; 404 if feed doesn't exist
lastUpdate = millis();

}


}

// onReceiveEEML is run every time your app receives back EEML that it has requested from a Pachube feed.
void onReceiveEEML(DataIn d){
myVariable = d.getValue(2); // get the value of the stream 1
println(myVariable);

}



We had two issues arise here. First of all, in order to control the Arduino board using Processing, Firmata had to be uploaded. In order to send and receive data, StandardFirmata was the most suitable to bridge the two. However, this was not ideal for controlling the servo and when we tried to run the above sketch with StandardFirmata uploaded to the Arduino board, the servo buzzed and wouldn't respond correctly to the input.

Previously, when the servo was just receiving data to control the servo (and not sending), we simply had ServoFirmata uploaded. This was no longer an option as it is crucial we are able to both send and receive data.

The other major roadblock was that while Processing was attempting to read an incoming feed, it was no longer able to update it's own feed.

To deal with one issue at a time, we began to search for a solution by attempting to modify the StandardFirmata sketch to make it successfully control the servo. We quickly found that this was beyond our level of understanding of Arduino and programming in general. We posted for help on the Processing and Arduino forums:

We are a working on creating a program where a button input sends data over the internet via Pachube which is received by another Arduino to control a servo.

We have gotten this successfully working using Processing and Servo Firmata in Arduino (i.e. my button push on my Arduino controls my teammates servo attached to his Arduino). Unfortunately, as we need to both send and recieve data from the same Arduino (send button push data and recieve data to control servo), we need to use the Standard Firmata. This however doesn't successfully control the servo causing it to buzz and not respond to the recieved data.

We have experimented trying to adapt the Firmata codes and using just a simpler code for trouble shooting problems as below. When the following code is run on Processing with Servo Firmata it works beautifully but when run with Standard Firmata, it has the same issue and buzzes / doesn't respond properly.


import processing.serial.*;
import cc.arduino.*;
Arduino arduino;

int servoPin = 10; // Control pin for servo motor

void setup(){

size (180, 50);
arduino = new Arduino(this, Arduino.list()[0]);
arduino.pinMode(servoPin, Arduino.OUTPUT);
// note - we are setting a digital pin to output
}

void draw(){
arduino.analogWrite(servoPin, mouseX); // the servo moves to the horizontal location of the mouse
}



If anyone has done anything similar or can think of a solution, any help would be much appreciated from this sleep deprived, caffeine driven group of uni students.


While waiting for a response and running out of time, we began to search for other alternatives in the meantime.