OSCUino- how to use received messages

Hello

I'm using the OSCuino library to successfully receive / send messages. Using the UDPEcho example, I can receive, and then in turn, send the message back to the host / server software, which in this case is Touch Designer.

What I'm trying to learn is how to program some logic based on the received message on the Arduino. I'm trying to use the received message, turn it into a variable, and based on the value of the variable, execute some commands. In pseudo-pseudo code:

On Arduino- receive message (example- 11001)
cast message to an int
if the first digit of the int is 1- do this
if the second digit of the int is 1- do this
if the third digit of the int is 1- do this
if the fourth digit of the int is 1- do this
if the fifth digit of the int is 1- do this

My problem is i can't figure out how to "access" the incoming message, or in other words, turn it into a variable. I know the message is there, because I am accurately sending it back to the host program.

Thanks for helping a newb.

My problem is i can't figure out how to "access" the incoming message

Then, how do you know you are receiving anything?

Clearly, you have some code on the Arduino that is doing something. You need to post it.

PaulS thanks- I'm using the example code "UDPEcho" from the OSCuino library.

/*

Leverage the UDP source IP and port calls to 
return OSC information back

This example can be extended to build routers and forwarders of OSC packets

 */
#include <Ethernet.h>
#include <EthernetUdp.h>
#include <SPI.h>    
#include <OSCBundle.h>

EthernetUDP Udp;

//the Arduino's IP
IPAddress ip(128, 32, 122, 252);

//port numbers
const unsigned int inPort = 8888;
const unsigned int outPort = 9999;


 byte mac[] = {  
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; // you can find this written on the board of some Arduino Ethernets or shields
void setup() {
  Ethernet.begin(mac,ip);
  Udp.begin(inPort);
}

void loop(){
    OSCBundle bndl;
   int size;
   
    //receive a bundle
   if( (size = Udp.parsePacket())>0)
   {
//        unsigned int outPort = Udp.remotePort();

         while(size--)
           bndl.fill(Udp.read());

       //This is where I'm stuck. I want to use the incoming message to do some work before I send it back out.

        if(!bndl.hasError())
        {
              //and echo it back
             if(bndl.size() > 0)
             {
                static int32_t sequencenumber=0;

                // we can sneak an addition onto the end of the bundle
               bndl.add("/micros").add((int32_t)micros()); // (int32_t) is the type of OSC Integers
                bndl.add("/sequencenumber").add(sequencenumber++);

                Udp.beginPacket(Udp.remoteIP(), outPort);
                bndl.send(Udp);
                Udp.endPacket();     
             }
        }
   }
}

The way i know it works is because I am using Touch Designer as a sender and receiver. So, Touch Designer creates a constantly updating message, sends it, the Arduino receives it, processes it, and sends it back to Touch Designer. I can see the sent and received messages, and can verify that they are indeed making the round trip.

I'm not a good Processing or Arduino programmer, and I'm wondering if there's any way someone with experience with the OSCuino library could help me understand it a little better. This is a test setup, so I can learn how to translate the incoming message into an int variable I can work with. Once I can figure out how to do that, I can hopefully gain some insight into how to make the library truly useful for me.

The actual documentation - the section I'm learning is here:

http://cnmat.berkeley.edu/library/oscuino/omessage

It's just a bit over my head as a newb. I'm trying to work with messages instead of bundles, and learning as I go. Thanks.

I'm wondering if there's any way someone with experience with the OSCuino library could help me understand it a little better.

I don't think that experience with that particular package is necessary.

    //receive a bundle
   if( (size = Udp.parsePacket())>0)
   {
//        unsigned int outPort = Udp.remotePort();

         while(size--)
           bndl.fill(Udp.read());

The Arduino gets a UDP packet, and does nothing with it except feed it to another instance.

If you wanted to do something with the message, you'd store what Udp.read() returned in an array, manipulate that array, and then give the modified array to the fill() method (perhaps one character at a time).

It's still all handwaving, though, until you show us what these messages look like, and explain how you want to map the incoming message to the outgoing message.

Just FYI, the only reason I'm using OSC as a wrapper is due to way the "host / server" program (Touch Designer) works. It's the fastest way to transmit UDP when communicating with an Arduino (that I can use right now, with my hardware/ software combo). I'm using a very new Arduino Uno R3, and a very new Arduino Ethernet Shield, which I haven't mentioned yet.

My incoming OSC message is always formatted like this - it never varies in its format. From http://opensoundcontrol.org/spec-1_0

An OSC message consists of an OSC Address Pattern followed by an OSC Type Tag String followed by zero or more OSC Arguments.

The incoming message is "/ard/12345", where the argument is always a 5 digit int. It could be "11111", or "91919", but it will never be longer or shorter than 5 digits. The address will never change, it's always "/ard".

When the OSC message arrives at the Arduino, I want to "intercept" it, then break the OSC message argument into 5 variables- 5 single digits ints.

Each of these will will be used to drive processes on the Arduino. They are not specific processes yet. I'm trying to build a solid communication foundation between Touch Designer and Arduino first, before I start designing Arduino processes. So, for example, I could create a scenario like this:

argument digit 1 becomes a variable that is used to drive a motor
argument digit 2 becomes a variable that is used to drive an led
argument digit 3 becomes a variable that is used to drive a different led
etc.

After the Arduino has intercepted, interpreted, and used the incoming message, I'll send a customized message back to Touch Designer.

There are many OSC libraries for the Arduino, the reason I am using OSCuino is that it seems like the most robust. But I'm finding the documentation to be over my head. I can successfully receive OSC bundles, and I can build custom messages and bundles to send. It's pretty easy to build bundles to send:

OSCBundle bndlOUT;
bndlOUT.add("/from_ard").add(111);
Udp.beginPacket(Udp.remoteIP(), outPort);
bndlOUT.send(Udp);
Udp.endPacket();

The part of this process that I'm stuck on is how to (on the Arduino) break the incoming OSC message argument into 5 variables- 5 single digits ints. Once I have those, I can use the variables in custom functions.

Thanks very much for your help-

I got it working. Wheew. I will post results here in a few hours.

The trick, in my case, was to route the incoming bundle to another function called MOTORControl(). That helped me turn the bundle into a message, and from there i used

float inValue = msg.getFloat(0);

to get the message.

//OSCUINO------------------------------------------------------------
#include <Ethernet.h>
#include <EthernetUdp.h>
#include <SPI.h>    
#include <OSCBundle.h>
EthernetUDP Udp;

//the Arduino's IP
IPAddress ip(192, 168, 1, 70);

// you can find this written on the board of some Arduino Ethernets or shields
byte mac[] = {  0x90, 0xA2, 0xDA, 0x0F, 0x23, 0x58  }; 

//port numbers
const unsigned int inPort = 8888; // Touch Designer OSC out CHOP
const unsigned int outPort = 9999; // Touch Designer OSC in CHOP



//SERVO-------------------------------------------------------------------------
#include <Servo.h> 
Servo myservo;  // create servo object to control a servo // a maximum of eight servo objects can be created 
int pos = 0;    // variable to store the servo position 
 
 
 
 
 
void setup() 
{ 
  //OSCuino
  Ethernet.begin(mac,ip);
  Udp.begin(inPort);

  myservo.attach(9);  // attaches the servo on pin 9 to the servo object 

} 
 
 
 
 
 
void MOTORControl(OSCMessage &msg, int offset){

            float inValue = msg.getFloat(0);
            //inValue = inValue + 1;

            myservo.write(inValue);  //0=full reverse, ~90= stall, 180=full forward
            
            OSCBundle bndlOUT;
            bndlOUT.add("/from_ard").add(inValue+1);
            Udp.beginPacket(Udp.remoteIP(), outPort);
            bndlOUT.send(Udp);
            Udp.endPacket(); 
}
 
 
 
 
void loop() 
{ 
    OSCBundle bndl;
    int size;
   
    //receive a bundle
   if( (size = Udp.parsePacket())>0)
   {
         while(size--)
           bndl.fill(Udp.read());

        if(!bndl.hasError())
        {
          
          //DO SOME WORK HERE-------------------
          bndl.route("/step", MOTORControl);
          
              //and echo it back
             if(bndl.size() > 0)
             {
                //static int32_t sequencenumber=0;
                //we can sneak an addition onto the end of the bundle
                //bndl.add("/micros").add((int32_t)micros()); // (int32_t) is the type of OSC Integers
                //bndl.add("/sequencenumber").add(sequencenumber++);

                Udp.beginPacket(Udp.remoteIP(), outPort);
                bndl.send(Udp);
                Udp.endPacket();     
             }
        }
   }                              



}