# STM 32 F446RE for calculating velocity of a motor using Encoder

## I am Using STM 32 F446RE with Arduino IDE for programming. Encoder will provide me 10000pulese per revolution and motor speed is 10rpm(max). I want to find out the exact velocity from that. I tried coding and ran into some error and not able to solve it. Please have look into the code and help me out. Also I have got couple of questions: Why interrupt is important for Encoder sensor? What is the need for pull up resistor?

//#include <RotaryEncoder.h>;

// Initialization
const int pinA = D0;
const int pinB = D2;
int counterA = 0;
int counterB = 0;
int digA = 0;
int digB = 0;
int prevCountA = 0;
int prevCountB = 0;
unsigned long time;
unsigned long currenttime;
const unsigned long period = 100; //the value is a number of milliseconds
float angle = 0;
float rpm = 0;

// the setup routine runs once when you press reset:
void setup()
{
// initialize serial communication at 9600 bits per second:
Serial.begin(9600);
// make the pushbutton's pin an input:
pinMode(pinA, INPUT_PULLUP);
pinMode(pinB, INPUT_PULLUP);

}

// the loop routine runs over and over again forever:
void loop()
{
// call encoder
time = millis();

call_encoder();
calc_vel();
// delay(1); // delay in between reads for stability
}

void call_encoder()
{
if (prevCountA != digA)
{
counterA = counterA+1;
}
if (prevCountB != digB)
{
counterB = counterB+1;
}
Serial.print("A");
Serial.print(counterA);
Serial.println();
Serial.print("B");
Serial.print(counterB);
Serial.println();
// Serial.print(digA);
// Serial.println();
//
// Serial.print(digB);
// Serial.println();
prevCountA = digA;
prevCountB = digB;
}

void calc_vel()
{
// currenttime = millis(); //get the current "time" (actually the number of milliseconds since the program started)
if (time >= period) //test whether the period has elapsed
{
angle = (counterA/200)*360;
rpm = angle/360;
Serial.print("rpm");
Serial.print(rpm);
Serial.println();
time = 0;
}

}

``````angle = (counterA/200)*360;
``````

with a quadrature encoder having 2 inputs there are 4 possible events per contact or vane passing across the inputs. I have experience with optical encoders using photo transistors to detect the crossing of vane between the detectors.

you appear to count a change at each input. if you have 200 vanes or contacts, counting the change at both inputs will result in 4 times the number of vanes or contacts. If you have 200 vane, you would count 800 after 1 revolution.

in order to get something working sanely, you don't need to count each change and it would be simpler to simply count a rising (or falling) edge at one input. if you have 200 vanes there should be 200 edges per rotation.

``````rpm = angle/360;
``````

the above is the number of rotations, not rpm. rpm is the # of rotation / time.

``````time = millis();
...
time = 0;
``````

above you reset time, suggesting that you think time will be the time since that last time it captured millis(). but millis() is cumulative.

the following captures the time since the last loop() iteration and performs an rpm calculation.

this example uses a delay to test the dMsec value and perform a calculation. If there are 300 counts in 1 second, that's 1.5 rev/sec or 90 rpm.

count should be the count since the last cycle. So it needs to be reset (count = 0) after each calculaton

``````void
setup (void) {
Serial.begin (115100);

}

void
loop  (void) {
static unsigned long msecLst = 0;
unsigned long msec    = millis();
unsigned long dMsec   = msec - msecLst;
msecLst = msec;

#define N_VANE  200
int count   = 300;
int rpm     = 60000 * count / N_VANE / dMsec;

char s ;
sprintf (s, " %6ld msec, %6d rpm", dMsec, rpm);
Serial.println (s);
delay (1000);
}
``````