domingo, 13 de mayo de 2018

Vamos a programar #53 - Errores y cómo tratarlos en c#

Hola de nuevo a todos, el día de hoy vamos a ver un poco acerca de cómo se tratan los errores en c#.

En repetidas ocasiones, he dicho que siempre que se crea código nuevo, por más que uno lleve años programando, siempre apareceran errores. Algunos tan sencillos cómo "¡Olvide una coma, un punto, importar un espacio de nombres!", otros no tan sencillos o que se haran presentes hast que se ejecute el programa en la computadora del usuario final.

El programador dispone de muchos mecanismos para reportar los detalles de las operaciones que se realizan. Algunas son tan simples cómo mostrar una caja de mesaje diciendo si la operacion se llevó a cabo de manera correcta o no y otras un tanto más complicadas cómo BSOD (blue screen of death)
Solo en tiempos recientes se ha cambiado el aspecto "temible" de antes
En el caso particular de C# (y .NET en lo general), dentro del lenguaje de programación se ofrecen las herramientas necesarias para poder manejar los errores. Antes de empezar a ver cómo se debe hacer el tratamiento, debemos de tomar en cuenta el tipo de error que se produce. Siempre habrán dos tipos de errores; uno será aquellos en los que se pueda continuar con la aplicación a pesar de que se ha producido y otro (y más grave), serán aquellos en los que ya no se puede continuar.

En este caso solo nos vamos a centrar en lo errores que son producidos por Software (código), imaginemos que tenemos un fragmento de código cómo el que sigue:

private void button1_Click(object sender, EventArgs e)
{
		int j = 0;
		int I = 100 / j;
}

A pesar de que el error es realmente inminente, si ejecutamos la aplicación y además hacemos click en botón, aparecerá un mensaje cómo el siguiente:
Si hacemos clic en continuar, la aplicación tratará de continuar, pero si no le es posible, simplemente mostrará el mensaje una y otra vez hasta el final de la ejecución (o en este caso, cada que se haga clic). Si hacemos clic en el botón salir, la aplicación se cerrará y la ejecución terminará.

Actualmente hay un debate muy fuerte en la comunidad de programadores. Cuando hay este tipo de errores, es decir cuando sabemos van a pasar, ¿es necesario crear un manejador de errores en este caso? Lo ideal sería evitar que se realice cualquier división entre cero, pero por mas repetitivo que suene, nunca es posible prever todas las variables.

Manejando los errores.

El objetivo del post es ver cómo tratar lo errores en .NET (c#), asi que veamos el siguiente código:

private void button1_Click(object sender, EventArgs e)
{
	try
	{
		int j = 0;
		int I = 100 / j;
	}
	catch(Exception Err)
	{
		MessageBox.Show(Err.Message+"\n En: "+Err.Source, "MDev 2018",MessageBoxButtons.OKCancel,MessageBoxIcon.Error);
	}
}

Es exactamente el mismo, solo que ahora agregamos las palabras reservadas try y catch. Todo el código que queremos ejecutar, lo debemos de poner dentro de try, en el caso del código anterior, la división la ponemos aquí, cuando se produce el error, toda la parte dentro del bloque catch, es la que se ejecutará y para este ejemplo, mostrará una caja de mensaje.
En su forma más simple, el bloque catch, se puede escribir sin los parámetros, pero si queremos obtener detalles acerca del error, creamos una variable del tipo Exception que posee algunos detalles del error.
Dependiendo del tipo de error, se puede definir un bloque catch diferente, al código anterior agreguemos un bloque catch pero con el error que esperamos, es decir: DivideByZeroException, al ejecutar el código en lugar de ver la caja de mensaje con el icono de error, veremos la que definimos cuando se produce DivideByZeroException.

private void button1_Click(object sender, EventArgs e)
{
	try
	{
		int j = 0;
		int I = 100 / j;
	}
	catch(DivideByZeroException)
	{
		MessageBox.Show("No puede divir entre cero");
	}
	catch(Exception Err)
	{
		MessageBox.Show(Err.Message+"\n En: "+Err.Source, "MDev 2018",MessageBoxButtons.OKCancel,MessageBoxIcon.Error);
	}
}

El resultado

Finalmente, en algunos casos aun cuando se produjo el error, debemos de liberar los recursos que se usaron (o cerrar archivos), para eso se dispone de la palabra reservada finally todo el bloque de código que contenga, es el que se ejecutará al final y usualmente se usa para este fin

Cómo ya lo mencioné, es importante decidir cuando es importante tomar medidas en caso de que un error ocurra, pero imaginemos que tenemos un formulario y en el una caja de texto en la cual el usuario ingresará su número de teléfono; es bien sabido que cualquier número telefónico esta conformado por números, entonces si al hacer las comprobaciones, notamos que hay algo que no es un número, de inmediato sabremos que algo no está bien y lo adecuado sería mostrar un mensaje informado de ese detalle y no hacer un manejador solo para ese error.

Y bien, por ahora es todo.Existen muchas maneras de tratar los errores pero con las vistas aquí, es más que suficiente, errores más graves requieren otro tratamiento, pero no suelen ser comunes.

Los leo luego.


domingo, 6 de mayo de 2018

Vamos a programar #52 - Introducción al paralelismo (Básico)

Hola de nuevo a todos, el día de hoy vamos a ver cómo es que se usan las clases en .NET para poder usar el paralelismo.

Antes que nada, ¿que es el paralelismo?

El paralelismo es una forma de computación en la cual varios cálculos pueden realizarse simultáneamente,​ basado en el principio de dividir los problemas grandes para obtener varios problemas pequeños, que son posteriormente solucionados en paralelo. Hay varios tipos diferentes de paralelismo: nivel de bit, nivel de instrucción, de datos y de tarea. El paralelismo ha sido empleado durante muchos años, sobre todo para la Computación de alto rendimiento. Wikipedia/paralelismo.
 Aplicado a los términos de la programación tradicional, el paralelismo significa crear varias tareas que se ejecutan de forma simultanea, en el caso de los sistemas de computo moderno, la gran mayoría de ellos disponen de más de un procesador (9~12 núcleos en el mejor de los casos para el computo casero), pero a la hora de hacer cálculos, al menos en mi caso, nunca me preocupe por usar el mayor poder de computo disponible.

Todas las tareas las hacia de forma secuencial (una tras la otra), pero si el hardware puede hacer más, ¿porque no explotarlo cómo se debe? Actualmente los lenguajes de programación de .NET, disponen de una clase que ayuda a la hora de crear los procesos paralelos.

Para darnos una idea de cómo implementarlo, veamos el siguiente código.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Security.Cryptography;
using System.Threading.Tasks;

namespace PruebaParalelo
{
	public partial class FrmMain : Form
	{
		private FileInfo[] Archivos;

		private string GetMd5(string filename)
		{
			StringBuilder SBuild = new StringBuilder();
			using (var md5 = MD5.Create())
			{
				using (var stream = File.OpenRead(filename))
				{
					byte[] Data = md5.ComputeHash(stream);
					for (int i = 0; i < Data.Length; i++)
					{
						SBuild.Append(Data[i].ToString("x2"));
					}
				return SBuild.ToString();
				}
			}
		}

		public FrmMain()
		{
			InitializeComponent();
		}

		private void BtnAddFiles_Click(object sender, EventArgs e)
		{
			string Path;
			using(FolderBrowserDialog FolderDialog = new FolderBrowserDialog())
			{
				FolderDialog.Description = "Selecciona un folder con archivos";
				if (FolderDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
				{
					Path = FolderDialog.SelectedPath;
					DirectoryInfo di = new DirectoryInfo(Path + "\\");
					Archivos = di.GetFiles("*.*", SearchOption.AllDirectories);
					foreach (FileInfo Archivo in Archivos)
					{
						LVFiles.Items.Add(Archivo.FullName);
					}
				}
			}
		}
		
		private void BtnParallel_Click(object sender, EventArgs e)
		{
			string[] HASH2;
			int ItemCount = Archivos.Length;
			HASH2 = new string[Archivos.Length];
			int j = 0;
			try
			{
				Parallel.For(0, ItemCount, (i) =>
				{
					HASH2[i] = GetMd5(Archivos[i].FullName);
				}
				);
				foreach (FileInfo Archivo in Archivos)
				{
					LVFiles.Items[j].SubItems.Add(HASH2[j]);
					j++;
				}
			}
			catch
			{
			}
		}
	}
}


Para poder usar las funciones de paralelismo, debemos de importar el espacio System.Threading.Tasks. El código simplemente calcula el número MD5 de un archivo, pero si no fijamos con detenimiento en BtnParallel_Click, veremos que hacemos uso de Parallel.For , que en su forma más simple, recibe 3 argumentos. El primero, es un valor del tipo int que servirá para indicar desde que número empezaremos la iteración, en este caso es el número 0 (porque desde ahí vamos a empezar a contar). El siguiente parámetro, también es un valor del tipo int, que se usará cómo limite para la iteración, en el caso del código anterior, indicamos que solo va a llegar hasta ItemCount que almacena el número de elementos que contiene un arreglo. Finalmente viene la acción, en este caso la creamos por medio de una expresión lambda en la cual decimos que por cada elemento, se va llamar a la función GetMd5, y a su vez el valor resultante se asignará a un elemento de la matriz HASH2, cuando termine el proceso, todos los valores se agregaran al listview principal y se mostrarán al usuario.

Los resultados los podemos ver en la siguiente imagen (hablando de rendimiento).


Mientras que de un lado tenemos que el uso del CPU está en 25% y tardo 30 segundos en calcular el HASH de algunas imágenes, del otro vemos que el uso del CPU es al 100% y además el tiempo que le tomo fue una cuarta parte del tiempo del calculo secuencial.

Para que revises bien el código, lo pongo en mi dropbox cómo de costumbre, pero cabe aclarar que es meramente ilustrativo, pero cómo introducción funciona. En futuros post veremos cómo hacer uso de las sobrecargas que tienen la misma función Parallel.for, pero además veremos cuales son las diferencia con el multi-therad tradicional (recuerdo que hice un post pero no se publicó y desapareció).

Los leo luego

domingo, 29 de abril de 2018

Back to basics #5 - Prefijos y potencias.

Hola de nuevo a todos, el día de hoy vamos a hablar un poco de sobre las potencias de 10.
Hace algunos días, fui a comprar un par de capacitores a la tienda de electronica más cercana a mi casa, al llegar, el tecnico me pidio amablemente mi orden a lo cual dije "quiero 2 capacitores de 22 pF", reviso una tabla y no vio cual era el numero para 22 pF (pico faradios), entonces le dije, "son 22pF, el capacitor deberia de tener un numero 22 en la parte de enfrente", reviso y no lo tenía, a lo cual me ofrecio uno de 22 µF, de inmediato le dije que era un valor exageradamente grande.

De inmediato puso cara de sorpresa y fue aun mayor cuando le dije que 1 µF es un millon de veces 1 pF, la explicación se la di  y de paso anote la mayoria de prefijos y sus equivalencias.

Tabla de prefijos y sus valores.

La siguiente tabla muestra los prefijos más comunes:

NombreSimboloMultiplicadorPotencia
yottaY1 000 000 000 000 000 000 000 00010^24
zettaZ1 000 000 000 000 000 000 00010^21
exaE1 000 000 000 000 000 00010^18
petaP1 000 000 000 000 00010^15
teraT1 000 000 000 00010^12
gigaG1 000 000 00010^9
megaM1 000 00010^6
kilok1 00010^3
milim0.00110^-3
microµ0.000 00110^-6
nanon0.000 000 00110^-9
picop0.000 000 000 00110^-12
femtof0.000 000 000 000 00110^-15
attoa0.000 000 000 000 000 00110^-18
zeptoz0.000 000 000 000 000 000 00110^-21
yoctoy0.000 000 000 000 000 000 000 00110^-24
Con lo anterior, podemos nombrar cualquier cantidad, algunos de ellos te resultarán familiares; kilo, mega, giga e incluso mili. Ahora sabrás que cuando alguien dice que tiene kilo-algo, se refiere a que tienen 1000 de ese algo.

En adicion, hay algunos prefijos que no se listan en la tabla anterior, incluso algunos se usan cotidianamente cómo el caso de "centi", este se usa cuando tomamos algo y lo dividimos en 100, tal cómo el caso del centimetro, pero decidi no agregarlo, puesto que en la mayoria de lecturas de este blog, siempre usaremos algunas de las listadas en la tabla anterior.

Y bien, por ahora es todo, en el siguiente post continuaremos con más sobre programación.

Los leo luego.

domingo, 15 de abril de 2018

Vamos a platicar #5 - La importancia de reciclar.

Hola de nuevo a todos, el día de hoy vamos a platicar un poco. En esta ocasión, veremos un poco de la importancia de reciclar (en este caso pilas/baterias).
Cómo algunos sabrá, hace poco hicimos un velocímetro para bicicleta (que quedo bien), todos los materiales fueron dispuestos y a la hora de hacerlo funcionar, solo quedaba una interrogante: ¿Cómo alimentarlo? La respuesta es simple, tenia un par de power banks por ahí, uno con una capacidad de aproximadamente 2500 mAh y otro de aproximadamente 800 mAh. Lo bueno de los productos chinos, es su bajo precio, lo malo; algunas veces te dan gato por liebre.

Hace poco adquirí algunos power banks y  a la hora de utilizarlos, me di cuenta que no cumplían con las exigencias necesarias. Intente cargar un teléfono que tiene una batería de 1380 mAh y al usar el power bank de supuestos 2500 mAh, este solo logró cargar el telefono a un 30%. La primer acción fue dejar cargar el power bank toda la noche (cosa que no es muy recomendable) para poder usarlo al día siguiente. Al hacer la prueba me di cuenta que en efecto, el power bank no tenia los 2500 mAh que prometía.

Decidido a encontrar la falla, procedí a examinarlo, por lo que lo abrí. Todos los circuitos estaban en orden pero al inspeccionar la pila más de cerca, note que solo era de 400 mAh. Un timo realmente, sabía que en algunos productos chinos era normal que exageraran e incluso podía esperar la mitad de la capacidad prometida, pero no fue así. Debido a que el velocímetro tienen un gasto de aproximadamente 150 mA, si usaba ese power bank, solo tendría una autonomia de un par de horas efectivas. Asi que decidi buscar una solucion a esto.


Aprovechando que tenía algunas baterias por ahí, busque la forma de reciclar, la forma más sencilla, fue tomar el power bank, extraer el circuito de control (carga/boost/descarga) y reemplazar la batería por una más grande. Recorde que tenía una bateria de 3100 mAh por ahí, entonces decidí usarla, con mucho cuidado procedi a remover el circuito de protacción que la batería tenía integrado, medí el voltaje y al ver que aún entregaba 3.9 V, significaba que aun estaba en buen estado. Al unir los componentes, todo funciono de maravilla y lo mejor es que ahora tendria aproximadamente 20 horas de autosuficiencia en el velocimetro.

Al ver que esto funciono, hice lo mismo con un PSP, cómo ya no es sencillo encontrar una bateria original (y cuando compré una tambien me estafaron), hice exactamente lo mismo, de la bateria original del PSP solo extraje los circuitos de protección y la bateria la reemplace con la del telefono viejo.
Admiren al: "PSP-Frankestein edition", use una tapa diferente para no cortar la original y el lector de UMD aun abre, por cierto la bateria de la primer imagen y esta son diferentes
Pese a que no es muy estetico, soy de los que no les importa cómo luzaca, si no como funciona. La batería original del PSP es de 1200 mAh, al agregar una batería de 2100 mAh casi duplicamos la capacidad y por la tanto la autonomía.

Por triste que parezca, al menos en el lugar donde vivo, sale más barato comprar un power bank mobo (no es la mejor marca, pero tiene algo de soporte y funciona), que comprar los componente por separado y hacer un circuito similar (eso si se consiguen, en las cercanías donde vivo ir y comprar un inductor es casi imposible).

De todas, solo la que tiene el logo de motorola y la que esta al extremo derecho las he comprado nuevas, el resto son recicladas y aun funcionan.
Antes de determinar si una batería aun es apta para su uso o no, hay que tener algunas PRECAUCIONES, la mala manipulación de algunas puede resultar en daños (o cosas peores), pero eso lo veremos en otro post, por ahora es todo y recuerda, algunas cosas merecen una segunda oportunidad.

Los leo luego.

domingo, 8 de abril de 2018

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.

domingo, 1 de abril de 2018

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.

domingo, 18 de marzo de 2018

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.

domingo, 11 de marzo de 2018

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.

domingo, 4 de marzo de 2018

Vamos a programar #47 - Co-Rutinas en LUA.

Hola de nuevo a todos, el día de hoy vamos a ver un poco sobre el lenguaje de programación LUA.

Antes que nada, debo de aclarar que este no es un tutorial para aprender a programar en Lua, en este post solo explicaré cómo hacer uso de las co-rutinas. Probablemente en el futuro, habrá un ecuatorial completo en las series "Learning machine", pero por ahora y por petición de un amigo mio, veremos cómo es que se hace uso de ellas. Eso no nos impedirá ver lo básico, ¿Que es Lua?; bueno, lua es un lenguaje de programación interpretado; es decir, a diferencia de lenguajes cómo C o C#, este, no es necesario compilarlo para usarlo, una vez escrito el código fuente, se puede pasar al interprete (que será el ejecutable) y este interpretará el código y producirá un resultado, si es necesario cambiar alguna parte del programa, en lugar de volver a compilar el ejecutable, bastará con modificar el código fuente.

Co-rutinas.

Ahora veamos lo que nos trajo a este post, hace un tiempo, mientras un escribía código para "Play List M" (una aplicación para PSVita), un amigo vio lo que hacía y pregunto que si sabía usar lua, le dije que si, toda la aplicación esta hecha en ese lenguaje, entonces me pregunto si sabia usar las co-rutinas y si podía explicarserlas.

Las co-rutinas en lua, sirven para ejecutar código en una sección aparte, es muy similar un "thread" en c#, pero de una forma un tanto distinta. Veamos cómo es que se ejecuta un programa con un "thread" (hilo desde ahora) separado. Ahora observemos las siguientes imágenes.
Esta es la representación más simple de un programa

Esta es la representación más simple de un programa con un hilo adicional.

La ventaja de tener un hilo secundario, es que la aplicación no se bloqueara mientras haga un trabajo difícil (o haga un ciclo o un bucle), si los resultados no son necesarios para continuar con la ejecución del programa, podemos hacer otra tarea mientras el código del otro hilo termina.

En el caso de lua, cuando hablamos de co-rutinas, no significa que creemos otro hilo, para observar a detalle lo que ocurre, tomemos el siguiente código:


local counter = 1; local function OneToHoundred() while counter < 50 do io.write("Contador:"..counter.."\n"); coroutine.yield(); counter = counter + 1; end end CoProc = coroutine.create(OneToHoundred); local counter2 = 0; while counter2 < 101 do coroutine.resume(CoProc); io.write("Contador2:"..counter2.."\n"); counter2= counter2 + 1; end

En lua, la manera sencilla de crear una co-rutina, es haciendo uso de "coroutine.create()" y en su forma más sencilla, debemos de pasar una función cómo parámetro. para poder interactuar con la función, dentro de esta, debe de haber algo que diga "oye, tengo que decir algo", la función "coroutine.yield()" se encarga de hacer eso, finalmente, debemos de tener una parte que escuche y para eso existe "coroutine.resume()". Si tomamos cómo ejemplo el código anterior, vemos que hay que crear la funcion y esta debe de contener la "interrupción", en este caso "coroutine.yield()" la manera en que lua trabaja con las co-rutinas, es interrumpiendo, es decir si estamos ejecutando un trozo de código, este normalmente se ejecutará de forma lineal hasta el final, pero si usamos las co-rutinas, cuando observamos en el segundo bucle, y en general cuando se encuentre con la instrucción "coroutine.resume()", la ejecución pasará a la co-rutina y esta se ejecutará hasta que se encuentre con "coroutine.yield()", cuando se encuentra con esta instrucción, la ejecución continuará con la linea inmediata después de "coroutine.resume()".

Para poder apreciar mejor el resultado, puedes ir a la página de lua, y probar el código anterior.
Cómo lua es un lenguaje de "scripting" es usado en varias plataformas y las funciones disponibles pueden variar, pero todas las que se usan aquí, deben de estar disponibles en la mayoría, ahora por ejemplo, si queremos cargar archivos sin bloquear la pantalla principal, podemos hacerlo usando co-rutinas. Esa seria la introducción, pero esto se puede ampliar un poco mas, en otro post.

Los leo luego.

domingo, 18 de febrero de 2018

Vamos a platicar #4 - Luchando contra la estupidez.

Hola de nuevo a todos, el día de hoy vamos a platicar un poco sobre la estupidez.

Cómo muchos se habrán dado cuenta, el día 16 de febrero del 2018, en México, ocurrió un sismo de una magnitud considerable.


Aquí lo rescatable, es que todo estuvo en orden, la preocupación por las edificaciones que resultaron dañadas el 19 de septiembre, solo quedó en eso; preocupación. Todo quedo en la sacudida y ya. Pero la gente es pesimista por naturaleza, y de inmediato empezaron a cuestionarse; ¿Si este fue más fuerte que el otro, por que no pasó nada (al menos en la zona centro de México)? La respuesta es simple, el sismo se genró en una zona alejada, por eso a comparación del 19 de septiembre, ahora si sonó la alerta sísmica con 60 segundos (+-), suficiente para salir o resguardarte en una zona segura.

Desde el sismo anterior, a muchas personas les dio por adivinar cuando es que ocurriría el próximo sismo, muchos prácticamente todos los días publicaron en su twitter "hoy va a temblar"; así lo hicieron todos los días hasta que eventualmente ocurrió una coincidencia. Es importante resaltar la palabra "coincidencia", si has andado por estos lares, sabrás que prácticamente todos los días tiembla, lo hace en magnitudes "pequeñas" (2.0~5.0 grados) y por eso no son perceptibles para la mayoría de la población. De todos los temblores que ocurren, un día habrá uno de una magnitud considerable y esta gente cómo se la pasó todos los días haciendo lo mismo, lamentablemente acierta.

Mientras navegaba por internet, vi una cantidad de vídeos impresionante en las que se aseguraba predijeron tal evento. Solo para tratar de evidenciar lo charlatanes que eran las personas que hicieron esos videos, entré y comenté algo sensato. La respuesta de la gente fue realmente estúpida, de 10 personas que respondieron mi comentario, ninguna se tomo la molestia de revisar alguno de los enlaces que puse a fuentes confiables (cómo la universidad nacional autónoma de México), lejos de eso, me atacaron, que dejara de desvirtuar el video, que solo era un troll de internet tratando de hacer fama insultando al video e incluso alguien que aseguraba ser geólogo y además decía que si era posible predecir los temblores. Todo esto era bastante frustrante, tan solo por la primicia; "predecir temblores en base a la actividad del sol".

Cualquiera creería que no hay gente tan tonta cómo para creer en cosas tan descabelladas, y si, es muy probable que algunos de los comentarios fueran solo con la intensión de molestar, pero cuando hablé con alguien en la vida real, me dijo exactamente lo mismo que el video y me trato de idiota por decir que estaba mal.

Alguna vez, uno de mis profesores en la facultad, dijo que la estupidez debía de combatirse, pero cómo rayos se hace cuando la persona es necia? Tratar de insistir me volveria en alguien molesto que solo trata de mostrar que tiene un poco de razón. Finalmente desistí, algunas veces hay que dejar a los necios morir en su necedad.

Y bien por ahora es todo, solo me queda recordarles lo básico: los temblores no son predecibles, diario tiembla y en el caso de la zona centro de México; si suena la alerta sísmica, es para resguardarse (y no para ver si tiembla). La semana que viene continuaremos con más programación, hace poco alguien me pidió ayuda en lua y creo que serviría para aprender y cómo introducción para hacer lo mismo en otros lenguajes.

Los leo luego.