void loop() keep looping while functions run

Hello,

Im new to Arduino but I do have some programming experience.

And I have a question regarding the standard loop.

Sample code:

void loop()
{
functA();
functB();
}

void functA()
{
//some code which takes 5 seconds to run
}

void functB()
{
//some code which takes 1 seconds to run
}

When the loop starts it will obviously first run functA(); and then start functB();
The thing is that functB(); will be started after 5 seconds and keeps being started after an interval of 5 seconds.

What I want to accomplice is that functB(); keeps running every 1 second and not being slowed down by functA();

Is there a way to do this?

Thanks!

Don't use delay() in your functions and take a look at the Blink Without Delay example.

Hi Arrch,

Thanks for your reply.

The delay is not caused by delay(). I send an ICMP ping to a host and once the host goes offline it will timeout.. this timeout takes around 5 seconds. So once the host is online the function will run in 1 second but when it it's offline it will take 5 seconds.

It would be nice to run the functions asynchronous.

The delay is not caused by delay().

Can you post the "some code" please?

Sure, I found code on the Internet that I use and modify to my needs:

/*
Repeatedly ping a number of servers and output the response to serial and pins 2,3,4

pin 2: ping request sent
pin 3: ping response received
pin 4: ping response not received

This software requires the ICMPPing library, available at

http://www.blake-foster.com/projects/ICMPPing.zip

Portions of this code were derived from code available at

http://www.blake-foster.com/project.php?p=44

My thanks go to Blake for his hard work.

If you do not wish to output to the serial port, comment out the line
#define serialOut 1
If you do not wish to output to the LEDs, comment out the line
#define ledOut 1

The lines
byte ip[] = {192,168,0,177}; // ip address for ethernet shield
byte pingAddr[8][4] = { {91,121,5,142}, {91,121,5,143}, {91,121,5,144}, {91,121,5,145}, {91,121,5,146}, {91,121,5,147}, {91,121,5,148}, {91,121,5,149} }; // ip address to ping

need to be changed to suit your own needs. If your network has DHCP the arduino
will automatically grab an IP address for itself.
*/

#include <SPI.h>
#include <Ethernet.h>
#include <ICMPPing.h>

byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED}; // mac address for ethernet shield
byte ip[] = {172,16,0,60}; // ip address for ethernet shield
byte pingAddr[1][4] = { {172,16,0,112}};
int numAddresses = 1; //sizeof(pingAddr[0]);
bool deviceFound = false;
int lampCountdown = 10;

SOCKET pingSocket = 0;

char buffer [256];

int delayMS = 1 * 1000; // check every 1 seconds (delay between successive pings (60 * 1000 = 60 seconds))

#define serialOut 1
#define ledOut 1

#ifdef ledOut
	#define ledPing 2
	#define ledOk 3
	#define ledFail 4
	#define lamp 5

	void startPing()
	{
		digitalWrite(ledPing, HIGH);
	}

	void endPing()
	{
		digitalWrite(ledPing, LOW);
	}

	void pingSuccess()
	{
		deviceFound = true;

	}

	void pingFail()
	{
		deviceFound = false;
		
	}
#endif

void setup()
{
	#ifdef ledOut
		pinMode(ledPing, OUTPUT);
		pinMode(ledOk, OUTPUT);
		pinMode(ledFail, OUTPUT);
		pinMode(lamp, OUTPUT);

		// initialising, turn all LEDs on
		digitalWrite(ledFail, HIGH);
		digitalWrite(ledOk, HIGH);
		digitalWrite(ledPing, HIGH);
	#endif

	#ifdef serialOut
		// start serial port:
		Serial.begin(9600);
		Serial.println("Starting ethernet connection");
	#endif
	// start Ethernet
	if (Ethernet.begin(mac) == 0) {
		#ifdef serialOut
		Serial.println("Failed to configure Ethernet using DHCP");
		#endif
		// DHCP failed, so use a fixed IP address:
		Ethernet.begin(mac, ip);
	}
}

int i = 0;

void loop()
{
	pingDevice();

	if(deviceFound==true){
		lampCountdown=10;
		digitalWrite(ledFail, LOW);
		digitalWrite(ledOk, HIGH);
		digitalWrite(lamp, HIGH);
	}else{
		if(lampCountdown<=0){
			digitalWrite(lamp, LOW);
		}else{
			digitalWrite(ledFail, HIGH);
			digitalWrite(ledOk, LOW);
			Serial.print("Device not found: ");
			Serial.println(lampCountdown);
			lampCountdown--;
		}
	}
}

void pingDevice(){

	bool pingRet; // pingRet stores the ping() success (true/false)
	#ifdef ledOut
		startPing();
	#endif
	
	ICMPPing ping(pingSocket);
	byte pingAddr2[] = { pingAddr[i][0], pingAddr[i][1], pingAddr[i][2], pingAddr[i][3] };
	pingRet = ping(4, pingAddr2, buffer);
	
	#ifdef ledOut
		delay(250);
		endPing();
	#endif

	#ifdef serialOut
		Serial.print("i:");
		Serial.print(i);
		Serial.print(" ");
		Serial.println(buffer);
	#endif

	#ifdef ledOut
		if(pingRet) // Failure
			pingSuccess();
		else
			pingFail();
	#endif

	i++;

	if(i >= numAddresses)
		i = 0;
		delay(delayMS);
}

The delay is not caused by delay(). I send an ICMP ping to a host and once the host goes offline it will timeout.. this timeout takes around 5 seconds. So once the host is online the function will run in 1 second but when it it's offline it will take 5 seconds.

Ok, so let's rephrase. Take a look at the blink without delay example to run the second function every 1 second and ensure that neither function are blocking.

svh1985:
It would be nice to run the functions asynchronous.

If you want true multitasking, get a Propeller.

svh1985:
The delay is not caused by delay().

int delayMS = 1 * 1000; // check every 1 seconds (delay between successive pings (60 * 1000 = 60 seconds))

...

void pingDevice(){

...

  delay(delayMS);
}

The one-second delay there won't be helping.

Inside the library I guess you are using:

bool ICMPPing::waitForEchoReply()
{
	time_t start = millis();
	while (!W5100.getRXReceivedSize(socket))
	{
		if (millis() - start > PING_TIMEOUT) return false;
	}
	return true;
}

You may need to rework so that rather than looping until a timeout, you check and then return. In other words, handle timing-out a different way. Effectively this makes it asynchronous.

Thanks for your reply's.

I will try to implement these suggestions this weekeind and post my findings back here.

Cheers!