motor speed controll doesnt work in reverse

hello there, i'm new to the forum,

i'm trying to make a coilwinder for guitar pickups, and am facing a problem, whenever i try to change the speed of the motor during reverse, it changes to a very slow forward rotation.

i'm using a arduino uno, a bts motor driver 48A, ive got a 12v 30A regulated powersupply, and the motor is a black $ decker cordless drill.

i've got both enable pins of the driver wired to digital pin 2 on the arduino, pwm_left to digital pin 12, and pwm right to digital pin 3.

i'llpost my code below, if anyone can help its much apreciated.

int usMotor_Status = 0;
int pwm_right=3;
int pwm_left=11;
int EN_r=2;
//int EN_l=12;
short usSpeed=10;

void setup() {
  pinMode(pwm_right, OUTPUT);
  pinMode(pwm_left, OUTPUT);
  pinMode(EN_r, OUTPUT);
  pinMode(EN_l, OUTPUT);
  usMotor_Status = 0;
  // put your setup code here, to run once:
  Serial.begin(9600); 
  Serial.println("1. STOP");
  Serial.println("2. FORWARD");
  Serial.println("3. REVERSE");
  Serial.println("4. READ CURRENT");
  Serial.println("+. INCREASE SPEED");
  Serial.println("-. DECREASE SPEED");
  Serial.println();
}

void loop() 
{
  char user_input;   

  
  
  while(Serial.available())
  {
    user_input = Serial.read(); //Read user input and trigger appropriate function
    
 
     
    if (user_input =='1')
    {
       Stop();
    }
    else if(user_input =='2')
    {
      Forward();
    }
    else if(user_input =='3')
    {
      Reverse();
    }
    else if(user_input =='+')
    {
      IncreaseSpeed();
    }
    else if(user_input =='-')
    {
      DecreaseSpeed();
    }
    else
    {
      Serial.println("Invalid option entered.");
    }
      
  }
}





void Stop()
{
  Serial.println("Stop");
  digitalWrite(EN_r, LOW);
  //digitalWrite(EN_l, LOW);
  digitalWrite(pwm_left, LOW);
  digitalWrite(pwm_right, LOW);
  usMotor_Status = Stop;


}

void Forward()
{
  Serial.println("forward");
  digitalWrite(EN_r, HIGH);
  //digitalWrite(EN_l, HIGH);
  digitalWrite(pwm_left, LOW);
  analogWrite(pwm_right, usSpeed);
  usMotor_Status = Forward;


}

void Reverse()
{
  Serial.println("reverse");
  digitalWrite(EN_r, HIGH);
  //digitalWrite(EN_l, HIGH);
  digitalWrite(pwm_right, LOW);
  analogWrite(pwm_left, usSpeed);
  usMotor_Status = Reverse;


}

void IncreaseSpeed() {
  usSpeed = usSpeed + 10;
  if(usSpeed > 255)
  {
    usSpeed = 255;  
  }
  if (usMotor_Status = Forward){
    Forward();
  } else if (usMotor_Status = Reverse) {
    Reverse();
  }
  
  Serial.print("Speed +: ");
  Serial.println(usSpeed);


}

void DecreaseSpeed() {
  usSpeed = usSpeed - 10;
  if(usSpeed < 0)
  {
    usSpeed = 0;  
  }
  if (usMotor_Status = Forward){
    Forward();
  } else if (usMotor_Status = Reverse) {
    Reverse();
  }
  
  Serial.print("Speed -: ");
  Serial.println(usSpeed);


}

btw. just as a note, i have both enable pins wired together because in the tutorial i found, it said you could also just wrie them to 5v

I'm always curious about the projects people take on. What's the advantage of winding your own pick-ups?

Check all your if statements to make sure you have == and not =.
You could also use a switch..case block for processing the serial input instead of all the if..elses.

Have you had a look at this?

  if (usMotor_Status = Forward){
    Forward();
  } else if (usMotor_Status = Reverse) {
    Reverse();
  }

= is not ==

wow, wasn't expecting that fast of a response haha, the == did the thing thanks to all of you.

arduarn:
I'm always curious about the projects people take on. What's the advantage of winding your own pick-ups?

Check all your if statements to make sure you have == and not =.
You could also use a switch..case block for processing the serial input instead of all the if..elses.

i'm not aware of what a switch..case block is but it sounds interesting, i'm gonna look into it, and about the pick-up winding, there are quite some advantages, you always have the option for customization, since everything from wire thickness to the actual shape and dimentions of the pick-up affect the sound, sure there are a lot of great pickups on the market, but in some cases you are looking for something that may not have been made yet, or meybe you want to try and remake something that just kand of got lost in time so to say, it can also be cost effective sometimes, especcially in the case of extended range guitars, where the pickup market starts getting narrower, and finally there is the fact that you can make custom pickups that align with a custom multiscale, lots of extra possibilities when making your own, and its also kinda fun :D.

DKWatson:
no, not yet, thanks for the tip!!

Have you had a look at this?

evanmars:

  if (usMotor_Status = Forward){

Forward();
  } else if (usMotor_Status = Reverse) {
    Reverse();
  }




= is not ==

got it, thanks! :wink:

one quick other question, i'm trying to controll the speed and direction with a 20 step rotary encoder (without breakoutboard), and am facing the problem that when using the driver i use in combination with an lcd screen, leaves me with only pins 1, 12 and 13 to use for the rotary encoder, and i notice i need interrupt pins for this and the uno only has pin 1 and 2 as interupt...

Use pin change interrupts. Pin12 is PCINT4 and pin13 is PCINT5. Stay away from pin1.

and the uno only has pin 1 and 2 as interupt...

Wrong. The external interrupt pins are pins 2 and 3.

Move the LCD. The pins you are using for it do NOT have to have any special capabilities. The pins used for the encoder do.

hello, sorry for the late answer, thanks for the answers, yes, i mixed the numbers up, i meant pin 2 and 3, not sure how pin change interrupts would affect the working of the device, i have no experience with them, but from what i have come across readein, they dont seem to be the most efficient way of doing it, especially when the same program is trying to count revolutions at 1200 rpm, but i'll give it a try, in the mean time i found a topic on how to us a rotary encoder with only one interrupt pin, and it works, i only seem to have messed up somewhere, i suspect it has something to do with it having an isr and i'm combining it with while loops, something must be going wrong there, as for the lcd, i try to avoid rewiring it, because its on a breakout board that fits right ontop of the arduino, and i figure it would be quite some trouble to change that in a propper way

just measured, if i upload the example sketch, pin a and b from the encoder, which are pin 2 and 12 on the arduino uno, both measure around 4,8v to ground, it sets the internal pullup resistors for both of them, when i upload my sketch in wich i didnt change anything to the original example (except for the function it executes when you turn the knob), just put it in as a part of my scetch, now it detects one CCW pulse if i turn it or not, and despite the pullup resistoors, pin 12 measures the normal 4,8v aprox. and pin 2 measures 0-0,1v, the variables for pin 2 and 12 arent used for anything else than the rotary encoder... clueless...

this is my code (first half because its pretty longpretty long):

#include <LiquidCrystal.h>
LiquidCrystal lcd(8,9,4,5,6,7);  
int Ver = 1;
//timing
unsigned long previousMillis = 0;
const long interval = 1000;
const long interval2 = 400;
int Blinkstate = 0;

volatile bool fired;
volatile bool up;
int usMotor_Status;
int pwm_right=3;
int pwm_left=11;

int EN_l=13;
int RevSpeed;
const int buttonPin = A1; //red
int buttonState = 0;
short usSpeed = 0;
const byte encoderPinA = 2; //white
const byte encoderPinB = 12; //greem
int stationary = 0;
unsigned int stopV[5] = {0,0,0,0,0};
int stop_var_n= 0;

//lcd variables
bool executable = false;
unsigned int charsel = 4;
unsigned int stopvar;
int stopvarC = 0;
int sens_pin = A2;
int screen_delay =500;
unsigned int count = 0;
unsigned int sens_outp = 0;
unsigned int sens_temp_state = 0;
int keypad_pin = A0;
int keypad_value = 0;
int keypad_value_old = 0;
char btn_push;
byte mainMenuPage = 1;
byte mainMenuPageOld = 1;
byte mainMenuTotal = 4;
 
// Interrupt Service Routine for a change to encoder pin A
void isr ()
{
  if (digitalRead (encoderPinA))
    up = digitalRead (encoderPinB);
  else
    up = !digitalRead (encoderPinB);
  fired = true;
}  // end of isr


void setup() {
  pinMode(pwm_right, OUTPUT);
  pinMode(pwm_left, OUTPUT);

  pinMode(EN_l, OUTPUT);
  pinMode(buttonPin, INPUT);
  pinMode (encoderPinA, INPUT_PULLUP);     // enable pull-ups
  pinMode (encoderPinB, INPUT_PULLUP); 
  attachInterrupt (digitalPinToInterrupt (encoderPinA), isr, CHANGE);   // interrupt 0 is pin 2
  usMotor_Status = 0;
  // put your setup code here, to run once:
  Serial.begin(9600); 
  Serial.println("1. STOP");
  Serial.println("2. FORWARD");
  Serial.println("3. REVERSE");
  Serial.println("4. READ CURRENT");
  Serial.println("+. INCREASE SPEED");
  Serial.println("-. DECREASE SPEED");
  Serial.println();
  lcd.begin(16,2);  //Initialize a 2x16 type LCD
  pinMode(keypad_pin, INPUT);
  pinMode(sens_pin, INPUT);
  lcd.setCursor(2,0);
  MainMenuDisplay();
}

void loop() 
{
  //menu loop stuff
  btn_push = ReadKeypad();
   
    MainMenuBtn();
   
    if(btn_push == 'S')//enter selected menu
    {
        WaitBtnRelease();
        switch (mainMenuPage)
        {
            case 1:
              MenuA();
              break;
            case 2:
              MenuB();
              break;
            
        }
 
          MainMenuDisplay();
          WaitBtnRelease();
    }
   
 
 
    //delay(10);
    
}

void MenuA()
{  
    lcd.clear();
    stop_var_n = 0;
    
    while(ReadKeypad()!= 'L')
    {
    Serial.println(up);
      char user_input;   
      while(Serial.available())
  {
    user_input = Serial.read(); //Read user input and trigger appropriate function
     
    if (user_input =='1')
    {
       Stop();
    }
    else if(user_input =='2')
    {
      Forward();
    }
    else if(user_input =='3')
    {
      Reverse();
    }
    else if(user_input =='+')
    {
      IncreaseSpeed();
    }
    else if(user_input =='-')
    {
      DecreaseSpeed();
    }
    else
    {
      Serial.println("Invalid option entered.");
    }
      
  }
  buttonState = analogRead(buttonPin);
  
  if (stationary != 0) {
      if ((buttonState == 0)){
      Stop();
      stationary = 0;
      delay(500);
      
      }
  }
  
  if (fired)
    {
    if (up) {
      IncreaseSpeed();
      
    }
    else {
      DecreaseSpeed();
      
    }
    delay(20);
    fired = false;

    
    }  // end if fired
  
  
  
    lcd.setCursor(0,0);
    lcd.print("turns =");
    
    Count();
 
    }
    count = 0;
    stopvarC = 0;
    stopV[0] = 0;
    stopV[1] = 0;
    stopV[2] = 0;
    stopV[3] = 0;
    stopV[4] = 0;
    Blinkstate = 0;
    usMotor_Status = 0;
}
void MenuB()
{  
    lcd.clear();
    stop_var_n = 1;
    while(ReadKeypad()!= 'L')
    {
      char user_input;   
       while(Serial.available())
  {
    user_input = Serial.read(); //Read user input and trigger appropriate function

    if (user_input =='1')
    {
       Stop();
    }
    else if(user_input =='2')
    {
      Forward();
    }
    else if(user_input =='3')
    {
      Reverse();
    }
    else if(user_input =='+')
    {
      IncreaseSpeed();
    }
    else if(user_input =='-')
    {
      DecreaseSpeed();
    }
    else
    {
      Serial.println("Invalid option entered.");
    }
      
  }
      if ((stationary != 0) && (count == stopvar)) {
      
      Stop();
      stationary = 0;
      delay(500);
    }
  buttonState = analogRead(buttonPin);
  
  if (stationary != 0) {
      if ((buttonState == 0)){
      Stop();
      stationary = 0;
      delay(500);
      
      }
  }
  
  if (fired)
    {
    if (up) {
      IncreaseSpeed();
      delay(20);
    }
    else {
      DecreaseSpeed();
      delay(20);
    }
    fired = false;

    
    }  // end if fired
 
    lcd.setCursor(0,0);
    lcd.print("turns =");
     
    
      while((ReadKeypad() != 'S') && (stopvarC == 0))
      {
        setStopVar();    
      }
  
  
    if (ReadKeypad() == 'S'){
      stopvarC = 0;
    }
    
    Count();
    lcd.setCursor(8,0);
    lcd.print(stopvar); 
    
    
    }
    count = 0;
    stopvarC = 0;
    stopV[0] = 0;
    stopV[1] = 0;
    stopV[2] = 0;
    stopV[3] = 0;
    stopV[4] = 0;
    Blinkstate = 0;
    usMotor_Status = 0;
}

 
void MainMenuDisplay()
{
    lcd.clear();
    lcd.setCursor(0,0);
    switch (mainMenuPage)
    {
        case 1:
          lcd.print("1. Handmatig");
          break;
        case 2:
          lcd.print("2. Autostop");
          break;
        case 3:
          lcd.print("3. Menu C");
          break;
        case 4:
          lcd.print("4. Menu D");
          break;
    }
}
 
void MainMenuBtn()
{
    WaitBtnRelease();
    if(btn_push == 'D')
    {
        mainMenuPage++;
        if(mainMenuPage > mainMenuTotal)
          mainMenuPage = 1;
    }
    else if(btn_push == 'U')
    {
        mainMenuPage--;
        if(mainMenuPage == 0)
          mainMenuPage = mainMenuTotal;    
    }
   
    if(mainMenuPage != mainMenuPageOld) //only update display when page change
    {
        MainMenuDisplay();
        mainMenuPageOld = mainMenuPage;
    }
}
 
char ReadKeypad()
{
  /* Keypad button analog Value
  no button pressed 1023
  select  741
  left    503
  down    326
  up      142
  right   0
  */
  keypad_value = analogRead(keypad_pin);
 
  if(keypad_value < 100)
    return 'R';
  else if(keypad_value < 200)
    return 'U';
  else if(keypad_value < 400)
    return 'D';
  else if(keypad_value < 600)
    return 'L';
  else if(keypad_value < 800)
    return 'S';
  else
    return 'N';
 
}
 
void WaitBtnRelease()
{
    while( analogRead(keypad_pin) < 800){}
}

and second half:

void Count() {
  sens_outp = analogRead(sens_pin);
  if (sens_outp < 400){
    sens_outp = 200;
    sens_temp_state = 1;
  }else if (sens_outp > 400){
    sens_outp = 900;
    sens_temp_state = 0;
    executable = true;
  }
  if ((sens_temp_state == 1) && (executable == true)) {
    if (usMotor_Status == 1){
    count = count +1;
    executable = false;
    lcd.setCursor(0,1);
    lcd.print("        ");
    } else if(usMotor_Status == 2){
    count = count -1;
    executable = false;
    lcd.setCursor(0,1);
    lcd.print("        ");
    }
  }

  if ((count == stopvar) && (stop_var_n != 0)) {
    lcd.setCursor(0,1);
    lcd.print(count);
    delay(screen_delay);
    lcd.setCursor(0,1);
    lcd.print("       ");
    delay(screen_delay);
    } else {
    
    lcd.setCursor(0,1);
    lcd.print(count);
    }
}

void setStopVar() {
  
  unsigned long currentMillis = millis();
  
  lcd.setCursor(8,0);
  lcd.print(stopV[0]);
  lcd.print(stopV[1]);
  lcd.print(stopV[2]);
  lcd.print(stopV[3]);
  lcd.print(stopV[4]);
  if (currentMillis - previousMillis >= interval2) {
  // save the last time you blinked the LED
  previousMillis = currentMillis;
 
  
  if (Blinkstate == 0){
  
  lcd.setCursor((charsel +8),1);
  lcd.print("^");
  Blinkstate = 1;
  } else if (Blinkstate == 1){
  lcd.setCursor((charsel +8),1);
  lcd.print(" ");
  Blinkstate = 0;
  } 
    if (ReadKeypad() == 'L') {
    lcd.setCursor((charsel +8),1);
    lcd.print(" ");
    charsel = charsel -1;
  } else if (ReadKeypad() == 'R'){
    lcd.setCursor((charsel +8),1);
    lcd.print(" ");
    if (charsel > 4){
      charsel = 4;
    } else {
    charsel = charsel +1;
    }
  }
  
  
  
  }

  if (ReadKeypad() == 'U'){
    if (stopV[charsel] >= 9){
      stopV[charsel] = 0;
    } else {
      stopV[charsel] = stopV[charsel] +1;
      
    }
    delay(250);
  }
  if (ReadKeypad() == 'D'){
    if (stopV[charsel] <= 0){
      stopV[charsel] = 9;
    } else{
      stopV[charsel] = stopV[charsel] -1;
      
    }
    delay(250);
  }
  if (ReadKeypad() != 'S') {
    stopvarC = 0;
  } else {
    stopvarC = 1;
    lcd.setCursor(8,0);
    lcd.print("      ");
    lcd.setCursor(8,1);
    lcd.print("      ");
    delay(1000);
  }
  
  stopvar = ((((stopV[0]*10+stopV[1])*10+stopV[2])*10+stopV[3])*10+stopV[4]);
  
}
void Stop()
{
  stationary = 0;
  Serial.println("Stop");

  digitalWrite(EN_l, LOW);
  digitalWrite(pwm_left, LOW);
  digitalWrite(pwm_right, LOW);
usMotor_Status= 0;
  usSpeed = 0;
  delay(10);


}

void Forward()
{
  
    stationary = 1;
  
  Serial.println("forward");

  digitalWrite(EN_l, HIGH);
  digitalWrite(pwm_left, LOW);
  usMotor_Status = 1;
  if (usSpeed <= 255){
  analogWrite(pwm_right, usSpeed);}
  


}

void Reverse()
{
  
    stationary = 1;
  
  Serial.println("reverse");

  digitalWrite(EN_l, HIGH);
  digitalWrite(pwm_right, LOW);
  usMotor_Status = 2;
  if (RevSpeed <= 255){
  analogWrite(pwm_left, RevSpeed);}
  


}

void IncreaseSpeed() {
  
  usSpeed = usSpeed + 5;
  if(usSpeed > 255)
  {
    usSpeed = 255;  
  }
  if (usSpeed > 0) {
    if((usSpeed > 0) && (usSpeed < 15)){
      usSpeed = 15;
    }
    
    Forward();
    
  }
  
  else if(usSpeed < 0)
  {
    if((usSpeed < 0) && (usSpeed > -15)){
      Stop();
      
    } else {
   RevSpeed = abs(usSpeed);
   Reverse();}
     
  }
  
  
  Serial.print("Speed +: ");
  Serial.println(usSpeed);


}

void DecreaseSpeed() {
  usSpeed = usSpeed - 5;
  
  if(usSpeed < 0)
  {
    if((usSpeed < 0) && (usSpeed > -15)){
      usSpeed = -15;
    }
   RevSpeed = abs(usSpeed);
   Reverse();
     if(usSpeed < -255) {
    usSpeed = -255;
  }
  }
  
  else if (usSpeed > 0) {
    if((usSpeed > 0) && (usSpeed < 15)){
      Stop();
    } else {
    
    Forward();}
  }
  
  
  Serial.print("Speed -: ");
  Serial.println(usSpeed);


}

but its a different problem than the one for this thread, so ill start a new one, thanks to everyone for the help! :slight_smile: