Go Down

Topic: void loop() keep looping while functions run (Read 910 times) previous topic - next topic

svh1985

Hello,

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

And I have a question regarding the standard loop.

Sample code:
Code: [Select]

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!

Arrch

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

svh1985

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.

Nick Gammon

http://www.gammon.com.au/blink

Quote
The delay is not caused by delay().


Can you post the "some code" please?
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

svh1985

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

Code: [Select]

/*
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);
}


Arrch

#5
Dec 20, 2012, 10:19 pm Last Edit: Dec 20, 2012, 10:24 pm by Arrch Reason: 1
Quote
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.


It would be nice to run the functions asynchronous.


If you want true multitasking, get a Propeller.

Nick Gammon


The delay is not caused by delay().


Code: [Select]

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.
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

Nick Gammon

Inside the library I guess you are using:

Code: [Select]

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.
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

svh1985

Thanks for your reply's.

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

Cheers!

Go Up