automatic sketch restart

I can not understand why if I insert code into two functions of the same sketch, the sketch is ever restarted;
it's quietly if I leave it blank, instead i I put the code happens the damage ...
the fact that the sketch restart it will be deducted from the lack of output on the LCD screen and the continuous print (on the serial monitor) for certain phrases that I put in the constructor of an object (which automatically creates the library )....

what I do not go back is that there are features that add to have problems like segmentation fault, since they do not have time to be invoked ....

I ask your help because I really do not understand why ...
the compiled results to be 25,824 ...

I post the code of the functions

char *typeSocketToString(int8_t type){
  switch(type){
    case(COOLER): return "REFRIGERATORE";
    case(FANS): return "VENTOLE";
    case(FILTER): return "FILTRO";
    case(HEATER): return "RISCALDATORE";
    case(KALKWASSER): return "KALKWASSER";
    case(LIFTS): return "RISALITA";
    case(LIGHT): return "LUCE";
    case(MANGER): return "MANGIATOIA";
    case(MOBILE_FANS): return "VENT. MOBILE";
    case(MOON_LIGHT): return "LUCE LUNARE";
    case(OTHER): return "ALTRO";
    case(PUMP): return "POMPA";
    case(REACTOR): return "REATTORE";
    case(SKIMMER): return "SKIMMER";
    case(AQUARIUM_SOLENOID): return "ELETTROV. VASCA";
    case(REACTOR_SOLENOID): return "ELETTROV. REATTORE";
    case(TOPPING_TANK): return "RABBOCCO VASCA";
    case(TOPPING_SUMP): return "RABBOCCO SUMP";
  
    case(COOLER_PROBED): return "REFRIG. SONDATO";
    case(TOPPING_TANK_PROBED): return "RABB. VASCA SONDATO";
    case(TOPPING_SUMP_PROBED): return "RABB. SUMP SONDATO";
    case(AQUARIUM_SOLENOID_PROBED): return "ELETTR. VASCA SONDATA";
    case(REACTOR_SOLENOID_PROBED): return "ELETTR. REATTORE SONDATA";
    case(ORP_PROBED): return "ORP SONDATO";
    case(MOON_LIGHT_PROBED): return "LUCE LUNARE SONDATA";
    case(HEATER_PROBED): return "RISCALDATORE SONDATO";
    case(FANS_PROBED): return "VENTOLE SONDATE";
    
    case(TURNED_OFF): return "SPENTA";
    default: return "TIPO SCONOSCIUTO";
  }
}

void makeSocket(uint8_t indexSocket){
  uint8_t socketType = TURNED_OFF, row = 0;
  int8_t n = 0, sel = 0, sel2 = 0;
  short on = 0, off = 0;
  float th = 0.0;
  
  IO.clearLcd();
  IO.lcdPrint((int) indexSocket + 1, 0);
  IO.lcdPrint(") ");
  switch((sel = IO.readSelectedIndex("LA PRESA E'", "TEMPORIZZATA", "SEMPRE ACCESA", "SEMPRE SPENTA", "SONDATA", NULL))){
    case(0): case(1): case(2):
     if((sel2 = IO.readSelectedIndex("TIPO PRESA", "LUCE", "POMPA", "FILTRO", "RISCALDATORE", "RISALITA", "SKIMMER",
          "VENTOLE", "REFRIGERATORE", "MANGIATOIA", "VENT. MOBILE", "LUCE LUNARE", "REATTORE", "KALKWASSER", "ELETTROV. REATTORE",
          "ELETTROV. VASCA", "RABBOCCO VASCA", "RABBOCCO SUMP", "ALTRO", "SPENTA", NULL)) >= 0)
      socketType = sel2; //di default e' gia' TURNED_OFF
    break;
    case(3):
      if((sel2 = IO.readSelectedIndex("TIPO PRESA", "RISCALDATORE SONDATO", "ELETTR. REATTORE SONDATA", "ELETTR. VASCA SONDATA",
            "RABB. VASCA SONDATO", "RABB. SUMP SONDATO", "REFRIG. SONDATO", "VENTOLE SONDATE", "LUCE LUNARE SONDATA",
            "ORP SONDATO", NULL)) >= 0)
        socketType = HEATER_PROBED + sel2; //HEATER_PROBED + sel2 perche' sel2 e' lo "scostamento" dalla prima presa sondata
      if(socketType != TURNED_OFF){
        IO.clearLcd();
        IO.lcdPrint("SOGLIA = ");
        th = IO.readFloat(10); // 10 = strlen("SOGLIA = ") + 1
      }
   break;
  }
  if(sock.setPowerSocket(indexSocket, socketType, th) == CORRECT){
    if(sel == 1)
      sock.setPowerSocketEverOn(indexSocket);
    else if(socketType != TURNED_OFF && sel == 0){
      IO.clearLcd();
      IO.lcdPrint("ACCENSIONI (<=", 2);
      IO.lcdPrint((int) MAX_SOCKET_SWITCH);
      IO.lcdPrint(")");
      n = IO.readInt(MAX_SOCKET_SWITCH, ++row);
      IO.clearLcd();
      for(int i = 0, row = 0; i < n; i++){
        if(row == LCD_ROW){
          IO.clearLcd();
          row = 0; 
        }
        IO.lcdPrint("ON  ", row++);
	IO.lcdPrint(i + 1);
	IO.lcdPrint(" = ");
	on = IO.readTime(9);
	IO.lcdPrint("OFF ", row++);
	IO.lcdPrint(i + 1);
	IO.lcdPrint(" = ");
	off = IO.readTime(9);
	sock.addTime(indexSocket, ((on == TIME_OUT) ? 0 : on), ((off == TIME_OUT) ? 0 : off));
	}
    }
  }
}

IO.readSelectedIndex, works because I use it in other part of the sketch and goes ok

int InputOutputI2C::readSelectedIndex(const char *query, ...){
	char key = CHAR_NOT_INSERT;
	va_list argList;
	uint8_t i = 0, nArg = 0, select = 0, row = 0;
	bool timeout = false;

	va_start(argList, query);
	while(va_arg(argList, char *))
		nArg++;

	char *args[nArg];

	va_start(argList, query);
	for(; i < nArg; i++)
		args[i] = va_arg(argList, char *);
	va_end(argList);


	clearLcd();
	if(query)
		lcdPrint(query, row++);
	_secondsWithoutInput = 0;
	do{
		for(i = 0; i < _lcdRow - (query ? 1 : 0); i++){ //-1 perche' devo togliere la prima riga di "intestazione"
			clearLcdRow(row + i);
			if(i == 0) //solo la prima opzione ha ->
				lcdPrint("->", row);
			lcdPrint(args[(select + i) % nArg], row + i, 2);
		}

		// fino a che non scade il tempo scarto tutti i caratteri inseriti che non sono
		while(!timeout && ((key = readChar()) != ENTER && key != CANCEL && key != CURSOR_UP && key != CURSOR_DOWN))
			timeout = _secondsWithoutInput > MAX_SECOND_WAIT_INPUT_TIME;
		
		if(key == CURSOR_UP)
			select = (nArg + select - 1) % nArg;  //nArg perche' le opzioni sono nArg; devo sommarlo perche' -1 % nArg e' corretto, ma io voglio solo valori positivi
		else if(key == CURSOR_DOWN)
			select = (select + 1) % nArg;  //nArg perche' le opzioni sono nArg
	}while(key != ENTER && key != CANCEL && !timeout);
	return ((key == ENTER) ? select : ((key == CANCEL) ? CANCELED : TIME_OUT));
}

edit:
the blame can be attributed to the fact that both functions create many literals ...
how you might solve?

You are using a lot of strings, which consume a lot of RAM. You might consider moving those strings into PROGMEM.

did not know him ...
I gave it a quick read and I understand very little ...

how would you suggest to make IO.readSelectedIndex with the PROGMEM?
pass an array of prog_char terminated by a NULL and do something similar to what is now?

p.s. but uses the EEPROM is not it?

Brig:
p.s. but uses the EEPROM is not it?

It uses the PROGMEM (not the EEPROM). And the strings are in PROGMEM anyway (and are copied to RAM). Following that suggestion you only have one copy not two.

you're right ... I do not know why I confused the flash memory with EEPROM.

These variables "PROGMEM" can be automatic variables or must be global?

Tomorrow I will try to calmly put the literals in PROGMEM ...

But say this solves the problem of the reboot? because I was able (by shortening all literals) to make it work, then change one thing and, of course, do not work anymore ...

may there is some libraries but a good start :

Considering the board you get (arduino; mega; ...) EEPROM can also be another way of storing things

I modified my function like this

PROGMEM const char *socketTypeTimed[] = {"LUCE", "POMPA", "FILTRO", "RISCALDATORE", "RISALITA", "SKIMMER",
          "VENTOLE", "REFRIGERATORE", "MANGIATOIA", "VENT. MOBILE", "LUCE LUNARE", "REATTORE", "KALKWASSER", "ELETTROV. REATTORE",
          "ELETTROV. VASCA", "RABBOCCO VASCA", "RABBOCCO SUMP", "ALTRO", "SPENTA", NULL};

PROGMEM const char *socketTypeProbed[] = {"RISCALDATORE SONDATO", "ELETTR. REATTORE SONDATA", "ELETTR. VASCA SONDATA",
            "RABB. VASCA SONDATO", "RABB. SUMP SONDATO", "REFRIG. SONDATO", "VENTOLE SONDATE", "LUCE LUNARE SONDATA",
            "ORP SONDATO", NULL};

char *typeSocketToString(int8_t type){
  if(sock.isProbedSocket(type))
    return (char *) pgm_read_word(socketTypeProbed[type -  HEATER_PROBED]);
  else if(type >= 0 && type < HEATER_PROBED)
    return (char *) pgm_read_word(socketTypeTimed[type]);
  return "SCONOSCIUTO";
}

how about ?

edit:
edited everything with PROGMEM but it's worse than before ...

what can I do?

No. Read the example on this page:

Your strings have to be individually assigned like this:

#include <avr/pgmspace.h>

prog_char string_0[] PROGMEM = "LUCE";   // "String 0" etc are strings to store - change to suit.
prog_char string_1[] PROGMEM = "POMPA";
prog_char string_2[] PROGMEM = "FILTRO";
prog_char string_3[] PROGMEM = "RISCALDATORE";


// Set up a table to refer to your strings.

PROGMEM const char *string_table[] = 	   // change "string_table" name to suit
{   
  string_0,
  string_1,
  string_2,
  string_3,
  };

char buffer[30];    // make sure this is large enough for the largest string it must hold

void setup()			  
{
  Serial.begin(115200);
  for (int i = 0; i < 4; i++)
  {
    strcpy_P(buffer, (char*)pgm_read_word(&(string_table[i]))); // Necessary casts and dereferencing, just copy. 
    Serial.println( buffer );
    delay( 500 );
  }

}

void loop()			  
{
}

ok ... even if I do not understand what changes ... and right now I have no way of wanting to discover

but now I make all the literals in this way ... I solve my problem or not?

edit:
do not ask me why, but function as I did; if I enter any string into an array does not work... I have done so

PROGMEM const char *socketTypeGeneral[] = {"TEMPORIZZATA", "ACCESA", "SPENTA", "SONDATA", NULL};
int InputOutputI2C::readSelectedIndex(const char *query, const PROGMEM prog_char *options[]){
	char key = CHAR_NOT_INSERT;
	uint8_t i = 0, nArg = 0, select = 0, row = 0;
	bool timeout = false;
	while((char*) pgm_read_word(&(options[nArg])))
		nArg++;

	clearLcd();
	if(query)
		lcdPrint(query, row++);
	_secondsWithoutInput = 0;
	do{
		for(i = 0; i < _lcdRow - (query ? 1 : 0); i++){ //-1 perche' devo togliere la prima riga di "intestazione"
			clearLcdRow(row + i);
			if(i == 0) //solo la prima opzione ha ->
				lcdPrint("->", row);
			lcdPrint((char*) pgm_read_word(&(options[(select + i) % nArg])), row + i, 2);
		}

		// fino a che non scade il tempo scarto tutti i caratteri inseriti che non sono
		while(!timeout && ((key = readChar()) != ENTER && key != CANCEL && key != CURSOR_UP && key != CURSOR_DOWN))
			timeout = _secondsWithoutInput > MAX_SECOND_WAIT_INPUT_TIME;
		
		if(key == CURSOR_UP)
			select = (nArg + select - 1) % nArg;  //nArg perche' le opzioni sono nArg; devo sommarlo perche' -1 % nArg e' corretto, ma io voglio solo valori positivi
		else if(key == CURSOR_DOWN)
			select = (select + 1) % nArg;  //nArg perche' le opzioni sono nArg
	}while(key != ENTER && key != CANCEL && !timeout);
	return ((key == ENTER) ? select : ((key == CANCEL) ? CANCELED : TIME_OUT));
}

I tried it with several sets of options and goes (if not put them in an array as the example you posted)

But in tow point continues to restart the sketch ... I can not understand why ...
But in broad outline seems to go better... although it continues to restart and I would like to solve this problem ...

the function is that

void makeSocket(uint8_t indexSocket){
  uint8_t socketType = TURNED_OFF, row = 0;
  int8_t n = 0, sel = 0, sel2 = 0;
  short on = 0, off = 0;
  float th = 0.0;
  char str[] = ") LA PRESA E'";
  char query[strlen(str) + 3]; // + 2 perche' ci scrivo un numero massimo 255 (3 cifre) prima
  
  sprintf(query, "%d%s", indexSocket, str);
  switch((sel = IO.readSelectedIndex(query, socketTypeGeneral))){
    case(0): case(1):
     if((sel2 = IO.readSelectedIndex(NULL, socketTypeTimed)) >= 0)
      socketType = sel2; //di default e' gia' TURNED_OFF
    break;
    case(3):
      if((sel2 = IO.readSelectedIndex(NULL, socketTypeProbed)) >= 0)
        socketType = HEATER_PROBED + sel2; //HEATER_PROBED + sel2 perche' sel2 e' lo "scostamento" dalla prima presa sondata
      if(socketType != TURNED_OFF){
        IO.clearLcd();
        typeSocketToString(socketType);
        IO.lcdPrint("SOGLIA = ", 1);
        th = IO.readFloat(9); // 9 = strlen("SOGLIA = ") ////////here is a point
      }
   break;
  }
  if(sock.setPowerSocket(indexSocket, socketType, th) == CORRECT){
    if(sel == 1)
      sock.setPowerSocketEverOn(indexSocket);
    else if(socketType != TURNED_OFF && sel == 0){
      IO.clearLcd();
      IO.lcdPrint("ACCENS (<=", 0);
      IO.lcdPrint((int) MAX_SOCKET_SWITCH);
      IO.lcdPrint(")");
      n = IO.readInt(MAX_SOCKET_SWITCH, 1); ///////here is the other point
      IO.clearLcd();
      for(int i = 0, row = 0; i < n; i++){
        if(row == LCD_ROW){
          IO.clearLcd();
          row = 0; 
        }
        IO.lcdPrint("ON  ", row++);
	IO.lcdPrint(i + 1);
	IO.lcdPrint(" = ");
	on = IO.readTime(9);
	IO.lcdPrint("OFF ", row++);
	IO.lcdPrint(i + 1);
	IO.lcdPrint(" = ");
	off = IO.readTime(9);
	sock.addTime(indexSocket, ((on == TIME_OUT) ? 0 : on), ((off == TIME_OUT) ? 0 : off));
	}
    }
  }
}
float InputOutputI2C::readFloat(uint8_t column){
	float f = 0.0;
	unsigned char key = CHAR_NOT_INSERT;	
	_secondsWithoutInput = 0;	
	lcdPrint("0.00", _currentLcdRow, column);
	do{
		if((key = readChar()) != CHAR_NOT_INSERT && key != ENTER){
			if(key == CANCEL)
				f = ((float) ((int) (f * 100))) / 1000; // il doppio cast (prima ad int e poi e float) serve per eliminare le cifre decimali che sballano il risultato
			else if(((float) ((int) (f * 1000 + (key - '0')))) / 100 > 99.99){
				lcdPrint(((float) ((int) (f * 1000 + (key - '0')))) / 100, _currentLcdRow, column + 3); //3 = ">> "
				delay(DELAY_FOR_INCORRECT_INSERT_VALUE);
			}else
				f = ((float) ((int) (f * 1000 + (key - '0')))) / 100;
			clearLcdRow(_currentLcdRow, column);
			lcdPrint(f, _currentLcdRow, column);
		}
	}while(!(key == ENTER) && _secondsWithoutInput <= MAX_SECOND_WAIT_INPUT_TIME);
	return ((key == ENTER) ? f : (float) TIME_OUT);
}
int InputOutputI2C::readInt(int maxIn){
	char key = CHAR_NOT_INSERT, oldK = CHAR_NOT_INSERT; // serve per vedere se vuole cancellare l'input o no
	int digit = 0;

	_secondsWithoutInput = 0;
	clearLcdRow(_currentLcdRow);
	lcdPrint(">> 0", _currentLcdRow, 0);
	lcdSetCursor(_currentLcdRow, 3);
	do{
		if((key = readChar()) != CHAR_NOT_INSERT && key != ENTER){ // finche' non c'e' un carattere in ingresso (e che non sia ENTER)
			oldK = key;
			if(key == CANCEL){
				clearLcdRow(_currentLcdRow);
				lcdPrint(">> ", _currentLcdRow);
				lcdPrint((digit /= 10));
				if(digit == 0)
					lcdSetCursor(_currentLcdRow, 3);
			}else if((digit * 10 + (key - CHAR_ZERO)) <= maxIn){
				if((digit = digit * 10 + (key - CHAR_ZERO)) > 0)  //nel caso prima fosse 0 e venisse immesso uno 0
					lcdPrint(key - CHAR_ZERO);
			}else{
				lcdPrint(key - CHAR_ZERO);
				delay(DELAY_FOR_INCORRECT_INSERT_VALUE);
				clearLcdRow(_currentLcdRow);
				lcdPrint(">> ", _currentLcdRow);
				lcdPrint(digit);
			}
		}
	}while(key != ENTER && _secondsWithoutInput <= MAX_SECOND_WAIT_INPUT_TIME);
	//fintanto che il penultimo carattere e' == '*' (cancella input). L'ultimo e' '#'
	return ((key != ENTER) ? TIME_OUT : ((oldK == CANCEL) ? CANCELED : digit));
}

Your strings have to be individually assigned

That's one thing I hate about PROGMEM, I think there are two ways around it, first is to use a single comma (or whatever) delimited string

PROGMEM const char *socketTypeProbed[] = {"RISCALDATORE SONDATO,ELETTR. REATTORE SONDATA"};

And copy it to RAM and chop it up when needed. If there is only a single massive string then this still uses RAM so you are no better off, but if it's 10 medium-sized strings it makes sense.

But also I have put stuff into a struct with fixed-length arrays

typedef struct peripheral {
	char	name[10];
	int		addresses [20];

PROGMEM static peripheral peripherals [] = {
	{"PORTB",	{0x36,0x37,0x38,0xFFFF}},
	{"PORTA",	{0x39,0x3A,0x3B,0xFFFF}},
	{"TMR0",	{0x35,0x53,0x52,0x34,0x33,0x32,0x59,0x58,0xFFFF}},
	{"TMR1",	{0x20,0x50,0x4F,0x47,0x46,0x49,0x4E,0x45,0x4D,0x4C,0x4B,0x4A,0x59,0x58,0x44,0xFFFF}},
	{"USI",		{0x2F,0x30,0x2E,0x2D,0x31,0xFFFF}},
	{"AC",		{0x28,0x29,0x21,0x22,0xFFFF}},
	{"ADC",		{0x26,0x25,0x24,0x27,0x23,0x21,0x22,0xFFFF}},
	{"EEPROM",	{0x3C,0x3D,0x3E,0x3F,0xFFFF}},
	{"MCU",		{0x5A,0x5B,0x51,0x48,0x55,0x44,0xFFFF}}
};

That works and presumably the struct can have any elements you like. The catch is I think that the arrays have to be fixed length, you can't have an array of pointers to PROGMEM strings without going back to individually declaring every string (AFIAK).


Rob

I think the problem with PROGMEM arrays of strings is that if you use the keyword PROGMEM you force the array to be in program memory, but not what it is pointing to. There must be a way, I haven't found it yet.

For example:

PROGMEM const char *socketTypeTimed[] = {"LUCE", "POMPA", "FILTRO", "RISCALDATORE", "RISALITA", "SKIMMER",
          "VENTOLE", "REFRIGERATORE", "MANGIATOIA", "VENT. MOBILE", "LUCE LUNARE", "REATTORE", "KALKWASSER", "ELETTROV. REATTORE",
          "ELETTROV. VASCA", "RABBOCCO VASCA", "RABBOCCO SUMP", "ALTRO", "SPENTA", NULL};

The pointers are in progmem, but not the data. That is, a pointer to "LUCE" is in progmem, but "LUCE" is not. That's the problem.

From the fact that the Playground site does not recommend anything less tedious, I can only assume that greater minds than mine have looked at it, and been unable to solve it.

Graynomad's approach may well be a simple solution.

this is a reasonable ground! (which would also explain why the sketch is still wrong)

But I do not understand how come with the latest version of readSelectedIndex does not work with the "Matrix" but with the carrier single ...
how do you suggest to modify it to work with arrays?

Another solution might be to create a string given by the concatenation of the other, copy with the strcpy (when needed) and partitioned with the strtok ...
or always keep this string with separators and make a strchar and printing from the initial point to the symbol ... perhaps save all pointers in an array beginning of the line ...
The second solution is certainly more expensive in terms of time (although it is O(n ))... the first is perhaps more intuitive, but you copy from a literal PROGMEM variable automatic whenever you need it ... there is to see if you have no space?
(both solutions are along the lines of a proposed solution above ...)

or else try to make a script ...

I've done as you said but nothing's going...

Well, since you're the one with all the gear, you're going to have to break it down until it does work.
Maybe put some debug prints in, or if you're too short of RAM, some LED blinking code, but make sure you debug that thoroughly before merging it with your code.

Brig:
I've done as you said but nothing's going...

I agree with AWOL that the best way is usually some debugging (eg. a spare pin with an LED on it). If you are still having problems you need to post the revised sketch.

Unfortunately, there isn't a debugger like gdb or that of java ...

the only thing you can do are the prints (which of course I put it) ... but at least I can not make sense of anything ...

Unfortunately I tried the code on the PC (by changing the IO Libraries "low level") and it works ...
or so the bug is in library code (copied from a working ...) but I tried it myself and it worked ... or I don't know...
will post more than code ...