[SOLVED] "Multitasking" with an Arduino Mega?

I am working on a project in which I need a timer counting down. But I ALSO need to constantly be checking for key input from a keypad. In the setup, I have a while loop for the timer, using delays to count down one integer every second. I need to be able to check for keypad input while the loop is going on.

I cannot seem to find any other setup than the one I have done…I did kind of trap myself with the delay. I mean, the Mega has a TON of memory and processing power. It has to be able to handle multitasking, yes?

I have tried to understand using timers and milliseconds, but I cannot wrap my head around it. Any help would be greatly appreciated!

Read this:
http://www.gammon.com.au/forum/?id=12127

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

.

Try to avoid delays and while() loops. Make loop() run as fast as possible. It should run several thousand times per second. Most of those times, there's nothing to do: no inputs have changed and no timers have expired.

Sometimes it does something. Try to make that something short. Don't wait for the user to push a button - that's an input that the main loop should be checking.

Have a look at Several things at a time

...R

@ rowanaut20

Let us assume that we have the following two tasks:

  1. At the elapse of 200 mS time, we need to refresh '7-seg display unit' being driven by PORTD & PORTB.

  2. A switch (K1) is connected at APin-A0. It is to be sampled for close condition and then ignite built-in
    LED (L) of ArduinoUNO.

  3. Solution: (for one pass only)

        L1: Initiaize T1 to genertae 200 mS Time Tick
              Initialize others as needed (enable internal pull-up at A0-pin and etc.)
        L2:  if (TOV1 has occured)
                 Refresh Display 
        L3:  if (K1 is found closed)
                 Ignite LED (L)
        L4:  Halt
  1. Transform the Pseuod Codes of Step-3 into C codes and accommodate them in the Arduino
    void setup() {} and void loop() {} structures.

Switch delays and while loops and use Threads instead.

Arduino Thread

rezik:
Switch delays and while loops and use Threads instead.

How much overhead does that add on top of something simple like millis() as in Several Things at a Time?

...R

Try playing with this:

unsigned long currentMicros;

 unsigned long previousMicros;

 unsigned long elapsedTime;

 // Initial time to start, 00:00:00 with 0 years, 0 days. 

 // adjust as needed.

 byte hundredths;

 byte tenths;

 byte secondsOnes = 0;

 byte oldsecondsOnes;

 byte secondsTens = 0;

 byte minutesOnes = 0;

 byte minutesTens = 0;

 byte hoursOnes= 0;

 byte hoursTens = 0;

 void setup(){

 Serial.begin(115200); // make serial monitor match

 Serial.println ("Setup Done");

 }

 void loop(){

 currentMicros = micros();

 // how long's it been?

 elapsedTime = currentMicros - previousMicros;

 if ( elapsedTime >=10000UL){ // 0.01 second passed? Update the timers

 previousMicros = previousMicros + 10000UL;

 if (hundredths > 0){

 hundredths = hundreths - 1; // decrement

 }

 else {

 hundredths = 9; // else rollover and decrement next digit, ripples thru: 23:59:59:99

 if (tenths >0){

 tenths = tenths-1;

 }

 else {

 tenths = 0;

 if (secondsOnes > 0){

 secondsOnes = secondsOnes - 1;

 }

 else {

 secondsOnes = 9;

 if (secondsTens >0){

 secondsTens = secondsTens -1;

 }

 else {

 secondsTens = 5;

 if (minutesOnes >0){

 minutesOnes = minutesOnes -1;

 }

 else {

 minutesOnes = 9;

 if (minutesTens >0 ){

 minutesTens = minutesTens -1;

 }

 else {

 minutesTens = 5;

 if (hoursOnes >0){

 hoursOnes = hoursOnes - 1;

 }

 else {

 hoursOnes = 9;

 if (hoursTens >0){

 hoursTens = hoursTens -1;

 }

 } //hoursTens rollover check

 } // hoursOnes rollover check

 } // minutesTens rollover check

 } // minutesOnes rollover check

 } // secondsTens rollover check

 } // secondsOnes rollover check

 } // tenths rollover check

 } // hundredths rollover check

 } // hundredths passing check

 if (oldSecondsOnes != secondsOnes){ // show the elapsed time

 oldSecondsOnes = secondsOnes;

 Serial.print(hoursTens);

 Serial.print(hoursOnes);

 Serial.print(":");

 Serial.print(minutesTens);

 Serial.print(minutesOnes);

 Serial.print(":");

 Serial.print(secondsTens);

 Serial.println(secondsOnes);

 } // end one second check

 // MOST PROGRAM TIME WILL BE SPENT BETWEEN THESE 2 LINES, the above will take very little time to execute every 10milliseconds

 } // end loop

(Looks much better with CTRL-T in the IDE, I had it saved and the forum threw away all the formatting)

rowanaut20:
See my edit of the original post for what I did.

Please don't make changes to earlier Posts (apart from correcting typos) as it destroys the chronology of the Thread and someone reading it at a later date cannot learn from your experience.

If it is possible to restore the Original Post and add the new stuff after this it would be good.

...R

Wooooo! I managed to solve my problem. I set up a combination of a few answers, and came up with a hacky method of doing this.

void loop(){
  
while ((endtime - starttime) <=1000)
{
   sevseg.setNumber(join(join(numCode,numCode2),join(numCode3,numCode4)),2);
   sevseg.refreshDisplay();
   keycheck();
   endtime=millis();
}
    a-=1;
   lcd.setCursor(0,1);
   lcd.print("       ");
   lcd.print(a);
   lcd.print(" ");
   tone(buzzer, 1000, 100);
   starttime = millis();
   endtime = starttime;
   if(a<=1) endgame();

  
}

Thanks to everyone who responded to this thread :slight_smile:

rowanaut20:
I cannot seem to find any other setup than the one I have done...I did kind of trap myself with the delay. I mean, the Mega has a TON of memory and processing power. It has to be able to handle multitasking, yes?

Just jumping on this point here, a Mega actually doesn't have any more processing power than an Uno. It has more IO, peripherals, and memory, but the CPUs are clocked the same.

a Mega actually doesn't have any more processing power than an Uno.

And that's why you don't stay up really late programming, get frustrated, and write a question. I don't even know why I said that. But thanks for clarifying! :3

Jiggy-Ninja:
a Mega actually doesn't have any more processing power than an Uno. It has more IO, peripherals, and memory, but the CPUs are clocked the same.

The Mega is even a little slower, because it has to handle longer addresses on calling and returning.

Whandall:
The Mega is even a little slower, because it has to handle longer addresses on calling and returning.

That would make sense. Although, I'd imagined it's just a few milliseconds slower, really. I think the memory makes up for the lost speed, though.

rowanaut20:
Although, I’d imagined it’s just a few milliseconds slower, really.

Microseconds

…R

The Mega is even a little slower, because it has to handle longer addresses on calling and returning.

  1. ArduinoUNo uses Atmega328 chip with Flash Space : 0x0000 - 0x3FFF (word address).
    (a) During SUR/ISR call, the MCU saves 2-byte data (the value of Return Address) onto stack.
    (b) While returning from SUR/ISR, the MCU retrieves return address (2-byte) from stack.
    (c) Let us assume that this stack handling time is t1.

  2. ArduinoMEGA uses Atmega2560 with Flash Space : 0x000000 - 0x01FFFF (word address).
    (a) During SUR/ISR call, the MCU saves 3-byte data (the value of Return Address) onto stack.
    (b) While returning from SUR/ISR, the MCU retrieves the return address (3-byte) from stack.
    (c) Let us assume that this stack handling time is t2.

  3. t2 > t1; this is what has been concisely indicated by Whandall.

rowanaut20:
I have tried to understand using timers and milliseconds, but I cannot wrap my head around it. Any help would be greatly appreciated!

You can use my millisDelay library
https://www.forward.com.au/pfod/ArduinoProgramming/TimingDelaysInArduino.html
or Coding Timers and Delays in Arduino : 7 Steps - Instructables

and for multitasking I have recently published a detailed tutorial for Uno/Mega (and ESP32)
https://www.forward.com.au/pfod/ArduinoProgramming/RealTimeArduino/index.html
or Simple Multitasking in Arduino on Any Board : 12 Steps (with Pictures) - Instructables

that is very simple to program and does not require the use of an RTOS library.