Please help with weird behavior

I am pretty new to the Arduino and haven't done C/C++ programming in years so I need help.

I have a sketch that I writing to handle keypad input and output text via USB Serial to a computer.

I am having problems with what I would call flaky operation, but I think it has to do with my programming. Actually, I think it specifically has to do with the way the variables are handled because the changes that make it work or not are sometimes addition of comments or commenting of debugging statements to remove them or reinstate them. Perhaps it's terminiators for the arrays, but I can't seem to get my head around it.

I have attached Monitor.pde with my sketch. Any help will be appreciated!

The specific behavior I see is:

  1. the call to RTC.now() seem to return nothing. When I attempt to use the output it is blank "0/0/2000 00:00"
    -- When this happens, I have been able to get the date back by adding a call to Serial.print("anything");. Then I comment it out and the date will stay. I make other changes someplace else it the code that has absolutely nothing to do with the clock and I lose it again.
  2. in the method endProcessing() the code will call printTicketLines(), but it never returns. printTicketLines() is used several times in the program and works fine everytime except when called from endProcessing(). I have added debug statements into printTicketLines() and it gets to "tag2" but does not reach "tag3". Further troubleshooting indicates it reaches the line "TicketLine += line[8];" and does not proceed any further.
    -- This one is similar in that adding debug statements or commenting them will make it complete through "Finished" or not. It's never a consistent behavior.

I'm thinking it could be something with the arrays. Maybe I overflow the arrays somehow? A prime example is how I just removed a 5 line block of comments and it started working again. Why? It was just comments.

Monitor.pde (19.2 KB)

Almost certainly you're running out of memory. You'll need to learn about putting strings in program memory (search Arduino.cc for progmem strings), and learn about monitoring your memory use (search for free memory). The other thing to do is try getting your sketch to work with way less libraries at first, and then slowly adding in functionality. For a sketch that's not working, this one is way too big.

Yes, that program looks like it needs too much RAM. As well as moving string literals into progmem, I suggest you rewrite it to avoid using the String class. IMO it should never have been included in the Arduino library, see Five things I never use in Arduino projects | David Crocker's Solutions blog.

I was afraid it was a memory situation, but I didn't know how to check.

Thanks for your help.

I'm working on getting rid of all of the Strings. I'm having trouble with my date and time functions.
What's the best way to rewrite this to get rid of the String? I want it to return something I insert into a char*.

	String insertDate()
	{
		DateTime now = RTC.now();

		String myDate = itoa(now.month(), buf,10);
		//if (now.month() < 10)
		myDate += "/";
			
		if (now.day() < 10)
			myDate += "0";
		myDate += itoa(now.day(), buf,10);
		myDate += "/";

		myDate += itoa(now.year(), buf,10);

		return myDate;
	}

Untested:

size_t insertDate(char* p)
{
  DateTime now = RTC.now();
  itoa(now.month(), p, 10);
  p += strlen(p);
  *p++ = '/';
  if (now.day() < 10)
  {
     *p++ = '0';
  }
  itoa(now.day(), p ,10);
  p += strlen(p);
  *p++ = '/';
  itoa(now.year(), p,10);

  p[strlen(p)] = ' ';   // remove this line if you want to leave the null terminator in place  
}

Call it with a pointer to the position in the buffer that you want to insert the date. The length will vary depending on whether the month has 1 or 2 digits.

I have this array:
char* line[lineLength] = {"551","1","0","0","0","0","0","0","0","0","FALSE","FALSE","FALSE","0","FALSE","","FALSE","FALSE","FALSE","FALSE","0","0","0","0","1"};

and I want it in index 7 or line[7].

This doesn't work at all:

		char* test;
		insertDate(test);
		line[7] = test;

and this

		insertDate(line[7]);

gives this output:
551,1,1,1/22/2012 SKU then ,HEADER,1,1/22/2012 SKU then ,1/22/2012 SKU then ,1/22/2012 11:48:04,ALARM,FALSE,FALSE,FALSE,1/22/2012 SKU then ,FALSE,22/2012 SKU then ,1/22/2012 SKU then ,FALSE,FALSE,FALSE,1/22/2012 SKU then ,1/22/2012 SKU then ,1/22/2012 SKU then ,1/22/2012 SKU then ,122/2012 SKU then

Try this. Remove the last statement in my version of insertDate() because you DO need the null terminator. I'm assuming you rework insertTime in the same way as insertDate.

	void sendHeader()
	{
		/*Header line example
		*	store, term, trans#, identifier, Anetnna
		**/
		itoa(ticket,bTicket,10);
		line[2] = bTicket;
		line[4] = "HEADER";
		line[5] = "1";
		line[6] = "0";
		insertDate(buf);
                size_t n = strlen(buf);
                buf[n] = ' ';
                insertTime(buf + n + 1);
		line[7] = buf;
		line[8] = buf;
		line[9] = "ALARM";
		line[10] = "FALSE";
		line[11] = "FALSE";
		line[12] = "FALSE";
		line[13] = "0";
		line[14] = "FALSE";
		Serial.println(printTicketLine());
	}

dgerler:
This doesn't work at all:

		char* test;
	insertDate(test);
	line[7] = test;



and this 

  insertDate(line[7]);

Since test is an unintialised char pointer rather than a char array, you're writing your string to an arbitrary memory location i.e. corrupting some other memory.

That did it DC42, thanks!

If you don't mind I have another problem I could use help with.

In function getPassword(), the first time through the password is read correctly. However, on each successcive pass (meaning on the next run through loop()) I pick up '?' at the beginning of the password. This problem was there and then went away and now it's been back for a couple days. See this output, please. between -- and --.

551,1,1,0,HEADER,1,0,1/22/2012 12:28,1/22/2012 12:28,ALARM,FALSE,FALSE,FALSE,0,FALSE,,0,FALSE,FALSE,FALSE,0,0,0,0,1
551,1,1,0,TICKET,0,Plu,5555,1,0,Sec Code Accepted,FALSE,FALSE,0,FALSE,,0,FALSE,FALSE,FALSE,0,0,0,0,1
551,1,1,0,TICKET,1,Plu,,1,1, ,FALSE,FALSE,0,FALSE,,0,FALSE,FALSE,FALSE,0,0,0,0,1
551,1,1,0,TICKET,1,Plu,123,1,1,Clerk Code Accepted,FALSE,FALSE,0,FALSE,,0,FALSE,FALSE,FALSE,0,0,0,0,1
551,1,1,0,TENDER,0,Plu,EOT,1/22/2012 12:28, ,551, , ,0,FALSE,,0,FALSE,FALSE,FALSE,0,0,0,0,1
freeRam:561
551,1,2,0,HEADER,1,0,1/22/2012 12:28,1/22/2012 12:28,ALARM,FALSE,FALSE,FALSE,0,FALSE,,0,FALSE,FALSE,FALSE,0,0,0,0,1
551,1,2,0,TICKET,0,Plu, --?5555-- ,1,0,Sec Code Not Accepted,FALSE,FALSE,0,FALSE,,0,FALSE,FALSE,FALSE,0,0,0,0,1
551,1,2,0,TICKET,1,Plu,5555,1,1,Sec Code Accepted,FALSE,FALSE,0,FALSE,,0,FALSE,FALSE,FALSE,0,0,0,0,1
551,1,2,0,TICKET,2,Plu,,1,2, ,FALSE,FALSE,0,FALSE,,0,FALSE,FALSE,FALSE,0,0,0,0,1
551,1,2,0,TICKET,2,Plu,123,1,2,Clerk Code Accepted,FALSE,FALSE,0,FALSE,,0,FALSE,FALSE,FALSE,0,0,0,0,1
551,1,2,0,TENDER,0,Plu,EOT,1/22/2012 12:28, ,551, , ,0,FALSE,,0,FALSE,FALSE,FALSE,0,0,0,0,1
freeRam:314

In getPassword():

		char pass[5];
...
		line[7] = pass;

When you return from getPassword, variable 'pass' ceases to exist and its storage gets reused for other stuff. So the value in "line[7]" is no longer valid once you have returned from getPassword. One way of fixing this is to declare "pass" globally instead of locally in the function.

I suggest you also add a counter in getPassword() to count how many characters you have entered and avoid storing more than 4. As it stands your program has a classic buffer overflow vulnerability and is likely to crash or do wierd things if you enter more than 4 characters before the #.