Pages: [1] 2   Go Down
Author Topic: reading serial port  (Read 1015 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 16
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,
I've got problems storing the byte read from the serial port. Here is the code:

Code:
long interval = 1000;
long previous = 0;
char string[300];

void setup() {
  int j;
  Serial.begin(115200);
  for(j=0; j<300; j++) {string[j] = '\0';}
}

void loop() {
  unsigned long start = millis();
  byte p;
  char c;
  int i=0,j;
 
   if (Serial.available()>0) {     
     while (Serial.available() >0) {
      c=Serial.read();
      string[i] = c;
      //Serial.print("i: ") ;
      i++;
     }
   }
   if (start-previous > interval) {
     Serial.print("string: ");
     Serial.println(string);
     previous = start;
  }
}

Using serial monitor I send "123456", but the I've got

Code:
string: 6

While un-commenting the line:
Code:
//Serial.print("i: ") ;

 I've got:
Code:
i: i: i: i: i: i: string: 123456
string: 123456

Obviously I'd like to have the "123456" string. Can anyone help me to explain the situation?
Thank you in advance,

Logged

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

Quote
Can anyone help me to explain the situation?
Briefly: Serial communications are slow, microcontrollers are fast.
Slowing your sketch down by adding delays (or in your case prints) allows the serial comms to catch up.
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.

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

Code:
     Serial.print("string: ");
     Serial.println(string);
Try sending 1234567890 followed by ABCD. Prepare to be disappointed. Prepare to learn the difference between a string and an array of chars to resolve the problem.
Logged

Switzerland
Offline Offline
Faraday Member
**
Karma: 96
Posts: 4702
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

This slightly different version will probably do what you want.

loop() is executed very often if you don't slow it down (by using Serial.print()). If you start your string (by setting i to 0) in every run, you won't get much string.

Code:
long interval = 1000;
long previous = 0;
char string[300];
int i = 0;

void setup() {
  int j;
  Serial.begin(115200);
  for(j=0; j<300; j++) {string[j] = '\0';}
}

void loop() {
  unsigned long start = millis();
  byte p;
  char c;
  int j;
 
   if (Serial.available()>0) {     
     while (Serial.available() >0) {
      c=Serial.read();
      string[i] = c;
      //Serial.print("i: ") ;
      i++;
     }
   }
   if (start-previous > interval) {
     Serial.print("string: ");
     Serial.println(string);
     previous = start;
     i=0;
  }
}
Logged

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

Quote
loop() is executed very often if you don't slow it down (by using Serial.print()). If you start your string (by setting i to 0) in every run, you won't get much string.
Which, of course, is why you need start and end of packet markers to properly manage serial data. Receiving strings bounded by start and end markers is then trivial:
 
Code:
#define SOP '<'
#define EOP '>'

bool started = false;
bool ended = false;

char inData[80];
byte index;

void setup()
{
   Serial.begin(57600);
   // Other stuff...
}

void loop()
{
  // Read all serial data available, as fast as possible
  while(Serial.available() > 0)
  {
    char inChar = Serial.read();
    if(inChar == SOP)
    {
       index = 0;
       inData[index] = '\0';
       started = true;
       ended = false;
    }
    else if(inChar == EOP)
    {
       ended = true;
       break;
    }
    else
    {
      if(index < 79)
      {
        inData[index] = inChar;
        index++;
        inData[index] = '\0';
      }
    }
  }

  // We are here either because all pending serial
  // data has been read OR because an end of
  // packet marker arrived. Which is it?
  if(started && ended)
  {
    // The end of packet marker arrived. Process the packet

    // Reset for the next packet
    started = false;
    ended = false;
    index = 0;
    inData[index] = '\0';
  }
}
Logged

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

Before to try with communication markers, I've tryed with this code:

Code:
long interval = 3000;
long previous = 0;
char string[300];
int i=0;

void setup() {
  int j;
  Serial.begin(115200);
  for(j=0; j<300; j++) {string[j] = '\0';}
}

void loop() {
  unsigned long start = millis();
  byte p;
  char c;
  int j;
 
   if (Serial.available()>0) {     
     while (Serial.available() >0) {
      c=Serial.read();
      string[i] = c;
      //Serial.print(c) ;
      delay(10);
      i++;
     }
   }
   if (start-previous > interval) {
     Serial.print("string: ");
     Serial.println(string);
     previous = start;
     i=0;
  }
}

That is working very well with short messagges, but when I try with:
Code:
#1234567890#0#1234567890#1#1234567890#2#1234567890#3#1234567890#4#1234567890#5#1234567890#6#1234567890#7#1234567890#8#1234567890#9#1234567890#10#1234567890#11#1234567890#12#1234567890#13#1234567890#14#1234567890#15#1234567890#16#1234567890#17#1234567890#123

I obtain:
Code:
string: #1234567890#0#1234567890#1#1234567890#2#1234567890#3#1234567890#28

Is there another obvious reason for this behaviour?
Thank you in advance,
Logged

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

Quote
s there another obvious reason for this behaviour?
A break of 10ms or more in the transmission?
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.

Switzerland
Offline Offline
Faraday Member
**
Karma: 96
Posts: 4702
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
if (start-previous > interval) {

This is depending only on a variable set in the body of the if block (previous). Let's assume you're sending the big string when start - previous is at 998. You get as many characters as the serial interface gets (there's a limit for the buffer, 64 I think). You're not reading for a second but only for 2 ms giving about 23 bytes for the baud rate you chose.
Logged

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

@pylon: I don't think that's the reason - if you look at the "while" loop, you'll see a 10 ms delay in it.
Normally at this rate, that would be enough time to receive 115 characters, so you would expect the receiver to stay locked in the "while" loop, until a break of at least 10 milliseconds.
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.

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

I've put 10ms delay inside the loop.
This is the complete transmission

Code:
string:
string:
string:
string: #1234567890#0#1234567890#1#1234567890#2#1234567890#3#1234567890#28
string: #1234567890#0#1234567890#1#1234567890#2#1234567890#3#1234567890#28
string: #1234567890#0#1234567890#1#1234567890#2#1234567890#3#1234567890#28

Why the string is always the same?
Logged

Switzerland
Offline Offline
Faraday Member
**
Karma: 96
Posts: 4702
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

@AWOL: Correct, I looked at the code I posted, there was no delay. My fault, should always look at the newest posted code :-).
Logged

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

Quote
Why the string is always the same?
Because the data is already in your array - you're resetting the index, but not treating the array like a C string, terminating it each time you read in a new character.
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.

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

Quote
Because the data is already in your array - you're resetting the index, but not treating the array like a C string, terminating it each time you read in a new character.
Exactly. See reply #2.
Logged

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

Sorry,

I've update the code with your suggestion (if I understand):
Code:
long interval = 3000;
long previous = 0;
char string[300];
int i=0;

void setup() {
  int j;
  Serial.begin(115200);
  for(j=0; j<300; j++) {string[j] = '\0';}
}

void loop() {
  unsigned long start = millis();
  byte p;
  char c;
  int j;

   if (Serial.available()>0) {     
     while (Serial.available() >0) {
      c=Serial.read();
      string[i] = c;
      string[i+1] ='\0';
      //Serial.print(c) ;
      delay(10);
      i++;
     }
   }
   if (start-previous > interval) {
     Serial.print("string: ");
     Serial.println(string);
     previous = start;
     i=0;
  }
}

I've got the following result...
Code:
string:
string:
string: #1234567890#0#1234567890#1#1234567890#2#1234567890#3#1234567890#29
string: #1234567890#0#1234567890#1#1234567890#2#1234567890#3#1234567890#29
string: #1234567890#0#1234567890#1#1234567890#2#1234567890#3#1234567890#29
string: #1234567890#0#1234567890#1#1234567890#2#1234567890#3#1234567890#29
string: #1234567890#0#1234567890#1#1234567890#2#1234567890#3#1234567890#29

Why I didn't solve the problem?
Logged

New Hampshire
Offline Offline
God Member
*****
Karma: 13
Posts: 779
There are 10 kinds of people, those who know binary, and those who don't.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

You're also overflowing your serial buffer.  At 115200 baud rate, you're transmission rate is about 11 characters per millisecond.  With a 10msec delay, you can potentially receive 11.5*10= 115 characters during your delay.  You then grab a single character and delay another 10msec.  The serial buffer will quickly overflow if you send a long string of data.

Bottom line is, delay() should never be used to sync up serial communications.  As Pauls has already said (but I'll restate more emphatically), the ONLY way to properly and reliably sync up nontrivial serial communications is with start and end of packet markers.
Logged


Pages: [1] 2   Go Up
Jump to: