Ping))) to Arduino to Max

snathan's icon

Hi,
As part of my thesis project, I am trying to read distance sensor data into Max. This seems like it should be so easy! I've been trying for over a week with no luck, and I really need to show some progress soon.

I have successfully connected the Ping to the Arduino; I know this is working properly. It gives accurate readings into the Arduino serial monitor. I did exactly this :: http://arduino.cc/en/Tutorial/Ping ...I even edited the code to print only integers representing inches. So I have the exact data I need, it's just in Arduino Serial Monitor and not in Max!

I've looked extensively at the Arduino2Max code + patch. I think the problem is that for the Ping, a digital write is required in order to transmit a signal for the sensor to use, and Arduino2Max doesn't facilitate this.

When the Ping is streaming data into the Arduino Serial Monitor, its LED blinks. When I close Arduino, the LED still blinks. However, when I open a Max patch with a serial object, it immediately stops blinking. I don't really understand why this would be happening. Is there any way to just avoid the serial object and tell Max just to copy what Arduino is already doing with the "serial.print"?

Anyway, I have been trying countless different ways to splice together Arduino sketches (I still don't entirely understand the language) so that Max can read the sensor data. I feel like there is a super easy solution that I'm just somehow overlooking. I would sincerely appreciate any help! Thanks!

pdelges's icon

I can't test the following, but it works for me in other contexts:

In the .pde file for PING))), replace

  Serial.print(inches);
  Serial.print("in, ");
  Serial.print(cm);
  Serial.print("cm");
  Serial.println();

by

  Serial.print(inches);
  Serial.print("_");
  Serial.print(cm);
  Serial.println();

"_" is used as a separator between your 2 values.

In Max, try this:

Max Patch
Copy patch and select New From Clipboard in Max.

A bit OT:
I often have problems with the [serial] object, and I then generally have to restart my Mac. Using [comport] seems to be much more stable...

nick rothwell | project cassiel's icon

It's not too difficult to start from scratch, devise a simple serial protocol between the Arduino and Max, and then implement it at both ends. This will give you something that is fairly simple, easy to understand, and which and does exactly what you want, no more, no less.

I'm using a [serial] object on a MacBook Pro and it seems to work fine. I occasionally need to reset the object to run at a speed other than 9600 if I reload the board, but otherwise, no problems.

Scott Fitzgerald's icon

I would suggest looking at the various examples included in the Arduino software. In particular, look at the Sketchbook>Examples>Communication examples which are all about serial communication.

You can also look at this example I posted a few months ago.

Also follow this quick checklist.

snathan's icon

Thank you all so much! Patrick, I tried your patch and arduino code. As before, the arduino side is working fine. Just to clarify, after uploading the arduino sketch onto the board, I should close arduino before opening max, right? ...I've tried both ways.

I think i'm having the same problem as before, it's just clearer now. So I uploaded the modified arduino code, saw the LED blinking and closed arduino. I opened Patrick's patch and clicked print. The max window shows port c: COM3 and port f: COM6 (I know the arduino is on COM6). The drop-down window also shows these two options. But when I select either of them, the max window tells me "specified port not available"!? Didn't it just tell me they were available? Any ideas why this would be happening? Thanks!

snathan's icon

I should also mention that I changed <> to <>, but have tried all possible combinations as far as port IDs go. None of this seems to have an effect on the error "specified port not available" message.

I have also made sure that the baud rates are consistent
(9600) between Arduino and Max.

pdelges's icon

It's indeed better to close the Arduino IDE before opening the Max patch (as [serial] has a close message since Max5, it shouldn't be necessary but it's more secured like that).

I suppose you installed the FTDI driver?http://www.ftdichip.com/Drivers/VCP.htm

Just to make sure your COM port is released, did you try to restart your PC (keeping the arduino running) before starting Max?

p

snathan's icon

Yeah, I tried restarting. Reinstalled the driver, restarted, restarted again. Still the same problem...

David Beaudry's icon

Then it's probably time to share a patch and probably your sketch...we can only guess at this point.

David

snathan's icon

I tried reinstalling Arduino + drivers, still the problem persists.

My patch isn't much different from the one Patrick posted. I changed it to correspond to port f : COM6::

Max Patch
Copy patch and select New From Clipboard in Max.

The arduino code is the same as posted here http://arduino.cc/en/Tutorial/Ping with the exception suggested by Patrick above:

int pingPin = 7;

void setup()
{
Serial.begin(9600);
}

void loop()
{
long duration, inches, cm;

// The PING))) is triggered by a HIGH pulse of 2 or more microseconds.
// We give a short LOW pulse beforehand to ensure a clean HIGH pulse.
pinMode(pingPin, OUTPUT);
digitalWrite(pingPin, LOW);
delayMicroseconds(2);
digitalWrite(pingPin, HIGH);
delayMicroseconds(5);
digitalWrite(pingPin, LOW);

// The same pin is used to read the signal from the PING))): a HIGH
// pulse whose duration is the time (in microseconds) from the sending
// of the ping to the reception of its echo off of an object.
pinMode(pingPin, INPUT);
duration = pulseIn(pingPin, HIGH);

// convert the time into a distance
inches = microsecondsToInches(duration);
cm = microsecondsToCentimeters(duration);

Serial.print(inches);
Serial.print("_");
Serial.print(cm);
Serial.println();

delay(100);
}

long microsecondsToInches(long microseconds)
{
// According to Parallax's datasheet for the PING))), there are
// 73.746 microseconds per inch (i.e. sound travels at 1130 feet per
// second). This gives the distance travelled by the ping, outbound
// and return, so we divide by 2 to get the distance of the obstacle.
// See: http://www.parallax.com/dl/docs/prod/acc/28015-PING-v1.3.pdf
return microseconds / 74 / 2;
}

long microsecondsToCentimeters(long microseconds)
{
// The speed of sound is 340 m/s or 29 microseconds per centimeter.
// The ping travels out and back, so to find the distance of the
// object we take half of the distance travelled.
return microseconds / 29 / 2;
}

snathan's icon

I suppose I should also mention that I'm using a new Arduino Duemilanove, which seems to work fine for the included examples and for streaming the Ping data into the serial monitor.

Whether I upload the Arduino2Max sketch or the above-pasted one to arduino, and whether I open the Arduino2Max patch or the one above, all combinations have the same problem. Both patches print COM3 and COM6 as available ports, but selecting either from the drop-down menu causes a "specified port not available" message in the max window.

David Beaudry's icon

snathan wrote on Wed, 01 July 2009 01:29Whether I upload the Arduino2Max sketch or the above-pasted one to arduino, and whether I open the Arduino2Max patch or the one above, all combinations have the same problem. Both patches print COM3 and COM6 as available ports, but selecting either from the drop-down menu causes a "specified port not available" message in the max window.

Since you can see it in the Arduino environment, I would bet money your problem is in the patch.

So couple of things:
First, in your patch you have the left-most outlet of umenu connected to "prepend port", which gives "port 0" "port 1", which is causing your "specified port not available" errors. Connect it to the middle outlet of umenu and it will at least send the right port name that the serial object can recognize.

Second, connect a bang to the outlet of the serial object to see if you are getting data.

Third, you are looking for a carriage return to process your list (13), and since your sketch isn't providing the carriage return it may not be the best way to group your list. Many serial devices add a carriage return (all my bluetooth modems do), but again, you aren't specifically passing that along in your sketch. You are passing a line feed (10) via Serial.println, so group the list that way.

For debugging, I would just do the patch below to see if you are even getting data. Also, I would vote not have "_" as the separator, but rather a simple space, e.g.

Serial.print(inches);
Serial.print(32);// space in ascii
Serial.print(cm);
Serial.println();

See if that helps at all.

Best,
David

Max Patch
Copy patch and select New From Clipboard in Max.

David Beaudry's icon

David Beaudry wrote on Wed, 01 July 2009 10:00
Serial.print(inches);
Serial.print(32);// space in ascii
Serial.print(cm);
Serial.println();

Oops, slight change here (now that I have my coffee)...when adding the ascii space the line should read:

Serial.print(32, BYTE);// space in ascii

i.e. you need to pass it along as a byte so it stays "32", otherwise is gets converted to "51" "50" ("3" "2").

Sorry about that!
David

snathan's icon

Got it! Many thanks, David + coffee! That definitely passed me by about the umenu, but I understand now. Thank you all for your help!
-Nathan

pdelges's icon

Nathan,

sorry for the error in my patch! I just used some part of it and discovered this [umenu] wrong connection I made. Fortunately, David was much faster than I was to notice this! I will double check next time I send something!

p

ikid's icon

hi. i have a question for the maxmsp/arduino/ping users.
im using a ping with max/msp via arduino.
the code i use in arduino for the ping is:

int pingPin = 7;

void setup()
{
Serial.begin(9600);
}

void loop()
{
long duration, inches, cm;

// The PING))) is triggered by a HIGH pulse of 2 or more microseconds.
// We give a short LOW pulse beforehand to ensure a clean HIGH pulse.
pinMode(pingPin, OUTPUT);
digitalWrite(pingPin, LOW);
delayMicroseconds(2);
digitalWrite(pingPin, HIGH);
delayMicroseconds(5);
digitalWrite(pingPin, LOW);

// The same pin is used to read the signal from the PING))): a HIGH
// pulse whose duration is the time (in microseconds) from the sending
// of the ping to the reception of its echo off of an object.
pinMode(pingPin, INPUT);
duration = pulseIn(pingPin, HIGH);

// convert the time into a distance
inches = microsecondsToInches(duration);
cm = microsecondsToCentimeters(duration);

Serial.print(inches);
Serial.print(32, BYTE);// space in ascii
Serial.print(cm);
Serial.println();

delay(100);
}

long microsecondsToInches(long microseconds)
{
// According to Parallax's datasheet for the PING))), there are
// 73.746 microseconds per inch (i.e. sound travels at 1130 feet per
// second). This gives the distance travelled by the ping, outbound
// and return, so we divide by 2 to get the distance of the obstacle.
// See: http://www.parallax.com/dl/docs/prod/acc/28015-PING-v1.3.pdf
return microseconds / 74 / 2;
}

long microsecondsToCentimeters(long microseconds)
{
// The speed of sound is 340 m/s or 29 microseconds per centimeter.
// The ping travels out and back, so to find the distance of the
// object we take half of the distance travelled.
return microseconds / 29 / 2;
}

Max Patch
Copy patch and select New From Clipboard in Max.

and the patch in maxmsp is:

how you can see the arduino code generates 2 separate numbers to use in maxmsp's message.
now, i have a big problem!!!
i want to use 4 or more ping with arduino via maxmsp.
but if i connect another ping in the same port of arduino (digital 7), arduino and max/msp makes a real mess.
the numbers are confused and it is impossible to have the real numbers of distance. and mostly the numbers in maxmsp's message are always 2 and not 4 or more. i tried to connect the ping in another port (digital 6) but the ping doesnt start. i dont know to solve the problem.
so... my question is: can someone help me about it?
is anyone able to create a new code in arduino to use 4 or more ping via max/msp?

i hope you real programmers can help me..
thanx in advance and looking forward to have a solution.
.k

ikid's icon

anyone read or can be so gently to help me???
.k

pdelges's icon

If you use 4 pings, you should use 4 different i/o pins on your arduino and adapt your arduino code accordingly. So instead of one ping variable, you should declare 4 of them (or better, create an array of pingPins) and duplicate your code (or better, do a loop over the 4 pins).

Something like this (for 4 pins plugged on pins 7, 8, 9 and 10:

int pingPin[4] = {7, 8, 9, 10}

void loop()
{

    for (int currentPingPin = 0, currentPingPin < 4, currentPingPin++)
    {
        pinMode(pingPin[currentPingPin], OUTPUT);
        ...

        pinMode(pingPin[currentPingPin], INPUT);
        ...

        Serial.print(currentPingPin);
        Serial.print(32, BYTE);
        Serial.print(inches);
        Serial.print(32, BYTE);// space in ascii
        Serial.print(cm);
        Serial.println();

    }
}

Now the arduino will send triplets like this 0 12 13
First comes the ping ID, then the values. You then need to parse this in Max.

ikid's icon

thanx a lot for your help patrick. but.. can you write the entire code of arduino, please? in this way im not able to understand right what i have to write in the arduino sketch.
cause i tried to change something but i did a real mess, and arduino didnt recognise the pingpins.
sorry my ignorance about it but im new with arduino. i hope you really can be good to help me.
thanx in advance
.k

can you do with the pins 7 6 5 4? cause digital pins in arduino 2009 are by 0 to 7.

ikid's icon

please, patrick i trust in your help!!!

ikid's icon

help help help!!!

pdelges's icon

Don't you think I may have much more important things to do?

p

ikid's icon

sure. i ever didnt say that! i just asked help on the forum. and you gently answered me.. so..
if you want to give me your help, i will be grateful to you... but if you are busy with other important things..
i understand!
i just posted my question to have help if it is possible.

balam's icon

Perhaps the solution to your problem is the serial is overflowing
maybe if you add serial.flush at the end of loop

may resolve the issue.

Szczepan Sot's icon

Attaching the distance sensor to the DIGITAL side of the Uno, this way you don't need a bread board. It's the easiest way to use the distance sensor...

void setup() {
pinMode (2,OUTPUT);//attach pin 2 to vcc
pinMode (5,OUTPUT);//attach pin 5 to GND
// initialize serial communication:
Serial.begin(9600);
}

void loop()
{
digitalWrite(2, HIGH);
// establish variables for duration of the ping,
// and the distance result in inches and centimeters:
long duration, inches, cm;

// The PING))) is triggered by a HIGH pulse of 2 or more microseconds.
// Give a short LOW pulse beforehand to ensure a clean HIGH pulse:
pinMode(3, OUTPUT);// attach pin 3 to Trig
digitalWrite(3, LOW);
delayMicroseconds(2);
digitalWrite(3, HIGH);
delayMicroseconds(5);
digitalWrite(3, LOW);

// The same pin is used to read the signal from the PING))): a HIGH
// pulse whose duration is the time (in microseconds) from the sending
// of the ping to the reception of its echo off of an object.
pinMode (4, INPUT);//attach pin 4 to Echo
duration = pulseIn(4, HIGH);

// convert the time into a distance
inches = microsecondsToInches(duration);
cm = microsecondsToCentimeters(duration);

Serial.print(cm); //to get rid of confusion print only one value. Cm will give you a higher range than inches.
Serial.println();

delay(10);
}

long microsecondsToInches(long microseconds)
{
// According to Parallax's datasheet for the PING))), there are
// 73.746 microseconds per inch (i.e. sound travels at 1130 feet per
// second). This gives the distance travelled by the ping, outbound
// and return, so we divide by 2 to get the distance of the obstacle.
// See: http://www.parallax.com/dl/docs/prod/acc/28015-PING-v1.3.pdf
return microseconds / 74 / 2;
}

long microsecondsToCentimeters(long microseconds)
{
// The speed of sound is 340 m/s or 29 microseconds per centimeter.
// The ping travels out and back, so to find the distance of the
// object we take half of the distance travelled.
return microseconds / 29 / 2;
}

Now I've seen couple of people saying to use this part of the code;

Serial.print(inches);
Serial.print("_");
Serial.print(cm);
Serial.println();

This does not separate the 2 values, what this does, it multiplies inches by centimeters. And trust me you don't want that, this will not give you a clean transition...

To use inches instead of centimeters replace

Serial.print(cm);

by this

Serial.print(inches);

Stefano Scarani's icon

Dear Szczepan Sot,
I'm a new new new Arduino user. I'm try to use your sketch, and they work very well in arduino (Uno), but I can't read the data in Max; I've try with the simple patch by ikid but still freezed. I don't understand where is my mistake. Are you shure that this patch/sketch working together?

Stefanoo