huborarduino.com

La web de Hubor para la simulación de Arduino con Proteus

Banner Guia Programacion Arduino Con Proteus

[Proteus versión 8.1]

Hasta ahora el curso se ha centrado más en la utilización de nuestro Arduino y la serie de componentes que giran a su alrededor. Pero en esta ocasión hemos querido dedicar esta lección a un concepto puramente de sotware: las operaciones matemáticas. El uso de operadores matemáticos y de funciones matemáticas es una tema fundamental en la mayoría de los proyectos desarrollados con Arduino porque son los que nos posibilitan la realización de los diferentes cálculos necesarios para llevar a buen fin nuestro proyecto.

Los lectores que estén familiaraizados con la programación en C o C++ podrán comprobar que los operadores y las funciones matemáticas son iguales que los que se utilizan en estos lenguajes de programación. Como suele ser habitual en el tratamiento de este tema en todos los libros de texto, vamos a estudiar los operadores matemáticos agrupados por familias básicas. Para poder practicar con su uso vamos a realizar el siguiente montaje, dónde simplemente se utiliza un terminal para poder presentar por pantalla los valores resultantes de nuestras operaciones.

Lec14 001

Operadores suma, resta, multiplicación y división.

Sirven para realizar las cuatro operaciones fundamentales y se utilizan los operadores universales para estas operaciones +, -,* y /. Para comprobar su funcionamiento vamos a utilizar el siguiente programa muy sencillo que nos muestra su uso.

Lec14 002

Hemos utilizado la función setup() en lugar de la habitual loop() para que las operaciones no se estén realizando de forma continua. El resultado de compilar y ejecutar nuestro programa es el mostrado en la imagen siguiente, donde se pueden ver el resultado de las cuatro operaciones matemáticas básicas.

Lec14 003

Podemos utilizar paréntesis para indicar qué operaciones se deben llevar a cabo con anterioridad a otras.

Lec14 004

Operadores Incrementadores y Decrementadores.

Los operadores para incrementar o decrementar el valor de una variables son += y -=. Su uso equivale a las siguientes sumas y restas:

resultado += 5  --> resultado = resultado + 5

resultado -=3  --> resultado = resultado - 3.

Su utilización se muestra en el siguiente ejemplo.

Lec14 005

También se pueden utilizar los operadores para incrementar y decrementar una variable un número 'n' de veces. Es decir usar los operadores *= y /= para multiplicar o dividir una variable por un número. El equivalente con los productos y divisiones sería:

resultado *=5 --> resultado = resultado * 5

resultado /= 3  --> resultado = resultado / 3

Un código que utiliza estos operadores sería:

Lec14 006

Para terminar esta sección, veremos los operadores ++ y --. Sirven para incremetar o decrementar una unidad el valor de la variable. El equivalente con las sumas y restas serían:

resultado++ ---> resultado = resultado + 1

resultado-- ---> resultado = resultado - 1

Un programa de ejemplo sería:

Lec14 007

Operador Resto de una división.

El operador resto (%) nos proporciona el resto resultante de dividir dos números. El ejemplo de utilización se muestra en la siguiente imagen.

Lec14 008

En este caso el resto es 0.

Lec14 009

Y en este caso el resto es 1.

Un sencillo ejemplo de utilización sería el siguiente código que comprueba si un número es par o impar.

Lec14 010

Función valor absoluto.

Para calcular el valor absoluto de una variable podemos utilizar la función abs( <operando> ) que nos devulve una variable de tipo entero que se corresponde con el valor absoluto del operando. El ejemplo de uso se muestra a continuación.

Lec14 011

El resultado devuelto será 15. Es importante caer en la cuenta que en la programación de Arduino se utiliza el punto '.' como separador decimal y no la coma ','.

Función potencia.

Para calcular el resultado de elevar un determinado número x a una potencia y, la función que tenemos que utlizar es pow( <base> , <exponente>). Su uso se muestra en el siguiente código.

Lec14 012

Para calcular la raiz cuadrada de un número utilizaremos la función sqrt( <operando>).

Lec14 013

Números decimales y varibles tipo float.

Hasta ahora hemos utilizado números enteros en todos nuestros ejemplos. Sin embargo, es muy habitual que los cálculos matemáticos den como resultados números decimales y no enteros. Para manejarlos, Arduino nos permite utilizar dos tipos de variables: float y double. En Arduino se mantienen los dos tipos por compatibilidad con C y C++, pero es importante tener en cuenta que no hay diferencia entre ambos. Los dos permiten utilizar números decimales entre el intervalo 3.4028235e+38 y -3.4028235e+38.

En informática, para gestionar números decimales utilizamos la técnica denominada de punto flotante. La razón de ello es que la memoria limitada de nuestros equipos no nos permiten guardar una gran cantidad de números con la precisión necesaria para almacenarlos con todas sus cifras decimales. Por ello, se recurre a la mencionada técnica que consiste en descomponer el número en dos partes y almacenarlas juntas. Por un lado se almacena la mantisa (también llamada coeficiente o significando) que contiene los dígitos del número. Mantisas negativas representan números negativos. Por otro lado se almacena el exponente que indica dónde se coloca el punto decimal (o binario) en relación al inicio de la mantisa. Exponentes negativos representan números menores que uno. Este formato cumple las siguientes exigencias:

  • Puede representar números de órdenes de magnitud enormemente dispares (limitados a la longitud del exponente).
  • Proporciona la misma precisión relativa para todos los órdenes (limitadoa a la longitud de la mantisa).
  • Permite cálculos entre magnitudes: multiplicar un número muy grande y uno muy pequeño conserva la precisión de ambos en el resultado.

Los números de coma flotante normalmente se expresan en notación científica con un punto explícito siempre entre el primer y el segundo dígitos. El exponente o bien se escribe explícitamente incluyendo la base, o se usa una e (indiferentemente en mayúsculas o minúsculas) para separarlo de la mantisa. Ejemplos de uso son:

El número float escrito 10.0 equivale a 10

El número float escrito 10.324 equivale a 10,324

El número float escrito 2.34E5  equivale a 2.34 * 10^5  y su valor es 234000

El número float escrito 67e-12  equivale a 67.0 * 10^-12  y su valor es 0.000000000067

El número float escrito 3.45e-5 equivale a 3.45 * 10^-5 y su valor es 0.0000345

Es importante tener en cuenta las siguientes limitaciones en el uso de números de coma flotante:

  • Los float tienen una precisión de 6 o 7 dígitos decimales. Esto significa el número total de dígitos, no el número a la derecha de la coma decimal. Al contrario que en otras plataformas, donde tu podrías obtener mayor precisión usando una variable tipo double (por ejemplo, por encima de 15 dígitos), en Arduino los double tienen el mismo tamaño que los float.
  • Los números en coma flotante no son exactos, y muchos proporcionan falsos resultados cuando son comparados. Por ejemplo, 6.0 / 3.0 puede no ser igual a 2.0. Debes comprobar que el valor absoluto de la diferencia entre los números pertenezca a un rango pequeño.
  • La matemática en coma flotante es mucho más lenta que la matemática de enteros para realizar operaciones, por lo que deberías evitarla si, por ejemplo, un bucle tiene que ejecutarse a la máxima velocidad para funciones con temporizaciones precisas. Los programadores normalmente suelen asignar unas longitudes para convertir las operaciones de coma flotante en cálculos con enteros, para aumentar la velocidad.

Es importante dedicar un tiempo a estudiar y practicar el uso correcto de los números en coma flotante (float) porque tiene singularidades, como acabamos de ver, que conviene tener en cuenta.

Además, es importante tener en cuenta que cuando utilizamos las funciones print o println para mostrar una variable de tipo float, hay que utilizar la siguiente sintaxis para no ver truncados los valores decimales, porque por defecto print y println sólo muestran dos posiciones decimales. Un ejemplo nos ayudará a entender la diferencia.

Lec14 014

Lec14 015

funciones trigonométricas.

Las funciones trigonométricas básicas se pueden calcular utilizando las funciones sin( <angulo> ), cos(<angulo> ) y tan( <angulo> ). Con ellas podemos calcular el seno, el coseno y la tangente de un ángulo dado. Es importante tener en cuenta que las tres funciones esperan que el ángulo se exprese en radianes. El radián es la unidad de ángulo plano en el Sistema Internacional de Unidades. Representa el ángulo central en una circunferencia y abarca un arco cuya longitud es igual a la del radio. Por tanto, el ángulo completo de una circunferencia de radio r, medido en radianes es 2Π radianes.

Lec14 016

Si preferimos pasar el ángulo expresado en grados sexagesimales, podemos convertirlos facilmente utilizando la constante DEG_TO_RAD definida por defecto cuando utilizamos el sistema de desarrollo de ARDUINO. El siguiente programa nos facilita la conversión de grados sexagesimales a radianes de todos los valores comprendidos entre 0º y 360º en saltos de 5 en 5.

Lec14 019

El resultado en el terminal será:

Lec14 020

Veamos ahora un ejemplo de utilización de las funciones vistas para calcular el seno, el coseno y la tangente de 45º. Observe que utilizamos la función println con la cláusula DEC para no truncar los números decimales.

Lec14 017

El resultado obtenido en el terminal virtual debe ser:

Lec14 018

Con lo visto en esta lección, el lector ya está en disposición de enfrentarse con aquellos proyectos que necesitan realizar cálculos matemáticos.

 

 

[Proteus versión 8.1]

Antes de empezar con esta nueva lección, vamos a facilitar la solución a los problemas que planteamos en la anterior. El profesor German Tojeiro ha sido tan amable de hacernos llegar un vídeo donde ofrece una solución original y muy interesante. Utiliza una librería disponible de forma gratuita en la red para el control del dispositivo DS1621. La solución la podemos encontrar en su blog utilizando el siguiente enlace: http://arduinorastman.blogspot.com.es/2014/04/utilizacion-del-sensor-de-temperatura.html. Los que quieran, pueden acceder directamente al vídeo donde se muestra en vivo toda la elaboración del proyecto acudiendo directamente a youtube con el siguiente enlace: http://www.youtube.com/watch?v=wLyWQK3_CvY&feature=youtu.be.

Ahora ya estamos en condiciones de pasar a la lección de hoy. Nos vamos a ocupar de controlar desde nuestro Arduino un motor de corriente continua (normalemente nos referimos a él utilizando la siglas DC). El motor DC es una máquina capaz de convertir la energía eléctrica en mecánica provocando un movimiento rotatorio.

Lec12 001

Su funcionamiento interno es sencillo y puede consultarse en diversas páginas de internet. Por ejemplo, podemos visitar la entrada disponible en wikipedia en el siguiente enlace: http://es.wikipedia.org/wiki/Motor_de_corriente_continua.

Leccion12 002

A todos aquellos que les guste la electrónica y hayan desmontado alguna vez algún dispositivo para ver qué hay por dentro, seguro que se han encontrado en muchas ocasiones con un motor de este tipo. Dentro de una unidad de disquetes, de un DVD, de un coche de juguete, de un ventilador manual, etc, hay un motor DC que genera el movimiento de las piezas móviles. Para ponerlo en marcha, la operativa es muy sencilla. Este tipo de motores tiene dos polos donde debemos conectar la alimentación. Si alimentamos con la tensión nominal (siempre con corriente contínua) al motor empieza a girar. Y aquí empieza una de las características más interesantes de este tipo de motores que los hace tan útiles para usarlos en nuestros diseños. Si bajamos la tensión de alimentación el motor girará más despacio y si intercambiamos la polaridad girará en sentido contrario. Como modificar la tensión y cambiar la polaridad son operaciones muy sencillas de implementar en nuestro diseño, las posibilidades que nos brinda este dispositivo son enormes y con muy poco esfuerzo.

Proteus nos permite simular el funcionamiento de este tipo de motores, utilizando el dispositivo MOTOR.

Lec12 003

Vamos a ver cómo funciona para sacarle el máximo rendimiento a nuestra simulación. Colocamos un dispositivo motor en nuestro montaje de la siguiente forma.

Lec12 004

Y ahora sólo tenemos que arrancar la simulación, para observar el movimiento (en esta página la imagen aparece congelada en un momento dado, pero si está usted siguiendo la lección con Proteus, podrá ver el efecto del movimiento).

Lec12 005

Solo nos resta configurar adecuadamente nuestro modelo de motor para que la simulación sea más consistente. Para ello, nos pondremos sobre el icono del motor, pulsaremos el botón derecho del ratón y editaremos sus propiedades. En la ventana resultante podemos seleccionar la tensión nominal de nuestro motor (muy importante), el número de revoluciones con las que va a girar (ojo, estamos hablando de la simulación y poner velocidades muy altas cargará mucho la cpu de nuestro ordenador de forma totalmente innecesaria) y la resistencia interna.

Lec12 006

Si probamos a cambiar la alimentación intercambiando los +5V y el GND, podemos comprobar que el motor gira en el sentido contrario. Si cambiamos el potencial VDD (recuerde que son +5V) y lo fijamos a valores de +4V, +3V, +2V y +1V, podremos observar que el motor gira a menor velocidad. Como es lógico, si ponemos un 0V el motor se detendrá. Con esto, ya sabemos todo lo necesario sobre nuestro motor de corriente continua y estamos en disposición de comenzar a controlarlo con nuestro ARDUINO.

En muchas webs y libros sobre ARDUINO encontraréis explicaciones de cómo controlar el motor DC directamente desde nuestro equipo ARDUINO utilizando una salida del tipo PWM que vimos en nuestra lección 6. Este sistema es perfectamente válido y controlaremos la velocidad de nuestro motor aumentando o disminuyendo el pulso de modulación. Pero, sin duda, el lector que siga nuestro curso será, a estas alturas, capaz de hacerlo por sí mismo siguiendo los pasos mencionados en aquella lección. Por ello, en esta ocasión vamos a utilizar un método alternativo y vamos a utilizar el driver para el control de motores L293D. Este chip (de coste muy reducido inferior a los 3€) nos permite controlar motores de DC (cuatro de forma unidireccional o dos de forma bidireccional) utlizando una técnica denominada puente en H. Utilizándolo lograremos controlar motores de mayor consumo y de tensiones diferentes a las que podríamos utilizar utilizando nuestro ARDUINO para controlar el motor de forma directa. En el siguiente enlace podemos encontrar toda la información técnica de este integrado: http://www.ti.com/lit/ds/symlink/l293d.pdf.

Lec12 007

Proteus incluye el modelo para poder simular el funcionamiento de nuestro driver L293D. Así que vamos a realizar el siguiente montaje para realizar nuestra práctica.

Lec12 008

Cómo se puede observar hemos conectado nuestro motor a la salidas OUT1 y OUT2 del L293D (porque lo vamos a utilzar de forma bidireccional). La alimentación del motor, en este caso, la estamos haciendo con el mismo potencial VDD aplicándolo al pin 8. Las entradas para gobernar la velocidad y el sentido de giro de nuestro motor (IN1 e IN1) del L293D las hemos conectados a las salidas IO11 e IO10 de nuestro Arduino. Además hemos conectado un led a la salida IO0 de nuestro Arduino por motivos pedagógicos para facilitar la interpretación al lector de la fase de nuestro programa en la que nos encontramos.

El código de nuestro programa es el siguiente.

Lec12 009

El programa empieza con las declaraciones y configuraciones, según es habitual. La lógica de funcionamiento es la siguiente. Encendemos el led y ponemos el pin IO11 a cero, mientras vamos aumentando el valor del pulso de modulación de la salida PWM sobre el pin IO10 progresivamente desde 0 a 255 en saltos de 5 en 5. De esta manera el motor girará en un sentido cada vez a mayor velocidad. A continuación apagamos el led y vamos disminuyendo el pulso de modulación de forma progresiva hasta detener el motor. Más tarde repetimos la operación pero invirtiendo los pines. En este caso ponemos a cero el pin IO10 y aumentamos y disminuimos el pulso de modulación sobre el pin IO11 con lo que logramos que el motor acelere y luego disminuya su velocidad pero, esta vez, en sentido contrario de giro.

Esperamos que esta lección os haya resultado útil. Seguro que encontráis muchas aplicaciones prácticas al uso de motores DC en vuestros diseños.

Para los que quieran comprobar sus conocimientos, proponemos usar nuestro ARDUINO y dos drivers L293D para controlar una grua. Con uno de los motores podemos desplazar el brazo de nuestra grúa en sentido horario y antihorario. Con el segundo podemos deslizar el carretón desde el centro hasta el extremo. Y con el tercer motor podemos subir y bajar la carga.

Por supuesto, tendremos que utilizar seis entradas digitales para implementar una botonera de mando para gobernar nuestra grúa en los dos sentidos posibles por cada uno de los tres movimientos disponibles. Además, si queremos perfeccionar nuestro trabajo, utilizaremos varias entradas digitales para controlar finales de carrera que nos avisen cuando llegamos al tope del recorrido de nuestro carretón impidiendo dañar el motor siguiendo empujando en una dirección cuando hemos alcanzado el final del recorrido posible. ¿Os animáis a mandarnos vuestras soluciones a nuestro facebook? https://www.facebook.com/pages/Hubor-Proteus/294446180592964

Lec12 010

 

 

[Proteus versión 8.1]

Como vimos en la lección anterior, nuestro Arduino puede expandirse y aumentar significativamente sus capacidades utilizando el bus i2c. En esta lección vamos a introducirnos en los fundamentos de este bus.

El bus I2C es un estándar diseñado por Philips, que facilita la comunicación entre diferentes microcontroladores, memorias y otros dispositivos con una cierta capacidad de contener lógica. Utiliza una tecnología de tipo bus. Es decir que sólo requiere dos hilos o pistas para intercomunicar todos los componentes entre sí, por los que se trasmiten los datos vía serie. En la imagen siguiente (sacada de un documento original de Philips) se puede observar la topografía de este sistema de comunicaciones en un ejemplo de utilización bastante complejo con muchas de las posibilidades que brinda (incluidos extensores de bus, utilización de múltiples maestros, etc.).

Lec10 001

Se utiliza uno de los dos conductores para manejar la sincronización mediante la generación de un tren de pulsos de reloj (SCL) y el otro para intercambiar los datos (SDA). Las dos líneas, SDA (Serial Data) y SCL (Serial Clock), se conectan a la fuente de alimentación a través de dos resistencias de pull-up. Cuando el bus está libre, ambas líneas están en nivel alto. Cuando algún dispositivo quiera utilizar el bus, lo hará poniendo en ambas líneas valores de alto o bajo según las necesidades. Como la línea está en descanso en nivel alto, la forma de actuar cada uno de los dispositivos sobre ella es ponerlo a masa y de esa manera forzar el nivel bajo en esa línea. La línea de reloj sólo la gobierna el maestro (puede haber varios maestros, pero en cada momento sólo un dispositivo actúa como tal). Mientras que la línea de datos la gobiernan tanto el dispositivo maestro como el esclavo que es interrogado en ese momento.

El Maestro es el dispositivo que inicia (y gobierna mientra dura) la transferencia de datos por el bus. El bus está diseñado para permitir la participación de varios Maestros, ya que el protocolo incluye un sistema detector de colisiones. El maestro se encarga de generar la señal de reloj. El esclavo es el dispositivo direccionado que escucha y, si es necesario, responde al requerimiento del maestro. Cada dispositivo tiene una única dirección que lo identifica de modo unívoco dentro del bus, de tal manera que siempre está claro a qué dispositivo interroga el maestro y qué dispositivo debe responder a esa consulta. Si por error, configuramos dos dispositivos con la misma dirección se producirá una colisión en el bús y el sistema no funcionará correctamente.

La cantidad de dispositivos que se pueden conectar al bus está limitada, unicamente, por la máxima capacidad permitida, que es de 400 pF y el número máximo de dispositivos que se pueden direccionar. Cada dispositivo puede operar como transmisor o receptor de datos, dependiendo de su función. Por ejemplo, un display es solo un receptor de datos. Y, como otro ejemplo, una memoria es un emisor y receptor de datos.

Los bits de datos se transmiten por la línea SDA. Por cada bit de información se necesita un pulso del reloj en la línea SCL. El dato transmitido por la línea SDA sólo pueden cambiar cuando la línea SCL está a nivel bajo. Están prohibidas las transiciones de la línea SDA mientra la línea SCL esté en nivel alto. La única excepción a esta regla son las señales de arranque (start) y parada (stop).

Lec10 009

Sólo los maestros pueden iniciar una comunicación. La condición inicial, de bus libre, es cuando ambas líneas están en estado lógico alto. En esta situación cualquier maestro puede disponer del bus. Para hacerlo, establece la condición de inicio (start). Esta condición de inicio se produce cuando un maestro pone en estado bajo la línea de datos (SDA) y deja en nivel alto la línea de reloj (SCL).

Lec10 002

El primer byte que se transmite a continuación de la condición de inicio, está formado por siete bits que contienen la dirección del dispositivo con el que se desea establecer la comunicación, más un octavo bit que indica el tipo de operación que se establecerá con él (lectura o escritura).

Lec10 003

Si el dispositivo cuya dirección se corresponde con la indicada en los siete primeros bits (A0-A6) está presente en el bus, contestará con un bit bajo, ubicado inmediatamente a continuación del octavo bit que ha enviado el dispositivo maestro. Este bit de reconocimiento (ACK) en bajo le indica al dispositivo maestro que el esclavo reconoce la solicitud y está en condiciones de comunicarse.

Lec10 004

En este momento, en el que ya ha quedado claro quien es el maestro y cúal es el esclavo que debe mantener la comunicación, comienza el intercambio de información entre los dos dispositivos. Si el bit de lectura/escritura (R/W) fue puesto a nivel lógico bajo (escritura), el dispositivo maestro envía datos al dispositivo esclavo. Este proceso se mantiene mientras se reciban señales de reconocimiento por parte del esclavo. La comunicación concluye cuando se hayan transmitido todos los datos.

Lec10 005

Cuando el bit de lectura/escritura fue puesto a nivel alto (modo lectura), el maestro genera pulsos de reloj para que el dispositivo esclavo pueda enviar los datos. Después de cada byte recibido el maestro que está recibiendo los datos genera un pulso de reconocimiento.

 

Lec10 006

El maestro deja libre el bus generando una condición de parada (stop).

 

Lec10 007

También es posible un modo mixto, donde el maestro envía datos al esclavo y a continuación recibe datos de ese mismo esclavo. En este caso el maestro genera otra condición de inicio en lugar de una condición de parada. Esta nueva condición de inicio se denomina "inicio reiterado" y se puede emplear para direccionar un dispositivo esclavo diferente o para alterar el estado del bit de lectura/escritura.

Lec10 008

Lo más común en los dispositivos para el bus I2C es que utilicen direcciones de 7 bits, aunque existen dispositivos capaces de gestionar direcciones de 10 bits.  Una dirección de 7 bits implica que se pueden poner hasta 128 dispositivos sobre un bus I2C, ya que un número de 7 bits puede ir desde 0 a 127. La mayoría de los proyectos tienen más que suficiente con esta capacidad de direccionamiento y no es habitual encontrarnos con casos donde nos veamos comprometidos por esta limitación.  El hecho de colocar la dirección de 7 bits en los 7 bits más significativos del byte produce confusiones entre quienes comienzan a trabajar con este bus. Si, por ejemplo, se desea escribir en la dirección 21 (hexadecimal), en realidad se debe enviar un 42, que es un 21 desplazado un bit hacia arriba.

La lección de hoy ha sido evidentemente teórica. Pero no debemos asustarnos. Hemos explicado todo esto porque una buena base teórica nos ayudará a entender cómo funciona nuestro bus i2c y, sobre todo, a detectar de donde provienen los problemas cuando se produzcan. Pero no hay que olvidar que las librerías de software disponibles nos facilitan toda la gestión del bus y nos permiten olvidarnos de todos estos entresijos a la hora de programar.

En la lección anterior vimos que era muy fácil utilizar el bus i2c. En ella utilizamos un dispositivo i2c que nos proporcionaba 8 salidas digitales adicionales (el PCF8574). También vimos que podíamos utilizar el depurador de mensajes i2c incluído en Proteus. Con el depurador podíamos visualizar los mensajes que se transmitían por el bus. En concreto transmitíamos una secuencia de órdenes que iban encendiendo y apagando los leds situados en las ocho salidas de forma secuencial. En un momento dado, uno de los mensajes transmitidos era el siguiente:

Lec10 010

Ahora, a la luz de la teoría vista, ya podemos interpretar este mensaje:

En primer lugar la 'S' simboliza el bit de arranque.

Luego se trasmite el byte de valor 40 (0x40 en hexadecimal) que representa la dirección del esclavo. Si recordáis nuestro componente PCF8574 tenía la dirección 20 en hexadecimal (0x20). 0x20 es 10 0000 en binario. Si escribimos este número en binario en los siete bits superiores y le añadimos en el octavo bit el valor 0  para indicar que es una orden de lectura, tenemos el valor 100 0000 que en hexadecimal se corresponde con el valor 0x40.

La 'A' que aparece a continuación es el pulso de reconocimiento (acknowledgement) que devuelve el esclavo para decir que está listo.

El siguiente byte 00 (0x0 en hexadecimal) es el byte de datos que se transmite. Si visualizamos el programa de la lección anterior, veremos que este valor de byte va aumentando en cada nuevo mensaje para ordenar el encendido secuencial de los leds.

Lec10 011

La nueva 'A' que aparece detrás del byte del dato, es el nuevo pulso de reconocimiento que devuelve el esclavo para decir que ha recibido el dato correctamente.

Por último, la 'P' es el bit de parada que manda el maestro para dar por concluido las comunicaciones.

Sencillo ¿verdad? Depurar ahora nuestras comunicaciones i2c y descubrir los posibles errores es un poco más fácil.

En posteriores lecciones aumentaremos nuestro conocimiento y utilizaremos de forma más intensiva las capacidades del bus i2c.

 

[Proteus versión 8.1]

Ahora que ya hemos visto en la anterior lección la base teórica de la utilización del bus i2c, estamos en condiciones de ver un ejemplo práctico de utilización de un dispositivo i2c para medir temperaturas desde nuestro equipo Arduino. Esta selección tiene un evidente caracter pedagógico. Este dispositivo es configurable por software a través del bus i2c y devuelve el dato de la temperatura medida. Así podremos practicar una secuencia completa de escrituras y lecturas a través del bus i2c.

Nuestra primera tarea consiste en seleccionar el dispositivo i2c más adecuado y comprobar sus características para aprender a utilizarlo en nuestro proyecto. En este caso, deseamos medir temperaturas. Así que vamos a utilizar el termómetro digital de la casa MAXIM (Dallas Semiconductor) referencia DS1621 que tiene un precio inferior a los 6,00€. Podemos encontrar fácilmente la información completa de este dispositivo en internet en la dirección: http://pdfserv.maximintegrated.com/en/ds/DS1621.pdf De todas formas, como internet es un 'animal vivo' donde los enlaces pueden variar con el tiempo, si no estuviera disponible en el momento de leer esta lección, podemos también realizar una búsqueda de este dispositivo con google que nos ayudará a encontrar la información de este dispositivo. Además, este componente tiene una ventaja adicional muy interesante para nosotros. Proteus incluye entre sus librerías un modelo completo de simulación para este elemento que nos permite ir fijando en tiempo real diversas temperaturas con ayuda de unos botones y de esa manera simular su funcionamiento real.

Lec11 001

Como se puede observar en la imagen, el modelo nos permite ver en pantalla la temperatura actual y modificarla a nuestro antojo con los botones con las flechas arriba y abajo.

El segundo paso consiste en conectar nuestro dispositivo a nuestro Arduino a través del bus i2c. Para hacerlo, conviene recordar que el bus i2c se compone de dos hilos cada uno de ellos conectado a VCC a través de sendas resistencias de pull-up. El esquema completo de conexionado se muestra a continuación.

Lec11 002

Hemos conectado el bus (a la línea del reloj representada por el rótulo SCL y a la línea de datos representada por el rótulo SDA)  el dispositivo DS1621, el depurador del bus i2c y nuestro equipo Arduino. Observe que para conectar el Arduino al bus hemos unido el terminal AD5 a la línea SCL y el AD4 a la línea SDA. Además, hemos conectado un terminal virtual a los terminales TXD y RXD para poder enviar datos a la consola durante la ejecución de nuestro programa. En otro lugar de nuestro esquema el terminal TXD está unido al pin IO1 de nuestro arduino y el terminal RXD al pin IO0. Este es el mismo procedimiento que hemos utilizado en lecciones anteriores para usar el terminal virtual. De todas formas, a continuación, mostraremos el esquema completo para que no existan dudas.

Lec11 003

Una vez realizadas las conexiones del hardware, tenemos que direccionar correctamente nuestro termómetro digital. El DS1621 se direcciona de la siguiente manera (se puede consultar sus datos para comprobarlo). Como todo dispositivo i2c, utiliza siete bits para fijar su dirección. Los cuatro primeros bits adoptan siempre el valor fijo 1001. Los tres útlimos bits se confguran utilizando los pines A0, A1 y A2. Si el pin está conectado a VCC tomará el valor 1 y si está conectado a GND el valor 0. Por lo tanto la dirección del dispositivo será la siguiente: 1 0 0 1 A2 A1 A0. En nuestro caso el proyecto sólo utiliza un dispositivo DS1621, así que hemos conectado los tres pines a GND y la dirección resultante es: 1001000 (0x48 en hexadecimal y 72 en decimal).

Ya podemos escribir nuestro primer programa.

Lec11 004

Lo hemos hecho expresamente corto, para ir siguiendo paso a paso todo el proceso y poder desgranarlo y comprenderlo perfectamente. El programa contiene una sentencia include para enlazar con la librería de Arduino que nos ayuda a gestionar el uso del bus i2c. Luego declaramos tres variables, una para almacenar el valor de la temperatura en grados centígrados, otra para guardarla en grados Farenheit y una tercera con la dirección de nuestro dispositivo i2c (acabamos de ver que su dirección es 0x48 en hexadecimal).

En la sección de configuración, inicializamos el puerto serie donde conectamos nuestro terminal virtual para usarlo a una velocidad de 9600 baudios. Inicializamos también el bus i2c con la función wire.begin() de la librería wire.h.

A continuación hacemos una cosa extraña, pero que la llevamos a cabo para que el lector pueda ver el uso del depurador del bus i2c paso a paso. Sólo utilizamos las funciones beginTransmission() y endTransmission(). A la primera le pasamos como parámetro la dirección de nuestro termómetro digital. Con esto logramos enviar un único telegrama a través de nuestro bus i2c. Un telegrama que básicamente es una orden de direccionamiento del maestro y que debe ser contestada por nuestro esclavo con un bit de reconocimiento (ACK).

Ejecutemos la simulación y obtendremos lo siguiente:

Lec11 006

Cómo espérabamos en nuestro depurador se puede observar el único telegrama que hemos puesto en el bus: S 90 A P. Es decir, un bit de arranque (S). El byte de valor 0x90 que se corresponde con la dirección de nuestro dispositivo (0x48 = 100 1000) más un bit 0 a su derecha que indica que el telegrama es para escribir (1001 0000 = 0x90). Un bit de reconocimiento del esclavo (A). Y, por último, un bit de parada (P).

Con esto hemos comprobado que todo funciona bien y que nuestro esclavo está direccionado según nosotros creemos.

Cambiemos nuestro programa y sustituyamos el valor de la variable dirección por 0x49. Compilemos y arranquemos la simulación. Nuestro depurador del bus i2c mostrará el siguiente telegrama.

Lec11 007

Se puede ver que el bit de reconocimiento (A) se ha sustituido por un bit de no reconocimiento (N). Eso significa que hemos mandado un telegrama por el bus dirigido a un dispositivo con una dirección que nadie reconoce. De esta manera tenemos una forma sencilla de comprobar que el direccionamiento de los dispositivos que hemos puesto en nuestro proyecto se corresponde con el que nosotros esperábamos. Volvamos a dejar nuestro programa con la dirección correcta.

Nuestro termómetro digital es susceptible, como ya dijimos, de ser configurado a través del bus i2c. Esto se logra mediante la escritura de una serie de comandos (se puede ver la lista completa de los comandos disponibles en la documentación del dispositivo). En nuestro caso nos interesa programar nuestro DS1621 para que esté realizando de forma continua lecturas de temperatura. Para hacerlo modificaremos nuestra función de configuración de la siguiente manera.

Lec11 008

Como es nuestra costumbre, añadimos unos comentarios para entender cada uno de los pasos que estamos dando. El comando 0xAC le indica al DS1621 que deseamos escribir en su configuración y el byte que enviamos a continuación es el valor de configuración que deseamos escribir. En este caso 0x02 siginifica que deseamos que el dispositivo esté leyendo las temperaturas de forma continuada. 

A continuación volvemos a utilizar la función beginTransmission() para hacer un inicio reiterado y poder mandar un segundo comando. En este caso el comando es el 0xEE que ordena a nuestro dispositivo que comience con las lecturas de temperaturas. Por último finalizamos el telegrama.

Si compilamos y ejecutamos la simulación, el resultado debe ser.

Lec11 009

A estas alturas ya tenemos que ser capaces de reconocer perfectamente lo que aparece en el depurador i2c.

Todavía no estamos leyendo datos a través del bus. Sólo hemos escrito la configuración. Nuestro siguiente paso, será recibir las lecturas de temperatura y mostrarlas en el terminal virtual. Para ello modificaremos la función del bucle continuo de nuestro arduino.

Lec11 010

En este caso enviamos un nuevo telegrama de escritura en el esclavo para enviar el comando que fuerza la lectura de la temperatura. Para ello utilizamos la funciones beginTransmission, write y endTransmission de la librería wire.

A continuación mandamos un nuevo telegrama para que el esclavo nos devuelva el valor de temperatura leído. Lo llevamos a cabo con la funcion requestFrom. El resultado de la lectura recogido por la funcion read, lo guardamos en la variable tempC. Para obtener el valor en grados Faranheit, utilizamos una sencilla fórmula matématica y el resultado lo guardamos en la variable tempF.

El resto del programa es para enviar los resultados por el puerto serie hacia el terminal virtual.

Si compilamos y arrancamos la simulación podremos ver en el terminal virtual las temperaturas léidas. Podemos cambiar la temperatura a leer con los botones de subir y bajar del dispositivo DS1621.

Lec11 011

También podemos observar en el depurador del bus i2c, los diferentes telegramas que se envían.

Lec11 012

El primero es el que se utiliza para escribir la configuración. Los otros van en parejas. Uno es de escritura (por eso la dirección es 0x90 para que el último bit sea 0) y el otro el de lectura (la dirección es 0x91 porque el último bit es 1).

El valor leído dependerá de lo que hayamos introducido en nuestro dispositivo DS1621 con los botones. En nuestro caso se corresponde con una lectura de temperatura de 18ºC (0x12 en hexadecimal es 18 en decimal).

Nuestro programa tiene un defecto. Si seleccionamos una lectura negativa (grados bajo cero) observar que lectura recibimos. Os dejamos como tarea para investigar, la solución de este problema.

Además os invitamos a un nuevo reto. El DS1621 puede activar su pin 3 (TOUT) cuando la temperatura se encuentra entre un determinado rango de valores configurables. Esta función se llama termostato en contraposición a la función termómetro que hemos utilizado nosotros en este ejemplo. ¿Se anima el lector a intentar poner en marcha esta función para comprobar sus conocimientos sobre el dispositivo y la utilización del bus i2c?

El curso se vuelve un poco más interactivo para hacerlo más interesante. Los que tengan la solución a nuestros dos problemas, las pueden compartir en nuestra página de facebook:

https://www.facebook.com/pages/Hubor-Proteus/294446180592964?ref=hl

 

[Proteus versión 8.1]

Hasta ahora hemos visto en estas lecciones las capacidades de nuestro equipo Arduino para conectarse con el mundo exterior. Entradas digitales, entradas analógicas, salidas digitales, salidas analógicas (con la matización de que las implementamos utilizando la técnica de PWM) y comunicaciones vía serie. Dependiendo de la placa de Arduino que estemos utilizando para llevar a cabo nuestro proyecto, el microprocesador ATMEGA que incorpore tendrá más o menos pines utilizados para una u otra de estas funciones. Podemos consultar el esquema de todos los pines de nuestro microprocesador ATMEGA en el enlace de la sección documentos de nuestra web siguiente: http://huborarduino.com/index.php/herramientas/documentos/23-diagramas-de-pines-de-los-arduino.

En muchas ocasiones las necesidades de nuestro proyecto se podrán satisfacer con las posibilidades que nos brinda nuestro microprocesador. Pero no es raro (desgraciadamente con más frecuencia de lo que cabría esperar en un principio) que nos encontremos en situaciones donde el microprocesador se nos quede corto. En estos casos podemos optar por intentar utilizar otro microprocesador con más pines (aunque, ojo, nunca hay un microprocesador suficientemente grande que sirva para todo) u optar por la solución del tipo que vamos a analizar en esta y las siguientes lecciones de nuestro curso: expandir las capacidades de nuestro microprocesador utilizando periféricos con una función específica.

Esta opción que presentamos es muy habitual en todos los sistemas de automatización (los conocidos con el acrónimo de PLC) presentes en el mercado: Siemens, Omron, AEG, Schneider, Allen Bradley, Pep, etc. Basicamente consiste en tener una tarjeta principal (CPU) donde se aloja nuestro controlador del sistema y unir por un bus de datos una serie de tarjetas auxiliares de funciones definidas. Cada una de estas tarjetas contiene la electrónica (y los microprocesadores necesarios para ejecutar la lógica de funcionamiento de la tarjeta de ampliación y las comunicaciones con la CPU) específicos para llevar a cabo la tarea que se le encomienda.

Lec09 001

Vamos a conectar nuestro equipo Arduino con los 'equipos periféricos' utilizando un sistema de comunicaciones del tipo bus serie. En el mercado hay distintas opciones para desempeñar estos trabajos. Nosotros vamos a utilizar una especificación concreta: el bus i2c. Hacemos esta selección porque es un bus que utilizan muchos dispositivos por lo que contaremos con un amplio abanico de soluciones específicas. Además, porque su funcionamiento e implantación, tanto de hardware como de software, es sencilla y económica. Y, finalmente, porque existen librerías estándar en Arduino que nos ayudan en esta tarea.

Lec09 002

Para poder llevar a cabo nuestro trabajo, tenemos que ir recorriendo un camino compuesto de varias etapas intermedias que nos obligará a familiarizarnos con conceptos nuevos: uso de librerías en Arduino, utilización de un bus de comunicaciones serie, conocimiento del estándar i2c, exploración de los dispositivos disponibles y de sus características específicas, etc. Lógicamente según nuestro conocimiento y experiencia del mundo del control industrial, este camino puede ser muy rápido o un poco más largo. 

Para darnos una idea de la enorme variedad de dispositivos i2c disponibles, podemos utilizar a modo de muestra los dos enlaces siguientes:

Dispositivos i2c de Philips Semiconductor

Dispositivos i2c de Texas Instruments

Podemos disfrutar comprobando que existen dispositivos para aumentar el número de las entradas y salidas digitales, ampliar las entradas y salidas analógicas, acceder a nuevos sistemas de comunicaciones serie, expandir el alcance del bus, controlar teclados, controlar leds, ampliar la memoria, medir la temperatura, medir la corriente y la tensión y un largo etc. más. No nos tenemos que dejar llevar por la euforia de las posibilidades que se nos abren, ni caer en el pesimismo pensando que el camino a recorrer sea técnicamente demasiado complicado. Vamos a recorrer todo el trayecto en diferentes fases, de una en una para comprenderlas bien, dominarlas y llegar a buen puerto. Como este curso siempre se ha marcado como objetivo ir dirigido a quien no sabe (nadie estudia un curso de algo que ya conoce) no tenemos más remedio que plantearnos abordar este tema desde el principio, paso a paso y dividiéndo nuestra tarea entre varias lecciones.

En ésta que nos ocupa ahora, sólo vamos a esbozar las posibilidades del sistema propuesto. Utilizaremos el siguiente esquema electrónico.

Lec09 003

En primer lugar, como es lógico, está nuestro equipo Arduino. A continuación, preparamos el bus (en nuestro caso, el i2c, se compone de dos hilos). Por ahora nos sirve con considerar el bus como dos hilos que unen todos nuestros dispositivos i2c. Uno de estos hilos lo llamaremos SCL y el otro SDA. Estos dos hilos están conectados ambos a +5V por medio de una resistencia de 4k7 Ohms. La solución propuesta por nuestro estánar i2c sería como sigue:

Lec09 005

En nuestro esquema de prueba, lo llevamos a cabo utilizando este montaje:

Lec09 004

Conectamos a este bus, nuesto Arduino (pines AD4 y AD5) utilizando la técnica de los terminales de la siguiente manera:

Lec09 006

Para nuestro primer ejemplo, vamos a utilizar como equipo periférico un chip de Phillips llamado PCF8574 que nos permite utilizar desde nuestro Arduino a través del bus i2c ocho salidas digitales. Como es lógico, para funcionar, tiene que estar conectado al bus. Además, en este caso, lo vamos a utilizar para controlar con sus ocho salidas digitales ocho leds. El montaje se recoje en la siguiente imagen:

Lec09 007

Además hemos incluido el analizador del bus i2c incorporado en Proteus que nos permite 'espiar' todos los datos que circulan por nuestro bus. Es muy pronto para entender su utilidad, pero queremos presentarlo en esta primera aproximación, para que tengamos presente su existencia y que sepamos que contamos con potentes herramientas de depuración que nos ayudarán a solucionar los fallos que puedan surgir en la utilización de los periféricos i2c.

Lec09 008

El software que corre en nuestro Arduino, no puede ser más sencillo. Todo el código se recoge en el siguiente listado:

Lec09 009

Con muy poco esfuerzo estamos implementando nuestro módulo de expansión de ocho salidas digitales. Como ya dijimos, en próximas lecciones, destriparemos todo este código para entenderlo perfectamente y dominarlo. Pero, por ahora sólo vamos a limitarnos a activar la simulación y ver como las diferentes salidas digitales van encendiéndose y apagándose mostrando un contador descendente (un byte (desde 1111 1111 en formato binario hasta 0000 0000).

Lec09 010

En la zona inferior derecha se puede observar la ventana de nuestro depurador del bus i2c donde van apareciendo toda la actividad que se produce en el bus. Tampoco en este momento sabemos interpretar los datos que nos muestra. Pero no tardaremos en aprender a utilizarlo y comprobar su utilidad.

Esperamos haber despertado vuestro interés y que animados por las posibilidades que nos abre el bus i2c nos acompañéis en las siguientes lecciones que dedicaremos a desgranar todo este trabajo.


Esta página es propiedad de Hubor.

2014.

Guardar
Preferencias de usuario para las Cookies
Estamos utilizando las cookies para asegurarnos de que le podemos ofrecer el mejor servicio posible en este sitio web. Si rechaza el uso de las cookes, es posible que esta web no funcione como estaba previsto por el equipo de programadores.
Aceptar todo
Rechazar todo
Leer más
Estadísticas
Las cookies de preferencias permiten a la página web recordar información que cambia la forma en que la página se comporta o el aspecto que tiene, como su idioma preferido o la región en la que usted se encuentra.
Google Analytics
Aceptar
Rechazar