# I am developing a feedback control system using arduino UNO , a simple dc geared motor and an optical incremental encoder (400 PPR) .

#### shyank_1001

Joined Aug 16, 2021
8
I am developing a feedback control system using Arduino UNO , a simple dc geared motor and an optical incremental encoder (400 PPR) . I am supposed to write a write a program using Arduino IDE such that I am able to provide RPM from from serial monitor to the Arduino UNO which will in turn provide the concerned PWM value to the L298 motor driver module. Due to this the motor will start rotating and the RPM will be read by the encoder and the RPM so read by the encoder will get printed on serial monitor in vertical format ( one below the other ) .Sir, I want to make this system such that it should be a complete closed loop system and should respond in a very quick manner ( I really don't know how quick ) but the response should be good . Kindly provide me the guidance and the code as soon as possible . Thank you

#### shyank_1001

Joined Aug 16, 2021
8
C:
# define PPR 400.0
const int phase_a = 2;
const int phase_b = 3;
volatile long pulse = 0;
int interval = 1000;
long pasttime, presenttime ;
long pastpulse, presentpulse;
float dt, disp;
int pwm;
float avg_rpm;
float rpm;
int pwm_pin = 9;
int mot_pin_1 = 8;
int mot_pin_2 = 7;
void setup()
{
pinMode (mot_pin_1, OUTPUT);
pinMode (mot_pin_2, OUTPUT);
pinMode (pwm_pin, OUTPUT);
pinMode (phase_a, INPUT_PULLUP);
pinMode (phase_b, INPUT_PULLUP);
Serial.begin (9600);
}
void loop()
{

if ( Serial.available () == 0)
{
}
if ( Serial.available () != 0)
{
attachInterrupt(digitalPinToInterrupt(3), updateEncoder, RISING);
pastpulse = pulse;
pasttime = millis();
avg_rpm = Serial.parseInt();
Serial.parseInt();
pwm = ((0.0005 * avg_rpm * avg_rpm * avg_rpm) - (0.002 * avg_rpm * avg_rpm) + (0.52 * avg_rpm) + 20.64);
analogWrite(pwm_pin, pwm);
digitalWrite(mot_pin_1, HIGH);
digitalWrite(mot_pin_2, LOW);
presenttime = millis();
presentpulse = pulse;

if ( presenttime - pasttime > 0)
{
disp = (presentpulse - pastpulse) / PPR;
dt = ( presenttime - pasttime) / 1000;
rpm = (disp / dt) * 60;
}
}
if ( rpm > 0)
{

Serial.print ("\t""\t""\t""\t");
Serial.print ( "you have provided the rpm as ...");
Serial.print (avg_rpm);
Serial.print ("\t""\t");
Serial.print ("RPM of the encoder is..... ");
Serial.println(rpm );
}
pulse = 0;
}
void updateEncoder()
{
pulse++;
}
kindly note that the forth given code is being used but I am not able to get the accurate avlue of the RPM from the encoder . Also there is a delay in printing of RPM if RPM is provided from the serial monitor . Kindly provide the solution to this problem

Mod edit: code tags - JohnInTX

Last edited by a moderator:

Joined Jul 18, 2013
23,803
You can achieve a higher feedback resolution by using all 4 edges of the A & B pulses to obtain 1600 PPR.

#### shyank_1001

Joined Aug 16, 2021
8
ok but how can it be used with interrupts ??

#### shyank_1001

Joined Aug 16, 2021
8
and also let me know how to go for one single time input from serial monitor rather than giving the input twice from serial ( as i am giving now )

Joined Jul 18, 2013
23,803
.Sir, I want to make this system such that it should be a complete closed loop system and should respond in a very quick manner
It would appear that all you are doing is controlling RPM rate rather than positioning?
The RPM with feedback could be done by just reading the Z pulse of the encoder. See PDF.
Also shows a version in C

#### Attachments

• 3.8 MB Views: 2

#### shyank_1001

Joined Aug 16, 2021
8
It would appear that all you are doing is controlling RPM rate rather than positioning?
The RPM with feedback could be done by just reading the Z pulse of the encoder. See PDF.
Also shows a version in C

Thank you so much for your attention ....i will be going through your pdf provided

#### shyank_1001

Joined Aug 16, 2021
8
this is my system and i am giving RPM ( say 300 RPM) using serial monitor as a command . Then from the serial monitor command ( RPM) the pwm wm is calculated as per the equation
pwm = ((0.0005 * avg_rpm * avg_rpm * avg_rpm) - (0.002 * avg_rpm * avg_rpm) + (0.52 * avg_rpm) + 20.64);
This PWM is provided to the the analog pin though analog write and then the motor is run . Then the encoder ( which is coupled to the motor shaft (black one )) reads the rpm and then sends it to arduino SERIAL MONITOR

My problem is that I have to give the RPM twice so that the rpm from motor gets printed. HowEVER I WANT THAT I WILL GIVE THE RPM ONCE AND THE RPM, WILL BE READ . This is not happening insted after giing the Rpm from serial monitor the motor starts rotating but the RPM only appears after giving the input twice. This will make my system out of sync .

#### Attachments

• 3.2 MB Views: 3