使用 Arduino 将位置编码器值转换为 RPM 时出现问题
Problems translating positional encoder values into RPM with Arduino
我正在使用带有Arduino的400 PPR编码器来测量编码器值。我能够让编码器读取值 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 RPM 的电机旋转。根据 Arduino 输出,这转换为我的代码测量为 13,350 RPM 的 RPM,这是一个更高的数字。我相信脉冲秒变量的测量不正确,而不是转换为 RPM 的方式不正确,但我不确定问题到底是什么。
每次毫秒变化时,您都会写入大约 30 个字节。 4800 波特时的 30 字节是 30/480 * 1000 ms = 62ms。因此,一旦缓冲区已满,这将阻塞。但是你假设你的计算只经过了一毫秒。
此外,您计算脉冲的方式也有偏差:
// ai0 is activated if DigitalPin nr 2 is going from LOW to HIGH
// Check pin 3 to determine the direction
// ai[1] is activated if DigitalPin nr 3 is going from LOW to HIGH
// Check with pin 2 to determine the direction
因此,如果我们有偏移编码,则每个脉冲周期有两个计数器增量:
pin 2 ________********________********
pin 3 ****________********________****
!ai0 !ai0
!ai1 !ai1
counter++ counter++
counter++ counter++
所以你可能每转一圈递增计数器 800 倍。
- 警告处理为错误这里有什么问题
- 最小硬币更换问题(自上而下方法)
- 为"adjacent"变量赋值时出现问题
- 我的神经网络不起作用 [XOR 问题]
- 在Ubuntu 16.04上安装Cilk时出现问题
- C++我的数学有什么问题,为什么我的代码不能正确循环
- 编译包含字符串的代码时遇到问题
- Project Euler问题4的错误解决方案
- 问题:什么是QAbstractItemView::NoEditTriggers的反面
- 在编译C++代码(具有dlib和opencv)到WASM时面临问题
- 在进程中对同一管道进行读取和写入时C++管道出现问题
- 静态数据成员的问题-修复链接错误会导致编译器错误
- C++ 雷神库 - 使用资源加载器类时出现问题(不命名类型)
- 一个关于在C++中重载布尔运算符的问题
- 首要问题的答案让值班员搞错了
- setlocale的C++土耳其字符串问题
- 如何重构类层次结构以避免菱形问题
- 基于boost的程序的静态链接——zlib问题
- C++格式化输出问题
- 使用 Arduino 将位置编码器值转换为 RPM 时出现问题