From the code side of this their is 3 major steps to make this sculpture to work.
– Basic Communication between the Arduino and the SyRen 50 motor driver
– Reading the weather API with processing using Processing and JSONObject
– Serial communication between Processing and Arduino
For each of this steps we can go as in-depth as needed.
For the propose of this post I will share with you the process of the “how to” starting form very simple code.
The hope is that then the reader can navigate the process, understand it , make it his/her own for future and share the result with the rest of us so wee can all be inspired and expand out technical knowledge as well as our creative options.
The core of this installation however is not the technology nor the code. The hart of it all is in the way we massage the number to create the right behavioral patterns that best fits the esthetic and the conceptual needs of the work.
I stress this because when using digital technology is often easy to lose site of the over all nature of the work.
Not bing a formally trained technology I have found my self in this very situation. Eager to prove my self form a technological/skill stand point, I have spend endless hours researching a learning how to “code it right” or “build it right” infatuated by the endless opportunities available . This forgetting that I most of all an artist not a technician.
Skill and knowledge are indeed freedom but, after all, there is not use for a nicely skillfully painted painting if its content is shallow or rhetoric .
– Basic Communication between the Arduino and the SyRen 50 motor driver
This is the basic test code to control the motor via SyRen 50.
With this code I was able to test the rope traction on the motor and position avoid the rope to loop and catch on it self.
When that happens the rope stop easing-out in one side, wrapping it self on the motor and laterally eradicating things form the walls.
The other challenge is the winch radius. Due to financial restriction I had to purchase winches with different radius .
The winch with a larger radius works well with the 4mm rope, the smaller not so much, increasing the possibility of wrapping the rope on in its self.
Below is the basic Arduino code to control the motor .
For more detail on the SyRen Libraries for Arduino, how the drivers works and large motor see my previous post at : http://www.maiamarinelli.com/2015/03/04/swd/
______________________________________________________________________________________________
#include
SyRenSimplified ST;
void setup(){
SyRenTXPinSerial.begin(9600); // This is the baud rate you chose with the DIP switches.
ST.motor(1, 0);
}
//-127 FULL reverse. 0 is stop. +127 is FULL forward
void loop(){
ST.motor(1,0);
delay(120000);//pouse 2 minute
ST.motor(1,-100);
delay(720000);//go 12 minutes
}
______________________________________________________________________________________________
In this case I’m moving the motor backwards at speed -100 for 12 minute and pause it for 2 minute.
Pause the motor is a good practice especially when working on installation that are designed active for a long period of time .
This allows the motor to cool down extending its life and the life of the installation. For that reason when working with motors one MUST remember that motors not and will not run all day for ever , especially if applied with heavy loads like in the case of this series of installations.
– Reading the weather API with processing using Processing and JSONObject
Now that I know my motor driver works and my rope are installed correctly I want to read dynamically the weather data translating it into a kinetic experience.
First have to extract the data using Processing and weather API.
I used the Weather Underground API : http://www.wunderground.com/weather/api/d/docs?d=data/conditions
Weather Underground provides all the information I need into a JSON file.
A JSON (JavaScript Object Notation) is a lightweight data-interchange format based on a subset of the JavaScript Programming Language. Basically is a long list of information is easy for humans to read and write and easy for machines to parse and generate.
To read this information I use Processing, a open source JavaScrtip base programming language that is designed, among other things, to interface with Arduino and is perfectly capable to parse a JSON file using a JSONObject
Processing : https://processing.org/
JSONObject: https://processing.org/reference/JSONObject.html
To download the code and the fake JSON go here:
Link to zip file : http://www.maiamarinelli.com/wp-content/uploads/2015/04/Archive.zip
With this code I can read :
Barometric pressure
Wind Speed
Wind direction (degrees)
———————————————————————————-
// now we read a fake “fakeweather.json” file.
void setup() {
size(300, 300);
//each data parcing is treated as a separate function in itself this way it can be called globally and the code is lighter and more precise
getRemoteWeatherJSON();
parseWeatherJSON();
parseWspeedJSON();
parseWdegreesJSON();
}
void draw(){
// we will put out timer here (
}
void getRemoteWeatherJSON() {
JSONObject json_to_read;
json_to_read = loadJSONObject(“fakeweather.json”);
//String query = “http://api.wunderground.com/api/” + API_key + “/conditions/q/CA/San_Francisco.json”; /// get your EPI
//json_to_read = loadJSONObject(query);
JSONObject new_observations = json_to_read.getJSONObject(“response”); // look in to the data under the “response” in the “fakeweather.json”
String version_number = new_observations.getString(“version”); // print the version number listed in the code as a “string”
//int numberOfElements = results.length();
println(version_number);
}
void parseWeatherJSON() {
JSONObject json_to_read;
json_to_read = loadJSONObject(“fakeweather.json”);
JSONObject new_observations = json_to_read.getJSONObject(“current_observation”);
String millibars = new_observations.getString(“pressure_mb”);
//int numberOfElements = results.length();
println(“millibars “+ millibars);
saveJSONObject(json_to_read, “data/new_data.json”);
}
//read the local file and return the barometric pressure
// in the JSON file Baroemtric pressure is a “string”
//pressure in a usable way = a “float”
float getPressure() {
JSONObject json_to_read;
json_to_read = loadJSONObject(“fakeweather.json”);
JSONObject new_observations = json_to_read.getJSONObject(“current_observation”);
String millibars = new_observations.getString(“pressure_mb”);
//int numberOfElements = results.length();
//println(millibars);
return float(millibars);
}
void parseWspeedJSON() {
JSONObject json_to_read;
json_to_read = loadJSONObject(“fakeweather.json”);
JSONObject new_observations = json_to_read.getJSONObject(“current_observation”);
int Wspeed = new_observations.getInt (“wind_kph”);
//int numberOfElements = results.length();
println(“Wspeed “+ Wspeed);
saveJSONObject(json_to_read, “data/new_data.json”);
}
void parseWdegreesJSON() {
JSONObject json_to_read;
json_to_read = loadJSONObject(“fakeweather.json”);
JSONObject new_observations = json_to_read.getJSONObject(“current_observation”);
int Wdegrees = new_observations.getInt (“wind_degrees”);
//int numberOfElements = results.length();
println(“wind_degrees ” + Wdegrees);
saveJSONObject(json_to_read, “data/new_data.json”);
}
———————————————————————————-
Now we were able to parse the information out of the JSON file we have to set up a system to pass the information along and a time frame to read the API online.
I’m suing a free Weather API which limits the amount of calls permitted per day.
Also for the nature of my installation I don’t need to read the weather every second so I have to set up a timer to read the weather every hour.
Arduino and Processing are very similar both as an interface and leguage.
They both have a “void setup()” but while Arduino have “void loop()” Processing uses “void draw()”
Just like in Arduino the “void setup()” is a place where you set up your basic information, function and variable.
Think of it like a list of tools list or stencil list ready to grab when needed.
The “void draw()” is like “void loop()” in Arduino.
This is essentially it is the hart beat and the brain of you program, commanding your tools when exaltedly to perfume a task and with what condition .
At each hart beat the program is re-read, re-fresh or re-draw and within it all the function attached to that hart beat .
“void draw()” is where I will put my timer telling the program to check the time and when one hour is passed to go online to check the on the Weather API and get the new set of data .
Here are some timer set up examples
http://www.learningprocessing.com/examples/chapter-10/example-10-4/
http://www.learningprocessing.com/examples/chapter-10/example-10-5/
Also in this example I no longer read a fake JSON file but I actually use my API key to check the data directly online. The actual API key however is omitted with “XXXXX” . That means you will need to have your own API key to make this code work .
Also, In this code I crate place holder for all my data so that later on it can be easily retrieved and send over to Arduino via serial communication
———————————————————————————-
//Based on using http://www.wunderground.com/ API
// Import serial library to connect to Arduino.
import processing.serial.*;
Serial myPort;
int savedTime;
int totalTime = 3600000;// this unit is in millisecond
// Has five seconds passed? = 5000
// Has five minutes passed? = 300000
// Has one hour passed? = 3600000
String API_key = “XXXXX”;
String Location = “/conditions/q/HI/Haiku.json”;
float pressure;
int intPressure;
float diameter;
float diametersk;
int intDiameter;
int speed;
int direction;
int millibars;
void setup() {
size(300, 300);
background(Wdegrees()+100, WindSpeed()); // WindSpeed in the sculpture = motor speed
savedTime = millis();
pressure = getPressure(); // between 1000 and 1030 // in the sculpture running time
int intPressure = int(pressure); // trasfroming the Float value of “pressure” in to an int to transmit it ti arduino via write()
diameter = pressure – 1000; // subtract 1000 from the gtpressure()
diametersk = map(diameter, 0, height/2, 0, 255 ); // diamtare is between 0 to 30 and map it to a numebr between 0 to 255
int intDiameter = int(diameter);
ellipse(width/2, height/2, diameter, diameter);
speed = WindSpeed();
direction = Wdegrees();
// print the data so we know were we stand and waht kind of data we got.
println (” intDiameter :” + intDiameter + ” intPressure :” + intPressure);
println (” pressure :” + pressure + ” diameter on sketch :” + diametersk + ” speed :” + speed + ” direction :” + direction );
}
void draw(){
int passedTime = millis() – savedTime;
// Has five seconds passed? = 5000
// Has five minutes passed? = 300000
// Has one hour passed? = 3600000
//to calculate time in millisecond go to https://www.unitjuggler.com/convert-time-from-s-to-ms.html?val=5
if (passedTime > totalTime) {
println( ” 1 hour have passed! ” );
getPressure();
WindSpeed();
Wdegrees();
savedTime = millis(); // Save the current time to restart the timer!
println (savedTime);
println (” pressure :” + pressure + ” speed :” + speed + ” direction :” + direction);
}
}
//
//read the local file and return the atmospheric
//Trasform pressure delivered in the Json as string into a usable falue “float”
float getPressure() {
JSONObject json_to_read;
json_to_read = loadJSONObject(“http://api.wunderground.com/api/” + API_key + Location);
String query = “http://api.wunderground.com/api/” + API_key + “/conditions/q/CA/San_Francisco.json”;
JSONObject new_observations = json_to_read.getJSONObject(“current_observation”);
String millibars = new_observations.getString(“pressure_mb”);
//int numberOfElements = results.length();
println(millibars);
return float(millibars);
}
Integer WindSpeed() {
JSONObject json_to_read;
json_to_read = loadJSONObject(“http://api.wunderground.com/api/” + API_key + Location);
String query = “http://api.wunderground.com/api/” + API_key + “/conditions/q/CA/San_Francisco.json”;
JSONObject new_observations = json_to_read.getJSONObject(“current_observation”);
int Wspeed = new_observations.getInt (“wind_kph”);
println(Wspeed);
return Wspeed;
}
Integer Wdegrees() {
JSONObject json_to_read;
json_to_read = loadJSONObject(“http://api.wunderground.com/api/” + API_key + Location);
String query = “http://api.wunderground.com/api/” + API_key + “/conditions/q/CA/San_Francisco.json”;
JSONObject new_observations = json_to_read.getJSONObject(“current_observation”);
int Wdegrees = new_observations.getInt (“wind_degrees”);
println(Wdegrees);
return Wdegrees;
}
———————————————————————————-
– Serial communication between Processing and Arduino
Now this is all nice and groovy !
Look how much information we got !!! Now no one is to prevent us from read multiple data point form multiple locations … possibility are endless.
However going back the installation, how do I take all that information, send it over to the Arduino and organize it in a way that makes sense for both Arduino and the driver?
Remember the SyRen 50 controls the motor using serial commands and Arduino speaks and receive data from processing via serial communication using pin 0 and 1 (RX and TX) which which also goes to the computer via the USB connection.
This is the equivalent 3 people trying to talk at the same time on the same conference call.
The solution is to use a “Serial Softwere” wich can be download into the Arduino Library allowing to transform existing pins in to serial pins
But first lets simplify things a bit. Lets read one data point at the time initiating a simple serial communication between Processing and Arduino
Because I’m missing home I chose wind speed form Haiku , Hawaii.
First here are some basic example to initiate serial communication between Processing and Arduino .
https://learn.sparkfun.com/tutorials/connecting-arduino-to-processing
I will control the brightness of a LED based on wind speed.
This is a easy test because it also requires a very simple hardware set up
This code is a based on a code originally wrote by Tom Igoe and Scott Fitzgerald
http://www.arduino.cc/en/Tutorial/Dimmer
Circuit
An LED connected to pin 9. Use an appropriate resistor as needed. For most common LEDs, a 220 or 330 ohm resistor will work.
Here is the processing code
As you can see I edit out the Weather API key as it is easer to tinker with the fake JSON wild perfecting the code. One you are ready you can add your API key as shown in the code above.
I also edit out timer so that I can read the data right away .
———————————————————————————-
// now we read a fake “fakeweather.json” file.
import processing.serial.*;
Serial port;
void setup() {
size(300, 300);
WindSpeed();
String portName = Serial.list()[4];
port = new Serial(this, portName, 9600);
}
//TImer go here
void draw(){
port.write(WindSpeed());
}
Integer WindSpeed(){
JSONObject json_to_read;
json_to_read = loadJSONObject(“fakeweather.json”);
JSONObject new_observations = json_to_read.getJSONObject(“current_observation”);
int Wspeed = new_observations.getInt (“wind_kph”);
//int numberOfElements = results.length();
println(Wspeed);
return Wspeed;
// saveJSONObject(json_to_read, “data/new_data.json”);
}
———————————————————————————-
This is our Arduino code
———————————————————————————-
const int ledPin = 9; // the pin that the LED is attached to
void setup()
{
// initialize the serial communication:
Serial.begin(9600);
// initialize the ledPin as an output:
pinMode(ledPin, OUTPUT);
}
void loop() {
byte brightness;
// check if data has been sent from the computer:
if (Serial.available()) {
// read the most recent byte (which will be from 0 to 255):
brightness = Serial.read();
// set the brightness of the LED:
analogWrite(ledPin, brightness);
}
}
———————————————————————————-
So this will be it for this post on the next post we will take a step by step approach progressively transforming this simple code into a multichannel weather reader and motor control .