Archivo de la etiqueta: Comunicación Serie

Estructuras Propias de Arduino

Lo visto hasta ahora son estructuras y sintaxis de programación que es casi genérica a C++, pero el core de Arduino incluye algunas funciones propias para el uso de Arduino como la lectura de entradas analógicas y digitales y la escritura de salidas analógicas y digitales.

Para saber más de C y de la API de Arduino:

Veamos estas estructuras más específicas que están documentadas en el reference de Arduino https://www.arduino.cc/en/Reference/HomePage

Cómo Leer el Reference Arduino

En el reference de Arduino tenemos toda la información necesaria para entender cómo funciona el lenguaje o core de programación de Arduino. Está todo perfectamente documentado de cómo funciona cada estructura y cómo se comportan las funciones,

Reference: https://www.arduino.cc/en/Reference/HomePage 

Cuando entramos en el reference y vemos un nuevo método o función deberemos leer:

  • Description: Hace una descripción de lo que hace ese método y función
  • Syntax: Sintaxis de la función con todas las formas de llamarlo y los parámetros a pasar. Puede haber varias formas de llamar a una función, por ejemplo https://www.arduino.cc/en/Reference/EthernetBegin
  • Parameters: Descripción de los parámetros a pasar a esa función. Puede que no haya que pasar ninguno: https://www.arduino.cc/en/Reference/Millis
  • Returns: que valor me devuelve y qué tipo de dato es. Puede que no devuelva nada como https://www.arduino.cc/en/Reference/PinMode
  • Note: Nota sobre el uso de la función
  • Example: Un ejemplo de cómo usar la función
  • See Also: Otras funciones relacionadas

Entradas y Salidas Digitales

En arduino para tratar las entradas y salidas digitales usamos las siguientes funciones:

En la imagen siguiente se muestra el estado por defecto de una I/O digital en un microcontrolador de Arduino. Se ha simplificado con interruptores la compleja electrónica que hay dentro. Por defecto los digital I/O pins están configurados como inputs en un estado de alta impedancia (equivalente a una resistencia de 100 Mohms en frente del pin), es decir, SW3 a ON y no hace falta llamar a la función pinMode() aunque es recomendable para aclarar el código.

  • PinMode(x, INPUT) –> SW3 = ON (resto a OFF). Los valores leídos serán aleatorios si el pin de Arduino está al aire. El pin está en un estado de alta impedancia (resistencia de 100 Mohms).
  • PinMode(x,INPUT_PULLUP) –> SW3 = ON & SW4 = ON (resto a OFF). Los valores leídos sin nada conectado al pin es HIGH. La Resistencia R1 tiene un valor dependiendo del microcontrolador, pero tiene un valor entre 20kOhm y 150kOhm.
  • PinMode(x, OUTPUT) & digitalWrite(x,HIGH) –> SW2 = ON & SW1 = +5V (resto a OFF). Estado de baja impedancia, no hay resistencia interna y es necesario poner una resistencia adecuada a la salida el pin para no superar los 40mA (source) máximos admitidos
  • PinMode(x, OUTPUT) & digitalWrite(x,LOW) –> SW2 = ON & SW1 = GND (resto a OFF). Estado de baja impedancia, no hay resistencia interna y es necesario poner una adecuada para no superar los 40mA (sink) máximos admitidos

Entradas y Salidas Analógicas

En Arduino para tratar las entradas y salidas analógicas usamos las siguientes funciones:

Otras funciones interesantes con entradas/salidas analóicas:

La mayoría de Arduino no tienen salidas analógicas puras sino PWM. Algunos pines digitales pueden usarse como salidas analógicas PWM:

Las Salidas PWM (Pulse Width Modulation) permiten generar salidas analógicas desde pines digitales. Arduino Uno no posee salidas analógicas puras, sin embargo el Arduino Due sí tiene salidas analógicas puras mediante dos DAC. El arduino due, posee dos salidas analógicas puras mediante dos conversores digital a analógico. Estos pines pueden usarse para crear salidas de audio usando la librería correspondiente.

La modulación por ancho de pulsos (también conocida como PWM, siglas en inglés de pulse-width modulation) de una señal o fuente de energía es una técnica en la que se modifica el ciclo de trabajo de una señal periódica (una senoidal o una cuadrada, por ejemplo), ya sea para transmitir información a través de un canal de comunicaciones o para controlar la cantidad de energía que se envía a una carga.

El ciclo de trabajo de una señal periódica es el ancho relativo de su parte positiva en relación con el período. duty cycle = (tiempo que la salida está a uno o HIGH)/ (periodo de la función)

Diferentes valores de una señal PWM:

Entradas y Salida Avanzadas

Advanced I/O:

  • tone() – Genera una onda cuadrada (ciclo y 50% de servicio) de la frecuencia especificada en un pin. Una duración se puede especificar, de lo contrario la onda continúa hasta una llamada a noTone (). El pin puede ser conectado a un zumbador piezo u otro altavoz para reproducir tonos.
  • noTone() – Detiene la generación de una onda cuadrada provocada por tone(). No tiene ningún efecto si no se está generando el tono.
  • shiftOut() – Desplaza un byte de datos de un bit cada vez. Comienza a partir del más o menos significativo. Cada bit es escrito en un pin cada vez que se produce un pulso de reloj.
  • shiftIn() – Desplaza un byte de datos de un bit cada vez. Comienza a partir dell más o menos significativo. Para cada bit, el reloj es puesto a HIGH, el siguiente bit es leído de la línea de datos y entonces el reloj es puesto a LOW.
  • pulseIn() – Lee un pulso de un pin. Si el valor es HIGH, la función espera a que el pin se ponga a HIGH, comienza a temporizar y espera hasta que el pin vuelve a LOW, devolviendo la longitud del pulso en microsegundos.

Ejemplo de uso: https://www.arduino.cc/en/Tutorial/ShiftOut 

Bits y Bytes

Bits and Bytes

  • lowByte(): extrae el byte más a la derecha (low-order o menos significativo de una variable.
  • highByte(): extrae el byte más a la izquierda (high-order o más significativo de una variable.
  • bitRead(): lee el bit de una variable numérica. 
  • bitWrite(): escribe el bit de una variable numérica
  • bitSet(): pone a 1 un bit de una variable numérica 
  • bitClear(): pone a 0 un bit de una variable numérica 
  • bit(): Calcula el valor del bit especificado (el bit 0 es 1, el bit 1 es 2, el bit 2 es 4, etc.)

Constantes

Constants;

  • HIGH | LOW – Al leer o escribir en un pin solo hay estas dos posibilidades. Su significado es diferente si el pin está configurado como INPUT o OUTPUT.
  • INPUT | OUTPUT | INPUT_PULLUP – Modo en el que pueden configurarse los pines digitales.
  • LED_BUILTIN – La mayoría de las placas Arduino tienen un pin conectado a un led en la placa y esta constante devuelve el número de pin en función de la placa.
  • true | false – Representación de las constantes booleanes en arduino
  • integer constants – son los números usados directamente en un sketch como ‘123’. Por defecto estos números son tratados como enteros pero puede cambiarse con los modificadores U y L. Las constante enteras se tratan como base 10 (decimal) pero puede usarse otra notación.
  • floating point constants – al igual que las constantes enteras, las constantes de coma flotante permite definir los número decimales. Son posibles varias notaciones para expresar constantes de coma flotante, por ejemplo: n = .005. También pueden expresarse en notación científica como 2.34E5.

Utilidades

Utilities:

  • sizeof() – devuelve el número de bytes en una variable o el número de bytes ocupados por un array.
  • PROGMEM – se usa para guardar en la memoria flash en lugar de en la SRAM. Al usarlo le dice al compilador que ponga la información de la variable en la memoria flash en lugar de la SRAM, donde iría normalmente.

PROGMEM es parte de la librería pgmspace.h http://www.nongnu.org/avr-libc/user-manual/group__avr__pgmspace.html que solo está disponible para la arquitectura AVR, así que para usarlo hay que inclirla al principio del sketch con #include <avr/pgmspace.h>

La macro F() se puede usar para facilitar el manejo de PROGMEM en las instrucciones print, de forma que todo el texto a imprimir (ya sea en Serial, Ethernet u otra librería) se lea de la Flash y no ocupando tamaño en la SRAM. Esta macro está incluida en el core de Arduino.

Operadores Bit a Bit

Bitwise Operators:

  • & (bitwise and)
  • | (bitwise or)
  • ^ (bitwise xor)
  • ~ (bitwise not)
  • << (bitshift left)
  • >> (bitshift right)

Operadores Compuestos

Compound Operators

  • ++ (increment)
  • (decrement)
  • += (compound addition)
  • -= (compound subtraction)
  • *= (compound multiplication)
  • /= (compound division)
  • %= (compound modulo)
  • &= (compound bitwise and)
  • |= (compound bitwise or)

Ambito de las Variables y Calificadores

Variable Scope & Qualifiers

  • variable scope – ámbito de la variable
  • static – hace que el valor de una variable local persista más alla de la función haciendo que su valor se mantenga entre llamadas a funciones
  • volatile – Declarar una variable volátil es una directiva para el compilador. Específicamente, dice al compilador que cargue la variable desde la RAM y no desde un registro de almacenamiento, que es una ubicación de memoria temporal donde se almacenan y manipulan las variables del programa. Bajo ciertas condiciones, el valor de una variable almacenada en registros puede ser inexacto.
  • const – es un cualificador de variable que modifica el comportamiento de la variable haciendo que sea de solo lectura.

Se deben declarar como “volatile” cualquier variable que sea modificada dentro de la función llamada por una interrupción.

Funciones de Tiempo

Funciones para trabajar con el tiempo

  • delay() – Para el programa en unidades de ms
  • delayMicroseconds() – Para el programa en unidades de us
  • micros() – Microsegundos transcurridos desde el inicio o reset de la placa
  • millis() – Milisegundos transcurridos desde el inicio o reset de la placa

Funciones USB

Keyboard – Las funciones del teclado permiten que las tarjetas micro basadas en 32u4 o SAMD envíen las pulsaciones de teclas a un ordenador conectado a través del puerto USB nativo de su micro.

Mouse – Las funciones del ratón permiten a las tarjetas micro basadas en 32u4 o SAMD controlar el movimiento del cursor en un ordenador conectado a través del puerto USB nativo de su micro. Cuando se actualiza la posición del cursor, siempre es relativa a la posición anterior del cursor.

Funciones Matemáticas

La librería math.h ya está incluida por defecto en Arduino. 

Librería math C++: http://www.cplusplus.com/reference/cmath/

Librería math.h de AVR libc:

Algunas de la funciones matemáticas del Reference de Arduino:

Números Pseudoaleatorios

random() – generador de números pseudoaleatorios

randomSeed() – Inicializa el generador de números

Comunicación Serie

Librería Stream de la que heredan las librerías de comunicación serie: https://www.arduino.cc/reference/en/language/functions/communication/stream/

Comunicación serie: https://www.arduino.cc/reference/en/language/functions/communication/serial/

Funciones:

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

Comunicación Serie Arduino

La comunicación serie es muy importante porque casi todos 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 generalmente para comunicar el Arduino con el Ordenador.

Para manejar el puerto serie en Arduino, disponemos de la librería Serial http://arduino.cc/en/Reference/Serial que hereda los métodos de la librería Stream https://www.arduino.cc/en/Reference/Stream

Todas las placas Arduino tienen al menos un puerto serie disponible en los pines digitales 0 (RX) y 1 (TX) compartido con el USB. 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 y todos los puestos serie tienen niveles de 3.3V TTL.

Métodos más importantes de la librería Serial:

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

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

Software Serial

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.

Reference de la librería Software Serial, limitaciones y ejemplos en: http://arduino.cc/en/Reference/SoftwareSerial

Práctica: Puerto Serie

Hacer esta práctica de un chat por el puerto serie entre dos ordenadores usando dos Arduinos: https://aprendiendoarduino.wordpress.com/2016/07/02/chat-serie/

Práctica: Menú interactivo con Arduino.

Para unir todo lo visto en una práctica, hacer un ejemplo de un menú interactivo donde se dan varias opciones y pulsando cada una de ellas se ejecuta una acción concreta. Si el valor pulsado no es ninguna de las opciones avisar y volver a mostrar el menú hasta que se pulse una opción correcta.

Solución: https://github.com/jecrespo/Aprendiendo-Arduino/tree/master/Ejercicio46-Estructuras_de_Control

Modificar el programa para que haga la pregunta de forma continua.

Chat Serie

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.

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 básica: https://github.com/jecrespo/Aprendiendo-Arduino/tree/master/Ejercicio22-ChatSerie

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