Xwork's Blog

The lord is waiting to take your hand.

Mostrando las entradas con la etiqueta velocimetro. Mostrar todas las entradas
Mostrando las entradas con la etiqueta velocimetro. Mostrar todas las entradas

Vamos a programar #100 - Speedometer M. Versión Final.

 Hola de nuevo a todos, el día de hoy empezaremos a ver la versión final del velocímetro.

Este proyecto fue iniciado mas o menos por el 2018 y ha sufrido una serie de cambios a lo largo del tiempo, si bien la última versión que fue publicada funcionaba bien, poco a poco se fueron agregando funciones para hacerlo funcionar de manera optima con el mínimo de hardware posible (de ahí que nunca le agregue ningún tipo de botón). Finalmente, tras días de pruebas y pruebas, he decidido finalizar con este proyecto porque finalmente ha alcanzado el nivel de confiabilidad para poder usarse en el día a día.


Primero que nada, veamos el código que hace funcionar a "Speeedometer M"


// Incluir la libreria para la pantalla
#include <LiquidCrystal.h>
// Pines usados en la pantalla extraido de los ejemplos incluidos en la libreria
const int rs = 13, en = 12, d4 = 11, d5 = 10, d6 = 9, d7 = 8;
// iniciar el objeto LiquidCrystal
LiquidCrystal lcd(rs , en , d4 , d5 , d6 , d7);
// Este es el valor que debes de modificar para que funcione correctamente
// Puedes ver instrucciones en https://xworkforall.blogspot.mx/2018/03/vamos-programar-49.html
const float Llanta = 1.9572;
//Algunas variables
const int HallSensor1 = 3;
const int LED1 =  7;
const int LED2 = 6;
const int LED3 = 5;
int Vuelta = 0;
unsigned long OldTime = 0;
float Distancia = 0.0;
float Speed = 0.0;
int ledState = LOW;
int VoltSensor = 0;
float BattVolt = 0.0;

// v=99.99
char BuffVelocity[15];
//d=999.99
char BuffDistance[15];
//R=999999
char BuffRevolution[15]; 
//V=4.2
char BuffBattery[15];

//Incializar todo
void setup() {
  //Serial.begin(9600);
  lcd.begin(16, 2);
  lcd.setCursor(0, 0);
  lcd.print("@XWork");
  pinMode(HallSensor1, INPUT);
  attachInterrupt(digitalPinToInterrupt(HallSensor1) , GetVelocity , LOW);
  pinMode(LED1 , OUTPUT);
  pinMode(LED2 , OUTPUT);
  pinMode(LED3 , OUTPUT);
}

// Calcular la velocidad
void GetVelocity() {
  if (millis() - OldTime > 70) {
    Speed = Llanta / ((float)( millis() - OldTime) / 1000) * 3.6;
    OldTime = millis();
    Distancia = Distancia + Llanta / 1000;
    Vuelta += 1;
    if (ledState == LOW)
      ledState = HIGH;
    else 
      ledState = LOW;
  }
}
//Bucle principal
void loop() {
  VoltSensor = analogRead(A5);
  BattVolt = (VoltSensor * (10.0 / 1023.0));

  dtostrf(Speed , 5 , 2 , BuffVelocity);
  dtostrf(Distancia , 6 , 2, BuffDistance);
  sprintf(BuffRevolution , "R=%6d", Vuelta);
  dtostrf(BattVolt , 5 , 1, BuffBattery);
  
  lcd.setCursor(0, 0);
  lcd.print("d=");
  lcd.setCursor(2 , 0);
  lcd.print(BuffDistance);
  
  lcd.setCursor(9, 0);
  lcd.print("v=");
  lcd.setCursor(11, 0);
  lcd.print(BuffVelocity);
  
  lcd.setCursor(0,1);
  lcd.print(BuffRevolution);
  
  lcd.setCursor(9,1);
  lcd.print("V=");
  lcd.print(BuffBattery);
  
  digitalWrite(LED1 , ledState);
  digitalWrite(LED2 , ledState);
  digitalWrite(LED3 , ledState);
  
  if ((millis() - OldTime) > 3000){
    ledState = LOW;
    Speed = 0.0;
  }
}


Si haz seguido el proyecto desde el inicio, te darás cuenta que la mayoría de las funciones han cambiado un poco y algunos de los elementos que en ocasiones usamos para algunos post, los retomamos para llegar a está versión. Antes de continuar, voy a responder a unas cuantas preguntas que surgieron durante todo el proceso. La primera de ellas: ¿Cuánta es la máxima distancia que se puede alcanzar con el diseño original? La respuesta es relativamente sencilla, ya que usamos seis espacios de la pantalla y usamos tres para los enteros, una para el punto y dos para los decimales; la máxima distancia posible es 999.99 km, que es mas que suficiente para la mayoría de las personas, pero aquí es donde viene la parte "truculenta". La parte donde se llevan la cuenta de las revoluciones, el máximo posible es de 999,999 vueltas, en el caso de una llanta 24x2.25, la circunferencia es de 1.95m por lo que al multiplicar por el número de vueltas máximo obtenemos 1,949,998.05m máximo o lo que es lo mismo 1949km y esto bastaría para desbordar la parte de la distancia.

Otro dato que cambio fue la información que se usa para la batería. En algún momento del desarrollo, pensé en incluir un icono de batería, pero cada una de las baterías son diferentes y por lo tanto no es factible escribir el código ya que es casi una garantía que la pila no es igual en la mayoría de los casos. y por ejemplo, la pila que yo uso era de un teléfono y traía consigo una protección que corta la corriente cuando la pila alcanza 2.5v, pero una pila Sony VTC6 recomienda que el voltaje nunca baje de los 3v.

Es posible usar una pantalla de 20x4, pero la 16x2 es mas compacta y además, permite tener todo de manera lo mas sencilla posible.

Por último, he actualizado el proyecto en easyeda y he hecho el PCB de la mejor manera posible y es posible ordenarlos, pero quiero resaltar que aun no los he probado (o no al momento de que esto fue escrito) y eso se debe a que van a tardar un par de semanas. De todos modos, se pueden seguir las conexiones del diagrama y hacerlo en un placa perforada a mano.

O mandarlas a fabricar (que repito, aun no he probado.)

Y bien por ahora es todo, tal y cómo lo mencioné al principio, ya no voy a publicar mas actualizaciones, pienso que todo funciona cómo debe, pero además todo está disponible para que cada quien lo modifique a cómo lo necesite, recuerda que puedes hacer el pedido desde JLCPCB y además puedes descargar el código desde mi DropBox para que lo modifiques a tu gusto.

Los leo luego

Vamos a programar #94 - Formateando números en arduino - Camino a speedometer version final.

Hola de nuevo a todos, el día de hoy vamos a continuar con mas partes para llegar a la versión final del velocímetro.


Leyendo algunos comentarios que hace la gente sobre que más se le podría modificar al velocímetro, muchos de ellos coincidían que había que corregir algunos de ellos. Los principales "detalles" estaban en la pantalla. Si bien no eran errores, aprovechando que se va a actualizar, decidí arreglarlos de una vez.

Supongamos que en la pantalla tenemos una velocidad de 10.09 km/h pero si desaceleramos, a por ejemplo 9.1 la pantalla mostraba algo cómo 9.19, y la cosa era peor si nos deteníamos ya que se mostraba 0.09. La razón por la que pasaba esto es por cómo se maneja la pantalla. Para ponerlo de forma simple, solo cuando se escribe algo en cierta posición, la pantalla se actualiza pero solo en esa zona, cuando escribimos "v=10.09" se usan siete espacios y mientras los usemos con números que usen el mismo "ancho" no se verá ningún problema, pero cuando tenemos cualquier número inferior a 10.00 cómo 9.9 ahora solo se usan menos espacios por lo que en lugar de actualizar los mismos siete de antes, solo se actualizan cinco o seis. Para poder solucionarlo, podemos escribir número que si importar cual sea, siempre ocupen la misma cantidad de espacios.

En C existen varias formas de formatear números, pero algunas de ellas no están disponibles para usarse en arduino (y debo de admitirlo, eso no lo sabia hasta apenas) y por eso veremos cómo es posible usar el reemplazo que arduino ofrece.

Primero que nada, hay que definir cual es el "estilo" que queremos que cada número tenga. En el caso del velocímetro, hay cuatro números importantes: la velocidad, la distancia, las revoluciones (o vuletas) y el voltaje de la batería. En el caso de la velocidad, una velocidad máxima de 99.99km/h es mas que suficiente para una bicicleta por lo que el numero ocuparía cinco espacios (con el punto incluido). Para las distancia, un viaje de 999.99 km es mas que suficiente para la mayoría de los ciclistas, por lo que seis digitos parecen suficiente, para las revoluciones, 999999 parecen suficientes por lo que seis espacios parecen suficientes y finalmente la batería, ya que el voltaje máximo de una sola pila es 4.2v, con solo reservar tres espacios es mas que suficiente.

Ahora veamos un código hipotético en C que serviría para usarse en un programa de computadora (por ejemplo) pero que no produciría el resultado esperado en arduino. EL código es el siguiente:

#include <stdio.h>

float Speed = 9.1;
float Distance = 9.04;
int Revolution = 16384;
float Battery = 2.0;

char BuffSpeed[20];
char BuffDistance[20];
char BuffRevolution[20];
char BuffBattery[20];

int main()
{

    sprintf(BuffBattery , "R=%3.1f\n", Battery);
    sprintf(BuffRevolution , "R=%6d\n", Revolution);
    sprintf(BuffDistance , "d=%6.2f\n", Distance);
    sprintf(BuffSpeed, "V=%5.2f\n", Speed);

    printf(BuffSpeed);
    printf(BuffDistance);
    printf(BuffRevolution);
    printf(BuffBattery);

    return 0;
}

Al compilarlo con los valores asignados, produce el siguiente resultado:

V= 9.10

d=  9.04

R= 16384

R=2.0

Pero cómo no es muy fácil de apreciar, solo para este ejemplo vamos a poner "0" en lugar de espacios en blanco para que se mas fácil de apreciar (en la pantalla no para poder preservarla un poco mas.) por lo que probamos con el siguiente código:

#include <stdio.h>

float Speed = 9.1;
float Distance = 9.04;
int Revolution = 16384;
float Battery = 2.0;

char BuffSpeed[20];
char BuffDistance[20];
char BuffRevolution[20];
char BuffBattery[20];

int main()
{

    sprintf(BuffBattery , "R=%3.1f\n", Battery);
    sprintf(BuffRevolution , "R=%06d\n", Revolution);
    sprintf(BuffDistance , "d=%06.2f\n", Distance);
    sprintf(BuffSpeed, "V=%05.2f\n", Speed);

    printf(BuffSpeed);
    printf(BuffDistance);
    printf(BuffRevolution);
    printf(BuffBattery);

    return 0;
}

Al compilarlo con los valores asignados, produce el siguiente resultado:

V=09.10

d=009.04

R=016384

R=2.0

Ahora resulta mas sencillo observar que por ejemplo la velocidad siempre ocupara cinco espacios a pesar de ser menor a 10km/h y que por ejemplo la distancia ocupa seis espacios a pesar de ser menor a 100km.

Pero que pasa si tratamos de ejecutar el mismo código en arduino?


Cómo puede observarse, la mayor parte del código se compila pero no funciona. Esto se debe principalmente a que a la hora de formatear los números del tipo "float" requiere mas poder de procesamiento por lo que en arduino no se implementó (**o eso es lo que quiero creer**), para el caso del los enteros es posible usar la misma función "sprintf()".

Para poder hacer algo similar, podemos usar la funcion "dtostrf()". Esta funcion lo que hace es convertir un número "double" a su equivalente en "string", para eso la funcion recibe cuatro parametros.

  • char * dtostrf (double __val, signed char __width, unsigned char __prec, char *__s)
    • __val es el valor que se va a convertir
    • __width es el tamaño que debe de tener la cadena.
    • __prec Es la cantidad de decimales que usaran
    • __s Es el sitio donde se almacenara el resultado.
Ahora recordemos que queremos que la velocidad tenga cinco espacios, pero además de dos decimales, lo que podemos hacer es algo cómo lo que sigue:

dtostrf(Speed , 5 , 2 , BuffVelocity);

Con lo anterior le estamos indicando que el string resultante debe de convertir la variable "speed", pero además el resultado, debe de tener una longitud de 5 y dos decimales, todo lo anterior lo debe de guardar en "BuffVelocity". Solo para ejemplificar, portemos el programa que corre en la computadora para que corra en arduino y para eso usaremos una pantalla LCD.

//YWROBOT
//Compatible with the Arduino IDE 1.0
//Library version:1.1
#include <Wire.h> 
#include <LiquidCrystal_I2C.h>
// Conexiones de la pantalla usando el convertidor a i2c
//SCL - A5
//SDA - A4
LiquidCrystal_I2C lcd(0x27,20,4);  // set the LCD address to 0x27 for a 16 chars and 2 line display

float Speed = 9.1;
float Distance = 9.04;
int Revolution = 16384;
float Battery = 2.0;

char BuffSpeed[20];
char BuffDistance[20];
char BuffRevolution[20];
char BuffBattery[20];


void setup()
{
    lcd.init();
    lcd.backlight();
}


void loop()
{
    dtostrf(Speed , 5 , 2 , BuffSpeed);
    dtostrf(Distance , 6 , 2, BuffDistance);
    sprintf(BuffRevolution , "R=%6d", Revolution);
    dtostrf(Battery , 4 , 2, BuffBattery);

    lcd.setCursor(0, 0);
    lcd.print("v=");
    lcd.setCursor(2 , 0);
    lcd.print(BuffSpeed);

    lcd.setCursor(8, 0);
    lcd.print("d=");
    lcd.setCursor(10, 0);
    lcd.print(BuffDistance);

    lcd.setCursor(0,1);
    lcd.print(BuffRevolution);

    lcd.setCursor(10,1);
    lcd.print("v=");
    lcd.print(BuffBattery);
}


Al compilarlo y ejecutarlo tenemos que ahora si se produce el resultado esperado.

Y bien, por ahora es todo, ya casi llegamos a la versión final del velocímetro que justo acaba de cumplir tres años desde la primera.

Los códigos de antes solo fueron ilustrativos, por lo que si quieres probarlos, puedes copiarlos y pegarlos para usarlos.

Los leo luego.

Back to basics #10 - Control de LED's (con transistores) - Camino a Spedometer v. Final

 Hola de nuevo a todos, el día de hoy vamos a ver cómo instalar una mejora a las luces del velocímetro y además, veremos cómo es que los transistores nos pueden ayudar a manejar algunas cosas que no podríamos directamente desde el arduino.

 

Si hacemos memoria la primera vez que construimos el velocímetro, usábamos un par de diodos LED para hacernos visibles a la hora de manejar en la noche, pero los diodos que se usan al ser de 20mA @ 3.1v solo funcionaban en lugares pequeños (llámese calle promedio), pero cuando se trata de recorridos por caminos más amplio, la idea es ser visible desde la mayor distancia posible, por lo que se hace necesario usar un fuente luminosa mas intensa.

Cuando controlamos los diodos LED directamente desde el arduino, disponemos de una cantidad limitada de potencia. Normalmente el arduino UNO es capaz de suministrar un voltaje de 5v en los pines, pero tienen un limite de corriente de solo 40mA, si conectamos algo que requiera más corriente las cosas pueden ponerse feas.

Por los lugares que suelo andar en bicicleta, los diodos antes mencionados cumplen con su trabajo, pero me llegaron algunas peticiones a mi twitter preguntando por la posibilidad de agregar algo mas fuerte. La mayoría quería agregar los módulos que consisten de tres (o seis) diodos LED 5050.


Si conectamos uno de estos módulos al arduino, simplemente nada pasará, ya que requieren un voltaje de 12V (si hago bien memoria cuando es un solo led 5050 de color blanco consume 60mA a 3.2v), para poder agregar uno de estos módulos, primero que nada, necesitaremos agregar un elevador de voltaje y para controlarlas el transistor.

Para este caso voy a usar un transistor TIP31c (que era lo que tenía a la mano) pero el siguiente diagrama aplica a cualquier transistor NPN. Pero primero que nada ¿Que es un transistor?.

El transistor es un dispositivo electrónico semiconductor utilizado para entregar una señal de salida en respuesta a una señal de entrada. Cumple funciones de amplificador, oscilador, conmutador o rectificador. El término «transistor» es la contracción en inglés de transfer resistor («resistor de transferencia»). Actualmente se encuentra prácticamente en todos los aparatos electrónicos de uso diario tales como radios, televisores, reproductores de audio y video, relojes de cuarzo, computadoras, lámparas fluorescentes, tomógrafos, teléfonos celulares, aunque casi siempre dentro de los llamados circuitos integrados.

https://es.wikipedia.org/wiki/Transistor

Tal y cómo lo dice la definición, necesitamos una señal de entrada para obtener una señal de salida, por lo que en este ejemplo el transistor lo usaremos cómo un apagador (se puede usar para más muchas más aplicaciones pero por ahora solo esto). Antes de continuar, quiero resaltar que usaremos un transistor NPN, existen de más tipos (que eventualmente veremos) pero por ahora y cómo el objetivo no es aprender a usarlos, bastará con usar un transitor del mismo tipo y con las caracteristicas que veremos un poco más adelante.

Para el transistor TIP31c los pines son de la siguiente manera:

  1. Base
  2. Colector
  3. Emisor

.Para hacer las conexiones solo deberás de identificar cual corresponde a cada pin del transistor que elijas y todo debería de funcionar.


Y el diagrama correspondiente sería:


SI todo salió bien las luces deberían de encender cuando el PIN de arduino este en "HIGH".


Cabe aclarar que lo mas recomendable para está situación, sería usar una fuente de energía adicional, puesto que el velocímetro es alimentado por una pila, agregar dos elevadores de voltaje podría reducir la durabilidad de esta de forma drástica. En cambio si agregamos otra pila aparte si se agota el velocímetro podría seguir operando con normalidad.

Aunque la idea me agrado, está no es la solución que agregué a mi bicicleta, la solución que yo le puse la veremos en el siguiente post. Por cierto, se que al inicio del año prometí post cada quincena, pero por razones que son difíciles de entender (aun para mi) los post saldrán pero no de forma periódica.

Los leo luego.

Vamos a programar #89 - Midiendo voltajes con arduino - Camino a Spedometer v. Final

Hola de nuevo a todos, el día de hoy vamos a ver cómo medir voltajes usando arduino. Todo esto para agregarlo a "Spedometer M" (y de una vez por todas decir que está terminado). Uno de los principales puntos a tratar, es la presentación de la batería, haciendo memoria en el código habían 5 situaciones diferente para mostrar el estado de la batería, pero algo importante que olvide mencionar, es que eran meramente ilustrativas. Uno podría pensar que al haber 5 "iconos" diferentes, cada uno representaría al 20%, pero en este caso no es así.


El primero de los problemas es que no tenemos una lectura precisa del nivel de la batería, anteriormente ya habíamos hecho un post en el cual mostraba cómo es que se hace la lectura de un voltaje, pero ¿podemos ser mas precisos? Para entender cómo podemos ganar precision, primero hay que recordar cómo es que se hacen las lecturas (y recomiendo que leas un post donde hablamos un poco).

Para medir el voltaje, lo que hacemos es ingresarlo por un pin del arduino, internamente, este posee un mecanismo que traslada el voltaje un valor digital. Cuando conectamos 0v a un pin analogo del arduino y hacemos la lectura con "analogread()" está devolverá un valor de 0. EN cambio si conectamos 5v esta devolverá un valor de 1023. ¿Por que ocurre esto? Simple arduino cuenta con convertidor análogo-digital con una resolución de 8 bits por lo que cada valor entre 0 y 1023 sera igual a un valor de 0v a 5v. Para saber que valor le corresponde a cada voltaje, bastará con mirar la siguiente formula:
donde "n" es el valor de la lectura que "analogread()" regresa . Para entender un poco lo que pasa, supongamos que toamos la lectura usando arduino y este nos regreso un valor de 155.
al sustituirlo tenemos:
Y si lo medimos usando un multimetro tenemos:

Que es bastante acertado. Pero ahora lo que nos interesa hacer es ganar mas definición. Cuando arduino "mide" un voltaje en realidad lo que hace es compararlo con otro, por default este es de 5v, pero se puede elegir otro.

Para indicar que queremos usar un voltaje externo de referencia, podemos usar la función "analogReference()" que recibe un parámetro que puede ser cualquiera de los siguientes:


  • DEFAULT (el valor de la alimentación, si se usan 5v, esta sera la referencia, si se usan 3.3v esta lo será).
  • INTERNAL (Usa un voltaje interno de 1.1v pero solo en el modelo uno, en otros modelos es de 2.56v y elgunos no esta disponible).
  • EXTERNAL (Usa el PIN AREF y se puede usar un valor mayor a cero y menor o igual a 5v)

Existen otros parámetros, pero por ahora nos centraremos en estos.

Primero usaremos el parámetro "INTERNAL" y para que pruebes, puedes usar el siguiente código:

int ValIn = 0;
int CurVal = 0;
float CurVolt =0;

void setup()
{
	analogReference(INTERNAL);
	Serial.begin(9600);
}

void loop()
{
	CurVal=analogRead(ValIn);
	Serial.println(CurVal);
	CurVolt=CurVal*1.1; 
	Serial.print("Valor");
	Serial.print(CurVal);
	Serial.print("mV:");
	Serial.println(CurVolt);
	Serial.println("Done");
	delay(2000);
}

Una vez que lo subas a tu arduino, deberás de conectar el voltaje positivo de tu voltaje (una pila por ejemplo) al pin A0 y el voltaje negativo a tierra. Yo al hacer la medición de la misma pila me da un valor de 710 que al reemplazarlo en la formula (actualizando los valores) no da:
Que es un valor mas cercano al que nos dio el multímetro.

Y sabiendo lo anterior ahora podemos hacer que la referencia sea la indicada para el nivel de la batería. Primero modificaremos un poco el código para hacer uso de la referencia externa, para eso prueba copiar el siguiente código:
int ValIn = 0;
int CurVal = 0;
float CurVolt =0;

void setup()
{
	analogReference(EXTERNAL);
	Serial.begin(9600);
}

void loop()
{
	CurVal=analogRead(ValIn);
	Serial.println(CurVal);
	CurVolt=CurVal*1.1; 
	Serial.print("Valor");
	Serial.print(CurVal);
	Serial.print("mV:");
	Serial.println(CurVolt);
	Serial.println("Done");
	delay(2000);
}

Ahora deberás de conectar un voltaje de 4.2v al pin "AREF" del arduino y conectar el lado positivo de la pila al pin "A0" y el negativo a tierra. Es importante tener nuestro voltaje de referencia estable. Si has seguido los post sobre el velocímetro, sabrás que hacemos uso de un boost converter para obtener un voltaje estable de 5v, si no te quieres complicar la vida, simplemente puedes usar un divisor resistivo con una resistencia de 1.2 kohm junto co una de 6.3 kohm (si tienes 5v exactos te dará 4.2v a la salida).

Algo que es importante aclarar para finalizar el post, es que para mostrar el porcentaje de batería no podemos simplemente usar la formula del porcentaje ya que todas las pilas son diferentes y a pesar de que la capacidad de una pila se puede medir de acuerdo al voltaje que esta nos da, depende meramente del fabricante cómo es "la curva de descarga" (que veremos en otro post) cómo dije al inicio, en el caso del velocímetro, los iconos son meramente ilustrativos de "la pila recien se cargo", "Está medio vacía" y "ya hace falta una recarga".

Y bien, por ahora es todo, lo ejemplos de código cómo son sencillos puedes simplemente copiarlos y pegarlos para probarlos y hago énfasis en que al pin "AREF" del arduino SIEMPRE se le debe aplicar un voltaje mayor a cero y menor o igual a 5.

Los leo luego.

Vamos a programar #82 - Actualizando el velocímetro - Spedometer M V2.

Hola de neuvo a todos, el día de hoy vamos a ver cómo actualizar el velocímetro que previamente ya habíamos hecho a la versión 2.0


Después de varios meses de espera, finalmente he decidido actualizar el velocímetro a la siguiente versión. Ademas de hacer mejoras en la construcción, decidí actualizar el código para hacerlo un poco mas eficiente y funcional.

"Mejorando la casa"

La primera construcción la hice en una caja de plástico barato y no era muy estable que digamos, y debido a eso en situaciones de terreno muy empedrado, la débil construcción hacia que el velocímetro fallara. Por eso hice una caja de acrílico (los pasos no lo muestro, ya que es una caja y me quedo horrible) unida con silicon frió y tornillos, gracias a eso las pruebas que he hecho en terrenos realmente accidentados, han sido exitosas. Antes cuando estaba en la caja de plástico, en algunos caminos se reiniciaba (supongo que por la vibración), pero ahora ya no.

Además de manera opcional, incluí un LED de color rojo para saber cuando es que está en operación, no ayuda en nada pero siempre resulta util saber que cuando la luz está encendida, lo demás también debería.

En sustitución del la placa Arduino Uno, decidí usar directamente el micro-controlador ATMEGA328p (en un futuro post veremos cómo hacer un "Minimal arduino").

Las conexiones y el código.

Para las conexiones, bastará con mirar el siguiente diagrama:
Y el siguiente código:

// Incluir la libreria para la pantalla
#include <LiquidCrystal.h>
// Pines usados en la pantalla extraido de los ejemplos incluidos en la libreria
const int rs = 13, en = 12, d4 = 11, d5 = 10, d6 = 9, d7 = 8;
// iniciar el objeto LiquidCrystal
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
// Este es el valor que debes de modificar para que funcione correctamente
// Puedes ver instrucciones en https://xworkforall.blogspot.mx/2018/03/vamos-programar-49.html
const float Llanta = 1.9572;
//Algunas variables
const int HallSensor1 = 3;
const int LED1 =  7;
const int LED2 = 6;
const int LED3 = 5;
int Vuelta = 0;
unsigned long OldTime = 0;
float Distancia = 0.0;
float Speed = 0.0;
int ledState = LOW;
int VoltSensor = 0;
float BattVolt = 0.0;

const byte Batt100[] = {
	B01110,
	B11111,
	B11111,
	B11111,
	B11111,
	B11111,
	B11111,
	B11111
};

	const byte Batt75[] = {
	B01110,
	B10001,
	B11111,
	B11111,
	B11111,
	B11111,
	B11111,
	B11111
};

	const byte Batt50[] = {
	B01110,
	B10001,
	B10001,
	B10001,
	B11111,
	B11111,
	B11111,
	B11111
};

	const byte Batt25[] = {
	B01110,
	B10001,
	B10001,
	B10001,
	B10001,
	B10001,
	B11111,
	B11111
};

	const byte Batt0[] = {
	B01110,
	B10001,
	B10001,
	B10001,
	B10001,
	B10001,
	B10001,
	B11111
};

//Incializar todo
void setup() {
	//Serial.begin(9600);
	lcd.createChar(0, Batt0);
	lcd.createChar(1, Batt25);
	lcd.createChar(2, Batt50);
	lcd.createChar(3, Batt75);
	lcd.createChar(4, Batt100);
	lcd.begin(16, 2);
	lcd.setCursor(0, 0);
	lcd.print("@XWork");
	pinMode(HallSensor1, INPUT);
	attachInterrupt(digitalPinToInterrupt(HallSensor1), GetVelocity, LOW);
	pinMode(LED1, OUTPUT);
	pinMode(LED2, OUTPUT);
	pinMode(LED3, OUTPUT);
}
//Dibujar el icono de bateria***
void DrawBatt(int Value){
	lcd.setCursor(15, 1);
	if (Value > 90)
		lcd.write(byte(4));
	  if (Value < 91 && Value > 75 )
		lcd.write(byte(3));
		if (Value < 76 && Value > 50 )
		lcd.write(byte(2));
		if (Value < 51 && Value > 10 )
		lcd.write(byte(1));
		if (Value < 11 )
		lcd.write(byte(0));
}
// Calcular la velocidad
void GetVelocity() {
  if (millis() - OldTime > 70) {
	Speed = Llanta / ((float)( millis() - OldTime) / 1000) * 3.6;
	OldTime = millis();
	Distancia = Distancia + Llanta / 1000;
	Vuelta += 1;
	if (ledState == LOW) {
	  ledState = HIGH;
	} else {
	  ledState = LOW;
	}
  }
}
//Bucle principal
void loop() {
	VoltSensor = analogRead(A5);
	BattVolt = (VoltSensor * (10 / 1023.0)) * 100;
	lcd.setCursor(0, 0);
	lcd.print("v=");
	lcd.setCursor(2, 0);
	lcd.print(Speed);
	lcd.setCursor(8, 0);
	lcd.print("d=");
	lcd.setCursor(10, 0);
	lcd.print(Distancia);
	lcd.setCursor(0,1);
	lcd.print("Rev=");
	lcd.setCursor(4,1);
	lcd.print(Vuelta);
	DrawBatt(map(BattVolt, 300,405,1,100));
	digitalWrite(LED1, ledState);
	digitalWrite(LED2, ledState);
	digitalWrite(LED3, ledState);
	if ((millis() - OldTime) > 3000){
		ledState = LOW;
		Speed = 0.0;
	}
}

Lo primero que hay que resaltar es que es conveniente darse una vuelta por el post donde hicimos la primera version, ya que todos los fundamentos están en esa serie de posts.

Para esta versión se agregan solo dos resistencias y tres LED's. Hace unas cuantas semanas vimos cómo medir voltajes usando arduino, para eso usamos un divisor resistivo compuesto por dos resistencias de dos mega ohm y la parte media, la conectamos al pin A5. Cómo el voltaje está dividido a la mitad (puedes ver cómo funciona en el post de  de divisores resistivos), en lugar de medir los 4.2v solo mediríamos cómo máximo 2.1v que se resuelve si se multiplica por dos.

Algo que es muy importante resaltar, es que el indicador de la batería no es muy preciso, eso se debe principalmente a que no encontré una hoja de datos del modelo especifico y por las que encontre, si hay diferencia entre marca y marca por lo que hay que ajustar los niveles de acuerdo a lo que se especifique según el tipo de batería que uses.

Y bien, por ahora es todo. En el siguiente post, veremos una explicación detallada del código, por ahora intentare buscar una hoja de datos o trataré de implementar una forma un poco mas precisa de desplegar el porcentaje de la batería. El código cómo de costumbre lo puedes descargar de dropbox (es el mismo link pero actualizado).

Los leo luego.

Vamos a platicar #8 - Reseña del velocímetro.

Hola de nuevo a todos, el día de hoy vamos a hablar sobre una de las cosas que prometí hace mucho: La reseña del velocímetro.


En abril del 2018 fue cuando empece con la construcción del velocímetro, y desde ese día lo he usado casi a diario, muy pocas le he modificado. Algunas de las cosas que tenía planeadas simplemente ya nos las implementé, si hacemos memoria, implementar las direccionales era algo que tenia planeado hacer (y no he hecho), pero a medida que lo usaba me di cuenta que con una luz intermitente tradicional y con la pantalla de 16x2 era más que suficiente; eso hasta cierto punto.

Normalmente lo uso en la mañana, pero me di cuenta de algunas cosas que podrían ser realmente útiles y que gracias al arduino se pueden implementar de manera un tanto sencilla. Un reloj en tiempo real, eso es algo que sin duda podría resultar útil. En algunas ocasiones he ido en bicicleta a lugares donde tengo compromisos y en ocasiones no dimensiono cuanto tiempo es el que he gastado en el camino. Puedo consultar mi teléfono y ver la hora (o comprar un G-Shock de Casio), pero a veces en medio del trafico hay que poner atención al camino, entonces ahi es cuando se dificulta un poco ver la hora. En cambio si se le agregara el modulo, bastaría con mirar un instante a la pantalla y ya sabría que hora es.

En la parte del software, he pensado en agregar algunas funciones, pero para poder desplegarlas todas, es necesario una pantalla más grande. Hace tres meses ordene una pantalla de 20x4 en ali-express, pero no ha llegado; en ese tiempo estaba pasando todos los componentes a una caja de acrilico que hice, entonces pensé que seria buena idea actualizar el hardware antes de sellar medianamente bien la caja, pero espere y la pantalla que tenia tiempo de espera estimado para su llegada de dos meses; aun no llega.
El motivo para usar una pantalla más grande es simple: así no es necesario agregar botones; si se agregaran botones para la operación del velocímetro, entonces sería lo mismo que sacar mi teléfono de mi mochila, presionar un botón, ver la hora y volverlo a guardar.

Por lo demás, lo que es el "Sistema básico" funciona de maravilla, a pesar de que el cálculo de la velocidad depende en buena medida de la llanta de enfrente, el margen de error está dentro del 5% por cada cien metros en la presentación; es decir, al momento de mostrar la distancia solo se usan dos decimales y por lo tanto se redondea, pero internamente el calculo se hace bien (dentro del margen de error) y las distancias que he medido con respecto a las mediciones que ya hay suelen estar bien (dentro de lo que cabe).

Y bien, por ahora es todo, si no has intentado construir tu propia versión del velocímetro, puedes hacerlo ahora siguiendo las instrucciones que hay en los post.

Los leo luego.

Vamos a programar #51 - Terminando el velocímetro.

Hola de nuevo a todos, el día de hoy vamos a terminar con el velocímetro para bicicleta. Hoy veremos los esquemas, conexiones y el código par hacerlo funcional.
Así luce en el empaque menos prolijo.

El hardware

Para empezar veamos las conexiones.

  • De la pantalla 1602A
    • VSS va a tierra.
    • VDD va a5v.
    • VO controla el contraste de la pantalla, un valor aceptable son 2.2KOhms.
    • RS va al pin 12 del arduino (se puede modificar).
    • RW va a tierra.
    • E va al pin 11 del arduino.
    • D4 al pin 9 (se puede modificar).
    • D5 al pin 8.
    • D6 al pin 7.
    • D7 al pin 6.
    • A va a 5V.
    • K va a tierra.
  • Del sensor de efecto Hall 1
    • Data va al pin 3.
  • Del sensor de efecto Hall 2
    • Data va al pin 4.
Con la conexiones anteriores, tendremos listo lo necesario, la pantalla puede ser un poco diferente pero esta al ser la mas barata, funcionara de maravilla, puedes omitir el segundo sensor de efecto hall, tendrá utilidad pero no por ahora.

Con lo anterior, empezaremos con el montaje. Lo principal es montar el sensor y los imanes. procurando que todo este lo mas asilado posible, usar plástico termo-contraible es una buena opción para esto.

Para conectar el sensor, use cable de red, solo separe tres hilos y los trencé, luego los aseguré a la tijera que sostiene la llanta usando cinchos de plástico, procurando dejar la longitud adecuada para que cuando el amortiguador recupere su posición original, no tense o afloje de más el cable y pueda atorarse en la llanta.
Dicen que en una bicicleta el polvo es sinónimo de uso rudo (o de que no se limpia seguido).

Después, solo busque una caja de plástico que tenía por ahí, le hice una perforación en donde ajustara la pantalla y simplemente metí todos los componentes.

Para alimentar todo el circuito, uso un power bank, al inicio planeaba usar una batería de litio de un teléfono viejo, pero por cuestiones de espacio, no fue posible, además por ahora, la carcasa será temporal por lo que todo se puede remover fácilmente (exceptuando la caja). Toda la alimentación se hace directo del power bank, incluso si miras bien el esquema, verás que se hace uso de los pines VIN y GND del arduino.

El software.

Ahora pasemos a la parte del software, el código esta listo para usarse, lo único que debes de modificar es la circunferencia de la llanta, en mi caso es una de 24x1.125, pero la más común es de 26xX.XXX, además también debes de incluir la librería para controlar la pantalla.

// Incluir la libreria para la pantalla
#include <LiquidCrystal.h>
// Pines usados en la pantalla extraido de los ejemplos incluidos en la libreria
const int rs = 12, en = 11, d4 = 9, d5 = 8, d6 = 7, d7 = 6;
// iniciar el objeto LiquidCrystal
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
// Este es el valor que debes de modificar para que funcione correctamente
// Puedes ver instrucciones en https://xworkforall.blogspot.mx/2018/03/vamos-programar-49.html
const float Llanta = 1.9572;
//Algunas variables
const int HallSensor1 = 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(HallSensor1, INPUT);
 attachInterrupt(digitalPinToInterrupt(HallSensor1), GetVelocity, LOW);
 pinMode(LED, OUTPUT);
}
// Calcular la velocidad
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; 
}

Las conexiones se hacen de acuerdo al hardware.

Conclusion.

Con esto hemos creado un velocímetro, debo de admitirlo, aun no lo he probado (al menos en el momento en que este post se publicó), pero en cuanto lo haga, pondré cualquier actualización necesaria.

El segundo sensor de efecto hall, se va a usar para activar una luz de frenado, usando el mismo principio, en cuanto la palanca de freno se presiona, si acercamos un imán al sensor que estará fijo al manubrio, esto activará una luz roja en la parte posterior de la bicicleta (tal y cómo los autos). Probablemente también en un futuro se agregue la función de luces direccionales, aun no figuro cómo hacerlo de manera eficiente.

Y bien, por ahora es todo, el código completo para arduino lo puedes descargar de mi dropbox, recuerda que puedes modificarlo a tu gusto.

Los leo luego.

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.

Vamos a programar #49 - Inútil apps #3 - Cómo calcular la velocidad.

Hola de nuevo a todos, el día de hoy vamos a continuar con la construcción de un velocimetro para bicicleta, en el post anterior vimos cómo hacer uso del sensor de efecto hall para poder detectar cuando es que la rueda da una vuelta completa (o cuando un imán es detectado por el sensor). Asi que ahora vamos a ver una parte importante.

Para que el velocimetro quede bien, pienso que al menos debe de medir lo siguiente:

  1. Velocidad (obviamente).
  2. Distancia.
  3. RPM (revoluciones por minuto).
Bien, con lo anterior solo necesitaremos saber cual es la forma de calcular la velocidad. La forma más simple de hacerlo, es usando la formula fisica: v= d/t; donde v es la velocidad en Km/h, d es la distancia en Km y t es el tiempo en horas.

Al mirar el enunciado anterior, podemos determinar que es lo que ya tenemos; la velocidad, es lo que queremos saber, distancia, esta la podemos obtener y el tiempo; para este, arduino cuenta con varias formas de "contar el tiempo".

Obteniendo la distancia.

Para poder obtener la distancia, tenemos que medir cual es la circunferencia de la rueda, hay varias forma de obtenerla.

La primera es mirando la siguiente tabla:

Diámetro Medida rueda (mm)
16x1.75x2 1272
20x1.75x2 1590
24x1 3/8 1948
24x1.75x2 1907
26x1 1973
26x1.5 2026
26x1.6 2051
26x1.75x2 2070
26x1.90 2089
26x1.95 2050
26x2.00 2114
26x2.125 2133
26x1 3/8 2105
26x1 3/8x11/2 2086
26x3/4 1954
27x1 1/4 2199
27x1 1/4 Fifty 2174
27.5x2.10 2150
27.5x2.25 2195
28x1.5 2224
28x1.75 2268
28x1 1/2 2265
28x1 3/8x1 5/8 2205
29 x 2.10 2300
Para saber cual es tu llanta, bastará con revisar un costado de la misma, en mi caso es 24x2.125 (que no esta en la tabla), al revisar, no hay una medida para esa, por lo que pasaremos al siguiente metodo.

Si al revisar la tabla no viste un valor igual al tuyo, podemos obtener la circunferencia si usamos la siguiente formula: C = D * π, Donde C = a la circunferencia en centimetros, D = al diametro en centimetros y π = al numero pi (3.141592654), el diametro lo podemos obtener si usamos una regla para medir. En mi caso, la llanta tiene un diámetro de 62.3 cm, al aplicarlo a la formula anterior, tenemos que la rueda tiene una circunferencia de 195.72 cm.

Otra opción y la mas viable, es medir la circunferencia dando una vuelta, es decir poner una marca en la rueda y en el suelo; pedalear hasta dar una vuelta completa y medir la longitud de la linea.En mi caso la mediad resultante fue de 194.6 cm y esta medida es la mejor, porque ya cuenta con mi peso y si vemos no es muy diferente a la del calculo anterior.

Ahora ya podemos tener la distancia, sabemos, que en mi caso, cada vuelta representan 195.72 cm, la manera simple, es sumar cada medición, por lo que si al dar una vuelta sumamos 195.72 cm, al dar la segunda tendremos 391.44 cm y asi sucesivamente, por lo que la distancia la podemos definir de la siguiente manera: d=195.72 * N° de vuelta, para hacer más fácil la visualización, vamos a convertir los 195.72 cm a m lo que resulta que cada vuelta son 1.9572 m.


Obteniendo la velocidad.

Ahora que tenemos la distancia, podemos obtener la velocidad, de la formula v=d/t, solo nos queda determinar el tiempo. al inicio pensaba usar el modulo de reloj ds1302, pero no se me hacía rentable, dado que solo podria medir tiempo en segundos, cómo programador, se que cada procesador es capaz de llevar la cuenta del tiempo (relativamente), al investigar un poco, vi que arduino cuenta con las funciones millis() y micros() que; respectivamente, llevan la cuenta de los milisegundos y los microsegundos desde que se empezo a ejecutar el programa (desde que se incendio?), para nuestros fines, podemos usar la función millis().

Con un temporizador, podemos tomar el tiempo de cada cuanto el sensor se activo, para eso, primero haremos la medicion de "en que momento estamos" y cuando el sensor detecte un cambio, anotar el tiempo, despues restaremos el tiempo de inicio con el del final y ese lapso de tiempo nos indicará, cuanto tiempo le toma avanzar 1.9572 m (en mi caso).

Con esa información, podemos crear una función en arduino cómo la que sigue:

// {...}
//obtener la velocidad
float GetVelocity(){
	float Velocity = Distancia/((float)(millis()-OldTime)/1000);
	OldTime=millis();
	return Velocity;
}
// {...}

Con esta estaremos midiendo la velocidad en metros por segundo. para hacer la conversion a Km/h, debemos de multiplicar por 3600 (segundos en una hora) y dividir entre 1000 (metros por cada kilometro).

Hay que tener en cuenta algunas consideraciones, ¿cuando es prudente decir que la bicicleta se detuvo? en mi experiencia, el usuario normal, no puede ir muy lento asi que haremos las preparaciones para que cuando el sensor no se active en al menos tres segundos, asumamos que la bicicleta se ha detenido.

Y bien, por ahora es todo, en el siguiente post implementaremos todo el código neceario.

Los leo luego.

Vamos a programar #48 - Inútil apps #3 -Velocímetro para bicicleta, sensor de efecto Hall.

Hola de nuevo a todos. El día de hoy vamos a ver una pequeña introducción a la construcción de un velocímetro.

Cómo algunos sabrán, tengo cierta afición por hacer viajes en bicicleta, pero cómo soy un hombre de números, siempre me ha gustado cuantificar lo que hago (en medida de lo posible), así que decidí llevar la cuenta de la actividad que hacía. Por fortuna, muchos de los teléfonos actuales, tienen aplicaciones que ayudan a llevar el registro (gracias a sensores y al GPS).
Hasta hace poco tenía la idea de hacer una versión propia de un programa que lleve todos esos datos, pero un par de eventos bastante desafortunados, bastaron para pensarlo dos veces. Entonces opté por comprar un velocímetro, lo encargue desde China y tenía un tiempo estimado de entrega de dos meses, pero por sismos y varias cosas, no llegaron (ya va medio año prácticamente, pero aun espero su llegada junto con la de algunos paquetes mas grandes).
Al revisar cómo es que funcionan, noté que la gran mayoría funcionan de la misma manera; se pone un sensor en la tijera que sostiene una llanta y cada vez que ésta da una vuelta, de alguna manera se notifica. En el caso del velocímetro que encargue, en el manual (de internet) decía que se debía de pegar un imán a un rayo de la llanta y el sensor ponerse fijo en la tijera, al revisar más a detalle, averigüe que se trataba de un sensor de efecto Hall.

El sensor de efecto Hall.

El sensor de efecto Hall o simplemente sensor Hall o sonda Hall (denominado según Edwin Herbert Hall) se sirve del efecto Hall para la medición de campos magnéticos o corrientes o para la determinación de la posición en la que está.
Si fluye corriente por un sensor Hall y se aproxima a un campo magnético que fluye en dirección vertical al sensor, entonces el sensor crea un voltaje saliente proporcional al producto de la fuerza del campo magnético y de la corriente. Si se conoce el valor de la corriente, entonces se puede calcular la fuerza del campo magnético; si se crea el campo magnético por medio de corriente que circula por una bobina o un conductor, entonces se puede medir el valor de la corriente en el conductor o bobina.
Si tanto la fuerza del campo magnético como la corriente son conocidos, entonces se puede usar el sensor Hall como detector de metales. Wikipedia/SensorHall
Ahora veremos cómo conectar el sensor de efecto hall, para hacerlo, necesitas lo siguiente:

  1. Sensor efecto hall.
  2. Resistencia 1KΩ  ~10KΩ. 
  3. Arduino

En mi caso, el sensor es el 44e938, cuyos pines son:


  1. Supply (4.5~24V).
  2. Ground.
  3. OutPut.
Para conectarlo, simplemente debemos de conectar la pata uno a V+, en este  caso 5V, Ground a tierra y output a un pin del arduino. Para poder sensar correctamente, debemos de poner una resistencia entre la pata 3 (output) y la pata 1 (supply), al inicio veía esquemas en los cuales siempre usaban resistencias de 10K, pero en mi caso y por el tamaño de los imanes que uso, con una resistencia de 1K fue más que suficiente. Si la resistencia no se pone, el sensor queda muy sensible (valga la redundancia) y detectara cambios tan pequeños en el flujo magnético que incluso acercar tu dedo afecta. OutPut lo conectaremos a un pin del arduino, si quieres probar el código, puedes conectarlo en el pin 3.

Con lo anterior pasemos al código.
//Pin al que coenctaremos el sensor
const int HallSensor = 3;
//LED para mostrar el cambio en caso de no disponer del monitor serie
const int LED =  13;
//Estado del sensor
int HallSensorVal = 0;
//Número de vuelta
int Lap = 0;
//Estado anterior del sensor
int OldState = 0;
//Inicializar lo necesario
void setup() {
	Serial.begin(9600);
	pinMode(LED, OUTPUT);
	pinMode(HallSensor, INPUT);
}
//Bucle princial
void loop() {
	HallSensorVal = digitalRead(HallSensor);
	if (OldState != HallSensorVal) {
		if (HallSensorVal == LOW) {
			digitalWrite(LED, HIGH);
			Lap += 1;
			Serial.println("Vuelta:");
			Serial.println(Lap);
			delay(1);
		}
		else {
		digitalWrite(LED, LOW);
		}
	}
	if (Lap > 99)
		Lap = 1;
	OldState = HallSensorVal;
}

El código anterior, lo único que hace, es verificar cual es el estado del sensor, cuando esta en modo "LOW", prende el LED que viene por default en el pin 13 y a la variable "Lap" le suma 1 (indicando una vuelta). Para probar el código anterior, necesitaras también un par de imanes, en mi caso, los extraje de un quemador de CD viejo, y los pegué en un motor (también extraído del lector de CD).
El resultado:

Con esto podemos probar que el sensor funciona de manera correcta.

Y bien, por ahora es todo, en el siguiente post, veremos cómo medir distancia y velocidad con el mínimo hardware posible. Aun no he decidido si usar las matrices para mostrar los datos o usar una pantalla LCD (cómo la del nokia) o incluso pantalla de siete segmentos. El código lo puedes copiar y pegar para usarlo, en cuanto este completo lo subire a mi dropbox.

Los leo luego.