Page 1 of 1
OSC Sending Problem
Posted: Tue Nov 08, 2016 13:21
by msq127
Hello there!
for a university Project I am trying to connect a touch board to Arena via OSC.
Aim is, that if an electrode gets touched a dedicated video gets played.
The Ardunio Code works just fine, but something in the Processing Sketch that should
send out the OSC to Arena does not really work. I can't get the OSC messages to be sent out.
Ardunio Code:
Code: Select all
// serial rate
#define baudRate 57600
#include <MPR121.h>
#include <Wire.h>
// this is the touch threshold - setting it low makes it more like a proximity trigger
// default value is 40 for touch
const int touchThreshold = 40;
// this is the release threshold - must ALWAYS be smaller than the touch threshold
// default value is 20 for touch
const int releaseThreshold = 20;
void setup(){
Serial.begin(baudRate);
while(!Serial); // only needed for Arduino Leonardo or Bare Touch Board
// 0x5C is the MPR121 I2C address on the Bare Touch Board
if(!MPR121.begin(0x5C)){
Serial.println("error setting up MPR121");
switch(MPR121.getError()){
case NO_ERROR:
Serial.println("no error");
break;
case ADDRESS_UNKNOWN:
Serial.println("incorrect address");
break;
case READBACK_FAIL:
Serial.println("readback failure");
break;
case OVERCURRENT_FLAG:
Serial.println("overcurrent on REXT pin");
break;
case OUT_OF_RANGE:
Serial.println("electrode out of range");
break;
case NOT_INITED:
Serial.println("not initialised");
break;
default:
Serial.println("unknown error");
break;
}
while(1);
}
MPR121.setTouchThreshold(touchThreshold);
MPR121.setReleaseThreshold(releaseThreshold);
}
void loop(){
readRawInputs();
}
void readRawInputs(){
int i;
if(MPR121.touchStatusChanged()) MPR121.updateTouchData();
MPR121.updateBaselineData();
MPR121.updateFilteredData();
Serial.print("");
for(i=0; i<12; i++){ // 13 touch values
Serial.print(MPR121.getTouchData(i), DEC);
if(i<12) Serial.print(" ");
}
Serial.println();
}
The Processing Code:
Code: Select all
//Die Bibliothek einbinden für das Lesen des seriellen Inputs
import processing.serial.*;
import oscP5.*;
import netP5.*;
final String host = "localhost";
final int portListening = 7001 ;
final int portSending = 7373;
OscP5 oscP5;
NetAddress OSCLocation;
OscBundle OSCBundle;
OscMessage OSCMessage;
final int baudRate = 300;
final String port = "/dev/cu.usbmodem1421";
final int lf = 10;
//Setzen der Variablen
Serial Microcontroller;
String input;
String[] electrodes;
//Setup
void setup()
{
//Die vordefinierten Variablen werden zugewiesen
Microcontroller = new Serial( this, port, baudRate );
Microcontroller.bufferUntil(lf);
oscP5 = new OscP5( this, 7001 );
OSCLocation = new NetAddress( host, 7373 );
OSCBundle = new OscBundle();
OSCMessage = new OscMessage("/");
OSCMessage.setAddrPattern( "/layer1/clip1/connect" );
OSCMessage.add( 1 );
OSCBundle.add( OSCMessage );
OSCMessage.clear();
oscP5.send( OSCBundle, OSCLocation );
}
//Draw (Brauchen wir nicht, kann man löschen, wenns kein Error gibt)
void draw() { }
void serialEvent( Serial p ) {
input = p.readString();
electrodes = splitTokens( input, " " );
updateOSC( electrodes );
}
void updateOSC( String[] electrodes ) {
String touchedElectrodes = "";
for ( int i = 0; i < electrodes.length; i++ ) {
int value = parseInt( electrodes[i] );
if ( value > 0 ) {
touchedElectrodes += i + " ";
}
}
if ( touchedElectrodes == "Unkown" ) {
OSCMessage.setAddrPattern( "/layer1/clip1/video/position/playmode" );
OSCMessage.add( 1 );
OSCBundle.add( OSCMessage );
OSCMessage.clear();
}
}
I'd be glad if someone could help me solve this problem.
Best,
Marco
Re: OSC Sending Problem
Posted: Tue Nov 08, 2016 13:39
by Joris
To send an osc message or bundle using oscP5, you need a call to oscP5.send().
In your code, oscP5.send() is only called in setup(). And setup() is only executed once in Processing, during start up.
It looks like you want to do the sending in updateOsc(). But you don't make any messages and bundles there for clip triggering. You do make a bundle for pausing the timeline, but you never actually send it.
If you create a bundle for clip triggering and a call to oscP5.send() in updateOsc(), you should be good.
Also, I'm a bit rusty on how Java handles pointers, but can you actually clear an OSCMessage before sending it?
Re: OSC Sending Problem
Posted: Tue Nov 08, 2016 14:14
by msq127
Okay that works - Processing is now sending an OSC Message (checked that with OSCulator).
But still Resolume does not play the desired video. What could be wrong here?
The ports are all checked and work just fine.
Also, I'm a bit rusty on how Java handles pointers, but can you actually clear an OSCMessage before sending it?
> I'm actually just a beginner, I can't answer that.
Re: OSC Sending Problem
Posted: Tue Nov 08, 2016 14:53
by Zoltán
from the timestamps it looks like you are sending the osc messages constantly, I guess that's not what you intend.
It looks like it would make resolume restart the clip 10 times per millisecond.
clearing the oscMessage after it has been added to the bundle is no problem.
a good way to keep track of events inside processing is to place println("your message"); lines into your code you want to take a closer look, how many times a given loop gets executed, how often ,etc.
Re: OSC Sending Problem
Posted: Tue Nov 08, 2016 15:24
by msq127
Absolutely right, that's not what I intend. So if only send it once when the electrode gets
touched instead of 10 times per millisecond that should work just fine?
Maybe I can fix that with a switch:
https://processing.org/reference/switch.html
That way it would only do something when the first change appears.
Does that sound like a good way to go?
Re: OSC Sending Problem
Posted: Tue Nov 08, 2016 15:41
by Zoltán
the switch statement in java is not the switch you are looking for.
it's more like a lot of 'if then else' statements.
what you could do is to store the input's status in variables then compare the currently received state with the last, and only send the osc messages if the state changed.
also there is the question if resolume actually gets the osc message, but if the port and host is correct in processing and resolume has it's osc input enabled on the same port that should be working.
Re: OSC Sending Problem
Posted: Tue Nov 08, 2016 16:50
by msq127
With a little bit of help I tried to change the code.
Now it only sends one OSC Message (in the Code it just prints a message but I'll put the OSC Message part in there later) when pressed. I also incorporated a sort of a timeout that blocks the pin for a ceratin time - the time needed for the video to play in Arena so the program won't recieve new messages when playing.
I'll test that out and keep you updated.
Code: Select all
//Die Bibliothek einbinden für das Lesen des seriellen Inputs
import processing.serial.*;
import oscP5.*;
import netP5.*;
final String host = "localhost";
final int portListening = 7001 ;
final int portSending = 7373;
OscP5 oscP5;
NetAddress OSCLocation;
OscBundle OSCBundle;
OscMessage OSCMessage;
final int baudRate = 300;
final String port = "/dev/cu.usbmodem1421";
final int lf = 10;
//Setzen der Variablen
Serial Microcontroller;
String input;
String[] electrodes;
int[] pins_state = {0,0,0,0,0,0,0,0,0,0,0,0};
int[] pins_time = {0,0,0,0,0,0,0,0,0,0,0,0};
//Setup
void setup()
{
//Die vordefinierten Variablen werden zugewiesen
Microcontroller = new Serial( this, port, baudRate );
Microcontroller.bufferUntil(lf);
oscP5 = new OscP5( this, 7001 );
OSCLocation = new NetAddress( host, 7373 );
OSCBundle = new OscBundle();
OSCMessage = new OscMessage("/");
OSCMessage.setAddrPattern( "/layer+" + electrodes + "/clip1/connect" );
OSCMessage.add( 1 );
OSCBundle.add( OSCMessage );
OSCMessage.clear();
oscP5.send( OSCBundle, OSCLocation );
}
//Draw (Brauchen wir nicht, kann man löschen, wenns kein Error gibt)
void draw() { }
void serialEvent( Serial p ) {
input = p.readString();
electrodes = splitTokens( input, " " );
// Delay, warte 100 Millisekunden, bis nächstes OSC Paket gesendet wird
updateOSC( electrodes );
}
void updateOSC( String[] pins ) {
//int[] pins = int(electrodes.split(' '));
//Pin O Anfang
if(int(pins[0]) == 1 && pins_state[0] == 0) {
pins_state[0] = 1;
println("Pin 0 touched"); //hier OSC message
pins_time[0] = millis();
} else if (int(pins[0]) == 0 && pins_state[0] == 1 && (millis() - pins_time[0] >= 3000 /*Abspielzeit bzw. Blockierzeit*/ )) {
pins_state[0] = 0;
pins_time[0] = 0;
}
//Pin 0 Ende
//println(int(pins[0]) == 1);
/*
String touchedElectrodes = "";
for ( int i = 0; i < electrodes.length; i++ ) {
int value = parseInt( electrodes[i] );
if ( value > 0 ) {
//OSC Message Start hier
OSCMessage.setAddrPattern( "/layer" + electrodes[i] + "/clip1/connect" );
OSCMessage.add( 1 );
OSCBundle.add( OSCMessage );
OSCMessage.clear();
oscP5.send( OSCBundle, OSCLocation );
// OSC Message Ende
}
}*/
}
there is the question if resolume actually gets the osc message
In Processing:
Code: Select all
final int portListening = 7001;
final int portSending = 7373;
In Resloume:
that should be working.
Re: OSC Sending Problem
Posted: Tue Nov 08, 2016 21:07
by msq127
Okay, I got it to work. When I touch one of the electrode it sends out the OSC message and plays the desired video.
Nevertheless there are two problems:
When I have two electrodes connected and sending out osc message they somehow mess up. Sometimes when touching an electrode it plays the video of the other or both.
The second problem is, that sometimes the eletrode needs to be touched twice oder three times, sometimes just once is enough.
This is what the code looks like:
Code: Select all
//Die Bibliothek einbinden für das Lesen des seriellen Inputs
import processing.serial.*;
import oscP5.*;
import netP5.*;
final String host = "localhost";
final int portListening = 7001 ;
final int portSending = 7373;
OscP5 oscP5;
NetAddress OSCLocation;
OscBundle OSCBundle;
OscMessage OSCMessage;
final int baudRate = 57600;
final String port = "/dev/cu.usbmodem1421";
final int lf = 10;
//Setzen der Variablen
Serial Microcontroller;
String input;
String[] electrodes;
int[] pins_state = {0,0,0,0,0,0,0,0,0,0,0,0};
int[] pins_time = {0,0,0,0,0,0,0,0,0,0,0,0};
//Setup
void setup()
{
//Die vordefinierten Variablen werden zugewiesen
Microcontroller = new Serial( this, port, baudRate );
Microcontroller.bufferUntil(lf);
oscP5 = new OscP5( this, 7001 );
OSCLocation = new NetAddress( host, 7373 );
OSCBundle = new OscBundle();
OSCMessage = new OscMessage("/");
OSCMessage.setAddrPattern( "/layer+" + electrodes + "/clip1/connect" );
OSCMessage.add( 1 );
OSCBundle.add( OSCMessage );
OSCMessage.clear();
oscP5.send( OSCBundle, OSCLocation );
}
//Draw (Brauchen wir nicht, kann man löschen, wenns kein Error gibt)
void draw() { }
void serialEvent( Serial p ) {
input = p.readString();
electrodes = splitTokens( input, " " );
// Delay, warte 100 Millisekunden, bis nächstes OSC Paket gesendet wird
updateOSC( electrodes );
}
void updateOSC( String[] pins ) {
//int[] pins = int(electrodes.split(' '));
//Pin O Anfang
if(int(pins[0]) == 1 && pins_state[0] == 0) {
pins_state[0] = 1;
//println("Pin 0 touched");
OSCMessage.setAddrPattern( "/layer1/clip1/connect" );
OSCMessage.add( 1 );
OSCBundle.add( OSCMessage );
OSCMessage.clear();
oscP5.send( OSCBundle, OSCLocation );//hier OSC message
pins_time[0] = millis();
} else if (int(pins[0]) == 0 && pins_state[0] == 1 && (millis() - pins_time[0] >= 3000 /*Abspielzeit bzw. Blockierzeit*/ )) {
pins_state[0] = 0;
pins_time[0] = 0;
}
//Pin 0 Ende
//Pin 1 Anfang
if(int(pins[1]) == 1 && pins_state[1] == 0) {
pins_state[1] = 1;
println("Pin 1 touched"); //hier OSC message
pins_time[1] = millis();
} else if (int(pins[1]) == 0 && pins_state[1] == 1 && (millis() - pins_time[1] >= 3000 /*Abspielzeit bzw. Blockierzeit*/ )) {
pins_state[1] = 0;
pins_time[1] = 0;
}
//Pin 1 Ende
//Pin 2 Anfang
if(int(pins[2]) == 1 && pins_state[2] == 0) {
pins_state[2] = 1;
println("Pin 2 touched"); //hier OSC message
pins_time[2] = millis();
} else if (int(pins[2]) == 0 && pins_state[2] == 1 && (millis() - pins_time[2] >= 3000 /*Abspielzeit bzw. Blockierzeit*/ )) {
pins_state[2] = 0;
pins_time[2] = 0;
}
//Pin 2 Ende
//Pin 3 Anfang
if(int(pins[3]) == 1 && pins_state[3] == 0) {
pins_state[3] = 1;
println("Pin 3 touched"); //hier OSC message
pins_time[3] = millis();
} else if (int(pins[3]) == 0 && pins_state[3] == 1 && (millis() - pins_time[3] >= 3000 /*Abspielzeit bzw. Blockierzeit*/ )) {
pins_state[3] = 0;
pins_time[3] = 0;
}
//Pin 3 Ende
//Pin 4 Anfang
if(int(pins[4]) == 1 && pins_state[4] == 0) {
pins_state[4] = 1;
println("Pin 4 touched"); //hier OSC message
pins_time[4] = millis();
} else if (int(pins[4]) == 0 && pins_state[4] == 1 && (millis() - pins_time[4] >= 3000 /*Abspielzeit bzw. Blockierzeit*/ )) {
pins_state[4] = 0;
pins_time[4] = 0;
}
//Pin 4 Ende
//Pin 5 Anfang
if(int(pins[5]) == 1 && pins_state[5] == 0) {
pins_state[5] = 1;
println("Pin 5 touched"); //hier OSC message
pins_time[5] = millis();
} else if (int(pins[5]) == 0 && pins_state[5] == 1 && (millis() - pins_time[5] >= 3000 /*Abspielzeit bzw. Blockierzeit*/ )) {
pins_state[5] = 0;
pins_time[5] = 0;
}
//Pin 5 Ende
//Pin 6 Anfang
if(int(pins[6]) == 1 && pins_state[6] == 0) {
pins_state[6] = 1;
println("Pin 6 touched"); //hier OSC message
pins_time[6] = millis();
} else if (int(pins[6]) == 0 && pins_state[6] == 1 && (millis() - pins_time[6] >= 3000 /*Abspielzeit bzw. Blockierzeit*/ )) {
pins_state[6] = 0;
pins_time[6] = 0;
}
//Pin 6 Ende
//Pin 7 Anfang
if(int(pins[7]) == 1 && pins_state[7] == 0) {
pins_state[7] = 1;
println("Pin 7 touched"); //hier OSC message
pins_time[7] = millis();
} else if (int(pins[7]) == 0 && pins_state[7] == 1 && (millis() - pins_time[7] >= 3000 /*Abspielzeit bzw. Blockierzeit*/ )) {
pins_state[7] = 0;
pins_time[7] = 0;
}
//Pin 7 Ende
//Pin 8 Anfang
if(int(pins[8]) == 1 && pins_state[8] == 0) {
pins_state[8] = 1;
println("Pin 8 touched"); //hier OSC message
pins_time[8] = millis();
} else if (int(pins[8]) == 0 && pins_state[8] == 1 && (millis() - pins_time[8] >= 3000 /*Abspielzeit bzw. Blockierzeit*/ )) {
pins_state[8] = 0;
pins_time[8] = 0;
}
//Pin 8 Ende
//Pin 9 Anfang
if(int(pins[9]) == 1 && pins_state[9] == 0) {
pins_state[9] = 1;
println("Pin 9 touched"); //hier OSC message
pins_time[9] = millis();
} else if (int(pins[9]) == 0 && pins_state[9] == 1 && (millis() - pins_time[9] >= 3000 /*Abspielzeit bzw. Blockierzeit*/ )) {
pins_state[9] = 0;
pins_time[9] = 0;
}
//Pin 9 Ende
//Pin 10 Anfang
if(int(pins[10]) == 1 && pins_state[10] == 0) {
pins_state[10] = 1;
println("Pin 10 touched"); //hier OSC message
pins_time[10] = millis();
} else if (int(pins[10]) == 0 && pins_state[10] == 1 && (millis() - pins_time[10] >= 3000 /*Abspielzeit bzw. Blockierzeit*/ )) {
pins_state[10] = 0;
pins_time[10] = 0;
}
//Pin 10 Ende
//Pin 11 Anfang
if(int(pins[11]) == 1 && pins_state[11] == 0) {
pins_state[11] = 1;
//println("Pin 11 touched");
OSCMessage.setAddrPattern( "/layer2/clip2/connect" );
OSCMessage.add( 1 );
OSCBundle.add( OSCMessage );
OSCMessage.clear();
oscP5.send( OSCBundle, OSCLocation );//hier OSC message
pins_time[11] = millis();
} else if (int(pins[11]) == 0 && pins_state[11] == 1 && (millis() - pins_time[11] >= 3000 /*Abspielzeit bzw. Blockierzeit*/ )) {
pins_state[11] = 0;
pins_time[11] = 0;
}
//Pin 11 Ende
//println(int(pins[0]) == 1);
/*
String touchedElectrodes = "";
for ( int i = 0; i < electrodes.length; i++ ) {
int value = parseInt( electrodes[i] );
if ( value > 0 ) {
//OSC Message Start hier
OSCMessage.setAddrPattern( "/layer" + electrodes[i] + "/clip1/connect" );
OSCMessage.add( 1 );
OSCBundle.add( OSCMessage );
OSCMessage.clear();
oscP5.send( OSCBundle, OSCLocation );
// OSC Message Ende
}
}*/
}
This is what it sends when touching one of the electrodes a single time:
Am I missing something obvious?
Re: OSC Sending Problem
Posted: Tue Nov 08, 2016 21:19
by Zoltán
you forget to clear the oscBundle after sending it
edit:
also be avare that casting a string to int will result in 0 if the string is
- "0"
- empty
- null
- contains any other characters than numbers
maybe a better, error handling capable way to convert a string to integer would be using the Integer.parseInt(myString) method, which can throw a numberFormatException which you'd need to catch of course.