I wrote a program for position control of DC motor
/*******************************************************************************
*program to control dc motor using rotary encoder with 2 interuppts
*Utilises PID for controlling motor
*From PIDtune in MATLAB Kp = 0.0790, Ki = 0.0067604, Kd = 0.0016901
*Program written for Arduino Uno
*******************************************************************************/
#define encoder0PinA 2
#define encoder0PinB 3
#define motorACW 5
#define motorCW 6
#include <PID_v1.h>
volatile unsigned int encoder0Pos = 0, Error;
double Setpoint, Input, Output; //Define variables we will be connecting to
PID motorControl(&Input, &Output, &Setpoint, 0.079042, 0.0067604, 0.0016901, DIRECT); //Specify the links and initial tuning parameters
void setup() {
pinMode(encoder0PinA, INPUT);
pinMode(encoder0PinB, INPUT);
pinMode(motorCW, OUTPUT);
pinMode(motorACW, OUTPUT);
attachInterrupt(0, doEncoderA, CHANGE); // encoder pin on interrupt 0 (pin 2)
attachInterrupt(1, doEncoderB, CHANGE); // encoder pin on interrupt 1 (pin 3)
Input = encoder0Pos;
Setpoint = 1000;
motorControl.SetMode(AUTOMATIC);
motorControl.SetOutputLimits(100,255);
Serial.begin (9600);
}
void loop(){
Input = encoder0Pos;
motorControl.Compute();
Error = Setpoint - encoder0Pos;
if (Error > 0){
analogWrite(motorCW,Output);
digitalWrite(motorACW,LOW);
}
else if (Error < 0){
digitalWrite(motorCW,LOW);
analogWrite(motorACW,Output);
}
}
void doEncoderA(){
if (digitalRead(encoder0PinA) == HIGH) // look for a low-to-high on channel A
{
if (digitalRead(encoder0PinB) == LOW) // check channel B to see which way encoder is turning
{
encoder0Pos = encoder0Pos + 1; // CW
}
else
{
encoder0Pos = encoder0Pos - 1; // CCW
}
}
else // must be a high-to-low edge on channel A
{
if (digitalRead(encoder0PinB) == HIGH) // check channel B to see which way encoder is turning
{
encoder0Pos = encoder0Pos + 1; // CW
}
else {
encoder0Pos = encoder0Pos - 1; // CCW
}
}
Serial.println (encoder0Pos, DEC);
}
void doEncoderB(){
if (digitalRead(encoder0PinB) == HIGH) // look for a low-to-high on channel B
{
if (digitalRead(encoder0PinA) == HIGH) // check channel A to see which way encoder is turning
{
encoder0Pos = encoder0Pos + 1; // CW
}
else
{
encoder0Pos = encoder0Pos - 1; // CCW
}
}
else // Look for a high-to-low on channel B
{
if (digitalRead(encoder0PinA) == LOW) // check channel B to see which way encoder is turning
{
encoder0Pos = encoder0Pos + 1; // CW
}
else {
encoder0Pos = encoder0Pos - 1; // CCW
}
}
}
To check whether motor is giving proper response to PWM signals or not I wrote a simple code mentioned below
//written for uno
#define motorCW 5
#define motorACW 6
void setup() {
pinMode(motorCW, OUTPUT);
pinMode(motorACW, OUTPUT);
}
void loop() {
digitalWrite(motorCW,LOW);
analogWrite(motorACW,150);
}
If I give pwm value below 150, motor doesn't moves properly and refuses to move below pwm value 100. Motor simply hums and the TIP 122/127 (in the h bridge circuit) heats up.
Using Pitmann motor GM9236 (Datasheet attached). Circuit of H - Bridge is attached
Is the problem due to H - Bridge not able to supply enough current?
What if I use motorControl.SetOutputLimits(150,255)? Will I get accurate motion?

9230_dc_motor.pdf (829 KB)
