How to modify the sketch to control a two PWM pins input motor driver?

I was going to answer but I got delayed 1000 times then 500 then 100 a few times then 1000 again....

That can't be usable like that?

MorganS:
I was going to answer but I got delayed 1000 times then 500 then 100 a few times then 1000 again....

That can't be usable like that?

Thank you, you are right, the many delays for debug purpose. when I use serial monitor , the date runs too fast to see, and I don't know how to stop the page.

BTW, code in #14 doesn't work, I used a joystick tested it , wired LPWMA to pin5 (or pin6), and RPWMA to any pin, motor A just one direction.

laoadam:
Thank you, you are right, the many delays for debug purpose. when I use serial monitor , the date runs too fast to see, and I don't know how to stop the page.

Don't use delay() for that purpose as it will interfere with the normal running of the program. Even printing debug data at full program speed can slow a program.

Use millis() to manage timing without blocking as illustrated in Several Things at a Time. That way you only print data maybe every 500 millisecs. If it is essential to collect a series of successive values write them to an array and print the array when it is full.

And see Using millis() for timing. A beginners guide if you need more explanation.

...R

Robin2:
The usual way to control a motor driver that requires separate PWM signals for FWD and REV is like this

if (direction == 'F') {

digitalWrite(revPin, LOW);
  analogWrite(fwdPin, pwmVal);
}
else {
  digitalWrite(fwdPin, LOW);
  analogWrite(revPin, pwmVal);
}




...R

Thank you MorganS, I used MEGA2560 that has many PWM pins, and I setup Timer3 and Timer4 at 0x02 3921.16 Hz, test result is pin5/pin6 runs motor smooth and well, the pin7/pin8 doesn’t. any where wrong in the following code?

//int ledPin = 13;
int joyPin1 = 0;                 // slider variable connecetd to analog pin 0
int joyPin2 = 1;                 // slider variable connecetd to analog pin 1

int value1 = 0;                  // variable to read the value from the analog pin 0
int value2 = 0;                  // variable to read the value from the analog pin 1

int STBY = 10; //standby

int PWMAL = 5;
int PWMAR = 6; //PWM  WORK WELL

int PWMBL = 7; //??Speed control
int PWMBR = 8; //??Speed control

const boolean FORWARD = HIGH; ////The const keyword stands for constant. It is a variable qualifier that modifies the behavior of the variable, making a variable "read-only". This means that the variable can be used just as any other variable of its type, but its value cannot be changed. You will get a compiler error if you try to assign a value to a const variable.
const boolean REVERSE = LOW;
float speed_Max = 255; //pwm usually goes from 0-255  ////A float is a floating-point number, which means it is a number that has a decimal place
float speed_Min = 0;
float analogInput_Max = 1023;  ////bool类型只有两个值:true =1 、false=0。
float analogInput_Min = 0;
float analogInput_Middle_X = 515;//ideally it would be analogInput_Max / 2
float analogInput_Middle_Y = 495;//ideally it would be analogInput_Max / 2
float deadBand = 0;
float middleMax = (analogInput_Max / 2) + deadBand;
float middleMin = (analogInput_Max / 2) - deadBand;
boolean pastDirection = FORWARD;

void setup() {

// Configure Timer 3 for PWM @ 14 kHz.
    TCCR3A = 0;           // undo the configuration done by...
    TCCR3B = 0;           // ...the Arduino core library
    TCNT3  = 0;           // reset timer
    
    TCCR3A = _BV(COM3A1)  // non-inverted PWM on ch. A
           | _BV(COM3B1)  // same on ch; B
           | _BV(WGM30);  // mode 10: ph. correct PWM, TOP = ICR1

    TCCR3B = (TCCR3B & 0b11111000) | 0x01; // / 0x01/31372.55 [Hz] / 0x02  3921.16 Hz / //** use this code got 3.9khz but joystick works not too good
  
 // Configure Timer 4 for PWM @ 14 kHz.
    TCCR4A = 0;           // undo the configuration done by...
    TCCR4B = 0;           // ...the Arduino core library
    TCNT4  = 0;           // reset timer
    
    TCCR4A = _BV(COM4A1)  // non-inverted PWM on ch. A
           | _BV(COM4B1)  // same on ch; B
           | _BV(WGM40);  // mode 10: ph. correct PWM, TOP = ICR1

   TCCR4B = (TCCR4B & 0b11111000) | 0x01; // / 0x01/31372.55 [Hz] / 0x02  3921.16 Hz / //** use this code got 3.9khz but joystick works not too good
  
  Serial.begin(9600);

  pinMode(PWMAL, OUTPUT);
  pinMode(PWMAR, OUTPUT);

  pinMode(PWMBL, OUTPUT);
  pinMode(PWMBR, OUTPUT);

}

void loop() {
  // reads the value of the variable resistor
  value1 = analogRead(joyPin1);

  Serial.println("value1= ");
  Serial.println(value1);

  // this small pause is needed between reading
  // analog pins, otherwise we get the same value twice
  delay(100);
  // reads the value of the variable resistor
  value2 = analogRead(joyPin2);

  Serial.println("value2 =  ");
  Serial.println(value2);

  int commands[2] = {value1, value2};
  motorControl(commands[0], commands[1]);
  //motorControl(value1, value2);
}

void move(int motor, int speed, boolean direction) {

  if (motor == 1) {
    if (direction) {
      // digitalWrite(RPWMA, LOW);
      analogWrite(PWMAL, speed);

      Serial.println("speedL =  ");
      Serial.println(speed);

    } else  {
      // digitalWrite(PWMAR, LOW);
      // analogWrite(LPWMA, speed);

      analogWrite(PWMAR, speed);

      Serial.println("speedR =  ");
      Serial.println(speed);
    }
  } else {
    if (direction) {
      //    digitalWrite(RPWMB, LOW);
      analogWrite(PWMBL, speed);
    } else  {
      //     digitalWrite(RPWMB, HIGH);
      analogWrite(PWMBR, speed); // not use 255-speed, cause of the date are already processed.
    }
  }
}

void motorControl(float x, float y) {

  boolean currentDirection = y >= analogInput_Middle_Y;

  //map(value, fromLow, fromHigh, toLow, toHigh);
  if (currentDirection == REVERSE) {
    y = map(y, analogInput_Middle_Y, analogInput_Min, speed_Min, speed_Max) ;
  } else {
    y = map(y, analogInput_Middle_Y, analogInput_Max, speed_Min, speed_Max);
  }

  int subtractFromLeft = map(x, analogInput_Middle_X, analogInput_Min, speed_Min, y);

  Serial.println("subtractFromLeft =  ");
  Serial.println(subtractFromLeft);

  int subtractFromRight = map(x, analogInput_Middle_X, analogInput_Max, speed_Min, y);

  Serial.println("subtractFromRight =  ");
  Serial.println(subtractFromRight);

  if (subtractFromRight < 0) {
    subtractFromRight = 0;
  }

  if (subtractFromLeft < 0) {
    subtractFromLeft = 0;
  }

  int Throttle_RIGHT = y - subtractFromRight;
  int Throttle_LEFT = y - subtractFromLeft;

  boolean currentDirection_LEFT = currentDirection;
  boolean currentDirection_RIGHT = currentDirection;


  if (Throttle_LEFT < 1 && Throttle_RIGHT > 1) {
    currentDirection_LEFT = !currentDirection; //
    Throttle_LEFT = Throttle_RIGHT;
  }

  if (Throttle_RIGHT < 1 && Throttle_LEFT > 1) {
    currentDirection_RIGHT = !currentDirection;
    Throttle_RIGHT = Throttle_LEFT;
  }

  move(1, Throttle_LEFT, currentDirection_LEFT);
  move(2, Throttle_RIGHT, currentDirection_RIGHT);

  Serial.println("Throttle_LEFT: ");
  Serial.println(Throttle_LEFT);
  Serial.println(" Throttle_RIGHT: ");
  Serial.println(Throttle_RIGHT);
  Serial.println("");

}

On a Mega Timer3 is associated with Pins 5, 2 and 3 and Timer4 is associated with pins 6,7 and 8

I don't have time to read the datasheet to see how the 3 pins are used for each timer but I suggest you try using pins 5,2 and 6,7

...R

Robin2:
On a Mega Timer3 is associated with Pins 5, 2 and 3 and Timer4 is associated with pins 6,7 and 8

I don't have time to read the datasheet to see how the 3 pins are used for each timer but I suggest you try using pins 5,2 and 6,7

...R

Thank you,
The pins OK now.
There are two more questions:

  1. The motor automatically moving when power on at Y reverse direction;
  2. The motor doesn't stop when the joystick is released to its center position.

Any help?

laoadam:
Any help?

Not without seeing the latest version of your program.

...R

Robin2:
Not without seeing the latest version of your program.

…R

Sorry, here you go.

#include <VirtualWire.h>


//motor A connected between A01 and A02
//motor B connected between B01 and B02

int STBY = 10; //standby  ////  An integer (more commonly called an int) is a number without a decimal point.


//Motor A
int PWMAL = 3; //??Speed control X
int PWMAR = 5; //??Speed control

// int AL_EN = 3; //Direction Y
//int AR_EN = 4; //Direction

//Motor B
int PWMBL = 6; //??Speed control
int PWMBR = 7; //??Speed control

//int BL_EN = 9; //Direction
//int BR_EN = 10; //Direction  ////WAS16

/*
const boolean A_FORWARD = HIGH; ////The const keyword stands for constant. It is a variable qualifier that modifies the behavior of the variable, making a variable "read-only". This means that the variable can be used just as any other variable of its type, but its value cannot be changed. You will get a compiler error if you try to assign a value to a const variable.
const boolean B_FORWARD = HIGH;
const boolean REVERSE = LOW;
const boolean REVERSE = LOW;
*/

const boolean FORWARD = HIGH; ////The const keyword stands for constant. It is a variable qualifier that modifies the behavior of the variable, making a variable "read-only". This means that the variable can be used just as any other variable of its type, but its value cannot be changed. You will get a compiler error if you try to assign a value to a const variable.
const boolean REVERSE = LOW;

float speed_Max = 255; //pwm usually goes from 0-255  ////A float is a floating-point number, which means it is a number that has a decimal place
float speed_Min = 0;
float analogInput_Max = 1023;  ////bool类型只有两个值:true =1 、false=0。
float analogInput_Min = 0;
float analogInput_Middle_X = 515;//ideally it would be analogInput_Max / 2
float analogInput_Middle_Y = 495;//ideally it would be analogInput_Max / 2
float deadBand = 0;
float middleMax = (analogInput_Max / 2) + deadBand;
float middleMin = (analogInput_Max / 2) - deadBand;
boolean pastDirection = FORWARD;

// boolean B_pastDirection = B_FORWARD;

void setup() {

////////////////////////////
// Configure Timer 3 for PWM @ 3.9 kHz. Timer3 is associated with Pins 5, 2 and 3 and Timer4 is associated with pins 6,7 and 8
//try using pins 5,2 and 6,7

    TCCR3A = 0;           // undo the configuration done by...
    TCCR3B = 0;           // ...the Arduino core library
    TCNT3  = 0;           // reset timer
    
    TCCR3A = _BV(COM3A1)  // non-inverted PWM on ch. A
           | _BV(COM3B1)  // same on ch; B
           | _BV(WGM30);  // mode 10: ph. correct PWM, TOP = ICR1

    TCCR3B = (TCCR3B & 0b11111000) | 0x02; // / 0x01/31372.55 [Hz] / 0x02  3921.16 Hz / //** use this code got 3.9khz but joystick works not too good
  
  //////////////////////////////
// Configure Timer 4 for PWM @ 3.9 kHz.
    TCCR4A = 0;           // undo the configuration done by...
    TCCR4B = 0;           // ...the Arduino core library
    TCNT4  = 0;           // reset timer
    
    TCCR4A = _BV(COM4A1)  // non-inverted PWM on ch. A
           | _BV(COM4B1)  // same on ch; B
           | _BV(WGM40);  // mode 10: ph. correct PWM, TOP = ICR1

   TCCR4B = (TCCR4B & 0b11111000) | 0x02; // / 0x01/31372.55 [Hz] / 0x02  3921.16 Hz / //** use this code got 3.9khz but joystick works not too good
  
  /////////////////////////////////

  Serial.begin( 9600 );

  pinMode(STBY, OUTPUT); //// pin: the number of the pin whose mode you wish to set; mode: INPUT, OUTPUT, or INPUT_PULLUP.

  pinMode(PWMAL, OUTPUT);
  pinMode(PWMAR, OUTPUT);

 // pinMode(AL_EN, OUTPUT);
//  pinMode(AR_EN, OUTPUT);

  pinMode(PWMBL, OUTPUT);
  pinMode(PWMBR, OUTPUT);

 // pinMode(BL_EN, OUTPUT);
 // pinMode(BR_EN, OUTPUT);

  //receiver setup
  vw_set_rx_pin(2);          //Sets pin 12 as the RX Pin  //// should be pin '2' for easy hook out 
  vw_set_ptt_inverted(true); // Required for DR3100
  vw_setup(2000);            // Bits per sec
  vw_rx_start();             // Start the receiver PLL running
}

void loop() {

  uint8_t buf[VW_MAX_MESSAGE_LEN]; // This declares a variable array. instead of 7 variables buf1, buf2 etc...
  uint8_t buflen = VW_MAX_MESSAGE_LEN;
  if (vw_get_message(buf, &buflen)) // Non-blocking
  {
    int i;
    int column = 0;
    String message;
    int commands[30];

    // Message with a good checksum received, dump it.
    for (i = 0; i < buflen; i++)
    {
      //DEBUG:
      Serial.print(char(buf[i]));

      if (char(buf[i]) == '|') {
        commands[column] = message.toInt();
        message = "";
        column++;
      } else {
        message += char(buf[i]);
      }
    }
    //one more time to capture the last value since the message does not end with |
    commands[column] = message.toInt();

    // DEBUG
    //		Serial.print("X: ");
    //		Serial.print(commands[0]);
    //		Serial.print(" Y: ");
    //		Serial.println(commands[1]);

    motorControl(commands[0], commands[1]);

  }

}

void move(int motor, int speed, boolean direction) {
  digitalWrite(STBY, HIGH); //disable standby //// Write a HIGH or a LOW value to a digital pin.
  ///////////////////////////////////////////////////
  /*
    if (motor == 1) {
      digitalWrite(AL_EN, direction);
      digitalWrite(AR_EN, !direction);
      analogWrite(PWMAL, speed);   // ?? Writes an analog value (PWM wave) to a pin.
      analogWrite(PWMAR, speed); //??
    } else {
      digitalWrite(BL_EN, !direction);
      digitalWrite(BR_EN, direction);
      analogWrite(PWMBL, speed); //??
      analogWrite(PWMBR, speed); //??
    }

  */

  if (motor == 1) {
    if (direction) {

      // digitalWrite(AL_EN, HIGH); // sime time short these two pins directly hook to Vc better
     // digitalWrite(AR_EN, HIGH); //
      analogWrite(PWMAL, speed);

      Serial.println("speedL =  ");
      Serial.println(speed);

    } else  {

      // digitalWrite(AL_EN, HIGH); // sime time short these two pins directly hook to Vc better
     //  digitalWrite(AR_EN, HIGH); //
      analogWrite(PWMAR, speed);

      Serial.println("speedR =  ");
      Serial.println(speed);
    }
  } else {
    if (direction) {

      // digitalWrite(BL_EN, HIGH); // sime time short these two pins directly hook to Vc better
     //  digitalWrite(BR_EN, HIGH); //
      analogWrite(PWMBL, speed);

    } else  {

     // digitalWrite(BL_EN, HIGH); // sime time short these two pins directly hook to Vc better
     // digitalWrite(BR_EN, HIGH); //
      analogWrite(PWMBR, speed);

    }
  }

}

void motorControl(float x, float y) {
  boolean currentDirection = y >= analogInput_Middle_Y;

  //map(value, fromLow, fromHigh, toLow, toHigh);
  if (currentDirection == REVERSE) {

    //  if (currentDirection == REVERSE) {

    y = map(y, analogInput_Middle_Y, analogInput_Min, speed_Min, speed_Max) ;
  } else {
    y = map(y, analogInput_Middle_Y, analogInput_Max, speed_Min, speed_Max);
  }

  int subtractFromLeft = map(x, analogInput_Middle_X, analogInput_Min, speed_Min, y);
  int subtractFromRight = map(x, analogInput_Middle_X, analogInput_Max, speed_Min, y);

  if (subtractFromRight < 0) {
    subtractFromRight = 0;
  }

  if (subtractFromLeft < 0) {
    subtractFromLeft = 0;
  }

  int Throttle_RIGHT = y - subtractFromRight;
  int Throttle_LEFT = y - subtractFromLeft;

  boolean currentDirection_LEFT = currentDirection;
  boolean currentDirection_RIGHT = currentDirection;


  if (Throttle_LEFT < 1 && Throttle_RIGHT > 1) {
    currentDirection_LEFT = !currentDirection; ////如果值为true,则!运算后为false
    Throttle_LEFT = Throttle_RIGHT;
  }

  if (Throttle_RIGHT < 1 && Throttle_LEFT > 1) {
    currentDirection_RIGHT = !currentDirection;
    Throttle_RIGHT = Throttle_LEFT;
  }

  move(1, Throttle_LEFT, currentDirection_LEFT);
  move(2, Throttle_RIGHT, currentDirection_RIGHT);

  
}
[code]

laoadam:

  1. The motor automatically moving when power on at Y reverse direction;

I suspect that is because you don’t analogWrite() the stationary value in setup()

  1. The motor doesn’t stop when the joystick is released to its center position.

Your code is hard to follow because you have things like Y rather than meaningful variable names. I can’t even figure out what variables have the joystick values.

My guess is that you need to establish a dead-zone around the centre position and if the joystick value is in that zone you should command the motors to stop. Something like

if (joystickValue < deadZoneValue) {
   stopMotors();
}

If the joystick value is 0 to 512 then the deadZone might be 0 to 30 or 0 to 50

…R

Robin2:
I suspect that is because you don’t analogWrite() the stationary value in setup()
Your code is hard to follow because you have things like Y rather than meaningful variable names. I can’t even figure out what variables have the joystick values.

My guess is that you need to establish a dead-zone around the centre position and if the joystick value is in that zone you should command the motors to stop. Something like

if (joystickValue < deadZoneValue) {

stopMotors();
}




If the joystick value is 0 to 512 then the deadZone might be 0 to 30 or 0 to 50

...R

Thank you Robin2, I’ll test this out.