像往常一样,我知道如何通过一些丑陋的补丁工作来绕过这个问题,但我想让它优雅:我想为Arduino命令的电机制作一个小包装器,遗憾的是这意味着写一个明显的中断每个电机实例的例程,因为它必须修改右步计数器(电机类的成员变量)以确定其速率。但是这些功能显然会有相同的处理...... 我的问题是:如何确定在一个独特的中断例程中修改哪个计数器?
这是我到目前为止所做的,我想隐藏用户的中断。
class Motor {
volatile int counter;
unsigned long lastUpdate; //Last timestamp update (for calculating the rate)
static const unsigned int RESOLUTION = 1024; //Number of steps in one rev
static const unsigned int RPMS_TO_RPM = 60000; //Convers rev/ms to rpm
public:
Motor() : counter(0)
{
lastUpdate = millis();
}
void encoderInput(bool pinA, bool pinB)
{
counter += (pinA ^ pinB)*(-1)+!(pinA ^ pinB);
}
int getRate() {
int ret = float(counter)/RESOLUTION/(millis() - lastUpdate)*RPMS_TO_RPM;
lastUpdate = millis();
counter = 0;
return ret;
}
};
/* Example:
* Motor motor1;
*
* void motor1_isr(void) {
* motor1.encoderInput(PIN_A, PIN_B);
* }
*
* void setup() {
* attachInterrupt(PIN_I, motor1_isr, CHANGE);
* Serial.begin(9600);
* }
*
* void loop() {
* Serial.println(motor1.getRate());
* delay(1000);
* }
*/
感谢您的帮助,我认为一旦完成,对其他人也会有用:)
此致 Mystère先生
答案 0 :(得分:1)
您面临一个基本问题:调用ISR时没有数据。换句话说,不向ISR功能提供任何指示其中断源的数据。
基本方法是编写代码的人通过硬编码函数提供输入和动作之间的联系。您正在寻找的棘手方法是ISR可以确定源是什么的方法。
因此,您希望N电机具有正交编码器的2N输入。在CHANGE条件下,单个中断处理程序连接到所有输入引脚。所有N个电机都会调用相同的处理程序。它可以通过将输入引脚与上次调用的值进行比较来确定要更新的电机。如果输入引脚发生变化,则调用该电机。这是一个伪代码
Motor motor1;
Motor motor2;
onSomethingChanged() {
static int in1aprev, in1bprev;
static int in2aprev, in2bprev;
int in1a, in1b;
int in2a, in2b;
in1a = digitalRead(....
same for other in's
if( (in1a!=in1alast) || (in1b!=in1blast)) {
motor1.encoderInput(in1a,in1b);
in1alast = in1a;
in1blast = in1b;
}
if( (in2a!=in2alast) || (in2b!=in1blast)) {
motor2.encoderInput(in2a,in2b);
in1a2ast = in2a;
in1b2ast = in2b;
}
return;
}
不久前,这种类型的功能将在整个芯片中处理(参见programmable interrupt controller)。该芯片实现了触发和捕获中断源的所有逻辑。主CPU只是触发“发生了什么事”。处理程序轮询芯片询问“发生了什么”。
提供这种方法后,我不确定我会推荐。您无法隐藏代码的内容。电机必须物理连接到正确的引脚。你消耗了稀缺的资源 - 你必须告诉别人。