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.

Friday, May 21, 2010

Button to Servo

First attempt at connecting two Arduinos over Pachube - one wired up with a simple digital input sending a 0 (off) or a 1 (on) to a Pachube feed. The Arduino on the second computer retrieves and reads the feed. If the recieved input is 0, the servo is set to 0*. If the input received is 1 (button is pushed), the servo turns to 180*.

This was successfully achieved with no major problems other than simply syntax errors. The codes used are as follows:

Send button push (using Processing):

// Code was adapted from eeml_manual_button example and is run with StandardFirmata uploaded onto the Arduino board.
// This code sends a value of 0 or 1 from a digital input attached to pin 2.
// Uploads to a Pachube feed every 5 seconds.

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


DataOut dOut;

float lastUpdate;
int buttonState =0;

void setup(){
// set up DataOut object; requires URL of the EEML you are updating, and your Pachube API key
dOut = new DataOut(this, "FEED LINK HERE",
"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()
{

// 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();
}
}


Receive button push and control servo (using Processing):

// This code was adapted from eeml_auto_request_arduino and is run with ServoFirmata uploaded ont
o the Arduino board.
// - A basic example to retrieve data from an existing Pachube feed
// This code reads the value from the data feed every 5 seconds and controls the servo position accordingly.

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

float myVariable;

//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,"FEED LINK HERE",
"API CODE HERE", 5000);

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

arduino.pinMode(10, Arduino.OUTPUT);
}

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.
}
}

// 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);


}

Next step from here is to wire up both circuits with both a button and a servo and recode so that both can send and receive data from Pachube. But to finish off, here are the faces behind it.



Friday, May 14, 2010

That's Smart.

The Project:
Smart Systems describe and analyze a situation, makes decisions and takes action on the available data, hence performing smart actions. Smart Systems address environmental, societal and economic challenges like limited resources, climate change, aging population, and globalization.

The project is to network our four Arduinos over the internet, sending and receiving data from feeds via Pachube to create some sort of Smart System.


Initial Ideas:
Initial discussion and brainstorm of ideas, we were exploring the concept of cooperative decision making. We got initially quite excited during a simple exercise where two people were each controlling an analogue input (potentiometers) to collaborative determine the position of a single ellipse on screen.


We like the idea of having something physical and tangible resulting from the collaboration, not just something that exists while it is operation. We discussed creating a creature powered by an Arduino which took input from the other Arduinos - perhaps by various sensors - to determine its physical movement and position on a canvas and create a sort of art work.


We like the link between the various representations of data which would come as a result: the physical input - pressure, light, movement - to the binary data read and understood by the computer and program, to the data it outputs in a form we can understand - i.e. analog value from 0 to 1023 - and finally the physical output of a painting which documented all the others in an abstract manner.


We put a lot of thought into what the more of the conceptual meanings and implications of each aspect were but we found it was all too open and hinged mostly on this idea of a physical result.


Personally, I thought we could adapt it to the input coming from pressure sensors placed around town (stationary) or even attached to the bottom of our feet (mobile) and rather than a flat output, having the creature with a bulldozer sort of attachment and pushing around sand.

This way, it would still create some sort of physical result which would be different every time it was run. The link between the input and the output, though initially a bit obvious, was the effect of the human footprint or existence on earth. Perhaps even some twist on a pedometer.

The Idea:

After further discussions, we changed our idea considerably which started with the idea that because we would be communicating our Arduinos over the internet from our own houses, we should control something in each others houses.

So we took the simple idea of a light switch.
We are planning on building a fixture which you would attach to on top of your light switch. You cannot actually access the light switch but instead, there is another switch on top of it. The actual switch (the one on the wall of the house) is activated by a servo physically changing it.


However, only three people out four can have light at any given time. The system will make the decision of who gets to have their light on based on the available data, possibly informed by a sensor such as an LDR.

This idea is quite a simple application of a smart system and the conceptual basis is simply that that there aren't enough resources for everyone; there are people who miss out on those that we take for granted and are accessible to us as simply as flicking a switch. This systems takes away an element of control from the user and forcing the sharing out of resources.