max samplerate of this setup?

Hello,

I’m working at a project where I have to design a measurement device which has to do a clearance measurement in a turbine motor. We measure the clearance between a blade and the turbine housing.
Now we are in the calibrationfase and encountered a problem. We use the program gobetwino to log the data from our distance sensor. This way you can safe the results and study them. When a turbine is rotating you sometimes measure a blade but most of the time the blade isn’t in front of the sensor. When the turbine isn’t rotating it works just fine, but at a certain speed the results aren’t correct and it seems like the arduino can’t sample the correct data which is taken when the blade is in front of the sensor. I use a baud rate of 115200 and a delay of 1ms. So per ms we write/safe the data in a textfile. When we check these files the measured distance from the blade varys all the time and they appeare at a non regular base while our speed stays the same. We used different delays from 1 till 30ms and it doesn’t improve. Does anybody recognize the problem? It wouldn’t surprise me if it’s a small detail but I also have to mention I’m new in this kind of technology.

This is my setup

I use an inductive sensor which gives a voltage from 0 to 10V proportional to the distance. The arduino can only handle 5V so I added a voltage divider. The measurement is translated by the arduino from a 1023 resolution to 2000 micrometer.(the range is only 2mm).

The datasheet from my sensor
http://www.balluff.com/Balluff/de/ProductsChannel/Product+Detail/en-gb/ProductDetail.htm?ProductID=BAW+G06EE-UAF20B-EP03-K&ProductGroupGuid={7E5D485B-BE05-4E2A-89E6-62BBB24A337D}&ProductGroupName=Induktive%20Abstandssensoren

The program we use so far

int sensePin =0;

void setup()
{
  analogReference(DEFAULT);
  Serial.begin(115200);  
}

void loop()
{
  int val = analogRead(sensePin);

  float mmWaarde = 2000.0 * val / 1023;
  Serial.println(mmWaarde, 1);

  delay(1);
}

The program we load when we try to log the data

int serInLen = 25;
char serInString[25];

int sensePin=0;
int result;

void setup() 
{ 
  // Setup serial comm. Initialize random function.
  analogReference(DEFAULT);
  Serial.begin(115200); 
  randomSeed(analogRead(0));
  delay(5); 
  // Use the CPTEST copy file command to make a copy of a new empty logfile
  Serial.println("#S|CPTEST|[]#");
  readSerialString(serInString,1000);
  // There ought to be a check here for a non 0 return value indicating an error and some error handeling
} 
 
void loop() 
{ 
   //Create some random values to log to a file on the PC.  This could be sensor readings or whatever
   //but for this example it's just 3 random values
   int val = analogRead(sensePin);
   float mmWaarde = 2000.0 * val / 1023;
   logData(mmWaarde);
   delay(5); 
}

// Send the LOGTEST command to Gobetwino the 3 random values are seperated by semicolons
 
void logData( float mmWaarde) 
{
   char buffer[5];
  
   Serial.print("#S|LOGTEST|[");
   Serial.print(itoa((mmWaarde), buffer, 10));
   Serial.println("]#");
   readSerialString(serInString,1000);
   // There ought to be a check here for a non 0 return value indicating an error and some error handeling
} 

//read a string from the serial and store it in an array
//you must supply the array variable - return if timeOut ms passes before the sting is read
void readSerialString (char *strArray,long timeOut) 
{
   long startTime=millis();
   int i;

   while (!Serial.available()) {
      if (millis()-startTime >= timeOut) {
         return;
      }
   }
   while (Serial.available() && i < serInLen) {
      strArray[i] = Serial.read();
      i++;
   }
}

Thanks for the advice 8)

Your bottleneck is the serial data upload. You have 115200 baud rate that transfers 11520 bytes or characters per second. Each data entry is about 23 characters so 2 milliseconds. During this time you can't read analog. Is this delay too long for your speed (never mentioned)? Your analogRead also takes 0.1 ms, not to mention the serialRead for data confirmation takes some unknown amount of time since you didn't post the program that handles receiving data FROM arduino. That program could be a bugger too.

My suggestion is to NOT print any strings and just binary data, no wasted bandwidth for human-readable messages. Do analogRead, decide whether the result needs to be integer (0-1023 levels) or you are ok with byte (0-255 levels) If one byte is enough, then you can just send that down serial and that takes 0.1 ms only.

We want the speed to be as high as possible, at least 10ms per value. The program we use to save the data is gobetwino http://www.mikmo.dk/gobetwino.html

The thing is that we don't know whether the sensor can diverse its value at this kind of speed. It also could be that the wrong data is saved because some kind of delay. We can save the data at 1 value per ms, but it isn't the correct value. We will try to use a byte value but I don't think this is the problem.

Is there also a possibity to reduce the delay? Now we use 1ms because this is the smallest value we can fill in the code but is there a way to save the data at 0,1ms for example?

liudr's tip to use binary data makes much sense. would remove a factor in communication

Some additional tips to improve performance - higher baudrate: Arduino can set its baudrate to 230400 and 345600. Don't know if gobetwino can handle it (to be tested) - don't convert the analogRead to a float, just send the int to the PC and let the PC do the conversion, The PC is much faster. BTW you convert to a float and than with itoa to an int again - The readSerialString(serInString,1000); has a timeout of 1000 milliSecond, that is one whole second = a lot of samples....

testcode

int sensePin =0;

void setup()
{
  analogReference(DEFAULT);
  Serial.begin(115200);    // 230400, 345600
}

void loop()
{
  int val = analogRead(sensePin);
  Serial.println(val);
  // Serial.write(val /256);    // high byte binary mode
  // Serial.write(val & 255);  // low byte
  // Serial.write(val/4);       // if you only want to send 1 byte as liudr proposed.
  delay(1);
}

Does gobetwino just put the data in a textfile? Maybe a dedicated prog is faster. Gobetwino command "LOGTEST" might be abbreviated to a single char "L" improving speed too when sticking to Gobetwino.

If you have python you might try the test app with this:

import sys, os, serial, threading

def capture():

    ser = serial.Serial(COMPORT, BAUDRATE, timeout=0)

    while (1):
    #read from serial in binary mode
        val = ser.read()
        val = val * 256 + ser.read()
        # write to file
        text_file = open("data.log", "w")
        text_file.writeln(val)
        text_file.close()

    print "Stop Capture"


""" -------------------------------------------
MAIN APPLICATION
"""  

print "Start capture"
print

COMPORT = 4;
BAUDRATE = 115200

capture()

2 cents

-- update -- fixed binary mod in python script/.

You have the source of analog read, and you'll see that it breaks down into three sections, 1) setup the input and start the conversion, 2)wait for the conversion to complete and then 3)read back the result.

It is relatively simple to break this up so that any blocking is minimised, and conversions can be interleaved with other operations

you can use delayMicroseconds for shorter delays that are more reliable than delay especially close to a few milliseconds time delays. Each analog read will take 0.1ms to complete.

Right now we are trying to send the data to matlab. Thanks for the all the advice we will use it in our code and will let you know what worked.

JohnTampon: Right now we are trying to send the data to matlab. Thanks for the all the advice we will use it in our code and will let you know what worked.

Not very sure how to communicate with matlab though. I'm sure if you post your questions with matlab in the title, you will find the right persons to answer your specific matlab questions :)