OSC messages controlling 2 servos

Hi there,

I'm trying to controll 2 servos with my iPhone/iPad with TouchOSC. One servo works perfect but two... thats the problem.

Here is my setup:
iPhone > TouchOSC (2 faders) > Processing > Arduino (with io shield) > servoA and servoB

Arduino Code:

#include <Servo.h> 

Servo myservo;
Servo myservo2;// create servo object to control a servo 

int val = 0;    
//int message = 0;     
int redLED = 0;

void setup() {  
  Serial.begin(9600);  //set serial to 9600 baud rate
  myservo.attach(8);
  myservo2.attach(9);

  
}

void loop(){  
    if (Serial.available() > 0) { //  Check if there is a new message
      val = Serial.read();    //  Put the serial input into the message
      //val = message;
      myservo.write(val);                  // sets the servo position according to the scaled value 
      delay(15); 
      myservo2.write(val);                  // sets the servo position according to the scaled value 
      delay(15);  
      
    }   
}

Processing Code:

import oscP5.*;        //  Load OSC P5 library
import netP5.*;        //  Load net P5 library
import processing.serial.*;    //  Load serial library

Serial arduinoPort;        //  Set arduinoPort as serial connection
OscP5 oscP5;            //  Set oscP5 as OSC connection
// arduino //

int redLED = 0;
int redLEDB = 0;
int [] led = new int [2];
int currentPos = 0;
int desiredPos = 0;
int currentPosB = 0;
int desiredPosB = 0;

void setup() {
  size(200,200);
  noStroke();
  oscP5 = new OscP5(this,8000);  // Start oscP5, listening for incoming messages at port 8000
  arduinoPort = new Serial(this, Serial.list()[0], 9600);    // Set arduino to 9600 baud
}


void oscEvent(OscMessage theOscMessage) {

	String addr = theOscMessage.addrPattern();
	if(addr.indexOf("/1/servo") != -1) {
	desiredPos = int(theOscMessage.get(0).floatValue());
        }
        if(addr.indexOf("/2/servo2") != -1) {
	desiredPosB = int(theOscMessage.get(0).floatValue());
        }


}

void draw() {

background(50);

	if(currentPos != desiredPos) {
	String pos = str(desiredPos);
        println("Servo_A " + pos);
	arduinoPort.write(desiredPos);
	currentPos = desiredPos;
}

        if(currentPosB != desiredPosB) {
	String pos = str(desiredPosB);
        println("Servo_B " + pos);
	arduinoPort.write(desiredPosB);
	currentPosB = desiredPosB;
}

redLED = int(map(desiredPos, 0, 180, 0, 255));
	fill(redLED,0,0);
	ellipse(50,50,50,50);

redLEDB = int(map(desiredPosB, 0, 180, 0, 255));
	fill(redLEDB,0,0);
	ellipse(120,50,50,50);
}

Both servos are moving if I change the sliders on the iPhone.

Help?

Both servos are moving if I change the sliders on the iPhone.

Why does that surprise you?

      val = Serial.read();    //  Put the serial input into the message
      //val = message;
      myservo.write(val);                  // sets the servo position according to the scaled value 
      delay(15); 
      myservo2.write(val);                  // sets the servo position according to the scaled value 
      delay(15);

You are telling both servos to go to the same position.

Looks to me like you want to read a value, send one servo to that position, read another value and send the other servo to that position.

Thanks, I get the point to define an extra value but don't know how to write it down in the script (sorry i'm a newbie)

Thanks, I get the point to define an extra value but don't know how to write it down in the script (sorry i'm a newbie)

Make the highlighted changes:

if (Serial.available() > 1)
{ // Check if there are 2 new messages
val = Serial.read(); // Put the serial input into the message
myservo.write(val); // sets the servo position according to the scaled value
delay(15);
val = Serial.read(); // Put the serial input into the message
myservo2.write(val); // sets the servo position according to the scaled value
delay(15);
}

Thanks I changed the code, still both servo's move on both sliders in TouchOSC. Is there a way to 'link' the right incoming message to the right output? I guess something goes wrong in the processing code...

void draw() {

background(50);

	if(currentPos != desiredPos) {
	String pos = str(desiredPos);
        println("Servo_A " + pos);
	arduinoPort.write(desiredPos);
	currentPos = desiredPos;
}

        if(currentPosB != desiredPosB) {
	String pos = str(desiredPosB);
        println("Servo_B " + pos);
	arduinoPort.write(desiredPosB);
	currentPosB = desiredPosB;
}

You need to send an identifier for each value, so that the Arduino knows which servo to move.

I guess something goes wrong in the processing code...

Only you can see the debug output from Processing. So, if you have to guess that there is something wrong, then we have no way to argue with you.

You need to send an identifier for each value, so that the Arduino knows which servo to move.

Looking at the Processing code, I don't see the need. There is an OSC event when you move a slider. In the event handler, either desiredPos or desiredPosB (desiredPos should be desiredPosA) is given a new value. Nothing is sent to the Arduino, though.

In the draw() method, desiredPos and desiredPosB are compared to the old positions, and only the changed values are sent. So, yes, you are right. There may only be one value sent per iteration of loop.

There needs to be two values sent - which servo should move and where it should move to.

Both draws are writing to the same arduinoPort (arduinoPort.write(desiredPosB); ) is that what you mean? How do I create a unique id for each port (still learning...)

Both draws are writing to the same arduinoPort

There us only one draw() method. It contains two statements that conditionally write to the same port.

Add another write() statement in each block:
if(currentPos != desiredPos) {
String pos = str(desiredPos);
println("Servo_A " + pos);
arduinoPort.write('A');
arduinoPort.write(desiredPos);
currentPos = desiredPos;
}

if(currentPosB != desiredPosB) {
String pos = str(desiredPosB);
println("Servo_B " + pos);
arduinoPort.write('B');
arduinoPort.write(desiredPosB);
currentPosB = desiredPosB;
}

Then, change the Arduino code:
if (Serial.available() > 1)
{ // Check if there are 2 new messages
char srv = Serial.read(); // Read which servo
val = Serial.read(); // Read the position
if(srv == 'A')
myservo.write(val); // sets the servo position according to the scaled value
else if (srv == 'B')
myservo2.write(val); // sets the servo position according to the scaled value
delay(15);
}

There needs to be two values sent - which servo should move and where it should move to.

Which is what I said.

Which is what I said.

Sure. I was just elaborating on what the two values were, and why sending what was currently being sent was not sufficient.

I'm sure you knew right off the bat why, but OP certainly didn't.

It Works! Thank you so much...