Strange fault. LCD corrupts and arduino crashes

cowasaki:
I have just reduced the size of the text strings by 600 bytes and hey presto it all works perfectly, then logged back in and read dc42's post (great minds etc)!!

Glad you got it working. The 328p only has 2KB of RAM for static data, strings, stack and any dynamic memory you allocate; and 600 bytes is quite a large chunk of that.

dc42, \n just saved me nearly 1/2K !!! :slight_smile:

Off to work now...... think I'm going to be late :smiley:

dc42, \n just saved me nearly 1/2K !!!

It saved you nearly 1/2k of ROM. If you're using only half of your ROM, that isn't such a big deal.
Your problem is that all those long strings are using up RAM, as I pointed out earlier.

In future, if you have lots of long strings that you want to print, here is how to do it:

#include <avr/pgmspace.h>
#include <alloca.h>

void serialPrint_P(const prog_char* s)
{
  char* p = (char*)alloca(strlen_P(s) + 1);
  strcpy_P(p, s);
  Serial.print(p);
}

void setup()
{
  Serial.begin(9600);
}

void loop()
{
  serialPrint_P(PSTR("Hello"));
  delay(500);
  serialPrint_P(PSTR(" world!\n"));
  delay(500);
}

String literals enclosed in PSTR() are held in program space instead of RAM; but you can't pass them to Serial.print directly, so you print them with serialPrint_P instead. The amount of RAM you need for these strings is about the length of the longest string you print in this way, instead of the total length of all the strings.

void serialPrint_P(const prog_char* s)
{
  char* p = (char*)alloca(strlen_P(s) + 1);
  strcpy_P(p, s);
  Serial.print(p);
}

Or save stack space, and just print them one character at a time.

The command:

Serial.println('something to print');

Why would this create a variable?

Sorry but I am an experienced programmer but not particularly with this language. I would have thought that the above line would be a constant and therefore not use up variable space.

My understanding might be completely wrong though!

Why would this create a variable?

Well, not so much a variable as something that occupies RAM.

Consider the "println" method.
It has a overload that takes a "char*".
"char*" can only sensibly point to RAM.

AWOL:

dc42, \n just saved me nearly 1/2K !!!

It saved you nearly 1/2k of ROM. If you're using only half of your ROM, that isn't such a big deal.
Your problem is that all those long strings are using up RAM, as I pointed out earlier.

Yes, that's what I thought.

I thought (as per above post) that serial.print('xxxxxx'); wouldn't use ram

I'm a little confused as to why I am getting the problem that I am. I am using only a few global variables and a few local ones. I am also stashing away a number of values in EEPROM.

Yes, that's what I thought.

It saved you ROM because you had fewer calls to "Serial.println()"

AWOL:

Why would this create a variable?

Well, not so much a variable as something that occupies RAM.

Consider the "println" method.
It has a overload that takes a "char*".
"char*" can only sensibly point to RAM.

I would expect the serial.println function to use a small amount of ram whilst it us doing it's thing but then release it afterwards. I wouldn't expect it to keep that ram.

Why would it?

I am not questioning anybody, I'm just confused as to why it would

Because the string HAS to live in RAM.

AWOL:

Yes, that's what I thought.

It saved you ROM because you had fewer calls to "Serial.println()"

Like I said. Yes that exactly what I would have expected.

AWOL:
Because the string HAS to live in RAM.

Why? The function call can be in ROM transferring the value to RAM for the call. It seems a strange thing to do to store all function call CONSTANTS in RAM.

Oh well if it does it does but it still sound daft.

It would make more sense to send the ROM address

Why? The function call can be in ROM transferring the value to RAM for the call. It seems a strange thing to do to store all function call CONSTANTS in RAM.

The function call IS in ROM - all the code is in ROM.
This is Harvard architecture processor, not von Neumann.

It would make more sense to send the ROM address

Consider:

char string [] = "Where do I put this?";
Serial.println (string);
Serial.println("And where should I put this and distinguish it from the other one?");

Well at least I now know.

It still seems ridiculous that it doesn't just pass the address of the constant but now that I know I can work round it.

Thanks everyone. This would certainly explain the issues.

AWOL:

Why? The function call can be in ROM transferring the value to RAM for the call. It seems a strange thing to do to store all function call CONSTANTS in RAM.

The function call IS in ROM - all the code is in ROM.
This is Harvard architecture processor, not von Neumann.

It would make more sense to send the ROM address

Consider:

char string [] = "Where do I put this?";

Serial.println (string);
Serial.println("And where should I put this and distinguish it from the other one?");

I appreciate what you are saying and do understand. I am just expecting more from it than it does! I will look at the examples earlier on and change the code to suit.

I am so used to either higher or lower level languages. In assembler for example I would use

Call stringprint
This is the text
NULL CHAR

And use the program counter as the pointer.

I do appreciate everything that's been said. It's a steep learning curve switching programming languages but I'm starting to get the hang of more of this one now :smiley:

Thanks again everyone!

I am so used to either higher or lower level languages

Maybe you're not used to using languages more normally used on von Neumann architectures on Harvard architecture processors.

One thing not well discussed:

Serial.print(char ) doesn't allocate any temp space at all. It just keeps calling Serial.write(byte) with incrementing the char, so one byte at a time. There is no cost (except for return address and byte on stack) to SRAM for calling Serial.print. This also explains why the Serial.print will not print strings stored in FLASH. Print assumes the char * is a pointer to SRAM location. You can probably hack the library to add an overloaded print that takes PROGMEM_P sort of pointer (Am I right on the data type?).

You can probably hack the library to add an overloaded print that takes PROGMEM_P sort of pointer

No, because PROGMEM is simply a qualifier.

So what is the best way of doing this then, when it is a constant string ????