¿Qué es este blog?

La idea de este blog nace para compartir los avances que se vayan realizando a lo largo de un estudio sobre cómo interconectar los distintos sensores que se pueden encontrar en el mercado, o fabricar de forma casera, con la plataforma Mindstorms de LEGO. Para ello se hará uso ARDUINO, un entorno de desarrollo abierto basado en microcontrolador.

lunes, 7 de marzo de 2011

Solución a los problemas entre Arduino Mega 2560 y el Mindstorm

En primer lugar, hacer referencia a una publicación que hice hace unos días, donde explicaba el problema y aún no le había encontrado solución: enlace

En ella, básicamente comentaba los problemas que tenía para comunicar el NXT con la placa Arduino Mega 2560 mediante I2C. Voy a resumir el problema con datos y medidas para que todo quede bien claro, y finalmente pondré la solución a la que hemos llegado.
  • En primer lugar, se hicieron pruebas de comunicación I2C entre Arduino Duemilanove y el NXT. La conexión entre ambos era la siguiente:
    • Pines 2 y 3 del NXT (Rojo y negro) (tierra) --> Arduino GND.
    • Pin 4 del NXT (alimentacion) (verde) --> Arduino 5V
    • Pin 5 del NXT (Amarillo) (SCL) --> Arduino A5
    • Pin 6 del NXT (Azul) (SDA) --> Arduino A4
    Con estas conexiones, y un programa sencillo que simplemente recogiera algunos datos del Arduino y los mostrara en la pantalla del NXT todo funcionó perfectamente. El programa usado también lo comenté en otra publicación y lo podéis encontrar aquí.
  • El siguiente paso era hacer el mismo intercambio de datos usando una placa algo más potente y con más prestaciones: la Arduino Mega 2560. Las conexiones que se tienen que hacer para ellos son estas:
    • Pines 2 y 3 del NXT (Rojo y negro) (tierra) --> Arduino GND
    • Pin 4 del NXT (alimentacion) (verde) --> Arduino 5V
    • Pin 5 del NXT (Amarillo) (SCL) --> Arduino SCL
    • Pin 6 del NXT (Azul) (SDA) --> Arduino SDA
Bien, haciendo esto y lanzando exactamente el mismo programa que en el caso del Arduino Duemilanove tanto para el Mindstorm como para el Arduino... no pasó absolutamente nada. Es decir, no hubo intercambio de datos. ¿Por qué? Bueno, voy a ir explicando los pasos que he dado hasta dar con la solución...
    Diferencias entre Arduino Duemilanove y Arduino Mega 2560
    Si nos fijamos en los esquemáticos de ambos (disponibles en la página oficial de Arduino), hay una diferencia en el camino que recorren tanto la señal de datos (SDA) como la de reloj (SCL) del protocolo I2C desde el conector hasta el microcontrolador. Se trata de dos resistencias de pull-up, de un valor de 10K que sirven para mantener el valor lógico "uno" si la tensión en la línea no es suficiente. Estas resistencias son las que nos están originando el problema, como entenderemos enseguida. Estas resistencias las vemos en la siguiente captura (extraída del esquemático):

    ¿Por qué pueden dar problemas?
    En principio, una resistencia de pull-up no es malo, sino todo lo contrario. Pero en este caso nos está perjudicando. Vamos a analizar el recorrido de las señales de reloj (SCL) y de datos (SDA) en el Mindstorm en el caso del puerto A (es idéntico para todos los puertos). 

    En la figura que tenemos aquí vemos como del procesador (AT91SAM7S256) salen las señales DIG1A0 y DIG1A1. Estas son las señales SCL y SDA respectivamente. 



    Estas señales, van a parar al circuito siguiente:


    En él vemos el recorrido que hacen hasta obtener las señales DIGIAI0 y DIGIAI1 que son las que tendremos a la salida (podemos ver el conector en la figura inferior). Si nos fijamos, estas señales pasan por una resistencia en serie de 4,7 K y a continuación tienen conectadas unas resistencias de pull-up de 82 K que van alimentadas a 5V (ver nota 1). 


    Esta resistencia de pull-up de 82 K, al conectar nuestro Mindstorm con la placa Arduino Mega 2560 se asocia en paralelo con la de 10 K de dicha placa, formando una resistencia equivalente de 8,91 K (es decir, casi diez veces inferior a la original). 
    El procesador nos dará como nivel alto un valor de 3,3 V, y como nivel bajo 0 V. Si hacemos algunos cálculos (teniendo en cuenta el circuito equivalente) para calcular qué valores vamos a tener a la salida en cada caso, obtendremos lo siguiente:


    • Circuito equivalente conectando el NXT con Arduino Duemilanove: se obtiene un valor a la salida de 3,40 V (nivel alto) y de 0,28 V (nivel bajo).
    • Circuito equivalente conectando el NXT con Arduino Mega 2560 (y por tanto con el paralelo de las dos resistencias de pull-up): se obtiene un valor a la salida de unos 3,89 V (nivel alto) y 1,70 V (nivel bajo).

    Lo que parece, es que el valor de tensión a la salida para el nivel alto será detectado sin problemas, pero para el nivel bajo, en el caso del Arduino Mega tenemos 1,70 V. Es un valor demasiado alto, y probablemente pueda confundirse con el '1' lógico haciendo que la comunicación falle. Esto se debe a que la resistencia de 4,7 K que vemos en serie a la salida del Mindstorm, está alterando el valor de tensión que hay a la salida y hace que las resistencias de pull-up entren en acción cuando no deberían, es decir, cuando la línea está a nivel bajo.

    Primeras medidas
    Todas las medidas que se describen a continuación han sido realizadas con un osciloscopio digital de la marca Tektronix, modelo TDS 210, del departamento de Ingeniería de Sistemas y Automática de la Universidad de Málaga.

    Lo primero que se hizo fue, para descartar que hubiera cualquier problema en los puertos I2C de la placa Arduino Mega 2560, interconectar dicha placa con la de Arduino Duemilanove y ponerlas a intercambiar datos. Hay muchos ejemplos de esto por internet, pero el que seguimos fue este. Al hacer esto, vimos que la comunicación era correcta, y que las señales de datos y de reloj mantenían un valor medio de señal próximo a los 5 v (de aproximadamente 4,90 V y cercano a 0 para el '0' lógico.

    A continuación, para comprobar los cálculos teóricos que comentamos en el apartado anterior, se hicieron las medidas conectando en primer lugar el NXT con la placa Duemilanove, y a continuación con la Mega. Lo que se vio confirmó lo que pensábamos, ya que, aunque el valor medio de las señales era similar, en el caso de la conexión con Arduino Mega la señal tenía la mitad de amplitud (unos 2 V pico a pico) y su extremo inferior estaba cercana a los 2 V, mientras que con Duemilanove el pico inferior rozaba los 0 V y tenía una amplitud de 4 V pico a pico.

    Por lo tanto, efectivamente el nivel bajo de la señal se está confundiendo con el nivel alto. 

    La solución
    Tras todo este proceso, la única solución viable era la de eliminar las resistencias de la placa de Arduino Mega 2560. Para aquellos que tengan el modelo Arduino Mega (versión anterior) lo tendrán más fácil, ya que lo que tienen es simplemente dos resistencias separadas que se pueden desoldar y eliminar fácilmente. En nuestro caso, es algo más complejo ya que las resistencias están dentro de un encapsulado DIL, que contiene además la resistencia que mantiene el reset a nivel alto hasta que lo pulsemos. Si se eliminase este encapsulado (que vemos en la figura inferior con un 103 escrito), se estaría dejando el reset permanentemente a nivel bajo, y por lo tanto la placa no llegaría a encenderse. 


    (Gracias por la captura a Chiva, del foro oficial de Arduino :) )

    Aunque había otra alternativa, como desoldar el encapsulado, y colocar después una resistencia de 10k para el reset, optamos por "cortar" las líneas de datos que unían las pistas de SDA y SCL con las resistencias. Para ello, nos fijamos en el esquema de PCB de Arduino (también disponible en la página oficial) y elegimos el mejor sitio para el corte. En las dos figuras de abajo se han resaltado las líneas SDA y SCL, y se ha marcado en verde el sitio por el que se ha hecho el corte:




    Y tras hacer estos cortes (con cuidado, arañando con un cúter hasta comprobar con un multímetro que la vía por la que pasa la señal y la patilla de la resistencia ya no hacían contacto) se ha vuelto a probar la comunicación entre el NXT y el Arduino Mega 2560 y... todo funciona correctamente :)

    Nota1: Sobre la tensión VCC_RS485


    En los cálculos se ha asumido que la tensión VCC_RS485 es de 5 V. Para ello, se ha recurrido una vez más al esquemático. El diagrama de bloques del sistema de alimentación se puede ver a continuación.



    Si nos fijamos, la señal VCC_RS485 tiene a su entrada un conmutador que alterna su valor entre 5 V y un circuito abierto. La señal que controla esto es POWER_EN que procede del ATMEGA48, y que corresponde al pin PB7. Se trata de una señal periódica generada por el oscilador interno del microcontrolador y que hace que el conmutador vaya abriéndose y cerrándose continuamente. 







    No hay comentarios:

    Publicar un comentario