IDE Serial Monitor Send repeats previous data though not currently entered

If I use the Serial Monitor to send a 7-character string to the Arduino Uno, and then a single character string, the Ser Mon actually sends the new single character plus the other 6 characters from the previous send. This persists through a succession of single character sends; all contain the extra characters from the longer first string. (Aside: I've noticed that other terminal emulators [Bray Terminal, Hyperterminal] also do this. Very peculiar!!) It's as if the Ser Mon send/transmit buffer never gets cleared, only overwritten.

Is there a setting in the IDE (or some other way) to make the Ser Mon stop this action, i.e., each new Send only sends what is currently typed in the data-to-be-sent field? Thanks.

Mick H.
28 Apr 17
2:25 PM PDT

?

It sounds like you are not resetting a variable in your code before processing the next input string, but without seeing your code who but you can tell ?

AWOL - sorry, I don't understand the meaning of the above "?" Is it that you don't understand what I am asking? My question is about using the Ser Mon. Thanks for the reply.

UKHeliBob- thanks for your reply. The problem has nothing to do with my code, it's entirely in the IDE and the Ser Mon. I just want to know if there are any settings or usage details in the Ser Mon that would affect what is sent out COM1 by the Ser Mon. If a longer string is sent out by Ser Mon, and then a short string, the ending data of the previous long string is resent even though not entered along with the short string. Example:

Send S123456 this is sent fine, Arduino receives this
Then send upper case D only Arduino actually receives D123456 from Ser Mon

I need Ser Mon to only send D in the second case above. Hope this is more clear.

Appreciate the help.

Mick H
28 Apr 17
3:52 PM PDT USA

I took example two of Serial Input Basics - updated and this is the output (line ending in serial monitor set to newline) after sending both strings that you provided

<Arduino is ready>
This just in ... S123456
This just in ... D

So I do suspect that it has everything to do with your code. And as UKHeliBob indicated, you more-than-likely do not clear your receive buffer or you don’t specifically add a nul terminator. To prove us wrong, show your code.

Hi,

Send S123456 this is sent fine, Arduino receives this
Then send upper case D only Arduino actually receives D123456 from Ser Mon

How do you know the Arduino receives D123456?
If you are displaying this on an LCD display, then your code is receiving the D, just you have not cleared the LCD before over writing the LCD location.

The 123456 is what is left over on your display from S123456 when you display D.
That is if you are using an LCD display.

I could be wrong.

Please read the first post in any forum entitled how to use this forum.
http://forum.arduino.cc/index.php/topic,148850.0.html then look down to item #7 about how to post your code.

Thanks.. Tom... :slight_smile:

Thanks much for all the replies. My great apology for appearing egotistical and pompous; I surely don’t know for certain where the problem is.

The code for this project is shown below:

// Sketch clock_mhh7<ver> - program to operate settable 4-digit clock with easy DST/PST conversion
// Template by Tony DiCola for Adafruit Industries.
// MHH 19 Apr 17

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <RTClib.h>
#include "Adafruit_LEDBackpack.h"

boolean stringComplete = false; // Test variable for whether input string is complete
bool setClockTime = false; // 

// Set to false to display time in 12 hour format, or true to use 24 hour:
#define TIME_24_HOUR      false

// I2C address of the display.  Stick with the default address of 0x70
// unless you've changed the address jumpers on the back of the display.
#define DISPLAY_ADDRESS   0x70


// Create display and DS3231 objects.  These are global variables that
// can be accessed from both the setup and loop function below.
Adafruit_7segment clockDisplay = Adafruit_7segment(); // Declared in Adafruit_LEDBackpack .h & .cpp
RTC_DS3231 rtc = RTC_DS3231();

// Variables for date and time values
int Y;
int M;
int D;
int Hrs;
int Mins;
int Secs;

// Variables to hold input characters and/or strings
char inBuf[64];
char input;
char action;
char Sub1;
char Sub2;
char Sub3;

// Remember if the colon was drawn on the display so it can be blinked
// on and off every second.
bool blinkColon = false;

void setup() {
  // Setup function runs once at startup to initialize the display
  // and DS3231 clock.

  // Setup Serial port to print debug output.
  Serial.begin(115200);
  Serial.println("Clock starting!");

  // Setup the display.
  clockDisplay.begin(DISPLAY_ADDRESS);

  // Setup the DS3231 real-time clock.
  rtc.begin();
//  rtc.adjust(DateTime(2017,4,21,17,00,00));
}

void loop() {
// Loop function runs over and over again to allow setting of clock and implement the clock logic.

// Read the RTC each loop to keep display on real time from accurate source
  DateTime now = rtc.now(); // Get date and time from DS3231
  
    Y = now.year();
    M = now.month();
    D = now.day();
    Hrs = now.hour();
    Mins = now.minute();
    Secs = now.second();

  // Show the time on the display by turning it into a numeric
  // value, like 3:30 turns into 330, by multiplying the hour by
  // 100 and then adding the minutes.
  int displayValue = Hrs*100 + Mins;

  // Do 24 hour to 12 hour format conversion when required.
  if (!TIME_24_HOUR) {
    // Handle when hours are past 12 by subtracting 12 hours (1200 value).
    if (Hrs > 12) {
      displayValue -= 1200;
    }
    // Handle hour 0 (midnight) being shown as 12.
    else if (Hrs == 0) {
      displayValue += 1200;
    }
  }

  // Now print the time value to the display.
  clockDisplay.print(displayValue, DEC); // "DEC" declared in Adafruit_LEDBackpack.h

  // Add zero padding when in 24 hour mode and it's midnight.
  // In this case the print function above won't have leading 0's
  // which can look confusing.  Go in and explicitly add these zeros.
  if (TIME_24_HOUR && Hrs == 0) {
    // Pad hour 0.
    clockDisplay.writeDigitNum(1, 0);
    // Also pad when the 10's minute is 0 and should be padded.
    if (Mins < 10) {
      clockDisplay.writeDigitNum(2, 0);
    }
  }

  // Blink the colon by flipping its value every loop iteration
  // (which happens every second).
  blinkColon = !blinkColon;
  clockDisplay.drawColon(blinkColon);

  // Now push out to the display the new values that were set above.
  clockDisplay.writeDisplay(); // Variables declared in Adafruit_LEDBackpack.cpp

  // Pause for a second for time to elapse.  This value is in milliseconds
  // so 1000 milliseconds = 1 second.
  delay(1000);

  // If action chartacter is sent to Arduino set clock or increment or decrement the hour by one as for DST/PST
  if (stringComplete) {
    setClockTime = true;
    if (setClockTime) {    
    Serial.println(inBuf);
    String input = String(inBuf);
    String action = input.substring(0, 1);
      if(action == "S") {
        String Sub1 = input.substring(1,3);
        String Sub2 = input.substring(3,5);
        String Sub3 = input.substring(5);
        Hrs = Sub1.toInt();
        Mins = Sub2.toInt();
        Secs = Sub3.toInt();
        rtc.adjust(DateTime(Y, M, D, Hrs, Mins, Secs)); // Set clock
      }
      if(action == "I") {
        rtc.adjust(DateTime(Y, M, D, (Hrs + 1), Mins, Secs)); // Increment hour
      }
      if(action == "D") {
        rtc.adjust(DateTime(Y, M, D, (Hrs - 1), Mins, Secs)); // Decrement hour
      }
    setClockTime = false;
  }
   // Send date and time values to Serial Monitor for operational check
      DateTime now = rtc.now(); // Get new date and time from DS3231
      Serial.print("Read date & time from DS3231: ");
      Serial.print(now.year(), DEC);
      Serial.print('/');
      Serial.print(now.month(), DEC);
      Serial.print('/');
      Serial.print(now.day(), DEC);
      Serial.print(' ');
      Serial.print(now.hour(), DEC);
      Serial.print(':');
      Serial.print(now.minute(), DEC);
      Serial.print(':');
      Serial.print(now.second(), DEC);
      Serial.println();
      stringComplete = false;
  }
  // Back to the start of the loop function again!
}

// Sense whether anything has been sent in to clock via COM1
void serialEvent() {
  while (Serial.available()) {
    // Get incoming data
      Serial.readBytes(inBuf, 64);
      stringComplete = true;
    }
}

I am sending and receiving using the Serial Monitor window in the IDE, and am using the line Serial.println(inBuf) in the code to monitor what the Arduino sees. I realized that I have been assuming the 4th line from the end of the code [Serial.readBytes(inBuf, 64)] was reading all and clearing all 64 bytes of the serial input buffer on each event even if the incoming data was only one byte. If that isn’t happening, I don’t have a clue as to why. If there is a way to fix this function in the code, or a better way to do it, I would welcome any suggestions.

The above code works fine in use, setting the clock and/or incrementing/decrementing the displayed time. It just seems very sloppy to leave that unused data in the inBuf variable.

Many thanks to any and all who might care to offer any further suggestions, corrections, or advice.

Mick H
28 Apr 17
10:19 PM PDT USA

I can't reconcile

The problem has nothing to do with my code, it's entirely in the IDE and the Ser Mon.

and

I've noticed that other terminal emulators [Bray Terminal, Hyperterminal] also do this.

It just seems very sloppy to leave that unused data in the inBuf variable.

There are more elegant solutions, but you could fill the buffer with zeroes before reading in the data or use the value returned by the function to insert a zero at the end to properly terminate the string before printing it.

I see that you are messing around with Strings (objects created by the String library) which is often regarded as not a good idea on the Arduino due to the small amount of memory available. Consider using strings (zero terminated arrays of chars) instead.

Note that using serialEvent() has no advantages over checking yourself whether serial data is available and that it is not interrupt driven so will only execute once per iteration of the loop() function.

MickHoll:
AWOL - sorry, I don't understand the meaning of the above "?" Is it that you don't understand what I am asking? My question is about using the Ser Mon. Thanks for the reply.

I'm sorry, the solitary question mark was my shorthand for "Why haven't you posted the code you claim displays this behaviour no-one else seems to have noticed?".

MickHoll:
The code for this project is shown below:

Have you tried the code in the link in Reply #4?
What happened?

...R

MickHoll:
I realized that I have been assuming the 4th line from the end of the code [Serial.readBytes(inBuf, 64)] was reading all and clearing all 64 bytes of the serial input buffer on each event even if the incoming data was only one byte. If that isn't happening, I don't have a clue as to why. If there is a way to fix this function in the code, or a better way to do it, I would welcome any suggestions.

Because that is not how it is implemented. You will have to clear that buffer yourself, e.g. when you set stringComplete to false.

The better way is e.g. to use the examples in the thread (written by Robin2) that I linked. Learning a proper implementation when you're 'fresh' instead of having to get rid of bad habits when you're 'old' is always an advantage.

The String class (capital S) can leaves holes in your memory big enough to hide an elephant. Possibly not a problem now but it might result in strange bugs in a new code that you might want to write if future.

Most profound thanks to all who have taken the trouble to reply.

sterretje:
... You will have to clear that buffer yourself, e.g. when you set stringComplete to false.

Sterretje - I've made several attempts to do just that, none have worked. Have to confess that I don't know how. Any suggestions?

sterretje:
.... Learning a proper implementation when you're 'fresh' instead of having to get rid of bad habits when you're 'old' is always an advantage.

Unquestionably true. I'll certainly see what I can do with the info in the link in post #4.

UKHeliBob:
Consider using strings (zero terminated arrays of chars) instead.

UKHeliBob - tried that with notable lack of success (had troubles with parsing the incoming string(s)). I'll try again, particularly to be more efficient in memory handling. Also, checking of incoming data once each loop pass only is the way I want it to work.

An example of how to unconditionally clear the input buffer after stringComplete False would be much appreciated.

Again, many thanks to all.

Mick H.
29 Apr 17
10:11 AM PDT USA

for (int x = 0; x < sizeof(inBuf); x++)
{
  inBuff[x] = 0;
}

will fill the buffer with zeroes which will ensure that any characters written to it, up to a limit 63, will be zero terminated. As I suggested earlier you could also use the value returned by Serial.readBytes() to determine exactly where to put the zero. However, if you read the incoming data byte by byte instead of in a single chunk as you do now then you can simply put the terminating zero at the end of the received data.

Also, checking of incoming data once each loop pass only is the way I want it to work.

That does not mean that you have to use serialEvent(), which I still think brings nothing useful to the Arduino party.

memset(inputBuffer, 0, sizeof(inputBuffer));

// late edit: got the function wrong (was memcpy)

Thanks profoundly for the suggestions/examples on clearing the serial input buffer; I'm sure one or both will work. I did try the While serial.available - serial.Read approach but could not get that to work.

That does not mean that you have to use serialEvent(), which I still think brings nothing useful to the Arduino party.

[/quote]

UKHeliBob - understood; serialEvent() was just there in the prototype I began modifying. I'd be interested in knowing what's wrong with it.

Again, thanks to all.

MickH
29 Apr 17
7:16 PM PDT USA

serialEvent() was just there in the prototype I began modifying. I'd be interested in knowing what's wrong with it.

Nothing inherently wrong with it but as you have to write the code for it you might as well just use Serial.available() to determine that there is serial data.

I find it particularly ironic that your function has a while loop starting
  while (Serial.available()) {. This while loop could just as well be in the loop() function.

It would be a different matter if serialEvent() were interrupt driven which the name implies.

UKHeliBob - thanks for the reply:

UKHeliBob:
Nothing inherently wrong with it but as you have to write the code for it you might as well just use Serial.available() to determine that there is serial data.

I find it particularly ironic that your function has a while loop starting
  while (Serial.available()) {. This while loop could just as well be in the loop() function.

It would be a different matter if serialEvent() were interrupt driven which the name implies.

Also understood. That part of the code is essentially intact from Mr. DiCola's template. Once I get somewhat further toward finalizing this clock-control code I'll branch off and try to clean it up using the suggestions from this thread.

Thanks again.

MickH
30 Apr 17
1:17 PM PDT USA

Interesting prelim result re clearing the serial input buffer in my code (earlier post this thread): the following code snippet works (thanks UKHeliBob):

for (int x = 0; x < sizeof(inBuf); x++) {
inBuf = 0;
}

The snippet below (from Serial Input Basics - updated) does NOT work:

while (Serial.available() > 0) {
Serial.read();
}

Don’t have a clue as to why it doesn’t work; posted for any possibly interested person’s info.

MickH
3 May 17
11:14 AM PDT USA

Here is the code from reply #18 posted correctly (spot the difference and use code tags in future(

for (int x = 0; x < sizeof(inBuf); x++) 
{
   inBuf[x] = 0;
}

My code works and so does Robin’s, but they do different things. Mine puts a zero in each of the elements of the inBuf array so that within reason anything else added to it later is zero terminated. Robin’s code removes all data from the Arduino Serial input buffer. Not the same thing at all.