2a Modulo Arduino (1)
2a Modulo Arduino (1)
Programación en informática
En el ámbito de la informática, la programación refiere a la acción de crear programas o aplicaciones a
través del desarrollo de un código fuente, que se basa en el conjunto de instrucciones que sigue el ordenador
para ejecutar un programa.
La programación es lo que permite que un ordenador funcione y realice las tareas que el usuario solicita.
Los programas informáticos suelen seguir algoritmos, que son el conjunto de instrucciones organizadas y
relacionadas entre sí que permiten trabajar al software de los equipos de computación.
Historia de la programación
Los comienzos del desarrollo de la programación informática coinciden con la aparición de las primeras
computadoras en la segunda mitad del siglo XX. La historia de la programación se puede describir a través
del desarrollo de los diferentes lenguajes de programación:
Lenguaje máquina. En este primer período se utilizaban lenguajes máquina muy básicos y limitados
basados en el sistema binario (uso de los números 0 y 1 en distintas combinaciones) que es el lenguaje que
los ordenadores reconocen, por lo que aún hoy todo lenguaje es convertido a este. Fue reemplazado, ya
que resultaba una forma de programación tediosa y difícil.
Lenguaje ensamblador. Más tarde comenzaron a surgir lenguajes que hacían uso de códigos de palabras.
Se utilizaban palabras simples, mnemotécnicas y abreviaturas que tenían su correlativo y eran traducidas
al código máquina. El lenguaje ensamblador fue incorporado porque resultaba más fácil de recordar y
realizar por el usuario que el código máquina.
Lenguaje de alto nivel. A finales de la década del 50 surgió el Fortran, un lenguaje de programación
desarrollado por IBM que dio inicio a la aparición de lenguajes basados en conjuntos de algoritmos mucho
más complejos. Estos lenguajes se adaptaban a distintos ordenadores y eran traducidos por medio de un
software al lenguaje de máquina.
Tipos de programación
Programación estructurada. Busca mejorar y reducir el tiempo del proceso al utilizar subrutinas
(subalgoritmos dentro del algoritmo principal que resuelve una tarea).
Programación modular. Divide los programas en módulos para trabajar con ellos y resolver
los problemas de manera más simple.
UEF CYI 1
Programación orientada a objetos. Utiliza objetos (entes con características, estado y comportamiento)
como elementos fundamentales para la búsqueda de soluciones.
Elementos de la programación
Existen ciertos elementos que son clave a la hora de conocer o ejecutar un lenguaje de programación, entre
los más representativos están:
Palabras reservadas. Palabras que dentro del lenguaje significan la ejecución de una instrucción
determinada, por lo que no pueden ser utilizadas con otro fin.
Operadores. Símbolos que indican la aplicación de operaciones lógicas o matemáticas.
Variables. Datos que pueden variar durante la ejecución del programa.
Constantes. Datos que no varían durante la ejecución del programa.
Identificadores. Nombre que se le da a las diferentes variables para identificarlas.
El lenguaje
El lenguaje es nuestro principal medio de comunicación y es el que permite que interactuemos entre humanos,
así ha sido siempre. Por ejemplo, para una sociedad humana, el lenguaje contiene los elementos necesarios
que permite a las personas comunicarse. Estos elementos pueden ser palabras, señas o sonidos que en sí
mismos son abstractos, sin embargo, para las personas que forman parte de la sociedad, tienen un sentido,
expresan un significado y señalan objetos o acciones. Así es como se logra la comunicación entre ellos.
Si hacemos una analogía, imagina que esa sociedad es tu computadora y que las personas son las piezas de
hardware y software que la conforman. Igual que la sociedad de humanos, esta sociedad hipotética dentro de
tu computadora necesita comunicarse entre sí para que ésta funcione como esperas y puedas hacer cálculos,
abrir un navegador o crear un documento. Cuando utilizas el ratón o el teclado, estos dispositivos envían
instrucciones a los miembros de ésa sociedad en un lenguaje común que pueden interpretar por que han sido
programados para ello. Este lenguaje normalmente es representado por un conjunto de bits, unos (1) y ceros
(0), cuya combinación crea el significado de las instrucciones. Este conjunto de 1 y 0 es un sistema de
codificación conocido como código binario. La traducción del lenguaje de programación en binario se conoce
como “compilación”.
Lenguaje de programación
Un lenguaje de programación, en palabras simples, es el conjunto de instrucciones a través del cual los
humanos interactúan con las computadoras. Un lenguaje de programación nos permite comunicarnos con las
computadoras a través de algoritmos e instrucciones escritas en una sintaxis que la computadora entiende e
interpreta en lenguaje de máquina.
Las instrucciones que sigue el ordenador para la ejecución de aplicaciones y programas están escritas
en lenguaje de programación y luego son traducidas a un lenguaje de máquina que puede ser interpretado y
ejecutado por el hardware del equipo (parte física).
El código fuente está formado por líneas de texto que expresan en lenguaje de programación las instrucciones
que debe llevar a cabo el ordenador. Este código es creado, diseñado, codificado, mantenido y depurado a
través de la programación.
UEF CYI 2
Los lenguajes de programación permiten a las computadoras procesar de forma rápida y eficientemente
grandes y complejas cantidades de información. Por ejemplo, si a una persona se le da una lista de números
aleatorios que van de uno a diez mil y se le pide que los coloque en orden ascendente, es probable que tome
una cantidad considerable de tiempo e incluya algunos errores, mientras que, si le das la misma instrucción a
una computadora utilizando un lenguaje de programación, podrás obtener la respuesta en unos cuantos
segundos y sin errores.
Existen docenas de lenguajes de programación utilizados en la industria hoy en día. Algunos lenguajes de
programación populares incluyen C++, C#, Visual Basic, Go, Ruby, JavaScript, Java y Python, por mencionar
algunos. Cuando piensas en un lenguaje de programación, tal como en la analogía que hicimos antes, puedes
compararlo con los lenguajes que utilizamos para comunicarnos porque comparten muchas características
similares.
Para utilizar un lenguaje de programación, de manera efectiva, debemos estudiarlo y comprenderlo desde tres
perspectivas:
En español, las letras forman palabras que forman oraciones. En los lenguajes de programación, los caracteres
forman sentencias que en conjunto forman instrucciones.
Sintaxis
Para aclarar esto aún más, observa estos 3 ejemplos de sintaxis en distintos lenguajes de programación, todos
intentan describir la misma instrucción, es decir, esperan obtener como salida del programa el mismo
resultado:
C#
Console.WriteLine(“Hola Mundo!”);
Python
UEF CYI 3
Assembly (en español, lenguaje ensamblador)
;nasm 2.11.08
section .data
hello: db 'Hola Mundo!',10 ; 'Hello world!' plus a linefeed character
helloLen: equ $-hello ; Length of the 'Hello world!' string
section .text
global _start
_start:
mov eax,4 ; The system call for write (sys_write)
mov ebx,1 ; File descriptor 1 - standard output
mov ecx,hello ; Put the offset of hello in ecx
mov edx,helloLen ; helloLen is a constant, so we don't need to say
; mov edx,[helloLen] to get it's actual value
int 80h ; Call the kernel
mov eax,1 ; The system call for exit (sys_exit)
mov ebx,0 ; Exit with return code of 0 (no error)
int 80h;
Podemos ver en los ejemplos, tres tipos diferentes de sintaxis. La sintaxis de Python, tiene la estructura más
corta y fácil de las tres, por eso es considerado uno de los mejores lenguajes de programación para aprender a
programar, mientras que la sintaxis de Assembly es la más compleja de las tres, ya que requiere de una mayor
cantidad de instrucciones para decirle a la computadora que realice la misma función, imprimir “¡Hola
Mundo!”.
Semántica
Por otro lado, la semántica trata sobre el significado de la instrucción. Responde a las preguntas: ¿es válida
ésta instrucción? Si es así, ¿qué significa la instrucción? ¿Qué queremos lograr con la instrucción? Veamos el
siguiente ejemplo,
x++; // incremento
foo(xyz, --b, &qrs); // call foo
En el ejemplo, las 2 sentencias o instrucciones son sintácticamente válidas en C#. ¿Pero, qué quieren decir?
¿Es incluso válido intentar transformar estas declaraciones en una secuencia ejecutable de instrucciones?
Estas son el tipo de preguntas que están en el corazón de la semántica.
Pragmática
La pragmática, en programación, se refiere al modo en que el contexto influye en la forma cómo interpretamos
y analizamos los problemas que queremos resolver con un lenguaje de programación. Como vimos en el
ejemplo de sintaxis, el mismo problema puede ser resuelto utilizando diferentes lenguajes de programación,
incluso existen problemas que pueden ser resueltos aplicando distintas sentencias o instrucciones lógicas
usando el mismo lenguaje.
UEF CYI 4
Aplicamos el pragmatismo cuando creamos una solución considerando el contexto y cómo afecta a nuestro
problema y a nuestra solución, aunque eso implique utilizar otro lenguaje o herramienta que nos ofrece una
mejor oportunidad de resolver el problema.
Existen una variedad de lenguajes de programación que los programadores pueden usar para comunicarse con
una computadora, a través de lo que conocemos como código fuente, y a pesar de que todos comparten las
características antes mencionadas, cada lenguaje es diferente y de forma individual puede ser más adecuado
utilizarlo para un determinado propósito.
El código fuente constituye la estructura básica de programas, páginas web y aplicaciones en general.
Los lenguajes de programación se utilizan para crear sistemas operativos, programas de escritorio,
aplicaciones móviles, para resolver problemas o interpretar datos. Por ejemplo, existen lenguajes de
programación que son más adecuados para crear software o aplicaciones de entretenimiento, para crear
dispositivos inteligentes hasta crear robots utilizando inteligencia artificial, los límites de lo que se puede
lograr a través de los lenguajes de programación, son desconocidos.
A medida que avanza la tecnología y van apareciendo nuevas necesidades de negocio, también aparece una
fuerte necesidad de lenguajes de programación únicos y diversos, pero es prácticamente imposible que exista
un único lenguaje de programación universal que satisfaga todas las necesidades, gigantes como Google son
de los principales partícipes en esa búsqueda. Los lenguajes de programación a menudo se revisan, actualizan
e incluso se combinan con otros lenguajes a lo largo del tiempo en el intento de evolucionar para satisfacer
nuestras necesidades tecnológicas cambiantes.
Una nota curiosa sobre los lenguajes de programación es que, en general, están escritos en inglés. Ya sea que
programes en JavaScript, Ruby, C#, Go, Ruby o Python, tienen su sintaxis y palabras clave en inglés, incluso
si el lenguaje nativo de sus creadores es inglés o no.
Lenguajes de bajo nivel. Se trata de lenguajes de programación que están diseñados para un hardware
específico y que por lo tanto no pueden migrar o exportarse a otros computadores. Sacan el mayor
provecho posible al sistema para el que fueron diseñados, pero no aplican para ningún otro.
Lenguajes de alto nivel. Se trata de lenguajes de programación que aspiran a ser un lenguaje más
universal, por lo que pueden emplearse indistintamente de la arquitectura del hardware, es decir, en
diversos tipos de sistemas. Los hay de propósito general y de propósito específico.
Lenguajes de nivel medio. Este término no siempre es aceptado, que propone lenguajes de programación
que se ubican en un punto medio entre los dos anteriores: pues permite operaciones de alto nivel y a la vez
la gestión local de la arquitectura del sistema.
BASIC. Su nombre proviene de las siglas de Beginner’s All- purpose Symbolic Instruction Code (Código
simbólico de instrucciones de propósito general para principiantes), y es una familia de lenguajes
imperativos de alto nivel, aparecidos por primera vez en 1964. Su versión más actual es Visual Basic
.NET.
COBOL. Su nombre es un acrónimo para Common Business-Oriented Lenguage (Lenguaje común
orientado a los negocios) y se trata de un lenguaje de programación universal creado en 1959, orientado
principalmente a la informática de gestión, es decir, empresarial.
FORTRAN. Su nombre proviene de The IBM Mathematical Formula Translating System (El sistema de
traducción de fórmulas matemáticas de IBM), y es un lenguaje de programación de alto nivel, propósito
general y de tipo imperativo, diseñado para aplicaciones científicas y de ingeniería.
Java. Un lenguaje de programación de propósito general, orientado a objetos, cuyo espíritu se resume en
las siglas WORA: Written Once, Run Anywhere, es decir: Escrito una vez, funciona en cualquier parte. La
idea era diseñar un lenguaje universal empleando sintaxis derivada de los lenguajes C y C++, pero
empleando menos utilidades de bajo nivel que cualquiera de ambos.
El código fuente suele ser visible durante algunas operaciones determinadas del software, pero sus
instrucciones serán incomprensibles excepto para quien maneje el lenguaje específico en el que fue
programado. Esto ocurre también con las páginas web y otro tipo de elementos de software, programados en
lenguajes-web (como HTML o Java Script) y luego ejecutados o interpretados por la ventana
del navegador de Internet.
El área de la computación que se dedica a la creación de estos códigos fuente es la ingeniería de software,
dedicada a la creación de programas de computadoras. Dicha creatividad es, además, respaldada por las leyes
de derecho de autor, en el sentido de que el código fuente es obra y creación exclusiva de sus programadores,
inalterable e irreproducible por terceros, tanto como el contenido de una obra literaria.
ARDUINO
¿Qué es Arduino?
Arduino es una plataforma electrónica de código abierto basada en hardware y software fáciles de usar. Las
placas Arduino pueden leer entradas (luz en un sensor, un dedo en un botón o un mensaje de Twitter) y
convertirlas en una salida: activar un motor, encender un LED o publicar algo en línea. Puede decirle a su
placa qué hacer enviando un conjunto de instrucciones al microcontrolador de la placa. Para ello se utiliza el
lenguaje de programación Arduino (basado en Wiring), y el Software Arduino (IDE), basado en Processing.
UEF CYI 6
A lo largo de los años, Arduino ha sido el cerebro de miles de proyectos, desde objetos cotidianos hasta
complejos instrumentos científicos. Una comunidad mundial de creadores (estudiantes, aficionados, artistas,
programadores y profesionales) se ha reunido en torno a esta plataforma de código abierto; sus contribuciones
han sumado una increíble cantidad de conocimiento accesible que puede ser de gran ayuda tanto para
principiantes como para expertos.
Arduino nació en el Ivrea Interaction Design Institute como una herramienta sencilla para la creación rápida
de prototipos, dirigida a estudiantes sin experiencia en electrónica y programación. Tan pronto como llegó a
una comunidad más amplia, la placa Arduino comenzó a cambiar para adaptarse a nuevas necesidades y
desafíos, diferenciando su oferta desde simples placas de 8 bits hasta productos para aplicaciones de IoT,
dispositivos portátiles, impresión 3D y entornos integrados. El software Arduino es fácil de usar para
principiantes, pero lo suficientemente flexible para usuarios avanzados. Se ejecuta en Mac, Windows y Linux.
Si bien todas las placas Arduino difieren entre sí, hay varios componentes clave que se pueden encontrar en
prácticamente cualquier Arduino. Echemos un vistazo a la imagen a continuación:
3. Chip USB a serie: el USB a serie es un componente importante, ya que ayuda a traducir datos que
provienen, por ejemplo, de una computadora al microcontrolador integrado. Esto es lo que hace posible
programar la placa Arduino desde tu ordenador.
4. Pines digitales: pines que utilizan lógica digital (0,1 o BAJO/ALTO). Comúnmente utilizado para
interruptores y para encender/apagar un LED.
5. Pines analógicos: pines que pueden leer valores analógicos con una resolución de 10 bits (0-1023).
UEF CYI 7
7. GND: también conocido como ground, negativo o simplemente -, se utiliza para completar un circuito,
donde el nivel eléctrico es de 0 voltios.
8. VIN: significa Entrada de voltaje, donde puede conectar fuentes de alimentación externas.
Dependiendo de la placa Arduino encontrarás muchos más componentes. Los elementos enumerados
anteriormente generalmente se encuentran en cualquier placa Arduino.
Operación básica
La mayoría de las placas Arduino están diseñadas para tener un único programa ejecutándose en el
microcontrolador. Este programa puede diseñarse para realizar una sola acción, como hacer parpadear un
LED. También puede diseñarse para ejecutar cientos de acciones en un ciclo. El alcance varía de un programa
a otro.
El programa que se carga en el microcontrolador comenzará a ejecutarse tan pronto como se encienda. Cada
programa tiene una función llamada "bucle". Dentro de la función de bucle, puedes, por ejemplo:
Leer un sensor.
Enciende una luz.
Compruebe si se cumple una condición.
Todo lo anterior.
La velocidad de un programa es increíblemente rápida, a menos que le digamos que disminuya la velocidad.
Depende del tamaño del programa y del tiempo que tarda el microcontrolador en ejecutarlo, pero generalmente
es en microsegundos (una millonésima de segundo).
UEF CYI 8
finalmente al pin de tierra (GND). Cuando el pin se establece en estado ALTO, el microcontrolador de la
placa Arduino permitirá que fluya una corriente eléctrica a través del circuito, lo que enciende el LED. Cuando
el pin está en estado BAJO, el LED se apagará, ya que no fluye corriente eléctrica a través del circuito.
Los circuitos generalmente se representan como esquemas, que son los planos de su circuito. La siguiente
imagen muestra la representación esquemática del mismo circuito que se muestra en la imagen de arriba.
Señales Electrónicas
Toda comunicación entre componentes electrónicos se facilita mediante señales electrónicas. Hay dos tipos
principales de señales electrónicas: analógicas y digitales.
Señal análoga
Una señal analógica generalmente está limitada a un rango. En un Arduino, ese rango
suele ser de 0 a 5 V o de 0 a 3,3 V.
Los controladores ATmega utilizados para Arduino contienen un convertidor analógico a digital (A/D)
integrado de 6 canales (8 canales en el Mini y Nano, 16 en el Mega). El convertidor tiene una resolución de
10 bits y devuelve números enteros de 0 a 1023. Si bien la función principal de los pines analógicos para la
mayoría de los usuarios de Arduino es leer sensores analógicos, los pines analógicos también tienen toda la
funcionalidad de los pines de entrada/salida de propósito general (GPIO). (lo mismo que los pines digitales 0
- 13).
UEF CYI 9
En consecuencia, si un usuario necesita más pines de entrada y salida de uso general y no todos los pines
analógicos están en uso, los pines analógicos pueden usarse para GPIO.
Mapeo de pines
Los pines analógicos se pueden usar de manera idéntica a los pines digitales, usando los alias A0 (para
entrada analógica 0), A1, etc. Por ejemplo, el código se vería así para configurar el pin analógico 0 en una
salida y configurarlo en ALTO:
Resistencias pull-up
Los pines analógicos también tienen resistencias pull-up, que funcionan de manera idéntica a las resistencias
pull-up de los pines digitales. Se habilitan emitiendo un comando como:
Sin embargo, tenga en cuenta que activar un pull-up afectará los valores informados por analogRead().
Detalles y advertencias
El comando analogRead no funcionará correctamente si un pin se configuró previamente en una salida, por lo
que, si este es el caso, vuelva a configurarlo en una entrada antes de usar analogRead. De manera similar, si
el pin se ha configurado en ALTO como salida, la resistencia pull-up se configurará cuando se vuelva a
cambiar a una entrada.
La hoja de datos de ATmega también advierte contra el cambio de pines analógicos en proximidad temporal
para realizar lecturas A/D (analogRead) en otros pines analógicos. Esto puede provocar ruido eléctrico e
introducir fluctuaciones en el sistema analógico. Puede ser deseable, después de manipular pines analógicos
(en modo digital), agregar un breve retraso antes de usar analogRead() para leer otros pines analógicos.
La modulación de ancho de pulso, o PWM, es una técnica para obtener resultados analógicos con medios
digitales. El control digital se utiliza para crear una onda cuadrada, una señal que cambia entre encendido y
apagado. Este patrón de encendido y apagado puede simular voltajes entre el Vcc completo de la placa (por
ejemplo, 5 V en UNO, 3,3 V en una placa MKR) y apagado (0 voltios) cambiando la porción del tiempo que
pasa la señal en comparación con el tiempo que pasa la señal. La duración del "tiempo" se denomina ancho
de pulso. Para obtener valores analógicos variables, cambia o modula ese ancho de pulso. Si repite este patrón
de encendido y apagado lo suficientemente rápido con un LED, por ejemplo, el resultado es como si la señal
fuera un voltaje constante entre 0 y Vcc que controla el brillo del LED.
En el gráfico siguiente, las líneas verdes representan un período de tiempo regular. Esta duración o período es
la inversa de la frecuencia PWM. En otras palabras, con la frecuencia PWM de Arduino en aproximadamente
500 Hz, las líneas verdes medirían 2 milisegundos cada una. Una llamada a analogWrite () está en una escala
de 0 a 255, de modo que analogWrite(255) solicita un ciclo de trabajo del 100% (siempre encendido), y
analogWrite(127)es un ciclo de trabajo del 50% (en la mitad del tiempo), por ejemplo.
UEF CYI 10
En algunos microcontroladores, PWM solo está disponible en pines seleccionados. Considere el diagrama de
distribución de pines de su placa para saber cuáles puede usar para PWM. Se indican con un signo (~).
Señal digital
Las señales digitales pueden parecer muy básicas (sólo 0 o 1), pero en realidad son mucho más avanzadas.
Por ejemplo, podemos crear una secuencia enviando un estado alto o bajo rápidamente varias veces. Esto se
conoce como secuencia binaria o flujo de bits.
UEF CYI 11
Esta es una forma inteligente de enviar grandes cantidades de datos de un punto a otro, enviando rápidamente
señales altas y bajas. Para interpretar los datos de las señales, utilizamos protocolos de comunicación serie .
Sensores y actuadores
Cuando se trabaja con Arduino, es importante comprender los sensores y actuadores, y la diferencia entre
ellos.
¿Qué es un sensor?
En términos simples, un sensor se utiliza para detectar su entorno, lo que significa que registra un parámetro
físico, por ejemplo, la temperatura, y lo convierte en una señal electrónica.
Los sensores también pueden tomar la forma de un simple botón: cuando cambia un estado (presionamos un
botón), la señal electrónica cambia de bajo a alto (0 a 1).
Hay muchos tipos de sensores y varias formas de registrar datos a partir de ellos. Quizás el más fácil de usar
es un sensor analógico, donde comunicamos un rango de valores alterando la entrada de voltaje alimentada a
un pin analógico Arduino (generalmente entre 0 y 5 voltios). Esto simplemente le brinda un rango entre 0-
1023 (una resolución de 10 bits).
Los sensores digitales son un poco más avanzados, según el tipo. Dependen de protocolos de comunicación
en serie para enviar los datos en consecuencia y requieren un poco más de esfuerzo para traducir los datos.
Como se mencionó en la sección Señales electrónicas anterior, los datos se envían utilizando una secuencia
binaria (por ejemplo, 101101 es 45), y esto debe abordarse y configurarse a nivel de software.
Afortunadamente, muchos sensores vienen acompañados de bibliotecas de software, lo que hace que su
lectura sea mucho más fácil.
En muchos casos, al utilizar una biblioteca, todo lo que necesitamos es solo una línea de código:
¿Qué es un actuador?
Un actuador, en términos simples, se utiliza para accionar o cambiar un estado físico. Algunos ejemplos son:
Los actuadores convierten las señales eléctricas, por ejemplo, en energía radiante (luz) o energía mecánica
(movimiento). La forma en que se controlan los actuadores realmente depende del tipo de componente que
tengamos. La forma más sencilla es simplemente encender o apagar algo, mientras que la forma más avanzada
es controlar la cantidad de voltaje que recibe un componente (es decir, la velocidad de un motor). Para
controlar actuadores, es común utilizar digitalWrite() y analogWrite().
UEF CYI 12
De entrada y salida
Los sensores y actuadores generalmente se denominan entradas y salidas. Cuando escribimos un programa,
es común construir condicionales que verifiquen el estado de un sensor y decidan si debe activar algo.
Un ejemplo básico de esto es un botón y un LED. Podemos escribir un condicional que verifique si se presiona
un botón, encienda el LED y lo apague si no se presiona el botón. En un programa Arduino, se ve así:
Memoria
La SRAM (memoria estática de acceso aleatorio) se utiliza, por ejemplo, para almacenar el valor de una
variable (como el estado de un valor booleano). Cuando se apaga, esta memoria se reinicia.
La memoria Flash se utiliza principalmente para almacenar el programa principal o las instrucciones del
microcontrolador. Esta memoria no se borra cuando se apaga, por lo que las instrucciones para el
microcontrolador se ejecutan tan pronto como se enciende la placa.
La cantidad de memoria disponible en un Arduino varía de una placa a otra. Por ejemplo, el Arduino UNO
tiene una memoria flash de 32 kB/SRAM de 2 kB, mientras que un Nano 33 IoT tiene una memoria flash de
256 kB/SRAM de 32 kB.
Una unidad de microcontrolador (también conocida como MCU) es un circuito integrado (IC), que
normalmente se utiliza para realizar aplicaciones o tareas específicas. Por lo general, este tipo de CI recopila
información o datos de su entorno, los procesa y genera resultados específicos de acuerdo con los datos
recopilados.
Los bloques de memoria son partes esenciales de los sistemas integrados modernos, especialmente los basados
en microcontroladores. Los bloques de memoria son dispositivos semiconductores que almacenan y
recuperan información o datos; Una unidad central de procesamiento (CPU) de microcontrolador utiliza y
procesa datos almacenados en bloques de memoria para realizar tareas específicas.
La memoria en los sistemas informáticos puede ser volátil o no volátil. La memoria volátil es una memoria
temporal, esto significa que los datos se almacenan mientras el sistema está en ejecución, pero se pierden
para siempre cuando se apaga el sistema. La memoria no volátil es memoria permanente; Los datos no se
pierden incluso si el sistema está apagado.
UEF CYI 13
Arquitecturas de memoria 101
La arquitectura informática es un tema muy amplio; Nos centraremos en un panorama general que nos
permitirá comprender cómo se organiza la memoria en los microcontroladores utilizados en las placas
Arduino®.
En los inicios de la informática surgieron dos arquitecturas informáticas, es decir, la organización de los
componentes dentro de un sistema informático: von Neumann y Harvard.
Arquitectura de Harvard
Los sistemas informáticos modernos utilizan modelos de arquitecturas híbridas que maximizan el
rendimiento utilizando lo mejor de ambos mundos, los modelos de von Neumann y Harvard.
Los microcontroladores se utilizan habitualmente en aplicaciones integradas. Deben realizar tareas definidas
de manera confiable y eficiente, con recursos bajos o limitados; Esta es la razón por la que el modelo de
arquitectura de Harvard se utiliza principalmente en microcontroladores: los microcontroladores tienen
una pequeña memoria de programas y datos a la que se debe acceder simultáneamente. Sin embargo, la
arquitectura Harvard no siempre se utiliza en microcontroladores; Algunas familias de microcontroladores
utilizan modelos de arquitectura híbrida o Von Neumann.
UEF CYI 14
Arquitecturas de placas Arduino
Las placas Arduino se basan principalmente en dos familias de microcontroladores: AVR y ARM. Mientras
que los microcontroladores de la familia AVR se basan en el modelo de arquitectura Harvard, los
microcontroladores de la familia ARM pueden basarse en modelos de arquitectura von Neuman o Harvard.
La siguiente tabla resume las arquitecturas de los microcontroladores de las placas Arduino:
Tipos de memoria
Todas las diferentes unidades de memoria dentro de un microcontrolador se pueden dividir en dos tipos
principales: RAM y ROM. La RAM (de memoria de acceso aleatorio) en sistemas basados en
microcontroladores es una memoria volátil que se utiliza para almacenar datos temporales, como las variables
UEF CYI 15
de firmware del sistema. La ROM (de memoria de solo lectura) en sistemas basados en microcontroladores es
una memoria no volátil que se utiliza para almacenar datos permanentes, como el firmware del sistema.
La RAM y la ROM en los sistemas basados en microcontroladores se organizan en tres categorías principales:
Flash
RAM
EEPROM
Flash
La memoria flash en los sistemas basados en microcontroladores forma parte de su ROM. La memoria flash
es donde se almacena el firmware del sistema para su ejecución. Pensemos, por ejemplo, en el famoso
Blink.ino sketch: cuando compilamos este sketch, creamos un archivo binario que luego se almacena en la
memoria flash de una placa Arduino. Luego, el boceto se ejecuta cuando se enciende la placa.
RAM
La RAM del sistema en los sistemas basados en microcontroladores es donde se almacenan los datos
temporales o los datos de tiempo de ejecución; por ejemplo, las variables creadas por funciones de un
programa. La RAM en los microcontroladores suele ser SRAM; Este es un tipo de RAM que utiliza un flip-
flop para almacenar un bit de datos. También existe otro tipo de RAM que se puede encontrar en los
microcontroladores: la DRAM.
EEPROM
Como se mencionó anteriormente, las placas Arduino se basan principalmente en dos familias de
microcontroladores, AVR y ARM; Es importante saber que la asignación de memoria difiere en ambas
arquitecturas. En la arquitectura AVR basada en Harvard, la memoria está organizada como se muestra en
la siguiente imagen:
UEF CYI 16
Es importante mencionar sobre las placas Arduino basadas en AVR cómo se organiza su SRAM en diferentes
secciones:
Text
Data
BSS
Stack
Heap
El text la sección contiene instrucciones cargadas en la memoria flash; data la sección contiene variables
inicializadas en el boceto, BSS la sección contiene datos no inicializados, stack la sección almacena datos de
funciones e interrupciones, y heap la sección almacena variables creadas durante el tiempo de ejecución.
En las arquitecturas ARM híbridas, se implementa el llamado mapa de memoria, con una configuración de
mapa de direcciones diferente de 32 bits, 36 bits y 40 bits que depende del requisito de espacio de direcciones
System On a Chip (SoC) con DRAM adicional. Memory Map otorga una interfaz con diseño SoC, al tiempo
que tiene la mayor parte del control del sistema en una codificación de alto nivel. Las instrucciones de acceso
a la memoria se pueden utilizar en código de alto nivel para administrar módulos de interrupción y periféricos
integrados. Todo ello controlado por la Unidad de Gestión de Memoria (MMU).
El recurso de memoria es manejado por la MMU. La función principal de la MMU es permitir que el
procesador ejecute múltiples tareas de forma independiente en su propio espacio de memoria virtual; Luego,
la MMU utiliza tablas de traducción para establecer un puente entre las direcciones de memoria física y virtual.
La dirección virtual se administra mediante software con instrucciones de memoria, y la dirección física es el
sistema de memoria que se controla dependiendo de la entrada de la tabla de traducción proporcionada por la
dirección virtual.
La memoria del microcontrolador basado en ARM está organizada en las siguientes secciones dentro del tipo
de dirección mencionado anteriormente:
Dirección virtual:
o Kernel code and data
o Application code and data
UEF CYI 17
Dirección física:
o ROM
o RAM
o Flash
o Peripherals
UEF CYI 18
Sensores integrados
Bluetooth se utiliza para comunicarse con dispositivos cercanos y es realmente útil para mantener una
conexión rápida y confiable. Por ejemplo, en aplicaciones de la vida real, la tecnología Bluetooth se utiliza,
por ejemplo, en auriculares y altavoces inalámbricos.
De manera similar a los protocolos en serie, los módulos de radio utilizan su propio conjunto de protocolos
para comunicarse, como HTTP, MQTT y UPD.
API de Arduino
La API de Arduino, también conocida como "lenguaje de programación Arduino", consta de varias funciones,
variables y estructuras basadas en el lenguaje C/C++.
Partes principales
La API de Arduino se puede dividir en tres partes principales: funciones, variables y estructura:
Funciones: para controlar la placa Arduino y realizar cálculos. Por ejemplo, para leer o escribir un estado en
un pin digital, asigne un valor o utilice comunicación en serie.
Variables: las constantes de Arduino, tipos de datos y conversiones. Por ejemplo, int, boolean, array.
UEF CYI 19
bosquejo (loop(), setup())
estructura de control (if, else, while, for)
operadores aritméticos (multiplicación, suma, resta)
operadores de comparación, como == (igual a),!= (no igual a), > (más grande que).
La API de Arduino puede describirse como una simplificación del lenguaje de programación C++, con muchas
adiciones para controlar el hardware de Arduino.
El requisito mínimo absoluto de un programa Arduino es el uso de dos funciones: void setup() y void loop().
El "nulo" indica que no se devuelve nada durante la ejecución.
void setup() - esta función se ejecuta solo una vez, cuando el Arduino está encendido. Aquí definimos
cosas como el modo de un pin (entrada o salida), la velocidad en baudios de la comunicación serie o
la inicialización de una biblioteca.
void loop() - aquí es donde escribimos el código que queremos ejecutar una y otra vez, como
encender/apagar una lámpara en función de una entrada, o realizar una lectura de sensor cada X
segundo.
Las funciones anteriores siempre son necesarias en un boceto de Arduino, pero, por supuesto, puedes agregar
varias funciones más, lo cual es útil para programas más largos.
El "boceto"
La carpeta puede incluir otros archivos, como un archivo de encabezado, que se pueden incluir en su boceto.
Boceto de ejemplo
A continuación, se muestra un ejemplo de un boceto estándar de Arduino, que contiene algunos elementos de
programación Arduino populares.
UEF CYI 20
Bibliotecas
Las bibliotecas de Arduino son una extensión de la API estándar de Arduino y constan de miles de bibliotecas,
tanto oficiales como aportadas por la comunidad.
Las bibliotecas simplifican el uso de códigos que de otro modo serían complejos, como leer un sensor
específico, controlar un motor o conectarse a Internet. En lugar de tener que escribir todo este código usted
mismo, puede simplemente instalar una biblioteca, incluirla en la parte superior de su código y utilizar
cualquiera de sus funcionalidades disponibles. Todas las bibliotecas de Arduino son de código abierto y de
uso gratuito para cualquier persona.
Para usar una biblioteca, debe incluirla en la parte superior de su código, como se muestra a continuación:
Robóticas
Comunicación
IPC- para comunicarse con dispositivos que utilizan el autobús de Interfaz Periférico Serial (SPI).
Alambre- Interfaz de dos alambres (TWI/I2C) para el envío y recepción de datos a través de un rojo
de dispositivos o sensores.
SoftwareSerial- para la comunicación serie en cualquier pellies digitales.
Conectividad
Bibliotecas para acceder a módulos de radio en diferentes tableros de IoT (Wi-Fi, Bluetooth, LoRa, GSM,
NB-IoT, Sigfox).
UEF CYI 21
WiFiNINA- biblioteca para tableros con un módulo Wi-Fi NINA, para conexiones a Internet vía Wi-
Fi.
ArduinoAPDS9960- biblioteca para utilizar el sensor de gesto APDS9960; detecta gestos, color,
iluminación de ambiente y proximidad.
Arduino-LSM6DS3- biblioteca para utilizar el eje LSM6DS3 6 IMU disponible en el Arduino Nano
33 IoT y el Arduino UNO WiFi Rev. 2.
Arduino-LSM9DS1- biblioteca para utilizar el eje LSM9DS1 9 IMU disponible en el Arduino Nano
33 BLE y el Arduino Nano 33 BLE Sense.
Ardu-LSM6DSOX- - biblioteca para usar LSM6DSOX 6 eje IMU disponible en el Arduino Nano
RP2040 Connect.
ArduinoLPS22HB- biblioteca para usar el barómetro y el sensor de temperatura LPS22; es un sensor
ultracompacto que funciona como un barómetro de salida digital.
ArduinoHTS221- biblioteca para utilizar el sensor de humedad y temperatura relativa HTS221.
PDM- - biblioteca para usar el micrófono digital MP34DT05 (Nano BLE Sense y Nano RP2040
Connect).
Memoria
Display
Schduler - gestionar múltiples tareas sin bloqueo (también funciona con Arduino Due).
RTCZero- Reloj en Tiempo Real para programar eventos.
ArduinoMKRGPS - biblioteca para ser utilizada con el Escudo GPS Arduino MKR.
ArduinoMKRRGB - biblioteca para ser utilizada con el Escudo RGB Arduino MKR.
ArduinoGraphics - biblioteca con gráficos primitivos, trabaja también con el Escudo Arduino MKR
RGB.
ArduinoRS485- biblioteca que implementa RS485 en el escudo Arduino MKR RS485.
ArduinoMKRENV- biblioteca para leer todos los sensores MKR Escudo ENV.
ArduinoMKRTHERM - Para leer los sensores conectados al Escudo Arduino MKR THERM.
MKRIMU- - biblioteca para leer los ángulos de aceleración, giroscopio, campo magnético y Euler.
ArduinoMotorCarrier- biblioteca para el control del MKR / Nano Motor Carriers.
Arduino-MKRIoTCarrier- - biblioteca para controlar el MKR IoT Carrier
UEF CYI 22
Audio
USB
Otros
Firmata- para comunicarse con aplicaciones en la computadora usando un protocolo serial estándar.
Bibliotecas retiradas
CurieBLE- interactúa con teléfonos inteligentes y tabletas con Bluetooth Low Energy.
CurieIMU- gestiona el acelerómetro y el giroscopio.
CurieTimerOne- permite utilizar las funciones de Timer.
CurieTime- permite controlar y utilizar el RTC (Reloj en Tiempo Real) interno.
Esplora- Esta biblioteca le permite acceder fácilmente a varios sensores y actuadores montados en la
placa Esplora.
Robot- esta biblioteca permite un fácil acceso a las funciones del Robot Arduino.
Bridge- permite la comunicación entre el procesador Linux y el microcontrolador del Yún.
Ciao- tiene como objetivo simplificar la interacción entre el microcontrolador y el sistema operativo
Linino permitiendo una variedad de conexiones con los protocolos más comunes.
Cada placa Arduino requiere un "núcleo" o "paquete" que debe instalarse para poder programarla. Todos los
paquetes contienen la API estándar de Arduino, pero también una API específica que sólo se puede utilizar
con placas específicas.
Por ejemplo, el paquete clásico ArduinoCore-avr incluye automáticamente las bibliotecas EEPROM y
SoftwareSerial y se puede utilizar libremente sin ninguna instalación adicional. En este paquete encontrarás
los clásicos Arduino UNO, Nano, Mega2560 y más.
Otro ejemplo es el paquete ArduinoCore-mbed , que incluye más de 40 bibliotecas, diseñadas para funciones
específicas de la placa, como:
UEF CYI 23
PDM: se utiliza para muestrear audio de los micrófonos que se encuentran a bordo del Nano 33 BLE
Sense y Nano RP2040 Connect.
Ethernet: para utilizar las funcionalidades Ethernet de Portenta Vision Shield.
GSM - para acceder a las funcionalidades GSM del Portenta Cat. Escudo GNSS IoT M1/NB.
Otra parte integral del ecosistema Arduino son sus herramientas de software.
El IDE de Arduino, como se le conoce comúnmente, es un entorno de desarrollo integrado. ¿Pero qué significa
eso exactamente?
Para programar su placa, necesita escribir un programa, compilarlo en código de máquina y, finalmente: enviar
el nuevo programa a su placa.
El IDE de Arduino facilita todo esto, desde la primera línea de código escrita, hasta ejecutarlo en el
microcontrolador de la placa Arduino. Es un programa o aplicación que puedes descargar (o usar una versión
en línea) para gestionar todo el desarrollo de tu código. En el pasado, este era un proceso complicado que
requería un buen conjunto de conocimientos en electrónica e informática. Ahora cualquiera puede aprender a
hacerlo con la ayuda del IDE de Arduino.
Para cargar código en una placa Arduino utilizando el IDE, normalmente se hace lo siguiente:
1. Instale su placa: esto significa instalar el "paquete" correcto para su placa. Sin el paquete, simplemente no
podrás utilizar tu placa. La instalación se realiza directamente en el IDE y es una operación rápida y sencilla.
2. Cree un nuevo boceto: un boceto es su archivo de programa principal. Aquí escribimos un conjunto de
instrucciones que queremos ejecutar en el microcontrolador.
3. Compile su boceto: el código que escribimos no es exactamente como se ve cuando lo cargamos en nuestro
Arduino: compilar el código significa que lo verificamos en busca de errores y lo convertimos en un archivo
binario (1 y 0). Si algo falla, aparecerá esto en la consola de errores.
4. Sube tu boceto: una vez que la compilación sea exitosa, el código se puede cargar en tu tablero. En este
paso, conectamos físicamente la placa a la computadora y seleccionamos el puerto serie correcto.
5. Monitor serie (opcional): para la mayoría de los proyectos Arduino, es importante saber qué sucede en su
placa. La herramienta Serial Monitor disponible en todos los IDE permite enviar datos desde su placa a su
computadora.
Lenguaje de referencia
El lenguaje de programación Arduino se puede dividir en tres partes principales: funciones, valores (variables
y constantes) y estructura.
UEF CYI 24
Funciones
Variables
UEF CYI 25
Estructura
UEF CYI 26
Referencia general
setup()
loop()
La función es donde se almacena su programa principal. Funcionará mientras su placa esté encendida.
delay()
La función es increíblemente útil y la encontrará en casi todos los ejemplos. Pero, para la eficiencia del código,
no es la mejor opción, ya que impide que Arduino haga algo mientras dure el retraso.
millis()
La función es un poco más avanzada, pero es una función increíblemente ingeniosa. Le permite tener múltiples
eventos sucediendo simultáneamente, sin pausar el programa. Esto se hace midiendo el tiempo (en
milisegundos) transcurrido desde que se inició el programa.
Luego, con el uso de intervalos y el almacenamiento continuo de la hora del último evento, se puede crear un
algoritmo simple para que los eventos sucedan en momentos específicos sin pausar el programa.
UEF CYI 27
Funciones
Puede crear funciones personalizadas que simplemente ejecuten código y regresen al programa, o que
devuelvan un resultado.
UEF CYI 28
Definición de variables
Las variables se pueden crear local o globalmente. Variables que se definen en el loop() se consideran locales
y las variables definidas en la parte superior del boceto se consideran globales.
Tipos de datos
Hay varios tipos de datos disponibles para su uso y a continuación se detallan algunos de los más comunes:
Comunicación serial
La comunicación en serie es esencial para la programación de Arduino, ya que es la forma más sencilla de
saber qué sucede en su placa.
UEF CYI 29
Se utiliza para la comunicación entre la placa Arduino y una computadora u otros dispositivos. Todas las
placas Arduino tienen al menos un puerto serie (también conocido como UART o USART) y algunas tienen
varios.
La placa Nano ESP32 es una excepción debido a que está basada en el núcleo ESP32. Aquí, Serial0 se refiere
a RX0 y TX0, mientras Serial1 y Serial2 Son puertos adicionales que se pueden asignar a cualquier GPIO
libre.
En placas más antiguas (Uno, Nano, Mini y Mega), los pines 0 y 1 se utilizan para la comunicación con la
computadora. Conectar cualquier cosa a estos pines puede interferir con esa comunicación, incluso provocar
cargas fallidas en la placa.
Puede utilizar el monitor serie integrado del entorno Arduino para comunicarse con una placa Arduino. Haga
clic en el botón del monitor serie en la barra de herramientas y seleccione la misma velocidad en baudios
utilizada en la llamada a begin().
La comunicación serie en los pines TX/RX utiliza niveles lógicos TTL (5V o 3,3V según la placa). No conecte
estos pines directamente a un puerto serie RS232; funcionan a +/- 12 V y pueden dañar su placa Arduino.
Para utilizar estos puertos serie adicionales para comunicarse con su computadora personal, necesitará un
adaptador USB a serie adicional, ya que no están conectados al adaptador USB a serie de Mega. Para usarlos
UEF CYI 30
para comunicarse con un dispositivo serie TTL externo, conecte el pin TX al pin RX de su dispositivo, el RX
al pin TX de su dispositivo y la tierra de su Mega a la tierra de su dispositivo.
Serial.begin()
Inicializa la comunicación serial entre la placa y la computadora. Esto se define en el void setup(), donde
también se especifica la velocidad en baudios (velocidad de comunicación).
Serial.print()
Imprime datos en el puerto serie, que se pueden ver en la herramienta Arduino IDE Serial Monitor.
Serial.read()
GPIO/Gestión de pines
pinMode()
Configura un pin digital para que se comporte como entrada o salida. Está configurado dentro del void setup()
función.
digitalRead()
Lee el estado de un pin digital. Se utiliza, por ejemplo, para detectar el clic de un botón.
UEF CYI 31
digitalWrite()
Escribe un estado alto o bajo en un pin digital. Se utiliza para encender o apagar un componente.
analogRead()
Lee el voltaje de un pin analógico y devuelve un valor entre 0 y 1023 (resolución de 10 bits). Se utiliza para
leer componentes analógicos.
analogWrite()
Escribe un valor entre 0 y 255 (resolución de 8 bits). Se utiliza para atenuar luces o ajustar la velocidad de un
motor. También conocido como PWM o modulación de ancho de pulso.
PWM solo está disponible en pines específicos (marcados con un símbolo "~").
Estructura
La estructura de la API de Arduino se basa en C++ y puede considerarse los componentes básicos de un
programa.
Condicionales
Los condicionales son algunos de los elementos utilizados más populares en cualquier programa. En Arduino,
un condicional típico consta de un if y else declaración.
Bucles
El for y while. Los bucles se usan comúnmente en programas para ejecutar un bloque de código una cantidad
determinada de veces o mientras se cumple una condición.
Un uso básico de un while bucle para ejecutar un bloque de código mientras variable es verdad.
Un uso básico de un for. El bucle consiste en ejecutar un bloque de código un número personalizado de veces
(en este caso, 10).
UEF CYI 32
Para salir de un bucle, puedes usar break. En el siguiente fragmento, si se cumple una condición (la variable
es verdadera), salimos del ciclo.
Operadores aritméticos
Los operadores aritméticos se utilizan para sumas, restas, multiplicaciones, divisiones y otros cálculos
matemáticos.
Operadores de comparación
Los operadores de comparación se utilizan para comparar una propiedad con otra y son un componente clave
de una declaración condicional.
Operadores booleanos
Operadores booleanos ( logical NOT !, AND && y OR ||) se puede utilizar, por ejemplo, para condicionales
más avanzados.
Operadores compuestos
Los operadores compuestos constan de dos operadores, que se utilizan para realizar dos operaciones en la
misma declaración. Esto puede ser, por ejemplo, agregar + y asignar = un valor al mismo tiempo.
Existen varios protocolos de comunicación en serie que utilizan las señales digitales antes mencionadas para
enviar datos. Los más comunes son UART, SPI e I²C. El protocolo UART se utiliza, entre otras cosas, para
enviar datos entre una computadora y una placa Arduino, como cargar un nuevo programa o leer datos
directamente desde un Arduino.
Los protocolos SPI e I²C se utilizan para la comunicación entre componentes internos y externos. La
comunicación se maneja mediante algo llamado bus serie, que está conectado a un pin específico del Arduino.
Usando el protocolo I²C, podemos conectar varios sensores en el mismo pin y recuperar los datos con
precisión. Cada dispositivo tiene una dirección que debemos especificar en el programa, que utilizamos al
realizar solicitudes de datos.
UART
UEF CYI 34
¿Cómo se conectan los dispositivos UART?
UART funciona convirtiendo los datos en paquetes para enviarlos o reconstruyendo los datos a partir de los
paquetes recibidos.
Antes de que el dispositivo UART pueda enviar datos, el dispositivo transmisor convierte los bytes de datos
en bits. Después de convertir los datos en bits, el dispositivo UART los divide en paquetes para su transmisión.
Cada paquete contiene un bit de inicio, una trama de datos, un bit de paridad y los bits de parada. La figura a
continuación muestra un paquete de datos de ejemplo.
Después de preparar el paquete, el circuito UART lo envía a través del pin TX.
El dispositivo UART receptor comprueba si el paquete recibido (a través del pin RX) presenta errores,
calculando el número de 1’s y comparándolo con el valor del bit de paridad contenido en el paquete. Si no hay
errores en la transmisión, procederá a eliminar el bit de inicio, los bits de parada y el bit de paridad para
obtener la trama de datos. Es posible que tenga que recibir varios paquetes antes de poder reconstruir el byte
de datos completo a partir de las tramas de datos. Después de reconstruir el byte, se almacena en el buffer
UART. El dispositivo UART receptor utiliza el bit de paridad para determinar si hubo una pérdida de datos
durante la transmisión. La pérdida de datos en la transmisión ocurre cuando un bit cambia su estado mientras
se transmite. Los bits pueden cambiar debido a la distancia de transmisión, la radiación magnética y la falta
de coincidencia de las velocidades de transmisión, entre otras cosas.
Parámetros UART: UART tiene ajustes que deben ser iguales en ambos dispositivos para tener una
comunicación adecuada. Estos ajustes de UART son la tasa de baudios, la longitud de los datos, el bit de
paridad, el número de bits de parada y el control de flujo.
Tasa de baudios
La tasa de baudios es el número de bits por segundo (bps) que un dispositivo UART puede transmitir/recibir.
Necesitamos configurar ambos dispositivos UART con la misma tasa de baudios para tener una correcta
UEF CYI 35
transmisión de datos. Los valores más comunes para la tasa de baudios son 1200, 2400, 4800, 9600, 19200,
38400, 57600, y 115200 bps.
Bit de paridad
El bit de paridad es un bit que se añade a los datos transmitidos y que indica al receptor si el número de 1’s en
los datos transmitidos es par o impar. La configuración posible para el bit de paridad es par o impar.
ODD – el bit de paridad es ‘1’ si hay un número impar de 1’s en la trama de datos
EVEN – el bit de paridad es ‘0’ si hay un número par de 1’s en la trama de datos
Los dispositivos UART pueden utilizar ninguno, uno o dos bits de parada para marcar el final de un conjunto
de bits (llamados paquetes) transmitidos.
Control de flujo
El control de flujo es el método para evitar el riesgo de pérdida de datos cuando se transmiten datos por UART.
El dispositivo UART utiliza caracteres especiales como control de flujo para iniciar/detener la transmisión.
Arduino tiene uno o más pines UART dependiendo de la placa. En el caso de Arduino Uno, este tiene sólo
una interfaz UART, la que se encuentra en el pin 0 (RX0) y el pin 1 (TX0). Los pines 0 y 1 de Arduino también
se utilizan para comunicarse con el IDE de Arduino a través del USB. Así que, si vas a cargar sketches a tu
UNO, asegúrate de desconectar primero los cables de los pines 0 y 1. La figura a continuación muestra la
ubicación de los pines UART TX y RX.
Los niveles lógicos de UART pueden diferir entre fabricantes. Por ejemplo, un Arduino Uno tiene un nivel
lógico de 5V, pero el puerto RS232 de un ordenador tiene un nivel lógico de +/-12V. Conectar un Arduino
UEF CYI 36
Uno directamente a un puerto RS232 dañará el Arduino. Si ambos dispositivos UART no tienen los mismos
niveles lógicos, se necesita un circuito convertidor de nivel lógico adecuado para conectar los dispositivos.
La interfaz periférica serie (SPI) es un protocolo de datos serie síncrono utilizado por los microcontroladores
para comunicarse con uno o más dispositivos periféricos rápidamente en distancias cortas.
Con una conexión SPI siempre hay un dispositivo controlador (normalmente un microcontrolador) que
controla los dispositivos periféricos. Normalmente hay tres líneas comunes a todos los dispositivos:
CIPO (Controller In Peripheral Out): la línea periférica para enviar datos al controlador
COPI (Controller Out Peripheral In): la línea del controlador para enviar datos a los periféricos.
SCK (Reloj serie): los pulsos de reloj que sincronizan la transmisión de datos generada por el
controlador y una línea específica para cada dispositivo
CS (Chip Select): el pin de cada dispositivo que el controlador puede usar para habilitar y deshabilitar
dispositivos específicos. Cuando el pin de selección de chip de un dispositivo está bajo, se comunica
con el controlador. Cuando está alto, ignora el controlador. Esto le permite tener varios dispositivos
SPI que comparten las mismas líneas CIPO, COPI y SCK.
Para escribir código para un nuevo dispositivo SPI, debes tener en cuenta algunas cosas:
¿Cuál es la velocidad SPI máxima que puede usar su dispositivo? Esto está controlado por el primer
parámetro en SPISettings. Si está utilizando un chip clasificado a 15 MHz, use 15000000. Arduino
usará automáticamente la mejor velocidad que sea igual o menor que el número que usa con
SPISettings.
¿Los datos se transfieren primero al bit más significativo (MSB) o al bit menos significativo (LSB)?
Esto está controlado por el segundo parámetro SPISettings, ya sea MSBFIRST o LSBFIRST. La
mayoría de los chips SPI utilizan el primer orden de datos MSB.
¿El reloj de datos está inactivo cuando está alto o bajo? ¿Están las muestras en el flanco ascendente o
descendente de los pulsos de reloj? Estos modos están controlados por el tercer parámetro en
SPISettings.
El estándar SPI es flexible y cada dispositivo lo implementa de manera un poco diferente. Esto
significa que debes prestar especial atención a la hoja de datos del dispositivo al escribir tu código.
En términos generales, existen cuatro modos de transmisión. Estos modos controlan si los datos entran y salen
en el flanco ascendente o descendente de la señal del reloj de datos (llamado fase del reloj) y si el reloj está
inactivo cuando está alto o bajo (llamado polaridad del reloj). Los cuatro modos combinan polaridad y fase
según esta tabla:
UEF CYI 37
Una vez que tenga sus parámetros SPI, use SPI.beginTransaction() para comenzar a utilizar el puerto SPI.
El puerto SPI se configurará con todas sus configuraciones. La forma más sencilla y eficaz de utilizar
SPISettings es directamente dentro SPI.beginTransaction(). Por ejemplo:
Si otras bibliotecas usan SPI para interrupciones, se les impedirá acceder a SPI hasta que usted llame
SPI.endTransaction(). La configuración de SPI se aplica al comienzo de la transacción y
SPI.endTransaction() no cambia la configuración de SPI. A menos que usted, o alguna biblioteca, llame a
beginTransaction por segunda vez, la configuración se mantiene. Debe intentar minimizar el tiempo entre
antes de llamar SPI.endTransaction(), para una mejor compatibilidad si su programa se usa junto con otras
bibliotecas que usan SPI.
Con la mayoría de los dispositivos SPI, después SPI.beginTransaction(), escribirá el pin de selección de chip
BAJO, llame SPI.transfer() cualquier cantidad de veces para transferir datos, luego escriba el pin CS ALTO
y finalmente llame SPI.endTransaction().
Permite la comunicación entre dispositivos o sensores conectados mediante Bus Interfaz de Dos Hilos.
Una buena manera de agregar complejidad de funciones a sus proyectos sin agregar complejidad de cableado
es utilizar el protocolo de circuito interintegrado (I2C). El protocolo I2C es compatible con todas las placas
Arduino. Le permite conectar varios dispositivos periféricos, como sensores, pantallas, controladores de
motor, etc., con sólo unos pocos cables. Ofreciendo mucha flexibilidad y acelerando la creación de prototipos,
sin una gran cantidad de cables.
El protocolo I2C implica el uso de dos líneas para enviar y recibir datos: un pin de reloj en serie (SCL) que la
placa del controlador Arduino pulsa a intervalos regulares y un pin de datos en serie (SDA) a través del cual
se envían datos entre los dos dispositivos.
En I2C, hay un dispositivo controlador, con uno o más dispositivos periféricos conectados a las líneas SCL y
SDA de los controladores.
A medida que la línea del reloj cambia de bajo a alto (conocido como flanco ascendente del pulso del reloj),
se transfiere un solo bit de información desde la placa al dispositivo I2C a través de la línea SDA. A medida
que la línea del reloj sigue pulsando, se envían más y más bits hasta que se forma una secuencia de una
dirección de 7 u 8 bits y un comando o datos. Cuando se envía esta información (bit tras bit), el dispositivo
llamado ejecuta la solicitud y transmite sus datos de regreso (si es necesario) a la placa a través de la misma
línea utilizando la señal de reloj aún generada por el controlador en SCL como sincronización.
UEF CYI 38
Cada dispositivo en el bus I2C es funcionalmente independiente del controlador, pero responderá con
información cuando el controlador se lo solicite.
Debido a que el protocolo I2C permite que cada dispositivo habilitado tenga su propia dirección única, y como
tanto el controlador como los dispositivos periféricos se turnan para comunicarse a través de una sola línea,
es posible que su placa Arduino se comunique (a su vez) con muchos dispositivos, o otras placas, usando solo
dos pines de su microcontrolador.
El controlador envía instrucciones a través del bus I2C en el pin de datos (SDA), y las instrucciones
van precedidas de la dirección, de modo que solo escuche el dispositivo correcto.
Luego hay un bit que indica si el controlador quiere leer o escribir.
Cada mensaje debe ser reconocido, para combatir resultados inesperados, una vez que el receptor ha
reconocido la información anterior, se lo informa al controlador, para que pueda pasar al siguiente
conjunto de bits.
8 bits de datos
Otro poco de reconocimiento
8 bits de datos
Otro poco de reconocimiento
Pero, ¿cómo saben el controlador y los periféricos dónde comienza y termina la dirección, los mensajes, etc.?
Para eso está el cable SCL. Sincroniza el reloj del controlador con los dispositivos, asegurando que todos
pasen a la siguiente instrucción al mismo tiempo.
Sin embargo, casi nunca necesitarás considerar nada de esto; en el ecosistema Arduino tenemos la biblioteca
Wire que se encarga de todo por ti.
A continuación, se muestra una tabla que enumera los diferentes factores de forma de la placa y qué pines son
para I2C.
UEF CYI 39
Cableado I2C
A continuación, encontrará un par de formas de cablear módulos de conexión I2C. La mejor forma depende
de cada módulo y de sus necesidades.
Tableros de ruptura
Algunos módulos de placa de conexión le permiten cablearlos directamente, con cables desnudos en una placa
de pruebas. Para conectar un módulo como este a su placa Arduino, conéctelo de la siguiente manera:
*El nombre del pin puede variar según el módulo, VCC puede denominarse "VIN", "+", etc. GND puede
denominarse "-".
Al profundizar en el mercado de sensores y módulos de ruptura, encontrará que existen ecosistemas completos
donde los estándares se basan en el protocolo I2C. Ejemplos de tales estándares son Qwiic, desarrollado por
Sparkfun, y STEMMA QT, desarrollado por Adafruit. Tanto Qwiic como STEMMA QT utilizan un conector
UEF CYI 40
JST SH de 4 pines para dispositivos I2C, lo que facilita a terceros el diseño de hardware con amplia
compatibilidad. Al tener un conector estandarizado, sabrás que, si ves la palabra Qwiic o STEMMA QT
asociada con un artículo, funcionará junto con una placa Arduino con un conector Qwiic o STEMMA QT,
como el UNO R4 WiFi.
Tanto Qwiic como STEMMA QT agrupan cables de alimentación y tierra, así como los cables SDA y SCL
para I2C, lo que lo convierte en un kit completo, un cable que agrupa todo.
Tanto Qwiic como STEMMA QT utilizan I2C, e incluso cuando se inspeccionan de cerca los módulos que
utilizan los dos estándares, puede resultar difícil distinguir qué los hace únicos entre sí. ¡Pero hay una
diferencia! Y tiene algunas implicaciones sobre cómo y para qué puedes usarlos.
Qwiic tiene cambio de nivel y regulación de voltaje en el controlador (pero no en los periféricos). Lo que esto
significa es que Qwiic tiene una lógica de 3,3 V únicamente. Esto hace que sea más fácil de usar, ya que,
para el usuario final, hay una cosa menos que puede salir mal al diseñar y ensamblar su circuito.
STEMMA QT, por otro lado, no tiene esto. Esto le permite utilizar lógica de 3,3 V y 5 V para módulos. Esto
también significa que hay una cosa más que quizás debas considerar al crear tu circuito, pero también otorga
más flexibilidad en los requisitos lógicos y de energía.
El orden de pines para STEMMA QT está diseñado para coincidir con el orden de pines de Qwiic, lo que
permite la compatibilidad cruzada entre los dos estándares.
Grove
Grove es otro conector estándar, este desarrollado por seeed studio. Puede encontrar una gran cantidad de
módulos con un conector Grove, sin embargo, solo algunos de ellos usan I2C. No hay placas Arduino que
tengan un conector Grove incorporado; sin embargo, puede usar productos como el soporte del conector MKR
, Nano Grove Shield o el Base Shield del kit de sensores Arduino para conectar sensores Grove a su placa
Arduino.
Biblioteca Wire
La biblioteca Wire es lo que utiliza Arduino para comunicarse con dispositivos I2C. Está incluido en todos
los paquetes de la placa, por lo que no es necesario instalarlo manualmente para poder utilizarlo.
Bibliotecas derivadas
Cuando compras básicamente cualquier módulo de ruptura que utilice el protocolo I2C, vendrá con alguna
biblioteca que te ayudará a usar el sensor. La mayoría de las veces, esta biblioteca se construye sobre la
biblioteca Wire y la usa bajo el capó. Agregar funcionalidad para facilitar, por ejemplo, la lectura de la
temperatura.
Un ejemplo de esto es que, si desea utilizar el módulo de sensor Adafruits MCP9808, descargue la biblioteca
Adafruit_MCP9808 del administrador de bibliotecas IDE, que le permite usar funciones como
tempsensor.readTempC() para leer los datos de temperatura de los sensores solicitándolos desde la dirección
correcta y leer la información devuelta con una sola línea en lugar de escribir el código del cable usted mismo.
Ejemplos
Lector de controlador
En algunas situaciones, puede resultar útil configurar dos (¡o más!) placas Arduino para compartir información
entre sí. En este ejemplo, dos placas están programadas para comunicarse entre sí en una configuración de
lector de controlador/remitente de periféricos a través del protocolo serie síncrono I2C . de Arduino varias
funciones de la biblioteca Wire Para lograr esto se utilizan . Arduino 1, el controlador, está programado para
solicitar y luego leer 6 bytes de datos enviados desde el periférico Arduino con dirección única. Una vez que
se recibe ese mensaje, se puede ver en la ventana del monitor serie del software Arduino (IDE).
UEF CYI 42
Bosquejo del lector del controlador
UEF CYI 43
Bosquejo del escritor del controlador
Acelerómetro
UEF CYI 44
Este código le permite leer datos del acelerómetro de un módulo de acelerómetro de 6 ejes Grove utilizando
la biblioteca seeed arduino LSM6DS3 .
I2C BMP280
UEF CYI 45
Este ejemplo de código le permite leer la temperatura a través de I2C desde un módulo de conexión BMP280
de Adafruit:
LED I2C
Este ejemplo de código dibuja una versión del logotipo de Arduino en un OLED Grove I2C de 128x64:
UEF CYI 46
UEF CYI 47
UEF CYI 48