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

Thread Starter

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
 

Thread Starter

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)
  {
    Serial.println ("please provide the rpm");
   }
  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:

Thread Starter

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 )
 

MaxHeadRoom

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

Thread Starter

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
 

Thread Starter

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

Thread Starter

shyank_1001

Joined Aug 16, 2021
8
actually the encoder I am using is having only four wires having only A phase and B phase and vcc and ground ( z PULSE comes from the fifth wire )
 
Top