6
votes

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);


}
2

2 Answers

7
votes

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!

0
votes

I've got the same issue in c# ( the second parameter, in c# is the length of the substracting string). However, I saw that if I do not wait a little bit of time, the string transmitted is not always in the same form: such that: somtime, your string will be (value)a(value)b(value)c(value)d(value)e(value)f(value)g , BUT other times will be: (value)a(value)b(value)c(value)d(value) and the next string will be e(value)f(value)g(value)a(value)b(value) and so on... Well after all, all the data will be transmited, but it will not have the same structure, so I added a little bit of delay before every serial reading (to be sure that the previous serial string was read till the and and every timpe I get the string in the same form), and it works fine for me. Hope it is helpful for you too.