We closed this forum 18 June 2010. It has served us well since 2005 as the ALPHA forum did before it from 2002 to 2005. New discussions are ongoing at the new URL http://forum.processing.org. You'll need to sign up and get a new user account. We're sorry about that inconvenience, but we think it's better in the long run. The content on this forum will remain online.
IndexProgramming Questions & HelpSyntax Questions › Avoiding NaN when sending values over network
Page Index Toggle Pages: 1
Avoiding NaN when sending values over network (Read 1190 times)
Avoiding NaN when sending values over network
Mar 23rd, 2010, 8:51am
 
So, I have a project I am working on using two sonar sensors that affect audio playback. Both sensors are attached to arduinos, one of the sensors is connected to another computer and the values from the sensors are sent across a network. However, this sometimes causes NaN errors or just non-numerical characters which causes the program to crash. Can anyone help figure out where this error happens, how to stop it?

ARDUINO code:
Code:

const int pingPin = 7;

void setup() {
// initialize serial communication:
Serial.begin(9600);
}

void loop()
{
// 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(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.println();

delay(100);
}

long microsecondsToInches(long microseconds)
{

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;
}
Re: Avoiding NaN when sending values over network
Reply #1 - Mar 23rd, 2010, 8:52am
 
Processing SERVER code:
Code:
import ddf.minim.*;
import ddf.minim.effects.*;
import ddf.minim.signals.*;
import processing.serial.*;
import processing.net.*;

AudioOutput out;
Server server;
Minim minim;
AudioPlayer groove;
BandPass bpf;

PFont f;
int lf = 10;
String myString = null;
Serial myPort;
float num;
//values from arduino across the network
String clientID = "";
String serverSerial = null;
float num2;

void setup()
{
size(512, 200, P3D);

// server info
server = new Server(this, 5204);
f = createFont("Arial",12,true);

minim = new Minim(this);
out = minim.getLineOut(Minim.MONO);

groove = minim.loadFile("bass01.mp3");
groove.loop();
// make a band pass filter with a center frequency of 440 Hz and a bandwidth of 20 Hz
// the third argument is the sample rate of the audio that will be filtered
// it is required to correctly compute values used by the filter
bpf = new BandPass(440, 20, groove.sampleRate());
groove.addEffect(bpf);

println(Serial.list());
myPort = new Serial(this, Serial.list()[0], 9600);
myPort.clear();
}

void draw()
{
background(0);
textFont(f);
textAlign(LEFT);
fill(0, 102, 153);

stroke(255);
// draw the waveforms
// the values returned by left.get() and right.get() will be between -1 and 1,
// so we need to scale them up to see the waveform
for(int i = 0; i < groove.right.size()-1; i++)
{
float x1 = map(i, 0, groove.bufferSize(), 0, width);
float x2 = map(i+1, 0, groove.bufferSize(), 0, width);
line(x1, height/4 - groove.left.get(i)*50, x2, height/4 - groove.left.get(i+1)*50);
line(x1, 3*height/4 - groove.right.get(i)*50, x2, 3*height/4 - groove.right.get(i+1)*50);
}
// draw a rectangle to represent the pass band. num refers to local port communication
noStroke();
fill(255, 0, 0, 60);
rect(num - bpf.getBandWidth()/20, 0, bpf.getBandWidth()/10, height);

//Port talk
while (myPort.available() > 0) {
myString = myPort.readStringUntil(lf);
if (myString != null) {
print(myString); // Prints String
num=float(myString); // Converts and prints float
println(num);
}
}

// map the mouse position to the range [100, 10000], an arbitrary range of passBand frequencies
float passBand = map(num, 0, width, 100, 2000);
bpf.setFreq(passBand);
float bandWidth = map(num2, 0, height, 50, 500);
bpf.setBandWidth(bandWidth);
// prints the new values of the coefficients in the console
bpf.printCoeff();

// server talk
Client client = server.available();
if(client!= null) {
serverSerial = client.readString();
print(serverSerial);
num2 = float(serverSerial);
if (num2 == Float.NaN) {
num2 = 2;
}
if (num2 <= 1) {
num2 = 12;
}
if (num2 >= 200) {
num2 = 95;
}

text(clientID, 20, 20);
}
}

void serverEvent(Server server, Client client) {
clientID = "A new client has connected: " + client.ip();
println(clientID);
// Reset newMessageColor to black

}

void stop()
{
// always close Minim audio classes when you finish with them
groove.close();
// always stop Minim before exiting
minim.stop();

super.stop();
}
Re: Avoiding NaN when sending values over network
Reply #2 - Mar 23rd, 2010, 8:52am
 
processing CLIENT code:
Code:
import processing.net.*;
import processing.serial.*;
// Declare a client
Client client;
Serial myPort;
int lf = 10;
String myString = null;
float num;

void setup() {
size(400,200);
// Create the Client, connect to server at 127.0.0.1 (localhost), port 5204
client = new Client(this,"127.0.0.1", 5204);


println(Serial.list());
myPort = new Serial(this, Serial.list()[0], 9600);
myPort.clear();


}

void draw() {
background(255);
while (myPort.available() > 0) {
myString = myPort.readStringUntil(lf);
if (myString != null) {
print(myString); // Prints String
num=float(myString); // Converts and prints float


}

}
client.write(num + "\n");
delay(100);
}
Re: Avoiding NaN when sending values over network
Reply #3 - Mar 23rd, 2010, 12:48pm
 
It might help if you highlight where you get an error when it crashes and what kind of error it is.  One possible solution (just a hunch mind you) is that, assuming the crash occurs when you try to convert to a float, you simply wrap this in a try/catch statement:

Code:
if (myString != null) {
 print(myString);  // Prints String
 try {
   num=float(myString);  // Converts and prints float
   println(num);
 }
 catch (WhateverErrorIsBeingThrown err) { // You'll need to edit this ;)
   // handle as required - probably safe to ignore;
   // though a good idea to somehow log that an error has occured:
   println("NaN");
 }
}


Depending on what else relies on the num variable you may need to adjust the contents of the 'try'...  Alternatively it might simply be a matter of using a condition to check you don't have NaN before proceeding...
Re: Avoiding NaN when sending values over network
Reply #4 - Mar 23rd, 2010, 2:38pm
 
Well I don't get an error in Processing. It's just that when a NaN is received, the sound file stops, the line disappears and things jitter across the window. Technically, it's still running, however an error does show up in the clients window without actually shutting it down, I'll try grabbing that.

The code I added to try and stop NaN was this, but I don't know if it makes sense or works, it seems to prolong the program running correctly, but not forever, is it correct?

Code:
  num2 = float(serverSerial);
   if (num2 == Float.NaN) {
num2 = 2;
   }
   if (num2 <= 1) {
num2 = 12;
   }
   if (num2 >= 200) {
num2 = 95;
   }


Your suggestion is good, I'll try it and see if it works, thanks!
Re: Avoiding NaN when sending values over network
Reply #5 - Mar 23rd, 2010, 5:05pm
 
Also, is there a way to tell Processing to NOT send a value that is not an integer? If I could filter that out, then I may be able to avoid sending anything that isn't a coordinate and avoid crashing.
Re: Avoiding NaN when sending values over network
Reply #6 - Mar 24th, 2010, 4:55am
 
explodingbarrel wrote on Mar 23rd, 2010, 2:38pm:
   if (num2 == Float.NaN) {

I made the same error recently. This doesn't work. You must do:
if (Float.isNaN(num2)) {

Page Index Toggle Pages: 1