jueves, 28 de marzo de 2019

De regreso en la divulgación

La semana pasada y antepasada, di unas charlas sobre comunicaciones por radio en una primaria al sur en Mérida. Use mi dongle de SDR FunCube. Noté que a los niños les llamó bastante la atención el "arcoíris de radio" (como les digo para hacer referencia al espectrograma) y la demodulación del FM qué hago con SDR# en tiempo. No pude controlar a los de 4to mucho tiempo (son los de esta foto) pero los de 6to estuvieron muy tranquilos y entendieron perfectamente bien cómo funciona la modulación digital FSK y ASK. En todos los años que llevo haciendo divulgación científica he visto una y otra vez la capacidad de los niños de entender conceptos complejos si se encuentra la manera adecuada de presentarlos. Me molesta bastante que se les trate como tontos. Afortunadamente me invitaron a un nuevo grupo de difusión científica llena de excelentes personas: Asociación Juvenil de Ciencia Yucatán. He estado en varios grupos de divulgación pero este verdaderamente tiene miembros con un equilibrio perfecto entre entusiasmo y talento. Esto es algo que no digo todos los días (i. e. soy muy mamón a la hora de evaluar proyectos y personas) y aún más curioso considerando sus edades, la mayoría estudiantes de segundo semestre. Llevo poco tiempo conviviendo con los miembros y en sus eventos ya he hecho nuevos amigos muy interesantes. El tipo de amigos que me hubiera gustado tener en mis primer año en Puebla.

martes, 26 de marzo de 2019

Sobre el por qué documentarlo todo

Como a muchos, si no es el caso de la mayoría, odiaba documentar mis proyectos en la universidad hasta que entendí su utilidad. Los problemas, sin importar su tipo, están muy a menudo relacionados unos con otros. Cada problema que resuelves puede significar tiempo ahorrado en un problema futuro. Entre más problemas hayas resuelto, mejores son tus probabilidades de resolver tus siguientes problemas en menor tiempo. Pero esta experiencia no se organiza de forma automática en tu mente (bueno fuera que si). Para aplicar el principio que comento es necesario llevar un registro detallado de tus soluciones. Esta es mi regla: "documenta como si tú yo del futuro fuera a olvidarlo todo". Es decir, no puedes confiar en que el futuro seguirás teniendo en la memoria todos los pequeños detalles que le dieron contexto a tus soluciones. En otras palabras, "date a ti mismo la solución que te hubiera gustado que te cayera del cielo en ese momento". No es necesario ser muy formales en la redacción si es una documentación personal. Tengo varias libretas de "Príncipe Mestizo" llenas de taches y correcciones con lo que funcionó y no funcionó, y este mismo blog es también la versión on-line de mis apuntes. Tan pronto vean los resultados de esto amarán registrarlo todo. Siempre y cuando lo hagan de una manera fácil de consultar cuando sea requerido, les garantizo placeres profesionales. 

lunes, 25 de marzo de 2019

Gráfica de lecturas de un DHT11 en Python

Esta nota corta será para no olvidar como hacer una gráfica en Python de un conjunto de mediciones de temperatura a lo largo del tiempo. El sensor utilizado en un DHT11 (que muy tardé me di cuenta que tenía muy baja resolución y que es mejor el DHT22). Generé un archivo de texto a partir de comunicación serial entre un PIC y una Raspberry Pi dónde cada linea tiene la siguiente estructura:

2019-03-22 23:11:33,22,46
fecha, temperatura, humedad relativa 

Algo muy útilil que aprendí a hacer es trasferir archivos entre un host local y la Raspberry a través de la red con un solo comando de consola. El comando es scp y su sintaxis es la siguiente para copiar del host local a la Raspberry :

$ scp /un/dir/local/archivo usuario@ipremota:/un/dir/remoto/archivo

Y de la Raspberri al host local:

$ scp usuario@ipremota:/un/dir/remoto/archivo /un/dir/local/archivo

Ya con el archivo en mi computadora, utilicé el módulo Pandas para leer el archivo .txt dónde registre cerca de dos dias y medio de datos de temperatura y humedad relativa. Aplique un filtro de mediana con el modulo scipy.signal para quitar los picos abruptos en los datos. Finalmente realice los ajustes necesarios para mostrar únicamente la hora en el eje x. El programa completo es el siguiente:

Gráfica:

martes, 19 de marzo de 2019

CIAA

Hace unos días en un grupo de Facebook me ayudaron con una duda que me tenía intranquilo y no puedo expresar lo agradecido que estoy. Me especialicé en sistemas digitales y comunicaciones y no sé nada de manejo robusto de transientes e interfaces en entorno industrial. Resulta que los benditos argentinos tienen un proyecto de hardware y software abierto de sistemas de cómputo para entornos industriales llamado CIAA (Computadora Industrial Abierta Argentina). Tienen absolutamente todo lo que requería, diagramas de la circuitería de protección, documentación, tesis, pruebas ¡Todo! Esto me ahorra meses enteros de trabajo. Tenía muchas dudas sobre el como implementar circuitos de protección robustos para tarjetas de aplicación de microcontroladores (PIC, AVR, STM32, etc.) aptas para soportar las condiciones de un entrono industrial. Este es el el espíritu del hardware y software abiertos que tanto defiendo: llegar más lejos echándonos la mano entre todos.

lunes, 18 de marzo de 2019

LCD en MPLAB X / XC8

Había comentado en una entrada pasada que las nuevas versiones de XC8 dejaron de usar Peripheral Library y en esa misma entrada explico el truco que pueden hacer para utilizarla. Sin embargo, los usuarios de PIC's modernos deben saber lo cómodo que es usar ahora MCC. Pero también habrán notado que no hay un generador de código para el manejo de LCD's.  Así que he hecho un fork en GitHub de una librería hecha por Manolis Agkopian a la que hecho una mínima modificación para poder usarla en el PIC18F45K50. Pueden acceder a los códigos aquí. Esta librería me parece genial porque te permite usar el puerto que quieras, a diferencia de la mayoría que he visto que te limitan a un puerto fijo (que debes modificar si quieres usar otro). Lo único que deben hacer es agregar los archivos lcd.h y lcd.c a los headers de su proyecto. Como aún hay muchos usuarios del PIC18F4550 voy a poner aquí un ejemplo con él.  Usaré una tarjeta Miuva a 48 MHz: 

martes, 12 de marzo de 2019

Máquina de Estados Finitos en C [PIC18F45K50]

Para esta implementación en software de una máquina de estados finitos (FSM: Finite State Machine) haremos uso de punteros a funciones [click en el enlace para ver un video-tutorial]. Usaremos también  el compilador XC8 en MPLAB X y un PIC18F45K50 con las mismas configuraciones que en la entrada anterior.

En una gran cantidad de problemas a resolver mediante un sistema embebido es necesario llevar a cabo un proceso estrictamente secuencial. En estos casos es muy útil y elegante estructurar nuestros programas como una máquina de estados. Quizá muchos de ustedes estén tentados a usar una estructura case para elegir un segmento de código cuando se cumple una condición. Si el numero de estados es pequeño, quizá se una opción fácil. Desafortunadamente el uso de case's es muy ineficiente cuando la máquina de estados y su tabla de transiciones es muy compleja. La implementación que se mostrará en esta entrada parecerá un tanto rebuscada pero tiene la ventaja de tener buen despeño a la hora de escalarla a numero grande de estados.

El diagrama de estados de la FSM de este ejemplo es el siguiente:
Diagrama hecho en LaTeX con TIKz
Las entradas 0/1 representan los estados de un switch conectado a RB0. Los estados se harán visibles enviando el numero correspondiente al Puerto D [esta acción será definida en la función asociada a cada estado]. Obsérvese que está máquina describe a un contador ascendente o descendente según la entrada. Se agregará un retardo de un segundo para poder visualizar las transiciones.

Movámonos al programa. Primero, debemos definir un tipo enumerado para codificar nuestro conjunto de estados:

//-- Definición de tipo de estados
typedef enum {
    Estado_0,      // Estado inicial
    Estado_1,
    Estado_2,
    Estado_3,
    Estado_4,      
    No_de_Edos
} ESTADOS;

Creamos con esto una variable enumerada global que usaremos para almacenar el estado actual de la máquina:

//-- Variable global de estado
ESTADOS Estado_Actual = Estado_0;

El siguiente paso es definir una estructura que nos permitirá construir un objeto para nuestra FSM:

//-- Estructura de Maquina de Estados (FSM))
typedef struct {
    ESTADOS Estado; // Estado miembro del conjunto enumerado ESTADOS
    void (*func)(int); // Acciones asociadas al estado         
} FSM;

Con lo anterior podemos ahora crear una instancia que sera nuestra FSM:

//-- Prototipos de funciones de estado
void Codigo_EDO_0(int);
void Codigo_EDO_1(int);
void Codigo_EDO_2(int);
void Codigo_EDO_3(int);
void Codigo_EDO_4(int);

//-- Creación de la estructura global de la FSM
FSM Maquina_de_Estados[] = {
    {Estado_0,Codigo_EDO_0},
    {Estado_1,Codigo_EDO_1},
    {Estado_2,Codigo_EDO_2},
    {Estado_3,Codigo_EDO_3},
    {Estado_4,Codigo_EDO_4},
};

Es importante que los prototipos de las funciones asociadas a cada estado aparezcan antes de la creación de la estructura (estas funciones serán definidas más adelante en el código). El segmento de código principal queda reducido elegantemente de la siguiente manera:

void main(void) {
    int sw = 0;
    setup();
   
    //-- FSM ---
    while(1){
        sw = PORTBbits.RB0;
        (*Maquina_de_Estados[Estado_Actual].func)(sw);
    }
    return;
}

Código completo:
Circuito utilizado: