Touch OSC and Arduino

Hi there, I’m trying to control a set of LEDs with my ipod touch, using an app called TouchOSC. I want to be able to dim each LED individually from the iPod. Basically, the app on the iPod sends a value to processing, on my Mac, which then sends that value onto the arduino through serial. The arduino is then supposed to read the serial, figure out which LED it has to dim, and then dim it to that level.

I can turn each LED on and off individually using a different set of sketches, but I’m having trouble with this dimming one. I can see that processing is receiving the number from the iPod properly, because it prints it properly, but it doesn’t dim the lights on the arduino.

Any help would be greatly appreciated!
(P.S. the app that creates the TouchOSC templates is called TouchOSC Editor. I’ve tried to attach the templates I’ve created/am using, hopefully they upload properly)

Arduino code for the dimmer:

int LBlue = 3;
int LGreen = 5;
int LRed = 6;
int RBlue = 11;
int RGreen = 10;
int RRed = 9;
int message = 0;
int number = -1;
int value = 0;
String bla = "";

int serReadInt()


{
 int i, serAva;                           // i is a counter, serAva hold number of serial available
 char inputBytes [7];                 // Array hold input bytes
 char * inputBytesPtr = &inputBytes[0];  // Pointer to the first element of the array
     
 if (Serial.available()>0)            // Check to see if there are any serial input
 {
   delay(5);                              // Delay for terminal to finish transmitted
                                              // 5mS work great for 9600 baud (increase this number for slower baud)
   serAva = Serial.available();  // Read number of input bytes
   for (i=0; i<serAva; i++)       // Load input bytes into array
     inputBytes[i] = Serial.read();
   inputBytes[i] =  '\0';             // Put NULL character at the end
   return atoi(inputBytesPtr);    // Call atoi function and return result
 }
 else
   return -1;                           // Return -1 if there is no input
}

void setup()  {
  Serial.begin(9600);
  
}

void loop()  {
  while (Serial.available()) {
	  delay(10);
	    if (Serial.available() >0) {
	  number = serReadInt();
	  }

	if (number > -1) {
	Serial.print(number);
      }

    
    
    if(number <= 255)  {
      value = number;
      bla = "Left Blue";
      analogWrite(LBlue,value);
    }
    else if((number <= 511) && (number >= 256))  {
      value = number - 256;
      bla = "Left Green";
      analogWrite(LGreen, value);
    }
    else if((number <= 767) && (number >= 512))  {
      value = number - 512;
       bla = "Left Red";
      analogWrite(LRed,value);
    }
    else if((number <= 1023) && (number >=768))  {
      value = number - 768;
       bla = "Right Red";
      analogWrite(RRed, value);
    }
    else if((number <= 1279) && (number >= 1024))  {
      value = number - 1024;
       bla = "Right Green";
      analogWrite(RGreen,value);
    }
    else if((number <= 1535) && (number >= 1280))  {
      value = number - 1280;
       bla = "Right Blue";
      analogWrite(RBlue, value);
    }
    else if (number < 0)  {
      analogWrite(LBlue,255);
    }
  
  Serial.print("   ");
  Serial.print(value);
  Serial.println(" - " + bla);
  Serial.println("LBlue=0-255  LGreen=256-511  LRed=512-767  RRed=768-1023  RGreen=1024-1279  RBlue=1280-1535");
 
  delay(1000);
  number = -1;
}
}

Processing code for the dimmer:

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

float val = 0;
int message = 0;

    //  Array allows us to add more toggle buttons in TouchOSC


void setup() {
  size(130,130);        // Processing screen size
  noStroke();            //  We don’t want an outline or Stroke on our graphics
    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) {   //  This runs whenever there is a new OSC message

    String addr = theOscMessage.addrPattern();  //  Creates a string out of the OSC message
    if(addr.equals("/1/fader1"))  {
      float val = theOscMessage.get(0).floatValue();
      int message = (int) val;
    }
    else if(addr.equals("/1/fader2"))  {
      float val = theOscMessage.get(0).floatValue();
      int message = (int) val;
    }
    else if(addr.equals("/1/fader3"))  {
      float val = theOscMessage.get(0).floatValue();
      int message = (int) val;
    }
    else if(addr.equals("/1/fader3"))  {
      float val = theOscMessage.get(0).floatValue();
      int message = (int) val;
    }
   else if(addr.equals("/1/fader4"))  {
      float val = theOscMessage.get(0).floatValue();
      int message = (int) val;
    }
    else if(addr.equals("/1/fader5"))  {
      float val = theOscMessage.get(0).floatValue();
      int message = (int) val;
    }
    else if(addr.equals("/1/fader6"))  {
      float val = theOscMessage.get(0).floatValue();
      int message = (int) val;
    }
   
}

void draw() {
 background(50);

  arduinoPort.write(message);


}

Arduino code for on/off (this works fine, just giving it as an example):

int LBlue = 3;
int LBb = 0;
int LGreen = 5;
int LGb = 0;
int LRed = 6;
int LRb = 0;
int RBlue = 11;
int RBb = 0;
int RGreen = 10;
int RGb = 0;
int RRed = 9;
int RRb;
int message = 0;

void setup()  {
  Serial.begin(9600);
}

void loop()  {
  if(Serial.available() > 0)  {
    message = Serial.read();
    
    if (message == 'B')  {
      LBb = 255;
    }
    if (message == 'b')  {
      LBb = 0;
    }
    if (message == 'G')  {
      LGb = 255;
    }
    if (message == 'g')  {
      LGb = 0;
    }
    if (message == 'R')  {
      LRb = 255;
    }
    if (message == 'r')  {
      LRb = 0;
    }
    if (message == 'V')  {
      RBb = 255;
    }
    if (message == 'v')  {
      RBb = 0;
    }
    if (message == 'F')  {
      RGb = 255;
    }
    if (message == 'f')  {
      RGb = 0;
    }
    if (message == 'E')  {
      RRb = 255;
    }
    if (message == 'e')  {
      RRb = 0;
    }
    analogWrite(LBlue,LBb);
    analogWrite(LGreen,LGb);
    analogWrite(LRed,LRb);
    analogWrite(RBlue,RBb);
    analogWrite(RGreen,RGb);
    analogWrite(RRed,RRb);
  }
}

Processing code for on/off:

import oscP5.*;
import netP5.*;
import processing.serial.*;

Serial arduinoPort;
OscP5 oscP5;

float LBlue = 0.0f;
float LGreen = 0.0f;
float LRed = 0.0f;
float RBlue = 0.0f;
float RGreen = 0.0f;
float RRed = 0.0f;

void setup()  {
  size(100,100);
  oscP5 = new OscP5(this,8000);
  arduinoPort = new Serial(this,Serial.list()[0],9600);
}

void oscEvent(OscMessage theOscMessage)  {
  String addr = theOscMessage.addrPattern();
  float val = theOscMessage.get(0).floatValue();
  if(addr.equals("/1/toggle1"))  {LBlue = val;  }
  else if(addr.equals("/1/toggle2"))  {LGreen = val;  }
  else if(addr.equals("/1/toggle3"))  {LRed = val;  }
  else if(addr.equals("/1/toggle4"))  {RBlue = val;  }
  else if(addr.equals("/1/toggle5"))  {RGreen = val;  }
  else if(addr.equals("/1/toggle6"))  {RRed = val;  }
  
}
void draw()  {
  background(50);
  
  if(LBlue == 1.0f)
  {
    arduinoPort.write("B");
  }
  else
  {
    arduinoPort.write("b");
  }
  if(LGreen == 1.0f)
  {
    arduinoPort.write("G");
  }
  else
  {
    arduinoPort.write("g");
  }
  if(LRed == 1.0f)
  {
    arduinoPort.write("R");
  }
  else
  {
    arduinoPort.write("r");
  }
  if(RBlue == 1.0f)
  {
    arduinoPort.write("V");
  }
  else
  {
    arduinoPort.write("v");
  }
  if(RGreen == 1.0f)
  {
    arduinoPort.write("F");
  }
  else
  {
    arduinoPort.write("f");
  }
  if(RRed == 1.0f)
  {
    arduinoPort.write("E");
  }
  else
  {
    arduinoPort.write("e");
  }
  print(LBlue);
  print("   ");
  print(LGreen);
    print("   ");
  print(LRed);
    print("   ");
  print(RBlue);
    print("   ");
  print(RRed);
    print("   ");
  println(RGreen);
}

LED sliders.touchosc (428 Bytes)

LED toggles.touchosc (361 Bytes)

    if(addr.equals("/1/fader1"))  {
      float val = theOscMessage.get(0).floatValue();
      int message = (int) val;
    }

It doesn't appear that addr really matters. Regardless of the value of addr, you create a local variable, val, and extract a value from theOscMessage in exactly the same way. Then, you create a local variable, message, and convert the float to an int.

Those local variables go out of scope at the end of the if block they are defined in, so the values in them are lost.

Then, in the draw() method, you send the value of the global variable message to the Arduino. The global variable never gets a new value, so it is always 0.

Your function for reading data from the serial port on the Arduino needs work, as does the Processing code for writing data to the serial port.

There are no delimiters used between values, so if the Processing application writes new value to the serial port on every iteration through draw, as it does today, it will be sending a steady stream of data like "000000000000000000000000000000000000000". Where does one value end and another begin?

Suppose you fix the sending code to be sending something other than a steady stream of 0s. You might end up sending values like 100, 120, 137, 84, 299, and 580 as fast as you can, like "10012013784299580".

Now, how are you going to deal with that on the Arduino side?

On the Arduino side, you have an array that can hold 7 characters. You determine how many characters are available, and read that number of characters, and store them in the array. After reading all the data, you append a NULL to the string.

Now, this is all good, until there are 7 characters or more available to read. In that case, you will happily write beyond the end of your buffer, and overwrite something else.

Get rid of the delay. Send a delimiter, and read until the delimiter arrives or until the array is full. Then, use the value in the array and re-initialize the array.

By the way, inputBytes is also a "pointer to the first element of the array", so inputBytesPtr is unnecessary.

Thanks for the quick reply! I'm pretty new to all of this, and I don't have much of a background in computing or coding. How do I do what you just suggested?

How do I do what you just suggested?

I suggested lots of things. First, and most important, you need to get rid of the float and int type declarations in the oscEvent callback in the Processing application, so that val and message refer to the global variables.

    if(addr.equals("/1/fader1"))  {
      val = theOscMessage.get(0).floatValue();
      message = (int) val;
    }

Test this change, to see if the Processing application is now sending something other than a stream of 0s.

Once that works, we can work on making the actual exchange of data correct.

Hi again, thanks for your patience. I tried one or two changes, with the help of a kind and awesome friend. We’ve finally got it working!

Here is the working code, for anyone that might be interested:

Arduino code:

int LBlue = 9;
int LGreen = 10;
int LRed = 11;
int RBlue = 5;
int RGreen = 3;
int RRed = 6;
int message = 0;
int number = -1;
int value = 0;
String bla = "";

int serReadInt()


{
 int i, serAva;                           // i is a counter, serAva hold number of serial available
 char inputBytes [7];                 // Array hold input bytes
 char * inputBytesPtr = &inputBytes[0];  // Pointer to the first element of the array
     
 if (Serial.available()>0)            // Check to see if there are any serial input
 {
   delay(5);                              // Delay for terminal to finish transmitted
                                              // 5mS work great for 9600 baud (increase this number for slower baud)
   serAva = Serial.available();  // Read number of input bytes
   for (i=0; i<serAva; i++)       // Load input bytes into array
     inputBytes[i] = Serial.read();
   inputBytes[i] =  '\0';             // Put NULL character at the end
   return atoi(inputBytesPtr);    // Call atoi function and return result
 }
 else
   return -1;                           // Return -1 if there is no input
}

void setup()  {
  Serial.begin(9600);
  
}

void loop()  {
  while (Serial.available()) {
	  delay(10);
	    if (Serial.available() >0) {
	  number = serReadInt();
	  }

	if (number > -1) {
	Serial.print(number);
      }

    
    
    if(number <= 255)  {
      value = number;
      bla = "Left Blue";
      analogWrite(LBlue,value);
    }
    else if((number <= 511) && (number >= 256))  {
      value = number - 256;
      bla = "Left Green";
      analogWrite(LGreen, value);
    }
    else if((number <= 767) && (number >= 512))  {
      value = number - 512;
       bla = "Left Red";
      analogWrite(LRed,value);
    }
    else if((number <= 1023) && (number >=768))  {
      value = number - 768;
       bla = "Right Red";
      analogWrite(RRed, value);
    }
    else if((number <= 1279) && (number >= 1024))  {
      value = number - 1024;
       bla = "Right Green";
      analogWrite(RGreen,value);
    }
    else if((number <= 1535) && (number >= 1280))  {
      value = number - 1280;
       bla = "Right Blue";
      analogWrite(RBlue, value);
    }
    else if (number < 0)  {
      analogWrite(LBlue,255);
    }
  
  Serial.print("   ");
  Serial.print(value);
  Serial.println(" - " + bla);
  Serial.println("LBlue=0-255  LGreen=256-511  LRed=512-767  RRed=768-1023  RGreen=1024-1279  RBlue=1280-1535");
 
  delay(1000);
  number = -1;
}
}

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

float val = 0;
int message = 0;

    //  Array allows us to add more toggle buttons in TouchOSC


void setup() {
  size(130,130);        // Processing screen size
  noStroke();            //  We don’t want an outline or Stroke on our graphics
  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) {   //  This runs whenever there is a new OSC message

  String addr = theOscMessage.addrPattern();  //  Creates a string out of the OSC message
  float val = theOscMessage.get(0).floatValue();
  message = (int) val;
  arduinoPort.write(Integer.toString(message));
}

void draw() {
  background(50);
}

Attached is the TouchOSC template.

LED sliders.touchosc (428 Bytes)