Translate

viernes, 29 de noviembre de 2013

Control de múltiples servos con un único TIMER.



En esta entrada vamos a ver como conectar nuestro microcontrolador con otro dispositivo muy popular, un servomotor. Un servomotor es un motor DC, similar a los usados en las entradas que dedicamos al control de motores. Sin embargo, al contrario que los motores que manejamos allí, los servomotores incluyen su propio hardware de control, por lo que no tendremos que preocuparnos de esa parte.
En la primera parte de esta entrada describiremos los fundamentos de cómo controlar un servo con un microcontrolador, con una mínima sobrecarga para el PIC mediante el uso de un timer y sus interrupción asociada.

En la segunda parte extenderemos este enfoque para el caso de que necesitemos controlar muchos servos con un único PIC. Veremos como podemos controlar hasta 8/10 servos dedicando sólo un TIMER del microcontrolador.

Archivos de código asociados a esta entrada:  servo_calib.c  y  servo_n.c

--------------------------------------------------------------------------------------

lunes, 30 de septiembre de 2013

Monitor del ritmo cardíaco

Vamos a volver a usar el sensor de luz TSL235 en una aplicación más interesante: monitorizar nuestro ritmo cardíaco.  ¿Cómo hacerlo con un sensor de luz? 

La idea viene explicada en una "application note" dedicada a estos sensores:


La configuración propuesta se muestra en la imagen adjunta. Un LED (u otra fuente de luz) ilumina un dedo, detrás del cuál se encuentra nuestro sensor. A cada pulsación del corazón, un nuevo flujo de sangre llega al dedo, cambiando su "opacidad" a la luz. El objetivo es detectar dichas oscilaciones, determinar su frecuencia fundamental y a partir de ahí el ritmo cardíaco en pulsaciones por minuto (ppm).

En la aplicación citada antes, el microcontrolador solo recoge los datos del sensor y los manda al PC para su proceso. La principal mejora de mi proyecto es que el PIC no sólo captura la señal, sino que la procesa y obtiene el ritmo cardíaco. De esta forma tenemos un sistema autónomo.

Al igual que en otras entradas el código del PIC se complementa con un programa MATLAB que nos permite ver gráficamente los datos sobre los que trabajamos y los resultados obtenidos. Recalcar que el programa MATLAB sólo visualiza los datos: todos los cálculos se llevan a cabo en el PIC.

En este corto video podemos visualizar los datos obtenidos tras un pre-proceso de los datos del sensor. Es sobre esta señal sobre la que el PIC trabaja para estima su periodo:



Archivos de código asociados a esta entrada:

     PIC:   pulse_monitor2.c  

     MATLAB: heart_monitor.m


miércoles, 28 de agosto de 2013

Vuelta de vacaciones

 He vuelto hoy de vacaciones y me he encontrado con un montón de comentarios nuevos. Desde mi perspectiva norte-céntrica pensaba que agosto sería un mes muy tranquilo, pero veo que no.

Intentare ponerme al día en los próximos días.

   Un saludo,  Antonio.

miércoles, 3 de julio de 2013

Aplicación modo CAPTURA: sensor TSL235

En la entrada anterior describimos la funcionalidad del modo Captura del módulo CCP. En esta entrada usaremos dicha funcionalidad en una sencilla aplicación.  

Vamos a usar el sensor TSL235, que es un medidor de intensidad de luz. Al contrario que otros sensores, cuya salida es un voltaje proporcional a la irradianza recibida,  la salida de este sensor es una onda cuadrada, cuya frecuencia es proporcional a la magnitud (luz) medida. 

Usando el módulo de CAPTURA mediremos el periodo de los pulsos emitidos. A partir de dicho periodo será sencillo deducir su frecuencia y de ahí la irradianza (en W/m2) recibida.

Como en entradas anteriores, los datos recibidos se mandan al puerto serie del PC donde usamos un programa MATLAB para ver los resultados.

Archivos de código asociados a esta entrada:  

  Código para PIC      tls235.c  

  Programa MATLAB    flicker.m  



--------------------------------------------------------------------------------------------

Modo de Captura en el módulo CCP

En una entrada anterior (PWM) vimos una de las funcionalidades del módulo CCP. En esta entrada describiremos otra de sus funcionalidades, el modo CAPTURE.

Como su nombre indica, este modo se usa para capturar eventos. Los eventos serán bajadas o subidas de los pines correspondientes a CCP1 y CCP2 que son, respectivamente, RC2 y RC1 (este último puede cambiarse por RB3 en la configuración inicial).  Para la captura se precisa que un timer este corriendo. Este timer será nuestro "reloj": capturar un evento será grabar la "hora" (contador del timer) en que se ha producido. Los timers usados con el módulo de CAPTURA pueden ser tanto el TMR1 como el TMR3.

Podríamos conseguir similares resultados usando las interrupciones INTx que vimos en los codificadores en cuadratura. Cada vez que entre la interrupción podríamos guardar el valor de un timer que este corriendo. La diferencia es que con este enfoque, para cuando "miremos la hora" ya habrá pasado un tiempo (mientras el micro termina lo que esté haciendo, pasa el control a la interrupción, etc.) que puede ser del orden de microsegundos.

Por el contrario, si se usa el método de captura, en cuanto se produce el evento se copia el valor del timer usado a los registros CCPRxH:CCPRxL. Por supuesto, será nuestra responsabilidad guardar dicho valor en otra variable antes de que se repita el evento y se machaque con otro valor.

En la entrada explicaremos la configuración del modo de CAPTURA y los registros asociados. En la siguiente entrada usaremos el modo de CAPTURA para leer los datos de un sensor de luz (TSL235) cuya salida en una onda cuadrada de frecuencia variable. 

--------------------------------------------------------------------------------------------

viernes, 7 de junio de 2013

Proyecto: Medidor de potencia

En este proyecto vamos a construir un medidor de potencia, un dispositivo que monitoriza la potencia (de la que se puede deducir fácilmente el consumo) de un electrodoméstico o cualquier otro aparato conectado a la red.

Para obtener la potencia consumida tendremos que monitorizar (muestrear) la intensidad y el voltaje de la red. Como siempre que manipulemos la red, debemos ser muy cuidadosos con nuestros montajes. Existen varias formas de monitorizar el voltaje e intensidad de la red. En este montaje he escogido la que me ha parecido más segura: un montaje en el que existe un aislamiento galvánico entre la red y las señales que el micro monitoriza.

Una vez que tenemos las medidas de intensidad y voltaje a lo largo de un ciclo de trabajo (20 milisegundos si nuestra red va a 50 Hz) es muy sencillo para el micro estimar valores como la intensidad RMS, potencia RMS y potencia real consumida y volcar los resultados por el puerto serie o (si queremos un sistema más autónomo) presentarlos en un LCD.

Como en proyectos anteriores, se adjunta un programa MATLAB para visualizar los datos capturados (intensidad, potencia instantánea, etc.) a lo largo de un ciclo, permitiéndonos ver gráficamente aspectos como el desfase entre Intensidad y Voltaje, forma de onda de la intensidad, etc.  En el video adjunto se muestran los resultados para el caso de una pequeña batidora, mientras cambiamos su velocidad, ponemos el "turbo", etc:


Código asociado:  power_meter.c  (código PIC)
                         18f4520_g.lkr    (linker script modificado) 
                         power_meter.m (programa MATLAB de interfaz con el PC).  


martes, 4 de junio de 2013

Formateo de números en coma flotante

Como comentamos en la entrada anterior, la función sprintf (y sus variantes) del compilador C18 no tienen soporte para volcar datos de tipo float en coma flotante (modificador %f en ANSI C). La posible razón es que interpretar y volcar números en coma flotante no es trivial, por lo que el código necesario es relativamente grande. La función sprintf ya ocupa bastante código (alrededor de 2K word) y si incluyese soporte para números reales su tamaño posiblemente se doblaría. Al ser una función monolítica, dicho coste adicional lo sufrirían incluso aquellos usuarios que nunca trabajasen con números en coma flotante.


En esta entrada vamos a describir la representación de números en coma flotante dentro del PIC para entender como se guarda la información. A partir de ahí crearemos un par de rutinas que nos permitan volcar este tipo de datos a una cadena.

El objetivo es poder sacar datos por el LCD o puerto serie con los formatos mostrados en la figura adjunta, que corresponden a %e (izquierda) y %f (derecha) del printf definido en ANSI C.



Código asociado a esta entrada: float2ascii.c 

lunes, 3 de junio de 2013

Formateo de datos (para LCD o puerto serie)

En muchos momentos (presentación de resultados, debug) tendremos que visualizar valores de la variables de nuestro programa por el LCD, puerto serie o equivalente. Ello conlleva convertir los datos numéricos en cadenas de texto mostrando sus contenidos, bien sea en formato binario, hexadecimal, decimal, etc.

El compilador C18 (y otros basados en ANSI C) ya cuentan con una forma rápida y versatil de hacer dicha conversión: con las rutinas tipo printf, sprintf o equivalentes.

Estas funciones son muy flexibles y convenientes pero como veremos pueden ser lentas y ocupar bastante espacio. Son ideales por su conveniencia en las primeras fases de un desarrollo. Sin embargo, si la  aplicación se va complicando y nos acercamos a los límites del micro usado podemos encontrarnos con que ocupan demasiada memoria de programa y/o van demasiado lentas.

En esta entrada replicaremos la funcionalidad de sprintf de forma modular. Escribiremos varias rutinas para volcar diferentes datos enteros con varios formatos (binario, hexadecimal, decimal con o sin signo, etc). Estas funciones, al preocuparse de un solo argumento y tipo de formato van a ser mucho más pequeñas y rápidas que sprintf. Además, muchas veces, dentro de una aplicación, solo trabajaremos con un cierto tipo de datos, por lo que este tipo de rutinas pueden ahorrarnos bastante código.

En una entrada posterior trataremos el tema de la presentación de datos tipo float, del que carecemos por defecto en C18.

Código asociado a esta entrada: int2ascii.c 


viernes, 12 de abril de 2013

Tarjetas SD/SDHC (lectura/escritura de datos)


Tras aprender como inicializar una tarjeta SD y obtener información sobre su capacidad, etc, es hora de usarlas para lo que sirven: leer/escribir información.

En esta entrada completaremos nuestra introducción a las comunicaciones de bajo nivel entre un PIC y una tarjeta SD viendo las lecturas/escrituras a los sectores de datos de la tarjeta.  

Como siempre haremos algunos comentarios sobre como optimizar las rutinas para maximizar la velocidad de transferencia de datos.

Recordar que las rutinas que vamos a usar son de bajo nivel, escribiendo directamente sobre los sectores de la tarjeta. No saben nada del tipo de formato, sistema de archivos, etc, por lo que pueden destruir datos en la tarjeta que usemos. He escogido un número alto de sector (5000) para empezar a escribir por lo que posiblemente no estropearán el formato de la tarjeta pero si machacarán los datos de dichos sectores. No obstante, incluso si se estropea el formato siempre se puede volver a reformatear la tarjeta en el PC sin ningún problema. Obviamente debéis que evitar hacer pruebas con una tarjeta con datos de interés. 

Para verificar que las cosas están funcionando es útil contar con un lector de tarjetas para el PC y un software (tipo WINHEX o similar) que permita editar los sectores lógicos de un disco para ver si nuestros programas escriben lo que queremos y donde queremos. 



Código asociado a esta entrada: SPI_sdhc_v2.c18f4520_g.lkr

martes, 9 de abril de 2013

Tarjetas SDSC/SDHC (inicialización y lectura de registros)


Como un ejemplo un poco más complicado (pero muy útil) del uso del protocolo SPI veremos en más detalle el uso de tarjetas de memoria flash en su formato SD (SecureDigital). Entre las posibilidades de comunicación que ofrecen dichas tarjetas está un modo SPI. Este modo, aunque más lento que el modo SD nativo, es más sencillo de implementar.

En este tutorial nos centraremos en las conexiones hardware, la inicialización de la tarjeta (tanto para tarjetas SD standard como para las SDHC de alta capacidad), y la obtención de las características de la tarjeta (capacidad, número de sectores, número de serie, etc.) a través de sus registros CSD y CID.

El objetivo es conseguir el volcado de información que aparece a la derecha



En una entrada posterior veremos como leer/escribir datos en la tarjeta, considerando como optimizar dicha transferencia de datos. 


Código asociado a esta entrada: SPI_sdhc.c

lunes, 8 de abril de 2013

INTERFAZ SPI con memoria flash (M25P80)


Las memorias flash es un tipo de memoria electrónica no volátil, derivada de las EEPROM, que que puede ser borrada y reprogramada electrónicamente (http://en.wikipedia.org/wiki/Flash_memory). El tipo más común de memoria flash es el tipo NAND que es la base de las tarjetas de memoria,  USB oendrives y discos de estado sólido. Al contrario que una memoria EEPROM las memorias flash de tipo NAND pueden ser escritas o borradas en bloques más pequeños que todo el dispositivo (aunque mayores que los bytes individuales).  En todos estos casos la memoria va acompañada de un controlador que hace invisible el manejo a bajo nivel de la memoria. El usuario se reduce a escribir/leer sectores lógicos. En esta entrada vamos a escribir algunas rutinas para conectar una memoria flash (M25P80, 1 Mbyte) con un PIC usando una comunicación SPI. Al contrario que en los casos citados antes vamos a manejar directamente los sectores físicos de la memoria, por lo que además de los aspectos de la comunicación SPI aprenderemos también algunas peculiaridades de este tipo de memorias. 

Para nuestro desarrollo usaremos una breakboard (de MikroElektronica, figura adjunta, unos $10) que nos evita tener que soldar y nos da los pines correctamente espaciados y etiquetados.  Podemos ver la alimentación (3.3V) y GND, así como las conexiones SPI (~CS, SCK, MISO, MOSI). El único pin (que no usaremos) no identificable es ~HOLD (que permite dejar en suspenso una comunicación. El IC tiene un pin adicional ~WP (Write Protection) que permite implementar una protección hardware de los datos. En esta tarjeta está atado a 3.3V por lo que la tarjeta está "desprotegida" a nivel hardware (aunque es posible implementar protección parcial o total de datos a través del software). 

Código asociado a esta entrada: spi_flask.c

viernes, 5 de abril de 2013

Comunicaciones Serie SPI

La familia PIC18 dispone de varias posibilidades de comunicaciones serie. Además del puerto USART que ya describimos, dispone de un puerto dedicado a comunicaciones síncronas serie, el SSP (Serial Synchronous Port). Dicho puerto puede dedicarse a varios protocolos, tales como SPI o I2C. Ambos son excluyentes, esto es, si se configura el periférico para SPI no podrá usarse para I2C y viceversa. Si se precisan de forma conjunta comunicaciones I2C y SPI la única solución es un microcontrolador con dos puertos SSP o bien, implementar algunos de los dos protocolos a través de software.


En este tutorial vamos a examinar en el protocolo SPI (Serial Protocol Interface), describiendo los registros SFR involucrados y detallando los procedimientos para transmitir y recibir.  Lo ilustraremos con un ejemplo muy sencillo de comunicación  con un periférico SPI, un conversor DAC (MCP4822 de Microchip).

En entradas posteriores veremos ejemplos de comunicaciones SPI con otros periféricos con protocolos de comunicación más complicados.

Archivos de código asociados a esta entrada:  spi_mcp4822.c

miércoles, 20 de febrero de 2013

Proyecto: Levitador magnético

En este proyecto escribiremos un programa para el PIC que mantenga un imán suspendido en el aire. El PIC controlará la bobina de un electroimán a través de un L293D. Bajo este electroimán colocaremos un imán. En ausencia de corriente el imán siente dos fuerzas: la gravedad hacia abajo y la atracción magnética con el núcleo (un tornillo) del electroimán. 

Existe un punto donde ambas fuerzas están equilibradas. Desgraciadamente dicho punto es inestable. Si el imán se aparta un poco de la bobina la atracción magnética disminuye y el peso gana la partida: el imán cae. Si el imán se acercara un poco a la bobina, la atracción imán-tornillo es cada vez más fuerte, por lo que terminará pegándose arriba.  La idea es colocar un sensor de flujo magnético justo debajo de la bobina. Usando este sensor el PIC puede detectar la posición del imán y actuar en consecuencia: si el imán empieza a caerse, hacemos pasar la corriente por el electroimán de forma que atraiga un poco al imán y éste se recupere. Si se acerca, activamos la bobina en sentido contrario para rechazar el imán y volverlo a llevar a la posición ideal de equilibrio.

Podéis encontrar en internet bastantes variantes de este esquema, aunque la mayoría de ellas no usan un microcontrolador sino un integrado (MIC502) originalmente diseñado para modificar la velocidad de un ventilador (mediante PWM) en función de la temperatura de un sensor. La ventaja de un enfoque con un microcontrolador es que tenemos muchas más posibilidades de control (podríamos p.e. hacer oscilar a voluntad el imán). En este proyecto nos limitaremos a construir el programa básico. 

El objetivo del proyecto es lograr algo parecido a lo mostrado en este corto video:



Al igual que en las entradas correspondientes a control de motores acompañamos el código del PIC con un código MATLAB para visualizar los resultados y jugar con los parámetros de control. 

Código asociado:  maglev_4520.c  (código PIC)
                         maglev.m (programa MATLAB de interfaz con el PC).  
Fichero hex:        maglev_4520.hex 

viernes, 1 de febrero de 2013

Controlador PID para posición de un motor DC

En el tema anterior construimos una gráficas mostrando la relación entre el input (% PWM) aplicado y el resultado (velocidad) obtenido por el motor. Podríamos usar esa información para controlar nuestro motor. Si queremos que gire con una cierta velocidad, podríamos ver que entrada (PWM) precisamos y aplicarla. Sin embargo ya comentamos que dicha relación cambia por numerosos factores, por lo que nunca estaríamos seguros de alcanzar la velocidad deseada.

Técnicamente esta situación se conoce como un control de bucle abierto, al no tener un feedback que nos informe de lo que realmente está haciendo el motor. De hecho disponemos de dicho feedback (la info de los encoders en cuadratura) pero hasta ahora no la estamos usando.

En esta entrada vamos a "cerrar" el bucle, usando el feedback de que disponemos para controlar la posición de un  motor. La entrada suministrada por el usuario no será un PWM (de efectos inciertos) sino un objetivo en términos de la velocidad o posición deseada del motor. El sistema, en función del feedback recibido, variará adecuadamente su variable de control (en este caso el ciclo ON del PWM) para conseguir el objetivo dado. Usaremos un sencillo controlador PID para la implementación.

Al igual que en el tema anterior, acompañaremos al código en C del microcontrolador con un programa en MATLAB para poder mostrar de forma gráfica los movimientos del motor.



Archivos de código asociado a esta entrada: 
          PID_pos.c  monitor_PID.m (MATLAB)


Manejo de motores DC usando PWM

En este tema usaremos nuestros conocimientos del PWM del PIC para guiar un motor de corriente continua (DC). En esta primera entrada simplemente aplicaremos un PWM con un duty variable al motor y observaremos su respuesta (velocidad) usando los codificadores en cuadratura explicados en la entrada anterior.

Obviamente el PIC no puede proporcionar la intensidad necesaria para mover un motor, por lo que necesitaremos algún tipo de driver o interfaz. Para poder manejarlo en las dos direcciones usaremos un driver configurado como un puente en H (H-bridge). Describiremos el popular integrado (aunque no especialmente eficaz) L293D. Otras alternativas basadas en MOSFETs son más eficientes, pero el concepto y la forma de controlar el MOTOR serán comunes.

Ficheros de código asociados a esta entrada:  quad_pwm.c , auto_pwm.c , auto_pwm.m

Codificadores en cuadratura


Tras un largo paréntesis impuesto por el trabajo, retomo el blog. En las siguientes entradas vamos a aplicar la salida PWM del micro a un motor DC con capacidad para manejarlo en ambas direcciones.  Nuestro objetivo final será escribir un código de control para hacer que el motor alcance una posición dada y se detenga o se mueva con velocidad constante.  Para ello necesitaremos algún tipo de información sobre la posición del motor y su velocidad. La forma más común de obtener dicha información es a través de codificadores en cuadratura. 

En esta entrada describiremos su concepto y los diferentes modos en los que podemos monitorizarlos (1X, 2X, 4X).


Archivos de código asociado a esta entrada:   quad1.c