Go Down

Topic: Brushed DC Motor Speed Control with Incremental Encoder (Read 3279 times) previous topic - next topic

Sarisayko

Hello,
I'm going to make a DC motor speed control system with arduino as a course project. My aim is holding the speed constant against torque change. I
have basic knowledge about functions in arduino IDE. I made some projects from Arduino Starter Kit Manual. I'm using DME34BE50 12V brushed DC
motor with a single channel incremental encoder. I want to drive the motor at 5kHz. I have no problem with driver circuit, but I couldn't handle the
code. First, I tried to calculate the encoder output frequency difference between "no load" and "with load" states. According the difference, PWM
output of arduino should have changed (increase or decrease of duty cycle) to reach constant speed. I have googled to find a solution for days, but i
couldn't find one. There were some sample codes about encoders, but they were complicated for me. I need help and guidance about this problem.


Here is the code I wrote which didn't work:


Code: [Select]
int duty = 30; /* duty cycle - on time */

int encoderpin = 10;

int pwm_pin = 9;

void setup() {               
  pinMode(encoderpin, INPUT);  /*encoder input*/   
  pinMode(pwm_pin, OUTPUT);    /*pwm output*/
 
}

void loop() {
 
  unsigned long changeTime1; /*time when first squarewave from encoder gained*/
 
  unsigned long changeTime2; /*time when second squarewave from encoder gained*/
 
  int state = digitalRead(encoderpin);
 
  digitalWrite(pwm_pin, HIGH);   /* motor pwm on*/
 
  delayMicroseconds(duty);             
 
  digitalWrite(pwm_pin, LOW);    /*motor pwm off*/
 
  delayMicroseconds(200-duty);
 
    int y = 0;
 
    if (state == HIGH && y<3) {y++;}
 
    if (y == 1) {changeTime1 = micros();} /*first squarewave from encoder*/
 
    if (state == HIGH && y<3) {y++;}
 
    if (y == 2) {changeTime2 = micros();} /*second squarewave from encoder*/

    if (changeTime2 - changeTime1 > 4430) {duty = duty + 5;} /* encoder squarewave period was 4420 microseconds @no load, tried to stay close to it*/
   
    if (changeTime2 - changeTime1 < 4410) {duty = duty - 5;}
   

}


MarkT

You are running your duty-cycle adjustment everytime round the loop when the encoder input is high.

You need to detect changes in the encoder pin state, you are not doing so.  To detect change you need a variable that records the state of the encoder pin last time round the loop to compare against.
[ I will NOT respond to personal messages, I WILL delete them, use the forum please ]

Sarisayko


You are running your duty-cycle adjustment everytime round the loop when the encoder input is high.

You need to detect changes in the encoder pin state, you are not doing so.  To detect change you need a variable that records the state of the encoder pin last time round the loop to compare against.


Can you show me what you mean on an example? I didn't get it.

MarkT

digitalRead() can't tell you a value changed, it can only tell you what it is now.

You don't care what it is now, you want to know if it has changed since the last time you looked.

Code: [Select]

int previous ;

void loop ()
{
  int current = digitalRead (pin) ;
  if (current != previous)
  {
    if (current)
    {
      // just changed to HIGH / true
    }
    else
    {
      // just changed to LOW / false
    }
  }
  previous = current ;
}
[ I will NOT respond to personal messages, I WILL delete them, use the forum please ]

Go Up