1
votes

I have a sensor connected to the arduino uno pin 5 and it reads the sensor value every second and send out a sms every 1 minute. This works.

void loop() {
// read_sensor_and_store(5);
// increment_time_counter();
// if_time_counter is 60000 miliseconds then send the sms
delay(1000);
}

While this works, I want to call another function, say, read_another_sensor(pin, delay_0, count). What this will do is read the particular pin 'count' number of times with delay of 'delay_0'. (baically it will run a for loop with the given delay).

Now if I have something like this

void loop() {
// read_sensor_and_store(5);
// read_another_sensor(7, 2000, 4);
// increment_time_counter();
// if_time_counter is 60000 miliseconds then send the sms
delay(1000);
}

This too will work but while executing the read_another_sensor() the time will elapse and I will miss few readings of pin 5. Is there a way to execute these two functions in parallel or any other way to achieve the objective of "calling of read_another_sensor will not affect the continuous periodic functionality of read_sensor_and_store"

Appreciate any insight on this matter. Thank you

2

2 Answers

2
votes

Extending the answer of the user above, you can do something like this to allow you to spawn sensor2 task with arbitrary (multiply of 50 mili) periods:

const int ONE_SECOND = 1000;
const int ONE_MINUTE = 60*ONE_SECOND;

// 50 mili - has to be upper bound of total execution time
//           has to be [GCD][1] of periods of all your tasks
const int BASIC_PERIOD = 50; 

// FRAMES*BASIC_PERIOD has to be [LCM][2] of periods of all your tasks
const int FRAMES = ONE_MINUTE / BASIC_PERIOD; 

void read_another_sensor(delay_0, count) { 
    g_delay = delay_0;
    g_count = count;
}

...

void loop() {

    if ((unsigned long)(millis() - previousMillis) >= BASIC_PERIOD) {
        previousMillis = millis();

        frame_counter = (frame_counter + 1) % FRAMES;
 
        if (frame_counter == 0)
           send_sms();
        if frame_counter % ((FRAMES * BASIC_PERIOD) / ONE_SECOND) == 0
           read_sensor();
        if frame_counter % ((FRAMES * BASIC_PERIOD) / g_delay) == 0
            if (count > 0) {
               count--;
               read_sensor_2():
            }
        }
    }
}

If you need to use more periodic tasks with periods that are not multiply of 50 mili, your system becomes complex wor have high rate of deadline misses, please read about "cyclic executives".

GCD

LCM

0
votes

In general you can replace delay(1000) with a timestamp comparing code to reach your goal. The code construction (see below) is often used if one function needs to executed in an different interval than others or if you want to combine sketches. There are already several sources on the web and stackoverflow (e.g. see arduino-combine-sketches).

unsigned long interval=1000;  // the time we need to wait
unsigned long previousMillis=0; // millis() returns an unsigned long.

void setup() {
//...
}

void loop() {
 if ((unsigned long)(millis() - previousMillis) >= interval) {
 previousMillis = millis();
 // ... 
 }
}
//...

So in your case you need something like the following code, that I have not tested, but hopefully gives you an idea how you can manage the functions without delay():

unsigned long interval=1000;  // the time we need to wait (read_another_sensor)
unsigned long previousMillis=0; // millis() returns an unsigned long.


void setup() {
//...
}

void loop() {

 // every 1000 millisecs (=delay(1000))...
 if ((unsigned long)(millis() - previousMillis) >= interval) {
    previousMillis = millis();
    read_another_sensor();
    //...
 }

 read_sensor_and_store() // continuous periodic 
 // ... 

}