multitasking

So basically i want my program to run my stepper back and forth at the number of steps chosen in a loop but i also want my servo to be moving left and right constantly. It should be something easy to achieve but i am not really keen on that kind of commands. I tried using a while(1) statement but only the code in the statement was active (servo) and the rest (stepper) didn't happen. Thanks!

my code:

#include <Servo.h>
Servo myservo;
const int dirPin = 2;
const int stepPin = 5;
const int enablePin = 8;

const int stepsPerRevolution = 200;

void setup()
{
// Declare pins as Outputs
pinMode(stepPin, OUTPUT);
pinMode(dirPin, OUTPUT);

pinMode(enablePin, OUTPUT);
digitalWrite(enablePin, LOW);

myservo.attach(9);
myservo.write(45); // set servo to mid-point
delay(1000);
}

void loop()
{
// Set motor direction clockwise

while(1)
{
myservo.write(45);
delay(700);
myservo.write(135);
delay(700);
}

digitalWrite(dirPin, HIGH);

// Spin motor slowly
for(int x = 0; x < stepsPerRevolution; x++)
{

digitalWrite(stepPin, HIGH);
delayMicroseconds(1000);
digitalWrite(stepPin, LOW);
delayMicroseconds(1000);
}
delay(100);

// Set motor direction counterclockwise
digitalWrite(dirPin, LOW);

// Spin motor quickly
for(int x = 0; x < stepsPerRevolution; x++)
{

digitalWrite(stepPin, HIGH);
delayMicroseconds(1000);
digitalWrite(stepPin, LOW);
delayMicroseconds(1000);
}
delay(100);
}

Read a few subjects.

  1. How to use the Forum", "How to attach code etc".
  2. Read a topic named "How to do several things at the same time" by @Robin2

Never ever use delay(); at least not until you are aware of its evil negative side effects.


Read these discussions:

Multitasking:
Part 1:

Part 2:

Part 3:

nikolas550:
It should be something easy to achieve but i am not really keen on that kind of commands.

It is straightforward to achieve but I'm curious to know the kind of commands you are not keen on?

If you want a responsive program then don't use delay() or WHILE or FOR as they all block the Arduino until they complete. WHILE and FOR are fine if you know that they will complete in a few millisecs.

Have a look at how the code is organized in Several Things at a Time

Note how each function runs very briefly and returns to loop() so the next one can be called. None of the functions tries to complete a task in one call. And there may be dozens of calls to a function before it is actually time for it to do anything.

It also illustrates the use of millis() to manage timing without blocking. See Using millis() for timing. A beginners guide if you need more explanation.

...R

nikolas550:
I tried using a while(1) statement but only the code in the statement was active (servo) and the rest (stepper) didn't happen.

As you would expect, that completely confines the execution to that inescapable loop.

"while", "delay()" and use of "for" with large or unconstrained range are not useful in cooperative multitasking code - which is most of microcontroller work. :astonished:


Oh, and do read the instructions for posting here. :grinning:

I often use long duration for(see below) or while (while(1)) loops in a multi-threading or multi processing cooperative environment; such as using freeRTOS with a ESP32.

As one can see the code below is confined in a inescapable loop.

void DoTheBME280Thing( void *pvParameters )
{
  for (;;)
  {
    xEventGroupWaitBits (eg, evtDoTheBME280Thing, pdTRUE, pdTRUE, portMAX_DELAY ); //
    vTaskDelay( 2 );
    if ( !isnan(bme.readTemperature()) )
    {
      ePtr[0] = bme.readTemperature();
      ePtr[1] = bme.readPressure() / 133.3223684f; // mmHg
      ePtr[2] = bme.readHumidity();
      if ( MQTTclient.connected() ) // broker online, then send stuff
      {
        xSemaphoreTake( sema_MQTT_KeepAlive, portMAX_DELAY ); // do not send whiles keep alive is in progress and pause keep-alive during send
        MQTTclient.publish( topicInsideTemp, String(ePtr[0]).c_str() );
        vTaskDelay( 2 ); // gives the Raspberry Pi 4 time to receive the message and process
        MQTTclient.publish( topicInsideHumidity, String(ePtr[1]).c_str() );
        vTaskDelay( 2 ); // no delay and RPi is still processing previous message
        MQTTclient.publish( topicInsidePressure, String(ePtr[2]).c_str() );
        xSemaphoreGive( sema_MQTT_KeepAlive );
      }
    }
    //log_i( "DoTheBME280Thing high watermark %d",  uxTaskGetStackHighWaterMark( NULL ) );
  }
  vTaskDelete ( NULL );
}

Also, vTaskDelay is not a blocking delay, whiles this task is delaying for 2mS, other tasks in inescapable loops can be ran.

Idahowalker:
I often use long duration for(see below) or while (while(1)) loops in a multi-threading or multi processing cooperative environment; such as using freeRTOS with a ESP32.

That's not very practical for an Uno or Mega

...R

Robin2:
That's not very practical for an Uno or Mega

...R

I'm not arguing that with you.

This statement is incorrect, without qualifiers:

"while", "delay()" and use of "for" with large or unconstrained range are not useful in cooperative multitasking code -

.

In the code I posted, there is a infinite loop and a delay that runs in a multi-tasking environment. My delay and infinite for loop are very useful.

Also, using millis to do multiple things at the same time is a simulation of a RTOS/task scheduler and its in an infinite loop (loop()).

Idahowalker:
I often use long duration for(see below) or while (while(1)) loops in a multi-threading or multi processing cooperative environment; such as using freeRTOS with a ESP32.

(my emphasis)

Are we sure the OP is using such an environment?

TheMemberFormerlyKnownAsAWOL:
(my emphasis)

Are we sure the OP is using such an environment?

I am not arguing that with you.

So you are arguing that the blanket statement, without qualifiers,

"while", "delay()" and use of "for" with large or unconstrained range are not useful in cooperative multitasking code - which is most of microcontroller work.

is a correct statement?

I argue that the statement, blanket, without qualifiers, is incorrect.

There's a whole spectrum of microcontrollers, from ATTinys (and probably even smaller) to very advanced ARM-based devices (I'd even argue the Snapdragon in my phone is a microcontroller), with the oddball Tensilica architecture somewhere in-between, so if we're going to have to qualify all statements, we're going to see some very long answers to noob questions.
Or no answers at all.

Yes or no, is the statement as made, correct?

BTW
RTOS code with infinite loop and delay that runs on a MEGA:

void fSendOut_SEMAPHORE()
{
  Event_t  eventoutF;
  while (1)
  {
    Kernel.Ev_Receive(EVENT_F, uMT_ANY, &eventoutF);
    if ( sMessageToSend.length() >= 2 )
    {
      stream2Ptr->println( sMessageToSend );
      digitalWrite(byteUnoDataReady, HIGH);//TRIGGER RPi3 to read data
      Kernel.Tm_WakeupAfter( 50 );
      digitalWrite(byteUnoDataReady, LOW);//reset
      sMessageToSend = "";
      Kernel.Sm_Release( SEM_ID_01 ); // release a single SEMAPHORE token
    }
  }
}

I'm not arguing with you, I'm just asking if you're sure the OP is using anything other than a Uno/Micro/Nano

The guy is still at the stage of thinking pin numbers should be signed, so I think it unlikely s/he even even on nodding terms with any kind of RTOS.

I just don't want to have to write posts that need only a ten word answer, but twenty pages of Ts&Cs, when common sense suggests otherwise.

TheMemberFormerlyKnownAsAWOL:
I'm not arguing with you,

I'm just asking if you're sure the OP is using anything other than a Uno/Micro/Nano

So the statement is incorrect, right?

Idahowalker:
This statement is incorrect, without qualifiers:

while", "delay()" and use of "for" with large or unconstrained range are not useful in cooperative multitasking code -

Based on the code in the Original Post I think it was perfectly reasonable of me to make the assumption that the OP would be using an Arduino - most likely an Uno, nano or Mega. I take some trouble to write advice that matches what I believe to be the experience of the person seeking the advice.

For the same reason I think it was unreasonable of you to confuse the issue by introducing the irrelevancies of FreeRTOS and the ESP32.

If I had thought that the OP was using an ESP32 and that FreeRTOS was appropriate I probably would not have responded to this Thread.

...R

TheMemberFormerlyKnownAsAWOL:
... we're going to see some very long answers to noob questions.
Or no answers at all.

Robin2:
Based on the code in the Original Post I think it was perfectly reasonable of me to make the assumption that the OP would be using an Arduino - most likely an Uno, nano or Mega. I take some trouble to write advice that matches what I believe to be the experience of the person seeking the advice.

For the same reason I think it was unreasonable of you to confuse the issue by introducing the irrelevancies of FreeRTOS and the ESP32.

If I had thought that the OP was using an ESP32 and that FreeRTOS was appropriate I probably would not have responded to this Thread.

...R

And I did post a code example of running a RTOS with a MEGA, with infinate loops and a delay.

So the blanket statement, without qualifiers,

"while", "delay()" and use of "for" with large or unconstrained range are not useful in cooperative multitasking code - which is most of microcontroller work.

is, no matter the post qualifier spin, is incorrect?

Idahowalker:
This statement is incorrect, without qualifiers: .

In the code I posted, there is a infinite loop and a delay that runs in a multi-tasking environment. My delay and infinite for loop are very useful.

Also, using millis to do multiple things at the same time is a simulation of a RTOS/task scheduler and its in an infinite loop (loop()).

...but your environment is not a cooperative multitasking one, it is pre-emptive. That was the most important qualifier in the statement. Also imagine explaining how your code works, or trying to explain how to code in that environment, to an absolute beginner.

I doubt it is pre-emptive, but the voluntary yields are hidden.

I am impressed. :grinning: