Archivo de la categoría: Puerto Serie

Ejemplos Arduino con Arrays y Strings

Efectos con leds mejorado

El ejemplo anterior de los LEDs con el efecto del coche fantástico puede hacerse de una forma más eficiente con el uso de los arrays y la estructura de control for. Además hacer otros efectos de luces o cambios en el realizado es mucho más sencillo usando arrays.

Hacer el efecto del coche fantástico usando arrays y la estructura de control for.

Pistas:

int pinArray[] = {2, 3, 4, 5, 6};

for (int i = 0; i > 6; i++) {
    digitalWrite(pinArray[i], HIGH);
    delay(timer);
    digitalWrite(pinArray[i], LOW);
    delay(timer);
  }

O simplificado:

for (int i = 2; i < 6; i++) {
    digitalWrite(i, HIGH);
    delay(timer);
    digitalWrite(i, LOW);
    delay(timer);
  }

Tutorial: https://www.arduino.cc/en/Tutorial/KnightRider

Estructura de control for: https://www.arduino.cc/en/Reference/For

Esquema de conexión:

Solución: https://github.com/jecrespo/aprendiendoarduino-Curso_Arduino_2017/tree/master/Ejercicio09-CocheFantasticoMejorado

Control Velocidad del Efecto de Leds

Añadir el cambio de velocidad dentro del código al leer de un potenciómetro de forma que no haya que esperar a un ciclo de loop para cambiar la velocidad: “timer = analogRead(A0);”

Esquema de conexión:

O usando un LDR para el control de velocidad:

Solución: quitar los comentarios de https://github.com/jecrespo/aprendiendoarduino-Curso_Arduino_2017/tree/master/Ejercicio09-CocheFantasticoMejorado

Probar a hacer otros efectos como: https://github.com/jecrespo/Aprendiendo-Arduino/tree/master/Ejercicio48-Efectos_Led

Arrays

Leer las entradas analógicas de la A0 a la A5 y almacenar en un array para mostrarlo cada 5 segundos. Hacer lo mismo con las entradas digitales de la 2 a la 7.

Solución: https://github.com/jecrespo/aprendiendoarduino-Curso_Arduino_2017/tree/master/Ejercicio49-Arrays

Leer Strings por Puerto Serie

Aprender a manejar cadenas de caracteres es muy importante, a lo largo del curso se va a usar muy a menudo para comunicaciones y para interaccionar con el usuario.

Tutoriales para aprender a usar los Strings:

Hacer un programa donde al iniciar Arduino pregunta que introduzca un string cualquiera y lo mando a Arduino por puerto serie usando el monitor serie. Luego lo almacena en una variable y muestra lo leído por el puerto serie.

No olvidar poner en el setup() la inicialización del puerto serie: Serial.begin(9600);

Para leer por el puerto serie usar este código:

String cadena_leida;

while (Serial.available() == 0){
    //No hago nada
  }
  do{
    caracter_leido = Serial.read();
    cadena_leida += caracter_leido;
    delay(5);
  }  while (Serial.available() > 0);

La función Serial.available() me devuelve el número de bytes (caracteres) disponibles para leer del puerto serie. Estos son datos que han llegado al puerto serie de Arduino y se almacenan en el buffer de lectura de la UART. Más información: https://www.arduino.cc/en/Serial/Available

Serial.read() lee un caracter del puerto serie y los quita del buffer. Más información: https://www.arduino.cc/en/Serial/Read

NOTA para entender lo que está haciendo el programa poner la constante DEBUG a valor 1

Solución: https://github.com/jecrespo/aprendiendoarduino-Curso_Arduino_2017/tree/master/Ejercicio10-LeerStringSerie

Encender LED por Puerto Serie

Modificar el ejemplo anterior para que encienda el led de Arduino (pin 13) cuando mande la cadena “enciende” y lo apague cuando mande la cadena “apaga”.

Esquema de conexión:

Para comparar el texto introducido se proponen dos opciones, probar con ambas:

if (leido.startsWith("enciende"))

if (leido == "enciende")

Solución: https://github.com/jecrespo/aprendiendoarduino-Curso_Arduino_2017/tree/master/Ejercicio11-EncenderLedSerie

NOTA: Al igual que leemos y analizamos un valor con lo recibido por el puerto serie, la forma de trabajar si la comunicación es por ethernet, wifi, bluetooth, XBee, etc… es la misma, Arduino está escuchando por el puerto de comunicación y cuando recibe una petición válida ejecuta una acción. Los módulos de comunicación hablan con el microcontrolador a través los puertos serie (UART), I2C o SPI, cuyo funcionamiento es similar a lo visto en estas dos últimas prácticas.

Anuncio publicitario

Uso del Puerto Serie en Arduino

Código ASCII

La comunicación a través de cualquier puerto serie es en código binario y se mandan en grupos de 8 bits (byte). Puesto que el humano entiende caracteres alfanuméricos, codificamos los caracteres en binario según el código ASCII.

Práctica: Generar con Arduino una tabla de caracteres y sus valores ASCII en decimal, hexadecimal, octal y binario. http://arduino.cc/en/Tutorial/ASCIITable

Caracteres ASCII: http://es.wikipedia.org/wiki/ASCII y http://www.asciitable.com/

Fijaros en el carácter ÿ y recordad cuál es su valor en binario.

Solución: https://github.com/jecrespo/aprendiendoarduino-Curso_Arduino_2017/tree/master/Ejercicio12-ASCII

Otro ejemplo: http://diymakers.es/usando-el-puerto-serie-del-arduino/

Leer Números por Puerto Serie

Ver, entender y ejecutar este ejemplo https://github.com/jecrespo/aprendiendoarduino-Curso_Arduino_2017/tree/master/Ejercicio10-LeerStringSerie donde cada vez que reinicio Arduino espero a que se introduzca una cadena de caracteres y luego la muestro por pantalla. Con la opción DEBUG = 1, se muestra paso a paso cómo lee del puerto serie Arduino.

Basándonos en este ejemplo hacer una nueva versión donde me pide un número al iniciar Arduino y lo paso por el puerto serie. Luego multiplicar por 15 ese número y sacar por el puerto serie el resultado. En caso que lo introducido no sea un número sacar por pantalla el error.

Lo que hacemos es coger una cadena de texto que representa un número y lo convertimos a un número para poder operar con él. Esto lo aplicaremos en varios ejemplos para manejar por ejemplo la luminosidad de un led con un valor que paso por el puerto serie.

Recordar que es necesario usar la función toInt(): http://arduino.cc/en/Reference/StringToInt

Solución: https://github.com/jecrespo/aprendiendoarduino-Curso_Arduino_2017/tree/master/Ejercicio13-LeerNumeroSerie

Coche Fantástico Serial

Sobre el ejemplo del coche fantástico mejorado https://github.com/jecrespo/aprendiendoarduino-Curso_Arduino_2017/tree/master/Ejercicio09-CocheFantasticoMejorado, modificar el código para que el valor de la velocidad del efecto de los leds se pase por puerto serie y Arduino lo recoja y lo modifique para cambiar la velocidad a la que lucen los leds.

Esquema de conexión:

Solución: https://github.com/jecrespo/aprendiendoarduino-Curso_Arduino_2017/tree/master/Ejercicio14-CocheFantasticoSerial

Chat Serie

Para comunicar dos arduinos por el puerto serie y ver por pantalla lo que escribe desde el Arduino remoto, necesitamos dos puertos serie en cada uno de los Arduinos, uno para comunicar Arduino con el monitor serie (HW Serial) y otro para comunicar con el otro Arduino (SW Serial).

Hacer un programa que comunique por puerto serie un arduino UNO (usar la librería software serial) con otro Arduino UNO y saque por pantalla (puerto serie HW del USB) lo recibido por el puerto serie SW y mande por el puerto serie SW todo aquello que mandes desde el terminal. Es decir, hacer un chat punto a punto entre dos Arduinos.

Esquema de conexión:

Funciones y librerías a usar:

Preguntas:

  • Leer el código de la librería Softwareserial ¿Que tamaño de buffer tiene?. La librería está en la ruta “C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries”

Solución: https://github.com/jecrespo/aprendiendoarduino-Curso_Arduino_2017/tree/master/Ejercicio15-ChatSerie

Chat Serie Avanzado

Hacer una versión mejorada del anterior chat, de forma que al escribir en el monitor serie la cadena “repite”, Arduino pregunte cuantas veces y mandar por el chat serie la cadena “repite” tantas veces como se haya indicado. En este caso la estrategia es diferente, en lugar de leer un carácter del buffer en cada loop, en este caso hay que leer todo el buffer en el mismo loop para analizar lo que he recibido. Otra estrategia sería leer en cada loop línea por línea.

Comprobar las luces de Tx, Rx cada vez que se manda o recibe datos. Se podría hacer lo mismo con unos LEDs en los pines 10 y 11, encendiendo los leds cada vez que hagamos un write() o un read() en el puerto serie software y veríamos si se están mandando datos o no por la comunicación serie entre los dos Arduinos.

Solución: https://github.com/jecrespo/Aprendiendo-Arduino/tree/master/Ejercicio22-ChatSerieMejorado

Comunicación Serie Arduino

La comunicación serie es muy importante porque gran parte de los protocolos utilizados actualmente son serie y además muchos dispositivos de comunicación inalámbrica usan la comunicación serie para hablar con Arduino como los módulos bluetooth y los módulos Xbee. También la comunicación serie es la que se usa para comunicar el Arduino con el Ordenador a través del cable USB.

Para manejar el puerto serie en Arduino, debemos leer a fondo la referencia de Arduino:  http://arduino.cc/en/Reference/Serial que son las funciones que tenemos disponibles para trabajar con el puerto serie.

Todas las placas Arduino tienen al menos un puerto serie disponible en los pines digitales 0 (RX) y 1 (TX) compartido con el USB. Por lo tanto no es posible usar estos pines como entradas/salidas digitales.

El Arduino mega dispone de tres puertos adicionales Serial1 on pins 19 (RX) and 18 (TX), Serial2 on pins 17 (RX) and 16 (TX), Serial3 on pins 15 (RX) and 14 (TX). Estos pines no están conectados al interfaz USB del Arduino.

El Arduino Due tiene tres puertos adicionales pero con niveles de 3.3V TTL.

Comunicación serie:

La funciones más importantes que debemos conocer para manejar el puerto serie son: begin(), read(), write(), print() y available())

El código de la librería Serial se encuentra en el core del IDE de Arduino: https://github.com/arduino/Arduino/tree/master/hardware/arduino/avr/cores/arduino. Puede verse en el  código el tamaño del buffer de entrada y salida.

Otra técnica en lugar de usar las funciones “until” o similares, es almacenar en una variable String lo recibido como si fuera un buffer y luego analizarlo con las funciones de String.

Resto de funciones disponible para usar con el puerto serie y ejemplos de uso pueden verse en: https://www.arduino.cc/en/Reference/Serial

En el playground de Arduino tenemos más explicaciones y ejemplos de como funcional el puerto serie en Arduino: http://playground.arduino.cc/ArduinoNotebookTraduccion/Serial

Buffer Serial: los puertos serie de los microcontroladores tienen un buffer que se va llenando hasta que nosotros lo vamos leyendo con la función read() que lo vamos vaciando, es una pila FIFO. El tamaño del buffer serie en el Arduino Uno es de 64 bytes, cuando se llena ese buffer el resto de elementos recibidos se pierden.

Toda la información del puerto seríe del microcontrolador del arduino UNO la tenemos en la página 170 de http://www.atmel.com/images/Atmel-8271-8-bit-AVR-Microcontroller-ATmega48A-48PA-88A-88PA-168A-168PA-328-328P_datasheet_Complete.pdf

Para ampliar información:

Software Serial

¿Y si necesitas más puertos serie que los disponibles en un Arduino? Cada microcontrolador tiene un número de puertos serie hardware (UART), pero se ha desarrollado la librería SoftwareSerial para permitir la comunicación serie sobre otros pines digitales de Arduino, usando software para replicar las funcionalidades de la comunicación serie. Es posible tener varios puertos software serial con velocidades de hasta 115200 bps.

Ver funciones, limitaciones y ejemplos de la librería software serial en: http://arduino.cc/en/Reference/SoftwareSerial

Ejemplo de comunicación serie para comunicar con un shield GSM y mandar SMSs, usando el hw serial sin usar librerías o el sw serial usando librerías: http://arduinoguruji.blogspot.com.es/p/blog-page.html

Terminal Serie

Una vez visto cómo manejar el puerto serie en Arduino, si queremos comunicarnos con Arduino a través del puerto serie desde un ordenador debemos usar un emulador de terminal, el propio IDE de Arduino trae uno, pero existen otros más completos.

Terminales serie:

Otras alternativas al monitor serie: https://www.baldengineer.com/alternatives-to-arduinos-serial-monitor.html

En MAC usando el terminal con la utilidad screen:

ls /dev/tty.* (note the .*at the end) command to list all connected devices

screen /dev/xx.usbserial-XXXXXXXX 115200 –L

Ejemplos Arduino con Arrays y Strings

Efectos con leds mejorado

El ejemplo anterior de los LEDs con el efecto del coche fantástico puede hacerse de una forma más eficiente con el uso de los arrays y la estructura de control for. Además hacer otros efectos de luces o cambios en el realizado es mucho más sencillo usando arrays.

Hacer el efecto del coche fantástico usando arrays y la estructura de control for.

Tutorial: https://www.arduino.cc/en/Tutorial/KnightRider

Estructura de control for: https://www.arduino.cc/en/Reference/For

Esquema de conexión:

Solución: https://github.com/jecrespo/aprendiendoarduino-Curso_Arduino_2017/tree/master/Ejercicio09-CocheFantasticoMejorado

Control Velocidad del Efecto de Leds

Añadir el cambio de velocidad dentro del código al leer de un potenciómetro de forma que no haya que esperar a un ciclo de loop para cambiar la velocidad: “timer = analogRead(A0);”

Esquema de conexión:

O usando un LDR para el control de velocidad:

Solución: quitar los comentarios de https://github.com/jecrespo/aprendiendoarduino-Curso_Arduino_2017/tree/master/Ejercicio09-CocheFantasticoMejorado

Probar a hacer otros efectos como: https://github.com/jecrespo/Aprendiendo-Arduino/tree/master/Ejercicio48-Efectos_Led

Leer Strings por Puerto Serie

Aprender a manejar cadenas de caracteres es muy importante, a lo largo del curso se va a usar muy a menudo para comunicaciones y para interaccionar con el usuario.

Tutoriales para aprender a usar los Strings:

Hacer un programa donde al iniciar Arduino pregunta que introduzca un string cualquiera y lo mando a Arduino por puerto serie usando el monitor serie. Luego lo almacena en una variable y muestra lo leído por el puerto serie.

No olvidar poner en el setup() la inicialización del puerto serie: Serial.begin(9600);

Para leer por el puerto serie usar este código:

 
String cadena_leida;

while (Serial.available() == 0){
    //No hago nada
  }
  do{
    caracter_leido = Serial.read();
    cadena_leida += caracter_leido;
    delay(5);
  }  while (Serial.available() > 0);

La función Serial.available() me devuelve el número de bytes (caracteres) disponibles para leer del puerto serie. Estos son datos que han llegado al puerto serie de Arduino y se almacenan en el buffer de lectura de la UART. Más información: https://www.arduino.cc/en/Serial/Available

Serial.read() lee un caracter del puerto serie y los quita del buffer. Más información: https://www.arduino.cc/en/Serial/Read

NOTA para entender lo que está haciendo poner la constante DEBUG a valor 1

Solución: https://github.com/jecrespo/aprendiendoarduino-Curso_Arduino_2017/tree/master/Ejercicio10-LeerStringSerie

Encender LED por Puerto Serie

Modificar el ejemplo anterior para que encienda el led de Arduino (pin 13) cuando mande la cadena “enciende” y lo apague cuando mande la cadena “apaga”.

Esquema de conexión:

Para comparar el texto introducido se proponen dos opciones, probar con ambas:

 
if (leido.startsWith("enciende"))

if (leido == "enciende")

Solución: https://github.com/jecrespo/aprendiendoarduino-Curso_Arduino_2017/tree/master/Ejercicio11-EncenderLedSerie

NOTA: Al igual que leemos y analizamos un valor con lo recibido por el puerto serie, la forma de trabajar si la comunicación es por ethernet, wifi, bluetooth, XBee, etc… es la misma, Arduino está escuchando por el puerto de comunicación y cuando recibe una petición válida ejecuta una acción. Los módulos de comunicación hablan con el microcontrolador a través los puertos serie (UART), I2C o SPI, cuyo funcionamiento es similar a lo visto en estas dos últimas prácticas.

UART y USB en Arduino

Ya hemos visto  anteriormente que la UART o USART es el puerto serie hardware que todos los microcontroladores tienen al menos uno y la comunicación serie es la base de casi cualquiera de las comunicaciones de los microcontroladores.

El “Bus Universal en Serie”, en inglés: Universal Serial Bus más conocido por la sigla USB, es un bus estándar industrial que define los cables, conectores y protocolos usados en un bus para conectar, comunicar y proveer de alimentación eléctrica entre computadores, periféricos y dispositivos electrónicos.

Su desarrollo partió de un grupo de empresas del sector que buscaban unificar la forma de conectar periféricos a sus equipos, por aquella época poco compatibles entre si, entre las que estaban Intel, Microsoft, IBM, Compaq, DEC, NEC y Nortel. La primera especificación completa 1.0 se publicó en 1996, pero en 1998 con la especificación 1.1 comenzó a usarse de forma masiva.

La forma que tenemos de comunicar Arduino con el ordenador y para programarlo es mediante el USB. Casi todos los Arduinos y compatibles tienen un interfaz USB y sino usaremos un cable FTDI que nos hará la función de convertirnos el interfaz serie de la UART de Arduino a un interfaz USB. No confundir con lo visto anteriormente de uso del ICSP para programar, puesto que en ese caso programamos directamente la MCU sin necesidad de un bootloader.

El interfaz USB en el ordenador nos permite tener un puerto serie virtual que usamos para conectar con Arduino. Además de comunicación, USB es un interfaz de alimentación.

Físicamente un  USB tiene 4 pines:

Pin 1=> Alimentación con un voltaje de 5V DC
Pin 2 y 3 => Sirven para la transmisión de datos del BUS
Pin 4 = Masa o tierra

Aunque la mayoría de pc’s ya ofrecen protección interna se incorpora un fusible rearmable de intensidad máxima 500mA con la intención de proteger tanto la placa Arduino como el bus USB de sobrecargas y cortocircuitos. Si circula una intensidad mayor a 500mA por el bus USB (Intensidad máxima de funcionamiento), el fusible salta rompiendo la conexión de la alimentación. Podemos probar esto cortocircuitando GND y 5V en Arduino.

En el caso del USB el 0 y 1 se distingue por la diferencia de voltaje entre D+ y D-

Más información de USB:

Y para saber todo sobre USB ver “USB in a nutshell”: http://www.beyondlogic.org/usbnutshell/usb1.shtml

Para que un Arduino tenga un interfaz USB, necesita de un chip que ofrezca un interfaz USB, en algunos casos el propio microcontrolador ya dispone de ese interfaz y en otros caso utiliza un segundo microcontrolador con interfaz USB.

Tutorial USB:

Cuando conectamos un USB al ordenador, necesitamos un driver o trozo de software que nos  implemente la comunicación con el USB y nos monte un puerto serie virtual. Estos drivers deben estar certificados por http://www.usb.org/home y pagar las correspondientes licencias de uso. En el caso de Arduino los drivers ya están incluidos desde windows 8.1 y tienen su licencia de uso, por ese motivo cuando conectamos Arduino, automáticamente nos reconoce el dispositivo.

Todos los dispositivos USB tienen un USB vendor ID (VID) que identifica al fabricante y que es otorgado por http://www.usb.org/developers/vendor/ y un product ID (PID) que identifica el producto de ese vendedor. De esta forma es posible identificar un dispositivo USB por el ordenador. Más información: http://www.oshwa.org/2013/11/19/new-faq-on-usb-vendor-id-and-product-id/

Listado de VID:

Como sabemos hay dos Arduinos (arduino.cc y arduino.org) y por lo tanto hay dos VID para Arduino:

  • 2a03  dog hunter AG (arduino.org)
  • 2341  Arduino SA (arduino.cc)

Ejemplo de problemas con el uso de los drivers USB según el chip que lleve Arduino: http://blog.make-a-tronik.com/instalando-drivers-usb-serial-ch340g-para-arduino/

Cada dispositivo necesita tener unico product id y vendor id. Los VID son vendidos a los fabricantes y los PID son elegidos por cada compañía. Por ejemplo FTDI es el propietadior del VID #0403 y ellos dan a sus chips los IDs entre #0000 y #FFFF (65536 PIDs). Arduino tiene su propio VID y para el Arduino UNO el PID es el #0001

Si quisiéramos hacer cuenta propia placa compatible con Arduino hay varias opciones:

  • Usar un chip FTDI en lugar del 16u4 que ya tiene un VID
  • Si quieres hacer más de una placa y comercializar, tendrás que comprar un VID a usb.org en http://www.usb.org/developers/vendor/ y pagar la licencia
  • Si es para hacer una placa como experimento, puedes elegir un VID/PID que no interfiera con ninguno de los dispositivos del ordenador.
  • También es posible comprar licencias para un VID/PID de empresas que desarrollen dispositivos USB.

Sin embargo no es posible usar el VID de Arduino cuando quieres distribuir tu propia placa compatible con Arduino. Leer: http://electronics.stackexchange.com/questions/16665/arduino-uno-usb-vid-pid

En linux es posible ver mejor el proceso de reconocimiento de un dispositivo USB, leer: http://playground.arduino.cc/Linux/All

Tester de VID y PID basado en Arduino: https://learn.adafruit.com/simple-arduino-based-usb-vid-and-pid-tester/lets-do-this-thing

Para actualizar el firmware del Atmega16u2 que nos hace de interfaz entre el USB y el microcontrolador principal del Arduino UNO, seguir este procedimiento: http://arduino.cc/en/Hacking/DFUProgramming8U2.

Para comprobar la versión de firmware ir al gestor de dispositivos en Windows y buscar el Arduino, luego botón derecho y propiedades y buscar en driver details el VID, PID y el revision number.

La última versión del firmware está en https://github.com/arduino/Arduino/tree/master/hardware/arduino/avr/firmwares/atmegaxxu2 y usar un programador DFU como flip http://www.atmel.com/tools/flip.aspx para cargar el nuevo firmware.

Cuando usamos un Arduino basado en el microcontrolador ATmega32u4 como el leonardo, nos encontramos con que se hace una re-enumeración del puerto serie en el reset.

Puesto que estas placas no tienen un chip dedicado para manejar la comunicación serie y tienen un interfaz USB integrado, eso significa que el puerto serie es virtual, es una implementación software tanto en el ordenador como en la placa. Así como el ordenador crea una instancia del puerto serie cuando lo enchufas, el Arduino Leonardo crea una instancia serie cuando se ejecuta el bootloader. La placa es una instancia de un USB driver Connected Device Class (CDC), esto significa que cada vez que reseteas la placa, la conexión USB serie es rota y restablecida de nuevo. La placa desaparecerá de la lista de puertos serie y la lista se re-enumerará. Cualquier programa que tenga una conexión serie abierta con el Arduino Leonardo perderá su conexión. En el caso del Arduino cuando se resetea la placa se está reseteando el procesador principal ATmega328p sin cerrar la conexión USB que es mantenida por el microcontrolador secundario ATmega16u2. Esta diferencia de comportamiento tiene implicaciones en la carga y comunicación con el microcontrolador.

Los Arduinos basados en el ATmega32u4 aparecen también como un dispositivo genérico USB de teclado y ratón, y puede ser programado para controlar estos dispositivos usando las clases MouseKeyboard https://www.arduino.cc/en/Reference/MouseKeyboard, de forma que Arduino puede conportarse como un teclado u un ratón.

Más información: https://en.wikipedia.org/wiki/USB_communications_device_class

Cuando usamos un Arduino basado en el ATmega32u4 debemos usar la función if(serial) https://www.arduino.cc/en/Serial/IfSerial que indica si el puerto serie está preparado y en el caso del Leonardo, indica si la USB CDC serial connection está abierta. De esta  forma nos aseguramos que arranca el programa de Arduino cuando ya hay conexión entre el Arduino y el ordenador, sino podríamos perder los primeros envíos del Arduino al ordenador.

En el Arduino Leonardo, la clase Serial se refiere a la comunicación USB CDC, para la comunicación por TTL en los pines 0 y 1, se debe usar la clase Serial1.

En los Arduino basados en Atmega32u4 como el Arduino Leonardo usar:

void setup() { 
 //Initialize serial and wait for port to open:
  Serial.begin(9600); 
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB
  }
} 

V_USB es una implementación software de un dispositivo USB para microcontroladores USB, haciendo posible construir hardware USB con casi cualquier MCU AVR, sin necesidad de un chip adicional. Se trata de un puerto USB software. Más información:

USART Arduino

La USART es el puerto serie de los microcontroladores que en el caso de Arduino están conectadas a los pines 0 y 1.

UART: http://es.wikipedia.org/wiki/Universal_Asynchronous_Receiver-Transmitter. Las funciones principales de la UART son de manejar las interrupciones de los dispositivos conectados al puerto serie y de convertir los datos en formato paralelo, transmitidos al bus de sistema, a datos en formato serie, para que puedan ser transmitidos a través de los puertos y viceversa.

Arduino se conecta a nuestro ordenador a través del puerto USB, pero el puerto USB se debe conectar al microcontrolador a través del puerto serie, por ello debemos entender cómo están relacionados el puerto USB y el puerto serie.

En un Arduino usamos el puerto USB para tres funciones: cargar nuestro programa ya compilado en la memoria flash, conectarnos al puerto Serie (UART) predefinido en cada Arduino para comunicarnos durante la ejecución del programa y adicionalmente alimentar a Arduino. Todo ello se puede hacer sin la necesidad del puerto USB, pero dada la facilidad de uso y que todos los ordenadores disponen de un puerto USB, nos facilita mucho hacer estas operaciones.

El puerto serie conectado al USB lo usamos como puerto de consola o puerto de debug.

La UART normalmente no genera o recibe directamente las señales externas entre los diferentes módulos del equipo. Usualmente se usan dispositivos de interfaz separados para convertir las señales de nivel lógico del UART hacia y desde los niveles de señalización externos, como puede ser RS232 o RS485. Una UART está normalmente en un circuito integrado usado para comunicaciones serie sobre un ordenador u otro dispositivo periférico.

Los microcontroladores como el ATmega328p tiene USART (Universal Syncronous Asyncronous Receiver Transmitter). Una USART puede trabajar igual que una UART, pero tiene la capacidad adicional de actuar como síncrona, esto significa que los datos van sincronizados con una señal de reloj. El reloj es recuperado desde los propios datos o enviado como como una señal externa. En ese caso no se usan los bits de start y stop, lo que permite una velocidad en baudios mayor al operar en modo síncrono porque la temporización de los bits tienen una cierta garantía y más bits pueden ser usados para datos en lugar de cabeceras.

Por el contrario la UART dispone de una señal de reloj interno y los datos en el bus pueden tener una temporización más irregular. Las UART requieren bits de start y stop y los datos asíncronos sólo se sincronizan con los bits de start y stop. La palabra asíncrono indica que la UART recupera la temporización de los caracteres desde el flujo de datos, usando el bit de start y el de stop para indicar el marco de cada carácter.

En la transmisión síncrona, la señal de reloj es recuperada de forma separada del stream de datos, esto mejora la eficiencia de la transmisión al haber más bits de datos en la transmisión. Una conexión asíncrona no manda nada cuando el dispositivo que transmite no tiene nada que mandar, pero un interfaz síncrono debe mandar caracteres para mantener el sincronismo entre emisor y receptor, normalmente el carácter ASCII “SYN” se encarga de rellenar este hueco y esto puede ser hecho automáticamente por el dispositivo transmisor.

Diferencia entre UART y USART:

Para saber todo sobre la USART de Arduino y la comunicación serie ver:

La configuración de la UART de los microcontroladores AVR necesita acceder a unos registros:

  • USART Band Rate Register – UBRRH &UBRRL
  • USART Control and Status Register A – UCSRA
  • USART Control and Status Register B – UCSRB
  • USART Control and Status Register C – UCSRC
  • USART Data Buffer Register – UDA

UART es un módulo de hardware que traduce los datos de paralelo a serial para ser transmitidos, las UARTs son usadas comúnmente en conjunto con estándares de comunicación como EIA, RS-232, RS-422 o RS-485. la designación «universal» indica que el formato de los datos y las velocidades de transmisión pueden ser configuradas.

UART es normalmente un circuito integrado individual usado para comunicaciones de un sistema de cómputo, son normalmente incluidas en microcontroladores. Actualmente estos circuitos pueden comunicarse de manera sincrónica y asincrónica y son conocidos como USART. Las funciones principales de chip UART son: manejar las interrupciones de los dispositivos conectados al puerto serie y convertir los datos en formato paralelo, transmitidos al bus de sistema, a datos en formato serie, para que puedan ser transmitidos a través de los puertos y viceversa.

La USART de Arduino es un puerto de comunicaciones muy versátil (UNIVERSAL SYNCHRONUS and ASYNCHRONUS serial RECEIVER and TRANSMITTER). Se puede configurar como síncrono o como asíncrono. Los pines de conexión de la placa UNO que se utilizan con este periférico interno son los siguientes:

  • PIN 0 (RXD)   – Puerto D del microcontrolador  PD0
  • PIN 1 (TXD)   – Puerto D del microcontrolador  PD1
  • PIN 13 (SCK) – Puerto B del microcontrolador  PB15 (Sólo para el modo síncrono)

Para poder realizar la comunicación, los dispositivos que se vayan a comunicar deben conocer varios aspectos de ésta. El primero es la velocidad a la que se va a realizar, es decir a qué baudios se va a realizar la transmisión.

La comunicación comienza con una señal de Start, seguida de los bits a enviar, y se pueden seleccionar entre 5 y 9 bits a mandar, después tenemos que seleccionar si va a haber un bit de paridad para comprobar errores y por último si tenemos uno o dos bits de Stop. Estos parámetros han de estar configurados de igual manera en los dos dispositivos que se van a comunicar.

En la placa UNO se utiliza la USART para que el Atmega328  se comunique con el otro microcontrolador ATmega16U2 que hace la interface al puerto USB. Los leds (TX LED y RX LED) parpadean para indicar actividad en el puerto serie a través de la USART.

El baudio es una unidad de medida utilizada en telecomunicaciones, que representa el número de símbolos por segundo en un medio de transmisión digital. Cada símbolo puede codificar 1 o más bits dependiendo del esquema de modulación, un bit siempre representa dos estados, por lo tanto baudios por segundo no siempre es equivalente a bits por segundo, los símbolos son las unidades de información estas se representan en bits, de manera que la tasa de bits será igual a la tasa de baudios sólo cuando sea 1 bit por símbolo.

Principales características del módulo USART, para mayor información ver datasheet del microcontrolador.

  • Full Duplex Operation (Independent Serial Receive and Transmit Registers)
  • Asynchronous or Synchronous Operation
  • Master or Slave Clocked Synchronous Operation
  • High Resolution Baud Rate Generator
  • Supports Serial Frames with 5, 6, 7, 8, or 9 Data bits and 1 or 2 Stop Bits.

Antes de continuar es importante resaltar que AVR UART y USART son totalmente compatibles en términos de registros, generación de tasa de baudios, operaciones de buffer y funcionalidad de buffer en el transmisor/receptor. A continuación un resumen rápido de la configuración del módulo UART.

  1. Establecer la velocidad de transmisión en emisor y receptor debe ser la misma para poder realizar la comunicación.
  2. Establecer el número de bits de datos que deben ser enviados.
  3. Mantener el buffer listo, si es una transmisión cargarlo con el dato a transmitir, si es una recepción almacenar el dato recibido para poder recibir mas datos sin perder información
  4. Por último habilitar el transmisor/receptor de acuerdo con el uso que se le desee dar.

En el caso de la transmisión sincrónica (USART) es necesario enviar el reloj del sistema el microcontrolador que envía esta señal se llama Maestro y el otro se denomina esclavo; para transmisión Asíncrona no se hace esta denominación para los transmisores/receptores.

La tasa de baudios se establece en el registro de 16 bits UBRR:

Más información: http://sistdig.wikidot.com/wiki:usart  

Más información sobre la USART del MCU ATmega328p, ver página 170 de http://www.atmel.com/images/Atmel-8271-8-bit-AVR-Microcontroller-ATmega48A-48PA-88A-88PA-168A-168PA-328-328P_datasheet_Complete.pdf

Estándares de comunicación serie que definen las características eléctricas de los drivers y los receptores:

Explicación de la diferencia entre comunicación RS232 y TTL: RS-232 vs. TTL Serial Communication y http://www.atmel.com/Images/doc4322.pdf

USB to Serial en Arduino

Cuando conectamos Arduino a un ordenador mediante un cable USB, el ordenador instala un puerto serie virtual (COM) desde el cual podemos acceder al puerto serie de Arduino. Por este motivo es necesario instalar en el ordenador los drivers de interfaz USB de los microcontroladores de Atmel, esto se hace automáticamente al instalar el IDE de Arduino.

Arduino UNO como otros Arduinos disponen de microcontroladores que no tienen un interfaz USB incorporado, por lo tanto no se pueden conectar directamente a un Ordenador. Para ello usan un segundo microcontrolador que hace de intermediario, generalmente un ATmega16u2 que dispone de un interfaz USB. Este microcontrolador dispone de un firmware especial que facilita la carga del programa en la flash del Arduino y comunicar posteriormente por el USB.

Este firmware y su código se puede ver en https://github.com/arduino/Arduino/tree/master/hardware/arduino/avr/firmwares/atmegaxxu2/arduino-usbserial

Los microcontroladores de 8 bits mega AVR con interfaz USB están configurados de fábrica con un bootloader USB, este permite hacer un In-System Programming desde el interfaz USB sin eliminar la parte del sistema o sin una aplicación preprogramada y sin un un interfaz externo de programación.

USB DFU (Device Firmware Update) Bootloader: http://www.atmel.com/Images/doc7618.pdf

Más información del microcontrolador en: http://www.atmel.com/Images/Atmel-7766-8-bit-AVR-ATmega16U4-32U4_Datasheet.pdf

Niveles lógicos

Los niveles lógicos de los microcontroladores, son los niveles físicos de voltaje por los que se interpreta un microcontrolador un 1 y un 0. Niveles lógicos: https://en.wikipedia.org/wiki/Logic_level

En el caso de los ATmega AVR usan Tecnología TTL: http://es.wikipedia.org/wiki/Tecnolog%C3%ADa_TTL. Su tensión de alimentación característica se halla comprendida entre los 4,75V y los 5,25V (como se ve, un rango muy estrecho). Normalmente TTL trabaja con 5V. Los niveles lógicos vienen definidos por el rango de tensión comprendida entre 0,0V y 0,8V para el estado L (bajo) y los 2,2V y Vcc para el estado H (alto). La velocidad de transmisión entre los estados lógicos es su mejor base, si bien esta característica le hace aumentar su consumo siendo su mayor enemigo. Motivo por el cual han aparecido diferentes versiones de TTL como FAST, LS, S, etc y últimamente los CMOS: HC, HCT y HCTLS. En algunos casos puede alcanzar poco más de los 400 MHz.

TTL logic levels: https://learn.sparkfun.com/tutorials/logic-levels/ttl-logic-levels

Interesante nota de TI sobre como elegir la solución más adecuada para la conversión de niveles lógicos.

Niveles lógicos de Arduino: https://learn.sparkfun.com/tutorials/logic-levels/arduino-logic-levels

A medida que la tecnología avanza se crean dispositivos que necesitan menor consumo eléctrico y usan un menor voltaje de base (Vcc = 3.3 V en lugar de 5V). La técnica de fabricación es también diferente para dispositivos de 3.3V que permiten una huella menor y costes más pequeños. Para asegurar la compatibilidad de los dispositivos a 3.3V, se puede ver que la mayoría de los niveles de voltaje son casi los mismos para dispositivos de 3.3V y los de 5V. Un dispositivo de 3.3V puede interactuar con uno de 5V sin componentes adicionales. Por ejemplo un 1 lógico (HIGH) de un dispositivo de 3.3V será al menos 2.4V, esto sigue siendo interpretado como un 1 lógico en un dispositivo de 5V porque está por encima  de VIH que es 2V.

Sin embargo hay que tener en cuenta que un dispositivo de 3.3V es tolerante a señales de 5V, esta especificación es el “maximum input voltage” del dispositivo. En ciertos dispositivos de 3.3V, cualquier voltaje supuerior a 3.6V provocará un daño permanente en el chip, para evitar esto se puede usar un simple divisor de tensión (https://learn.sparkfun.com/tutorials/voltage-dividers) como una resistencia de 1KΩ y una de 2KΩ para bajar los 5V o usar un logic level shifter como https://www.sparkfun.com/products/12009

Voltaje 5V vs 3.3V http://jeelabs.org/2010/12/16/voltage-3-3-vs-5/

Cable FTDI

Cable FTDI es la forma más fácil de conectar el microcontrolador a un ordenador por USB. Consiste en un chip de conversión USB a Serie. Como ocurre con Arduino cuando lo conectamos, necesitamos los drivers de windows, cuando conectamos un cable FTDI también necesita sus drivers. Los driver FTDI vienen integrados en el IDE de Arduino.

FTDI es el fabricante más popular de chips conversores de USB a serie.

Drivers: https://web.archive.org/web/20141005060035/http://www.ftdichip.com/Drivers/VCP.htm

Productos de FTDI:

Chip FTDI:

FT231X tiene un buffer de comunicación mayor comparado con el FT232R. El FT231X tiene los niveles lógicos de 3.3 V y con entradas tolerantes a 5V. FTDI provee de drivers para los dispositivos USB incluyendo driver certificados para Windows, incluido Windows 10.

Interesante artículo sobre la comunicación serie con MCUs AVR: http://www.evilmadscientist.com/2009/basics-serial-communication-with-avr-microcontrollers/

Cable par comunicar con dispositivos de 3.3V: https://www.sparkfun.com/products/9873

Al comprar un cable FTDI hay que estar atento al pineado que no es el que usan los Arduino Ethernet y otros elementos, es posible que para conectarlo a un Arduino haya que intercambiar algunos pines. Este es el pineado correcto y los colores de los cables para un FTDI para Arduino:

ftdi

Existen en el mercado cable con otros colores y el pineado desordenado. Estos son los colores del cable y a que corresponde:

  • Red wire: 5V
  • Black wire: GND
  • White wire: RXD
  • Green wire: TXD
  • Yellow wire: RTS
  • Blue wire: CTS

Y el pineado bueno para arduino queda así:

ftdi luis

Los pines CTS y RTS es el flow control (control de flujo). El pin RTS es una salida y debe conectarse al pin de entrada CTS del otro dispositivo de la conexión a la UART.

  • Si el pin RTS está a 0, indica que puede aceptar más datos en el pin RXD
  • Si el pin RTS está a 1, indica que no puede aceptar más datos.

Los cambios de estado del pin RTS ocurren cuando el buffer del chip alcanza los últimos 32 bytes de espacio para dejar tiempo al dispositivo externo para que pare el envío de datos.

El pin CTS es una entrada y debe ser conectado a la salida RTS del dispositivo al otro extremo.

  • Si el pin CTS está a 0, indica que el dispositivo externo puede aceptar más datos y transmitirá por el pin TXD.
  • Si el pin CTS está a 1, indica que el dispositivo externo no puede aceptar más datos y parará la transmisión de datos en los siguientes 0 – 3 caracteres, dependiendo de lo que haya en el buffer de salida. Se debe tener en cuenta que al ser un dispositivo USB opera en base a paquetes y no a bytes.

CTS y RTS en RS232: https://en.wikipedia.org/wiki/RS-232#RTS.2C_CTS.2C_and_RTR

También en algunos dispositivos serie nos podemos encontrar con el pin DTR que es el control de flujo https://en.wikipedia.org/wiki/Data_Terminal_Ready. El DTR permite a Arduino hacer el auto reset cuando un nuevo sketch es cargado a la memoria flash. Esto permite cargar un sketch sin tener que pulsar el botón de reset.

Una de las líneas del hardware flow control (DTR) del ATmega8U2/16U2, están conectadas a la línea de reset del MCU ATmega328P a través de un condensador de 100 nanofaradios. Cuando esta línea se pone a 0 V, es capaz de resetear el MCU de Arduino. El IDE de Arduino usa esta capacidad para permitir cargar código a Arduino simplemente presionando el botón upload y hace que el el timeout del bootloader pueda ser menor y estar mejor coordinado con el comienzo de la carga del sketch.

Cuando se detecta un flujo de datos a través del interfaz USB conectando un ordenador al Arduino, automáticamente se resetea la MCU de Arduino y durante el siguiente medio segundo, el bootloader se ejecuta en Arduino. Como el bootloader está programado para ignorar datos malformados (cualquier cosa que no sea nuevo código de un sketch), interceptará los primeros bytes de los datos enviados a la placa tras la conexión. Por este motivo si un sketch está programado para recibir una comunicación por el puerto serie tras iniciarse, hay que asegurarse que el software que manda esa información espera al menos un segundo después de que se abra la conexión hasta que se manden los primeros datos.

Ojo con los chips FTDI falsos: http://hackaday.com/2016/02/01/ftdi-drivers-break-fake-chips-again/

Diferencia entre programadores AVR o adaptadores FTDI:

  • Los programadores AVR son más poderosos puesto que permite programar cualquier AVR, incluso los que vienen son bootloader de fábrica, pero también significa que es posible brickear el chip. Usando un programador se debe tener en cuenta que se sobreescribirá el bootloader.
  • Los adaptadores FTDI pueden enviar cualquier dato por puerto serie, incluyendo programar AVRs con un bootloader en ellos.

Más información de uso de un FTDI: https://cdn-learn.adafruit.com/downloads/pdf/ftdi-friend.pdf

Para las prácticas del curso disponemos de esta placa FTDI para programar tanto dispositivos a 5v como a 3.3 (los que habitualmente hay dispobles suelen ser a 5V), con selector de voltaje: http://www.tinyosshop.com/index.php?route=product/product&product_id=600, además este tiene DTR para conectar al reset y poder programar un arduino.

El FTDI usado usa el chip FT232 con características:

  • Interfaz estándar compatible con el tipo de controlador oficial de Arduino
  • Chipset FT232 original, funcionamiento estable, indicador de transmisión y recepción.
  • opción de fuente de alimentación 5V/3.3V
  • Chip de FT232R es la solución de un solo chip, con oscilador de cristal

FT232R tiene algunas funciones útiles:

Los microcontroladores AVR de Arduino para programarlos directamente por puerto serie, van a 5V, aunque si se usa un programador de 3.3v funciona porque el rx de arduino toma 0 cuando el voltaje es inferior a 0.7V y 1 cuando es superior a 2,4V.

Tal y como indica en las características del Arduino UNO en https://www.arduino.cc/en/main/arduinoBoardUno: “The Uno has a number of facilities for communicating with a computer, another Uno board, or other microcontrollers. The ATmega328 provides UART TTL (5V) serial communication, which is available on digital pins 0 (RX) and 1 (TX).”

Pero no solo se puede programar Arduino mediante el USB o por el puerto ICSP, sino que también es posible hacerlo mediante un cable FTDI conectado al puerto serie de Arduino. Para programar con el adaptador FTDI, necesitaré de un bootloader, con ICSP no.