Одна функция прерывания для изменения динамически определенного экземпляра?

Как обычно, я знаю, как обойти эту проблему с помощью некрасивой работы с патчами, но я хочу сделать ее элегантной: я хотел бы сделать небольшую оболочку для двигателей, управляемую 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);
* }
*/

Спасибо за вашу помощь, я думаю, что это будет полезно и другим людям, как только это будет сделано 🙂

С Уважением,
Мистер Мистер

0

Решение

Вы столкнулись с фундаментальной проблемой: 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;
}

Не так давно этот тип функции будет обрабатываться во всем чипе (см. программируемый контроллер прерываний ). Микросхема реализует всю логику для запуска и захвата источника прерывания. Основной процессор просто получает триггер «что-то случилось». Обработчик опрашивает чип, чтобы спросить «что случилось».

Предложив этот метод, я не уверен, что рекомендую. Ты не можешь скрывать что происходит с вашим кодом. Двигатель должен быть физически подключен к правильным контактам. Вы потребляли ограниченный ресурс — вы должны рассказать людям.

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]