Author Archives: Jose Nunez

Comandos por BLE – (Parte 2 de 2) – El Transmisor (TX)

22 Jul , 2017,
Jose Nunez
, , , , , ,
No Comments

Como lo prometido es deuda, acá está la 2da entrega referente a controlar cosas con telefonos celulares mediante Bluetooth Low Energy (BLE) usando IONIC 3.

En esta segunda parte, implementaremos una App (Android y IOS) usando IONIC 3 que le envía comandos al micro-controlador mediante el sistema BLE del teléfono.

Para ver la Parte 1 haz clic acá

(!) Antes de seguir estas instrucciones asegúrese de entender las Condiciones de Uso de nuestro sitio.

Programando el App

En resumen:

  1. IONIC 3 es un sistema para crear aplicaciones móviles usando tecnologías híbridas (cordova, angularjs 4, typescript, html, css, etc.)
  2. Necesitaremos configurar IONIC3 en nuestro computador; esto incluye NodeJS, NVM, NPM y IONIC.
  3. También necesitaremos un muy buen editor de código para TypeScript. Puedo recomendarles Visual Studio Code o Atom.
  4. Descargamos el código del app de ejemplo de mi repositorio de Github y lo abrimos con el IDE de ARDUINO.git clone https://github.com/janunezc/robotics.gitEl código se ubica en ~/robotics/intel_curie/ble_command_app/
  5. En el celular podemos utilizar el sistema Ionic View (descargado del App Store o Google Play) y previsualizar el app 03B50F88Las siguientes imágenes muestran la operación del app

 

Seguidamente mostramos las partes más importantes del código original del programa con los comentarios detallados sobre su funcionamiento. Es realmente sencillo; podemos resumirlo en:

  1. El tab “SCAN” implementa un proceso básico de búsqueda de dispositivos Bluetooth. No vamos a detallar mucho en este tutorial sobre ese tab.
  2. El tab “LED” implementa la búsqueda de un dispositivo específico y una vez que lo encuentra permite interactuar con el LED para encenderlo y apagarlo.
    1. Los componentes (tabs) de la aplicación IONIC3 se dividen en 3 elementos principales: una vista o view (led.html), un controlador (led.ts) y un modelo que corresponde a los datos que va a manejar la aplicación y que se ubican en el objeto this y sus propiedades públicas.
    2. El archivo led.html es realmente simple. Aparte de los párrafos de texto expicativo y títulos, posee un botón que tiene algunas características importantes de AngularJS como lo son el atributo [disabled] ligado a una variable del modelo denominada “ejecutandoComando”. Cuando la variable tiene un valor verdadero (true) el atributo disabled se activa y el botón se deshabilita. A su vez tiene una directiva (click) que ejecuta la función “Command()” del controlador.
    3. Una parte importante del archivo led.html es el último párrafo en la línea 11. Este utiliza una directiva *ngFor para iterar sobre la variable “messages” y mostrar cada mensaje como un párrafo ( <p> ) individual. Esto nos permite mostrar mensajes de aclaración conforme se ejecutan los procesos en el controlador.
  3. Exploremos ahora el archivo led.ts. Se trata de un script escrito en TypeScript. Un pseudo-lenguaje basado en JavaScript que permite una orientación a objetos más elaborada.
    1. Lo primero que se realiza en led.ts es importar las librerías necesarias. Dos de las más notorias serán BLE y ApplicationRef. La primera permite comunicación BLE, y la segunda permite manipular el framework de Angular para refrescar la pantalla cuando sea necesario.
    2. La siguiente parte super importante es el constructor, el cual implementa una serie de inyecciones de dependencia que vale la pena mencionar.
    3. Nótese la forma en que se inyectan en el constructor tanto la librería BLE como la librería de Angular ApplicationRef. En el constructor también se inicializan variables importantes tales como el ID de servicio y el ID de Característica que se van a manipular.
    4. Las funciones más interesantes en este archivo son:
      1. findDevice() que busca un dispositivo particular y una vez que lo encuentra cambia el modo de comandos para encender o apagar un LED. Para esto usa la funcion de BLE nativo denominada ble.scan()
      2. txData() que utiliza ble.connect y ble.write para conectarse al dispositivo y hacerle llegar un mensaje.
      3. SetMessage() tambien merece ser mecionado como la forma que tenemos de agregar mensajes de control que nos permitan entender cómo se está ejectuando el programa.

Espero que este artículo les sea de utilidad junto con el anterior para aprender a enviar comandos a un dispositivo BLE basado en Intel Curie, mediante el teléfono celular.

Los dejo con estos enlaces de utilidad:

  1. Aprender TypeScript: https://www.typescriptlang.org/docs/home.html
  2. Aprender Ionic 3: https://ionicframework.com/
  3. Aprender Angular 4: https://www.youtube.com/watch?v=kFTmoLm9Jwg

Que estén bien!


led.html

<ion-header>
   <ion-navbar>
   <ion-title>LED</ion-title>
   <p>Acá podemos operar el LED que está implementado en TinyTILE</p>
   <button ion-button [disabled]="ejecutandoComando" (click)="Command()">{{ComandoTXT}}</button>
</ion-navbar>
</ion-header>
<ion-content padding>
   <p>Histórico de Ejecución: ({{myCount}} | {{test}})</p>
   <hr />
   <p *ngFor="let message of messages">{{message}}</p>
</ion-content>

led.ts

import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';
import { BLE } from '@ionic-native/ble';
import { ApplicationRef } from '@angular/core';

@Component({
  selector: 'page-led',
  templateUrl: 'led.html'
})

export class LEDPage {

  public messages = []; //Histórico de ejecución
  public ejecutandoComando = false;
  public BLE;
  public ComandoTXT = "";
  public Value = "";
  public TargetDevice;
  private appRef;

  /**
   * CONSTANTES que serán usadas a lo largo del controlador
   */
  public constants  = {
      DEVICE_NAME: "COMANDO LED",
      CMD_FIND_DEVICE:"FIND DEVICE",
      CMD_STOP_SCAN:"Escaneando... (Clic para parar)",
      CMD_TOGGLE_LED:"CAMBIAR LED",
      ON:"ON",
      OFF:"OFF"
    };

  /**
   * Constructor para el controlador. Todo comienza acá...
   */
  constructor(public navCtrl: NavController, private ble: BLE /*Librería BLE nativa*/, private applicationRef : ApplicationRef /*Librería ApplicationRef de Angular*/ ) {
    this.appRef = applicationRef; //Referencia a la aplicación ANGULAR
    this.SetMessage("Constructor: Iniciado!");
    this.BLE = ble; //Acceso a la librería BLE Nativa
    this.ComandoTXT = this.constants.CMD_FIND_DEVICE;
    this.Value = "ON"; //VALOR PARA ENVIAR
    this.TargetDevice = {}; //Dispositivo al cual conectarse. Inicialmente vacío... se llenará cuando se encuentre el dispositivo en el escaneo.
    this['service_id'] = "db938b80-f010-44b6-8aa9-1835adf9419a"; //Identificador del servicio BLE a conectarse
    this['characteristic_id'] = "9906064e-9bbe-4eba-b415-bbd223f7d3d9"; //Identificador de la característica BLE a conectarse
    this.SetMessage("Constructor: Finalizado!");
  }

  /**
   * This is triggered when the button is clicked.
   */
  public Command(){
    this.ejecutandoComando = true;
    this.SetMessage("Command() - Comando recibido!");
    this.SetMessage(this["ComandoTXT"]);
    this.SetMessage("Interpretando comando...");

    if(this['ComandoTXT']===this.constants.CMD_FIND_DEVICE) {
      this.SetMessage("Ejecutando Comando: FIND DEVICE");
      this['ComandoTXT'] = this.constants.CMD_STOP_SCAN;
      this.findDevice();

    } else if (this['ComandoTXT']===this.constants.CMD_STOP_SCAN) {
      this.SetMessage("Ejecutando Comando: STOP SCAN");
      clearInterval(this['intervalHandle']);
      this['ComandoTXT'] = this.constants.CMD_FIND_DEVICE;
      this.ejecutandoComando = false;

    } else if(this['ComandoTXT']=== this.constants.CMD_TOGGLE_LED){
      this.SetMessage("Ejecutando Comando: TOGGLE LED: " + this.Value);
      this.SetMessage("Acá es donde enviamos un valor al dispositivo BLE");
      this.txData();
    }
  }

  /**
   * This searches for DEVICE in the AIR using SCAN technique.
   */
  private findDevice(){
      this.SetMessage("FindDevice() - INICIO!");
      let  ble = this.BLE;

      this.SetMessage("FindDevice() - ENABLE!");
      ble.enable();

      this.SetMessage("FindDevice() - SET INTERVAL!");
      this['intervalHandle'] = setInterval(() => { // PROGRAMAR UN TIMER DE 2.1 SEGUNDOS
        this.SetMessage("INTERVAL: INICIO! LLAMANDO A BLE SCAN...");
        ble.scan([], 2 /*seconds (0) */).subscribe( data => { //REALIZAR SCAN BLE POR 2 SEGUNDOS
          this.SetMessage("BLE SCAN CALLBACK: " + data['id'] + ' | ' + data['name'] + ' | ' + data['rssi']);
          if(data['name']==this.constants.DEVICE_NAME){
            this.SetMessage(this.constants.DEVICE_NAME + " HA SIDO ENCONTRADO!!");
            clearInterval(this["intervalHandle"]);
            this.TargetDevice = data;
            this["ComandoTXT"] = this.constants.CMD_TOGGLE_LED;
            this.ejecutandoComando = false;
          }
          this.appRef.tick();
        });
      },2100);//FIN DE LA DEFINICIÓN DEL TIMER
      this.ejecutandoComando = false;
    }

  /**
   * Transmitir datos al dispositivo BLE
   */
  private txData(){
    this.SetMessage("txData(): INICIO! Llamando a BLE CONNECT...");

    let id = this.TargetDevice.id;
    this.SetMessage("ID DE DISPOSITIVO: " + id);

    this.ble.connect(id).subscribe(datos=>{
      this.SetMessage("BLE CONNECT CALLBACK: INICIO!. Llamando a BLE WRITE..." + this.Value);

      this.ble.write(this.TargetDevice.id, this['service_id'],this['characteristic_id'], this.StringToBytes(this.Value) ).then(()=>{
        this.SetMessage("BLE WRITE CALLBACK: INICIO! Cambiando valor... " + this.Value);
        if(this.Value==this.constants.ON){
          this.Value = this.constants.OFF;
        } else {
          this.Value = this.constants.ON;
        }
        this.SetMessage("Nuevo valor... " + this.Value);

        this.SetMessage("Llamando a BLE DISCONNECT...");
        this.ble.disconnect(id);
        this.ejecutandoComando = false;
        this.appRef.tick();
      },(error)=>{
        this.SetMessage("BLE Write ERROR!");
        this.SetMessage(error);
        this.SetMessage("Llamando a BLE DISCONNECT...");
        this.ble.disconnect(id);
        this.ejecutandoComando = false;
        this.appRef.tick();
      });
    },error=>{
      this.SetMessage("BLE Connect ERROR!");
      this.SetMessage(error.message);
      this.ejecutandoComando = false;
      this.appRef.tick();
    });
  }

  /**
   * Agrega mensajes de ejecución al histórico
   */
  public SetMessage(message){
    var count = this['messages'].length;
    message = count + ':' + message;
    this['messages'].unshift(message);

    /*
      ESTA LINEA ES IMPORTANTE PARA REFRESCAR LA PANTALLA CUANDO SE GENERAN EVENTOS
      FUERA DEL CONTROL DE ANGULAR. POR EJEMPLO CUANDO SE LLAMA A UN CALLBACK EN
      UN PROCESO DE BLE SCAN.
    */
    this.appRef.tick();
  }

  // ASCII only. Convierte el valor a escribir a un arreglo de BYTES
  public StringToBytes(string) {
     let array = new Uint8Array(string.length);
     for (let i = 0, l = string.length; i < l; i++) {
         array[i] = string.charCodeAt(i);
      }
      return array.buffer;
  }

  // ASCII only
  public BytesToString(buffer) {
      return String.fromCharCode.apply(null, new Uint8Array(buffer));
  }
}

Comandos por BLE – (Parte 1 de 2) – El Receptor

21 Jul , 2017,
Jose Nunez
, ,
No Comments

Para continuar la exploración de la tecnología BLE que comenzó nuestra compañera Rebeca Rodriguez Tencio acá, les presentamos este primer tutorial de dos relacionados. La idea es poder implementar una forma de enviar comandos a una tarjeta de prototipado via Bluetooth Low Energy (BLE) desde una App de un teléfono Móvil.

En esta primera parte implementaremos un servicio “Comando LED” en un microcontrolador compatible con Arduino 101 llamado TinyTILE (basado en el chip Curie de Intel)

En la segunda parte, implementaremos una App (Android y IOS) usando IONIC 3 que le envía comandos al micro-controlador mediante el sistema BLE del teléfono.

(!) Antes de seguir estas instrucciones asegúrese de entender las Condiciones de Uso de nuestro sitio.

Primero: Programemos el Curie

En resumen:

  1. Necesitaremos un protoboard, un LED, una resistencia de 150 Ohm, un TinyTILE y un cable USB a micro-USB y una PC
  2. El circuito es muy sencillo:


  3. En la PC instalamos los controladores de placa “Arduino/Genuino 101” en el IDE de ARDUINO (V.1.8.2)
    • Menu: Tools >  Board > Board Manager > Search “Curie” > Instalar V 2.0.2 o superior.
  4. Descargamos el programa (sketch) de ejemplo de mi repositorio de Github y lo abrimos con el IDE de ARDUINO.
  5. Instalamos el boceto de ejemplo en la placa
    • Menu: Sketch > Upload
  6. Usamos una app para pruebas BLE denominada “BLE Scanner” para enviar comandos “ON” y “OFF”
  7. Nótese que hemos implementado una función “parpadear” que nos permite ver si el sketch arrancó adecuadamente.

Las siguientes imágenes ilustran el uso de BLE Scanner para enviar los comandos.

Seguidamente mostramos el código original del programa con los comentarios detallados sobre su funcionamiento. Es realmente sencillo; podemos resumirlo en:

  1. Definir un servicio BLE “ServicioBLE_Comando” (línea 5)
  2. Deinir una característica BLE “CaracteristiciaBLE_Comando” de tipo genérica, de lectura y escritura con mensajes de 20 bytes (línea 8)
  3. Darle un nombre al dispositivo “COMANDO LED” e inicializarlo, agregando el servicio y la característica (línea 19)
  4. Publicitamos el servicio (línea 23)
  5. Leemos eventos BLE en la característica (nuevos comandos) que luego son interpretados y ejecutados (líneas 31,33,57,61)
  6. Para esto convertimos el valor recibido a un String (línea 63)

 


#include <CurieBLE.h>
#define ledPin 13

//Definimos un servicio BLE
BLEService servicioBLE_Comandos("db938b80-f010-44b6-8aa9-1835adf9419a"); // create service

//Definimos una característica que pueda ser leida o escrita desde una central BLE, con capacidad de 20 bytes por mensaje.
BLECharacteristic caracteristicaBLE_Comandos("9906064e-9bbe-4eba-b415-bbd223f7d3d9", BLERead | BLEWrite, 20);

void setup() {
  Serial.begin(9600);
  pinMode(ledPin, OUTPUT); 
  delay(500); //Esperamos un poco de tiempo (500ms) por si se puede habilitar la terminal serial.
  parpadear(5,200);//Señalizamos con el LED que estamos iniciando el sketch
  
  BLE.begin(); //Inicializamos el sistema Bluetooth Low Energy (BLE) del Curie
  parpadear(2 ,100);//Señal de aviso de que la operación anterior fue exitosa
  
  BLE.setLocalName("COMANDO LED"); //Definimos un nombre para publicitar nuestro dispositivo
  BLE.setAdvertisedService(servicioBLE_Comandos);//Definimos el servicio que se va a publicitar
  servicioBLE_Comandos.addCharacteristic(caracteristicaBLE_Comandos); //Agregamos la característica al servicio
  BLE.addService(servicioBLE_Comandos); //Agregamos el servicio al dispositivo  
  BLE.advertise(); // Publicitamos el dispositivo
  parpadear(3 ,100);//Señal de aviso de que la operación anterior fue exitosa

  Serial.println("En este punto el dispositivo queda listo, publicitado y esperando conexiones...");
  parpadear(10,50);//Señal de aviso de que SETUP se concluyó satisfactoriamente
}

void loop() {
  BLE.poll(); // Obtenemos cualquier evento BLE que haya sido enviado al dispositivo

  if (caracteristicaBLE_Comandos.written()) { //Si hay datos, ejecutamos el comando
    leerYEjecutarComado();
  } // ... caso contrario simplemente se termina el flujo de loop()
}

/**
 * Este método lee el comando registrado en la característica BLE y lo ejecuta.
 */
void leerYEjecutarComado(){
    String valorDelComando = obtenerValorDelComando();

    if (valorDelComando.startsWith("ON")) {
      Serial.println("LED on");
      digitalWrite(ledPin, HIGH);
    } else {
      Serial.println("LED off");
      digitalWrite(ledPin, LOW);
    }
}

/**
 * Extraer el valor del comando en formato String
 */
String obtenerValorDelComando(){
    int longitudDelComando = caracteristicaBLE_Comandos.valueLength();
    Serial.print("Longitud: ");
    Serial.println(longitudDelComando);
      
    const byte* val = caracteristicaBLE_Comandos.value();
    
    String strValor = String((const char *)val).substring(0, longitudDelComando);
    Serial.println("|" + strValor + "|");

    return strValor;
}

void parpadear(int times, int milliseconds){
  for(int i=0; i<times; i++){
    digitalWrite(ledPin, HIGH);
    delay(milliseconds);
    digitalWrite(ledPin, LOW);
    delay(milliseconds);
  }
}

 

 

Prototipos de Software con Computadoras Virtuales c9.io

11 Jun , 2017,
Jose Nunez
, , , ,
No Comments

Este es un post realmente corto.

Cuando uno está experimentando o desarrollando con tecnologías de software para cosas como desarrollo web y de aplicaciones móviles, sistemas como NodeJS o Python, visión computarizada, etc… usualmente requerimos instalar en nuestros computadores una cantidad importante de bibliotecas y paquetes para realizar pruebas con dichas tecnologías.

C9.io es un servicio comercial de máquinas virtuales en la web.

La verdad me ha parecido muy sencillo y completo.

https://c9.io

Todo es cuestión de crear una cuenta de usuario, ojalá enlazada con nuestra cuenta de usuario de github.com (si la tuvieramos) y vualá, podemos crear nuevas máquinas virtuales, clonar las existentes, y operarlas para instalar y desinstalar cosas a nuestro antojo casi ilimitado.

Una cuenta gratuita nos permitirá generar nuevas máquinas virtuales con ciertas limitaciones de capacidad de procesador, memoria RAM (512MB) y almacenamiento (2GB) que por lo general son suficientes para realizar pruebas de concepto o experimentación.

En próximas entregas estaré discutiendo un poco cómo realizar pruebas en C9.io para desarrollo de apps en ionic, nodejs, python-opencv entre otros.

Mis primeros pasos con ionic

5 Jun , 2017,
Jose Nunez
, , , ,
No Comments

Bueno, como nos pasa a todos, un día desperté con esa imperiosa necesidad de crear una app para teléfonos inteligentes; y pues, comenzar no es fácil si tomamos en cuenta que las principales plataformas de desarrollo (IOS y Android) tienen sus costos y complejidades.

(!) Antes de seguir estas instrucciones asegúrese de entender las Condiciones de Uso de nuestro sitio.

Afortunadamente, mis compañeros del centro de innovación habían estado realizando una investigación sobre algo similar, y me hablaron del Ionic Framework, un sistema para desarrollar aplicaciones móviles usando tecnologías web (HTML, CSS, JS/TS, ANGULARJS) etc que luego pueden implementarse tanto en Android como IOS.

Dentro de las bondades de Ionic podemos listar las siguientes:

  1. Manejo de plantillas de proyecto predefinidas
  2. Acceso a características específicas de hardware (bluetooth, gps, camara, etc)
  3. Pre-visualizacion de las apps usando IonicView directamente en los dispositivos móviles tanto para Android como para IOS

Pero bueno, he querido comenzar con el pie derecho, configurando una estación de trabajo LINUX UBUNTU 16.04 así que aquí van algunos lineamientos básicos para comenzar:


#1 – NodeJS

Es necesario instalar nodeJS y npm. Para Ubuntuo 16.04 he encontrado esta guía que me ha parecido muy completa. En ella se discuten diferentes métodos. Yo elegí usar el método de nvm (node version manager) que se puede resumir en los siguientes comandos uno por uno.

Antes de iniciar vaya a https://nodejs.org/en/download/ y determine cual es la versión LTS (en nuestro caso es la 6.11)

cd
sudo apt-get update
sudo apt-get install build-essential libssl-dev
curl -sL https://raw.githubusercontent.com/creationix/nvm/v0.31.0/install.sh -o install_nvm.sh
bash install_nvm.sh
source ~/.profile
Opcionalmente: nvm ls-remote | grep Latest
nvm install  6.11
node -v
npm -v

#2 – Instalación de IONIC

Ahora, de acuerdo con la guía de inicio de IONIC procedemos con el siguiente comando (puede tardar muchos minutos):

npm install -g cordova ionic --verbose

Luego de unos minutos (como 15 con mi conexion 3G) y de mucho texto en la consola, podemos usar el comando ionic -v para determinar la versión que hemos instalado.

En este punto es importante crear una cuenta personal en https://apps.ionic.io/signup para poder visualizar las aplicaciones con Ionic View. Una vez creada la cuenta podemos usar el siguiente comando para que nuestra instalación de ionic quede conectada a nuestra cuenta.

ionic login

#3 Creación de un nuevo proyecto

(!) Antes de crear un nuevo proyecto, es importante asegurarse que su GIT local esté instalado y configurado.

Al momento de escribir este artículo, la guía de inicio hace mención de 3 tipos de proyecto: blank, tabs y sidemenu (aunque hay todo un mercado de tipos de proyecto en la red). La verdad nos gustó más el de tabs, así que usamos estos comandos:

cd
mkdir myIonicTests
cd myIonicTests
ionic start myApp tabs

Dado que ya habíamos hecho login en el paso anterior, podemos decirle que si (Y) a la pregunta de la terminal “Link this app to your Ionic Dashboard to use tools like Ionic View? (Y/n)“. Al decir que sí el sistema termina de crear el app y nos lleva al navegador de Internet a la página de ionic para crear nuevas apps para el visor. Más tarde será necesario utilizar el comando ionic link para conectar el código de nuestra app local con su correspondiente entrada en Ionic View.

(!) Notas: Algo importante de resaltar es que este template de una vez crea el proyecto como un repositorio GIT. Reconectar un repositorio GIT a nuestra cuenta GIT de preferencia es una tarea importante a  futuro, pero eso lo dejaremos para otro artículo.
Otra cosa importante es que el comando start de ionic necesitará una conexión a Internet estable para poder descargar todos los archivos, bibliotecas y dependencias necesarias.

En este punto ya podemos ejecutar el comando ionic serve para pre-visualizar el app en nuestro navegador local.


#4 Ejecutar la aplicación en un celular

Nótese que al crear la aplicación en el sitio web de ionic, se generó un código de identificación de la app. En la aplicación IonicViewer de Android o IOS se puede acceder con sus credenciales de ionic, o usando el código de identificación de la aplicación.

Antes de subir el código a Ionic View, necesitamos enlazarlo con nuestra nueva app; usando el comando ionic link. Se usan las flechas arriba y abajo del teclado para seleccionar el app.

Para subir el código más reciente utilizamos el comando ionic upload; luego en la aplicacion de celular Ionic View usamos la opción “Clear App Data” y luego “View App”

En una próxima entrada estaremos discutiendo cómo modificar el código.

 

Introducción al ESP8266

31 May , 2017,
Jose Nunez
, , , , ,
one comments

Aquí resumo algunas cosas que he ido descubriendo del ESP8266 esta semana:

#1 – El ESP8266 viene programado de manera nativa con un firmware que responde a comandos AT para realizar conexiones y comunicación WiFi. Una referencia útil al set de comandos se puede encontrar acá.

#2 – El ESP8266 puede ser programado mediante el IDE de ARDUINO. Para esto es necesario instalar la definición de placa usando la opción de Tools > Board Manager; pero antes de esto es necesario configurar la siguiente URL para definición de tarjetas adicionales usando la opción File > Preferences > Additional Boards Manager URLs.

URL:  http://arduino.esp8266.com/stable/package_esp8266com_index.json

Es necesario cerrar el IDE y volverlo a cargar para poder utilizar el board que aparece en la lista abajo como “Generic ESP8266 Module“. (!) Importante: Una vez re-programado el módulo se pierde el firmware que habilita los comandos AT. Para re-habilitarlos será necesario seguir alguno de los procedimientos disponibles para cargar el firmware

#3 – Se puede conectar el módulo directamente a la PC usando un convertidor USB-Serial FOCA 2.2 con las siguientes conexiones; pero antes se debe configurar el FOCA 2.2 para operar a 3.3V, caso contrario se daña el ESP8266:

esp8266_pinoutFOCAV2.2        ESP8266
   VCCIO -----> VCC (3.3V)
     TXD -----> RXD
     RXD <----- TXD
     GND <----- GND
   VCCIO -----> CH_PD

 Opcionalmente se enciende el dispositivo con el GPIO0 conectado a tierra (GND) para habilitar la descarga de sketches de ARDUINO en el módulo; y luego se desconecta de GND para operar con el Sketch descargado.
FTDI Cable             ESP8266
 VCCIO (red)    -----> VCC (3.3V) 
   TXD (orange) -----> RXD 
   RXD (yellow) <----- TXD
   GND (black)  <----- GND
 VCCIO (red)    -----> CH_PD

#4 – La definición de placa del ESP8266 de ARDUINO (“Generic ESP8266 Module“) incluye una cantidad importante de ejemplos muy básicos para la operación del módulo, ya sea como Cliente HTTP, o cliente WiFi, o Access point, e incluso la creación de redes tipo Mesh usando WiFi.

#5 – El módulo ESP8266 no tiene capacidad para comunicarse con servicios de Internet por canales seguros de tipo HTTPS, lo cual representa una limitante sobre el tipo de aplicación que se pueda implementar. Como medida mínima es recomendable conectar el ESP8266 a un IoT Gateway con capacidad de comunicación HTTPS hacia la nube y no usarlo en aplicaciones suceptibles en caso de ser “hackeadas” ya que es relativamente facil para un hacker poder interceptar los datos provenientes del ESP8266 (no cifrados) interpretarlos e incluso suplantarlos.

#6 – El ESP8266 se puede conseguir en Costa Rica en CR Cibernetica. Nótese que al momento de escribir este artículo el precio estaba en $7.95, solamente $1 por debajo del SONOFF que aparte de traer uno de estos módulos tiene el hardware necesario para manejar corriente AC y un programa predeterminado para poder operarlo mediante un App de teléfono.

#7 – En Amazon se puede conseguir hasta por $15 cuatro módulos ($3.75 cada uno!). En Wish.com se pueden conseguir incluso a $2. Aunque para ser sinceros la comodidad de comprarlos en CR Cibernética y que me los traigan a domicilio el día siguiente es inigualable.

 #8 – Volviendo a los comandos AT, se puede acceder a estos mediante una terminal como Putty usando el puerto serial del FOCA V2.2 a una velocidad de 115200 bauds, pero es necesario (al menos en el caso de Putty) utilizar [ENTER] y [CTRL]+[ J ] para enviar los comandos al módulo y obtener una respuesta. Una conexión parecida se puede usar desde un ARDUINO 101 (que opera a 3.3V) usando la librería SoftwareSerial para operar el ESP8266 usando comandos AT enviados desde el ARDUINO. También se puede operar el ESP8266 desde un arduino usando los GPIO del ESP8266 como indicativos de qué hacer y que un Sketch de ARDUINO en el ESP8266 tome decisiones y realice comunicaciones WiFi basadas en esas señales.

#9 –  Finalmente cabe mencionar que el módulo tiene la capacidad de almacenar información en estado apagado. Lo cual permite, por ejemplo, recordar cual fue el último SSID/Passphrase que se usó y reconectar al encender, tanto para aplicaciones basadas en comandos AT como para aplicaciones basadas en sketch de Arduino ejecutados en el módulo ESP8266.

Ya Contamos Personas… Ahora hagamos algo con Python

20 Abr , 2017,
Jose Nunez
, , , , ,
2 comments

Muchas personas piensan que la visión computarizada es un área de la tecnología reservada para genios matemáticos japoneses.

Nada más lejos de la realidad.

Mientras que en efecto se hace uso intensivo de matemática muy avanzada, y de sistemas computacionales de última generación; la realidad es que, gracias al código abierto, existen bibliotecas y frameworks  que hace accesible estas tecnologías a todas las personas que, con una dosis adecuada de interés quieran adentrarse en este mundo tan fascinante y a la vez de vital importancia para nuestra sociedad moderna.

En esta entrega les mostramos una extensión de nuestro artículo anterior sobre “Visión Computarizada: Contando Gente con OpenCV, ROS,..” donde exploramos la creación un programa básico en lenguaje Python que haga uso modesto de los datos generados por el contador de personas.

Recordemos que ROS (Robot Operating System) es un meta-sistema operativo de tipo publicador/suscriptor que facilita la comunicacion entre diversos nodos computacionales; y que está orientado a sistemas robóticos.

Como dijimos, en el artículo anterior exploramos cómo configurar un sistema Up-Board con Ubuntu Linux, para utilizar los datos provenientes de una cámara para analizar las imagenes en tiempo real y detectar personas. Fascinante.

Ahora, basados en el tutorial básico de ROS para creación de programas Python de publicación y escucha, acá listamos los pasos básicos para la creación de publicadores y escuchadores que funcionen con ROS.

(!) Antes, tengamos en cuenta que la detección de personas que viene con opencv_apps de ROS lo que hace es buscar en las imágenes patrones que coincidan con cierta geometría rectangular alta. Por eso en la imagen destacada de este artículo vemos marcas de rectángulos donde no hay personas. Al final de este artículo hablamos del comando rosrun rqt_reconfigure rqt_reconfigure que permite ajustar parámetros “en caliente” para mejorar la precisión.

También, antes de ejecutar estos procedimientos, es probable que necesite ejecutar las instrucciones de algunos artículos anteriores que se listan en esta página: http://costaricamakers.com/?p=914 a partir del punto 4.

En caso de duda o si algo no funciona, les agradezco nos lo hagan saber en los comentarios.


PASO 1 – Primeramente creamos un espacio de trabajo de tipo catkin. Es decir la estructura básica de archivos y herramientas de un espacio de trabajo para ROS usando el sistema de construcción Catkin.

mkdir -p ~/catkin_ws/src
cd ~/catkin_ws/src
cd ~/catkin_ws/
catkin_make
source devel/setup.bash

PASO 2 – Seguidamente crearemos un paquete de ROS al que llamaremos “beginner_tutorials”que no es otra cosa que un conjunto de programas que se pueden manipular mediante ROS.

cd ~/catkin_ws/src
catkin_create_pkg beginner_tutorials std_msgs rospy roscpp
cd ~/catkin_ws
catkin_make
. ~/catkin_ws/devel/setup.bash

De nuevo, para más información sobre la creación de paquetes puede visitar el tutorial oficial en http://wiki.ros.org/ROS/Tutorials/CreatingPackage


PASO 3 – Ahora escribiremos los programas básicos de publicación y escucha.

roscd beginner_tutorials
mkdir scripts
cd scripts
wget https://raw.github.com/ros/ros_tutorials/kinetic-devel/rospy_tutorials/001_talker_listener/talker.py
chmod +x talker.py

El comando wget de la linea 4 arriba se encargará de descargar nuestro programa de python llamado “talker.py” que se encarga de publicar mensajes en un nodo denominado “chatter” que luego serán leidos desde el programa de escucha o suscriptor.

Para crear el programa de escucha usamos los siguientes comandos:

roscd beginner_tutorials/scripts/
wget https://raw.github.com/ros/ros_tutorials/kinetic-devel/rospy_tutorials/001_talker_listener/listener.py
chmod +x listener.py

Con esto se descarga el programa “listener.py” en nuestra carpeta scripts para programas de python.

Este programa escuchará datos publicados al nodo “chatter” y los mostrará en la pantalla.


PASO 4 – Pongamos a prueba estos programas.

Para esto primero compilaremos el paquete usando los siguientes comandos

cd ~/catkin_ws
catkin_make

y luego ejecutaremos ambos scripts en terminales diferentes:

rosrun beginner_tutorials listener.py
rosrun beginner_tutorials talker.py

Al ejecutarse se puede apreciar como, el listener.py no hace nada, hasta que el talker.py es ejecutado. El programa talker.py envia mensajes con un numero al tópico chatter; estos mensajes son entonces escuchados por el programa listener.py el cual los muestra en la pantalla al recibirlos. Es una dinámica muy simple.


PASO 5 – Modifiquemos el listener.py

Ahora modificaremos el programa listener.py para que en lugar de escuchar el tópico ‘chatter’ publicado por talker.py, escuche un tópico un tanto más avanzado: la cuenta de personas de nuestra cámara.

Usando el siguiente comando abrimos listener.py usando el editor gedit que viene con Ubuntu.

cd ~/catkin_ws
sudo gedit src/beginner_tutorials/scripts/listener.py

Luego reemplazamos el contenido del script con el siguiente:

#!/usr/bin/env python
# Software License Agreement (BSD License)
#
# Copyright (c) 2008, Willow Garage, Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
#  * Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
#  * Redistributions in binary form must reproduce the above
#    copyright notice, this list of conditions and the following
#    disclaimer in the documentation and/or other materials provided
#    with the distribution.
#  * Neither the name of Willow Garage, Inc. nor the names of its
#    contributors may be used to endorse or promote products derived
#    from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
# Revision $Id$

## Simple talker demo that listens to std_msgs/Strings published 
## to the 'chatter' topic

import rospy
from std_msgs.msg import String
from opencv_apps.msg import RectArrayStamped

def callback(data):
    rospy.loginfo(rospy.get_caller_id() + 'I AAAA  heard %s', data)

def listener():

    # In ROS, nodes are uniquely named. If two nodes with the same
    # name are launched, the previous one is kicked off. The
    # anonymous=True flag means that rospy will choose a unique
    # name for our 'listener' node so that multiple listeners can
    # run simultaneously.
    rospy.init_node('listener', anonymous=True)

    rospy.Subscriber('people_detect/found', RectArrayStamped, callback)

    # spin() simply keeps python from exiting until this node is stopped
    rospy.spin()

if __name__ == '__main__':
    listener()

Podemos observar las partes clave del programa:

  1. Linea 41: Importamos de la librería opencv_apps.msg el tipo de datos RectArrayStamped, que es el tipo de datos con que se publican las personas encontradas .
  2. Linea 44: Se muestra en consola los datos recibidos por el suscriptor. Nótese que donde dice data, podríamos poner data.rects para obtener unicamente el arreglo de rectángulos que representa a cada persona.
  3. Linea 55: Se define un suscriptor para el tópico peopledetect/found con un tipo de dato RectArrayStamped que al escuchar datos llamatrá la función callback. Esta función se define en la línea 43 y 44.

Para ejecutar este script usariamos el siguiente comando que nos mostrará los datos escuchados.

rosrun beginner_tutorials listener.py

Otros comandos que suelen ser útiles:
Para listar todos los tópicos que están manejando en la instancia de ROS: rostopic list

Para ver la información de un tópico particular: rostopic echo people_detect/found

Para configurar los tópicos activos mediante un utilitario GUI: rosrun rqt_reconfigure rqt_reconfigure


Read More…

Visión Computarizada: Contando Gente con OpenCV, ROS, UP Board y una cámara Real Sense

7 Abr , 2017,
Jose Nunez
, , , ,
No Comments

En artículos anteriores hemos tocado el tema del kit de robótica de Intel con RealSense y UPBoard.

Como seguimiento a las instrucciones de inicio del Up Board les compartimos acá algunos comandos de ROS / LINUX para hacer uso de algunos de los ejemplos para aplicaciones de visión computarizada.


PASO 1 – Paquete OpenCV Apps

El primer paso sería la instalación de un paquete de ROS denominado “opencv_apps” mediante el siguiente procedimiento:

cd /opt
sudo apt-get install ros-kinetic-opencv-apps

PASO 2  – Ejemplo de la aplicación de detección de personas

El paquete OpenCV Apps de ROS contiene archivos de lanzamiento (.launch files) con ejemplos muy concretos sobre aplicaciones de visión computarizada.

Mediante el siguiente comando de ROS, la consola de LINUX se ubica en la ubicación del paquete OpenCV Apps:

roscd opencv_apps

Una vez en este directorio, echaremos un vistazo a la lista de archivos de lanzamiento:

cd launch
ls

El comando ls anterior lista en la consola todos los archivos .launch.

Uno de estos archivos es el denominado “people_detect.launch” el cual contiene las definiciones de ROS (en formato XML) que definen cómo tomar imágenes de una fuente (una cámara por ejemplo) y aplicar los métodos de detección de personas de OpenCV.

Para que este archivo funcione con las cámaras Real Sense, será necesario modificar este archivo “people_detect.launch” de la siguiente manera:

(!) Nota: Este procedimiento será necesario solamente una vez para una misma versión del paquete de ROS OpenCV Apps. Solo será necesario ejecutarlo nuevamente si se actualiza la versión del paquete de ROS OpenCV Apps.

Ejecute el comando gedit para editar el archivo:

sudo gedit people_detect.launch

Ubique las siguientes líneas en el archivo ver (estado inicial) y cámbielas para que luzcan como se especifica en (estado editado)

(estado inicial)

<arg name="image" default="image" doc="The image topic. Should be remapped to the name of the real image topic." />

<arg name="debug_view" default="true" doc="Specify whether the node displays a window to show edge image" />

(estado editado)

<arg name="image" default="camera/color/image_raw" doc="The image topic. Should be remapped to the name of the real image topic." /> 

<arg name="debug_view" default="false" doc="Specify whether the node displays a window to show edge image" />

PASO 3 –  Ejecución del ejemplo ROS para detección de personas

Ejecute los siguientes comandos de consola de manera individual, preferiblemente en una pestaña nueva de terminal (SHIFT CTRL  T)

1. Iniciar el nodo maestro de ROS

roscore &

2. Ubicarse en el directorio de ROS referente a la cámara Real Sense

roscd realsense_camera/

3. Lanzar (ejecutar) el procesador ROS de la cámara Real Sense

* Para una R200 use el siguiente comando: roslaunch realsense_camera r200_nodelet_default.launch &

* Para una SR300 use el siguiente comando: roslaunch realsense_camera sr300_nodelet_default.launch &

4. Ejecutar el procesador ROS para el proceso de detección de personas

roslaunch opencv_apps people_detect.launch

5. Carguemos ahora el visor de imágenes de ROS

rqt_image_view

* Este comando abre una ventana que tiene una caja de selección donde podemos elegir el canal que queremos visualizar.

 

Tips para Impresión 3D con Printbot

4 Mar , 2017,
Jose Nunez
, , , , ,
No Comments

Hace unos meses adquirimos unos Printbot Simplemetal de CRCibernetica.

El servicio que nos brindaron fue realmente excepcional. Parte de el servicio fueron unos tipos que nos enviaron por email, que me han resultado utiles al tratar de imprimir en 3D. Así que he decidido transcribirlos acá.

Aunque es probable que algunas instrucciones no apliquen para las versiones más recientes de Cura o de Printbot, espero que sea de utilidad a muchas otras personas.


Materiales requeridos:

  1. 3M Blue Masking Tape
  2. Alcohol de Fricción
  3. Algodón para aplicar el alcohol

Instrucciones Básicas

  1. Usar la version 15.04 de Cura (NO USAR LA ULTIMA VERSION):
    https://ultimaker.com/en/cura-software/list
  2. Seguir el setup Wizard seleccionando su impresora (Printrbot Metal Simple)
  3. Bajar el Profile “Getting Started.ini” de Printrbot:
    https://printrbot.zendesk.com/hc/en-us/articles/203814574-Getting-Started-Profile
  4. En Cura: File–>Open Profile y seleccionar el archivo “Getting Started.ini”
  5. En Preferences cambiar Printing Window type de “Basic” a “Pronterface UI”
  6. Cambiar Printing temperature(C) de 210 a 195. (Importante)

Cuando imprime, la impresora va a hacer los siguientes pasos:

  1. El “hot end” va a calentar al 195. (dura 1 minuto)
  2. Se va a mover a “Home” usando los switches de limite.
  3. Se va a iniciar el proceso de “Auto-Nivel” y mapear tres puntos en la cama.
  4. Va a empezar a imprimir.
  5. Cuando termina de imprimir se va a mover a “Home”.

Para crear sus propios modelos recomendamos tinkercad.com. Es gratuito y fácil de aprender. También sirve para “sanar” modelos de otras aplicaciones.

El sitio thingiverse.com tiene modelos 3D que se puede bajar.  Yo siempre busco alli antes de crear algo desde cero.

El spool holder que yo estoy utilizando es este:
https://www.youmagine.com/designs/printrbot-simple-filament-spool-holder-no-aluminum-handle

Impresión por SD Card

Si quiere imprimir directamente de un SD Card:

  1. Asegura que su impresora no esta conectada a su PC.
  2. Insierte un sd card en su PC
  3. En Cura, notar que el icono que normalmente apreta para imprimir ahora dice “SD”.
  4. Apreta este boton para copiar el GCode directamente al SD Card.
  5. Cambiar el nombre del archivo en el SD card a “auto0.g”. Asegura que NO tiene la extensión .gcode
  6. Con la impresora apagada insierte el SD Card.
  7. Prende la impresora.
  8. Tarda varios minutos en calentar y comenzar a imprimir. Puede tardar hasta 10 minutos.

El slot del SD Card no esta posicionado muy bien.  Para no tener que usar un alicate yo uso este holder que se puede imprimir usando la impresora: http://www.thingiverse.com/thing:416217

SimpleCV Hello World ++ en otros 5 minutos (Linux MINT 18)

Mar , 2017,
Jose Nunez
, , , , , ,
No Comments

Siguiendo nuestra serie sobre SimpleCV y como una motivación personal para aprender Python. Acá les presento un par de scripts basados en el ejemplo “Hello World” de SimpleCV.

El primero toma constantemente  una foto de una cámara y la “binariza”; es decir, la convierte cada pixel de la foto en negro o blanco dependiendo de su “posición estadística” respecto de los demás pixeles y muestra el resultado en pantalla.

El segundo toma la fotografía original, sin ser “binarizada” y la muestra en pantalla.

Al correr los scripts de manera simultánea podemos apreciar de mejor manera este filtro de binarización de la imagen.


PASO 1 – simplecv_helloworld.py

Usando un editor de texto como “xed” copiamos el siguiente programa y guardamos el archivo como “simplecv_helloworld.py”

from SimpleCV import Camera
# Initialize the camera
cam = Camera()
# Loop to continuously get images
while True:
    # Get Image from camera
    img = cam.getImage()
    img.save('/home/toruk-makto/imageport.jpg')
    # Make image black and white
    img = img.binarize()
    # Draw the text "Hello World" on image
    img.drawText("Hello World!")
    # Show the image
    img.show()

PASO 2 – simplecv_helloworld2.py

De nuevo, mediante el editor de texto copiamos el siguiente programa y guardamos el archivo como “simplecv_helloworld2.py”

from SimpleCV import Image

# Loop to continuously get images
while True:
    # Get Image from camera
    try:
        img = Image('/home/toruk-makto/imageport.jpg')
        # Draw the text "Hello World" on image
        img.drawText("Hello World!")
        # Show the image
        img.show()
    except:
        print "skip!"

PASO 3 – Ejecutar ambos scripts

En una terminal ejecutemos los siguientes dos commandos:



python simplecv_helloworld.py &

python simplecv_helloworld2.py &


Vemos como se muestran ambas imágenes “en tiempo real”

Para detener los scripts podemos digitar el comando fg(que trae el comando al “foreground de ejecución”) y luego usar las teclas CTRL C; o ejecutamos el comando sudo kill #### donde “####” corresponde al número del proceso que queremos detener; o simplemente cerramos la terminal.