Xwork's Blog

The lord is waiting to take your hand.

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

Inútil apps #5 - Visualizer V3 (parte 3)

Hola de nuevo a todos, después de tomar el sueño eterno (que en la actualidad es de seis a nueve meses!!) Por fin regresamos a terminar con los asunto pendientes y a tratar de aprender mas en el proceso. En el último post, estábamos fabricando unas luces que prenden y apagan al ritmo de la música.

Para poder comenzar vamos a ver el diagrama, esta disponible para su consulta en el sitio de OSHWLab, el proyecto puede ser visto en línea o puedes descargarlo para poder abrirlo en Eagle o Altium y antes de empezar te recomiendo revisar las primeras dos partes de proyecto, en la primera hablaamos sobre cómo amplificar la señal usando el circuito integrado LM358 y en la segunda parte, vimos cómo se hacen las conexiones para el LM3915.

Una vez dicho lo anterior, veamos todas las partes electricas que necesitaremos para el proyecto.

Una cosa mas antes de continuar con la lista de partes, todos los pines que tengan el prefijo "H" (Por ejemplo H1, H2, etc) Y también los llamados "AUDIOINR" y "AUDIOINL" los omitiré de la lista, ya que en lugar de soldar pines, ahí soldaré directamente los cable y dependiendo de cada quien, se pueden poner los pines o no.

ahora si, veamos la lista de componentes:
MARCAValor
R1,R4,R9,R1010k
R2,R51k
R3,R6200k
R7,R8680
C1,C210uF
D1,D21N4007
U1LM358
U2,U3LM3915
LED1,LED2,LED3,...,LED20 Diodo LED 5mm
POT1Potenciómetro 100k
BUCK1Buck converter

Nuevamente sugiero que revises la parte 1 y la parte 2 de este proyecto para poder entender el "porqué" de cada valor. Los circuitos los pedí por JLCPCB y llegaron en tiempo y en forma (nadie me paga por decir lo anterior), recomiendo ampliamente el ordenarlo, pero si no confías en este tipo de servicios, también es posible hacerlo a mano en placas de prototipo.

Una vez hechas las conexiones del diagrama, es necesario explicar para que sirven todos los pines.
  • AUDIOINR
    • Sirve para conectar el audio, el canal derecho es recomendado, en el pin que tiene forma de cuadrado o PIN1 conectamos la parte positiva del audio, el pin 2 no se conecta y el pin 3 va al negativo del audio.
  • AUDIOINL
    • Igual que el anterior, sirve para conectar el audio de entrada, el canal izquierdo es el recomendado.
  • H1
    • Comparte las conexiones del pin 1 y tres de los pines "AUDIOINR", pero además, en este se encuentra la salida regulada del audio que se conecta a una entrada del LM358.
  • H2
    • Comparte las conexiones del pin 1 y tres de los pines "AUDIOINL", pero además, en este se encuentra la salida regulada del audio que se conecta a una entrada del LM358.
  • H3
    • Es la entrada de 5v
  • H4
    • Es la entrada de 12v
  • U5 y U4
    • Son los jumpers para seleccionar el modo punto o barra del LM3615
Para controlar el nivel del audio, usamos un potenciómetro de 100k, al inicio planee ponerlo en la placa pero debido a que mi visión fue cómo la del prototipo (o la foto de arriba). El potenciómetro, debe de ir en una de las paredes del gabinete, por lo que es necesario usar los cables. Para que la detección funcione, necesitamos hacer las conexiones cómo sigue:

Y la razón por la que están compartidas las conexiones es simple, en mi caso, el las terminales del potenciómetro están conectadas a H1, pero queda libre "AUDIOINR" para poder conectar mi amplificador de audio y poder escuchar, algunos usan un plug de doble salida.

Para alimentar el circuito, se pueden usar fuentes de 5 hasta 24v, y se conectan a H4, pero además es necesario usar una fuente adicional para obtener un voltaje inferior y conectarlo a H3. Seguramente te estás cuestionando ¿para qué?. La respuesta es simple, supongamos que alimentamos a H4 con 5v, este voltaje se va a usar para alimentar el integrado LM358 que hace la amplificación, pero si recordamos, el LM358 no es capaz de sacar un voltaje igual al que se usa para alimentarlo, es decir si amplificamos 0.2v diez veces, tendremos una señal de 2v a la salida, ahora si por ejemplo, tomamos 0.49v y le aplicamos el mismo novel de ganancia, tendríamos a la salida del LM358 4.5v (no exactamente); la idea central de todo esto, es que el voltaje siempre será menor al que usemos de alimentación y a la hora de ingresarlo al LM3915 no seria suficiente para cubrir el rango de este que iría de 0v a 5v. Para solucionarlo, decidí usar un voltaje diferente e inferior para alimentar al LM3915, retomando los 5v de ejemplo, si usamos ese, a H3 lo podemos alimentar con 3.3v usando el buck converter (incluso usar el LM7803) y con eso aseguramos que el rango vaya de 0 3.3v, asegurando que la señal siempre podrá cubrirlo. La configuración que yo uso es 12v para H4 y 5v para H3

Finalmente para U4 y U5, si se hace un puente para cada una, es decir si los pines de U4 los unimos y hacemos lo mismo con U5; activaran el modo barra, si los dejamos abiertos, el LM3915 trabajará en modo punto.



Y bien, por ahora es todo, es cierto que pasaron momento difíciles (se que habrá algunos preocupados) en el blog pero planeo seguir con esto lo mas que se pueda. y por cierto, dejo un video del proyecto en acción.


Cómo de costumbre, los leo luego.

Vamos a programar #72 - Calculadora de resistencias para diodos LED (ver. Java para android).

Hola de nuevo a todo, el día de hoy vamos a ver el código en java para hacer una calculadora de resistencias para diodos LED.

En los post anteriores vimos cómo hacer la calculadora en javascript para los navegadores y en C# para las computadoras de escritorio ahora con está versión tenemos la versión para los teléfonos móviles.

Cómo el código (y su funcionamiento) es muy similar al de las otras versiones vamos a pasar directamente a el. El código que hacer funcionar la calculadora es el siguiente:

package com.mdev.ledrescalc;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.RadioButton;

public class MainActivity extends Activity {
EditText ETVin, ETVLed, ETILed, ETNLed, ETResult;
Button BtnCalc;
RadioButton RConexion1, RConexion2;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		ETVin = findViewById(R.id.ETVin);
		ETVLed = findViewById(R.id.ETVLed);
		ETILed = findViewById(R.id.ETILed);
		ETNLed = findViewById(R.id.ETNLed);
		ETResult = findViewById(R.id.ETResult);
		BtnCalc = findViewById(R.id.BtnCalc);
		RConexion1 = findViewById(R.id.Conexion1);
		RConexion2 = findViewById(R.id.Conexion2);
		BtnCalc.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				ETResult.setText(CalculateRes(ETVin.getText().toString(),ETVLed.getText().toString(),ETILed.getText().toString(),ETNLed.getText().toString(),RConexion1.isChecked()));
			}
		});
	}

	private String CalculateRes(String VIn, String VLed, String ILed, String NLed, boolean Serie)
	{
		double Corriente = 0;
		double DropVol = 0;
		double TotalRes = 0;
		double TotalVolt = 0;
		double Potencia = 0;
		double Vin = Double.parseDouble(VIn);
		double Vled = Double.parseDouble(VLed);
		double Iled = Double.parseDouble(ILed);
		double Nled = Double.parseDouble(NLed);
		if (Serie)
		{
			TotalVolt = Vled * Nled;
			if (Vin < TotalVolt){
				return "El voltaje es bajo";
			}
			Corriente = Iled;
			DropVol = Vin - TotalVolt;
			TotalRes = DropVol/Corriente;
			Potencia = Corriente * DropVol;
			return "Se necesita una resistencia de "+ TotalRes +" ohm(s) de una potencia de superior a "+ Potencia + " Watt(s)";
		}
		else{
			TotalVolt = Vled;
			if (Vin < TotalVolt){
				return "El voltaje es bajo";
			}
			Corriente = Iled * Nled;
			DropVol = Vin - TotalVolt;
			TotalRes = DropVol/Corriente;
			Potencia = Corriente * DropVol;
			return "Se necesita una resistencia de "+ TotalRes +" ohm(s) de una potencia de superior a "+ Potencia + " Watt(s)";
		}
	}
}

EL código anterior solo consta de una funcion llamada "CalculateRes()" qué cómo su nombre lo sugiere, se usa para hacer el cálculo para saber el valor de la resistencia necesaria. Recibe cinco parametros. Los primeros cuatro son del tipo "String" y que en orden de aparicion se usan para:

  1. El voltaje de entrada.
  2. El voltaje del LED.
  3. La corriente del LED.
  4. El número de LED's conectados.
El quinto parámetro es del tipo "boolean" y se usa para indicar se las conexiones son en serie o paralelo.

Con la anterior tenemos la calculadorra lista para poder usarla en el celular. Cómo de costumbre puede bajar el APK ya compilado o puedes descargar el código fuente; recuerda que solo incluye el código fuente y se quito la gran mayoria de archivos generados por android studio.

Los leo luego.

Vamos a programar #71 - Calculadora de resistencias para diodos LED (ver. C#).

Hola de nuevo a todos, el día de hoy vamos a continuar con mas sobre resistencias y diodos LED.
En el post anterior vimos el código en javascript que ya disponible en el blog para que lo revises y para que lo pruebes en linea (ya está corregido un par de errores que tenía).
Cómo el código es realmente similar al anterior, simplemente lo pongo para que lo revises, la explicación es un tanto similar a la versión en Javascript.

El código.


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace LedResCalculator
{
	public partial class FrmMain : Form
	{
		
	private string CalculateRes(decimal VIn, decimal VLed, decimal ILed, int NLed, bool Serie)
	{
		decimal Corriente = 0;
		decimal DropVol = 0;
		decimal TotalRes = 0;
		decimal TotalVolt = 0;
		decimal Potencia = 0;
		if (Serie)
		{
			TotalVolt = VLed * NLed;
			if (VIn < TotalVolt){
				return "El voltaje es bajo";
			}
			Corriente = ILed;
			DropVol = VIn - TotalVolt;
			TotalRes = DropVol/Corriente;
			Potencia = Corriente * DropVol;
			return "Se necesita una resistencia de "+ TotalRes +" ohm(s) de una potencia de superior a "+ Potencia + " Watt(s)";
		}
		else{
			TotalVolt = VLed;
			if (VIn < TotalVolt){
				return "El voltaje es bajo";
				}
				Corriente = ILed * NLed;
				DropVol = VIn - TotalVolt;
				TotalRes = DropVol/Corriente;
				Potencia = Corriente * DropVol;
				return "Se necesita una resistencia de "+ TotalRes +" ohm(s) de una potencia de superior a "+ Potencia + " Watt(s)";
			}
	}
		public FrmMain()
		{
			InitializeComponent();
		}

		private void BtnCalculate_Click(object sender, EventArgs e)
		{
			TxtResult.Text = CalculateRes(NUDVolt.Value, NUDVLed.Value, NUDILed.Value, (int)NUDNLED.Value, RBConexion1.Checked);
		}
	}
}

EL código consta de una sola función llamada "CalculateRes()" y recibe cinco parámetros; los primeros tres son del tipo "decimal" y en orden representan: el voltaje de entrada, el voltaje del LED y la corriente del LED. El siguiente parámetro es del tipo "int" y nos servirá para indicar el número de LED's que se conectan. Finalmente el parámetro llamado "Serie" del tipo "bool" nos indica si la conexión está en serie cuando su valor es "true". La decisión de usar valores del tipo decimal es simple, los controles "NumericUpDown" devuelven un valor de este tipo cuando se accede a la propiedad "Value" y es un tipo bastante adecuado para llevar a cabo la tarea que queremos realizar.

Cómo de costumbre el código lo puedes descargar de mi dropbox para probarlo.

Los leo luego.

Vamos a programar #70 - Calculadora de resistencias para diodos LED (ver. Javascript).

Hola de nuevo a todos, el día de hoy vamos a ver cómo hacer una calculadora en javascript que sirva para calcular que resistencia debemos de usar si queremos utilizar un diodo LED con un voltaje mayor a esperado.
Pero antes, unas consideraciones. Primero: esta no es la forma más eficiente de alimentar un LED, ya que mucha energia es deperdiciada. Segundo: Usar una sola resistencia para limitar la corriente que varios LED's no es lo mas recomendable; si se van a hacer uso de varios LED's lo mas recomendable sería poner una resistencia por cada LED que se conecte, es decir calcular el valor de cada uno y ponerle su resistencia y no cómo la imagen. En la calculadora es meramente ilustrativo.

 Ahora si, con las previsiones hechas, pasemos al código de la calculadora.

El código en javascript que hace funcionar la calculadora es el siguiente:

<html>
<head>
<title>Calculadora de resistencias para LED's</title>
<style type="text/css">
.h1RC
{
    font-size: 16px;
}
.formResCal{
    font: 95% Arial, Helvetica, sans-serif;
    max-width: 400px;
    margin: 10px auto;
    padding: 16px;
    background: #F9F9F9;
}
.textareaRC
{
    width: 100%;
    height: 150px;
    padding: 2px 5px;
    box-sizing: border-box;
    border: 2px solid #229;
    border-radius: 4px;
    resize: none;
    -webkit-transition-duration: 0.4s; /* Safari */
    transition-duration: 0.4s;
}

.textareaRC:focus
{
    width: 100%;
    height: 150px;
    padding: 2px 5px;
    box-sizing: border-box;
    border: 2px solid #0000BB;
    border-radius: 4px;
    resize: none;
}

.TextRC
{
    width: 100%;
    box-sizing: border-box;
    border: 2px solid #999;
    border-radius: 4px;
}

.ButtonRC
{
width: 100%;
    background-color: #57a2e2;
    border: none;
    color: white;
    padding: 15px 32px;
    text-align: center;
    text-decoration: none;
    display: inline-block;
    -webkit-transition-duration: 0.4s; /* Safari */
    transition-duration: 0.4s;
}

.ButtonRC:hover
{
width: 100%;
    background-color: #276775;
    border: none;
    color: white;
    padding: 15px 32px;
    text-align: center;
    text-decoration: none;
    display: inline-block;
}
</style>
<script type="text/javascript">

function RadioSelected(){
var radios = document.getElementsByName('Conexion');
	for (var i = 0, length = radios.length; i < length; i++) {
		if (radios[i].checked) {
			return Number(radios[i].value)
		}
	}
}

function CalculateRes()
{
	var VIn = Number(document.getElementById('InV').value);
	var VLED = Number(document.getElementById('LEDV').value);
	var ILED = Number(document.getElementById('LEDI').value);
	var NLED = Number(document.getElementById('LEDN').value);
	var Corriente = 0;
	var DropVol = 0;
	var TotalRes = 0;
	var TotalVolt = 0;
	var Potencia = 0;
	var ConexionType = RadioSelected();
	if (ConexionType == 1){
		TotalVolt = VLED * NLED;
		if (VIn < TotalVolt){
			alert('El voltaje es bajo');
			return;
		}
		Corriente = ILED;
		DropVol = VIn - TotalVolt;
		TotalRes = Math.ceil(DropVol/Corriente);
		Potencia = Corriente * DropVol;
		document.getElementById('Result').value = "Se necesita una resistencia de "+ TotalRes +"ohm(s) de una potencia de superior a "+ Potencia + " Watt(s)";
		}
		else{
		TotalVolt = VLED;
		if (VIn < TotalVolt){
			alert('El voltaje es bajo');
			return;
		}
		Corriente = ILED * NLED;
		DropVol = VIn - TotalVolt;
		TotalRes = Math.ceil(DropVol/Corriente);
		Potencia = Corriente * DropVol;
		document.getElementById('Result').value = "Se necesita una resistencia de "+ TotalRes +"ohm(s) de una potencia de superior a "+ Potencia + " Watt(s)";
		}

}
</script>
</head>
<body>
		<form class="formResCal">
			<span class="h1RC">Voltaje de alimentacion (V):</span><br />
			<input class="TextRC" id="InV" type="number" value = "5" placeholder = "Voltaje en volts"></input><br />
			<span class="h1RC">Voltaje del LED (V):</span><br />
			<input class="TextRC" id="LEDV" type="number" value = "3.1" placeholder = "Voltaje en volts"></input><br />
			<span class="h1RC">Corriente del LED (A):</span><br />
			<input class="TextRC" id="LEDI" type="number" value = "0.02" placeholder = "Corriente en Amperes"></input><br />
			<span class="h1RC">Numero de LED's:</span><br />
			<input class="TextRC" id="LEDN" type="number" value = "1"></input><br />
			<input type="radio" name="Conexion" value="1" checked> Serie<br>
			<input type="radio" name="Conexion" value="2"> Paralelo con una sola resistencia<br>
		<br>
			<input class="ButtonRC" id="ToAny" onclick="CalculateRes()" type="button" value="Calcular" /><br />
			<br />
			<span class="h1RC">Resultado:</span><br />
			<textarea class="textareaRC" id="Result" rows="5" placeholder = "Resultado"></textarea><br/>
			<br />
		</form>
</body>
</html>

Cómo podrás observar, simplemente pasamos a la computadora los cálculos que hicimos la vez pasada. El programa consta de dos funciones solamente. La primera de ellas es "RadioSelected()", que cómo su nombre lo indica, su trabajo es revisar cual de los controles del tipo "radio" es el que está seleccionado de la colección "Conexion", para ello itera a traves de todos los elementos y cuando encuentra uno que tenga la propiedad "checked" en "true" devuelve el valor del indice de este elemento.

Luego tenemos la funcion "CalculateRes()" primero lo que hacemos es obtener los valores que necesitamos usado la función "document.getElementById()" y los asignamos a la variables, luego se manda a llamar a la función "RadioSelected()" para ver que tipo de conexión es la que tienen los LED, en este caso, cuando es uno, significa que la conexión es en serie en caso contrario es paralelo .
Si revisas los apartado, veras que son muy similares y de hecho lo son, pero la diferencia, es que cuando la conexión es en serie, el voltaje aumenta y la corriente permanece, entonces la diferencia esta en cómo se mide esta, en una será la corriente que tenga la variable "VIn" y en la otra será la que resulte de multiplicar {"VIn * NLED"} donde "NLED" es el número de LED's conectados.

Finalmente, el resultado de los cálculos de la resistencia y la potencia se asignan al control "textarea" llamado "Result".

Cómo podrás ver, los cálculos son realmente sencillos y muy fáciles de portar a otro lenguajes; cosa que haremos la siguiente semana, ya que al igual que otros de los programas que hemos hecho, haremos una versión web, de escritorio y móvil.

El código lo puedes descargar de mi dropbox para que lo pruebes, pero además en breve subiré una versión al blog para que se pueda usar.

Y bien, por ahora es todo, en el próximo post veremos la version de C#.

Los leo luego.

Back to basics #6 - Resistencias y diodos LED.

Hola de nuevo a todos, el día de hoy vamos a ver un poco de cómo usar unos de mi componentes electrónicos favoritos: el diodo LED.
Imaginemos que en algun momento contruyes un velocímetro para una bicicleta y te levantas por las mañanas a hacer tu recorrido, pero un buen dia, por alguna razon las lamparas ddel alumbrado publico no encienden, al inicio supones que es algo normal, ya que las cosas tienden a fallar, pero tras tres semanas te das cuenta que probablemente no las van a reparar en fechas próximas por lo que decides agregarle "iluminacion" a tu bicicleta, pero surge una pregunta ¿Cómo alimentar la iluminacion?

Ultimamente se han hecho bastante accesibles los diodos LED, gracias a su alta eficiencia, son muy utiles a la hora de obtener alimentacion por medio de pilas o baterias pues nos asegura que estas duraran algo de tiempo; cosa que no pasaba antes con las lamparas que usaban filamento incandescentes y que se devoraban las pilas.

Si  no has visto cómo es que hice el velocímetro, aun puedes hacerlo pero haciendo memoria, este funciona con un voltaje de 5 v, si intentamos conectar un diodo directamente, este explotaría.

Dependiendo del tipo de diodo LED, este requerirá mas o menos voltaje, en mi caso conseguí LED's de color rojo, amarillo, azul, verde y blanco. Cada uno posee una hoja de datos en la cual podemos cuales son las condiciones para que cada uno de ellos funcione, en el caso de los LED's rojos, la hoja de datos dice que se le debe de aplicar un voltaje 2.1 v y una corriente de 0.02 A (20 mili Amperes), al conectarlo a una fuente con esas características, el diodo enciende.
La corriente esta limitada a 20mA

Pero si vemos bien en la imagen, si limitamos la corriente a 20 mA, el voltaje no es el que viene descrito en la hoja de datos, hay una diferencia de 0.1 V.

Para trabajar con diodos LED, lo primero que debemos de tomar en cuenta, es que no todos los diodos son iguales, la hoja de datos presentará datos nominales, pero en si cada uno es diferente. Al revisar 10 LED's rojos, si la corriente se mantiene constante, el voltaje varia desde los 1.9 V hasta los 2.2 V. Si a todos estos LED's se les alimenta con los 2.1V que dice la hoja de datos, los que funcionaron a los 1.9 V, se terminarán "acabando" mas rápido, debido que a mayor voltaje (del requerido), mayor corriente va a circular, generado calor que es uno de los enemigos de los LED, ya que a mayor temperatura, mayor corriente circula por ellos.

Si no se dispone de una fuente con control de corriente o cómo en mi caso, no es facil agregar un control de corriente (porque soy flojo), podemos simplemente agregar una resistencia que sirva para limitar la corriente.

En algunos de los post pasados hemos usado LED's y algunos de los visitantes del blog me han preguntado si podía hacer una calculadora que sirva para calcular la resistencia para llevarla en el teléfono y eso es lo que haremos, pero no en este post; al igual que en ocasiones anteriores, primero veremos como hacer los cálculos "a mano".

Aguantando con resistencia.

Para empezar, lo primero que debemos de tomar en cuenta es la ley del Ohm.

  • Donde R es la resistencia que se mide en Ohm y su símbolo es "Ω".
  • V es el voltaje que se mide en volt y su símbolo es "V".
  • I es la corriente que se mide en Ampere y su símbolo es "A".
Para conectar, la resistencia, simplemente debemos de ponerla en serie con el diodo.
De esta forma la resistencia "disipara" el voltaje excedente, es decir si vemos la imagen anterior, tendremos que la resistencia deberá de hacer algo con los 5V de entrada menos los 3.1V del diodo, es decir 5 V - 3.1 V  = 1.9 V y aquí es donde entra la ley del Ohm, el revisar la formula, vemos que necesitamos tres componentes: la resistencia, el voltaje y la corriente, pero de estos solo conocemos dos que son: el voltaje y la corriente por lo tanto si sustituimos los valores en la ecuación, tendremos:
Si tenemos un diodo 20 mA a 3.1 V y lo alimentamos con 5 V, necesitamos una resistencia de 95 Ω para que el diodo no se queme.

Ahora supongamos que conectamos diez diodos de las mismas características en paralelo, es posible poner una sola resistencia, pero debemos de tener algunas cosas en consideración, pero primero los cálculos.

Tenemos una corriente de 20 mA * 10 = 200 mA (hay que recordar que en este caso, en paralelo la corriente aumenta pero no el voltaje. Cosa contraria a cuando se hacen las conexiones en serie), el voltaje que "caerá" en la resistencia es el mismo, ya que usamos los mismos 5V para alimentar el circuito.

Al momento de elegir el tipo de resistencia, debemos de tener en cuenta cuanta potencia es capaz de disipar, en esto casos, la resistencia más común de 0.250W por lo que si excedemos esa potencia, esta se destruirá.

Para calcular cual es la potencia que una resistencia debe de soportar, debemos de recurrir a la ley del Watt que la siguiente:
Donde:
  • P  es la potencia que se mide en Watts y su símbolo es "W".
  • V es el voltaje que se mide en Volts y su símbolo es "V".
  • I es la corriente que se mide en Ampere y su símbolo es "A".
Tomado el ultimo ejemplo tenemos:
Por lo quedemos de usar una resistencia de 9.5Ω a medio Watt (que es lo mas común).

Dado que toda la energía no usada por el LED es disipada en calor por la resistencia, esta es una forma no muy conveniente de regularlo, pero para pocos LED's sirve.

Y bien, por ahora es todo, en el siguiente post haremos una calculadora para android que nos ayude a calcular la resistencia y la potencia de esta para poder usarlas, además veremos otras posibles soluciones.

Los leo luego.

Inútil apps #4 -Visualizador de sonido.

Desde que era pequeño, siempre tuve fascinación por las luces audioritmicas, recuerdo que mi papá tenía un Boom-Box (a grabadora) que tenia un visualizdaor de 10 niveles (un LED por nivel). El efecto que lograba era bastante llamativo y tal mosco a la luz, no podía evitar ser atraído por esta.


El día de hoy vamos a hacer un visualizador de sonido. usando uno de los integrados más comunes: el LM3915.

Para empezar revisemos el siguiente esquema:

El circuito integrado LM3915 se encarga de medir niveles de voltaje y es capaz de manejar 10 LED's.
Antes de continuar revisemos para que sirve cada una de las entradas del integrado

  1. Pin 1 - Salida de LED.
  2. Pin 2 - Tierra.
  3. Pin 3 - VCC (3 ~ 35V).
  4. Pin 4 - Divisor bajo
  5. Pin 5 - Input
  6. Pin 6 - Divisor alto.
  7. Pin 7 - Referencia de salida.
  8. Pin 8 - Ajuste de referencia.
  9. Pin 9 - Selector de modo.
  10. Pin 10 ~ Pin 18 - Salida de LED's
Para poder hacer el proyecto entonces necesitaremos los siguientes componentes:

  • U1 - Circuito integrado LM3915 (14/16).
  • D1 - Diodo 1N5819
  • R1 - Resistencia 680 Ohms
  • R2 - Resistencia 150 Ohms
  • R3 - Resistencia 10 KiloOhms
  • C1 - Capacitor electrolitico 10 micro Faradios.
  • LED1 ~ 10. Diodo LED.
Para empezar, el circuito integrado LM3915 tiene la capacidad de entregar de desde 2 mA hasta 30 mA, para poder ajustar la corriente que va a circular en cada salida, debemos de tomar en cuenta la siguiente formula:

  • 12.5/R1
En nuestro caso tenemos que la resistencia R1 tiene un valor de 680 Ohms por lo que sustituyendo tenemos:

  • 12.5/680 = 18.3 mA
Con 18.3mA tenemos la cantidad suficiente de corriente para manejar casi cualquier LED. Al establecer la corriente, no nos tendremos que preocupar por poner resistencias entre los LED's y VCC puesto que el integrado se encargara de administrar: pero hay que resaltar que si solo se va a hacer uso de un solo LED a cada salida, es recomendable bajar el voltaje al cual trabajaremos, si no lo hacemos, todo el voltaje sera disipado por el integrado y la vida útil de este se reducirá.
Si se quiere hacer uso de 12V podemos usar segementos de LED como los siguientes:


Este tipo de módulos son muy comunes, al hacer la medición cada segmento consume 20mA, para poder calcular la resistencia adecuada podemos re-acomodar la formula de tal forma que si queremos saber que resistencia debemos usar tendremos algo cómo lo que sigue:

  • 12.5/I (donde I es la corriente).
Y sustituyendo tenemos:

  • 12.5/0.02 =  625 Ohms
Ahora imaginemos que queremos usar 25 mA, solo bastará que se sustituya el nuevo valor de la corriente:

  • 12.5/0.025 = 500 Ohms.
Si se requiere una mayor corriente para manejar corrientes de mas de 30 mA, se deberá de usar algún transistor, si se le exige más corriente al integrado, este simplemente se quemará.

Para la entrada de señal, el circuito esta diseñado para ser conectado a la salida de un amplificador con niveles de 0V a 9V, para poder variar la sensibilidad, debemos de cambiar la corriente que circula por el pin8. Por ahora solo dejare esta versión, pero si necesitas saber cual es el valor de las resistencias para los voltaje, puedes leer la hoja de datos del integrado.

Para poder controlar cómo se va a mostrar los niveles, disponemos de dos modos:

  1. Modo Barra.
  2. Modo Punto.
El modo barra consiste en que todos los niveles se encenderán si hay uno superior activo, supongamos que tenemos el LED 8 encendido, entonces los LED's del 1 al 8 estarán encendidos, aunque parezca un poco obvio, es importante mencionarlo para contrastarlo con el modo punto; en el modo punto solo el LED 8 debe de estar encendido, solo este lo estará, es decir ninguno que no sea el del nivel actual estará encendido. Si se usa el modo punto, debemos de usar una resistencia de 1 a 10KOhms entre el PIN 1 y su respectivo LED, si no se pone, cuando el nivel sea diferente al del LED 1, este presentará un ligero resplandor.

El modulo rojo debería de estar totalmente apagado, pero sin la resistencia no lo hacer (aunque pienso que quueda bien)


Y bien, por ahora es todo, en el siguiente post, veremos cómo armar el circuito y trataremos de hacer un empaque para que se vea un poco mejor.

Los leo luego.

Vamos a programar #43 - Actualizando clock view.

Hola de nuevo a todos, el día de hoy vamos a ver una actualizacion del código de clock view.
Cómo recordarás, hace un buen rato dije que iba a actualizar el código, pero por varias razones lo pospuse, hasta que finalmente casí lo olvide. No se le hicieron muchos cambios, solo optimizaron algunas partes y se saco un poco más de provecho a las partes que ya se usaban y se agregaron unas cuantas más. Sí previamente ya habías hecho el proyecto, solo bastará con cargar el código al arduino, de cualquier forma, el código estará disponible para su descarga.

El código.

El código actualizado del Clock View es el siguiente:
//Clockview 2.0
#include <DS1302.h>
#include "LedControl.h"
#include <SD.h>
/*
	Para la conexión del modulo SD se siguen los siguientes:
	** MOSI - pin 11
	** MISO - pin 12
	** CLK - pin 13
	** CS - pin 10 - Este es el que se puede cambiar
*/
//Pin SD
int CS_PIN = 10;
//Constantes para los pines usados en la matriz
const int MaxDIn = 9;
const int MaxCS = 8;
const int MaxCLK = 7;
int MaxNDevices = 3;
bool IsConnected = false;
//Constantes para los pines usados en el reloj
const int kCePin = 6;  // RST
const int kIoPin = 5;  // Dat
const int kSclkPin = 4;  // Serial Clock
//Inicializacion de la matriz
//DIN,CLK,CS
LedControl lc = LedControl(MaxDIn, MaxCLK, MaxCS, MaxNDevices);
//Inicializacion del reloj
DS1302 rtc(kCePin, kIoPin, kSclkPin);
//Algunas variables
File Archivo;
char Texto[24];
int MatrixB = 10;
bool H24 = true;
bool HalfSecond = true;
bool IsScreenEnable = true;
bool ShowSeconds = true;
bool SDCardReady = false;
bool EditMode = false;
bool ShowDate = false;
bool Demo = false;
//Matriz con los "Numeros"
const unsigned char Numbers[] = {
	B11111110, B10000010, B11111110, //0
	B10000100, B11111110, B10000000, //1
	B11110010, B10010010, B10011110, //2
	B10000010, B10010010, B11111110, //3
	B00011110, B00010000, B11111110, //4
	B10011110, B10010010, B11110010, //5
	B11111110, B10010010, B11110010, //6
	B00000010, B00000010, B11111110, //7
	B11111110, B10010010, B11111110, //8
	B00011110, B00010010, B11111110, //9
	B11111110, B00010010, B11111110, //A - 10
	B11111110, B00011100, B11111110, //M - 11
	B11111110, B00010010, B00011110, //P - 12
	B11111110, B00010000, B11111110, //H - 13
	B11111110 ,B00110010, B11011110, //R - 14
};
//Definimos simbolos
const unsigned char Symbols[] = {
	B01000100, B00101000, B00010000, B11111110, B01010100, B00101000, //BT 0
	B00111100, B01000110, B01011010, B01001010, B01001010, B00111100, //Clock Adjust 1
	B11010110, B10111010, B01000100, B01000100, B10111010, B11010110//Brightness 2
};
//Imprimir simbolos
void PrintSymbol(byte Index,byte SymDevice){
	for (int Y = 1; Y < 7; Y++){
		lc.setRow(SymDevice, Y, Symbols[Index * 5 + Y - 1]);
	}
}
//Funcion para escribir los numero en la matriz.
void PrintNumber(byte NumberOne, byte NumberTwo, byte Device){
	for (int X = 1; X < 8; X++){
		if (X < 4){
			lc.setRow(Device, X, Numbers[NumberOne * 3 + X - 1]);
		}
		if (X == 4){
			lc.setRow(Device, 4, 0);
		}
		if (X > 4){
			lc.setRow(Device, X, Numbers[NumberTwo * 3 + X - 5]);
		}
	}
}
void printDate(){
	Time t = rtc.time();
	const String day = dayAsString(t.day);
	char buf[50];
	snprintf(buf, sizeof(buf), "%s %04d-%02d-%02d %02d:%02d:%02d",
	day.c_str(), t.yr, t.mon, t.date, t.hr, t.min, t.sec);
	int ShortYear = t.yr % 100;
	PrintNumber(t.date / 10, t.date % 10, 0);
	PrintNumber(t.mon / 10, t.mon % 10, 1);
	PrintNumber(ShortYear / 10, ShortYear % 10, 2);
}
//Imprimir el tiempo en las matrices y en el monitor serie.
void printTime(){
	Time t = rtc.time();
	const String day = dayAsString(t.day);
	char buf[50];
	snprintf(buf, sizeof(buf), "%s %04d-%02d-%02d %02d:%02d:%02d",
		day.c_str(), t.yr, t.mon, t.date, t.hr, t.min, t.sec);
	PrintNumber(AdjustTime(t.hr, H24) / 10,AdjustTime(t.hr, H24) % 10, 0);
	PrintNumber(t.min / 10, t.min % 10, 1);
	if (ShowSeconds){
		PrintNumber(t.sec / 10, t.sec % 10, 2);	
	}else{
		if(H24)
			PrintNumber(13, 14, 2);
		if(!H24 && t.hr < 13)
			PrintNumber(10, 11, 2);
		if(!H24 && t.hr > 12)
			PrintNumber(12, 11, 2);
	}
	//PrintSymbol(0, 2);
	if (IsScreenEnable == true)
	{
		if (HalfSecond == true){
			digitalWrite(3, HIGH);
			HalfSecond = false;
		}else{
			digitalWrite(3, LOW);
			HalfSecond = true;
		}
	}
	Serial.println(buf);
}
//Demo directo del ejemplo de la libreria
void ScreenDemo(){
	int devices=lc.getDeviceCount();
	for(int row=0;row<8;row++) {
		for(int col=0;col<8;col++) {
			for(int address=0;address<devices;address++) {
				int DemoButton = analogRead(A5);
				if(DemoButton < 200){
					Demo = false;
					break;
				}
				delay(40);
				lc.setLed(address,row,col,true);
				delay(40);
				lc.setLed(address,row,col,false);
			}
		}
	}
}
//Ajustar la hora
int AdjustTime(int Hour, bool In24Hformat){
	if(In24Hformat == true){
		return Hour;
	}
	if(In24Hformat == false && Hour > 12){
		Hour = Hour - 12;
		return Hour;
	}else{
		return Hour;
	}
}
//Guardar los ajustes
void SaveSettings(){
	Archivo = SD.open("Settings.clv", O_WRITE | O_CREAT);
	char SaveBuf[8];
	snprintf(SaveBuf, sizeof(SaveBuf), "%s%02d",">SETB", MatrixB);
	Serial.println(SaveBuf);
	if (Archivo){
		Archivo.seek(0);
		Archivo.println(SaveBuf);
		if(H24)
			Archivo.println(">SETF");
		else
			Archivo.println("XSETF");
		if (ShowSeconds)
			Archivo.println(">DISS");
		else
			Archivo.println("XDISS");
			Archivo.flush();
			Archivo.close();
		Serial.println("Guardado");
	} else {
		Serial.println("error writing test.txt");
	}
}
//Enviar un resumen de las configuraciones actuales
void SendResume(){
	
}
//Cargar los ajustes
void LoadSettings(){
	Archivo = SD.open("Settings.clv", FILE_READ);
	int B = 0;
	byte CurRead;
	char SettBuf[22];
	if (Archivo) {
		while (Archivo.available() > 0){
			CurRead = Archivo.read();
			if	(CurRead != 10 && CurRead != 13){
				SettBuf[B] = CurRead;
				B++;
				Serial.print(B);
			}else{
				CheckPetition(SettBuf, false);
				Serial.print(B);
				B = 0;
				for (int BF = 0; BF < 22; BF++)
					SettBuf[BF]=0;
			}
		}
		Archivo.close();
	}else{
		Serial.println("error opening file");
	}	
}
//Comprobar si hay algun comando
void CheckPetition(char DATA[], bool Save){
	int i = 0;
	int j = 0;
	String Texto(DATA);
	//>SETH2016122119001004
	if (Texto.startsWith(">DISS")){
		ShowSeconds = !ShowSeconds;
		if (Save)
			SaveSettings();
		Serial.print("No/Se muestran los segundos");
		for (int CurrentDevice = 0; CurrentDevice < MaxNDevices; CurrentDevice++){
			lc.shutdown(CurrentDevice, !IsScreenEnable);
		}
		for (j = 0; j < 11; j++) {
			DATA[j] = 0;
		}
		i = 0;
	}
	if (Texto.startsWith(">SCRA")){
		IsScreenEnable = !IsScreenEnable;
		Serial.print("Las matrices se apagaron/encendieron");
		for (int CurrentDevice = 0; CurrentDevice < MaxNDevices; CurrentDevice++){
			lc.shutdown(CurrentDevice, !IsScreenEnable);
		}
		for (j = 0; j < 11; j++) {
			DATA[j] = 0;
		}
		i = 0;
	}	
	if (Texto.startsWith(">RESET")){
		SD.remove("Settings.clv");
		for (int CurrentDevice = 0; CurrentDevice < MaxNDevices; CurrentDevice++){
			lc.shutdown(CurrentDevice, !IsScreenEnable);
		}
		for (j = 0; j < 11; j++) {
			DATA[j] = 0;
		}
		i = 0;
	}	
	if (Texto.startsWith(">SETF")){
		H24 = !H24;
		if (Save)
			SaveSettings();
		Serial.print("EL reloj cambio de formato 12H-24H");
		for (j = 0; j < 11; j++) {
			DATA[j] = 0;
		}
		i = 0;
	}
	if (Texto.startsWith(">SETH")){
		AdjustTime(Texto.substring(9, 5).toInt(),Texto.substring(11,9).toInt(),Texto.substring(13, 11).toInt(),
		Texto.substring(15, 13).toInt(), Texto.substring(17, 15).toInt(), Texto.substring(19, 17).toInt(),
		Texto.substring(21, 19).toInt());
		for (j = 0; j < 11; j++) {
			DATA[j] = 0;
		}
		i = 0;
	}
	if (Texto.startsWith(">SETB")){
		MatrixB = Texto.substring(5).toInt();
		if (Save)
			SaveSettings();
		Serial.println("El brillo se cambio");
		for (int CurrentDevice = 0; CurrentDevice < MaxNDevices; CurrentDevice++){
			lc.setIntensity(CurrentDevice, MatrixB);
		}
		for (j = 0; j < 11; j++) {
			DATA[j] = 0;
		}
		i = 0;
	}
	else {
		for (j = 0; j < 11; j++) {
			DATA[j] = 0;
		}
		i = 0;
	}
}
//Convertir los dias
String dayAsString(const Time::Day day){
	switch (day){
		case Time::kSunday: return "DOM";
		case Time::kMonday: return "LUN";
		case Time::kTuesday: return "MAR";
		case Time::kWednesday: return "MIE";
		case Time::kThursday: return "JUE";
		case Time::kFriday: return "VIE";
		case Time::kSaturday: return "SAB";
	}
	return "(unknown day)";
}
//Ajustar la hora
void AdjustTime(int Year,int Month, int Day, int Hour, int Minute, int Second, int DayOfWeek){
	Time::Day CurrentDay;
	switch (DayOfWeek){
		case 1:
			CurrentDay = Time::kSunday;
			break;
		case 2:
			CurrentDay = Time::kMonday;
			break;
		case 3:
			CurrentDay = Time::kTuesday;
			break;
		case 4:
			CurrentDay = Time::kWednesday;
			break;
		case 5:
			CurrentDay = Time::kThursday;
			break;
		case 6:
			CurrentDay = Time::kFriday;
			break;
		case 7:
			CurrentDay = Time::kSaturday;
			break;
	}
	//Esta parte se usa para actualizar la hora.
	rtc.writeProtect(false);
	rtc.halt(false);
	Time t(Year, Month, Day, Hour, Minute, Second, CurrentDay);
	rtc.time(t);	
}
//Inicializar la tarjeta SD para usarla
void InitializeSD(){
	pinMode(CS_PIN, OUTPUT);
	if (SD.begin()){
		SDCardReady = true;
		Serial.println("La tarjeta SD esta lista");
	}else{
		SDCardReady = false;
		Serial.println("La tarjeta SD no esta lista");
		return;
	}
}
//Setup
void setup(){
	Serial.begin(9600);
	for (int CurrentDevice = 0; CurrentDevice < MaxNDevices; CurrentDevice++){
		lc.shutdown(CurrentDevice, false);
		lc.setIntensity(CurrentDevice, MatrixB);
		lc.clearDisplay(CurrentDevice);
	}
	InitializeSD();
	pinMode(A2, INPUT_PULLUP);
	pinMode(A3, INPUT_PULLUP);
	pinMode(A4, INPUT_PULLUP);
	pinMode(A5, INPUT_PULLUP);
	pinMode(3, OUTPUT);
	if(SDCardReady){
		LoadSettings();
	}else{
		Serial.println("La tarjeta no está lista");
	}
}
//Loop
void loop(){
	int SetEditButton = analogRead(A2);
	int ShowDateButton = analogRead(A3);
	int TurnOffMatrixButton = analogRead(A4);
	int DemoButton = analogRead(A5);
	
	while (Demo == true){
		ScreenDemo();
	}
	if(DemoButton < 200){
		Demo = !Demo;
	}
	Serial.println(SetEditButton);	
	if(SetEditButton < 200){
		EditMode = !EditMode;
	}
	if(ShowDateButton < 200){
		ShowDate = true;
	}
	if(TurnOffMatrixButton < 200){
		IsScreenEnable = !IsScreenEnable;
		for (int CurrentDevice = 0; CurrentDevice < MaxNDevices; CurrentDevice++){
			lc.shutdown(CurrentDevice, IsScreenEnable);
		}
	}	
	if(ShowDate){
		printDate();
		delay(3000);
		ShowDate = false;
	}
	if(EditMode){
		int PotB = analogRead(A0);
		// print out the value you read:
		int MatrixB = map(PotB, 0, 1000, 1, 15);
		char SaveBuf[8];
		snprintf(SaveBuf, sizeof(SaveBuf), "%s%02d",">SETB", MatrixB);
		CheckPetition(SaveBuf, false);
		PrintNumber(MatrixB / 10,MatrixB % 10, 2);
		PrintSymbol(2,1);
		delay(100);
	}else{
		int i = 0;
		printTime();
		delay(100);
		if (Serial.available()) {
			while (Serial.available() > 0) {
				Texto[i] = Serial.read();
				i++;
			}
			Texto[i] = '\0';
		}
		CheckPetition(Texto, true);	
	}
}



El código es funcional, pero demostrativo. Uno de los cambios más notorios que se puede observar, es que los número son más grandes.
Los números eran de 3x5 LEDs, en su lugar, ahora son de 7x3
Además se hace uso de pulsadores para que tambien sea manipulable, en este caso, el código hace uso de 4, pero tal vez en un futuro, se usen solo 3, he visto muchos relojes que solo hacen el uso de ese número.
El código se actualizará nuevamente, pero por ahora lo público así para que te sientas libre de probar con tus propios ajustes. Si no dispones de pulsadores, no te preocupes, aun es totalmente utilizable solo por medio de bluetooth. El código anterior lo puedes descargar de la seccion de descargas y si quieres hacer uso de este, basta con copiarlo; todas las conexiones vienen en el código.
Por ahora es todo, los leo luego.

Vamos a programar #32 - Clock view en Windows.

Hola de nuevo a todos, el día de hoy vamos a continuar con un poco más de clock view.
En los post anteriores, vimos cómo controlarlo desde una aplicación para android, pero mucha gente me pregunto si era posible hacer algo similar pero desde una computadora con Windows.
La respuesta: Clock View para Windows.
Para llevar a cabo la conexión, primeramente debemos emparejar el bluetooth de Clock view con el de la computadora que vayamos a usar.

En mi caso es "Siqueiros printer" (ignora el nombre es un arduino)

Cuando ya estén emparejados, hay que revisar cual es el puerto que se asigno al bluetooth. Para eso, hay que ir a: Panel de control > Dispositivos e impresoras > "Nombre del Arduino", luego hay que hacer clic secundario y después propiedades.En la ficha "Servicios", nos mostrará cual es el puerto que se usará.

Una vez que sabemos esa información, pasaremos al código de C# que es el siguiente:

using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO.Ports;
using System.Windows.Forms;
using System.Configuration;

namespace ClockView
{
	public partial class FrmMain : Form
	{
		private SerialPort Port = new SerialPort();

		private void ArduinoMessage(string Message)
		{
			try
			{
				Port.Write(Message);
			}
			catch (Exception e)
			{
				MessageBox.Show(e.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
			}

		}

		public FrmMain()
		{
			InitializeComponent();
		}

		private void Form1_Load(object sender, EventArgs e)
		{
			string[] Ports = SerialPort.GetPortNames();
			CboPorts.Items.AddRange(Ports);
			Port.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
		}

		private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
		{
			SerialPort sp = (SerialPort)sender;
			string indata = sp.ReadExisting();
			if (indata == "Done")
			{

			}
		}
		private void BtnConnect_Click(object sender, EventArgs e)
		{
			try
			{
				if (Port.IsOpen == false)
				{
					Port.BaudRate = int.Parse(TxtSpeed.Text);
					Port.PortName = CboPorts.Text;
					Port.Parity = Parity.None;
					Port.StopBits = StopBits.One;
					Port.Parity = Parity.Even;
					Port.DataBits = 8;
					Port.Open();

				}				
			} catch (Exception ex) {
				MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
			}
		}

		private void BtnDisconnect_Click(object sender, EventArgs e)
		{
			if (Port.IsOpen == true)
			{
				Port.Close();
			}
		}

		private void Btn1224_Click(object sender, EventArgs e)
		{
			ArduinoMessage(">SETF");
		}

		private void BtnShowSeconds_Click(object sender, EventArgs e)
		{
			ArduinoMessage(">DISS");
		}

		private void BtnLights_Click(object sender, EventArgs e)
		{
			ArduinoMessage(">SCRA");
		}

		private void trkbarBrillo_MouseUp(object sender, MouseEventArgs e)
		{
			ArduinoMessage(">SETB" + trkbarBrillo.Value.ToString());
		}

		private void BtnSync_Click(object sender, EventArgs e)
		{
			//>SETH2016122119001004
			string HourData = string.Concat(">SETH", DateTime.Now.Year, DateTime.Now.Month.ToString("D2"), DateTime.Now.Day.ToString("D2"),
				DateTime.Now.Hour.ToString("D2"), DateTime.Now.Minute.ToString("D2"), DateTime.Now.Second.ToString("D2"),
				(((int)DateTime.Now.DayOfWeek)+1).ToString("D2"));
			ArduinoMessage(HourData);

		}
	}
}

Para hacer uso del puerto serial, debemos de crear un objeto SerialPort que se incluye en el espacio de nombres System.IO.Ports.
Cuando el formulario se carga, lo primero que hará es buscar todos los puertos disponibles, pero eso no quiere decir que este conectado o en uso el periférico. Si cuando inicias el programa no puedes ver el puerto al que está conectado tu arduino, basta con que escribas el nombre en la lista. Despues solo hay que hacer clic en conectar y si todo está en orden, se podrá controlar ClockView desde la computadora con BlueTooth.
Al igual que la aplicación para android, en está aplicación se incluyen los controles que cambian las configuraciones de ClockView. Además está aplicación sirve con un cable, si conectas Clock View con un cable USB, también podrás cambiar los ajustes, pero esa no es la idea; aun si prefieres hacer uso del cable, es recomendable que desconectes el módulo HC-05/06 del arduino para que no haya ningún tipo de problemas.
Al igual que todos los otros programas, dejo el código fuente para que los descargues y lo pruebes. El Código fuente de la aplicacion para android, aun lo voy a mejorar un poco y el software para arduino también.
Por ahora es todo. Los leo luego.

Vamos a programar #30 - El código de Clock View (Android)

Hola de nuevo a todos, el día de hoy vamos a explicar el código que hace funcionar la aplicación de android Clock View.


La interfaz.

Antes que nada vamos a empezar ´por la interfaz, para el caso de Clock View esta compuesta de 2 partes. La primera son todos los botones de "acción" y parte principal de la aplicacion; la segunda solo es la lista que se encarga de mostrar todos los dispositivos que estén emparejados al dispositivo.

Para mostrar la interfaz principal, en el Layout principal, debemos de agregar el siguiente código.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:tools="http://schemas.android.com/tools"
 android:id="@+id/activity_main"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:paddingBottom="@dimen/activity_vertical_margin"
 android:paddingLeft="@dimen/activity_horizontal_margin"
 android:paddingRight="@dimen/activity_horizontal_margin"
 android:paddingTop="@dimen/activity_vertical_margin"
 tools:context="com.mdev.clockview.MainActivity">

 <ScrollView
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:layout_alignParentTop="true"
  android:layout_alignParentLeft="true"
  android:layout_alignParentStart="true">

  <LinearLayout
   android:layout_width="match_parent"
   android:layout_height="wrap_content"
   android:orientation="vertical">

   <TextView
    android:text="La hora actual es:"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/TXTView"
    tools:ignore="HardcodedText" />

   <TextClock
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginTop="14dp"
    android:id="@+id/TXTClock"
    android:typeface="sans"
    android:textAlignment="center"
    android:textSize="30sp"
    android:fontFamily="monospace"/>

   <Button
    android:text="Conectar con arduino."
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/BtnConnect"
    android:textAlignment="center"
    android:textAllCaps="false" />

   <Button
    android:text="Cambiar 12/24 Horas."
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/BtnFormat" />

   <Button
    android:text="No/Mostrar segundos."
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/BtnShowS"/>

   <Button
    android:text="Apagar/Encender matrices"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/BtnOn"/>

   <Button
    android:text="Sincronizar hora."
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/BtnSync"/>

   <TextView
    android:text="Nivel de brillo:"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginLeft="11dp"
    android:layout_marginStart="11dp"
    android:layout_marginTop="10dp"
    android:id="@+id/textView2" />

   <SeekBar
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginTop="12dp"
    android:id="@+id/SKBrillo"
    android:max="15"
    android:progress="5" />

   <TextView
    android:text="Brillo: 15"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/txtSeekValue"/>

   <TextView
    android:text="Esperando a ClockView."
    android:layout_width="match_parent"
    android:id="@+id/TxtArduinoReturn"
    android:layout_height="wrap_content" />

   <Button
    android:text="Desconectar"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/BtnDisconnect" />
  </LinearLayout>
 </ScrollView>
</RelativeLayout>

Tras implementar el código, la aplicacion lucira algo similar a la siguiente imagen:



Cómo verás, solo consta de 6 botones, una barra de seek y las etiquetas para mostrar texto.
La funcion de cada uno, la veremos en el código Java, pero antes, vamos a terminar con la interfaz. La lista que contiene los dispositivos emparejados, es un layout que solo contiene un list view y su código es el siguiente;

<LinearLayout
 xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:tools="http://schemas.android.com/tools"
 android:id="@+id/bt_list"
 android:orientation="vertical"
 android:layout_width="match_parent"
 android:layout_height="match_parent">

 <ListView
  android:id="@+id/BTList"
  android:layout_width="match_parent"
  android:layout_height="200dp"
  android:headerDividersEnabled="true"
  android:footerDividersEnabled="false">
 </ListView>

</LinearLayout>

Con esto completamos la parte de la interfaz, además en el código completo he agregado el diseño para cuando la orientacion del dispositivo es vertical y para cuando es horizontal, en lo personal preferí forzar a que la aplicacion siempre este en horizontal, pero eres libre de cambiarla a tu gusto.

El código en java.

El código en Java, lo he modificado un poco desde la última vez, corregi algunos errores, uno de ellos era: cuando se intentaba hacer la conexion y esta fallaba, al hacer click en cualquier botón, este intentaba mandar algo a traves del socket que supestemente debio de haber sido creado, al no estar disponible, la aplicion "crasheaba" y salia; el error se debia que a pesar de no haber conexion, la condicion que se debia de comprobar era verdadera debido a que se verificaba si el bluetooth estaba activado; la condicion se podia cumplir, pero eso significaria necesariamente que el socket ya se hubiera creado. Para solucionarlo, simplemente use un flag boleano que solo se cambiaba cuando se abria o cerraba la conexion, ahora si no hay conexion, simplemente no se intenta enviar nada.

Ademas coerregi algunos detalles y bugs minimos. El código actualizado es el siguiente:

package com.mdev.clockview;

import android.app.Activity;
import android.app.AlertDialog;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.os.Build;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;
import android.app.ProgressDialog;
import android.os.AsyncTask;
import android.os.Handler;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.UUID;
import java.lang.reflect.Method;
import java.util.Set;
import java.util.Calendar;

import static com.mdev.clockview.R.layout.paired_devices_list;

public class MainActivity extends Activity {

 BluetoothAdapter myBluetoothAdapter = null;
 Button BtnConnect, BtnOnOff, BtnSecondsShow, BtnSyncHour, BtnChangeFormat,BtnDisconnect;
 SeekBar SkBright;
 TextView TxtArduinoRec, TxtBrigthValue;

 String address = null;
 private ProgressDialog progress;
 BluetoothSocket btSocket = null;
 private boolean isBtConnected = false;
 private static final UUID myUUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
 final int RECEIVE_MESSAGE = 1;
 private StringBuilder sb = new StringBuilder();
 private ConnectedThread mConnectedThread;
 Handler h;

 private Set<BluetoothDevice> pairedDevices;
 ListView myListView;
 ArrayAdapter BTArrayAdapter;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  //setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

  setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
  BtnConnect = (Button)findViewById(R.id.BtnConnect);
  myListView = (ListView)findViewById(R.id.BTList);
  TxtArduinoRec = (TextView)findViewById(R.id.TxtArduinoReturn);
  BtnOnOff = (Button)findViewById(R.id.BtnOn);
  BtnSecondsShow = (Button)findViewById(R.id.BtnShowS);
  BtnSyncHour = (Button)findViewById(R.id.BtnSync);
  BtnChangeFormat = (Button)findViewById(R.id.BtnFormat);
  BtnDisconnect = (Button)findViewById(R.id.BtnDisconnect);
  SkBright = (SeekBar)findViewById(R.id.SKBrillo);
  TxtBrigthValue = (TextView)findViewById(R.id.txtSeekValue);

  myBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

  if (myBluetoothAdapter == null) {
   msg("El bluetooth no es soportado por este dispositivo");
  }
  else {
   msg("Esperando la conexion");
  }
  SkBright.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener(){

   @Override
   public void onProgressChanged(SeekBar seekBar, int progress,
            boolean fromUser) {
    TxtBrigthValue.setText("Brillo: " + String.valueOf(progress));
    if (isBtConnected)
    {
     String result = String.format(">SETB%1$02d", progress);
     mConnectedThread.write(result);
    }
   }

   @Override
   public void onStartTrackingTouch(SeekBar seekBar) {
   }

   @Override
   public void onStopTrackingTouch(SeekBar seekBar) {

   }
  });
  BtnConnect.setOnClickListener(new View.OnClickListener() {
   @Override
   public void onClick(View view) {
    if (!myBluetoothAdapter.isEnabled()) {
     Intent turnOnIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
     startActivityForResult(turnOnIntent, 1);
    }else{
     showBTDialog();
    }
   }
  });
  BtnOnOff.setOnClickListener(new View.OnClickListener()
  {
   @Override
   public void onClick(View view){
    if (isBtConnected)
    {
     mConnectedThread.write(">SCRA");
    }
   }
  });

  BtnSecondsShow.setOnClickListener(new View.OnClickListener()
  {
   @Override
   public void onClick(View view){
    if (isBtConnected)
    {
     mConnectedThread.write(">DISS");
    }
   }
  });

  BtnSyncHour.setOnClickListener(new View.OnClickListener()
  {
   @Override
   public void onClick(View view){
    if (isBtConnected)
    {
     mConnectedThread.write(BuildHour(true));
    }
   }
  });

  BtnChangeFormat.setOnClickListener(new View.OnClickListener()
  {
   @Override
   public void onClick(View view){
    if (isBtConnected)
    {
     mConnectedThread.write(">SETF");
    }
   }
  });
  BtnDisconnect.setOnClickListener(new View.OnClickListener()
  {
   @Override
   public void onClick(View view){
    if (isBtConnected)
    {
     Disconnect();
    }
   }
  });
  //encargado de procesar los mensajes.
  h = new Handler() {
   public void handleMessage(android.os.Message msg) {
    switch (msg.what)
    {
     case RECEIVE_MESSAGE:
      byte[] readBuf = (byte[]) msg.obj;
      String strIncom = new String(readBuf, 0, msg.arg1);
      sb.append(strIncom);
      int endOfLineIndex = sb.indexOf("\r\n");
      if (endOfLineIndex > 0)
      {
       String sbprint = sb.substring(0, endOfLineIndex);
       sb.delete(0, sb.length());
       TxtArduinoRec.setText("Data from Arduino: " + sbprint);
      }
     break;
    }
   };
  };

 }
 private void msg(String s)
 {
  Toast.makeText(getApplicationContext(),s,Toast.LENGTH_LONG).show();
 }
 private String BuildHour(boolean ForArduino){
  //>SETH2016122119001004
  //>SETHAAAAMMDDHHMMSSWW
  Calendar c = Calendar.getInstance();
  int DiaSemana = c.get(Calendar.DAY_OF_WEEK);
  int Anio = c.get(Calendar.YEAR);
  int Mes = c.get(Calendar.MONTH);
  int Dia = c.get(Calendar.DAY_OF_MONTH);
  int Horas = c.get(Calendar.HOUR_OF_DAY);
  int Minutos = c.get(Calendar.MINUTE);
  int Segundos = c.get(Calendar.SECOND);
  String Fecha = null;
  if (ForArduino == true){
   Fecha = String.format(">SETH%1$04d%2$02d%3$02d%4$02d%5$02d%6$02d%7$02d",
     Anio, Mes + 1, Dia, Horas, Minutos,Segundos, DiaSema);
   msg(Fecha);
  }else {
   Fecha = String.format("%1$04d/%2$02d/%3$02d - %4$02d:%5$02d:%6$02d",
     Anio, Mes + 1, Dia, Horas, Minutos,Segundos);
  }
  return Fecha;
 }

 private void Disconnect()
 {
  if (btSocket!=null)
  {
   try
   {
    btSocket.close();
    isBtConnected = false;
   }
   catch (IOException e)
   { msg("Error");}
  }
 }

 private AdapterView.OnItemClickListener myListClickListener = new AdapterView.OnItemClickListener()
 {
  public void onItemClick (AdapterView<?> av, View v, int arg2, long arg3) {
   if (myBluetoothAdapter.isEnabled()) {
    String info = ((TextView) v).getText().toString();
    address = info.substring(info.length() - 17);
    msg(info);

   } else {
    msg("El Bluetooth debe de estar encendido.");
   }
  }
 };


 public void showBTDialog() {
  final AlertDialog.Builder popDialog = new AlertDialog.Builder(this);
  final LayoutInflater inflater = (LayoutInflater) this.getSystemService(LAYOUT_INFLATER_SERVICE);
  final View Viewlayout = inflater.inflate(paired_devices_list, (ViewGroup) findViewById(R.id.bt_list));

  popDialog.setTitle("Dispositivos Bluetooth:");
  popDialog.setView(Viewlayout);

  myListView = (ListView) Viewlayout.findViewById(R.id.BTList);
  BTArrayAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1);
  myListView.setAdapter(BTArrayAdapter);
  pairedDevices = myBluetoothAdapter.getBondedDevices();

  for(BluetoothDevice device : pairedDevices)
   BTArrayAdapter.add(device.getName()+ "\n" + device.getAddress());

  myListView.setOnItemClickListener(myListClickListener);
  // Button OK
  popDialog.setPositiveButton("Conectar",
    new DialogInterface.OnClickListener() {
     public void onClick(DialogInterface dialog, int which) {
      if (address != null)
      {
       new ConnectBT().execute();
      }
      dialog.dismiss();
     }
    });
  popDialog.create();
  popDialog.show();

 }
 private class ConnectedThread extends Thread {
  private final InputStream mmInStream;
  private final OutputStream mmOutStream;

  public ConnectedThread(BluetoothSocket socket) {
   InputStream tmpIn = null;
   OutputStream tmpOut = null;
   try {
    tmpIn = socket.getInputStream();
    tmpOut = socket.getOutputStream();
   } catch (IOException e) { }

   mmInStream = tmpIn;
   mmOutStream = tmpOut;
  }

  public void run() {
   byte[] buffer = new byte[256];
   int bytes;
   while (true) {
    try {
     bytes = mmInStream.read(buffer);
     h.obtainMessage(RECEIVE_MESSAGE, bytes, -1, buffer).sendToTarget();
    } catch (IOException e) {
     break;
    }
   }
  }

  public void write(String message) {
   byte[] msgBuffer = message.getBytes();
   try {
    mmOutStream.write(msgBuffer);
   } catch (IOException e) {
    msg("Error al enviar: " + e.getMessage());

   }
  }
 }

 private class ConnectBT extends AsyncTask<Void, Void, Void>
 {
  private boolean ConnectSuccess = true;

  @Override
  protected void onPreExecute()
  {
   progress = ProgressDialog.show(MainActivity.this, "Conectando ("+ address +")...", "Espera...!!!");
  }

  @Override
  protected Void doInBackground(Void... devices)
  {
   try
   {
    if (btSocket == null || !isBtConnected)
    {
     myBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
     BluetoothAdapter.getDefaultAdapter().cancelDiscovery();
     BluetoothDevice dispositivo = myBluetoothAdapter.getRemoteDevice(address);
     btSocket = createBluetoothSocket(dispositivo);
     btSocket.connect();
    }
   }
   catch (IOException e)
   {
    ConnectSuccess = false;
   }
   return null;
  }

  private BluetoothSocket createBluetoothSocket(BluetoothDevice device) throws IOException {
   if(Build.VERSION.SDK_INT >= 10){
    try {
     final Method  m = device.getClass().getMethod("createInsecureRfcommSocketToServiceRecord", new Class[] { UUID.class });
     return (BluetoothSocket) m.invoke(device, myUUID);
    } catch (Exception e) {
     msg("No se pudo crear la conexion");
    }
   }
   return  device.createRfcommSocketToServiceRecord(myUUID);
  }

  @Override
  protected void onPostExecute(Void result)
  {
   super.onPostExecute(result);

   if (!ConnectSuccess)
   {
    msg("La conexion falló, intentelo de nuevo");
    isBtConnected = false;
   }
   else
   {
    msg("Conectado.");
    isBtConnected = true;
    mConnectedThread = new ConnectedThread(btSocket);
    mConnectedThread.start();
   }
   progress.dismiss();
  }
 }
}

Ahora con el código actualizado vamos a ver que hace cada parte del el.

Clock view está compuesto por tres clases, la primera de ellas es la que se encarga de mostrar todos los componente de la interfaz principal (crear lo eventos para los botones, inflar las cosas necesarias, etc), la segunda es ConnectedThread.

La clase ConnectedThread, es la que se va a encarga de enviar y recibir los datos de y hacia la aplicación.
En ella hay dos métodos: run() y write(). En el método run es donde vamos a leer todos los datos que vienen desde el arduino. Lo pasaremos cómo mensaje y despues el manejado h, se encargará de re-direccionar el contenido y mostrarlo en un textview.
El método write(), servirá para enviar datos hacia el arduino, está es la función que se debe de usar para enviar los comandos, por ejemplo, para enviar el comando para mostrar los segundos, debemos de llamar a la función con el parámetro ">DISS" write(">DISS").
La tercera clase es la que se encarga de crear la conexion y mostrar un dialogo de progreso/espera, cuando la conexión se realiza, deja un socket bluetooth listo para usarse.

Cómo verás, la aplicación es realmente sencilla, pero aun queda mucho por agregar a ambas partes de Clock View, por ahora el código fuente completo lo reservo para cuando ya tenga todas la funciones listas, pero con lo anterior, ya puedes crear tu propia versión.

La parte del código para arduino se actualizará, pero ese en cuanto lo cambie, también actualizaré el vinculo en dropbox.

Por ahora es todo, pero a esto aun le resta bastante para que sea un reloj funcional (más funcional).
Los leo luego.

Vamos a programar #29 - Inútil Apps #2 - Creando un socket bluetooth (arduino y android)

Hola a todos, el día de hoy vamos a continuar con Clock View. Ahora con todo el hardware listo y con la parte de software de arduino también listo, solo queda crear una forma de interactuar con el hardware de Clock View. Al carecer de botones solo nos queda la opción de usar el modulo Bluetooth, para comunicarnos por medio de este, podemos usar aplicaciones que ya estan disponibles en la Playstore (S2 Terminal for bluetooth por ejemplo), pero esa no es la idea del blog, en la mediada de lo posible trataremos de usar nuestro propio software para hacer las cosas.

El dia de hoy les quiero presentar Clock View para android, una aplicación que tiene cómo unica función; conectar con el modulo bluetooth HC-05 o HC-06 y cambiar los ajustes de Clock View.

La aplicacion dispone de 6 botones y una barra de "seek". Para usarla, primero debes de asegurarte de que todo el hardware está listo, despues debes de iniciar la conexion con el boton "Conectar con clock view", cuando aparace un mensaje diciendo que la conexion se llevo a cabo, puedes modificar los ajustes.


Hoy solo veremos el código, en el siguiente post, explicaré un poco acerca de cómo se realiza el intercambio de datos entre arduino y android.

El código.

El siguiente es el código en java que se encarga de hacer funcionar las cosas, los estilos y demás "layouts", irán en la descarga completa al final del post.

package com.mdev.clockview;

import android.app.Activity;
import android.app.AlertDialog;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.os.Build;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;
import android.app.ProgressDialog;
import android.os.AsyncTask;
import android.os.Handler;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.UUID;
import java.lang.reflect.Method;
import java.util.Set;
import java.util.Calendar;

import static com.mdev.clockview.R.layout.paired_devices_list;

public class MainActivity extends Activity {

	BluetoothAdapter myBluetoothAdapter = null;
	Button BtnConnect, BtnOnOff, BtnSecondsShow, BtnSyncHour, BtnChangeFormat,BtnDisconnect;
	SeekBar SkBright;
	TextView TxtArduinoRec, TxtBrigthValue;

	String address = null;
	private ProgressDialog progress;
	BluetoothSocket btSocket = null;
	private boolean isBtConnected = false;
	private static final UUID myUUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
	final int RECEIVE_MESSAGE = 1;
	private StringBuilder sb = new StringBuilder();
	private ConnectedThread mConnectedThread;
	Handler h;

	private Set<BluetoothDevice> pairedDevices;
	ListView myListView;
	ArrayAdapter BTArrayAdapter;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		//setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
		setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
		BtnConnect = (Button)findViewById(R.id.BtnConnect);
		myListView = (ListView)findViewById(R.id.BTList);
		TxtArduinoRec = (TextView)findViewById(R.id.TxtArduinoReturn);
		BtnOnOff = (Button)findViewById(R.id.BtnOn);
		BtnSecondsShow = (Button)findViewById(R.id.BtnShowS);
		BtnSyncHour = (Button)findViewById(R.id.BtnSync);
		BtnChangeFormat = (Button)findViewById(R.id.BtnFormat);
		BtnDisconnect = (Button)findViewById(R.id.BtnDisconnect);
		SkBright = (SeekBar)findViewById(R.id.SKBrillo);
		TxtBrigthValue = (TextView)findViewById(R.id.txtSeekValue);

		myBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

		if (myBluetoothAdapter == null) {
			msg("El bluetooth no es soportado por este dispositivo");
		}
		else {
			msg("Esperando la conexion");
		}
		SkBright.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener(){

			@Override
			public void onProgressChanged(SeekBar seekBar, int progress,
										  boolean fromUser) {
				TxtBrigthValue.setText(String.valueOf(progress));
				if (isBtConnected)
				{
					String result = String.format(">SETB%1$02d", progress);
					mConnectedThread.write(result);
				}
			}

			@Override
			public void onStartTrackingTouch(SeekBar seekBar) {
			}

			@Override
			public void onStopTrackingTouch(SeekBar seekBar) {

			}
		});
		BtnConnect.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View view) {
				if (!myBluetoothAdapter.isEnabled()) {
					Intent turnOnIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
					startActivityForResult(turnOnIntent, 1);
				}else{
					showBTDialog();
				}
			}
		});
		BtnOnOff.setOnClickListener(new View.OnClickListener()
		{
			@Override
			public void onClick(View view){
				if (isBtConnected)
				{
					mConnectedThread.write(">SCRA");
				}
			}
		});

		BtnSecondsShow.setOnClickListener(new View.OnClickListener()
		{
			@Override
			public void onClick(View view){
				if (isBtConnected)
				{
					mConnectedThread.write(">DISS");
				}
			}
		});

		BtnSyncHour.setOnClickListener(new View.OnClickListener()
		{
			@Override
			public void onClick(View view){
				if (isBtConnected)
				{
					mConnectedThread.write(BuildHourToArduino());
				}
			}
		});

		BtnChangeFormat.setOnClickListener(new View.OnClickListener()
		{
			@Override
			public void onClick(View view){
				if (isBtConnected)
				{
					mConnectedThread.write(">SETF");
				}
			}
		});
		
		BtnDisconnect.setOnClickListener(new View.OnClickListener()
		{
			@Override
			public void onClick(View view){
				if (isBtConnected)
				{
					Disconnect();
				}
			}
		});
		//encargado de procesar los mensajes.
		h = new Handler() {
			public void handleMessage(android.os.Message msg) {
				switch (msg.what)
				{
					case RECEIVE_MESSAGE:
						byte[] readBuf = (byte[]) msg.obj;
						String strIncom = new String(readBuf, 0, msg.arg1);
						sb.append(strIncom);
						int endOfLineIndex = sb.indexOf("\r\n");
						if (endOfLineIndex > 0)
						{
							String sbprint = sb.substring(0, endOfLineIndex);
							sb.delete(0, sb.length());
							TxtArduinoRec.setText("Data from Arduino: " + sbprint);
						}
						break;
				}
			};
		};

	}
	private void msg(String s)
	{
		Toast.makeText(getApplicationContext(),s,Toast.LENGTH_LONG).show();
	}
	private String BuildHourToArduino(){
		//>SETH2016122119001004
		//>SETHAAAAMMDDHHMMSSWW
		Calendar c = Calendar.getInstance();
		int DiaSemana = c.get(Calendar.DAY_OF_WEEK);
		int Anio = c.get(Calendar.YEAR);
		int Mes = c.get(Calendar.MONTH);
		int Dia = c.get(Calendar.DAY_OF_MONTH);
		int Horas = c.get(Calendar.HOUR_OF_DAY);
		int Minutos = c.get(Calendar.MINUTE);
		int Segundos = c.get(Calendar.SECOND);

		String DateForArduino = String.format(">SETH%1$04d%2$02d%3$02d%4$02d%5$02d%6$02d%7$02d",
				Anio, Mes + 1, Dia, Horas, Minutos,Segundos, DiaSemana);
		msg(DateForArduino);

		return DateForArduino;
	}

	private void Disconnect()
	{
		if (btSocket!=null)
		{
			try
			{
				btSocket.close();
				isBtConnected = false;
			}
			catch (IOException e)
			{ msg("Error");}
		}
	}

	private AdapterView.OnItemClickListener myListClickListener = new AdapterView.OnItemClickListener()
	{
		public void onItemClick (AdapterView<?> av, View v, int arg2, long arg3) {
			if (myBluetoothAdapter.isEnabled()) {
				String info = ((TextView) v).getText().toString();
				address = info.substring(info.length() - 17);
				msg(address);

			} else {
				msg("El Bluetooth debe de estar encendido.");
			}
		}
	};


	public void showBTDialog() {
		final AlertDialog.Builder popDialog = new AlertDialog.Builder(this);
		final LayoutInflater inflater = (LayoutInflater) this.getSystemService(LAYOUT_INFLATER_SERVICE);
		final View Viewlayout = inflater.inflate(paired_devices_list, (ViewGroup) findViewById(R.id.bt_list));

		popDialog.setTitle("Dispositivos Bluetooth:");
		popDialog.setView(Viewlayout);

		myListView = (ListView) Viewlayout.findViewById(R.id.BTList);
		BTArrayAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1);
		myListView.setAdapter(BTArrayAdapter);
		pairedDevices = myBluetoothAdapter.getBondedDevices();

		for(BluetoothDevice device : pairedDevices)
			BTArrayAdapter.add(device.getName()+ "\n" + device.getAddress());

		myListView.setOnItemClickListener(myListClickListener);
		// Button OK
		popDialog.setPositiveButton("Conectar",
				new DialogInterface.OnClickListener() {
					public void onClick(DialogInterface dialog, int which) {
						if (address != null)
						{
							new ConnectBT().execute();
						}
						dialog.dismiss();
					}
				});
		popDialog.create();
		popDialog.show();

	}
	private class ConnectedThread extends Thread {
		private final InputStream mmInStream;
		private final OutputStream mmOutStream;

		public ConnectedThread(BluetoothSocket socket) {
			InputStream tmpIn = null;
			OutputStream tmpOut = null;
			try {
				tmpIn = socket.getInputStream();
				tmpOut = socket.getOutputStream();
			} catch (IOException e) { }

			mmInStream = tmpIn;
			mmOutStream = tmpOut;
		}

		public void run() {
			byte[] buffer = new byte[256];
			int bytes;
			while (true) {
				try {
					bytes = mmInStream.read(buffer);
					h.obtainMessage(RECEIVE_MESSAGE, bytes, -1, buffer).sendToTarget();
				} catch (IOException e) {
					break;
				}
			}
		}

		public void write(String message) {
			byte[] msgBuffer = message.getBytes();
			try {
				mmOutStream.write(msgBuffer);
			} catch (IOException e) {
				msg("Error al enviar: " + e.getMessage());

			}
		}
	}



	private class ConnectBT extends AsyncTask<Void, Void, Void>
	{
		private boolean ConnectSuccess = true;

		@Override
		protected void onPreExecute()
		{
			progress = ProgressDialog.show(MainActivity.this, "Conectando...", "Espera...!!!");
		}

		@Override
		protected Void doInBackground(Void... devices)
		{
			try
			{
				if (btSocket == null || !isBtConnected)
				{
					myBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
					BluetoothAdapter.getDefaultAdapter().cancelDiscovery();
					BluetoothDevice dispositivo = myBluetoothAdapter.getRemoteDevice(address);
					btSocket = createBluetoothSocket(dispositivo);
					btSocket.connect();
				}
			}
			catch (IOException e)
			{
				ConnectSuccess = false;
			}
			return null;
		}

		private BluetoothSocket createBluetoothSocket(BluetoothDevice device) throws IOException {
			if(Build.VERSION.SDK_INT >= 10){
				try {
					final Method  m = device.getClass().getMethod("createInsecureRfcommSocketToServiceRecord", new Class[] { UUID.class });
					return (BluetoothSocket) m.invoke(device, myUUID);
				} catch (Exception e) {
					msg("No se pudo crear la conexion");
				}
			}
			return  device.createRfcommSocketToServiceRecord(myUUID);
		}

		@Override
		protected void onPostExecute(Void result)
		{
			super.onPostExecute(result);

			if (!ConnectSuccess)
			{
				msg("La conexion falló, intentelo de nuevo");
				isBtConnected = false;
			}
			else
			{
				msg("Conectado.");
				isBtConnected = true;
				mConnectedThread = new ConnectedThread(btSocket);
				mConnectedThread.start();
			}
			progress.dismiss();
		}
	}
}

Cómo todo el código requiere una explicacion detallada (o si no quieres meterte en programacion), por ahora solo dejo el APK ya compilado,
Los leo luego.