Proyecto Rotae - Velocímetro y distancia recorrida mostrado en un TFT, sensor Hall y Arduino (Parte 1)

  En proyecto nos marcamos como objetivo crear un velocímetro con diferentes funciones. Queremos que sea capaz de medir la velocidad, registrar un espacio.

  En esta primera parte nos vamos a centrar sobretodo en el funcionamiento del sensor del efecto hall y en mostrarlo por la pantalla.

  En la segunda parte añadiremos varias funciones como, un cronometro y para e iniciar la cuenta de distancia, GPS, etc.


INTRODUCCIÓN



 La idea es muy sencilla, el sensor de efecto hall detecta el giro completo de una de las ruedas, contando el tiempo de vuelta y lo que recorre la rueda tenemos la velocidad.

  Esta velocidad es mostrada al usuario en la pantalla TFT, además en esta pantalla vamos a mostrar la distancia recorrida.



MATERIALES


  Para este proyecto vamos a necesitar los siguientes materiales

  • Arduino micro
  • 1.8 tft 128 x 160 ST-7735
  • Sensor Hall A3144
  • Imán
  • Resistencia de 10 Kohm

FUNCIONAMIENTO DEL SISTEMA DE LECTURA DE LA VELOCIDAD CON EL SENSOR HALL


  El sistema es sencillo detectar el paso de una vuelta con el sensor de efecto hall. El primer dato que nos interesa obtener es el espacio recorrido, muy sencillo.

  Generalmente el fabricante nos va a indicar el tamaño de la rueda de dos maneras, radio o diámetro de la rueda. Si no, nosotros podemos medir la rueda, es necesario hacer una medición precisa, ya que puede determinar la calidad de nuestra precisión de datos.

  Nuestro código necesita el radio en centímetros, si sabemos el diámetro solo necesitamos dividir entre dos.


  En nuestro código vamos a tener la variable float radioRueda, en la cual ingresaremos el diámetro de nuestra rueda en centímetros.

  Por otro lado el código automáticamente calcula el diámetro en metro de la rueda.
float perimetroRueda = 2 * pi * (radioRueda / 100); //Perimetro en metros

  Este perímetro de la circunferencia nos dice directamente cuanto recorre la rueda y por tanto cuanto nos desplazamos en total. Por lo tanto si tenemos un radio de 29,5 centímetros podemos saber que el perímetro de la rueda será 2*pi*(29,5/100) = 1,85 m

  Por otro lado necesitamos tener en cuenta cuanto tiempo trascurre entre una vuelta y otra de la rueda. Básicamente, esto refiere al tiempo entre dos detecciones sucesivas del sensor de efecto hall.

  En Arduino para poder saber el tiempo que trascurre entre dos momentos usamos la función millis(), esta función devuelve el número de milisegundos desde que el programa comenzó a funcionar.

  Por lo tanto si guardamos el tiempo cuando pasa el sensor por la rueda y lo comparamos con el tiempo anterior vamos a saber el tiempo que pasa entre cada vuelta. Por lo tanto vamos a tener dos tiempos que guardar y comparar.

  Y ya con estos datos tenemos todo lo necesario para contar todas las vueltas. Tiempo y espacio, por tanto, con la fórmula de la velocidad v = s/t ya sabemos la velocidad a la que nos desplazamos por cada vuelta de rueda completa.

CONECTANDO EL SENSOR HALL

  El sensor hall tiene 3 pines, y va a ser como un botón, usáremos el circuito a continuación para detectar en nuestro pin en cambio de estado.

  Usaremos una entrada digital del Arduino para detectar cada paso. Y a través de la función digitalRead(), sabremos le estado de nuestro sensor en cada momento.

  Vamos tener dos tomas del estado para asegurarnos que no tomamos dos veces el estado sin que la rueda haya dado una vuelta.

currentState_A = digitalRead(sensorPin); delay(10); currentState_B = digitalRead(sensorPin); if (currentState_A != currentState_B) {  //actua }

PANTALLA TFT




  Yo he elegido una pantalla de 1.8 pulgadas, que funciona con el drive ST7735, por lo tanto hay que descargarse una biblioteca par hacerla funcionar. En mi caso yo me he descargado esta biblioteca y no he tenido ningún problema.



  Esta bilbioteca es una adaptación de que ofrece Adafruit para un driver de pantalla similar y tendremos muchas funciones parecida. Encontrareis la bilbioteca aqui. Una vez descargada necesitáis internarla de manera normal y ya la podéis usar.

CONEXIONES TFT

  En la pantalla vamos a mostrar los dos datos que de momento manejamos, velocidad y distancia, la pantalla se va a actualizar cada vez que se necesite.

  Nuestra pantalla se conecta a través del protocolo SPI. Para conseguir que una conexión SPI funcione necesitamos 4 pines.Estos pines estan predefinidos en nuestro arduino, tanto a nivel hardware como en la biblioteca SPI.h que necesitaremos usar para poder utilizar este protocolo
  • SCLK (Clock): Es el pulso que marca la sincronización. Con cada pulso de este reloj, se lee o se envía un bit.
  • MOSI (Master Output Slave Input): Salida de datos del Master y entrada de datos al Slave.
  • MISO (Master Input Slave Output): Salida de datos del Slave y entrada al Master.
  • SS(CS)/Select: Para seleccionar un Slave, o para que el Master le diga al Slave que se active.
  En nuestra pantalla solo tenemos MOSI ya que nuestra pantalla solo recibe información y no envía nada de información.

  Por lo tanto solo vamos a necesitar 3 pines, Mosi, CSK y CS. El resto de pines serán lo mimso.

  Dependiendo el modelo de Arduino que usemos estos pines se conectaran en diferentes pines. Para el Uno, Nano y Mini pro usaremos el pin 11, 13 y 10. Sin embargo para el Arduino Mega lo pines serían 51, 52 y 53. En nuestro caso vamos a usar un Arduino nano, por lo tanto nuestras conexiones son las siguientes. El pin LED lo podemos conectar a 3.3V o a 5V, dependiendo si queremos mas o menos brillo.


CÓDIGO COMPLETO


  En en la siguiente parte vamos a ver como conectar nuestras baterias para alimentar el sistema. Aedmás diseñaremos varias piezas en 3D para imprimirlas y asi poder tener un sistema estable.


#include <TFT_ST7735.h> // Graphics and font library for ST7735 driver chip
#include <SPI.h>

TFT_ST7735 tft = TFT_ST7735();  // Invoke library, pins defined in User_Setup.h

#define color_background 0xEF9E
#define color_speed 0x256C
#define color_a 0x0000


int sensorPin = 3;

int currentState_A = 0;
int currentState_B = 0;
int lastState = 0;

int spinCount = 0;
float rRueda = 29.5; //INGRESAR radio de la rueda en cm
float pi = 3.1416;
float pRueda = 2 * pi * (rRueda / 100); //Calcula Perimetro en metros

int time_A = 0; //tiempo paso de rueda
int time_B = 0; //timepo paso de rueda
int diferenceTime = 0;
float timeHours = 0;


int currentSpeed = 0;
int currentDistance = 0;

void setup()
{
  Serial.begin(9600);
  Serial.print("Setup");

  pinMode(sensorPin, INPUT);

  tft.init();
  tft.setRotation(0);
  tft.fillScreen(color_background);
  tft.fillRect(-2, 0, 150, 150, color_background);
  currentDistance = 0;
  currentSpeed = 0;
}


void loop()
{
  //priemra lectura
  currentState_A = digitalRead(sensorPin);
  delay(10);
  //segunda lencuta
  currentState_B = digitalRead(sensorPin);

  if (currentState_A == currentState_B) {
    if (currentState_A != lastState) { // diferentes estados actua
      if (currentState_A == HIGH) {

        spinCount = spinCount + 1; // suma una vuelta

        currentSpeed = velocityCalculations(); // calcualdora de velocidad
        currentDistance = currentDistance + pRueda;

        //actualización tft
        tft.setTextColor(color_speed, color_background);
        tft.fillRect(-2, 20, 130, 50, color_background);
        tft.setTextSize(1);
        char copy[3];
        String(currentSpeed).toCharArray(copy, 3);
        tft.drawCentreString(copy, 64, 20, 7); // Overwrite the text to clear it7
        tft.drawCentreString("km/h", 64, 70, 1); // Overwrite the text to clear it
        tft.drawNumber(currentDistance, 5, 100, 4); // Overwrite the text to clear it
      }
    }
  }
  lastState = currentState_A; //guardamos el útimo estado
}


// funcion que calcula y devuelve la velocidad. en km/h
int  velocityCalculations() {
  int speedCalculated;
  if (spinCount % 2 == 0 ) { // sabemos si la vuelta e spar o impar
    time_A = millis();
  }
  else {
    time_B = millis();
  }

  diferenceTime = abs(time_B - time_A); //resta e ultiam vuelta menos la anterior para saber el tiempo transcurrido

  timeHours = (((diferenceTime / 1000.0) / 60.0) / 60.0); //pasamos el tiempo a horas
  
  return speedCalculated;
}

Comentarios

  1. muy buen proyecto Carlos . No se podría modificar para que marque los Km/h con decimales para mas esactitud ?

    ResponderEliminar
    Respuestas
    1. Si, claro que se puede, el valor simplemente debe de ser era un dólar. Ya que el informe solo es de enteros.

      La variable currentSpeed debe de ser float en ved de int.

      La función de "int velocityCalculstions ()" debe ser "floatvelocityCalculstions()" y por último la variable de dentro "int speedCalculated" debe ser "float speedCalculated"

      Ten en cuenta que el float puede ocupar más en la pantalla, también puedes probar en ved de float double, que te permite dos decimales.

      Eliminar

Publicar un comentario

Entradas populares de este blog

ARDUINO desde cero: 5 - Comunicación Serial

Evolucionando talado de columna: 1 - Guía laser, planificación y diseño