Go Down

Topic: DC motor / Encoder not responding correctly after reset (Read 3009 times) previous topic - next topic

metalman

Hello, I am having puzzling operation my DC motor project that only happens during power up or after reset.
First, a thank you to "KAS" on the forum( @ http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1282384853) as I am using this code.

I am trying to control a DC motor to go to 3 discrete positions, using 3 buttons, as described below:
Push button 1: motor turns forwards 1 revolution
Push button 2: motor turns forwards 2 revolutions
Push button 3: motor turns backwards 1 revolution

This code is working wonderfully except right after reset - if I push button 3 first I get 1 rev backwards (which is correct), then if I push button 2 next I get 4 revs forwards, not my desired 2 revs forwards.
I tried a debounce after each button push, suspecting that button 2 may be incorrectly pressed twice, but any other combination of button pushes after a re-set works fine without a debounce, and after this initial incorrect 4 forward revs, then I can push buttons in any combination and the DC motor responds correctly and will never do the 4 revs again after pushing button #2.

I am using an Uno board,
using this motor driver board from Pololu: http://www.pololu.com/catalog/product/708
And this motor with encoder from pololu. http://www.pololu.com/catalog/product/1447

I admit to having a pretty poor level of understanding of everything that is going on in this code and I have tried a couple of things (for the last two days) based off hunches but to no avail.
The only thing that makes a change is if I change button #2 to only go 1 revolution, then the motor responds correctly to any combination of button pushes after a reset.
I tried to set up the serial read to help with trouble shooting, but soon realized I do not have the knowledge to set up variables to show my encoder direction and count #.

Below is my code, any suggestions or insight is appreciated.

Code: [Select]
// MD03A_Motor_basic + encoder
//credit to: KAS http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1282384853
//
#define InA1        10      // Pin 10, goes to Pololu INA motor direction pin (low forward, high reverse)
#define InB1        11      // Pin 11, goes to Pololu INB motor direction pin (low reverse, high forward)
#define PWM1        6       // Pin 6, goes to Pololu PWM pin (speed)
#define encodPinA1  3       // Pin 3, reads encoder A signal (yellow)
#define encodPinB1  8       // Pin 8, reads encoder B signal (White)
#define FORWARD     1       //
#define BACKWARD    2      //
#define buttonPin   A0      // Analog pin A0, reads Voltage of button 1, 2, or 3
//#define LOOPTIME    100     // PID loop time - what is this ?

unsigned long lastMilli = 0;       // loop timing
unsigned long lastMilliPrint = 0;  // loop timing
long count = 0;                   // rotation counter
long countInit;
long tickNumber = 0;
boolean run = false;         // motor moves
int buttonValue = 0;       // defines switchValue as an interger, sets value at 0 (of 0 -1000)
//

void setup() {
  pinMode(InA1, OUTPUT);           // direction to Pololu motor board
  pinMode(InB1, OUTPUT);           // direction to Pololu motor board
  pinMode(PWM1, OUTPUT);           // PWM output to Pololu motor board
  pinMode(encodPinA1, INPUT);      // input from encoder
  pinMode(encodPinB1, INPUT);      // input from encoder
  pinMode(buttonPin,INPUT);           // pin A0, reads V input from buttons
  digitalWrite(encodPinA1, HIGH);      // turn on pullup resistor pin 10
  digitalWrite(encodPinB1, HIGH);      // turn on pullup resistor pin 11
  attachInterrupt(1, rencoder, FALLING);
  Serial.begin(9600);                 // set up Serial library at 9600 bps
}

void loop() {

  buttonValue = analogRead(buttonPin);   // Read Voltage on pin A0
  if(buttonValue>940)                   // Button #1 470 resistor 992 max (1023=5v)
    moveMotor(FORWARD, 250, 2000*1);      // direction, PWM (speed), ticks number (2000=360°)

  buttonValue = analogRead(buttonPin);
  if(buttonValue>750 && buttonValue<800)  // Button #2 4.7k resistor  790 max, min = less than bttn #1
    moveMotor(FORWARD, 250, 2000*2);        // direction, PWM (speed), ticks number (2000=360°)   

  buttonValue = analogRead(buttonPin);
  if(buttonValue>600 && buttonValue<630)  // Button #3 10k resistor  620 max, min = less than bttn #2
    moveMotor(BACKWARD, 250, 2000*1);       // direction, PWM (speed), ticks number (2000=360°)

}
void moveMotor(int direction, int PWM_val, long tick)  {
  countInit = count;                                // abs(count)
  tickNumber = tick;
  if(direction==FORWARD)          motorForward(PWM_val);
  else if(direction==BACKWARD)    motorBackward(PWM_val);
}

void rencoder()  {                           // pulse and direction, direct port reading to save cycles
  if (PINB & 0b00000001)    count++;         // if(digitalRead(encodPinB1)==HIGH)   count_r ++;
  else                      count--;         // if(digitalRead(encodPinB1)==LOW)   count_r --;
  if(run) 
    if((abs(abs(count)-abs(countInit))) >= tickNumber)     
      motorBrake();
}

void motorForward(int PWM_val)  {
  analogWrite(PWM1, PWM_val);
  digitalWrite(InA1, LOW);
  digitalWrite(InB1, HIGH);
  run = true;
}

void motorBackward(int PWM_val)  {
  analogWrite(PWM1, PWM_val);
  digitalWrite(InA1, HIGH);
  digitalWrite(InB1, LOW);
  run = true;
}

void motorBrake()  {
  analogWrite(PWM1, 0);
  digitalWrite(InA1, HIGH);
  digitalWrite(InB1, HIGH);
  run = false;
}

johnwasser

When you start out with count=0 and press 3 you now have count=-2000.  I think the problem is that you are using the abs() function a lot and therefore can't tell the difference between -2000 and +2000.

Why not just set count to 0 and increment it until you reach tick?  The direction is taken care of by the motor controller.
Send Bitcoin tips to: 1L3CTDoTgrXNA5WyF77uWqt4gUdye9mezN
Send Litecoin tips to : LVtpaq6JgJAZwvnVq3ftVeHafWkcpmuR1e

metalman

thanks for the quick reply, I understand your point, but not sure that I can execute it in code!

johnwasser

I was thinking of something like this:

Code: [Select]

// MD03A_Motor_basic + encoder
//credit to: KAS http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1282384853
//
const int InA1       = 10;      // Pin 10, goes to Pololu INA motor direction pin (low forward, high reverse)
const int InB1       = 11;      // Pin 11, goes to Pololu INB motor direction pin (low reverse, high forward)
const int PWM1    =    6;       // Pin 6, goes to Pololu PWM pin (speed)
const int encodPinA1 =  3;       // Pin 3, reads encoder A signal (yellow)
const int encodPinB1  = 8;       // Pin 8, reads encoder B signal (White)
const int FORWARD   =  1;       //
const int BACKWARD  =  2;      //
const int buttonPin =  A0;      // Analog pin A0, reads Voltage of button 1, 2, or 3

unsigned long lastMilli = 0;       // loop timing
unsigned long lastMilliPrint = 0;  // loop timing
volatile long count = 0;              // motion counter
volatile long ticks = 0;              // motion end point
volatile boolean run = false;         // motor moves

int buttonValue = 0;       // defines switchValue as an interger, sets value at 0 (of 0 -1000)

//

void setup() {
  pinMode(InA1, OUTPUT);           // direction to Pololu motor board
  pinMode(InB1, OUTPUT);           // direction to Pololu motor board
  pinMode(PWM1, OUTPUT);           // PWM output to Pololu motor board
  pinMode(encodPinA1, INPUT);      // input from encoder
  pinMode(encodPinB1, INPUT);      // input from encoder
  pinMode(buttonPin,INPUT);           // pin A0, reads V input from buttons
  digitalWrite(encodPinA1, HIGH);      // turn on pullup resistor pin 10
  digitalWrite(encodPinB1, HIGH);      // turn on pullup resistor pin 11
  attachInterrupt(1, rencoder, FALLING);
  Serial.begin(9600);                 // set up Serial library at 9600 bps
}

void loop() {

  buttonValue = analogRead(buttonPin);   // Read Voltage on pin A0
  if(buttonValue>940)                   // Button #1 470 resistor 992 max (1023=5v)
    moveMotor(FORWARD, 250, 2000*1);      // direction, PWM (speed), ticks number (2000=360°)

  buttonValue = analogRead(buttonPin);
  if(buttonValue>750 && buttonValue<800)  // Button #2 4.7k resistor  790 max, min = less than bttn #1
    moveMotor(FORWARD, 250, 2000*2);        // direction, PWM (speed), ticks number (2000=360°)   

  buttonValue = analogRead(buttonPin);
  if(buttonValue>600 && buttonValue<630)  // Button #3 10k resistor  620 max, min = less than bttn #2
    moveMotor(BACKWARD, 250, 2000*1);       // direction, PWM (speed), ticks number (2000=360°)

}
void moveMotor(int direction, int PWM_val, long tick)  {
  count = 0;                                // abs(count)
  ticks = tick;
  if(direction==FORWARD)   
    motorForward(PWM_val);
  else
    if(direction==BACKWARD)   
    motorBackward(PWM_val);
}

void rencoder()
{                           // pulse and direction, direct port reading to save cycles
  count++;
  if(run && count >= ticks)     
    motorBrake();
}

void motorForward(int PWM_val)  {
  analogWrite(PWM1, PWM_val);
  digitalWrite(InA1, LOW);
  digitalWrite(InB1, HIGH);
  run = true;
}

void motorBackward(int PWM_val)  {
  analogWrite(PWM1, PWM_val);
  digitalWrite(InA1, HIGH);
  digitalWrite(InB1, LOW);
  run = true;
}

void motorBrake()  {
  analogWrite(PWM1, 0);
  digitalWrite(InA1, HIGH);
  digitalWrite(InB1, HIGH);
  run = false;
}
Send Bitcoin tips to: 1L3CTDoTgrXNA5WyF77uWqt4gUdye9mezN
Send Litecoin tips to : LVtpaq6JgJAZwvnVq3ftVeHafWkcpmuR1e

metalman

ahh,  I was making this too complicated, I will give this code a try, thank you, I have a lot to learn!

metalman

I decided to give it a try on my own, and made a nice mess of it, ran your code and it worked fine.
thank you!

metalman

Need helo again - I am trying to serial print the encoder count once every two seconds.
I commented out some of the loop functions so that I was just looking at one button push.
Can you take a look at my "printcount" function at the end of this code and suggest how I can print the encoder count every two seconds for just one line?
thank you



Code: [Select]
// MD03A_Motor_basic + encoder
//credit to: KAS http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1282384853
// credit to JohnWasser
//
const int InA1       = 10;      // Pin 10, goes to Pololu INA motor direction pin (low forward, high reverse)
const int InB1       = 11;      // Pin 11, goes to Pololu INB motor direction pin (low reverse, high forward)
const int PWM1    =    6;       // Pin 6, goes to Pololu PWM pin (speed)
const int encodPinA1 =  3;       // Pin 3, reads encoder A signal (yellow)
//const int encodPinB1  = 8;       // Pin 8, reads encoder B signal (White)
const int FORWARD   =  1;       //
const int BACKWARD  =  2;      //
const int buttonPin =  A0;      // Analog pin A0, reads Voltage of button 1, 2, or 3
unsigned long lastMilli = 0;       // loop timing
unsigned long lastMilliPrint = 0;  // loop timing
volatile long count = 0;              // motion counter
volatile long ticks = 0;              // motion end point
volatile boolean run = false;         // motor moves
int buttonValue = 0;       // defines switchValue as an interger, sets value at 0 (of 0 -1023)

long previousMillis = 0;        // will store last time LED was updated
long interval = 200;           // interval at which to print

long wait  =  2000;
long currentMillis = 0;
//

void setup() {
  pinMode(InA1, OUTPUT);           // direction to Pololu motor board
  pinMode(InB1, OUTPUT);           // direction to Pololu motor board
  pinMode(PWM1, OUTPUT);           // PWM output to Pololu motor board
  pinMode(encodPinA1, INPUT);      // input from encoder
  //pinMode(encodPinB1, INPUT);      // input from encoder
  pinMode(buttonPin,INPUT);           // pin A0, reads V input from buttons
  digitalWrite(encodPinA1, HIGH);      // turn on pullup resistor pin 10
  //digitalWrite(encodPinB1, HIGH);      // turn on pullup resistor pin 11
  attachInterrupt(1, rencoder, FALLING);
  Serial.begin(9600);                 // set up Serial library at 9600 bps
 
}

void loop()
          {
           
  buttonValue = analogRead(buttonPin);   // Read Voltage on pin A0
  if(buttonValue>940)                   // Button #1 470 resistor 992 max (1023=5v)
    moveMotor(FORWARD, 250, 2000*1);      // direction, PWM (speed), ticks number (2000=360°)
   
  printCount(); 
   
  //buttonValue = analogRead(buttonPin); 
    //if(buttonValue>750 && buttonValue<800)  // Button #2 4.7k resistor  790 max, min = less than bttn #1
    //moveMotor(FORWARD, 250, 2000*2);        // direction, PWM (speed), ticks number (2000=360°)   
 
  //buttonValue = analogRead(buttonPin); 
  //if(buttonValue>600 && buttonValue<630)  // Button #3 10k resistor  620 max, min = less than bttn #2
    //moveMotor(BACKWARD, 250, 2000*1);       // direction, PWM (speed), ticks number (2000=360°)
 
}

void moveMotor(int direction, int PWM_val, long tick)  {
  count = 0;                                // abs(count)
  ticks = tick;
  if(direction==FORWARD)   
    motorForward(PWM_val);
  else
    if(direction==BACKWARD)   
    motorBackward(PWM_val);
}
void rencoder() {                           // pulse and direction, direct port reading to save cycles
  count++;
  if(run && count >= ticks)     
    motorBrake();
}

void motorForward(int PWM_val)  {
  analogWrite(PWM1, PWM_val);
  digitalWrite(InA1, LOW);
  digitalWrite(InB1, HIGH);
  run = true;
}

void motorBackward(int PWM_val)  {
  analogWrite(PWM1, PWM_val);
  digitalWrite(InA1, HIGH);
  digitalWrite(InB1, LOW);
  run = true;
}

void motorBrake()  {
  analogWrite(PWM1, 0);
  digitalWrite(InA1, HIGH);
  digitalWrite(InB1, HIGH);
  run = false;
}

void printCount()  {
   currentMillis == millis();   
   if (currentMillis + wait <= millis())
    Serial.println(count);   
}

MohitJindal

well i want to use magnetic encoder. AS5040 or AS5145. Can anyone modify the code above to work with As5040 ? I want to get the position/angle of dc motor. :~

zahrah

hello sir
sir ( metalman), the coding that you post, i did try it as i am programing an encoder dc gear motor.
but sir when i did put it in the h bridge, it is not working.y
??
:(

zahrah

hello sir
sir ( metalman), the coding that you post, i did try it as i am programing an encoder dc gear motor.
but sir when i did put it in the h bridge, it is not working.y
??
:(

Go Up
 


Please enter a valid email to subscribe

Confirm your email address

We need to confirm your email address.
To complete the subscription, please click the link in the email we just sent you.

Thank you for subscribing!

Arduino
via Egeo 16
Torino, 10131
Italy