1

I googled solutions and tried, but I still cannot get it working.

I've tried BlinkwithoutDelay.

I feel it is very confusing to track timing of two motors (i.e., step, direction, speed) for the following routine loop:

  • step 1: run motorA_forward() for 10 seconds;
  • step 2: run motorAB_stop() for 1 seconds;
  • step 3: run motorB_backward() for 3 seconds
  • step 4: run motorAB_stop() for 1 seconds
  • step 5: run motorA_backward() for 10 seconds
  • step 6: run motorAB_stop() for 1 seconds

Please help me on this!! I really appreciate your time and comments.

Thank you.

The following is my working code.

// ----------LIBRARIES--------------

#include <Wire.h>
#include <LIDARLite.h>
LIDARLite myLidarLite;


// ----------CONSTANTS--------------

const int motorA_pin_1 = 8;           // the pin numbers for the motors
const int motorA_pin_2 = 11;
const int motorA_pin_speed = 9;
const int motorB_pin_1 = 12;
const int motorB_pin_2 = 13;
const int motorB_pin_speed = 10;

//------------VARIABLES--------------

byte motorA_state_1 = LOW;             // used to record whether the motots are on or off
byte motorA_state_2 = LOW;             // LOW = off
byte motorB_state_1 = LOW;             
byte motorB_state_2 = LOW;             

int currentMillis               = 0;     // stores the value of millis() in each iteration of loop()
int motorA_Forward_Interval     = 5000;  // will store last time the motor was moved
int motorA_Backward_Interval    = 5000; // will store last time the motor was moved
int motorA_Stop_Interval        = 2000;  // will store last time the motor was moved
int motorB_Stop_Interval        = 2000;  // will store last time the motor was moved
int motorAB_BreakTime_Interval  = 2000;

unsigned long motorA_Forward_Timer      = 0;     // will store last time motorA start was updated
unsigned long motorA_Backward_Timer     = 0;     // will store last time motorA start was updated
unsigned long motorB_Forward_Timer      = 0;     // will store last time motorA start was updated
unsigned long motorB_Backward_Timer     = 0;     // will store last time motorA start was updated
unsigned long BreakTime_timer   = 0;     // will store last time motorA/B break time was updated


//------------INITIALIZATION--------------

void setup() 
{
  Serial.begin(115200);
  myLidarLite.begin();

  pinMode(motorA_pin_1,OUTPUT);         // set the motor pins as output:
  pinMode(motorA_pin_2,OUTPUT); 
  pinMode(motorA_pin_speed,OUTPUT); 
  pinMode(motorB_pin_1,OUTPUT); 
  pinMode(motorB_pin_2,OUTPUT); 
  pinMode(motorB_pin_speed,OUTPUT);


}

//------------LOOPING----------------------
// Notice that none of the action happens in loop() apart from reading millis()
// It just calls the functions that have the action code

void loop()
{
    Serial.println(myLidarLite.distance());

    unsigned long currentMillis = millis();

    motorA_forward();  // for 10 seconds
    motorAB_stop();    // for 1 seconds
    motorB_backward(); // for 3 seconds
    motorAB_stop();    // for 1 seconds
    motorA_backward(); // for 10 seconds
    motorAB_stop();    // for 1 seconds

}

//------------SUBROUTINE----------------------


void motorA_forward()
{   
  if(currentMillis - motorA_Forward_Timer <= motorA_Forward_Interval)
  {
    motorA_state_1 = HIGH;   // Turn motor A on - backward
    motorA_state_2 = LOW;  // 
    motorB_state_1 = LOW;   // Turn motor B off
    motorB_state_2 = LOW;   // 

    analogWrite(motorA_pin_speed,255);
    digitalWrite(motorA_pin_1,motorA_state_1);
    digitalWrite(motorA_pin_2,motorA_state_2);
    analogWrite(motorB_pin_speed,255);
    digitalWrite(motorB_pin_1,motorB_state_1);
    digitalWrite(motorB_pin_2,motorB_state_2);

    motorA_Forward_Timer = currentMillis;
  }
}

void motorA_backward()
{
    if(currentMillis - motorA_Backward_Timer <= motorA_Backward_Interval)
  {
    motorA_state_1 = LOW;   // Turn motor A on - backward
    motorA_state_2 = HIGH;  // 
    motorB_state_1 = LOW;   // Turn motor B off
    motorB_state_2 = LOW;   // 

    analogWrite(motorA_pin_speed,255);
    digitalWrite(motorA_pin_1,motorA_state_1);
    digitalWrite(motorA_pin_2,motorA_state_2);
    analogWrite(motorB_pin_speed,255);
    digitalWrite(motorB_pin_1,motorB_state_1);
    digitalWrite(motorB_pin_2,motorB_state_2);

    motorA_Backward_Timer += currentMillis;
  }
}

void motorB_forward()
{
    motorA_state_1 = LOW;   // Turn motor A off
    motorA_state_2 = LOW;   // 
    motorB_state_1 = HIGH;  // Turn motor B on - forward
    motorB_state_2 = LOW;   // 

    analogWrite(motorA_pin_speed,255);
    digitalWrite(motorA_pin_1,motorA_state_1);
    digitalWrite(motorA_pin_2,motorA_state_2);
    analogWrite(motorB_pin_speed,255);
    digitalWrite(motorB_pin_1,motorB_state_1);
    digitalWrite(motorB_pin_2,motorB_state_2);

    motorB_Forward_Timer = currentMillis;
}

void motorB_backward()
{
    motorA_state_1 = LOW;   // Turn motor A off
    motorA_state_2 = LOW;   // 
    motorB_state_1 = LOW;   // Turn motor B on - backward
    motorB_state_2 = HIGH;  // 

    analogWrite(motorA_pin_speed,255);
    digitalWrite(motorA_pin_1,motorA_state_1);
    digitalWrite(motorA_pin_2,motorA_state_2);
    analogWrite(motorB_pin_speed,255);
    digitalWrite(motorB_pin_1,motorB_state_1);
    digitalWrite(motorB_pin_2,motorB_state_2);

    motorB_Backward_Timer = currentMillis;
}

void motorAB_stop()
{
    motorA_state_1 = LOW;   // Turn motor A off
    motorA_state_2 = LOW;   // 
    motorB_state_1 = LOW;   // Turn motor B off
    motorB_state_2 = LOW;  // 

    analogWrite(motorA_pin_speed,0);
    digitalWrite(motorA_pin_1,motorA_state_1);
    digitalWrite(motorA_pin_2,motorA_state_2);
    analogWrite(motorB_pin_speed,0);
    digitalWrite(motorB_pin_1,motorB_state_1);
    digitalWrite(motorB_pin_2,motorB_state_2);

    BreakTime_timer = currentMillis;
}
2
int currentMillis               = 0;     // stores the value of millis() in each iteration of loop()
...

void loop()
{
    Serial.println(myLidarLite.distance());
    unsigned long currentMillis = millis();

You have two currentMillis variables. The global one never changes. You change a different one inside loop.


Remove the data definition. eg.

void loop()
{
    Serial.println(myLidarLite.distance());
    currentMillis = millis();  // change the global variable

Also make the global one unsigned long:

unsigned long currentMillis               = 0;     // stores the value of millis() in each iteration of loop()
2

This is a classic example where Object Oriented Programming (OOP) can make your life so much easier.

The principle behind OOP is to define a Class which contains all the actions you want to perform on something - in this case a motor. The Class contains all the instructions on how to do things like set the motor speed, the direction, start it, stop it, etc.

From that Class you then create Objects. The beauty is there is only one Class which has the abstract concept of "Motor Control", but that Class is used to create one Object for each motor you want to control.

A Class, and hence the Objects derived from it, are all completely self contained, which makes it so much easier to manage. All the variables associated with a single motor are wrapped up inside the Class and you don't need to worry about unique names for them all on a per-motor basis.

For example, you might define a class like this:

class Motor {
    private:
        int _speedPin;
        int _directionPin1;
        int _directionPin2;

    public:
        Motor(int sp, int dp1, int dp2) {
            _speedPin = sp;
            _directionPin1 = dp1;
            _directionPin2 = dp2;
        }
        void begin() {
            analogWrite(_speedPin, 0);
            pinMode(_directionPin1, OUTPUT);
            pinMode(_directionPin2, OUTPUT);
            digitalWrite(_directionPin1, LOW);
            digitalWrite(_directionPin2, LOW);
        }
        void forward() {
            digitalWrite(_directionPin1, HIGH);
            digitalWrite(_directionPin2, LOW);
        }
        void reverse() {
            digitalWrite(_directionPin1, LOW);
            digitalWrite(_directionPin2, HIGH);
        }
        void speed(int speed) {
            analogWrite(_speedPin, speed);
        }
        void stop() {
            analogWrite(_speedPin, 0);
            digitalWrite(_directionPin1, LOW);
            digitalWrite(_directionPin2, LOW);
        }
};

Everything you need to control a motor is in there. Then you could use that to create two motor objects:

Motor leftMotor(3, 4, 5);
Motor rightMotor(6, 7, 8);

You provide the pins that control the motor to the constructor of the object - that is pin 3 is the speed pin of the first motor, and pins 4 and 5 are the direction control pins, etc.

You can now control the motors very simply. Configure the pins by calling the begin function defined in the class above:

void setup() {
    leftMotor.begin();
    rightMotor.begin();
}

And now you can use similar decision making as normal to decide when to do what. The main difference is that your motor control code now looks as simple as:

leftMotor.forward();
rightMotor.reverse();

or

leftMotor.stop();
rightMotor.forward();
rightMotor.speed(30);

You then end up with a program that is much cleaner and easier to follow. And adding a third or forth motor is as simple as defining more Motor objects with their pins.

This video is a good introduction to what OOP is and how it differs from the "traditional" approach:

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.