Primero empezaremos programando al arduino :
PARTE 1: ARDUINO
El montaje, que es de lo más sencillo.Ahora el código, más conocido como "sketch"
const int LED = 13; //LED conectado al pin digital 13
int inByte = 0;
void setup(){
Serial.begin(9600); //Abrimos el el puerto serial
pinMode(LED, OUTPUT); //Seteamos que el ping digital será de salida
}
void loop(){
if(Serial.available() > 0){
inByte = Serial.read(); //lee los bytes que ingresan
if(inByte == '1')
digitalWrite(LED, HIGH); //Enciende el LED
else if(inByte == '0')
digitalWrite(LED, LOW); //Apaga el LED
}
}
PARTE 2: API
En segundo lugar pasaremos a programar el servidor, ya que no contamos con un ethernet shield para arduino. Para lograrlo he usado el concepto de API y REST, en este pequeño tutorial no usaré un token para autentificarme ya que es otro tema. En fin, lo bueno de programar en esta forma es que cualquier programa puede hacer la petición, esto significa que nuestro servidor es escalable y eso permite realizar mejores cosas =) .Antes de empezar tiene que descargar dos librerías : Bottle,que sirve para crear el API y PySerial 2.7, que sirve para comunicarse por el puerto serial. Si estamos en Windows, debemos ir a la carpeta donde ha sido descargada y abrir la consola y ejecutar lo siguiente.
python setup.py installDe esta manera ya tenemos instalada las dos librerías.
import serial
import time
from bottle import route, run, post, get, request, template
ser = serial.Serial('COM4', 9600) //definimos el puerto COM y los baudios
time.sleep(2) //*Importante*
@route('/arduino', method='POST') //definimos la ruta y la operación HTTP
def arduino():
led = request.forms.get('led') //obtenemos la variable led
if(ser.isOpen()):
ser.write(led) //envíamos la data recibida al arduino
else:
ser.open()
ser.write(led)
time.sleep(2)
run(host='192.168.2.10', port=8080) //definimos el nombre del host y el puerto
Como pueden apreciar el código es sencillo, en la parte de "time.sleep(2)" es muy importante, ya que tendremos que esperar 2 segundos para que se abra el puerto serial, de lo contrario ocurre un error interno ya todavía no está listo para ser usado. No olvidar ejecutar este código desde la consola de python.PARTE 3: ANDROID
Una de las características especiales de Android es el "Reconocimiento de Voz", para este aplicación se usará un UI sencilla que constará de un Button para activar el "Reconocimiento de Voz" y un TextView como salida.
Paso 1: Creamos un proyecto básico en Android en Eclipse
Paso 1: Creamos un proyecto básico en Android en Eclipse
Vamos a New > Project > Android Project y le ponemos su nombre. Este aplicativo lo he llamado AndruinoLED
Paso 2: Cambiamos el LayoutArchivo: res/layout/activity_main.xml
Paso 2: Cambiamos el LayoutArchivo: res/layout/activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
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=".MainActivity"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Presione el botón para iniciar el reconocimiento de voz">
<ImageButton
android:id="@+id/btnHablar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:src="@android:drawable/ic_btn_speak_now"
android:contentDescription="">
<TextView
android:id="@+id/tviSalida"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/salida">
</LinearLayout>
Paso 3: Código Java Android
Archivo: MainActivity.java
protected static final int RESULT_SPEECH = 1; private ImageButton mBtnHablar; private TextView mTviSalida; private ArrayListEste es el método que iniciara el reconocimiento de voz. Cada intent.putExtra recibe un nombre y un valor, esto luego será enviado al API de Reconocimiento de Voz de Google. En vez de RecognizerIntent.LANGUAGE_MODEL_FREE_FORM,también se podría poner un lenguaje específico como por ejemplo "en-US", en vez de "Diga Encender o Apagar" podemos cambiar el mensaje a cualquier cosa.mTexto; private String aux; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mTviSalida = (TextView) findViewById(R.id.tviSalida); mBtnHablar = (ImageButton) findViewById(R.id.btnHablar); mBtnHablar.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { iniciarReconocimientoVoz(); } }); }
private void iniciarReconocimientoVoz() {
Intent intent = new Intent(
RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
intent.putExtra(RecognizerIntent.EXTRA_PROMPT, "Diga Encender o Apagar");
try {
startActivityForResult(intent, RESULT_SPEECH);//Activia onActivityResult()
mTviSalida.setText("");
} catch (ActivityNotFoundException a) {
Toast.makeText(getApplicationContext(),
"Tu dispositivo no es compatible con el \"Reconocimiento de Voz\"",
Toast.LENGTH_SHORT).show();
}
}
Luego de ejecutar el método iniciarReconocimientoVoz() , se dispara el método que está en @Override onActivityResult(). Si el resultado es corrector y la data recibida no es null se procede a obtener la data recibida del API de Reconocimiento de Voz y luego comparar sí es "encender" o "apagar". Finalmente ejecutamos la tarea ComunicacionServidorTask,, para decirle a nuestro servidor que encienda el LED.@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case RESULT_SPEECH: {
if (resultCode == RESULT_OK && null != data) {
mTexto = data
.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
aux = mTexto.get(0);
if(aux.compareTo("encender")==0){
mTviSalida.setText("LED encendido");
aux = "1";
}else if(aux.compareTo("apagar")==0){
mTviSalida.setText("LED apagado");
aux = "0";
}else{
mTviSalida.setText("Usted dijo : "+aux+". Diga \"enceder\" o \"apagar\"");
}
new ComunicacionServidorTask(this).execute(aux);
}
}
break;
}
}
Finalmente la comunicación con el servidor, en postParameters.add(new BasicNameValuePair("led", aux)); seteamos el nombre y el valor que enviaremos al servidor. Y no olvidar dar el permiso <uses-permission android:name="android.permission.INTERNET"/> en el AndroidManifest.xml.class ComunicacionServidorTask extends AsyncTask<<String, Boolean, Integer>{
// TAG
private static final String TAG_COMUNICACION_SERVIDOR_TASK = "ComunicacionServidorTask";
private static final String MSG_SOCKET_EXCEPTION = "SocketException";
private static final String MSG_PARSE_EXCEPTION = "ParseException";
private static final String MSG_IO_EXCEPTION = "IOException";
private ProgressDialog mProgressDialog;
public ComunicacionServidorTask(Context context) {
this.context = context;
mProgressDialog = new ProgressDialog(context);
}
@Override
protected Boolean doInBackground(String... params) {
return ComunicacionServidor();
}
private Context context;
protected void onProgressUpdate(Integer... values) {
int progreso = values[0].intValue();
mProgressDialog.setProgress(progreso);
}
@Override
protected void onPreExecute() {
mProgressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
mProgressDialog.setMessage("Conectando. Espere unos momentos.");
mProgressDialog.setCancelable(true);
mProgressDialog.setMax(100);
mProgressDialog.setOnCancelListener(new OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
ComunicacionServidorTask.this.cancel(true);
}
});
mProgressDialog.setProgress(0);
mProgressDialog.show();
super.onPreExecute();
}
@Override
protected void onPostExecute(Boolean result) {
if(result==true){
mProgressDialog.dismiss();
Toast.makeText(context, "Se conectó al servidor.", Toast.LENGTH_LONG).show();
}else{
mProgressDialog.dismiss();
Toast.makeText(context, "No se pudo conectar al servidor.", Toast.LENGTH_LONG).show();
}
super.onPostExecute(result);
}
@Override
protected void onCancelled() {
Toast.makeText(context, "Se cancelo la conexión al servidor",
Toast.LENGTH_SHORT).show();
}
private Boolean ComunicacionServidor() {
boolean resultado = false;
HttpClient httpClient = new DefaultHttpClient();
HttpPost post = new HttpPost("http://192.168.2.10:8080/arduino");
try{
ArrayList postParameters;
postParameters = new ArrayList();
postParameters.add(new BasicNameValuePair("led", aux));
post.setEntity(new UrlEncodedFormEntity(postParameters));
HttpResponse resp = httpClient.execute(post);
String respStr = EntityUtils.toString(resp.getEntity());
Log.i(TAG_COMUNICACION_SERVIDOR_TASK, respStr);
if(respStr.equals("")){
resultado = true;
}
} catch (SocketException sEx) {
Log.e(TAG_COMUNICACION_SERVIDOR_TASK,
MSG_SOCKET_EXCEPTION + ": " + sEx.getMessage());
} catch (ParseException pEx) {
Log.e(TAG_COMUNICACION_SERVIDOR_TASK,
MSG_PARSE_EXCEPTION + ": " + pEx.getMessage());
} catch (IOException ioEx) {
Log.e(TAG_COMUNICACION_SERVIDOR_TASK,
MSG_IO_EXCEPTION + ": " + ioEx.getMessage());
}
httpClient.getConnectionManager().shutdown();
return resultado;
}
}
ScreenCapture de la aplicación :
Video demostrativo:
Este será el repositorio del blog https://github.com/IvanAliaga/EntreOtrosCodigos , ahí encontrarán todo el proyecto.
Y bueno esta es la primera vez que hago un blog, es la primera entrada, ya es 31 de enero y posteriormente realizaré otros pequeños proyectos o tutoriales como quieran llamarle, pero a pesar de todo transmitir lo que sé a todas las personas interesadas en estos temas para que integren estos pequeños conocimientos para algo más grandioso. Espero haber ayudado y Feliz Año Nuevo :D





No hay comentarios:
Publicar un comentario