Go Down

Topic: Ultrasonic anemometer reading (Read 5450 times) previous topic - next topic

Shad0x

Hi,

For my bachelor thesis I have one part where I need to measure wind speed and direction. For this I will be using CV7-F from LCJ capteurs: http://www.lcjcapteurs.com/CV7_3.htm

This will give me an output based on the NEMA0183 protocol.
For example: $IIMWV,225.0,R,000.0,N,A *38
$: start
IIMWV: wind speed and direction
225.0: wind direction
R: relative reference
000.0: wind speed
N: unit (knots)
A: available
*38: checksum

Now I don't have the sensor yet so I made a program that will sent the string of information to another arduino.

Code: [Select]
void setup()
{
Serial.begin(9600);
Serial2.begin(9600);
}

void loop()
{
  String anemometerString = "$IIMWV,225.0,R,000.0,N,A *38";
  Serial.println(anemometerString);
  Serial2.write ("$IIMWV,225.0,R,000.0,N,A *38");
  delay(500);
}


On the receiving arduino I've put a program to retrieve the information. There is where my problem starts. I can retrieve the information as separated characters. So on the monitor they just show up after each other. This is the program I made for it.
Code: [Select]
char anemometerIn = 0;
String anemometerString;

void setup()
{
Serial.begin(9600);
Serial2.begin(9600);
Serial.println("power on");
}

void loop()
{
if (Serial2.available() > 0)
{
   anemometerIn = Serial2.read();
   Serial.println(anemometerIn);
}

}


Now for getting all the information out of it I was thinking to get it back into a string. I started searching, but I don't get it how it works. I've tried it, but I got overflows or I got a string that was reading every char 2 times...

I'm totally new to this, only have been programming for 2-3 weeks now. Sorry for the maybe very easy question.

robtillaart

I noticed it is a popular subject these days in schools ...

backgrounder - http://www.technik.dhbw-ravensburg.de/~lau/ultrasonic-anemometer.html -
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

robtillaart



Receiver
Code: [Select]


char data[40];
int idx = 0;

void setup()
{
Serial.begin(9600);
Serial2.begin(9600);
Serial.println("power on");
}

void loop()
{
  if (Serial2.available() > 0)
  {
    c = Serial2.read();
    data[idx++] = c;
    if (c == '\n') // end of line
    {
      data[idx]  = 0; // string terminator
      processData();
      idx = 0;
    }
  }
}

void processData()
{
  // split the char array in fields (hint use strtok()
  // and process them e.g. printing 
}
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Shad0x

Where I am at the moment I get this as result:

Code: [Select]
$IIMWV,225.0,R,000.0,N,A *38$IIMWV,225.0,
$IIMWV,225.0,R,000.0,N,A *38$IIMWV,225.0R
$IIMWV,225.0,R,000.0,N,A *38$IIMWV,225.0,
$IIMWV,225.0,R,000.0,N,A *38$IIMWV,225.00
$IIMWV,225.0,R,000.0,N,A *38$IIMWV,225.00
$IIMWV,225.0,R,000.0,N,A *38$IIMWV,225.00
$IIMWV,225.0,R,000.0,N,A *38$IIMWV,225.0.
$IIMWV,225.0,R,000.0,N,A *38$IIMWV,225.00
$IIMWV,225.0,R,000.0,N,A *38$IIMWV,225.0,
$IIMWV,225.0,R,000.0,N,A *38$IIMWV,225.0N
$IIMWV,225.0,R,000.0,N,A *38$IIMWV,225.0,
$IIMWV,225.0,R,000.0,N,A *38$IIMWV,225.0A
$IIMWV,225.0,R,000.0,N,A *38$IIMWV,225.0
$IIMWV,225.0,R,000.0,N,A *38$IIMWV,225.0*
$IIMWV,225.0,R,000.0,N,A *38$IIMWV,225.03
$IIMWV,225.0,R,000.0,N,A *38$IIMWV,225.08
$IIMWV,225.0,R,000.0,N,A *38$IIMWV,225.0$
$IIMWV,225.0,R,000.0,N,A *38$IIMWV,225.0I
$IIMWV,225.0,R,000.0,N,A *38$IIMWV,225.0I
$IIMWV,225.0,R,000.0,N,A *38$IIMWV,225.0M
$IIMWV,225.0,R,000.0,N,A *38$IIMWV,225.0W
$IIMWV,225.0,R,000.0,N,A *38$IIMWV,225.0V
$IIMWV,225.0,R,000.0,N,A *38$IIMWV,225.0,
$IIMWV,225.0,R,000.0,N,A *38$IIMWV,225.02
$IIMWV,225.0,R,000.0,N,A *38$IIMWV,225.02


Etc... As you see, there are no endings in my strings, did I do something wrong with the transmitter program where I just sent a sting? Because nowhere in that string I have a '\n' . But I look at that to make my strings at the receiver. Or am I totally wrong ?

PaulS

Quote
As you see, there are no endings in my strings

Really? Then how did each $ end up on a new line? The sender appears to be sending a carriage return/line feed that ends a packet.
The art of getting good answers lies in asking good questions.

Shad0x


Quote
As you see, there are no endings in my strings

Really? Then how did each $ end up on a new line? The sender appears to be sending a carriage return/line feed that ends a packet.


Ok, true. But why do I always get half of a string after 1 total string. $IIMWV,225.0,R,000.0,N,A *38$IIMWV,225.00
The green is my string that I sent, and the red is a part of the next string I think. So where in my sending program is the decision made where to stop sending it? Or does it just keeps on sending the same string until my delay is over and than sent it, even if the other is half, again from the beginning?

PaulS

Quote
But why do I always get half of a string after 1 total string. $IIMWV,225.0,R,000.0,N,A *38$IIMWV,225.00
The green is my string that I sent, and the red is a part of the next string I think. So where in my sending program is the decision made where to stop sending it? Or does it just keeps on sending the same string until my delay is over and than sent it, even if the other is half, again from the beginning?

I don't know what code you are now running on the sender, or what code you are now running on the receiver, so I can't answer your question.
The art of getting good answers lies in asking good questions.

Shad0x

My sender is the program I put in my opening post.

My receiver now looks like this:

Code: [Select]

#include <string.h>

char data[40];
int dataStream;
int index = 0;
char *str = 0;
char *pointer = 0;

void setup()
{
Serial.begin(9600);
Serial2.begin(9600);
Serial.println("power on");
}

void loop()
{
  while (Serial2.available() > 0)
  {
    dataStream = Serial2.read();
   
    if (dataStream == '\n') // end of line
    {
      index = 0;
      data[index]  = 0; // string terminator
      processData();
    }
    else
    {
      data[index] = dataStream;
      index++;
    }
      Serial.println(data);
    }
}

void processData()
{
  while ((str = strtok_r(pointer, ",", &pointer)) != "\n") // delimiter is the comma
  {
   Serial.println(str);
  }
   pointer = NULL;
}


The void processData is just something that isn't working yet. I still need to figure out how this all works. I'm pretty new to programming so I have still a lot to learn...

robtillaart


$IIMWV,225.0,R,000.0,N,A *38$IIMWV,225.0A
your output looks this way probably  because the receiving char array is 40 bytes long and the lines too

There is a bug in your code (you did't copy very well ;)

your copy
Code: [Select]

    if (dataStream == '\n') // end of line
    {
      index = 0;
      data[index]  = 0; // string terminator
      processData();
    }


my original
Code: [Select]

    if (c == '\n') // end of line
    {
      data[idx]  = 0; // string terminator
      processData();
      idx = 0;
    }


do you notice the fundamental difference?
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

PaulS

Quote
The void processData is just something that isn't working yet.

Isn't working? Or, isn't called?

I'm not sure why you feel it necessary to print data each time you read a new character. data is not properly NULL terminated unless a carriage return arrives, so most of the time, data is not a valid array to pass to a function that expects a string (a NULL terminated array of chars).

You need to add
Code: [Select]
data[index] = '\0';
after
Code: [Select]
      data[index] = dataStream;
      index++;

dataStream is a lousy name for something that is not a stream, by the way.

Finally, strtok_r() is the thread-safe, and far more complex, version of strtok(). Since the Arduino is not multi-threaded, the advantages of using a thread-safe function escape me, while the disadvantages are obvious - larger code and far more variables to keep track of.
The art of getting good answers lies in asking good questions.

Shad0x

#10
May 06, 2012, 07:05 pm Last Edit: May 06, 2012, 07:29 pm by Shad0x Reason: 1


$IIMWV,225.0,R,000.0,N,A *38$IIMWV,225.0A
your output looks this way probably  because the receiving char array is 40 bytes long and the lines too

There is a bug in your code (you did't copy very well ;)

your copy

my original

do you notice the fundamental difference?



-I tried to put the data [28] but this didn't made any difference for some reason, that's why I put it back to 40.

-The bad copy is because your way wasn't very clear for me, and I found this one on the arduino forum. And this I did understand more. But I guess I don't get the fundamental difference than.. It would be nice if you maybe can explain it a little for me   :smiley-red:

@ PaulS:
-It's possible that it isn't called because I actually didn't knew it was possible to make a void that way.
- For the NULL terminated part, I don't know if I'm getting it right? So the '\0' tells that this is the end of the string, right? And with my 0 I'm just doing something foolish?
The data isn't a string at that moment? Because I thought, what I was doing is getting every character and putting if behind each other and therefor make a string? (correct me if I'm wrong)
- I changed dataStream to SerialInput. This maybe fits better.
-I used the strtok_r() because when I searched how the strtok() function worked, I always ended up with the strtok_r() function. What I got from it was that you can't overwrite the data in a memory with the strtok_r(), and with the normal strtok() you could. So I think this wasn't a good idea after all. The multi-threaded thing, I don't understand it yet. I'll search about it so that I can follow you.


I'm very sorry for these noobisch questions, but I can't help it that I need to do this for my bachlor thesis. I just hope I learn something about it because it looks very interesting atm. Even with this little knowledge that I got.

If there are other, better options to get the information from the received string, you can always tell, I don't know if this is the best way.

robtillaart

Quote
if you maybe can explain it a little for me


The fundamental difference is that I set the last element of the array with index idx to zero to get a proper zero terminated char array. That is the way C likes it.

You set the index to 0 and then set the first element of the array to zero. This causes problems in the strtok() code as it sees in essence an empty string ...(

Give it a try ...


Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Shad0x

Ok, I remade it to the things you teached me and put some comments at every line so that you see what I think it does.
Code: [Select]
char data[27];
int SerialInput;
int index = 0;

void setup()
{
Serial.begin(9600);
Serial2.begin(9600);
Serial.println("power on");
}

void loop()
{
  if (Serial2.available() > 0)
  {
    SerialInput = Serial2.read();  //Give a name to the input characters on RX2
    data[index]  = SerialInput;  //Put the characters into a string each character placed 1 position behind the previous one
    index++;
   
    if (SerialInput == '\n')   //If the SerialInput has ended his line
    {
      data[index] = 0;  //give the string a 0 on the end so it know it has ended
      processData();  // start void processData??
      index = 0;  // Let the index start from 0 again
    }
  }
if (index == 27)  // if the total string is placed, print the string
{
   Serial.println(data);
}
}


As result I only get 2 lines... After that it stops for some reason. If I remove my last If-loop, the data will be printed every time something changes. Therefore I get a lot of lines, but with a lot of wrong characters. They appear random in my strings.
The last character with the program I have right now is wrong, I get a 3 in stead of 8 (What I send him)

Again, thanks for all the help so far! Really nice people.
My questions:
-I am making a string right? Not an array, because I'm getting more confused every minute.
-Is data[index++] the same as data[index] and on the next line index++ Because once I got a different result... But after I uploaded it again this was ok.
-Is saying data[index] = 0 the same as data[index] = '\0' ? Or is the 0 character automatically seen as the  carriage return like PaulS told me to use?


PaulS

A string is an array of chars THAT IS NULL TERMINATED.

Just because you have an array that contains characters is not enough to make it a string. The NULL terminator is required.

Rob's code is correct in that it does add a NULL terminator, before expecting it to be used as a string, but I don't like it because the array is not always a string, so you can't print it as a string at any time. I prefer, and it doesn't take that much extra time, to always add a NULL after each character, so that the char array is always a string.
The art of getting good answers lies in asking good questions.

robtillaart

@PaulS
you are right, keeping the char array correctly terminated is far more robust.
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Go Up