Help please - Motor RPM maintenance (PID control)

Hi all

I need to maintain a nearly constant DC motor speed (approx. 1000 rpm) under variable load. I'm wondering whether anyone has done something similar before, or could give me any advice on coding etc.

I have:

-a motor driven by a power device and a motor driver
-a hall sensor for measuring rotation speed

I'm using an Arduino with sensor reading as input(pin 2), and desired speed as output(pin 3(pwm 0-255)) to the motor.

So far I have achieved - telling the motor to run at a pre-set speed, and display the sensor reading on screen.

Next step I'll need to write some codes (using PID control) so that when the sensor reading changes as a result of pressure, the output to the motor can be adjusted based on the errors so that the actual motor speed can be maintained.

I've seen others using a motor with encoder to achieve this using PID control. Is it possible to do it without an encoder at all? Any thoughts on the coding or examples please?

If not possible is it because of the sensitivity of the sensor, or for some other reasons? And if I really need an encoder to do this, or if an encoder will significantly reduce the efforts required, which not-too-expensive encoder would do the job?

Any advice/thoughts would be greatly appreciated!

I use this program to control the speed of a small DC motor

const byte fwdPin = 9;
const byte revPin = 10;
const byte potPin = A1;

int potVal;
int pwmVal;

unsigned long revMicros;
unsigned long prevRevMicros;
unsigned long revDuration;
unsigned long revCount;

unsigned long prevDisplayMillis;
unsigned long  displayInterval = 1000;

    // variables for the ISR
volatile unsigned long isrMicros;
volatile unsigned long isrCount;
volatile bool newIsrMicros = false;



void setup() {
    Serial.begin(115200);
    Serial.println("SimpleISRdemo.ino");
    pinMode (fwdPin, OUTPUT);
    pinMode (revPin, OUTPUT);

    isrCount = 0;
    attachInterrupt(0, revDetectorISR, RISING);
}

//==========

void loop() {
    getIsrData();
    if (millis() - prevDisplayMillis >= displayInterval) {
        prevDisplayMillis += displayInterval;
        showData();
        readPot();
        updateMotorSpeed();
    }
}

//===========

 void readPot() {
    potVal = analogRead(potPin);
}

//===========

void updateMotorSpeed() {
    pwmVal = potVal >> 2;

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

//===========

void getIsrData() {
    if (newIsrMicros == true) {
        prevRevMicros = revMicros; // save the previous value
        noInterrupts();
            revMicros = isrMicros;
            revCount = isrCount;
            newIsrMicros = false;
        interrupts();
        revDuration = revMicros - prevRevMicros;
    }
}

//===========

void showData() {
    Serial.println();
    Serial.println("===============");
    Serial.print("PWM Val "); Serial.println(pwmVal);
    Serial.print("  Rev Duration ");
    Serial.print(revDuration);
    Serial.print("  Rev Count ");
    Serial.print(revCount);
    Serial.println();
}

//===========

void revDetectorISR() {
    isrMicros = micros();
    isrCount ++;
    newIsrMicros = true;

}

I use an optical detector but I expect it would also work with a hall effect detector

...R

You just need some sort of feedback. The advantage of an optical encoder is that it usually has many counts per revolution whereas with a Hall effect sensor you probably only get a couple counts per revolution (except with a gear motor where there can be many motor revolutions per output shaft revolution). So with the optical encoder you would get more fine grained feedback. At 1000 RPM I don't think using the hall sensor will cause any significant problems.

pert:
The advantage of an optical encoder is that it usually has many counts per revolution

I should have mentioned in Reply #1 that my optical detector produces one pulse per revolution.

...R

pert:
You just need some sort of feedback. The advantage of an optical encoder is that it usually has many counts per revolution whereas with a Hall effect sensor you probably only get a couple counts per revolution (except with a gear motor where there can be many motor revolutions per output shaft revolution). So with the optical encoder you would get more fine grained feedback. At 1000 RPM I don't think using the hall sensor will cause any significant problems.

Thanks, but the problem is that 1000rpm is my least requirement, in further work, I will need 2000 or even 3000rpm.

That's fine. I only meant that, at the relatively high 1000 RPM, you don't really need more than one feedback per revolution because you're probably not going to need to adjust the motor speed more often than once per revolution. If the RPMs were much lower then you might actually want a higher resolution feedback so that you could adjust the motor speed more frequently.