Performing 2 routines at the same time

Hello, I would like to ask for your guidance.

I have searched online about "multi-threading" for Arduino, and based on what I've read, that is not possible. But there's an alternative. http://forum.arduino.cc/index.php/topic,5686.0.html

The code below was given by dmesser in that thread.

#define ledPin1 11
#define ledPin2 12

#define led1Cycle 100U
#define led2Cycle 275U

unsigned long led1LastMillis = 0;
unsigned long led2LastMillis = 0;

boolean led1State = false;
boolean led2State = false;

boolean cycleCheck(unsigned long *lastMillis, unsigned int cycle) 
{
  unsigned long currentMillis = millis();
  if(currentMillis - *lastMillis >= cycle)
  {
    *lastMillis = currentMillis;
    return true;
  }
  else
    return false;
}

void setup()
{
  pinMode(ledPin1, OUTPUT);
  pinMode(ledPin2, OUTPUT);
}

void loop()
{
  if(cycleCheck(&led1LastMillis, led1Cycle))
  {
    digitalWrite(ledPin1, led1State);
    led1State = !led1State;
  }
  if(cycleCheck(&led2LastMillis, led2Cycle))
  {
    digitalWrite(ledPin2, led2State);
    led2State = !led2State;
  }
}

How do I determine this two #define led1Cycle 100U, #define led2Cycle 275U? I have an alarm clock project. I want to use the toneAC library. Unfortunately, the delay with the toneAC is about 4 seconds which lags the display by 4 seconds. I want both function (playing the toneAC, and displaying the time) to be executed almost simultaneously.

Btw, I am using the toneAC_demo sample code. Below is the fragment of my code

{
		display_time(seconds,minutes,hours);
		display_date(day,date,month,year);
		delay(300);
		if (hours==alarmHours && minutes==alarmMinutes&&seconds==alarmSeconds){
			alarmLength = 1;/
			temp = minutes;
			Serial.println("ALARM TIME!!!");
		}
		//Serial.println(A0);
		//Serial.println(A1);
		
		if ((alarmLength > 0 && alarmLength < 31 && temp!=minutes)){
			temp = minutes;
			alarmLength++;
			Serial.println("ALARM TIME!!!");
			Serial.println(alarmLength);
		}
		if ((alarmLength > 0 && alarmLength < 31))
		{
			Serial.println(A3);
			if((digitalRead(A3) == LOW))
			{
				//digitalWrite(A2,HIGH);
				play_alarm();
				digitalWrite(A0,HIGH);
				digitalWrite(A1,HIGH);
			}
			else
			{
				digitalWrite(10,LOW);
				digitalWrite(A0,LOW);
				digitalWrite(A1,LOW);
			}
		}
		else
		{
			digitalWrite(10,LOW);
			digitalWrite(A0,LOW);
			digitalWrite(A1,LOW);
		}
	}
-------
void play_alarm(){
	for (unsigned long freq = 125; freq <= 15000; freq += 10) {  
		toneAC(freq); // Play the frequency (125 Hz to 15 kHz sweep in 10 Hz steps).
		delay(1);     // Wait 1 ms so you can hear it.
	}
	toneAC(); // Turn off toneAC, can also use noToneAC().

	delay(300); // Wait a second.

	for (int thisNote = 0; thisNote < 8; thisNote++) {
		int noteDuration = 1000/noteDurations[thisNote];
		toneAC(melody[thisNote], 10, noteDuration, true); // Play thisNote at full volume for noteDuration in the background.
		delay(noteDuration * 4 / 3); // Wait while the tone plays in the background, plus another 33% delay between notes.
	}
}[/code

How do I determine this two #define led1Cycle 100U, #define led2Cycle 275U?

They are the lengths of time between steps of the two cycles.

to be executed almost simultaneously.

This statement, and this code:

		delay(300);

just don't go together. There is no reason that you need this stupid delay(), if you write your code properly. Read the blink without delay example. Understand it. Embrace it, and you won't ever use delay() again.

		if (hours==alarmHours && minutes==alarmMinutes&&seconds==alarmSeconds){

Somepeopleunderstandtheuseofthespacebar,too. And, even embrace it.

		if ((alarmLength > 0 && alarmLength < 31 && temp!=minutes)){

Why are there two sets of parentheses that enclose EXACTLY the same stuff?

	delay(300); // Wait a second.

Useless comments should at least be correct useless comments.

They are the lengths of time between steps of the two cycles.

I am bothered with the U, 100U and 275U. What are those?

Why are there two sets of parentheses that enclose EXACTLY the same stuff?

Didn't notice. Sorry. There's another condition there before that's why there are 2 sets of parentheses there. I forgot to remove one of them.

Useless comments should at least be correct useless comments.

I copy-pasted the code from the toneAC_demo. It was originally 1 second. I just modified it to 300ms. Sorry.

I am bothered with the U

It's a suffix that means unsigned. The compiler generates somewhat different code to deal with signed and unsigned data, and generates a warning if signed and unsigned values are compared. 100 is a signed value. 100U is an unsigned value.

I developed this based on techniques the blinkwithoutdelay example. It flashes 2 pairs of LED's (in each pair one led is on and the other is off) and also waxes and wanes a further pair - as one led gets brighter, the other gets dimmer.

I called it "DoLots" because I want to see how much stuff I can cram into a single sketch, just for fun! But at present it does 3 things. Had intended to include making a stepper motor go back and forth but the stepper library seems to have the equivalent of a "delay" somewhere while the motor is running.

I have "functionised" and Boolean versions of this lot somewhere .. losing track of all my experiments!

/* 
Do lots of stuff to see how the timing goes
V01 = 2 pairs of flashing LEDS, at different intervals
RESULT - Pins 6 and 8 work, but pin 2 stays on and pin 4 does not come on
CURE - FIX STATE SETTINGSS!

V02
  Add in led3 with varying intensity
  
V03
  Add in second led (led5) with varying intensity, brightness inverse of the other one!
  RESULT: Works nicely thankyou. Compilation size 1652 bytes
  
V03b
  Alternative code for led3/5 bounds checking
  RESULT:
    Compile size with bounds checking removed = 1,614 bytes from 1652, with new bounds checking becomes 1,680
    Still works nicely but generates more code
    Removal of doubling-up of offset comes down to 1676 bytes, fade "changeover" looks a tiny bit smoother for the resultant pause
  
 

 */

// CONSTANTS DECLARATIONS
  const int led2Pin =  2;      // set pin numbers for digital outputs:
  const int led3Pin =  3;
  const int led4Pin =  4;
  const int led5Pin =  5;
  const int led6Pin =  6;
  const int led8Pin =  8;
  
  const int maxBrightness = 255;      // Max intensity of led
  
  long led2interval = 500;     // interval at which LED 2 & 4 to blink (milliseconds)
  long led6interval = 500;     // interval at which LED 6 & 8 to blink (milliseconds)
  long led3interval = 50;     // interval at which LED 3 brightness is adjusted(milliseconds)

// VARIABLES DECLARATIONS
  int led2State = LOW;         // ledStates used to set the LEDs
  int led4State = LOW;
  int led6State = LOW;
  int led8State = LOW;
  
  int led3brightness = 5;           //Brightness for led3 led5 will be inverse of this
  int led5brightness = 255;           //Brightness for led3 led5 will be inverse of this
  int brightnessincrement = 10;     //Incremental value for brightness. Coding caters for any value even if not divisible into 255  

  unsigned long currentMillis = 0; // Storage of timing info
  long led2previousMillis = 0;
  long led3previousMillis = 0;  
  long led6previousMillis = 0;


// INITIALISATION
void setup() 
{
  pinMode(led2Pin, OUTPUT);   // set the digital pins as output:
  pinMode(led4Pin, OUTPUT);
  pinMode(led6Pin, OUTPUT);
  pinMode(led8Pin, OUTPUT);
}

void loop()
{
// MAIN LOOP - START

//Store current timing
  currentMillis = millis(); 
 
// Check and switch LED2/LED4
  if(currentMillis - led2previousMillis > led2interval) 
    {
    led2previousMillis = currentMillis;    //Store new time   
    if (led2State == LOW)                      //If the LED is off turn it on and vice-versa:
      {
      led2State = HIGH;
      led4State = LOW;
      }
    else
      {
      led2State = LOW;
      led4State = HIGH;
      }
    digitalWrite(led2Pin, led2State);
    digitalWrite(led4Pin, led4State);
    }

// Check and switch LED6/LED8
  if(currentMillis - led6previousMillis > led6interval) 
    {
    led6previousMillis = currentMillis;    //Store new time   
    if (led6State == LOW)                      //If the LED is off turn it on and vice-versa:
      {
      led6State = HIGH;
      led8State = LOW;
      }
    else
      {
      led6State = LOW;
      led8State = HIGH;
      }
    digitalWrite(led6Pin, led6State);
    digitalWrite(led8Pin, led8State);
    }

// Check and adjust LED3/LED5 brightness
  if (currentMillis - led3previousMillis > led3interval)
    {
      led3previousMillis = currentMillis;    //Store timing      
      analogWrite(led3Pin, led3brightness);  //Ajust led3 brightness from preps on previous pass
      analogWrite(led5Pin, led5brightness);  //Ajust led5 brightness

      led3brightness = led3brightness + brightnessincrement;         // Increase brightness value for led3 for next time around
      led5brightness = -(led3brightness - 255);                      // Should always have pos or 0 value for led3 giving -ve val for led5, needs negating

                                                                     // Prepare for next time around

       if (led3brightness <= 0 || led3brightness >= 255)             //If brightness will go <= 0 or >= 255 negate the increment
          {brightnessincrement = -brightnessincrement;              // ...Negate the increment
           led3brightness = led3brightness + (brightnessincrement*2);  // ... and re-apply it(twice to ensure it moves on this steprather
           led5brightness = -(led3brightness - 255);}                                                           // than remaining static          
    }
    
//END OF MAIN LOOP
}

but the stepper library seems to have the equivalent of a "delay" somewhere while the motor is running.

The AccelStepper library doesn't. Get busy.

if(currentMillis - led2previousMillis > led2interval)

">="
Your code would be a lot shorter and easier to read if you used arrays.

AWOL:

if(currentMillis - led2previousMillis > led2interval)

Your code would be a lot shorter and easier to read if you used arrays.

Thank you for your input. One of the benefits I've found of no longer developing software professionally is that I can experiment with and lay out my code as I feel without constraints or the need to consider maintenance by others further down the line, and within the limitations of what I currently know about the particular language! :wink:

PS it must be almost a week now since I wrote my first piece of C code ....