Arduino interprets serial input differently from VB6

I have an RFID reader connected to my arduino Uno through Max3323.
the reader sends a 15 character string to the arduino when it reads a tag, that's fine and arrives correctly.
The reader has other functions where it sends a response to a string. For instance it reads its own operating frequency and sends the result '136.5'.
But If I ask for the date and time, which should come back as '131129202135 05' that is yymmddhhmmss and then two digits for day of week, I get L¦¦LLNLM& $&¦Cjªø or perhaps L¦¦LLNL???12 04 . the results are not consistent but are dominated by LNM.
Running the same routine from a small VB6 application gives perfect results, so it seems as if my problem relates to the reading of the serial input in the arduino sketch. I have tried using exactly the same code for the serial input of the tag data [correct] and the date/time data [incorrect]. both are a series of 15 digits, which I am serializing as a string.

the relevant code is this:-
void loop() {
if (requestTime) {
requestString = "RTM";
reader.println(requestString);
blinkLed();
delay(2000);
while (reader.available() >0){
char (timeChar) = (char) reader.read();
timeString += timeChar;
if ((timeString.length() == 15)||(timeChar == '\r')||(timeChar == '\n')){
timeComplete = true;
//char timeChar[10];
lcd.setCursor(3,1);
lcd.print(timeString);
Serial.print(timeString);
timeString = "";
requestTime = false;
}
}
}
Any Ideas? I know there are dozens of questions along these lines, but not too many that come close to my problem.

I am not certain about the output, but I have never had good results from the String data type. Every time I use it, my sketch eventually crashes. Try replacing the timeString with a character array rather than String.

Thanks, I'll set to and see if I can do that.

  char (timeChar) = (char) reader.read();

(Variable) (names) (do) (not) (need) (to) (be) (in) (parentheses).

the relevant code is this:-

The problem may not be in the part you think is relevant. Post ALL of your code.

PaulS, thanks for your reply.
I have hoovered up a few brackets!
I have done some further testing too. If I set the time.date to 100101000000 I am getting a consistent response of “LL~~~100xxxx 06” where xxxx is the correct relative mins and secs after resetting and 06 is saturday.
If I set date.time to 131130120000 the response is L||L&LLL™> 06, and a couple of minutes later is L||L&|LLLMML ~>,
Hmmm… typing that out tells me that they are all typed using the shift key…?

Any way here is the full code

#include <string.h>
#include <SoftwareSerial.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
String inputString = “”;// a string to hold incoming data
String previousString = “”;
String outputString = “”;
String rightString = “”;
String leftString = “”;
String lcdString = “”;
String timeString = “”;
String requestString = “”;

boolean stringComplete = false;// whether the string is complete
boolean timeComplete = false;
boolean requestTime = true;

const int ledPin = 7;
const int txpin1 = 2; //T1 in
const int rxpin1 = 3; //R1 out
const int notxpin = 255;
const int norxpin = 254;
LiquidCrystal_I2C lcd(0x27,20,4); // set the LCD address to 0x27 for a 20 chars and 4 line display

SoftwareSerial reader(rxpin1, txpin1);

void setup() {
lcd.init(); // initialize the lcd
lcd.backlight();
// initialize serial:
Serial.begin(9600);
reader.begin(9600);
digitalWrite(ledPin, LOW);
// reserve 32 bytes for the inputString:
inputString.reserve(32);
timeString.reserve(32);
pinMode(ledPin, OUTPUT);
pinMode(rxpin1, INPUT);
pinMode(txpin1, OUTPUT);
}

void loop() {
if (requestTime){
getTime();
}
if (stringComplete) {
if (inputString != previousString) {
leftString = inputString.substring(4,6) + “-” + inputString.substring(2,4) + “-” + inputString.substring(0,2);
rightString = inputString.substring(4,10) + " " + inputString.substring(10,15);
lcdString = (“UK” + rightString);
outputString = (leftString + " … UK" + rightString +’\n’);
previousString = inputString;
//outputString = inputString + ‘\n’;
Serial.print(outputString );

Serial.print(inputString +’\n’);
//lcd.clear();
lcd.setCursor(3,0);
lcd.print(lcdString);
//lcd.setCursor(3,1);
//lcd.print(timeString);
}

inputString = “”;
stringComplete = false;
}
if (timeComplete) {
Serial.print(timeString);
lcd.setCursor(3,1);
lcd.print(timeString);
timeComplete = false; //replace for not run once
}
while (reader.available()) {
char inChar = (char) reader.read();
inputString += inChar;
if (inChar == ‘\r’ or inChar == ‘\n’) { // or inputString.length() == 15
stringComplete = true;
}
}
}
void getTime(){
requestString = “RTM”;
reader.println(requestString);
blinkLed();
delay(200); //delay 2000 if Measure Frequency is request
while (reader.available() >0){
char timeChar = (char) reader.read();
timeString += timeChar;
if (timeString.length() == 15 || timeChar == ‘\r’ || timeChar == ‘\n’){
timeComplete = true;
requestTime = false;
lcd.setCursor(3,1);
lcd.print(timeString);
Serial.print(timeString);
timeString = “”;
}
}
}
void blinkLed(){
digitalWrite(ledPin, HIGH);
delay(100);
digitalWrite(ledPin, LOW);
}

String inputString = "";// a string to hold incoming data
  String previousString = "";
  String outputString = "";
  String rightString = "";
  String leftString = "";
  String lcdString = "";
  String timeString = "";
  String requestString = "";

There is no reason to be pissing away resources using Strings. Nothing in the code couldn't be done using NULL terminated arrays of chars.

getTime() implies that it returns a time. Functions with get in the name should return a value. Discarding the value that the function returns is then pointless. I can't even follow what the function is doing, since the SoftwareSerial instance name, reader, implies nothing about what it is reading from. The name is also confusing, since the first use of reader is as a writer.

At this point, I gave up. The function clearly gets, somehow from somewhere, a string that is less than 16 characters long, and is a known length. That is ideal for storing in a char array, but the function wastes resources using a String, instead.

The poorly named getTime() function writes to the LCD, too. Nothing in the name implies it is going to do that.

You have code in loop() for reading from the SoftwareSerial instance, and you have code in getTime() for reading from the instance. That is wrong. All the code for reading from the instance should be in one place.

Well, I expect you have guessed I am a novice. My formal programming education finished with elementary level AlgolW in 1972. So I apologise if I seem dim.
The reader is an RFID unit, whose RTC can be interrogated and whose time I would like to use for reference.

getTime() asks for the time, and the print to lcd was to help me find where the errors were coming in.

I do now understand that i should be using arrays rather than strings and I will attempt to rectify this.
I have had a stab at using an array for the timeString, and it yielded identical results.

It may be of interest to know that I decided to pull out the date only from the date.time data using .substrings and then print out only the date section, and now the program does exactly what I wanted with no sign of the unintelligible characters.

So I apologise if I seem dim.

No need to apologize for not being an expert, if you take the suggestions to heart.

The reader is an RFID unit, whose RTC can be interrogated and whose time I would like to use for reference.

OK. That was not at all clear.

getTime() asks for the time, and the print to lcd was to help me find where the errors were coming in.

storeTimeInGlobalVariables() might have been a better name, then.

It may be of interest to know that I decided to pull out the date only from the date.time data using .substrings and then print out only the date section, and now the program does exactly what I wanted with no sign of the unintelligible characters.

This suggests that memory is getting stomped on, then. Perhaps because of the use of Strings. Perhaps not. The real problem is that we can not see what you are seeing. There is an additional problem in that you are apparently using a very strange way of storing the time and date in the String and/or your problem description is unclear. For example, you say:

If I set the time.date to 100101000000 I am getting a consistent response of "LL~~~100xxxx 06" where xxxx is the correct relative mins and secs after resetting and 06 is saturday.

It isn't clear what time.date is. There is nothing in your code that is named anything like time.date. There is nothing that should be putting LL anything in a string/String that represents a date/time.

I'll continue trying to help. but a clearer description of the problem, and an explanation of why you choose to represent the time and date the way that you do is on order.

Re-reading my post I see I have described Date/Time as time.date, my error. The RFID unit outputs the Date/Time as 12 digits then a space and two digits. I only actually want the date, so am primarily interested in the first six digits.
I need the date in the format 13-11-30 in order to (in the future) pass it on to another Serial communication device, along with the identity of each RFID tag that is read.
I haven't outlined the entire project outside of the arduino as there is a lot of unnecessary clutter, and another softwareSerial still to be added.
I have been reading up on arrays vs strings and I will attempt to re-write the sketch.
I will post here again if I get into problems.
In the meantime, I have a working, if clumsy, solution which I can use to refer back to.
Thanks again...

and another softwareSerial still to be added.

For what purpose? Only one instance of SoftwareSerial can be listening at a time, so this severely limits what you can do with software serial ports.

Perhaps I put that wrong too, I need to have another Serial port wired into the uno to send processed, linked Date and Rfid data to another device.

PaulS, thank you so much for your pointers on a better way.

I have removed all the Strings, and replaced with strings. I now have an understanding of what was going wrong in my original question, as I can reproduce that by reading from beyond a string’s allocated length. I presume therefore that the Strings in VB6 are allocated memory in 255 byte blocks or somesuch, so that bytes beyond the end are automatically empty.

I now have a sketch that works perfectly, and I can understand how to develop it further. It already has more functionality than the first effort and is over 3kB smaller. I have posted the latest version with a lot of edited variable names.

/
  #include <SoftwareSerial.h>
  #include <Wire.h>
  #include <LiquidCrystal_I2C.h>
 
  char interrogateRfid[4] = "RTM";
  char rawDateArray[7];
  char formattedDateArray[10];
  char currentRfidArray[17];
  char previousRfidArray[17];
  char outputPrefixForLcd[3] = "UK";
  char outputPrefixForPharmweigh[5] = " .. "; // branded weighing m/c
  char outputForLcd[16];
  //char previousOutputForLcd[16];
  char Month[4];
  char* longMonthArray[]={"JAN","FEB","MAR","APR","MAY","JUN","JUL","AUG","SEP","OCT","NOV","DEC"};

  int month; //does not need (DEC)
  int i;

  boolean inputComplete = false;
  boolean timeComplete = false;
  boolean requestDate = true;
  
  const int ledPin = 7;
  const int txpin1 = 2; //T1 in  (rs232 pins)
  const int rxpin1 = 3; //R1 out
  const int txpin2 = 4; //T2 in
  const int rxpin2 = 5;  //R2 out 
  const int notxpin = 255;
  const int norxpin = 254;
  LiquidCrystal_I2C lcd(0x27,20,4);  // set the LCD address to 0x27 for a 20 chars and 4 line display
  
  SoftwareSerial rfidUnit(rxpin1, txpin1);  //comms with RFID tag reader
  SoftwareSerial pharmweigh(rxpin2, txpin2);  
  
  void setup() {
    lcd.init();        
    lcd.backlight();
    // initialize serial:
    Serial.begin(9600);
    rfidUnit.begin(9600);
    digitalWrite(ledPin, LOW);
    pinMode(ledPin, OUTPUT);
    pinMode(rxpin1, INPUT);
    pinMode(txpin1, OUTPUT);
  }
  
  void loop()  {
    if (requestDate){
      fetchDateArray();
    }
    while (rfidUnit.available()<16) {inputComplete = false;}
      inputComplete = true;
      for (i=0;i<16;i++){
        previousRfidArray[i] = currentRfidArray[i]; //previous starts out as null becomes current with new line
        currentRfidArray[i] = rfidUnit.read();  //current becomes new data
      }
    inputComplete = true; 
    rfidUnit.flush();
    if (inputComplete) {
      lcd.setCursor(0,1);
 
    }
  
    if(strcmp(currentRfidArray, previousRfidArray) != 0){ //discard duplicate reads
        blinkLed();   
        for (i=0;i<2;i++){
          outputForLcd[i] = outputPrefixForLcd[i];
        }
        for (i=2;i<8;i++){
          outputForLcd[i] = currentRfidArray[i+2];
        }
        outputForLcd[8] = ' '; 
        for (i=9;i<14;i++){
          outputForLcd[i] = currentRfidArray[i+1];
        }
        /*if (previousOutputForLcd[0] > 0){  //two line display, recent first
          lcd.setCursor (3,3);
          for (i=0;i<14;i++){
            lcd.write (previousOutputForLcd[i]);
          }
        }*/
        lcd.setCursor(3,2);
        for (i=0;i<14;i++){
          lcd.write (outputForLcd[i]); 
        //  previousOutputForLcd[i] = outputForLcd[i];
        }
        rfidUnit.flush();
        rfidUnit.end();
        Serial.print(formattedDateArray); //These four lines for serial monitor only
        Serial.print(outputPrefixForPharmweigh);
        Serial.print(outputForLcd);
        Serial.write('\n');
        pharmweigh.begin(9600);
        pharmweigh.print(formattedDateArray); 
        pharmweigh.print(outputPrefixForPharmweigh);
        pharmweigh.println(outputForLcd); //needs total chars27 with println for final output

        pharmweigh.end();blinkLed();
        rfidUnit.begin(9600);
    }
  }
  

  void fetchDateArray(){
    rfidUnit.flush();
    requestDate = false;  // i.e. run once
    rfidUnit.print(interrogateRfid);//'RTM'
    rfidUnit.print('\r');//completes request for date and time
    blinkLed(); 
    delay(100); //delay 2000 if interrogateRfid == Measure Frequency (MOF)
    while (rfidUnit.available()){ 
      for (i=0;i<6;i++){
        rawDateArray[i] = rfidUnit.read();
      }  // fetched first six bytes of date
      int month = ((rawDateArray[2]-48)*10 + rawDateArray[3]-49);
      char *Month = longMonthArray[month];
      rfidUnit.flush();  //discard remaining bytes
      for (i=0;i<2;i++){
      formattedDateArray[i] = rawDateArray[i+4];
      }
      for (i=3;i<6;i++){
      formattedDateArray[i] = Month[i-3];
      }
      for (i=7;i<9;i++){
      formattedDateArray[i] = rawDateArray[i-7];
      }
      formattedDateArray[2] = '-';
      formattedDateArray[6] = '-';
      lcd.print (formattedDateArray);
    }
  }
  void blinkLed(){
    digitalWrite(ledPin, HIGH);
    delay(100);
    digitalWrite(ledPin, LOW);
  }

Serial_UK_first_strings_to_arrays.ino (4.09 KB)