Arduino Mega multi-Tasking

I am trying to control the neck of a robot on 2 axis: heading and Pitch. A stepper moves the heading, and a DC motor moves the pitch.

The feedback is provided by potentiometers. I verified with the scope that the Mega can generate one Tone and one PWM in the same time .

However when I put it all in an If - Else situation with Analog read feedback the Tone executes first and the PWM second. The neck moves only one one axis a the time... Not cool...
What to do?


void LookAhead_Combined () // will line up the Neck to the fwd axis
int Neck_Heading = analogRead (A3); //Feedback from the heading axis
int Neck_Pitch = analogRead (A0)/10; //Feedback from the pitch axis
int ErrorHeading = abs (Neck_Heading-470);


if ((Neck_Pitch > 57) && (Neck_Heading <= 460)) //Case1 Neck is top right -Facing it from the front
{ analogWrite (PWM_UP_PIN, 200);
analogWrite (PWM_DN_PIN, 0);
delay (100); // the delay only scatters the motion, but wont do it at the same time .
digitalWrite (DirPin, HIGH);
tone(TonePin, (1000+(ErrorHeading*100)));

else if ((Neck_Pitch < 54) && (Neck_Heading <= 460))
{ analogWrite (PWM_DN_PIN, 200);
analogWrite (PWM_UP_PIN, 0);
delay (100);
digitalWrite (DirPin, HIGH);
tone(TonePin, (1000+(ErrorHeading*100)));

multi tasking is possible , however it can only do one thing at a time, however its done very fast.
for a pwm output you set it to a value and until it needs another value you can do other things.
same for the stepper if the stepper has to move go from the loop to a function(change the pins)
and go back
200 steps means 5 milliseconds.
in the meantime a simple uno can do 5000 lines of program or a 1000 other tasks.

Delay blocks everything else from happening while it's in the delay - is that what's causing your problem?

You should rewrite that to check the time with millis(), instead of using delay(). See the blinkwithoutdelay example.

Thanks for the suggestions.

Here is what I'd like to happen:
The loop looks at the value from the pot Neck_Pitch, sees the error and starts the moving of the DC motor by activating one of the "analogWrite (PWM_UP_PIN, 200);"

Then, in a few MS, the loop moves to the command of the Stepper and starts the Stepper by providing Tone and flipping direction, according to the IF _Else.
for example: digitalWrite (DirPin, HIGH);
tone(TonePin, (1000+(ErrorHeading*100)));

Then in a few MS, the loop goes again to the Neck_Pitch, and applies the PWM as required....

This way , both motors move in the same time bring my robot head to a central location.

Here is what happens instead:

Only the Stepper part gets executed, and when the Stepper gets to the "do nothing area" then, the loop takes care of the DC motor PWM and brings it in the "do nothing area".

else // Do nothing area (Head of the robot is centered left and right and up and down)
digitalWrite (DirPin, LOW);
analogWrite (PWM_UP_PIN, 0);
analogWrite (PWM_DN_PIN, 0);

Both instructions are completed, but one at the time. I wish the loop would do a bit of both really fast...

Have a look at how "multi-tasking" is acheived in several things at a time.

You need to use the sme approach in your project - a little bit of each thing in every iteration of loop().


Thanks a lot, that helped. I put the 2 tasks in 2 different functions with a 50Ms delay between them, so they have time to execute before they move to the next one. It seems to work as expected.

Your example is great. I wish it could do a ramp up and down speed of the servo. Of course that is easy with "for" and "delay" but is there a way to ramp up without delay?


but is there a way to ramp up without delay?

Yes of course.
It's easiest if your code is organised as a state machine, so when your timer lapses, you increment/decrement your fade variable and bounds-check it.

I wish it could do a ramp up and down speed of the servo.

If you post your code I would have a better idea of what you are trying to do.