# Interrupts to read from a rotary encoder with Matlab

Hey all,

I am trying to use an Arduino to reda data coming from a rotary quadrature encoder (so, two channels in a 90deg phase). Right now I am connecting the two outputs of my encoder to digital pins 2 and 3 of my Uno to be used as interrupts, and then I am using Matlab's rotaryEncoder function to calculate the rpm. The program, however, crashes when the speed goes higher than 2000 rpm. My encoder has a resolution of 500 counts per rev, and at 2000 rpm my encoder sends the Arduino a square wave with ~20kHz of frequency, for a total of 40k interrupts per seconds for each pin.

Is this frequency too high for the Aduino to read properly, or is it a problem with Matlab's implementation?

turn off interrupts on one pin unless speed is slower you already know the direction once the speed is up.

My encoder has 400 pulses per revolution and this code works well at high speeds

``````#define ClockPin 3 // Must be pin 2 or 3
//#define DataPin 9 // can be any other pin

// My Encoder has 400 Clock pulses per revolution
// note that 150000.0 = (60 seonds * 1000000 microseconds)microseconds in a minute / 400 pulses in 1 revolution)
// change the math to get the proper multiplier for RPM for your encoder
// yours has 4 pulses in 1 revolution
// note that 150000.0 = (60 seonds * 1000000 microseconds)microseconds in a minute / 4 pulses in 1 revolution)
#define Multiplier 15000000.0 // don't forget a decimal place to make this number a floating point number
volatile long count = 0;
volatile long EncoderCounter = 0;
volatile int32_t dTime; // Delt in time
volatile bool DataPinVal;

void onPin2CHANGECallBackFunction() {
static uint32_t lTime; // Saved Last Time of Last Pulse
uint32_t cTime; // Current Time
cTime = micros(); // Store the time for RPM Calculations

/*
// Encoder Code
// We know pin 2 just went high to trigger the interrupt
// depending on direction the data pin will either be high or low
EncoderCounter += (DataPinVal) ? 1 : -1; // Should we step up or down?
// End Encoder Code
*/
// calculate the DeltaT between pulses
dTime = cTime - lTime;
lTime = cTime;

}

void setup() {
Serial.begin(115200); //115200
// put your setup code here, to run once:
pinMode(ClockPin, INPUT);
//  pinMode(DataPin, INPUT);
attachInterrupt(digitalPinToInterrupt(ClockPin), onPin2CHANGECallBackFunction, RISING);
}

void loop() {
//  long Counter;
// bool DataPinValue
float DeltaTime;
float SpeedInRPM = 0;

// Serial print is slow so only use it when you need to (10 times a second)
static unsigned long SpamTimer;
if ( (unsigned long)(millis() - SpamTimer) >= (100)) {
SpamTimer = millis();
noInterrupts ();
// Because when the interrupt occurs the EncoderCounter and SpeedInRPM could be interrupted while they
// are being used we need to say hold for a split second while we copy these values down. This doesn't keep the
// interrupt from occurring it just slightly delays it while we maneuver values.
// if we don't do this we could be interrupted in the middle of copying a value and the result get a corrupted value.
//  Counter = EncoderCounter;
//  DataPinValue = DataPinVal;
DeltaTime = dTime;
dTime = 0; // if no pulses occure in the next 100 miliseconds then we must assume that the motor has stopped this allows a speed of zero to occure
interrupts ();
//   SpeedInRPM = Multiplier / ((DataPinValue) ? DeltaTime: (-1 * DeltaTime)); // Calculate the RPM Switch DeltaT to either positive or negative to represent Forward or reverse RPM
SpeedInRPM = Multiplier / DeltaTime; // Calculate the RPM Switch DeltaT to either positive or negative to represent Forward or reverse RPM
//   Serial.print(Counter );
//   Serial.print("\t");
Serial.print(SpeedInRPM , 3);
Serial.print(" RPM");
Serial.println();
}
}
``````

Z

Presumably you are sending something to Matlab over the serial port. What baud rate are you using?
Why are you using Matlab to calculate something that the Arduino could do just as easily?

Post your code - in code tags (the </> icon)

Pete