Vamos a programar #50 - ¿Debo usar las interrupciones de arduino?

Hola de nuevo a todos el día de hoy vamos a continuar con la construcción del velocímetro para bicicleta, pero antes de continuar, vamos a tomar una decisión importante.
En algunos de los post anteriores, vimos código que se encargaba de contar las vueltas que llevaba un motor (usando un sensor de efecto hall y un par de imanes), pero poco después, alguien me contacto en twitter y me dijo que esa no era la manera correcta de hacer la medición, que arduino posee las herramientas necesarias para medir de una manera más precisa. En arduino, es posible asignarle prioridad a uno de los pines, dependiendo de modelo de la placa, al menos dos pines tendrán esta capacidad.

Las interrupciones, se dan cuando se detecta un valor en un pin, siempre y cuando este se haya inicializado con attachinterrupt(), esta es una manera de indicar que uno de los pines tendrá prioridad y cuando su valor cambie (ahorita veremos de que modo), se llevará a cabo cierta acción, esto es independiente a lo que arduino este haciendo.

La función attachinterrupt(), toma 3 argumentos. El primero; es el pin en el cual arduino "vigilará". El segundo; es la función que se ejecutará cuando se detecte un cambio en el pin designado. El tercero, será la forma en que arduino se dará cuenta del cambio.

Para designar el pin, debemos de tomar en cuenta el modelo de arduino, en mi caso, el arduino uno dispone de los pines 2 y 3 (para los modelos Mega y Micro tambien aplica).

La función que se usará cómo segundo parametro, no debe de requerir de ningun parametro y tampoco debería de devolver nigun valor.

Para el modo en que arduino detectará el cambio, disponemos de los siguientes:

  • LOW
  • CHANGE
  • RISING
  • FALLING
  • HIGH
 LOW ocurre cuando el pin esta en ese estado (LOW), CHANGE ocurre cuando el pin pasa de HIGH a LOW o viceversa, RISING ocurre cuando el pin pasa de LOW a HIGH, FALLING ocurre cuando el pin pasa de HIGH a LOW y finalmente HIGH, este ocurre cuando el pin esta en estado HIGH (valga la redundancia).

Para apreciar mejor, veamos el siguiente fragmento de codigo:

#include <LiquidCrystal.h>
const int rs = 12, en = 11, d4 = 9, d5 = 8, d6 = 7, d7 = 6;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
const float Llanta = 1.9572;
//Algunas variables
const int HallSensor = 3;
const int LED =  13;
int HallState = 0;
int Vuelta = 0;
int OldState = 0;
unsigned long OldTime = 0;
float Distancia = 0;
float Speed = 0;
//Incializar todo
void setup() {
 Serial.begin(9600);
 lcd.begin(16, 2);
 lcd.setCursor(0, 0);
 lcd.print("@XWork");
 pinMode(HallSensor, INPUT);
 attachInterrupt(digitalPinToInterrupt(HallSensor), GetVelocity, LOW);
 pinMode(LED, OUTPUT);
}
void GetVelocity() {
 if (millis()-OldTime > 70) {
  Speed=Llanta/((float)(millis()-OldTime)/1000)*3.6;
  OldTime=millis();
  Distancia=Distancia+Llanta/1000; 
 }
}
//Bucle principal
void loop() {
 Serial.println("Velocidad en m/s");
 Serial.println(Speed);
 lcd.setCursor(0, 0);
 lcd.print("v= Km/h D = Km");
 lcd.setCursor(0, 1);
 lcd.print(Speed);
 lcd.setCursor(8, 1);
 lcd.print(Distancia);
  if ((millis()-OldTime)>2000){
  Speed=0.0; 
  }
}
Podemos observar que además de la declaración normal del pin (3), justo debajo hacemos la inicialización del pin que se usara para las interrupciones y hacemos uso de la función digitalPinToInterrupt() y le asignamos cómo parámetro el pin que antes habíamos iniciado (el pin 3), luego pasamos cómo parámetro la función GetVelocity(), esta es la que se ejecutará cada vez que se de la interrupción. Finalmente en el ultimo parámetro, le decimos que la interrupción se dará cuando el pin este en LOW

El código anterior es la mejor forma de hacer la cuenta, el código de post anterior cumplía y funcionaba, pero si por alguna razón la rueda girara muy rápido, llegaría el punto en que algunas de las lecturas del sensor del lector serian omitidas. Y bien, por ahora es todo en el próximo post terminaremos con este preyecto.

Los leo luego.

No hay comentarios.