Pages: 1 [2] 3   Go Down
Author Topic: Help with reading string from serial  (Read 3017 times)
0 Members and 1 Guest are viewing this topic.
Pittsburgh, PA, USA
Offline Offline
Faraday Member
**
Karma: 96
Posts: 4773
I learn a bit every time I visit the forum.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

As Grumpy_Mike says, you can not have 2 program using the same port on a PC. That may be a cause of the problem.

Grumpy_Mike is right.

I don't know any way to make the USB connected serial use different pins so perhaps if you use SoftwareSerial to connect the LCD to some other pins then your whole problem will be solved.

http://www.arduino.cc/en/Tutorial/SoftwareSerial
Logged

I find it harder to express logic in English than in Code.
Sometimes an example says more than many times as many words.

0
Offline Offline
Tesla Member
***
Karma: 141
Posts: 9470
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Moving target is spec that keep changing. 1st I write this and then you say it must do that. Mumbo-jumbo meaning -you- don't understand, therefore it must be nonsense?

I repeatedly (even using direct quoating of your statement) requested you to post the code you were talking about, and apparently you had a "brain freeze" and didn't understand what you previously posted.

Quote
EOL is standard for End Of Line. I even spelled it out in the first sentence of that post. Did you bother to read?

I know what EOL is (cr and/or lf), you just kept asking pointless questions instead of posting code.

Quote
You even QUOTE ME on that: they take 2 bytes per character

Interesting, so when C++ Strings are used in an IDE when writing code, the final machine code compiled for the processor will cause the processor to use two bytes per character as opposed to one byte per character when your method is used?



Logged

Consider the daffodil. And while you're doing that, I'll be over here, looking through your stuff.   smiley-cool

Pittsburgh, PA, USA
Offline Offline
Faraday Member
**
Karma: 96
Posts: 4773
I learn a bit every time I visit the forum.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

apparently you had a "brain freeze" and didn't understand what you previously posted.

or I felt that what you asked must be too simple to be believed.

Quote
you just kept asking pointless questions instead of posting code.

and you kept requesting pointless code

Quote
Quote
You even QUOTE ME on that: they take 2 bytes per character

Interesting, so when C++ Strings are used in an IDE when writing code, the final machine code compiled for the processor will cause the processor to use two bytes per character as opposed to one byte per character when your method is used?

I haven't torn into them on the Arduino. On my PC they do. And BTW, "my" method of dealing with strings is standard C. There's even a library I use called string.h. That's strings as opposed to Strings.

Nice to be told in a left-handed way that Arduino-IDE code doesn't use 2 bytes per character, if that's true.

And you've got your code example now so when you're ready, let's hear why you don't like that.





[/quote]
Logged

I find it harder to express logic in English than in Code.
Sometimes an example says more than many times as many words.

0
Offline Offline
Tesla Member
***
Karma: 141
Posts: 9470
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
And you've got your code example now so when you're ready, let's hear why you don't like that.

Where did I say that I didn't like it?  smiley-wink  You said,

Quote
I dunno why anyone would use C++ Strings on an Arduino, they take 2 bytes per character to do things that you might use on a PC. What a waste.

which seems to indicate that you are saying that using the string functions in the arduino environment some how translates to final machine code loaded in the arduino chip that waste bytes. I'm not familiar how the arduino string librarys interact with the arduino C compiler compared to using the usual C language. I've read post concerning possible issues with using the string librarys, but they were high level and did not provide a technical basis. So what is your technical basis for your statement concerning the string functions using two bytes in the arduino environment vs. the standard C language?

Logged

Consider the daffodil. And while you're doing that, I'll be over here, looking through your stuff.   smiley-cool

Pittsburgh, PA, USA
Offline Offline
Faraday Member
**
Karma: 96
Posts: 4773
I learn a bit every time I visit the forum.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

So what is your technical basis for your statement concerning the string functions using two bytes in the arduino environment vs. the standard C language?

Actually it doesn't, I'm trying to recall, but a C++ String object does contain overhead and really needs to be accessed through member functions. Still when I look where the data function points I do get single bytes.

The 2 byte characters are the wide-character format.

Still why would I want to include String object support unless I really need it? Why bring in a bunch of baggage just out of habit or not knowing how to get along without it? I don't include string.h unless I need it either.

It wouldn't be such an issue for me if these chips had a lot more flash and SRAM.


Logged

I find it harder to express logic in English than in Code.
Sometimes an example says more than many times as many words.

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 474
Posts: 18696
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I need to read a string sent from processing to the arduino. Seems simple enough. I have a processing program that justs write "abc123" to the arduino via serial and a arduino program that trys to read it and send it back. The problem I am getting is that the arduino serial monitor is showing stuff like this:
...
ab23
ab23
bcac123
a123
a1
a1
1

Weird. Here is my arduino code:


Rewrite, eliminating all the delay () calls.  Basically delay (x) says "do nothing else until x mS elapse". So don't complain if stuff doesn't get done.
Logged

0
Offline Offline
Tesla Member
***
Karma: 141
Posts: 9470
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Rewrite, eliminating all the delay () calls.  Basically delay (x) says "do nothing else until x mS elapse". So don't complain if stuff doesn't get done.

That points up two things, 1) there is a new requirement placed on the component sending data that a delimiter be included in what is being sent (instead of a delay between the transmissions as one has using the serial monitor for testing), and 2) the people that always say remove the delay generally never post improved *working* code that removes the delay. Goes back to those that can vs. those that can't. I don't want to be a forum "catfish".
Logged

Consider the daffodil. And while you're doing that, I'll be over here, looking through your stuff.   smiley-cool

Offline Offline
Newbie
*
Karma: 0
Posts: 15
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Geez, goforsmoke and zoomkat, that was the longest "he said" "she said" argument I have seen on this forum. I don't really understand what you two are talking about, but I know if you want to get anything done, you need to make a clear objective post that shouldn't contain unnecessary quotes that escalate the situation. As for my original question, what is the cause of the jumbled serial monitor? Nick Gammon suggested that it is because of the delay()s. Is this the only problem? I also agree with zooomkat that you should put example code instead of just ideas. It makes for a much for clear post. Thanks.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 15
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I have found a solution to my problem. After reading what techcone said about 2 programs using the serial, I closed down the serial monitor and made processing print the incoming serial. Thanks.

Processing and Arduino code if anyone wants:
The important part of the arduino program:
Code:
String readString(char terminator) {
  byte index=0;
  char data[18] = "";
  while(index<18) {
    if(Serial.available() > 0) {
      char c = Serial.read();
      if(c == terminator) break;
      data[index] = c;
      index++;
    }
  }
  return data;
}

And processing:
Code:
import processing.serial.*;

Serial myPort;

char TerminateChar = '*';

void setup() {
  size(100,100);
  myPort = new Serial(this,Serial.list()[0],9600);
}

void draw() {
  background(50);
  //arduinoPort.write(composePitch(0.1));
  /*
  char data[] = {'a','b','c','d','\n'};
  for(char c:data) {
    arduinoPort.write(c);
  }
  */
  myPort.write('a');
  myPort.write('b');
  myPort.write('c');
  myPort.write('d');
  myPort.write(',');
  if(myPort.available() > 0) {
    delay(5);
    String input = myPort.readStringUntil(',');
    print(input);
  }
  delay(200);
}
Logged

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 291
Posts: 25854
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Your Arduino code returns a char array for a function that is supposed to return a String.
It isn't even a C string, because it has no termination.
« Last Edit: November 12, 2011, 03:34:14 pm by AWOL » Logged

"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 474
Posts: 18696
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

... the people that always say remove the delay generally never post improved *working* code that removes the delay. Goes back to those that can vs. those that can't.

Apart from this?

http://www.gammon.com.au/blink

Anyway, in the interests of explaining, here is a version of the original post that eliminates delays, and uses millis instead.

Code:
void setup() {
  Serial.begin(9600);
}  // end of setup


// read into buffer until terminator received
// timeout if not received within timeout_period mS
// returns true if received within timeout period
// returns false if not received, or no terminator received but buffer full
bool readStringUntil (char * data,
                     const unsigned int length,
                     const unsigned long timeout_period,
                     const char terminator)
  {
  unsigned int index = 0;
  unsigned long start_time = millis ();
 
  while (index < length)
    {
     
    // check if time is up
    if (millis () - start_time >= timeout_period)
       return false;  // no data in timeout period

    // if data, add to buffer       
    if (Serial.available () > 0)
      {
      char r = Serial.read();
      if (r == terminator)
        {
        data [index] = 0;  // terminating null byte
        return true;
        }  // end if terminator reached
       
      data [index++] = r;
      }  // end if available

  }  // end while loop

  return false;  // filled up without terminator
 
}  // end of readStringUntil

void loop() {
 
 
  // see if there's incoming serial data:
  if (Serial.available() > 0) {
    char foo [20];
   
    if (readStringUntil (foo, sizeof foo, 500, '\n'))
      {
      Serial.print ("Got: ");
      Serial.println (foo);
      }
    else
      Serial.println ("timeout");
  }   
}  // end of loop

This also eliminates the use of the String class, which I think you will thank me for later.

Rather than using a "counted" timeout the code above uses a (supplied) timeout in mS. By checking millis () we can see if this is up.

It also fixes the problem of the original not putting a 0x00 at the end of the string, and also the (possible) problem of checking for data [ index ] being equal to terminator due to the fact that you are testing a memory location that has not been set yet.
Logged

0
Offline Offline
Tesla Member
***
Karma: 141
Posts: 9470
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

... the people that always say remove the delay generally never post improved *working* code that removes the delay. Goes back to those that can vs. those that can't.

Apart from this?

http://www.gammon.com.au/blink

You didn't even post the link, so Bzzzzzzt!  smiley
Logged

Consider the daffodil. And while you're doing that, I'll be over here, looking through your stuff.   smiley-cool

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 474
Posts: 18696
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I prefer to not use a separate function which "blocks" like readStringUntil does, because while you are inside readStringUntil you can't process other things (like button presses).

The example below shows how you can collect data in "loop" without blocking at all (without delay, hehe) and also lets you do other things in loop (eg. test switches). This is adapated a bit from my RFID reader code. In this case I am using newline as a terminator and discarding carriage-return. The newline is not stored in the buffer, but the buffer is null-terminated so you can subsequently use strcmp on it if you want to.

Code:
/*
Example of processing incoming serial data without blocking.

Author: Nick Gammon
Date:   13 November 2011

Released for public use.
*/

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


const unsigned int MAX_INPUT = 20;
char input_line [MAX_INPUT];
unsigned int input_pos = 0;

void loop()
{

  if (Serial.available () > 0)
    {
    char inByte = Serial.read ();

    switch (inByte)
      {

      case '\n':   // end of text
        input_line [input_pos] = 0;  // terminating null byte
        
        // terminator reached! process input_line here ...
        Serial.println (input_line);
  
        // reset buffer for next time
        input_pos = 0;  
        break;
  
      case '\r':   // discard carriage return
        break;
  
      default:
        // keep adding if not full ... allow for terminating null byte
        if (input_pos < (MAX_INPUT - 1))
          input_line [input_pos++] = inByte;
        break;

      }  // end of switch

  }  // end of incoming data

  // do other stuff here like testing digital input (button presses) ...

}  // end of loop

In the case of the RFID reader there were an extra couple of lines inside the switch statement:

Code:
   
    case 2:    // start of text
      input_pos = 0;
      break;

That was because it sent 0x02 (STX) at the start of scanning a new card. Thus you would set the input position back to zero to get rid of any "noise characters" which you might have received.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 15
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

AWOL, how can I turn a char array into a String object? I need the string methods for later on. Also by adding '\0' to the char[] and then casting, will it make it a legit String? I don't quite understand why everyone says char arrays are better than Strings.
Logged

Seattle, WA USA
Online Online
Brattain Member
*****
Karma: 601
Posts: 48554
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
I don't quite understand why everyone says char arrays are better than Strings.
Because char arrays are usually statically defined, while Strings use dynamically allocated memory.

On a system with 4G of memory, dynamically allocating space is fine. On a system with 2K of memory, dynamically allocating memory, especially in the small chunks that String does, causes problems.

Quote
I need the string methods for later on.
The String class simply uses the string functions internally. There is no reason why you can't do the same. The string functions are as easy to use as the stuff in the String class.
Logged

Pages: 1 [2] 3   Go Up
Jump to: