Wemos (esp8266) and Sonic Pi OSC


#1

Hello I’m trying to send data from my Wemos D1 module (ESP8266 based) to Sonic pi thru OSC.

I found an example on the help files of Sonic Pi for a local osc receving package.
And I have code I thought would work on the ESP8266 to send the data to Sonic Pi.

This is the code for Sonic Pi

live_loop :foo do
  use_real_time
  a, b, c = sync "/osc/trigger/prophet"
  synth :prophet, note: a, cutoff: b, sustain: c
end

And this is the code on the Module

/***************************************************
This is a library for the Si1145 UV/IR/Visible Light Sensor

Designed specifically to work with the Si1145 sensor in the
adafruit shop
----> https://www.adafruit.com/products/1777

These sensors use I2C to communicate, 2 pins are required to
interface
Adafruit invests time and resources providing this open source code,
please support Adafruit and open-source hardware by purchasing
products from Adafruit!

Written by Limor Fried/Ladyada for Adafruit Industries.
BSD license, all text above must be included in any redistribution
****************************************************/
#if defined(ESP8266)
#include <ESP8266WiFi.h>
#else
#include <WiFi.h>
#endif
#include <WiFiUdp.h>
#include <OSCMessage.h>
#include <Wire.h>
#include “Adafruit_SI1145.h”

char ssid[] = “name”; // your network SSID (name)
char pass[] = “pass”; // your network password

WiFiUDP Udp; // A UDP instance to let us send and receive packets over UDP
const IPAddress outIp(192,168,0,202); // remote IP of your computer
const unsigned int outPort = 4559; // remote port to receive OSC
const unsigned int localPort = 8888; // local port to listen for OSC packets (actually not used for sending)

Adafruit_SI1145 uv = Adafruit_SI1145();

void setup() {
Serial.begin(115200);

// Connect to WiFi network
Serial.println();
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, pass);

while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
}
Serial.println("");

Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());

Serial.println("Starting UDP");
Udp.begin(localPort);
Serial.print("Local port: ");

#ifdef ESP32
Serial.println(localPort);
#else
Serial.println(Udp.localPort());
#endif

Serial.println(“Adafruit SI1145 test”);

if (! uv.begin()) {
Serial.println(“Didn’t find Si1145”);
while (1);
}

Serial.println(“OK!”);
}

void loop() {
Serial.println("===================");
Serial.print("Vis: "); Serial.println(uv.readVisible());
Serial.print("IR: "); Serial.println(uv.readIR());

// Uncomment if you have an IR LED attached to LED pin!
//Serial.print("Prox: "); Serial.println(uv.readProx());

float UVindex = uv.readUV();
// the index is multiplied by 100 so to get the
// integer index, divide by 100!
UVindex /= 100.0;
Serial.print("UV: "); Serial.println(UVindex);
OSCMessage msg(“trigger/prophet”);
msg.add(“uv.readVisible, uv.readIR, UVindex”);
Udp.beginPacket(outIp, outPort);
msg.send(Udp);
Udp.endPacket();
msg.empty();
delay(1000);
}

I see nothing appearing on the sonic pi. And the wemos is giving values in the serial terminal.
So my guess something is not being send or received obviously.


#2

I think this line should probably have
“/trigger/prophet” with a / before trigger. All OSC messages start with a /


#3

Hi I’ve also tried that.

I’ve figured it out in max msp: I changed the message to msg.add(uv.readUV());
and i’m receiving integers in max msp, they should be floats but thats for later.

I just don’t understand how I should format the Sonic Pi code to read the value…


#4

Do you see any messages being received in the cues log in Sonic Pi? (If you can’t see it enable it in the editor preference panel)

Also, which version of Sonic Pi are you using? (there is a change you have to make to read the message if you are building your own 3.2dev…change “/osc/trigger/prophet” to “/osc*/trigger/prophet”) for 3.1 you don;t need that change.


#5

I’m using the mac os version to test the code and want it to work on rasbian.

Ok see the incoming messages (the data) but it doesn’t change or generate any sound.


#6

Can you give an example of what the full cue(s) look like in the cue log?

(you can add the relevant cue to your sync line (if you can see it) by typing

a, b, c, = sync 

with a space before and after sync and you should then get a drop down list of all the known cues from which you select the one you want (presumably "/osc/trigger/prophet")

Also you can try inserting a line

puts a, b, c

before the synth

I tried the program below to test your receiver and it works fine, if you are getting an appropriate osc message

#test program
use_osc "localhost",4559
#send an osc message locally to trigger the live_loop 
osc "/trigger/prophet",:c5,100,2

live_loop :foo do
  use_real_time
  a, b, c = sync  "/osc/trigger/prophet"
  puts a, b, c
  synth :prophet, note: a, cutoff: b, sustain: c
end

#7

One quick question. Have you told Sonic Pi that it’s allowed to receive external OSC messages? This is disabled by default.

You can enable this in the preferences:


#8

Yes I did and @robin.newman I did the test example you gave and that worked.

I think the data coming in is a to low number to generate as hearable sound. (0.200 for example)
My guess is I need to multiply the incoming data to a value that makes a hearable sound. Need to figure out how to do that.


#9

The best thing to do is to print the data, as per my example. You can then see if it is something you can use directly as note date.
This will respond to numbers in the range 0->255 but the hearable range is probably from about 30 to 110 (assuming synth :prophet … probably a higher value for the default synth say 55 upwards.

You can of course scale any incoming data. Another possibility is to treat the incoming number as frequency and use

play hz_to_midi  f #where f is say 220-4000 range)

#10

I’m stuck in converting the data in sonic pi when it comes in. Could you show me a small example how this could be done or where I can find this in the tutorials. Kind regards!


#11

I think you said that that data you had coming in was of the order of 0.200
As you say, you can’t play a sound directly with this value.
I think your starting point should be to look at the cues log. Unless you can see some osc messages arriving there, you can’t progress further. You should be able to see something like
/osc/trigger/prophet [0.200,...may be other numbers?]
assuming that you are receiving an osc message addressed to /trigger/prophet (sonic pi adds the /osc at the start)
The /osc/trigger/prophet should be with a pink background and the associated data received inside the [ ] will have a yellow background. I put 0.200 in as possible data as this is what you said was being sent…There may be further numbers or other items, all separated by commas depending on the data you are sending.

If you can see such data arriving in the cues log, and it will only be there is the sending program is addressing the OSC message to the IP address of the computer running sonic pi, AND is addressing it to port 4559, which is the port that sonic pIf you i is listening on, then you can progress to extracting the data, which you do in a live loop, as illustrated in the example I have given above, where I generate an OSC message to send in sonic pi and send it back to itself.
The example shows how the number transmitted can be received into a variable in Sonic Pi.
If you are not sure how many data items are being received , or if they are likely to vary (in number, not in value) then you can receive them with a single variable which will be set up as a list. In that case you extract each received value using indexes. I redo the exampler below in this way.

#test program
use_osc "localhost",4559
#send an osc message locally to trigger the live_loop
osc "/trigger/prophet",72,100,2

live_loop :foo do
  use_real_time
  data = sync  "/osc/trigger/prophet"
  puts data
  puts data[0],data[1],data[2]
  synth :prophet, note: data[0], cutoff: data[1], sustain: data[2]
end

data contains [72, 100, 2]
and data[0],data[1] and data[2] contain 72 100 and 2 respectively

Now suppose you receive a number like 0.200 in data[0] and you want to play a sound with it.
data[0]*50 would give you 100.00 and this would sound OK using the play command. It depends on what the range of numbers you receive is going to be what your scaling factor needs to be. You may need something more sophisticated if your numbers vary a lot, maybe including an offset as well eg data[0]*30 + 50

I can;t give further suggestions without more detail of what you are actually sending, but your first need is to get to the stage where you can see cues arriving in the sonic pi cues log.


#12

Thank you! wonder full now I get how to convert and play with it.

Last question (for now :slight_smile: ), I now get 260 nil nil , the data from the 260 is correct but the nil nil wasn’t there before.
I’m still looking at the arduino code, because my guess is that the problem is there? :slight_smile:


#13

Glad you are making progress and receiving the OSC message now.
There is only ONE piece of data included in the message as you can see from the cue log, namely the 261
so yes you need to look at the code at the other end where the OSC message is being sent. In particular, look at the mechanism for building the message and adding data items.
I’ve not done this from arduinos but I’m sure ytou can google examples.

Once you see three data items in the cue log fort each messages (they will appear between the […] then you are in business