Odd results when passing variables to a function.

I am building an RFID reader that reads tags, notes the time, and sends a message when it happens.

Here are the symptoms of my problem. Whenever I read a tag for the first time, the code works correctly and outputs:

Message Contents:
Tag ID Is: 39fl7412
Read At: Apr 01 2012 12:10:20

However, when I read it again I get:

Tag ID Is: 39fl7412
Read At: uy"null" 01 2012 12:10:20 (Where "null" is the null character, not the text)

And the third time:

Tag ID Is: 39fl7412
Read At: uy followed by 5 null characters, then part of the tag Id "fl7412" then 6 null characters, then 01.

After the third read, it's the same as above.

I have tried all kinds of stuff and haven't figured it out. Any help is greatly appreciated.

Here's my code:

#include <SoftwareSerial.h>
#include <SPI.h>
#include <Wire.h>
#include <RTClib.h>
#include <RTC_DS3234.h>

SoftwareSerial rfid(12,13);

// Create an RTC instance, using the chip select pin it's connected to
RTC_DS3234 RTC(8);

//RTC time buffer variables
const int len = 32;
static char buf[len];

//RFID variables
int flag = 0;
int Tag[11];



void parse(void);
void print_serial(void);
void read_serial(void);
void seek(void);
void set_flag(void);



void setup()
{
  Serial.begin(9600);
  Serial.println("Starting...");
  
  //Initialize RTC
  SPI.begin();
  RTC.begin();
  
  //Initialize RFID
  rfid.begin(19200);
  delay(10);
}

void loop()
{
  read_serial();
  
}

void read_serial()
{
  seek();
  delay(10);
  parse();
  set_flag();
  print_serial();
  delay(100);
}

void seek()
{
  
  rfid.write(255);
  
  int i = 0;
  rfid.write(i);
  rfid.write(1);
  rfid.write(130);
  rfid.write(131);
  delay(10);
}

void parse()
{
  while(rfid.available())
  {
    if(rfid.read() == 255)
    {
      for(int i=1;i<11;i++)
      {
        Tag[i]= rfid.read();
      }
    }
  }
}

void set_flag()
{
  if(Tag[2] == 6){
    flag++;
  }
  if(Tag[2] == 2){
    flag = 0;
  }
}

void print_serial()
{ 
  if(flag == 1)
  {
    DateTime now = RTC.now();
    String time = now.toString(buf,len);
    delay(100);
    
    String TagID = "";
    
    char buffer[3];
    for(int index = 8; index>4; index--)
    {
      itoa(Tag[index], buffer,16);
      TagID += buffer;
    }
    
    send_message(TagID, time);
    
  }
}

void send_message(String ID, String timestamp)
{
  Serial.println("Message Contents:");
  Serial.print("Tag ID Is: ");
  Serial.println(ID);
  Serial.print("Tag Read At: ");
  Serial.println(timestamp);
}

Your parse code does not check if there are 11 chars available but it does read as if there are. Think it needs a redesign

A blocking version...

void parse()
{
  while(rfid.available() < 11);
  for(int i=1;i<11;i++)
  {
    Tag[i]= rfid.read();
  }
}

Still haven't fixed this code, I see:

void parse()
{
  while(rfid.available())
  {
    if(rfid.read() == 255)
    {
      for(int i=1;i<11;i++)
      {
        Tag[i]= rfid.read();
      }
    }
  }
}

There is at least one byte available to read, so, read all 12 of them.

void loop()
{
  read_serial();
}

Why?

    String time = now.toString(buf,len);

What is in time now? Why is buf global? Why is it static?

int Tag[11];

Tag is now an int.

      itoa(Tag[index], buffer,16);

An int can hold a value up to 7FFF. Without taking my shoes off, I can see that they size of buffer needs to be 5 elements.

    char buffer[3];

But, it isn't.

Anywhere where a buffer overrun can occur, problems can, too. Wasting 5 bytes, and making buffer 8 bytes, is probably not going to kill your application.

Thanks for the advice, I was able to get this code working.

I am new to this and didn't realize that using const fixed the value. By moving the time buffer variables into the send_message function and removing the const I got it working. I was referencing some example code for the RTC I'm using.

Am I correct that, by declaring the time variables within the function, there are "re-initialized" every time the function is called?

I also changed the length of buffer to 8. For future reference, is there a reference that I can read that talks about determining appropriate buffer length?

I am new to this and didn't realize that using const fixed the value.

What did you think const meant?

By moving the time buffer variables into the send_message function and removing the const I got it working.

The only const I saw was for the buffer length, which should be const. If the toString() method is writing to the second argument, that looks like a bug to me.

Am I correct that, by declaring the time variables within the function, there are "re-initialized" every time the function is called?

Depends on how you declare them. By default, local variables are not initialized.

For future reference, is there a reference that I can read that talks about determining appropriate buffer length?

It's not hard to determine. Look at the maximum value that the variable that you want to convert to a string will have in the format that you want. Add 1 at a minimum, for the NULL.