Reading a OSC message from Arduino

Hello,

my main goal is to read OSC messages (sent via LAN) from the Arduino board such that I can control the GPIO in runtime.

I’m using the ENC28J60 controller as ethernet chip and a library written for that chip.

For managing the OSC part I’ve decided to use this library instead, called OSCuino written at University of Berkeley.

At the moment I’m sending OSC messages to the ENC28J60 chip, but Arduino seems not to correctly interpret them. Here’s an example: from my computer (ip: 192.168.1.5) I’m sending a OSC msg via a client written in Java (I’m posting it into a spoiler at the end of this post) and listening from Arduino via the following sketch

// Code largely inspired by the udpListener.ino sketch
// you can find in Brian Lee's library, "EtherCard".
//
// Credits to Brian Lee <cybexsoft@hotmail.com>

#include <EtherCard.h>
#include <IPAddress.h>

#include <OSCMessage.h>
#include <OSCBundle.h>

/* Network-unique MAC address for the ENC28J60 controller */
static byte mymac[] = { 0x70,0x69,0x69,0x2D,0x30,0x31 };

/* TCP/IP send/receive buffer */
byte Ethernet::buffer[500];

/* Defining a constant for a LED. Maybe useful on testing */
const unsigned int led=7;

/* Callback that prints received packets to the serial port */
void udpSerialPrint(word port, byte ip[4], const char *data, word len) {
  IPAddress src(ip[0], ip[1], ip[2], ip[3]);
  Serial.println(src);
  Serial.println(port);
  Serial.println(data);
  Serial.println(len);
}

/* Callback that changes state of a led depending on the received OSC message */
void udptoGPIO(word port, byte ip[4], const char *data, word len) {

  // Local debug here
  Serial.print("Content of datagram: ");
  Serial.println(data);
  Serial.print("Its length: ");
  Serial.println(len);

  OSCMessage msg("/led");

  msg.fill((uint8_t)data, len);

  /* If OSC message contains "on", then switch the led on */
  /*
  if (msg.fullmatch("/led/on")) {
    digitalWrite(led, HIGH);
  }
  */
    
}

void setup(){
  Serial.begin(57600);
  Serial.println("\n[backSoon]");
  
  if (ether.begin(sizeof Ethernet::buffer, mymac) == 0)
    Serial.println( "Failed to access Ethernet controller");

  if (!ether.dhcpSetup())
    Serial.println("DHCP failed");

  ether.printIp("IP:  ", ether.myip);
  ether.printIp("GW:  ", ether.gwip);
  ether.printIp("DNS: ", ether.dnsip);

  /* Register udpSerialPrint() to port 1337 */
  ether.udpServerListenOnPort(&udpSerialPrint, 1337);

  /* Setup GPIO stuff ...*/
  pinMode(led, OUTPUT);

  /* ... and register udptoGPIO() to port 8888 */
  ether.udpServerListenOnPort(&udptoGPIO, 8888);

}

void loop(){
  /* This MUST be called for ethercard functions to work */
  ether.packetLoop(ether.packetReceive());
}

though the statement

msg.fullmatch("/led/on")

turns out to be always false.

Where am I wrong?

Follows the code for a OSC client, written in Java. I’m pretty sure this is working since I’ve already used it for other applications.

import java.util.*;
import com.illposed.osc.*;
import java.net.*;

public class RemoteCommand {
    public static int MAX=255;
    public static void main(String[] arg) throws Exception {
        byte[] addr = {(byte)192, (byte)168, (byte)1, (byte)10};
        OSCPortOut sender =
        new OSCPortOut(InetAddress.getByAddress(addr),8888);

        Object args[] = new Object[1];
        args[0] = "on";

        OSCMessage msg = new OSCMessage("/led", args);
        System.out.println("Sent " + msg);

        try {
            sender.send(msg);
        } catch (Exception e) {
            e.printStackTrace();
        }

        Thread.sleep(100);
   }
}

Thank you in advance,

giuscri

there are several reasons why this does not work:

  1. The readme on the CNMat site says "- Sends and receives OSC packets over transport layers that implements the Arduino Stream Class such as Serial and Ethernet UDP" I don't think the ENC28J60 library does that. EthernetUDP is part of the Ethernet library that works with the Ethernet Shield or in general with Shields and embedded Ethernet Modules that use an Wiznet W5100 or W5200 chip. In essence the library that comes with the ENC28J60 would have to implement the pure virtual methods defined in UDP.h. I haven't looked at it in detail but, again, I don't think it does that.

  2. In order to use the OSCuino library you first have to receive a UDP package before you can fill the OSC message object with msg.fiill. Here is a little code snippet from one of my sketches that shoes how to receive a UDP packet and then fill the OSCmessage with msgIN.fill and then parse and route it to a callback function with msgIN.route().

void msgReceive(){
    OSCMessage msgIN;
    int size;
    if((size = Udp.parsePacket())>0){
        while(size--)
            msgIN.fill(Udp.read());
        if(!msgIN.hasError()){
            msgIN.route("/analog", handleAnalog);
            msgIN.route("/digital", handleDigital);
        }
    }
}

You am actually have more luck using this library for your Ethernet shield : http://forum.arduino.cc/index.php?topic=178024.120

It's API looks much closer to the Ethernet library than the on you linked to.