Я использую датчик PPR 400 с Arduino для измерения значений датчика.Мне удалось заставить кодировщик считывать значения 0-400 для положительного вращения и от 0 до -400 для отрицательного вращения и сбрасывать в 0, когда кодировщик делает полный оборот.Эта часть моего кода работает, проблема, с которой я сталкиваюсь, заключается в переводе этих позиционных значений в RPM.
Мой подход был следующим: я использую функцию millis () для отслеживания общего времени программы ипеременная time_now для хранения этого значения.У меня есть оператор if, который выполняется каждый раз, когда millis () становится больше, чем time_now, на REFRESH_RATE (в моем случае это значение равно 1 мсек), так что это выполняется каждую 1 миллисекунду.
Мой следующий подход - брать две выборки каждую миллисекунду.Разница между pointSample1 и pointSample2 должна давать мне количество тиков, которые кодер перемещает в 1 мсек.Это немного усложняется, потому что это по существу круг в 400 градусов, поэтому, например, если pointSample1 имеет угол 395 градусов, а pointSample2 читает 5 градусов, нам нужно взять разницу разрешения кодера и pointSample1, а затем добавить к pointSample 2 или (PPR -pointSample1) + pointSample2.
Опять же, это ДОЛЖНО давать мне количество тиков в мсекунду, которое затем легко конвертируется в RPM.
#define REFRESH_RATE 1 //sets the refresh rate for tracking RPM (in mSec)
volatile float temp, counter = 0; //This variable will increase or decrease depending on the rotation of encoder
int revsTotal = 0;
int pulseInitial = 0;
int PPR = 400; //Equal to the number of ticks per revolution of your encoder
unsigned long time_now = 0; //time since program start
int pulseDifferential = 24; //number of ticks per mSec for desired RPM
float pointSample1 = 0; //first tick sample
float pointSample2 = 0; //second tick sample
float pulsemSec = 0; //the amount of ticks the encoder is reading every millisecond
float RPM = 0; //RPM of the motor
void setup() {
pointSample1 = counter;
Serial.begin (4800);
pinMode(2, INPUT_PULLUP); //sets pin mode for pin 2
pinMode(3, INPUT_PULLUP); //sets pin mode for pin 3
//Setting up interrupt
//A rising pulse from encoder activated ai0(). AttachInterrupt 0 is DigitalPin nr 2 on most Arduinos.
attachInterrupt(0, ai0, RISING);
//B rising pulse from encoder activated ai1(). AttachInterrupt 1 is DigitalPin nr 3 on most Arduinos.
attachInterrupt(1, ai1, RISING);
}
void loop() {
// Send the value of counter
if( counter != temp ){ //if change is detected in the encoder, print the positional data values
Serial.println ("Positional Data: ");
Serial.println (counter);
temp = counter;
if( counter >= PPR or counter <= -PPR){ //This if statement resets the counter every time the encoder does a full revolution, protecting from reset after memory becomes filled
counter = 0;
}
}
if(millis() > (time_now + REFRESH_RATE) or millis() == 0){ //should run once every time the refresh rate is met (refresh rate = 1mSec, if statement runs once every mSec). millis() = 0; is for varibale overflow protection
pointSample2 = counter; //sets pointSample2 to the encoder position, pointSample1 starts at 0. This allows the difference between the two to be taken to determine the rotation per mSec
if(pointSample1 - pointSample2 < 0){ //conditional if / elseif statement checks the sign (positive or negative) of the ticks between samples, and makes sure that the pulses per mSec is always positive
pulsemSec = pointSample2 - pointSample1;
}
else if (pointSample1 - pointSample2 > 0){
pulsemSec = (PPR - pointSample1) + pointSample2;
}
RPM = (((pulsemSec / PPR) * 1000) * 60); //pulsemSec / PPR = revs per msec; revs per msec * 1000 = revs per sec; revs per sec * 60 = RPM
pointSample1 = pointSample2; //changes pointSample1 for the next cycle
time_now = millis(); //sets time_now to the amount of time since program start
Serial.println ("pulsemSec: ");
Serial.println (pulsemSec);
Serial.println ("RPM: ");
Serial.println (RPM);
}
}
void ai0() {
// ai0 is activated if DigitalPin nr 2 is going from LOW to HIGH
// Check pin 3 to determine the direction
if(digitalRead(3)==LOW) {
counter++;
}else{
counter--;
}
}
void ai1() {
// ai0 is activated if DigitalPin nr 3 is going from LOW to HIGH
// Check with pin 2 to determine the direction
if(digitalRead(2)==LOW) {
counter--;
}else{
counter++;
}
}
Во время тестирования у меня вращался двигатель со скоростью около 473 об / мин, измеренный с помощью цифрового тахометра.Согласно выводу Arduino, это переведено в число оборотов в минуту, измеренное моим кодом, как 13 350 оборотов в минуту, намного большее число.Я полагаю, что что-то не так с измерением переменной pulsemSec, а не с тем, как оно конвертируется в об / мин, но я не уверен, в чем конкретно проблема.