6 Motors doing different tasks at the same time

hi,

i can't get my head around this problem:

1x Arduino uno, 3 x L293D, 6 x Gearmotor

Motor1: run for (random) time, (random) speed, then stop and change direction, again run for (random) time, (random) speed
at the same time:
Motor2: run for (random) time, (random) speed, then stop and change direction, again run for (random) time, (random) speed
at the same time:
Motor3: run for (random) time, (random) speed, then stop and change direction, again run for (random) time, (random) speed
and so one...

my problem here is that all six motors doing this (differently) at the same time. one after the other would be easy to do...

Do i miss something essential ? any ideas where to go ?

thanks, Pe

Well, motors typically don't start & stop instantaneously, being electro-mechanical devices and having mass to deal with.
So set up a blink without delay loop and every 100uS check the status of your different motors and start & stop according to the times you setup, giving them a few cycles to get up to speed or to come to a halt so you don't induce big current draws trying to change direction instantaneously.

Your problem is that you're not thinking in terms of an event driven system. You're thinking in terms of a linear system.

In a linear system, A happens before B which happens before C which happens before D.

So... It's:

DoThingA();
delay();
DoThingB();
delay();
DoThingC();
delay();
DoThingD();

In an event driven system, you set up events, then stuff happens! It's more like:
Phase 1: Set up events.
Phase 2: ?
Phase 3: Profit!

Here's how you need to look at it. The 6 motors are indeed doing different tasks, but they are not being DIRECTED at the same time. Think of time as a line. The microcontroller is fast... damn fast. It can respond to an event and instruct the motor to do something in a tiny amount of time. Hundreds of these events can be preformed every second.

In an event driven system, the events are the trigger that causes the microcontroller to change the current status of the motor... like running or not running.

Let's look at your motor sequence for one motor:
'Motor1: run for (random) time, (random) speed, then stop and change direction, again run for (random) time, (random) speed
at the same time:"

Let's use my Event Manager system roboticcore.com to show how this works.

Basically. One handler per motor. You need a starter event in setup():

AddEvent(TIMER,ONE_SHOT,1000,Motor1Handler);

Then you need an event handler:

void Motor1Handler()
  {
  // Pseudo code.
  // Change motor direction.
  // Select random motor speed.
  // Drive motor at selected speed and direction.
  // Select random delay.

  AddEvent(TIMER,ONE_SHOT,random_delay,Motor1Handler);
  }

Your entire program is then:

#include "EventManager.h"

void Motor1Handler(void)
  {
  long random_time;

  // Motor 1 handler code here!

  // Reset event.
  AddEvent(TIMER,ONE_SHOT,random_time,Motor1Handler);
  }


void Motor2Handler(void)
  {
  long random_time;

  // Motor 2 handler code here!

  // Reset event.
  AddEvent(TIMER,ONE_SHOT,random_time,Motor2Handler);
  }


void Motor3Handler(void)
  {
  long random_time;

  // Motor 3 handler code here!

  // Reset event.
  AddEvent(TIMER,ONE_SHOT,random_time,Motor3Handler);
  }


void Motor4Handler(void)
  {
  long random_time;

  // Motor 4 handler code here!

  // Reset event.
  AddEvent(TIMER,ONE_SHOT,random_time,Motor4Handler);
  }


void Motor5Handler(void)
  {
  long random_time;

  // Motor 5 handler code here!

  // Reset event.
  AddEvent(TIMER,ONE_SHOT,random_time,Motor5Handler);
  }


void Motor6Handler(void)
  {
  long random_time;

  // Motor 6 handler code here!

  // Reset event.
  AddEvent(TIMER,ONE_SHOT,random_time,Motor6Handler);
  }


void setup()
  {
  // Initialize the Event Handler System.
  InitEvents();
 
  // Start Motor 1 event chain. Other motor starts are below.
  AddEvent(TIMER,ONE_SHOT,1000,Motor1Handler);
  AddEvent(TIMER,ONE_SHOT,1000,Motor2Handler);
  AddEvent(TIMER,ONE_SHOT,1000,Motor3Handler);
  AddEvent(TIMER,ONE_SHOT,1000,Motor4Handler);
  AddEvent(TIMER,ONE_SHOT,1000,Motor5Handler);
  AddEvent(TIMER,ONE_SHOT,1000,Motor6Handler);
  }


void loop()
  {
  ProcessEvents(millis());
  }

Thanks CrossRoads and TeslaFan,

@TeslaFan: This was exactly what i am looking for. Thank you.

You right with the "linear thinking" but i still have to get it right...(means drinking a big cap of coffee and reading your blog about Envent Manager)

here is a examle of two LED's blinking (cool) randomly:

#include "EventManager.h"

void Motor1AHandler(void)
  {
   long random_time; 
   random_time = random(900);   
   digitalWrite(13, HIGH);    // Set the LED13 on.
  AddEvent(TIMER,ONE_SHOT,random_time,Motor1BHandler);
  }
void Motor1BHandler(void)
  {
   long random_time;
   random_time = random(900);   
   digitalWrite(13, LOW);    // Set the LED13 off.
  AddEvent(TIMER,ONE_SHOT,random_time,Motor1AHandler);
  }


void Motor2AHandler(void)
  {
   long random_time;
   random_time = random(900);   
   digitalWrite(12, HIGH);    // Set the LED12 on.
  AddEvent(TIMER,ONE_SHOT,random_time,Motor2BHandler);
  }
void Motor2BHandler(void)
  {
   long random_time; 
   random_time = random(900);   
   digitalWrite(12, LOW);    // Set the LED12 off.
  AddEvent(TIMER,ONE_SHOT,random_time,Motor2AHandler);
  }


void setup()
  {
  pinMode(13, OUTPUT); // LED13.
  pinMode(12, OUTPUT); // LED12.
  
  digitalWrite(13, LOW);    // set the LED13 off.
  digitalWrite(12, LOW);    // set the LED12 off.  
  // Initialize the Event Handler System.
  InitEvents();
 
  // Start Motor 1 event chain. Other motor starts are below.
  AddEvent(TIMER,ONE_SHOT,1000,Motor1AHandler);
  AddEvent(TIMER,ONE_SHOT,1000,Motor2AHandler);
  }


void loop()
  {
  ProcessEvents(millis());
  }

Ah! Excellent!

You clearly grok the concept. You've modified the example given in the Event Manager post to make the LED blink by ping-ponging between two handlers that each select their own random time.

The beauty of this is that the LED can just be left to blink forever... oblivious to the rest of the sketch and without adding piles of extra code in the loop() function.

I use this for everything that uses non-critical timing (non-critical being defined as accuracy of a millisecond and higher). For sub-millisecond accuracy, I use interrupts. But really! 99% of your timing needs... LEDs, buttons, timers.... this is what you need.

Your Event Manager is the perfect solution for me, works very well. In case, here is my code for two motors:

 /* 
 
 this program runs two motors at different speeds and lenght. 
 Pins are connected to a L293D, Probably PWM needs to adjust
 to run your motors.
 
 Thanks to TeslaFan for his Event Manager: 
 http://roboticcore.com/?p=14
  
 */
 
#include "EventManager.h"

void Motor1AHandler(void)
  {
   char random_pwm;
   long random_time;
   random_pwm = random(17, 49);
   random_time = random(5000, 33000); 
   digitalWrite(0, HIGH);    // Set the direction.
   digitalWrite(1, LOW);    
   analogWrite(3, random_pwm);   // Set the speed.
  AddEvent(TIMER,ONE_SHOT,random_time,Motor1BHandler);
  }
void Motor1BHandler(void)
  {
   char random_pwm; 
   long random_time; 
   random_pwm = random(17, 49);
   random_time = random(5000, 33000);   
   digitalWrite(0, LOW);    // Set the direction.
   digitalWrite(1, HIGH);    
   analogWrite(3, random_pwm);   // Set the speed.
  AddEvent(TIMER,ONE_SHOT,random_time,Motor1AHandler);
  }


void Motor2AHandler(void)
  {
   char random_pwm;
   long random_time;
   random_pwm = random(17, 49);
   random_time = random(5000, 33000); 
   digitalWrite(12, HIGH);    // Set the direction.
   digitalWrite(13, LOW);    
   analogWrite(11, random_pwm);   // Set the speed.
  AddEvent(TIMER,ONE_SHOT,random_time,Motor2BHandler);
  }
void Motor2BHandler(void)
  {
   char random_pwm; 
   long random_time; 
   random_pwm = random(17, 49);
   random_time = random(5000, 33000);   
   digitalWrite(12, LOW);    // Set the direction.
   digitalWrite(13, HIGH);    
   analogWrite(11, random_pwm);   // Set the speed.
  AddEvent(TIMER,ONE_SHOT,random_time,Motor2AHandler);
  }
  


void setup()
  {  
  int pwmfreq = 1; // set the PWM freq 
  TCCR2B = (TCCR2B & 0xF8) | pwmfreq;
  
  pinMode(13, OUTPUT); // MotorBlock1
  pinMode(12, OUTPUT); // 
  pinMode(11, OUTPUT); // PWM
  
  pinMode(0, OUTPUT); // MotorBlok2
  pinMode(1, OUTPUT); // 
  pinMode(3, OUTPUT); // PWM
  
  digitalWrite(13, LOW);    
  digitalWrite(12, LOW);     
  digitalWrite(11, LOW);    
  digitalWrite(3, LOW); 
  digitalWrite(1, LOW); 
  digitalWrite(0, LOW); 
  
  // Initialize the Event Handler System.
  InitEvents();
 
  // Start Motor 1 event chain. Other motor starts are below.
  AddEvent(TIMER,ONE_SHOT,1000,Motor1AHandler);
  AddEvent(TIMER,ONE_SHOT,1000,Motor2AHandler);
  }


void loop()
  {
  ProcessEvents(millis());
  }