I have a small problem.
I am passing information from an arduino attached 3 axis accelerometer + 3 axis magnetometer + compass heading. These are scaled to midi ranges (0-127).
ARDUINO: This is passed in a serial print with a format like 76a45b120c23d12e23f34g
Serial.print(shiftAx);
Serial.print("a");
Serial.print(shiftAy);
Serial.print("b");
Serial.print(shiftAz);
Serial.print("c");
Serial.print(shiftMx);
Serial.print("d");
Serial.print(shiftMy);
Serial.print("e");
Serial.print(shiftMz);
Serial.print("f");
Serial.print(shiftHead);
Serial.print("g");
I can see this works using my serial monitor. (however I am unsure as to print it as println at "g" or not.)
PROCESSING 2:
I buffer until g in my void setup()
port = new Serial(this, "/dev/tty.usbmodem411", 9600);
port.bufferUntil('g');
i have the function
void serialEvent (Serial port)
{
data = port.readStringUntil('g');
AxVal = data.substring(0, data.indexOf('a'));
AyVal = data.substring(data.indexOf("a") + 1, data.indexOf("b"));
AzVal = data.substring(data.indexOf("b") + 1, data.indexOf("c"));
MxVal = data.substring(data.indexOf("c") + 1, data.indexOf("d"));
MyVal = data.substring(data.indexOf("d") + 1, data.indexOf("e"));
MzVal = data.substring(data.indexOf("e") + 1, data.indexOf("f"));
HeadVal = data.substring(data.indexOf("f") + 1, data.indexOf("g"));
}
THE PROBLEM So this doesn't work. No text displayed. (its just a simple fill(), text())
I don't see why. Is the problem my protocol (if I can call it that), how I'm unpacking the string? Or some other problem.
I am very confused.
I can get it to work with just two values as in this tutorial
notes: The arduino main loop is on delay(100); arduino is at 9600 baud rate
I shall attach the whole sketches if needed to help me, which I shall extend my thanks beforehand.
CODE:
PROCESSING
import themidibus.*; //Import the library
import javax.sound.midi.MidiMessage; //Import the MidiMessage classes http://java.sun.com/j2se/1.5.0/docs/api/javax/sound/midi/MidiMessage.html
import javax.sound.midi.SysexMessage;
import javax.sound.midi.ShortMessage;
import processing.serial.*;
MidiBus myBus; // The MidiBus
Serial port;
String AxVal = " ", AyVal = " ", AzVal = " ";
String MxVal = " ", MyVal = " ", MzVal = " ";
String HeadVal = " ";
String AxString="Ax",AyString = "Ay",AzString = "Az";
String MxString="Mx",MyString = "My",MzString = "Mz";
String HeadString="Heading";
String data = " ";
PFont font;
int status_byte = 0xB0; // send control change
int channel_byte = 0; // On channel 0
int first_byte; // cc number;
int second_byte; // value
void setup()
{
size(1000,500);
port = new Serial(this, "/dev/tty.usbmodem411", 9600);
port.bufferUntil('g');
font = loadFont("NanumBrush-48.vlw");
textFont(font, 48);
MidiBus.list(); // List all available Midi devices on STDOUT. This will show each device's index and name.
myBus = new MidiBus(this, 1, 0); // Create a new MidiBus object
}
void draw()
{
background(0,0,0);
//first_byte = 1;
//second_byte = int(AxVal); // But with less velocity
//myBus.sendMessage(status_byte, channel_byte, first_byte, second_byte);
fill(46, 209, 2);
text(AxVal, 60, 75);
text(AxString, 60, 125);
//first_byte = 2;
//second_byte = int(AyVal); // But with less velocity
//myBus.sendMessage(status_byte, channel_byte, first_byte, second_byte);
fill(0, 160, 153);
text(AyVal, 120, 75);
text(AyString,120,125);
// first_byte = 3;
//second_byte = int(AzVal); // But with less velocity
//myBus.sendMessage(status_byte, channel_byte, first_byte, second_byte);
fill(0, 160, 153);
text(AzVal, 180, 75);
text(AzString,180,125);
/*
first_byte = 4;
second_byte = int(MxVal); // But with less velocity
myBus.sendMessage(status_byte, channel_byte, first_byte, second_byte);
fill(0, 160, 153);
text(MxVal, 240, 75);
text(MxString,240,125);
first_byte = 5;
second_byte = int(MyVal); // But with less velocity
myBus.sendMessage(status_byte, channel_byte, first_byte, second_byte);
fill(0, 160, 153);
text(MyVal, 300, 75);
text(MyString,300,125);
first_byte = 6;
second_byte = int(MzVal); // But with less velocity
myBus.sendMessage(status_byte, channel_byte, first_byte, second_byte);
fill(0, 160, 153);
text(MzVal, 360, 75);
text(MzString,360,125);
first_byte = 7;
second_byte = int(HeadVal); // But with less velocity
myBus.sendMessage(status_byte, channel_byte, first_byte, second_byte);
fill(0, 160, 153);
text(HeadVal, 420, 75);
text(HeadString,420,125);
*/
}
void serialEvent (Serial port)
{
data = port.readStringUntil('g');
data = data.substring(0, data.length() - 1);
AxVal = data.substring(0, data.indexOf('a'));
AyVal = data.substring(data.indexOf("a") + 1, data.indexOf("b"));
AzVal = data.substring(data.indexOf("b") + 1, data.length());
/*
index = data.indexOf("c")+1;
MxVal = data.substring(index, data.indexOf("d"));
index = data.indexOf("d")+1;
MyVal = data.substring(index, data.indexOf("e"));
index = data.indexOf("e")+1;
MzVal = data.substring(index, data.indexOf("f"));
index = data.indexOf("f")+1;
HeadVal = data.substring(index, data.indexOf("g"));
*/
}
/*
void serialEvent (Serial port)
{
data = port.readStringUntil('g');
AxVal = data.substring(0, data.indexOf('a'));
AyVal = data.substring(data.indexOf("a") + 1, data.indexOf("b"));
AzVal = data.substring(data.indexOf("b") + 1, data.indexOf("c"));
MxVal = data.substring(data.indexOf("c") + 1, data.indexOf("d"));
MyVal = data.substring(data.indexOf("d") + 1, data.indexOf("e"));
MzVal = data.substring(data.indexOf("e") + 1, data.indexOf("f"));
HeadVal = data.substring(data.indexOf("f") + 1, data.indexOf("g"));
}
ARDUINO:
// Add lastvalue check
#include <Wire.h>
#include <LSM303DLH.h>
LSM303DLH glove;
//set max min magnetometer
int maxMx = +353, maxMy = +527, maxMz = 426;
int minMx = -700, minMy = -477, minMz = -561;
int maxA = 2019;
int minAx = -1043, minAy = -2048, minAz = -2048;
int shiftMx,shiftMy,shiftMz;
int shiftAx,shiftAy,shiftAz;
float shiftHeadTemp;
int shiftHead;
void setup()
{
Wire.begin();
glove.enableDefault();
Serial.begin(9600);
}
void loop()
{
glove.read();
shiftMx = ((glove.m.x - minMx) / (maxMx - minMx)) * 127;
shiftMy = ((glove.m.y - minMy) / (maxMy - minMy)) * 127;
shiftMz = ((glove.m.z - minMz) / (maxMz - minMz)) * 127;
shiftAx = ((glove.a.x - minAx) / (maxA - minAx)) * 127;
shiftAy = ((glove.a.y - minAy) / (maxA - minAy)) * 127;
shiftAz = ((glove.a.z - minAz) / (maxA - minAz)) * 127;
shiftHeadTemp = (glove.heading((LSM303DLH::vector){0,-1,0}));
shiftHead = (shiftHeadTemp/360)*127;
if (shiftMx < 0){shiftMx=0;}
if (shiftMx >127){shiftMx=127;}
if (shiftMy < 0){shiftMy=0;}
if (shiftMy >127){shiftMy=127;}
if (shiftMz < 0){shiftMz=0;}
if (shiftMz >127){shiftMz=127;}
if (shiftAx < 0){shiftAx=0;}
if (shiftAx >127){shiftAx=127;}
if (shiftAy < 0){shiftAy=0;}
if (shiftAy >127){shiftAy=127;}
if (shiftAz < 0){shiftAz=0;}
if (shiftAz >127){shiftAz=127;}
if (shiftHead < 0){shiftHead=0;}
if (shiftHead >127){shiftHead=127;}
Serial.print(shiftAx);
Serial.print("a");
Serial.print(shiftAy);
Serial.print("b");
Serial.print(shiftAz);
Serial.print("c");
Serial.print(shiftMx);
Serial.print("d");
Serial.print(shiftMy);
Serial.print("e");
Serial.print(shiftMz);
Serial.print("f");
Serial.print(shiftHead);
Serial.println("g");
delay(100);
}
I can't test your code right now but here are some ideas.
You could send JSON from your Arduino to processing. Here is the example I'm using in one of my own project but you could easily adapt it to suit your needs:
void sendJson(){
String json;
json = "{\"accel\":{\"x\":";
json = json + getXYZ(0);
json = json + ",\"y\":";
json = json + getXYZ(1);
json = json + ",\"z\":";
json = json + getXYZ(2);
json = json + "},\"gyro\":{\"yaw\":";
json = json + getYPR(0);
json = json + ",\"pitch\":";
json = json + getYPR(1);
json = json + ",\"roll\":";
json = json + getYPR(2);
json = json + "}}";
Serial.println(json);
}
The good thing about JSON is that it is easily "parsable" with processing using the getType()
function. No more readUntil
, it all goes like this: (note that in void setup()
you need to change port.bufferUntil('g');
to port.bufferUntil('\n');
because in the Arduino, json
is sent with Serial.println();
)
void serialEvent (Serial port){
String json = port.readString();
shiftAx = getInt("shiftAx");
shiftAy = getInt("shiftAy"); // and so on...
}
You will have to change your code a little but it will be a lot more maintainable in the long run, say if you add more sensors. You'll just need to change the json
in arduino and simply get the value in processing.
Another thing: you could use the constrain function to constrain your value between 0
and 127
.
value = constrain(value, 0, 127);
Hope it helps!