Go Down

Topic: Measuring speed of DC motor using rotary encoder and UNO (Read 1 time) previous topic - next topic

akzmn

Hi everyone... I am trying to use Arduino Uno to measure the speed of a DC motor and display it on a LCD. Below is the code that I use....This is part of a bigger system where an Arduino Mega is controlling the motors....Here is the strange happening: when I use different power supplies, I get different numbers for the motor speed...When I connect Uno to my laptop (usb) the readings are reasonable and close to actual RPM, but when I use a power supply (12V) which is also powering up Arduino Mega, I get much higher RPMs which are twice bigger than actual RPM. I will be grateful if anyone can help me with this situation.

(I am using Digital pin 2 as interrupt and since the rotation direction is always CW I only used channel A)


Code: [Select]

// Info:  Gear ratio of our motor (MMP D22-490D-24V GP52-019) is 19:1   & final output: 172 RPM  & for our encoder (EU-1024) CPR is 1024



#include <Wire.h>   
#include <LiquidCrystal_I2C.h>
#include <EasyTransfer.h>
volatile long counter = 0;

EasyTransfer ET;
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); 
struct DATA_STRUCTURE {
  int int_data;
  char char_data;
};

DATA_STRUCTURE myData;

void setup() {
  attachInterrupt(digitalPinToInterrupt(2), count, RISING);
  Serial.begin(9600);
  lcd.begin(20, 4);
  lcd.clear();
  lcd.setCursor(0, 0); //Start at character 0 on line 2
  lcd.print("User Setting: ");
  ET.begin(details(myData), &Serial);
  lcd.setCursor(0, 1);
  lcd.print(" >Speed (cm/s):");
  lcd.setCursor(0, 2);
  lcd.print(" >RPM (nozzle):");
}

void loop() {

  if (ET.receiveData())
  {
    if (myData.char_data == 109) {
      lcd.setCursor(16, 1);
      lcd.print("LS1");
    }
    else if (myData.char_data == 110) {
      lcd.setCursor(16, 1);
      lcd.print("LS2");
    }
    else if (myData.char_data == 111) {
      lcd.setCursor(16, 1);
      lcd.print("LS3");
    }
    else if (myData.char_data == 112) {
      lcd.setCursor(16, 1);
      lcd.print("LS4");
    }
    lcd.setCursor(0, 0);
    if (myData.int_data == 1) {
      lcd.setCursor(16, 2);
      lcd.print("20%");
    }
    else if (myData.int_data == 2) {
      lcd.setCursor(16, 2);
      lcd.print("40%");
    }
    else if (myData.int_data == 3) {
      lcd.setCursor(16, 2);
      lcd.print("60%");
    }
    else if (myData.int_data == 4) {
      lcd.setCursor(16, 2);
      lcd.print("100%");
    }
  }

  counter = 0;
  delay(5000);
  lcd.setCursor(0, 3);
  lcd.print("Actual RPM:  ");         //Here I want to report encoder reading (RPM)
    lcd.print((int)(float(counter)/19456.0*12.0)); //19*1024= 19456   (60sec/5sec=12)
    lcd.print("    "); 
}

void count() {
  counter++;
}

cattledog

Do you have an external pull up resistor to 5v on pin 2?

If not, try setting the pin mode of pin 2 as INPUT_PULLUP.

If the interrupt is only one one pin RISING, you can expect to see 1024/4 = 256 counts per revolution

MarkT

You should connect both A and B and handle quadrature properly or at low speeds vibration will give
very wrong (high) results.  You haven't said what speed you are testing at, I suspect its not just low
speed, so your issue is more likely to be noise or signal conditioning - its important with signals from
sensors near a motor to use shielded cable for the sensor and to run the cable well away from any
high current wiring going to the motor terminals (or its power source), since they put out loads
of electrical noise.

Adding a small capacitor (around 1nF) from each encoder output to ground will help suppress interference.
[ I will NOT respond to personal messages, I WILL delete them, use the forum please ]

Go Up