function order in scketch

I apologize, the question may be trivial, but I have not yet found a clear answer: in my sketch I have some functions after Setup () and loop (), but some are not accepted and give this error:
GenIno:37: error: 'multStrCat' was not declared in this scope
the error disappears when the function is inserted before setup() and loop() .

best regards
John Rossati

Hello John

Can you post your code, please? Use code tags (the "#" button above the row of smileys).

Thanks

Ray

Chances are the preprocessor isn't identifying them as you are using some structures of types that it doesn't like. In these cases you will have to either move them to before they are called, or craft your own manual function prototypes.

Normally you'd have to do these things anyway, but the Arduino IDE teaches you some very bad habits by trying to let you define functions after you call them.

If you don't want to move all the code of your function ahead of setup( ) or loop( ) in your source file, you can include a function prototype for it, above them.

Like this

void myFunction( int a );      // this is the function prototype for the function that you will define later.

void setup( )
{
     // do stuff here
}

void loop( )
{
   int c=7 ;
   myFunction( c ) ;    //  calls myFunction

}

void myFunction( int b )
{
   // do stuff here
}

thanks to all

The code is cumbersome, it is generate from few directives interpreted by an PHP executable, I can easely deplace the functions before setup() like it seems suggest michinyon; therefore why only one function give error?
Here is the code:

/*
Arduino Script generator version 0.2.3 18 April 2013
Wed 11 June 2014 14:14:43 El Condor. Condor informatique - Turin

A0	watt
*/
#include "C:\Users\El Condor\Documents\Arduino\GenIno\defs.h"
#include <SPI.h>
#include <SD.h>
analogicPin watt = {0,0,0,0,(fnzPointerAnalogicPin) readWatt};
float readBattery(float C) {
return  C*5/(0.31224 *1024);
}
float readWatt(float C) {
return 0.4883*C;      // (5*100*C)/1024
}
char * place = "place=Cumiana%20Solar%20Check";
File ag_fileHandle;		// handle of file
//  geninoVariables
#define EVENT_COMMAND 1
#define EVENT_DISABLED 0
#define EVENT_START 1
#define EVENT_END -1
#define LENGTHWORKBUFFER 200
char workBuffer [LENGTHWORKBUFFER+1];
boolean ag_debug = true;

char ag_processor[] = "Arduino Uno";
//  cronVariables
volatile unsigned long cClock = 0;
int delayClock = 500;    // delay

cronStructure cron[] =  {{60000,0,0,1,0,(fnzPointer) handle_watt,"watt"},
	{300000,300000,0,1,0,(fnzPointer) handle_seeFile,"seeFile"},
	{0,0,0,0,0,NULL,NULL}};
void setup() {
	Serial.begin(9600);
	multStrCat("","3",1,"Solar Check");
	Serial.write(workBuffer,strlen(workBuffer));
	Serial.println("");

	//  SD
	pinMode(10, OUTPUT);
  	if (!SD.begin(4)) {Serial.println("initialization failed!");
    return;
  	}
  	Serial.println("initialization done.");

	ag_fileHandle = SD.open("panel.csv", FILE_WRITE);
	multStrCat(",","3",1,"&time,Cumiana,Start,Arduino");
	ag_fileHandle.write(workBuffer,strlen(workBuffer));
	ag_fileHandle.println("");
	ag_fileHandle.flush();

	ag_fileHandle.seek(0);		// rewrite
}
void loop() {
	//  handleCronEvents
	delay(croner());
}
void handle_watt(cronStructure cron) {
		watt.value = watt.compute(ag_ReadPin(watt,5));
		multStrCat("","31",2,"&time,Cumiana,Read,watt ",watt.value);
	Serial.write(workBuffer,strlen(workBuffer));
	Serial.println("");

		multStrCat(",","31",2,"&time,Cumiana,Read,watt",watt.value);
	ag_fileHandle.write(workBuffer,strlen(workBuffer));
	ag_fileHandle.println("");
	ag_fileHandle.flush();

	}
void handle_seeFile(cronStructure cron) {
		multStrCat("","3",1,"&time Read data");
	Serial.write(workBuffer,strlen(workBuffer));
	Serial.println("");

			ag_fileHandle.close();
			File myFile = SD.open("panel.csv");
			if (myFile) {
			// read from the file until there's nothing else in it:
			while (myFile.available()) {Serial.write(myFile.read());}
			myFile.close();
			} else {Serial.println("error opening test.txt");}
			ag_fileHandle = SD.open("panel.csv", FILE_WRITE);
	}
//  multStrCat
void multStrCat(char* glue,char* mask,int num, ... ) {
	workBuffer[0] = 0;
	va_list args;
	va_start (args, num );           // Initializing arguments to store all values after num
	for (int j = 0; j < num; j++ )  { // Loop until all data are added
		if(mask[j] == '0') {
			strcat(workBuffer,va_arg (args, char*));		
		} else if(mask[j] == '2') {
			strcat(workBuffer,va_arg (args, fnzReturnChar)());
		} else if(mask[j] == '3') {		// string
			String x = va_arg (args, char*);
			x.replace("&time",elapsedTime());
			x.toCharArray( (char *) workBuffer+strlen(workBuffer),x.length()+1);
		} else {
			float f = va_arg (args, double);
			strcat(workBuffer,floatToString(f));
		}
		if (j < num-1) strcat(workBuffer,glue);
	}
	va_end(args);                  // Cleans up the list
}
char * floatToString(float f) {
	static char buffer[20];
	dtostrf(f, 16, 2, buffer);
    String s = buffer;    
	s.trim();
    s.toCharArray(buffer, s.length());
	buffer[s.length()] = 0;
	return buffer;
}
//  cronFunctions
int croner() {     // condor interrupt service routine 
	unsigned long time = millis();
	for (int i=0;cron[i].name != NULL;i++) {
		if (cron[i].status != EVENT_DISABLED) {
			if (cron[i].next <= 0) {
				cron[i].fnzActions(cron[i]);
				if (cron[i].duration > 0 && cron[i].status == EVENT_START) {
					cron[i].next += cron[i].duration;    // set new timeout
					cron[i].status = EVENT_END;
				} else {
					if (cron[i].command == EVENT_COMMAND) {
						cron[i].status = EVENT_DISABLED;
					} else {
						cron[i].status = EVENT_START;
						cron[i].next += cron[i].every;    	// set new timeout
						if(cron[i].duration > 0) cron[i].next -= cron[i].duration;
					}
				}
			}
			cron[i].next -= delayClock;
		}
	}
	cClock += delayClock;
	int Delta = millis()-time;
	int Reimander = Delta % 500;
	delayClock = Delta + 500 - Reimander;	
	return 500-Reimander;
}
int ag_searchCommand(cronStructure a[],char * name) {	// search the action at command
	for (int i=0;a[i].name != NULL;i++) {
		if (strcmp(name,a[i].name) == 0&& a[i].command == EVENT_COMMAND) return i;
	}
	return -1;
}
char * Time(unsigned long ms) {	// from start time
	static char timeOfDay[9] = "00:00:00";
	int s = (ms/1000) % 60;
	long h = ms / 3600000;
	int m = (ms/1000 - h*3600)/60;
	timeOfDay[0] = 48+h/10;
	timeOfDay[1] = 48+h%10;
	timeOfDay[3] = 48+m/10;
	timeOfDay[4] = 48+m%10;
	timeOfDay[6] = 48+s/10;
	timeOfDay[7] = 48+s%10;
	return timeOfDay;
}
char * Time() {		// clock Time
	return Time(millis());
}
char * elapsedTime() {		// clock from start Time
	return Time(cClock);
}
unsigned long stringToULong(String s){
	char char_string[s.length()+1];
	s.toCharArray(char_string, s.length()+1);
	return atof(char_string);
}
//  ag_ReadPin
float ag_ReadPinT(float f) {return f;}	// tunnel
float ag_ReadPin(analogicPin sensor, int times) {
    if (sensor.OnOff > 0) {
		pinMode(sensor.OnOff, OUTPUT);
		digitalWrite(sensor.OnOff, HIGH);
		if (sensor.wait > 0) delay(sensor.wait);
	}
	float C = 0;
    for (int i=0;i <= times;i++) if (i > 0) C += analogRead(sensor.pin);	// discard first read
	if (sensor.OnOff > 0) digitalWrite(sensor.OnOff, LOW);
    return C/times;
}

Is it the only function with an ellipsis "..."?

void multStrCat(char* glue,char* mask,int num, ... ) {

yes

The preprocessor cannot handle variadic arguments at all. It has no clue what they are. You will have to either move the function or create your own prototype for it above where you first call it.

BTW, in the latest beta version of UECIDE this is handled properly :wink:

Test sketch:

void setup() {
}

void loop() {	
}

void foo(int a, ...) {	
}

Arduino-generated CPP file:

#line 1 "sketch_jun11a.ino"
#include "Arduino.h"
void setup();
void loop();
#line 1
void setup() {
}

void loop() {
}

void foo(int a, ...) {
}

UECIDE generated CPP file:

#include <Arduino.h>
#line 1 "untitled4.ino"
void setup();
void loop();
void foo(int a, ...);
#line 1 "untitled4.ino"
void setup() {
}

void loop() {
}

void foo(int a, ...) {
}

Thanks to all

important is know why this happens.

John Rossati