Interrupciones dentro de declaraciones críticas
He rehecho un boceto de Arduino anterior que publiqué en el que tenía problemas para capturar los recuentos de codificadores dentro de las declaraciones críticas, sin tener suerte al adjuntar y desconectar las interrupciones correctamente. He estudiado varios bocetos de ISR pero no he podido producir nada que satisfaga mis necesidades.
Ahora tengo un caso de interruptor en el que un motor de CC con codificador CPR gira correctamente hacia adelante y hacia atrás entre los límites especificados si solo está en el bucle vacío. Sin embargo, una vez encerrado dentro de una declaración crítica (quiero que esta acción ocurra solo si se presiona un botón), el motor de CC continúa girando solo en una dirección.
Necesito ayuda sobre dónde adjuntar y desconectar correctamente estas interrupciones y cómo pasar correctamente el valor del codificador a la siguiente acción. A continuación se muestra lo que he hecho hasta ahora y cualquier ayuda sería muy apreciada.
#define enA 9
#define in1 6
#define in2 7
const int button1Pin = 8;
int button1State = 0;
volatile long temp, counter = 0;
long local_counter=counter;
enum {IdleState, ForwardState, BackwardState} State;
void setup() {
Serial.begin(9600);
pinMode(enA, OUTPUT);
pinMode(in1, OUTPUT);
pinMode(in2, OUTPUT);
Serial.begin (9600);
pinMode(2, INPUT_PULLUP);
pinMode(3, INPUT_PULLUP);
attachInterrupt(0, ai0, RISING);
attachInterrupt(1, ai1, RISING);
pinMode(button1Pin, INPUT);
State = IdleState;
}
void loop() {
button1State = digitalRead(button1Pin);
if( counter != temp ){
Serial.print("counter = ");
Serial.print (counter);
Serial.print(" local counter = ");
Serial.println(local_counter);
temp = counter;
}
//if (button1State == HIGH) {
switch (State) {
case IdleState:
halt ();
if (counter<2000)
State = ForwardState;
break;
case ForwardState:
clockwise();
if (counter>=2000)
State = BackwardState;
break;
case BackwardState:
counterclockwise();
if (counter <=0)
State = ForwardState;
break;
} // end switch
// }
}
void ai0() {
if(digitalRead(3)==LOW) {
counter++;
}else{
counter--;
}
}
void ai1() {
if(digitalRead(2)==LOW) {
counter--;
}else{
counter++;
}
}
void clockwise (){
analogWrite(enA, 255);
digitalWrite(in1, HIGH);
digitalWrite(in2, LOW);
}
void counterclockwise () {
analogWrite(enA, 255);
digitalWrite(in1, LOW);
digitalWrite(in2, HIGH);
}
void halt () {
digitalWrite(in1, LOW);
digitalWrite(in2, HIGH);
}
Una explicación de mi configuración es la siguiente:
Mi botón es un botón táctil en la placa de pruebas (conectado al pin 8 de un Arduino Uno), con suministro de 5V de Arduino. Los pines 6 del Arduino están conectados a la entrada 1 del controlador del motor L298N , el pin 7 de Arduino está conectado a la entrada 2 del controlador del motor y el pin 9 del Adruino está conectado a la habilitación del controlador del motor. El controlador del motor está siendo alimentado por una fuente externa de 12 V que también alimenta el motorreductor de 12 V CC con codificador . Las salidas del codificador están conectadas a los pines 2 y 3 del Arduino.
Respuestas
A mi modo de ver, el estado debería volver a IdleState si no se presiona el botón. Simplemente colocando la caja del interruptor dentro de la declaración if resultará en que el motor continúe girando de la forma en que giraba cuando se suelta el botón.
if (button1State == LOW ) {
State = IdleState;
counter=2000;
}
else if(button1State==HIGH && State==IdleState ) {
counter = 0;
}
switch(State) {
...
Dependiendo de lo que desee hacer, es posible que desee agregar otro estado (por ejemplo StoppedState), donde los motores se detienen, al igual que IdleState, pero no obtiene un cambio de estado si counter<2000. Entonces no tienes que cambiar la countervariable.
if (button1State == LOW ) {
State = StoppedState;
}
else if(button1State==HIGH && State==StoppedState ) {
State = IdleState;
}
switch(State) {
case StoppedState:
halt ();
break;
case IdleState:
...
PD: por favor, sangra las declaraciones if dentro de ti case.