UART sometimes missing first few characters on ATmega328P

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP












3












$begingroup$


I wrote some code for the ATmega328P, (Packaged in a module that clones the Arduino Nano).



Normally when I send UART data from my computer to these micros, it is received just fine. However I have started a new project and I am getting intermittent characters missing from the beginning of a message.



The code I wrote thus far reads the incoming data and prints it back to the computer. I am trying to send "<A2>". Something like 80% of the messages are received and printed back fine. The rest are missing characters. Oddly, they are at the beginning of the message, giving me "A2>" or "2>"



I am using a baud of 115200, though 9600 and even 600 appear to give the same ratio of bad messages. I tried swapping the micro and there was no change. I'm only sending messages once every 5 seconds or so.



The micro is being powered from the same USB cable going to the laptop that the data is sent over.



Below are oscilloscope/logic analyzer captures of two signals, one that worked fine and another that was missing characters. The probe is placed right at the "RX" pin and grounded right at "GND".



Signal received as "<A2>" (correct):
Scope capture (good)



Signal received as only "2>" (incorrect):
Scope capture (Not good?)



Those two signals look awfully close.



Update: As user duskwuff mentioned, the UART signals are actually not approaching 0V for LOW.



I tried using nothing but the bare module itself (no protoboard, nothing), but I'm getting the same results.



To further diagnose, I tried manually writing to the RX pin. That makes the signal swing properly down to 0V.



Test code:



void setup()

delay(500);
pinMode(0, OUTPUT);

while (true)

digitalWrite(0, HIGH);
delay(2000);
digitalWrite(0, LOW); //This reaches 0V
delay(2000);




Watching the RX line during code flash, the LOW is also about 1.5V.



Now I'm extra confused. How can I get the same result with multiple bare-modules, even brand-name ones? That makes me lean toward blaming software.



Arduino Nano Clone

Image from wikimedia.org



The purpose of my this code is to create a sort of protocol for received messages that processes them one at a time, even if multiples are sent all at once ("<A1><A2><A3>...") or if they are sent in only partial pieces ("<A" and then "2>").



const int pinBuzzer = A5; // the number of pin for the buzzer

unsigned long T = 0; // "T" value


//max input size expected for a single incoming msg
#define INPUT_SIZE 32
char serialCommandstr[INPUT_SIZE + 1];
char serialCommand_singleChar; //single char for itterating through incoming WX
byte serialCommandindex = 0; //index of RX buffer for itterating
bool serialCommand_msgPending = false; // if msg exists in buffer without termination ('>');
bool serialCommand_ready = false; // if terminated msg ready (a '>' is received)


void setup()

delay(500);
Serial.begin(115200);

// END Setup()


void loop()

Serial.println("Waiting for input in the form of "<XY>"");
Serial.println("X=[A/B], Y=[1~8]");


serialCommand_ready = false;
while (serialCommand_ready == false)

serialPreParse();

if (serialCommandstr[1] == 'A')

T = (serialCommandstr[2] - 1) - char('0');
Serial.print("A, ");


Serial.print("T=");
Serial.print(T);
Serial.print("us...");

//Beep to indicate waveform start
tone(pinBuzzer, 1319, 50);
delay(51);



void serialPreParse()

if (Serial.available() && serialCommand_msgPending == false)

// NEW incoming message (buffer previously empty)

//reinitialize
serialCommandstr[0] = '';
serialCommand_singleChar = '';
serialCommandindex = 0;
serialCommand_msgPending = true; // if msg received without termination
serialCommand_ready = false; // if terminated msg ready



while (Serial.available())

if (serialCommandindex == INPUT_SIZE)

//maximum size of C string reached
break;

serialCommand_singleChar = Serial.read();
//strcat(serialCommand_singleChar, serialCommandstr);
serialCommandstr[serialCommandindex] = serialCommand_singleChar;
serialCommandindex++;
serialCommandstr[serialCommandindex] = ''; //null-termination

if (serialCommand_singleChar == '>')

//End of single msg.
serialCommand_ready = true;
serialCommand_msgPending = false;
break;





if (serialCommand_ready == true)

if (serialCommandstr[0] != '<')

Serial.println("nIncomplete command!");


Serial.println();
Serial.print("RX:"");
Serial.write(serialCommandstr);
Serial.println(""");














share|improve this question











$endgroup$







  • 1




    $begingroup$
    What is your 328Ps clock source, and at what frequency?
    $endgroup$
    – marcelm
    Jan 23 at 21:35










  • $begingroup$
    It's a 16MHz crystal.
    $endgroup$
    – Bort
    Jan 24 at 0:19










  • $begingroup$
    It sounds to me like the UART isn't synching up correctly. I'm not familiar with modern ones, but 40 years ago you could sometimes select the clock divider value -- 16 was normal but you could go to 4 if you knew your clock and the signal were in sync. The higher the divider (with the clock multiplied appropriately) the better, within reason.
    $endgroup$
    – Hot Licks
    Jan 24 at 3:59










  • $begingroup$
    Another kinda stupid question is whether your program is enabling interrupts, polling, or whatever is needed at the appropriate time. If your program is off doing something else, or if it simply doesn't know the data has arrived, it will miss the data. (Do you check the UART's "overrun" flag?)
    $endgroup$
    – Hot Licks
    Jan 24 at 4:04










  • $begingroup$
    @Marcelem That's not a crystal at all- it's a ceramic resonator (under the D5 marking on the PCB). Not nearly as accurate as a crystal, but should be okay enough for serial communications.
    $endgroup$
    – Spehro Pefhany
    Jan 24 at 15:04















3












$begingroup$


I wrote some code for the ATmega328P, (Packaged in a module that clones the Arduino Nano).



Normally when I send UART data from my computer to these micros, it is received just fine. However I have started a new project and I am getting intermittent characters missing from the beginning of a message.



The code I wrote thus far reads the incoming data and prints it back to the computer. I am trying to send "<A2>". Something like 80% of the messages are received and printed back fine. The rest are missing characters. Oddly, they are at the beginning of the message, giving me "A2>" or "2>"



I am using a baud of 115200, though 9600 and even 600 appear to give the same ratio of bad messages. I tried swapping the micro and there was no change. I'm only sending messages once every 5 seconds or so.



The micro is being powered from the same USB cable going to the laptop that the data is sent over.



Below are oscilloscope/logic analyzer captures of two signals, one that worked fine and another that was missing characters. The probe is placed right at the "RX" pin and grounded right at "GND".



Signal received as "<A2>" (correct):
Scope capture (good)



Signal received as only "2>" (incorrect):
Scope capture (Not good?)



Those two signals look awfully close.



Update: As user duskwuff mentioned, the UART signals are actually not approaching 0V for LOW.



I tried using nothing but the bare module itself (no protoboard, nothing), but I'm getting the same results.



To further diagnose, I tried manually writing to the RX pin. That makes the signal swing properly down to 0V.



Test code:



void setup()

delay(500);
pinMode(0, OUTPUT);

while (true)

digitalWrite(0, HIGH);
delay(2000);
digitalWrite(0, LOW); //This reaches 0V
delay(2000);




Watching the RX line during code flash, the LOW is also about 1.5V.



Now I'm extra confused. How can I get the same result with multiple bare-modules, even brand-name ones? That makes me lean toward blaming software.



Arduino Nano Clone

Image from wikimedia.org



The purpose of my this code is to create a sort of protocol for received messages that processes them one at a time, even if multiples are sent all at once ("<A1><A2><A3>...") or if they are sent in only partial pieces ("<A" and then "2>").



const int pinBuzzer = A5; // the number of pin for the buzzer

unsigned long T = 0; // "T" value


//max input size expected for a single incoming msg
#define INPUT_SIZE 32
char serialCommandstr[INPUT_SIZE + 1];
char serialCommand_singleChar; //single char for itterating through incoming WX
byte serialCommandindex = 0; //index of RX buffer for itterating
bool serialCommand_msgPending = false; // if msg exists in buffer without termination ('>');
bool serialCommand_ready = false; // if terminated msg ready (a '>' is received)


void setup()

delay(500);
Serial.begin(115200);

// END Setup()


void loop()

Serial.println("Waiting for input in the form of "<XY>"");
Serial.println("X=[A/B], Y=[1~8]");


serialCommand_ready = false;
while (serialCommand_ready == false)

serialPreParse();

if (serialCommandstr[1] == 'A')

T = (serialCommandstr[2] - 1) - char('0');
Serial.print("A, ");


Serial.print("T=");
Serial.print(T);
Serial.print("us...");

//Beep to indicate waveform start
tone(pinBuzzer, 1319, 50);
delay(51);



void serialPreParse()

if (Serial.available() && serialCommand_msgPending == false)

// NEW incoming message (buffer previously empty)

//reinitialize
serialCommandstr[0] = '';
serialCommand_singleChar = '';
serialCommandindex = 0;
serialCommand_msgPending = true; // if msg received without termination
serialCommand_ready = false; // if terminated msg ready



while (Serial.available())

if (serialCommandindex == INPUT_SIZE)

//maximum size of C string reached
break;

serialCommand_singleChar = Serial.read();
//strcat(serialCommand_singleChar, serialCommandstr);
serialCommandstr[serialCommandindex] = serialCommand_singleChar;
serialCommandindex++;
serialCommandstr[serialCommandindex] = ''; //null-termination

if (serialCommand_singleChar == '>')

//End of single msg.
serialCommand_ready = true;
serialCommand_msgPending = false;
break;





if (serialCommand_ready == true)

if (serialCommandstr[0] != '<')

Serial.println("nIncomplete command!");


Serial.println();
Serial.print("RX:"");
Serial.write(serialCommandstr);
Serial.println(""");














share|improve this question











$endgroup$







  • 1




    $begingroup$
    What is your 328Ps clock source, and at what frequency?
    $endgroup$
    – marcelm
    Jan 23 at 21:35










  • $begingroup$
    It's a 16MHz crystal.
    $endgroup$
    – Bort
    Jan 24 at 0:19










  • $begingroup$
    It sounds to me like the UART isn't synching up correctly. I'm not familiar with modern ones, but 40 years ago you could sometimes select the clock divider value -- 16 was normal but you could go to 4 if you knew your clock and the signal were in sync. The higher the divider (with the clock multiplied appropriately) the better, within reason.
    $endgroup$
    – Hot Licks
    Jan 24 at 3:59










  • $begingroup$
    Another kinda stupid question is whether your program is enabling interrupts, polling, or whatever is needed at the appropriate time. If your program is off doing something else, or if it simply doesn't know the data has arrived, it will miss the data. (Do you check the UART's "overrun" flag?)
    $endgroup$
    – Hot Licks
    Jan 24 at 4:04










  • $begingroup$
    @Marcelem That's not a crystal at all- it's a ceramic resonator (under the D5 marking on the PCB). Not nearly as accurate as a crystal, but should be okay enough for serial communications.
    $endgroup$
    – Spehro Pefhany
    Jan 24 at 15:04













3












3








3





$begingroup$


I wrote some code for the ATmega328P, (Packaged in a module that clones the Arduino Nano).



Normally when I send UART data from my computer to these micros, it is received just fine. However I have started a new project and I am getting intermittent characters missing from the beginning of a message.



The code I wrote thus far reads the incoming data and prints it back to the computer. I am trying to send "<A2>". Something like 80% of the messages are received and printed back fine. The rest are missing characters. Oddly, they are at the beginning of the message, giving me "A2>" or "2>"



I am using a baud of 115200, though 9600 and even 600 appear to give the same ratio of bad messages. I tried swapping the micro and there was no change. I'm only sending messages once every 5 seconds or so.



The micro is being powered from the same USB cable going to the laptop that the data is sent over.



Below are oscilloscope/logic analyzer captures of two signals, one that worked fine and another that was missing characters. The probe is placed right at the "RX" pin and grounded right at "GND".



Signal received as "<A2>" (correct):
Scope capture (good)



Signal received as only "2>" (incorrect):
Scope capture (Not good?)



Those two signals look awfully close.



Update: As user duskwuff mentioned, the UART signals are actually not approaching 0V for LOW.



I tried using nothing but the bare module itself (no protoboard, nothing), but I'm getting the same results.



To further diagnose, I tried manually writing to the RX pin. That makes the signal swing properly down to 0V.



Test code:



void setup()

delay(500);
pinMode(0, OUTPUT);

while (true)

digitalWrite(0, HIGH);
delay(2000);
digitalWrite(0, LOW); //This reaches 0V
delay(2000);




Watching the RX line during code flash, the LOW is also about 1.5V.



Now I'm extra confused. How can I get the same result with multiple bare-modules, even brand-name ones? That makes me lean toward blaming software.



Arduino Nano Clone

Image from wikimedia.org



The purpose of my this code is to create a sort of protocol for received messages that processes them one at a time, even if multiples are sent all at once ("<A1><A2><A3>...") or if they are sent in only partial pieces ("<A" and then "2>").



const int pinBuzzer = A5; // the number of pin for the buzzer

unsigned long T = 0; // "T" value


//max input size expected for a single incoming msg
#define INPUT_SIZE 32
char serialCommandstr[INPUT_SIZE + 1];
char serialCommand_singleChar; //single char for itterating through incoming WX
byte serialCommandindex = 0; //index of RX buffer for itterating
bool serialCommand_msgPending = false; // if msg exists in buffer without termination ('>');
bool serialCommand_ready = false; // if terminated msg ready (a '>' is received)


void setup()

delay(500);
Serial.begin(115200);

// END Setup()


void loop()

Serial.println("Waiting for input in the form of "<XY>"");
Serial.println("X=[A/B], Y=[1~8]");


serialCommand_ready = false;
while (serialCommand_ready == false)

serialPreParse();

if (serialCommandstr[1] == 'A')

T = (serialCommandstr[2] - 1) - char('0');
Serial.print("A, ");


Serial.print("T=");
Serial.print(T);
Serial.print("us...");

//Beep to indicate waveform start
tone(pinBuzzer, 1319, 50);
delay(51);



void serialPreParse()

if (Serial.available() && serialCommand_msgPending == false)

// NEW incoming message (buffer previously empty)

//reinitialize
serialCommandstr[0] = '';
serialCommand_singleChar = '';
serialCommandindex = 0;
serialCommand_msgPending = true; // if msg received without termination
serialCommand_ready = false; // if terminated msg ready



while (Serial.available())

if (serialCommandindex == INPUT_SIZE)

//maximum size of C string reached
break;

serialCommand_singleChar = Serial.read();
//strcat(serialCommand_singleChar, serialCommandstr);
serialCommandstr[serialCommandindex] = serialCommand_singleChar;
serialCommandindex++;
serialCommandstr[serialCommandindex] = ''; //null-termination

if (serialCommand_singleChar == '>')

//End of single msg.
serialCommand_ready = true;
serialCommand_msgPending = false;
break;





if (serialCommand_ready == true)

if (serialCommandstr[0] != '<')

Serial.println("nIncomplete command!");


Serial.println();
Serial.print("RX:"");
Serial.write(serialCommandstr);
Serial.println(""");














share|improve this question











$endgroup$




I wrote some code for the ATmega328P, (Packaged in a module that clones the Arduino Nano).



Normally when I send UART data from my computer to these micros, it is received just fine. However I have started a new project and I am getting intermittent characters missing from the beginning of a message.



The code I wrote thus far reads the incoming data and prints it back to the computer. I am trying to send "<A2>". Something like 80% of the messages are received and printed back fine. The rest are missing characters. Oddly, they are at the beginning of the message, giving me "A2>" or "2>"



I am using a baud of 115200, though 9600 and even 600 appear to give the same ratio of bad messages. I tried swapping the micro and there was no change. I'm only sending messages once every 5 seconds or so.



The micro is being powered from the same USB cable going to the laptop that the data is sent over.



Below are oscilloscope/logic analyzer captures of two signals, one that worked fine and another that was missing characters. The probe is placed right at the "RX" pin and grounded right at "GND".



Signal received as "<A2>" (correct):
Scope capture (good)



Signal received as only "2>" (incorrect):
Scope capture (Not good?)



Those two signals look awfully close.



Update: As user duskwuff mentioned, the UART signals are actually not approaching 0V for LOW.



I tried using nothing but the bare module itself (no protoboard, nothing), but I'm getting the same results.



To further diagnose, I tried manually writing to the RX pin. That makes the signal swing properly down to 0V.



Test code:



void setup()

delay(500);
pinMode(0, OUTPUT);

while (true)

digitalWrite(0, HIGH);
delay(2000);
digitalWrite(0, LOW); //This reaches 0V
delay(2000);




Watching the RX line during code flash, the LOW is also about 1.5V.



Now I'm extra confused. How can I get the same result with multiple bare-modules, even brand-name ones? That makes me lean toward blaming software.



Arduino Nano Clone

Image from wikimedia.org



The purpose of my this code is to create a sort of protocol for received messages that processes them one at a time, even if multiples are sent all at once ("<A1><A2><A3>...") or if they are sent in only partial pieces ("<A" and then "2>").



const int pinBuzzer = A5; // the number of pin for the buzzer

unsigned long T = 0; // "T" value


//max input size expected for a single incoming msg
#define INPUT_SIZE 32
char serialCommandstr[INPUT_SIZE + 1];
char serialCommand_singleChar; //single char for itterating through incoming WX
byte serialCommandindex = 0; //index of RX buffer for itterating
bool serialCommand_msgPending = false; // if msg exists in buffer without termination ('>');
bool serialCommand_ready = false; // if terminated msg ready (a '>' is received)


void setup()

delay(500);
Serial.begin(115200);

// END Setup()


void loop()

Serial.println("Waiting for input in the form of "<XY>"");
Serial.println("X=[A/B], Y=[1~8]");


serialCommand_ready = false;
while (serialCommand_ready == false)

serialPreParse();

if (serialCommandstr[1] == 'A')

T = (serialCommandstr[2] - 1) - char('0');
Serial.print("A, ");


Serial.print("T=");
Serial.print(T);
Serial.print("us...");

//Beep to indicate waveform start
tone(pinBuzzer, 1319, 50);
delay(51);



void serialPreParse()

if (Serial.available() && serialCommand_msgPending == false)

// NEW incoming message (buffer previously empty)

//reinitialize
serialCommandstr[0] = '';
serialCommand_singleChar = '';
serialCommandindex = 0;
serialCommand_msgPending = true; // if msg received without termination
serialCommand_ready = false; // if terminated msg ready



while (Serial.available())

if (serialCommandindex == INPUT_SIZE)

//maximum size of C string reached
break;

serialCommand_singleChar = Serial.read();
//strcat(serialCommand_singleChar, serialCommandstr);
serialCommandstr[serialCommandindex] = serialCommand_singleChar;
serialCommandindex++;
serialCommandstr[serialCommandindex] = ''; //null-termination

if (serialCommand_singleChar == '>')

//End of single msg.
serialCommand_ready = true;
serialCommand_msgPending = false;
break;





if (serialCommand_ready == true)

if (serialCommandstr[0] != '<')

Serial.println("nIncomplete command!");


Serial.println();
Serial.print("RX:"");
Serial.write(serialCommandstr);
Serial.println(""");











microcontroller atmega serial uart c++






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Jan 24 at 21:06







Bort

















asked Jan 23 at 20:51









BortBort

3,32711639




3,32711639







  • 1




    $begingroup$
    What is your 328Ps clock source, and at what frequency?
    $endgroup$
    – marcelm
    Jan 23 at 21:35










  • $begingroup$
    It's a 16MHz crystal.
    $endgroup$
    – Bort
    Jan 24 at 0:19










  • $begingroup$
    It sounds to me like the UART isn't synching up correctly. I'm not familiar with modern ones, but 40 years ago you could sometimes select the clock divider value -- 16 was normal but you could go to 4 if you knew your clock and the signal were in sync. The higher the divider (with the clock multiplied appropriately) the better, within reason.
    $endgroup$
    – Hot Licks
    Jan 24 at 3:59










  • $begingroup$
    Another kinda stupid question is whether your program is enabling interrupts, polling, or whatever is needed at the appropriate time. If your program is off doing something else, or if it simply doesn't know the data has arrived, it will miss the data. (Do you check the UART's "overrun" flag?)
    $endgroup$
    – Hot Licks
    Jan 24 at 4:04










  • $begingroup$
    @Marcelem That's not a crystal at all- it's a ceramic resonator (under the D5 marking on the PCB). Not nearly as accurate as a crystal, but should be okay enough for serial communications.
    $endgroup$
    – Spehro Pefhany
    Jan 24 at 15:04












  • 1




    $begingroup$
    What is your 328Ps clock source, and at what frequency?
    $endgroup$
    – marcelm
    Jan 23 at 21:35










  • $begingroup$
    It's a 16MHz crystal.
    $endgroup$
    – Bort
    Jan 24 at 0:19










  • $begingroup$
    It sounds to me like the UART isn't synching up correctly. I'm not familiar with modern ones, but 40 years ago you could sometimes select the clock divider value -- 16 was normal but you could go to 4 if you knew your clock and the signal were in sync. The higher the divider (with the clock multiplied appropriately) the better, within reason.
    $endgroup$
    – Hot Licks
    Jan 24 at 3:59










  • $begingroup$
    Another kinda stupid question is whether your program is enabling interrupts, polling, or whatever is needed at the appropriate time. If your program is off doing something else, or if it simply doesn't know the data has arrived, it will miss the data. (Do you check the UART's "overrun" flag?)
    $endgroup$
    – Hot Licks
    Jan 24 at 4:04










  • $begingroup$
    @Marcelem That's not a crystal at all- it's a ceramic resonator (under the D5 marking on the PCB). Not nearly as accurate as a crystal, but should be okay enough for serial communications.
    $endgroup$
    – Spehro Pefhany
    Jan 24 at 15:04







1




1




$begingroup$
What is your 328Ps clock source, and at what frequency?
$endgroup$
– marcelm
Jan 23 at 21:35




$begingroup$
What is your 328Ps clock source, and at what frequency?
$endgroup$
– marcelm
Jan 23 at 21:35












$begingroup$
It's a 16MHz crystal.
$endgroup$
– Bort
Jan 24 at 0:19




$begingroup$
It's a 16MHz crystal.
$endgroup$
– Bort
Jan 24 at 0:19












$begingroup$
It sounds to me like the UART isn't synching up correctly. I'm not familiar with modern ones, but 40 years ago you could sometimes select the clock divider value -- 16 was normal but you could go to 4 if you knew your clock and the signal were in sync. The higher the divider (with the clock multiplied appropriately) the better, within reason.
$endgroup$
– Hot Licks
Jan 24 at 3:59




$begingroup$
It sounds to me like the UART isn't synching up correctly. I'm not familiar with modern ones, but 40 years ago you could sometimes select the clock divider value -- 16 was normal but you could go to 4 if you knew your clock and the signal were in sync. The higher the divider (with the clock multiplied appropriately) the better, within reason.
$endgroup$
– Hot Licks
Jan 24 at 3:59












$begingroup$
Another kinda stupid question is whether your program is enabling interrupts, polling, or whatever is needed at the appropriate time. If your program is off doing something else, or if it simply doesn't know the data has arrived, it will miss the data. (Do you check the UART's "overrun" flag?)
$endgroup$
– Hot Licks
Jan 24 at 4:04




$begingroup$
Another kinda stupid question is whether your program is enabling interrupts, polling, or whatever is needed at the appropriate time. If your program is off doing something else, or if it simply doesn't know the data has arrived, it will miss the data. (Do you check the UART's "overrun" flag?)
$endgroup$
– Hot Licks
Jan 24 at 4:04












$begingroup$
@Marcelem That's not a crystal at all- it's a ceramic resonator (under the D5 marking on the PCB). Not nearly as accurate as a crystal, but should be okay enough for serial communications.
$endgroup$
– Spehro Pefhany
Jan 24 at 15:04




$begingroup$
@Marcelem That's not a crystal at all- it's a ceramic resonator (under the D5 marking on the PCB). Not nearly as accurate as a crystal, but should be okay enough for serial communications.
$endgroup$
– Spehro Pefhany
Jan 24 at 15:04










4 Answers
4






active

oldest

votes


















2












$begingroup$

There is a flaw in your handling of your serialCommand_msgPending flag.



Consider the following scenario:



  1. No data has arrived, you call serialPreParse()

  2. serialCommand_msgPending is false

  3. Serial.available() returns 0 in the first line of serialPreParse(), so that block is skipped (so serialCommand_msgPending is still false)

  4. A byte arrives on the serial port

  5. In the while loop, Serial.available() returns 1 (or more, but not a full message), so you read the byte and exit the while loop (no more bytes available) and return from serialPreParse()

  6. serialPreParse() is called again

  7. Serial.available() returns non-zero and serialCommand_msgPending is false, so first block is now executed, re-initialising your buffer and setting serialCommand_mgsPending to true.

  8. Subsequently, the while loop in serialPreParse() will receive the rest of the message, however you've lost the first byte(s) because they are overwritten by the subsequent bytes.

To fix it, you just need to move the check for serialCommand_msgPending and the re-initialisation code into the while loop:



void serialPreParse()

while (Serial.available())

if (!serialCommand_msgPending)

// NEW incoming message (buffer previously empty)

//reinitialize
serialCommandstr[0] = '';
serialCommand_singleChar = '';
serialCommandindex = 0;
serialCommand_msgPending = true; // if msg received without termination
serialCommand_ready = false; // if terminated msg ready


if (serialCommandindex == INPUT_SIZE)

//maximum size of C string reached
break;

serialCommand_singleChar = Serial.read();
//strcat(serialCommand_singleChar, serialCommandstr);
serialCommandstr[serialCommandindex] = serialCommand_singleChar;
serialCommandindex++;
serialCommandstr[serialCommandindex] = ''; //null-termination

if (serialCommand_singleChar == '>')

//End of single msg.
serialCommand_ready = true;
serialCommand_msgPending = false;
break;




if (serialCommand_ready == true)

if (serialCommandstr[0] != '<')

Serial.println("nIncomplete command!");


Serial.println();
Serial.print("RX:"");
Serial.write(serialCommandstr);
Serial.println(""");











share|improve this answer









$endgroup$












  • $begingroup$
    Thanks for the step by step run-through, even if you saw I caught it before you posted. I'll conjure a fix tomorrow and report back. It was interesting to me at first that this race condition would happen so often, as it's two conditionals right after another, with the first being false/skipped. I thought "Hmm, there are so few executions for serial data to arrive in." but then I realized that it's because I have so little else going on in the loop. My much larger programs would be very unlikely to encounter this, and if they did, it would be ignored as a one-off error.
    $endgroup$
    – Bort
    Jan 24 at 23:29










  • $begingroup$
    When there's no data available you're running in quite a tight loop, so when you think about it, it's not too much of a surprise that a newly received byte might be detected first by either of the Serial.available() calls with a similar probability.
    $endgroup$
    – NMF
    Jan 24 at 23:38










  • $begingroup$
    I'm accepting this answer, as it has a step-by-step and your fix example code makes minimal changes to the original. You will receive your prize in the mail shortly.
    $endgroup$
    – Bort
    Jan 26 at 15:44


















10












$begingroup$

What jumps out to me here is the mark (low signal) levels in your UART signal. Marks should be close to zero, but the oscilloscope output you've included looks like it's only dropping to ~1.6V, especially on the first few characters. This is well above VIL for your microcontroller (0.2×VCC = 1V), so the microcontroller will not reliably interpret it as a logical low.



What hardware are you using to generate UART output from the computer? Make sure it shares a ground with the computer. If this doesn't help, it may be faulty and need to be replaced.






share|improve this answer











$endgroup$








  • 2




    $begingroup$
    I think you may be onto something. The mark levels appear to drop lower over the course of he 4-character message, making the last one more likely to be recognized than the 1st.
    $endgroup$
    – brhans
    Jan 23 at 21:39










  • $begingroup$
    Wow, I erroneously assumed that the signal was reaching near-zero because the logic decoder was right below it! Great catch, but I'm not sure how this can happen. I mentioned that the board is powered through the same USB cable that carries the data because I imagined ground issues would thus be ruled out. I even tried a different USB cable to no avail. What should I do next to isolate the cause?
    $endgroup$
    – Bort
    Jan 24 at 0:20










  • $begingroup$
    You probably have something else shorted to or driving the receive data pin
    $endgroup$
    – Chris Stratton
    Jan 24 at 1:49










  • $begingroup$
    @ChrisStratton - See my Q update. I believe I have isolated this to be a SW issue, as bare modules from different manufactures all give the same result. But how would SW cause this!?
    $endgroup$
    – Bort
    Jan 24 at 14:53



















2












$begingroup$

Lets assume that electrically everything is good and maybe your scope's ground was poorly connected. Can you try this as a test and see if it gives you the result you want ( I don't have an Arduino to test). Basically, it looks like there maybe a race condition in your code between where you are resetting the state of your preparser and where you are actually reading data. You can get into a state where you check if serial data is available in the reset code and its not, then you move on to the reading where there may now be data available.
In this condition the reset code did not execute so your index and other variables are not reset correctly.



This code simplifies the retrieving of the command just for a test so see if the software is the issue. It will call serialGetCommand and block until a '>' char is received. Once it is it will return with what was sent before the '>' in the serialCommandstr buffer which can then be checked. It seems like this is what you were trying to accomplish but I may be wrong.



const int pinBuzzer = A5; // the number of pin for the buzzer

unsigned long T = 0; // "T" value

//max input size expected for a single incoming msg
#define INPUT_SIZE 32
char serialCommandstr[INPUT_SIZE + 1];
byte serialCommandindex = 0; //index of RX buffer for itterating

void setup()

delay(500);
Serial.begin(115200);

// END Setup()


void loop()

Serial.println("Waiting for input in the form of "<XY>"");
Serial.println("X=[A/B], Y=[1~8]");

serialGetCommand();

if (serialCommandstr[1] == 'A')

T = (serialCommandstr[2] - 1) - char('0');
Serial.print("A, ");


Serial.print("T=");
Serial.print(T);
Serial.print("us...");

//Beep to indicate waveform start
tone(pinBuzzer, 1319, 50);
delay(51);



void serialGetCommand()

char serialCommand_singleChar = '';
serialCommandindex = 0;

while(serialCommand_singleChar != '>')

if(Serial.available())

serialCommand_singleChar = Serial.read();
serialCommandstr[serialCommandindex++] = serialCommand_singleChar;



serialCommandstr[serialCommandindex] = '';







share|improve this answer











$endgroup$












  • $begingroup$
    Can you give a quick run-down on the conceptual change of the code you provided, and the output you expect from it?
    $endgroup$
    – Bort
    Jan 24 at 17:58











  • $begingroup$
    Your fix appears to be missing-character-free! However, it's stuck in a loop, not allowing other things to happen. Maybe I can alter that, I'll have to take another look later.
    $endgroup$
    – Bort
    Jan 24 at 21:39







  • 1




    $begingroup$
    As for the race-condition, is it the time between if (Serial.available() && serialCommand_msgPending == false) ... and while (Serial.available()) ... ? If so, I think I understand your explanation to say that the if() could be false because there is no serial available, and then it becomes available and the while() becomes true. Perhaps I can fix that by combining the if() and the while() so that Serial.available() is only tested once per time-slice/loop.
    $endgroup$
    – Bort
    Jan 24 at 21:41










  • $begingroup$
    @Bort - that's it! My answer (that kind of explained what ace8080 was saying but in a different way) is just a few mintues too late.
    $endgroup$
    – NMF
    Jan 24 at 22:00










  • $begingroup$
    Ace, this is a great first post. You should register here at Stackexchange. Just wondering: How did you come across this question?
    $endgroup$
    – Bort
    Jan 24 at 23:31


















1












$begingroup$

Do you have external pull resistors on the RX line (including pulls that might be enabled in the USB to UART chip)? If so make sure you don't have the internal pull resistors enabled in ATMega (Write 0 to the appropriate bit in the appropriate PORT register).






share|improve this answer











$endgroup$












  • $begingroup$
    I tried bare modules and I get the same result.
    $endgroup$
    – Bort
    Jan 24 at 17:59










Your Answer





StackExchange.ifUsing("editor", function ()
return StackExchange.using("mathjaxEditing", function ()
StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix)
StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
);
);
, "mathjax-editing");

StackExchange.ifUsing("editor", function ()
return StackExchange.using("schematics", function ()
StackExchange.schematics.init();
);
, "cicuitlab");

StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "135"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);

else
createEditor();

);

function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);



);













draft saved

draft discarded


















StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2felectronics.stackexchange.com%2fquestions%2f418565%2fuart-sometimes-missing-first-few-characters-on-atmega328p%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown

























4 Answers
4






active

oldest

votes








4 Answers
4






active

oldest

votes









active

oldest

votes






active

oldest

votes









2












$begingroup$

There is a flaw in your handling of your serialCommand_msgPending flag.



Consider the following scenario:



  1. No data has arrived, you call serialPreParse()

  2. serialCommand_msgPending is false

  3. Serial.available() returns 0 in the first line of serialPreParse(), so that block is skipped (so serialCommand_msgPending is still false)

  4. A byte arrives on the serial port

  5. In the while loop, Serial.available() returns 1 (or more, but not a full message), so you read the byte and exit the while loop (no more bytes available) and return from serialPreParse()

  6. serialPreParse() is called again

  7. Serial.available() returns non-zero and serialCommand_msgPending is false, so first block is now executed, re-initialising your buffer and setting serialCommand_mgsPending to true.

  8. Subsequently, the while loop in serialPreParse() will receive the rest of the message, however you've lost the first byte(s) because they are overwritten by the subsequent bytes.

To fix it, you just need to move the check for serialCommand_msgPending and the re-initialisation code into the while loop:



void serialPreParse()

while (Serial.available())

if (!serialCommand_msgPending)

// NEW incoming message (buffer previously empty)

//reinitialize
serialCommandstr[0] = '';
serialCommand_singleChar = '';
serialCommandindex = 0;
serialCommand_msgPending = true; // if msg received without termination
serialCommand_ready = false; // if terminated msg ready


if (serialCommandindex == INPUT_SIZE)

//maximum size of C string reached
break;

serialCommand_singleChar = Serial.read();
//strcat(serialCommand_singleChar, serialCommandstr);
serialCommandstr[serialCommandindex] = serialCommand_singleChar;
serialCommandindex++;
serialCommandstr[serialCommandindex] = ''; //null-termination

if (serialCommand_singleChar == '>')

//End of single msg.
serialCommand_ready = true;
serialCommand_msgPending = false;
break;




if (serialCommand_ready == true)

if (serialCommandstr[0] != '<')

Serial.println("nIncomplete command!");


Serial.println();
Serial.print("RX:"");
Serial.write(serialCommandstr);
Serial.println(""");











share|improve this answer









$endgroup$












  • $begingroup$
    Thanks for the step by step run-through, even if you saw I caught it before you posted. I'll conjure a fix tomorrow and report back. It was interesting to me at first that this race condition would happen so often, as it's two conditionals right after another, with the first being false/skipped. I thought "Hmm, there are so few executions for serial data to arrive in." but then I realized that it's because I have so little else going on in the loop. My much larger programs would be very unlikely to encounter this, and if they did, it would be ignored as a one-off error.
    $endgroup$
    – Bort
    Jan 24 at 23:29










  • $begingroup$
    When there's no data available you're running in quite a tight loop, so when you think about it, it's not too much of a surprise that a newly received byte might be detected first by either of the Serial.available() calls with a similar probability.
    $endgroup$
    – NMF
    Jan 24 at 23:38










  • $begingroup$
    I'm accepting this answer, as it has a step-by-step and your fix example code makes minimal changes to the original. You will receive your prize in the mail shortly.
    $endgroup$
    – Bort
    Jan 26 at 15:44















2












$begingroup$

There is a flaw in your handling of your serialCommand_msgPending flag.



Consider the following scenario:



  1. No data has arrived, you call serialPreParse()

  2. serialCommand_msgPending is false

  3. Serial.available() returns 0 in the first line of serialPreParse(), so that block is skipped (so serialCommand_msgPending is still false)

  4. A byte arrives on the serial port

  5. In the while loop, Serial.available() returns 1 (or more, but not a full message), so you read the byte and exit the while loop (no more bytes available) and return from serialPreParse()

  6. serialPreParse() is called again

  7. Serial.available() returns non-zero and serialCommand_msgPending is false, so first block is now executed, re-initialising your buffer and setting serialCommand_mgsPending to true.

  8. Subsequently, the while loop in serialPreParse() will receive the rest of the message, however you've lost the first byte(s) because they are overwritten by the subsequent bytes.

To fix it, you just need to move the check for serialCommand_msgPending and the re-initialisation code into the while loop:



void serialPreParse()

while (Serial.available())

if (!serialCommand_msgPending)

// NEW incoming message (buffer previously empty)

//reinitialize
serialCommandstr[0] = '';
serialCommand_singleChar = '';
serialCommandindex = 0;
serialCommand_msgPending = true; // if msg received without termination
serialCommand_ready = false; // if terminated msg ready


if (serialCommandindex == INPUT_SIZE)

//maximum size of C string reached
break;

serialCommand_singleChar = Serial.read();
//strcat(serialCommand_singleChar, serialCommandstr);
serialCommandstr[serialCommandindex] = serialCommand_singleChar;
serialCommandindex++;
serialCommandstr[serialCommandindex] = ''; //null-termination

if (serialCommand_singleChar == '>')

//End of single msg.
serialCommand_ready = true;
serialCommand_msgPending = false;
break;




if (serialCommand_ready == true)

if (serialCommandstr[0] != '<')

Serial.println("nIncomplete command!");


Serial.println();
Serial.print("RX:"");
Serial.write(serialCommandstr);
Serial.println(""");











share|improve this answer









$endgroup$












  • $begingroup$
    Thanks for the step by step run-through, even if you saw I caught it before you posted. I'll conjure a fix tomorrow and report back. It was interesting to me at first that this race condition would happen so often, as it's two conditionals right after another, with the first being false/skipped. I thought "Hmm, there are so few executions for serial data to arrive in." but then I realized that it's because I have so little else going on in the loop. My much larger programs would be very unlikely to encounter this, and if they did, it would be ignored as a one-off error.
    $endgroup$
    – Bort
    Jan 24 at 23:29










  • $begingroup$
    When there's no data available you're running in quite a tight loop, so when you think about it, it's not too much of a surprise that a newly received byte might be detected first by either of the Serial.available() calls with a similar probability.
    $endgroup$
    – NMF
    Jan 24 at 23:38










  • $begingroup$
    I'm accepting this answer, as it has a step-by-step and your fix example code makes minimal changes to the original. You will receive your prize in the mail shortly.
    $endgroup$
    – Bort
    Jan 26 at 15:44













2












2








2





$begingroup$

There is a flaw in your handling of your serialCommand_msgPending flag.



Consider the following scenario:



  1. No data has arrived, you call serialPreParse()

  2. serialCommand_msgPending is false

  3. Serial.available() returns 0 in the first line of serialPreParse(), so that block is skipped (so serialCommand_msgPending is still false)

  4. A byte arrives on the serial port

  5. In the while loop, Serial.available() returns 1 (or more, but not a full message), so you read the byte and exit the while loop (no more bytes available) and return from serialPreParse()

  6. serialPreParse() is called again

  7. Serial.available() returns non-zero and serialCommand_msgPending is false, so first block is now executed, re-initialising your buffer and setting serialCommand_mgsPending to true.

  8. Subsequently, the while loop in serialPreParse() will receive the rest of the message, however you've lost the first byte(s) because they are overwritten by the subsequent bytes.

To fix it, you just need to move the check for serialCommand_msgPending and the re-initialisation code into the while loop:



void serialPreParse()

while (Serial.available())

if (!serialCommand_msgPending)

// NEW incoming message (buffer previously empty)

//reinitialize
serialCommandstr[0] = '';
serialCommand_singleChar = '';
serialCommandindex = 0;
serialCommand_msgPending = true; // if msg received without termination
serialCommand_ready = false; // if terminated msg ready


if (serialCommandindex == INPUT_SIZE)

//maximum size of C string reached
break;

serialCommand_singleChar = Serial.read();
//strcat(serialCommand_singleChar, serialCommandstr);
serialCommandstr[serialCommandindex] = serialCommand_singleChar;
serialCommandindex++;
serialCommandstr[serialCommandindex] = ''; //null-termination

if (serialCommand_singleChar == '>')

//End of single msg.
serialCommand_ready = true;
serialCommand_msgPending = false;
break;




if (serialCommand_ready == true)

if (serialCommandstr[0] != '<')

Serial.println("nIncomplete command!");


Serial.println();
Serial.print("RX:"");
Serial.write(serialCommandstr);
Serial.println(""");











share|improve this answer









$endgroup$



There is a flaw in your handling of your serialCommand_msgPending flag.



Consider the following scenario:



  1. No data has arrived, you call serialPreParse()

  2. serialCommand_msgPending is false

  3. Serial.available() returns 0 in the first line of serialPreParse(), so that block is skipped (so serialCommand_msgPending is still false)

  4. A byte arrives on the serial port

  5. In the while loop, Serial.available() returns 1 (or more, but not a full message), so you read the byte and exit the while loop (no more bytes available) and return from serialPreParse()

  6. serialPreParse() is called again

  7. Serial.available() returns non-zero and serialCommand_msgPending is false, so first block is now executed, re-initialising your buffer and setting serialCommand_mgsPending to true.

  8. Subsequently, the while loop in serialPreParse() will receive the rest of the message, however you've lost the first byte(s) because they are overwritten by the subsequent bytes.

To fix it, you just need to move the check for serialCommand_msgPending and the re-initialisation code into the while loop:



void serialPreParse()

while (Serial.available())

if (!serialCommand_msgPending)

// NEW incoming message (buffer previously empty)

//reinitialize
serialCommandstr[0] = '';
serialCommand_singleChar = '';
serialCommandindex = 0;
serialCommand_msgPending = true; // if msg received without termination
serialCommand_ready = false; // if terminated msg ready


if (serialCommandindex == INPUT_SIZE)

//maximum size of C string reached
break;

serialCommand_singleChar = Serial.read();
//strcat(serialCommand_singleChar, serialCommandstr);
serialCommandstr[serialCommandindex] = serialCommand_singleChar;
serialCommandindex++;
serialCommandstr[serialCommandindex] = ''; //null-termination

if (serialCommand_singleChar == '>')

//End of single msg.
serialCommand_ready = true;
serialCommand_msgPending = false;
break;




if (serialCommand_ready == true)

if (serialCommandstr[0] != '<')

Serial.println("nIncomplete command!");


Serial.println();
Serial.print("RX:"");
Serial.write(serialCommandstr);
Serial.println(""");












share|improve this answer












share|improve this answer



share|improve this answer










answered Jan 24 at 21:58









NMFNMF

9113




9113











  • $begingroup$
    Thanks for the step by step run-through, even if you saw I caught it before you posted. I'll conjure a fix tomorrow and report back. It was interesting to me at first that this race condition would happen so often, as it's two conditionals right after another, with the first being false/skipped. I thought "Hmm, there are so few executions for serial data to arrive in." but then I realized that it's because I have so little else going on in the loop. My much larger programs would be very unlikely to encounter this, and if they did, it would be ignored as a one-off error.
    $endgroup$
    – Bort
    Jan 24 at 23:29










  • $begingroup$
    When there's no data available you're running in quite a tight loop, so when you think about it, it's not too much of a surprise that a newly received byte might be detected first by either of the Serial.available() calls with a similar probability.
    $endgroup$
    – NMF
    Jan 24 at 23:38










  • $begingroup$
    I'm accepting this answer, as it has a step-by-step and your fix example code makes minimal changes to the original. You will receive your prize in the mail shortly.
    $endgroup$
    – Bort
    Jan 26 at 15:44
















  • $begingroup$
    Thanks for the step by step run-through, even if you saw I caught it before you posted. I'll conjure a fix tomorrow and report back. It was interesting to me at first that this race condition would happen so often, as it's two conditionals right after another, with the first being false/skipped. I thought "Hmm, there are so few executions for serial data to arrive in." but then I realized that it's because I have so little else going on in the loop. My much larger programs would be very unlikely to encounter this, and if they did, it would be ignored as a one-off error.
    $endgroup$
    – Bort
    Jan 24 at 23:29










  • $begingroup$
    When there's no data available you're running in quite a tight loop, so when you think about it, it's not too much of a surprise that a newly received byte might be detected first by either of the Serial.available() calls with a similar probability.
    $endgroup$
    – NMF
    Jan 24 at 23:38










  • $begingroup$
    I'm accepting this answer, as it has a step-by-step and your fix example code makes minimal changes to the original. You will receive your prize in the mail shortly.
    $endgroup$
    – Bort
    Jan 26 at 15:44















$begingroup$
Thanks for the step by step run-through, even if you saw I caught it before you posted. I'll conjure a fix tomorrow and report back. It was interesting to me at first that this race condition would happen so often, as it's two conditionals right after another, with the first being false/skipped. I thought "Hmm, there are so few executions for serial data to arrive in." but then I realized that it's because I have so little else going on in the loop. My much larger programs would be very unlikely to encounter this, and if they did, it would be ignored as a one-off error.
$endgroup$
– Bort
Jan 24 at 23:29




$begingroup$
Thanks for the step by step run-through, even if you saw I caught it before you posted. I'll conjure a fix tomorrow and report back. It was interesting to me at first that this race condition would happen so often, as it's two conditionals right after another, with the first being false/skipped. I thought "Hmm, there are so few executions for serial data to arrive in." but then I realized that it's because I have so little else going on in the loop. My much larger programs would be very unlikely to encounter this, and if they did, it would be ignored as a one-off error.
$endgroup$
– Bort
Jan 24 at 23:29












$begingroup$
When there's no data available you're running in quite a tight loop, so when you think about it, it's not too much of a surprise that a newly received byte might be detected first by either of the Serial.available() calls with a similar probability.
$endgroup$
– NMF
Jan 24 at 23:38




$begingroup$
When there's no data available you're running in quite a tight loop, so when you think about it, it's not too much of a surprise that a newly received byte might be detected first by either of the Serial.available() calls with a similar probability.
$endgroup$
– NMF
Jan 24 at 23:38












$begingroup$
I'm accepting this answer, as it has a step-by-step and your fix example code makes minimal changes to the original. You will receive your prize in the mail shortly.
$endgroup$
– Bort
Jan 26 at 15:44




$begingroup$
I'm accepting this answer, as it has a step-by-step and your fix example code makes minimal changes to the original. You will receive your prize in the mail shortly.
$endgroup$
– Bort
Jan 26 at 15:44













10












$begingroup$

What jumps out to me here is the mark (low signal) levels in your UART signal. Marks should be close to zero, but the oscilloscope output you've included looks like it's only dropping to ~1.6V, especially on the first few characters. This is well above VIL for your microcontroller (0.2×VCC = 1V), so the microcontroller will not reliably interpret it as a logical low.



What hardware are you using to generate UART output from the computer? Make sure it shares a ground with the computer. If this doesn't help, it may be faulty and need to be replaced.






share|improve this answer











$endgroup$








  • 2




    $begingroup$
    I think you may be onto something. The mark levels appear to drop lower over the course of he 4-character message, making the last one more likely to be recognized than the 1st.
    $endgroup$
    – brhans
    Jan 23 at 21:39










  • $begingroup$
    Wow, I erroneously assumed that the signal was reaching near-zero because the logic decoder was right below it! Great catch, but I'm not sure how this can happen. I mentioned that the board is powered through the same USB cable that carries the data because I imagined ground issues would thus be ruled out. I even tried a different USB cable to no avail. What should I do next to isolate the cause?
    $endgroup$
    – Bort
    Jan 24 at 0:20










  • $begingroup$
    You probably have something else shorted to or driving the receive data pin
    $endgroup$
    – Chris Stratton
    Jan 24 at 1:49










  • $begingroup$
    @ChrisStratton - See my Q update. I believe I have isolated this to be a SW issue, as bare modules from different manufactures all give the same result. But how would SW cause this!?
    $endgroup$
    – Bort
    Jan 24 at 14:53
















10












$begingroup$

What jumps out to me here is the mark (low signal) levels in your UART signal. Marks should be close to zero, but the oscilloscope output you've included looks like it's only dropping to ~1.6V, especially on the first few characters. This is well above VIL for your microcontroller (0.2×VCC = 1V), so the microcontroller will not reliably interpret it as a logical low.



What hardware are you using to generate UART output from the computer? Make sure it shares a ground with the computer. If this doesn't help, it may be faulty and need to be replaced.






share|improve this answer











$endgroup$








  • 2




    $begingroup$
    I think you may be onto something. The mark levels appear to drop lower over the course of he 4-character message, making the last one more likely to be recognized than the 1st.
    $endgroup$
    – brhans
    Jan 23 at 21:39










  • $begingroup$
    Wow, I erroneously assumed that the signal was reaching near-zero because the logic decoder was right below it! Great catch, but I'm not sure how this can happen. I mentioned that the board is powered through the same USB cable that carries the data because I imagined ground issues would thus be ruled out. I even tried a different USB cable to no avail. What should I do next to isolate the cause?
    $endgroup$
    – Bort
    Jan 24 at 0:20










  • $begingroup$
    You probably have something else shorted to or driving the receive data pin
    $endgroup$
    – Chris Stratton
    Jan 24 at 1:49










  • $begingroup$
    @ChrisStratton - See my Q update. I believe I have isolated this to be a SW issue, as bare modules from different manufactures all give the same result. But how would SW cause this!?
    $endgroup$
    – Bort
    Jan 24 at 14:53














10












10








10





$begingroup$

What jumps out to me here is the mark (low signal) levels in your UART signal. Marks should be close to zero, but the oscilloscope output you've included looks like it's only dropping to ~1.6V, especially on the first few characters. This is well above VIL for your microcontroller (0.2×VCC = 1V), so the microcontroller will not reliably interpret it as a logical low.



What hardware are you using to generate UART output from the computer? Make sure it shares a ground with the computer. If this doesn't help, it may be faulty and need to be replaced.






share|improve this answer











$endgroup$



What jumps out to me here is the mark (low signal) levels in your UART signal. Marks should be close to zero, but the oscilloscope output you've included looks like it's only dropping to ~1.6V, especially on the first few characters. This is well above VIL for your microcontroller (0.2×VCC = 1V), so the microcontroller will not reliably interpret it as a logical low.



What hardware are you using to generate UART output from the computer? Make sure it shares a ground with the computer. If this doesn't help, it may be faulty and need to be replaced.







share|improve this answer














share|improve this answer



share|improve this answer








edited Jan 23 at 23:26

























answered Jan 23 at 21:16









duskwuffduskwuff

17.2k32651




17.2k32651







  • 2




    $begingroup$
    I think you may be onto something. The mark levels appear to drop lower over the course of he 4-character message, making the last one more likely to be recognized than the 1st.
    $endgroup$
    – brhans
    Jan 23 at 21:39










  • $begingroup$
    Wow, I erroneously assumed that the signal was reaching near-zero because the logic decoder was right below it! Great catch, but I'm not sure how this can happen. I mentioned that the board is powered through the same USB cable that carries the data because I imagined ground issues would thus be ruled out. I even tried a different USB cable to no avail. What should I do next to isolate the cause?
    $endgroup$
    – Bort
    Jan 24 at 0:20










  • $begingroup$
    You probably have something else shorted to or driving the receive data pin
    $endgroup$
    – Chris Stratton
    Jan 24 at 1:49










  • $begingroup$
    @ChrisStratton - See my Q update. I believe I have isolated this to be a SW issue, as bare modules from different manufactures all give the same result. But how would SW cause this!?
    $endgroup$
    – Bort
    Jan 24 at 14:53













  • 2




    $begingroup$
    I think you may be onto something. The mark levels appear to drop lower over the course of he 4-character message, making the last one more likely to be recognized than the 1st.
    $endgroup$
    – brhans
    Jan 23 at 21:39










  • $begingroup$
    Wow, I erroneously assumed that the signal was reaching near-zero because the logic decoder was right below it! Great catch, but I'm not sure how this can happen. I mentioned that the board is powered through the same USB cable that carries the data because I imagined ground issues would thus be ruled out. I even tried a different USB cable to no avail. What should I do next to isolate the cause?
    $endgroup$
    – Bort
    Jan 24 at 0:20










  • $begingroup$
    You probably have something else shorted to or driving the receive data pin
    $endgroup$
    – Chris Stratton
    Jan 24 at 1:49










  • $begingroup$
    @ChrisStratton - See my Q update. I believe I have isolated this to be a SW issue, as bare modules from different manufactures all give the same result. But how would SW cause this!?
    $endgroup$
    – Bort
    Jan 24 at 14:53








2




2




$begingroup$
I think you may be onto something. The mark levels appear to drop lower over the course of he 4-character message, making the last one more likely to be recognized than the 1st.
$endgroup$
– brhans
Jan 23 at 21:39




$begingroup$
I think you may be onto something. The mark levels appear to drop lower over the course of he 4-character message, making the last one more likely to be recognized than the 1st.
$endgroup$
– brhans
Jan 23 at 21:39












$begingroup$
Wow, I erroneously assumed that the signal was reaching near-zero because the logic decoder was right below it! Great catch, but I'm not sure how this can happen. I mentioned that the board is powered through the same USB cable that carries the data because I imagined ground issues would thus be ruled out. I even tried a different USB cable to no avail. What should I do next to isolate the cause?
$endgroup$
– Bort
Jan 24 at 0:20




$begingroup$
Wow, I erroneously assumed that the signal was reaching near-zero because the logic decoder was right below it! Great catch, but I'm not sure how this can happen. I mentioned that the board is powered through the same USB cable that carries the data because I imagined ground issues would thus be ruled out. I even tried a different USB cable to no avail. What should I do next to isolate the cause?
$endgroup$
– Bort
Jan 24 at 0:20












$begingroup$
You probably have something else shorted to or driving the receive data pin
$endgroup$
– Chris Stratton
Jan 24 at 1:49




$begingroup$
You probably have something else shorted to or driving the receive data pin
$endgroup$
– Chris Stratton
Jan 24 at 1:49












$begingroup$
@ChrisStratton - See my Q update. I believe I have isolated this to be a SW issue, as bare modules from different manufactures all give the same result. But how would SW cause this!?
$endgroup$
– Bort
Jan 24 at 14:53





$begingroup$
@ChrisStratton - See my Q update. I believe I have isolated this to be a SW issue, as bare modules from different manufactures all give the same result. But how would SW cause this!?
$endgroup$
– Bort
Jan 24 at 14:53












2












$begingroup$

Lets assume that electrically everything is good and maybe your scope's ground was poorly connected. Can you try this as a test and see if it gives you the result you want ( I don't have an Arduino to test). Basically, it looks like there maybe a race condition in your code between where you are resetting the state of your preparser and where you are actually reading data. You can get into a state where you check if serial data is available in the reset code and its not, then you move on to the reading where there may now be data available.
In this condition the reset code did not execute so your index and other variables are not reset correctly.



This code simplifies the retrieving of the command just for a test so see if the software is the issue. It will call serialGetCommand and block until a '>' char is received. Once it is it will return with what was sent before the '>' in the serialCommandstr buffer which can then be checked. It seems like this is what you were trying to accomplish but I may be wrong.



const int pinBuzzer = A5; // the number of pin for the buzzer

unsigned long T = 0; // "T" value

//max input size expected for a single incoming msg
#define INPUT_SIZE 32
char serialCommandstr[INPUT_SIZE + 1];
byte serialCommandindex = 0; //index of RX buffer for itterating

void setup()

delay(500);
Serial.begin(115200);

// END Setup()


void loop()

Serial.println("Waiting for input in the form of "<XY>"");
Serial.println("X=[A/B], Y=[1~8]");

serialGetCommand();

if (serialCommandstr[1] == 'A')

T = (serialCommandstr[2] - 1) - char('0');
Serial.print("A, ");


Serial.print("T=");
Serial.print(T);
Serial.print("us...");

//Beep to indicate waveform start
tone(pinBuzzer, 1319, 50);
delay(51);



void serialGetCommand()

char serialCommand_singleChar = '';
serialCommandindex = 0;

while(serialCommand_singleChar != '>')

if(Serial.available())

serialCommand_singleChar = Serial.read();
serialCommandstr[serialCommandindex++] = serialCommand_singleChar;



serialCommandstr[serialCommandindex] = '';







share|improve this answer











$endgroup$












  • $begingroup$
    Can you give a quick run-down on the conceptual change of the code you provided, and the output you expect from it?
    $endgroup$
    – Bort
    Jan 24 at 17:58











  • $begingroup$
    Your fix appears to be missing-character-free! However, it's stuck in a loop, not allowing other things to happen. Maybe I can alter that, I'll have to take another look later.
    $endgroup$
    – Bort
    Jan 24 at 21:39







  • 1




    $begingroup$
    As for the race-condition, is it the time between if (Serial.available() && serialCommand_msgPending == false) ... and while (Serial.available()) ... ? If so, I think I understand your explanation to say that the if() could be false because there is no serial available, and then it becomes available and the while() becomes true. Perhaps I can fix that by combining the if() and the while() so that Serial.available() is only tested once per time-slice/loop.
    $endgroup$
    – Bort
    Jan 24 at 21:41










  • $begingroup$
    @Bort - that's it! My answer (that kind of explained what ace8080 was saying but in a different way) is just a few mintues too late.
    $endgroup$
    – NMF
    Jan 24 at 22:00










  • $begingroup$
    Ace, this is a great first post. You should register here at Stackexchange. Just wondering: How did you come across this question?
    $endgroup$
    – Bort
    Jan 24 at 23:31















2












$begingroup$

Lets assume that electrically everything is good and maybe your scope's ground was poorly connected. Can you try this as a test and see if it gives you the result you want ( I don't have an Arduino to test). Basically, it looks like there maybe a race condition in your code between where you are resetting the state of your preparser and where you are actually reading data. You can get into a state where you check if serial data is available in the reset code and its not, then you move on to the reading where there may now be data available.
In this condition the reset code did not execute so your index and other variables are not reset correctly.



This code simplifies the retrieving of the command just for a test so see if the software is the issue. It will call serialGetCommand and block until a '>' char is received. Once it is it will return with what was sent before the '>' in the serialCommandstr buffer which can then be checked. It seems like this is what you were trying to accomplish but I may be wrong.



const int pinBuzzer = A5; // the number of pin for the buzzer

unsigned long T = 0; // "T" value

//max input size expected for a single incoming msg
#define INPUT_SIZE 32
char serialCommandstr[INPUT_SIZE + 1];
byte serialCommandindex = 0; //index of RX buffer for itterating

void setup()

delay(500);
Serial.begin(115200);

// END Setup()


void loop()

Serial.println("Waiting for input in the form of "<XY>"");
Serial.println("X=[A/B], Y=[1~8]");

serialGetCommand();

if (serialCommandstr[1] == 'A')

T = (serialCommandstr[2] - 1) - char('0');
Serial.print("A, ");


Serial.print("T=");
Serial.print(T);
Serial.print("us...");

//Beep to indicate waveform start
tone(pinBuzzer, 1319, 50);
delay(51);



void serialGetCommand()

char serialCommand_singleChar = '';
serialCommandindex = 0;

while(serialCommand_singleChar != '>')

if(Serial.available())

serialCommand_singleChar = Serial.read();
serialCommandstr[serialCommandindex++] = serialCommand_singleChar;



serialCommandstr[serialCommandindex] = '';







share|improve this answer











$endgroup$












  • $begingroup$
    Can you give a quick run-down on the conceptual change of the code you provided, and the output you expect from it?
    $endgroup$
    – Bort
    Jan 24 at 17:58











  • $begingroup$
    Your fix appears to be missing-character-free! However, it's stuck in a loop, not allowing other things to happen. Maybe I can alter that, I'll have to take another look later.
    $endgroup$
    – Bort
    Jan 24 at 21:39







  • 1




    $begingroup$
    As for the race-condition, is it the time between if (Serial.available() && serialCommand_msgPending == false) ... and while (Serial.available()) ... ? If so, I think I understand your explanation to say that the if() could be false because there is no serial available, and then it becomes available and the while() becomes true. Perhaps I can fix that by combining the if() and the while() so that Serial.available() is only tested once per time-slice/loop.
    $endgroup$
    – Bort
    Jan 24 at 21:41










  • $begingroup$
    @Bort - that's it! My answer (that kind of explained what ace8080 was saying but in a different way) is just a few mintues too late.
    $endgroup$
    – NMF
    Jan 24 at 22:00










  • $begingroup$
    Ace, this is a great first post. You should register here at Stackexchange. Just wondering: How did you come across this question?
    $endgroup$
    – Bort
    Jan 24 at 23:31













2












2








2





$begingroup$

Lets assume that electrically everything is good and maybe your scope's ground was poorly connected. Can you try this as a test and see if it gives you the result you want ( I don't have an Arduino to test). Basically, it looks like there maybe a race condition in your code between where you are resetting the state of your preparser and where you are actually reading data. You can get into a state where you check if serial data is available in the reset code and its not, then you move on to the reading where there may now be data available.
In this condition the reset code did not execute so your index and other variables are not reset correctly.



This code simplifies the retrieving of the command just for a test so see if the software is the issue. It will call serialGetCommand and block until a '>' char is received. Once it is it will return with what was sent before the '>' in the serialCommandstr buffer which can then be checked. It seems like this is what you were trying to accomplish but I may be wrong.



const int pinBuzzer = A5; // the number of pin for the buzzer

unsigned long T = 0; // "T" value

//max input size expected for a single incoming msg
#define INPUT_SIZE 32
char serialCommandstr[INPUT_SIZE + 1];
byte serialCommandindex = 0; //index of RX buffer for itterating

void setup()

delay(500);
Serial.begin(115200);

// END Setup()


void loop()

Serial.println("Waiting for input in the form of "<XY>"");
Serial.println("X=[A/B], Y=[1~8]");

serialGetCommand();

if (serialCommandstr[1] == 'A')

T = (serialCommandstr[2] - 1) - char('0');
Serial.print("A, ");


Serial.print("T=");
Serial.print(T);
Serial.print("us...");

//Beep to indicate waveform start
tone(pinBuzzer, 1319, 50);
delay(51);



void serialGetCommand()

char serialCommand_singleChar = '';
serialCommandindex = 0;

while(serialCommand_singleChar != '>')

if(Serial.available())

serialCommand_singleChar = Serial.read();
serialCommandstr[serialCommandindex++] = serialCommand_singleChar;



serialCommandstr[serialCommandindex] = '';







share|improve this answer











$endgroup$



Lets assume that electrically everything is good and maybe your scope's ground was poorly connected. Can you try this as a test and see if it gives you the result you want ( I don't have an Arduino to test). Basically, it looks like there maybe a race condition in your code between where you are resetting the state of your preparser and where you are actually reading data. You can get into a state where you check if serial data is available in the reset code and its not, then you move on to the reading where there may now be data available.
In this condition the reset code did not execute so your index and other variables are not reset correctly.



This code simplifies the retrieving of the command just for a test so see if the software is the issue. It will call serialGetCommand and block until a '>' char is received. Once it is it will return with what was sent before the '>' in the serialCommandstr buffer which can then be checked. It seems like this is what you were trying to accomplish but I may be wrong.



const int pinBuzzer = A5; // the number of pin for the buzzer

unsigned long T = 0; // "T" value

//max input size expected for a single incoming msg
#define INPUT_SIZE 32
char serialCommandstr[INPUT_SIZE + 1];
byte serialCommandindex = 0; //index of RX buffer for itterating

void setup()

delay(500);
Serial.begin(115200);

// END Setup()


void loop()

Serial.println("Waiting for input in the form of "<XY>"");
Serial.println("X=[A/B], Y=[1~8]");

serialGetCommand();

if (serialCommandstr[1] == 'A')

T = (serialCommandstr[2] - 1) - char('0');
Serial.print("A, ");


Serial.print("T=");
Serial.print(T);
Serial.print("us...");

//Beep to indicate waveform start
tone(pinBuzzer, 1319, 50);
delay(51);



void serialGetCommand()

char serialCommand_singleChar = '';
serialCommandindex = 0;

while(serialCommand_singleChar != '>')

if(Serial.available())

serialCommand_singleChar = Serial.read();
serialCommandstr[serialCommandindex++] = serialCommand_singleChar;



serialCommandstr[serialCommandindex] = '';








share|improve this answer














share|improve this answer



share|improve this answer








edited Jan 24 at 19:17

























answered Jan 24 at 16:53









ace8080ace8080

212




212











  • $begingroup$
    Can you give a quick run-down on the conceptual change of the code you provided, and the output you expect from it?
    $endgroup$
    – Bort
    Jan 24 at 17:58











  • $begingroup$
    Your fix appears to be missing-character-free! However, it's stuck in a loop, not allowing other things to happen. Maybe I can alter that, I'll have to take another look later.
    $endgroup$
    – Bort
    Jan 24 at 21:39







  • 1




    $begingroup$
    As for the race-condition, is it the time between if (Serial.available() && serialCommand_msgPending == false) ... and while (Serial.available()) ... ? If so, I think I understand your explanation to say that the if() could be false because there is no serial available, and then it becomes available and the while() becomes true. Perhaps I can fix that by combining the if() and the while() so that Serial.available() is only tested once per time-slice/loop.
    $endgroup$
    – Bort
    Jan 24 at 21:41










  • $begingroup$
    @Bort - that's it! My answer (that kind of explained what ace8080 was saying but in a different way) is just a few mintues too late.
    $endgroup$
    – NMF
    Jan 24 at 22:00










  • $begingroup$
    Ace, this is a great first post. You should register here at Stackexchange. Just wondering: How did you come across this question?
    $endgroup$
    – Bort
    Jan 24 at 23:31
















  • $begingroup$
    Can you give a quick run-down on the conceptual change of the code you provided, and the output you expect from it?
    $endgroup$
    – Bort
    Jan 24 at 17:58











  • $begingroup$
    Your fix appears to be missing-character-free! However, it's stuck in a loop, not allowing other things to happen. Maybe I can alter that, I'll have to take another look later.
    $endgroup$
    – Bort
    Jan 24 at 21:39







  • 1




    $begingroup$
    As for the race-condition, is it the time between if (Serial.available() && serialCommand_msgPending == false) ... and while (Serial.available()) ... ? If so, I think I understand your explanation to say that the if() could be false because there is no serial available, and then it becomes available and the while() becomes true. Perhaps I can fix that by combining the if() and the while() so that Serial.available() is only tested once per time-slice/loop.
    $endgroup$
    – Bort
    Jan 24 at 21:41










  • $begingroup$
    @Bort - that's it! My answer (that kind of explained what ace8080 was saying but in a different way) is just a few mintues too late.
    $endgroup$
    – NMF
    Jan 24 at 22:00










  • $begingroup$
    Ace, this is a great first post. You should register here at Stackexchange. Just wondering: How did you come across this question?
    $endgroup$
    – Bort
    Jan 24 at 23:31















$begingroup$
Can you give a quick run-down on the conceptual change of the code you provided, and the output you expect from it?
$endgroup$
– Bort
Jan 24 at 17:58





$begingroup$
Can you give a quick run-down on the conceptual change of the code you provided, and the output you expect from it?
$endgroup$
– Bort
Jan 24 at 17:58













$begingroup$
Your fix appears to be missing-character-free! However, it's stuck in a loop, not allowing other things to happen. Maybe I can alter that, I'll have to take another look later.
$endgroup$
– Bort
Jan 24 at 21:39





$begingroup$
Your fix appears to be missing-character-free! However, it's stuck in a loop, not allowing other things to happen. Maybe I can alter that, I'll have to take another look later.
$endgroup$
– Bort
Jan 24 at 21:39





1




1




$begingroup$
As for the race-condition, is it the time between if (Serial.available() && serialCommand_msgPending == false) ... and while (Serial.available()) ... ? If so, I think I understand your explanation to say that the if() could be false because there is no serial available, and then it becomes available and the while() becomes true. Perhaps I can fix that by combining the if() and the while() so that Serial.available() is only tested once per time-slice/loop.
$endgroup$
– Bort
Jan 24 at 21:41




$begingroup$
As for the race-condition, is it the time between if (Serial.available() && serialCommand_msgPending == false) ... and while (Serial.available()) ... ? If so, I think I understand your explanation to say that the if() could be false because there is no serial available, and then it becomes available and the while() becomes true. Perhaps I can fix that by combining the if() and the while() so that Serial.available() is only tested once per time-slice/loop.
$endgroup$
– Bort
Jan 24 at 21:41












$begingroup$
@Bort - that's it! My answer (that kind of explained what ace8080 was saying but in a different way) is just a few mintues too late.
$endgroup$
– NMF
Jan 24 at 22:00




$begingroup$
@Bort - that's it! My answer (that kind of explained what ace8080 was saying but in a different way) is just a few mintues too late.
$endgroup$
– NMF
Jan 24 at 22:00












$begingroup$
Ace, this is a great first post. You should register here at Stackexchange. Just wondering: How did you come across this question?
$endgroup$
– Bort
Jan 24 at 23:31




$begingroup$
Ace, this is a great first post. You should register here at Stackexchange. Just wondering: How did you come across this question?
$endgroup$
– Bort
Jan 24 at 23:31











1












$begingroup$

Do you have external pull resistors on the RX line (including pulls that might be enabled in the USB to UART chip)? If so make sure you don't have the internal pull resistors enabled in ATMega (Write 0 to the appropriate bit in the appropriate PORT register).






share|improve this answer











$endgroup$












  • $begingroup$
    I tried bare modules and I get the same result.
    $endgroup$
    – Bort
    Jan 24 at 17:59















1












$begingroup$

Do you have external pull resistors on the RX line (including pulls that might be enabled in the USB to UART chip)? If so make sure you don't have the internal pull resistors enabled in ATMega (Write 0 to the appropriate bit in the appropriate PORT register).






share|improve this answer











$endgroup$












  • $begingroup$
    I tried bare modules and I get the same result.
    $endgroup$
    – Bort
    Jan 24 at 17:59













1












1








1





$begingroup$

Do you have external pull resistors on the RX line (including pulls that might be enabled in the USB to UART chip)? If so make sure you don't have the internal pull resistors enabled in ATMega (Write 0 to the appropriate bit in the appropriate PORT register).






share|improve this answer











$endgroup$



Do you have external pull resistors on the RX line (including pulls that might be enabled in the USB to UART chip)? If so make sure you don't have the internal pull resistors enabled in ATMega (Write 0 to the appropriate bit in the appropriate PORT register).







share|improve this answer














share|improve this answer



share|improve this answer








edited Jan 24 at 21:09









Josh H

31




31










answered Jan 24 at 13:12









Josh H.Josh H.

111




111











  • $begingroup$
    I tried bare modules and I get the same result.
    $endgroup$
    – Bort
    Jan 24 at 17:59
















  • $begingroup$
    I tried bare modules and I get the same result.
    $endgroup$
    – Bort
    Jan 24 at 17:59















$begingroup$
I tried bare modules and I get the same result.
$endgroup$
– Bort
Jan 24 at 17:59




$begingroup$
I tried bare modules and I get the same result.
$endgroup$
– Bort
Jan 24 at 17:59

















draft saved

draft discarded
















































Thanks for contributing an answer to Electrical Engineering Stack Exchange!


  • Please be sure to answer the question. Provide details and share your research!

But avoid


  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.

Use MathJax to format equations. MathJax reference.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2felectronics.stackexchange.com%2fquestions%2f418565%2fuart-sometimes-missing-first-few-characters-on-atmega328p%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown






Popular posts from this blog

Peggy Mitchell

Palaiologos

The Forum (Inglewood, California)