Go Down

Topic: DC motor / Encoder not responding correctly after reset (Read 2793 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