C Programming for Arduino by Julien Bayle_español
C Programming for Arduino by Julien Bayle_español
www.bookbenefits.com
Machine Translated by Google
Julien Bayle
BIRMINGHAM BOMBAY
www.bookbenefits.com
Machine Translated by Google
Todos los derechos reservados. Ninguna parte de este libro puede ser reproducida, almacenada en un
sistema de recuperación de información o transmitida en ninguna forma ni por ningún medio sin el
permiso previo por escrito del editor, excepto en el caso de citas breves incluidas en artículos críticos
o reseñas.
En la preparación de este libro se ha hecho todo lo posible para garantizar la exactitud de la información
presentada. Sin embargo, la información contenida en este libro se vende sin garantía, ya sea expresa o
implícita. Ni el autor, ni Packt Publishing, ni sus distribuidores serán responsables de ningún daño causado
o supuestamente causado directa o indirectamente por este libro.
Packt Publishing se ha esforzado por proporcionar información sobre marcas comerciales de todas las empresas
y productos mencionados en este libro mediante el uso apropiado de mayúsculas.
Sin embargo, Packt Publishing no puede garantizar la exactitud de esta información.
www.packtpub.com
www.bookbenefits.com
Machine Translated by Google
Créditos
Sajeev Raghavan
Revisores
India Morbiwala
Darwin Grosse
Brandt D’Mello
Pradumn Joshi
Aditya Nair
Phillip Mayhew
Alfida Paiva
Glenn D. Reuther
Editor de adquisiciones
Edward Gordon Correctores de pruebas
Martín buzo
Editor técnico principal
Panda susmita Indexador
Tejal R. Soni
Editores técnicos
Worrell Lewis
Gráficos
Varun Pius Rodrigues Ronak Dhruv
Jeque de Lubna
Pooja Chiplunkar
Trabajo de portada
Pooja Chiplunkar
www.bookbenefits.com
Machine Translated by Google
Como artista digital minimalista, trabaja en la intersección entre el sonido, lo visual y los
datos. Explora la relación entre los sonidos y lo visual a través de sus instalaciones
audiovisuales inmersivas, sus actuaciones en directo y su música publicada. Su obra, a menudo
descrita como "compleja, intrigante y relevante", intenta romper los códigos clásicos para
ofrecer a su público una nueva visión de nuestro mundo a través de sus estímulos
puramente digitales y generados en tiempo real.
www.bookbenefits.com
Machine Translated by Google
Reconocimiento
Me gustaría agradecer a mi dulce esposa Angela y a nuestra hija Alice por haber sido mis
incondicionales apoyos. ¡Un agradecimiento especial a nuestro hijo Max, que nació entre la
escritura del capítulo 11 y el capítulo 12!
También me gustaría agradecer a mis dos grandes amigos Laurent Boghossian y Denis
Laffont porque estuvieron ahí para mí durante todo el transcurso de este gran proyecto con
sus consejos, bromas y apoyo incondicional.
Me gustaría extender mi más sincero agradecimiento a dos personas y amigos muy amables a quienes
les pedí que revisaran este libro para mí: Glenn D. Reuther y Darwin Grosse.
Agradezco a los siguientes grandes programadores que codificaron algunas bibliotecas que se
han utilizado en este libro: Marcello Romani (la biblioteca SimpleTimer), Juan Hernández (la
biblioteca ShiftOutX), Thomas Ouellet Fredericks (la biblioteca Bounce), Tim Barrass (la biblioteca
Mozzi), David A. Mellis del MIT (la biblioteca PCM), Michael Margolis y Bill Perry (la biblioteca
glcdarduino) y Markku Rossi (biblioteca Arduino Twitter con soporte OAuth).
Quiero agradecer a los creadores de los siguientes marcos poderosos utilizados en este libro,
además del marco Arduino en sí: Max 6, Processing y Fritzing.
Por último, me gustaría abrazar a Massimo Banzi y al equipo del proyecto Arduino por haber
iniciado este gran proyecto y habernos inspirado tanto.
www.bookbenefits.com
Machine Translated by Google
www.bookbenefits.com
Machine Translated by Google
Desde entonces, pasó varios años en Grumman Aerospace como técnico de instrumentación de
pruebas en tierra y vuelo, antes de pasar al campo de TI.
Comenzó con una formación en Operaciones y Programación Informática, y luego trabajó como
ingeniero de redes y sistemas, con certificaciones de Microsoft y Novell. Después de más de 10
años en la Universidad de Virginia como ingeniero sénior de sistemas, pasa gran parte de su
tiempo libre trabajando con el estado actual de la tecnología musical. Su sitio web es http://
lico.drupalgardens.com.
En el pasado, ha sido revisor técnico de varios libros sobre combustibles alternativos (From the
Fryer to the Fuel Tank, de Joshua Tickell) y ha sido autor de guías de energía alternativa para
hacerlo usted mismo.
www.bookbenefits.com
Machine Translated by Google
www.bookbenefits.com
¿Sabías que Packt ofrece versiones en formato electrónico de todos los libros publicados, con archivos PDF y
ePub disponibles? Puedes actualizar a la versión en formato electrónico en www.PacktPub.com y, como cliente
de libros impresos, tienes derecho a un descuento en la copia en formato electrónico. Ponte en contacto con
nosotros en [email protected] para obtener más información.
En www.PacktPub.com, también puede leer una colección de artículos técnicos gratuitos, suscribirse a una
variedad de boletines gratuitos y recibir descuentos y ofertas exclusivas en libros y libros electrónicos de Packt.
MT.
http://PacktLib.PacktPub.com
¿Necesita soluciones instantáneas a sus preguntas sobre TI? PacktLib es la biblioteca de libros digitales en
línea de Packt. Aquí puede acceder, leer y buscar en toda la biblioteca de libros de Packt.
www.bookbenefits.com
Machine Translated by Google
Tabla de contenido
Prefacio 1
Capítulo 1: Conectemos las cosas ¿Qué 7
es un microcontrolador? 7
Presentación de la gran familia Arduino 8
Acerca del prototipado de hardware 11
Entendiendo la arquitectura del software Arduino Instalación 13
del entorno de desarrollo Arduino (IDE) 15
Instalación del IDE 15
¿Cómo lanzar el entorno? 16
¿Cómo se ve el IDE? 16
Instalación de controladores de Arduino 19
Instalación de controladores para Arduino Uno R3 19
Instalación de controladores para Arduino Duemilanove, Nano o Diecimilla 20
¿Qué es la electricidad? 20
Voltaje 21
Corriente y potencia 21
¿Qué son resistencias, condensadores, etc.? 22
Cableado de cosas y Fritzing 23
¿Qué es Fritzing? 25
Fundamentos de la fuente de 27
alimentación ¡Hola LED! 28
¿Qué queremos hacer exactamente? 29
¿Cómo puedo hacer eso usando código C? 29
¡Por fin subamos el código! 34
Resumen 34
www.bookbenefits.com
Machine Translated by Google
Tabla de contenido
Investigando un poco… 53
Hablar con la pizarra desde la computadora 54
Resumen 54
de 60
variables Cadena La definición de cadena 61
es una construcción Uso de índices y búsqueda dentro de String 61
charAt() 61
indexOf() y lastIndexOf() 62
comienza con() y termina con() 63
[ ii ]
www.bookbenefits.com
Machine Translated by Google
Tabla de contenido
El concepto de alcance: 72
calificadores estáticos, volátiles y constantes 73
74
constante 75
volátil estática 75
Operadores, estructuras de operadores y precedencia 76
Operadores aritméticos y tipos 76
Tipos de personajes 76
Tipos numéricos 77
[ iii ]
www.bookbenefits.com
Machine Translated by Google
Tabla de contenido
Resumen 134
[ iv ]
www.bookbenefits.com
Machine Translated by Google
www.bookbenefits.com
Tabla de contenido
Capítulo 6: Sentir el mundo – Sentir con entradas analógicas Sentir entradas analógicas 179
y valores continuos ¿Cuántos valores podemos distinguir? 180
180
Lectura de entradas analógicas 181
El verdadero propósito del potenciómetro 181
Cambiar el retardo de parpadeo de un LED con un potenciómetro 182
[ en ]
www.bookbenefits.com
Machine Translated by Google
Tabla de contenido
[ nosotros ]
www.bookbenefits.com
Machine Translated by Google
Tabla de contenido
[ vii ]
www.itebooks.info
Machine Translated by Google
Tabla de contenido
[ viii ]
www.itebooks.info
Machine Translated by Google
Tabla de contenido
[ ix ]
www.itebooks.info
Machine Translated by Google
Tabla de contenido
[x]
www.itebooks.info
Machine Translated by Google
Tabla de contenido
Resumen 428
[ xi ]
www.itebooks.info
Machine Translated by Google
Tabla de contenido
Resumen 471
Conclusión 471
Acerca de Packt Publishing 473
Acerca de Packt Open Source 473
Escribiendo para Packt 473
Índice 477
[ xii ]
www.itebooks.info
Machine Translated by Google
Prefacio
Nuestro mundo futurista está lleno de dispositivos inteligentes y conectados. Las comunidades
de aficionados al bricolaje siempre se han sentido fascinadas por el hecho de que cada una de ellas
pudiera diseñar y construir su propio sistema inteligente, dedicado o no, para tareas específicas.
Desde pequeños controladores que encienden las luces cuando detectan a alguien hasta un sofá inteligente
que envía correos electrónicos cuando nos sentamos en él, los proyectos electrónicos baratos se
han vuelto cada vez más fáciles de crear y, por contribuir a ello, todos tenemos que agradecer al equipo
que inició el proyecto Arduino alrededor de 2005 en Ivrea, Italia.
La plataforma Arduino es uno de los hardware de código abierto más utilizados en el mundo.
Proporciona un potente microcontrolador en una pequeña placa de circuito impreso con un factor de
forma muy pequeño. Los usuarios de Arduino pueden descargar el entorno de desarrollo integrado (IDE) de
Arduino y codificar su propio programa utilizando el lenguaje C/C++ y la biblioteca Arduino Core que
proporciona una gran cantidad de funciones y características útiles.
Con C Programming for Arduino, los usuarios aprenderán lo suficiente de C/C++ para poder diseñar
su propio hardware basado en Arduino. Este es un libro todo en uno que contiene toda la teoría necesaria
ilustrada con ejemplos concretos. Los lectores también aprenderán sobre algunos de los principales
marcos de diseño de interacción y multimedia en tiempo real, como Processing y el marco de
programación gráfica Max 6.
Programación en C para Arduino te enseñará el famoso método de trabajo "aprender haciendo" que
trato de seguir en todos mis cursos, desde Max 6 hasta Processing y Ableton Live.
Por último, Programación en C para Arduino abrirá nuevos campos de conocimiento al abordar el
concepto de entrada y salida, comunicación y redes, síntesis de sonido y diseño de sistemas reactivos. Los
lectores aprenderán las habilidades necesarias para poder continuar su viaje mirando el mundo moderno
de otra manera, no solo como usuarios sino también como verdaderos creadores.
Para obtener más detalles, puede visitar mi sitio web del libro en http://
cprogrammingforarduino.com/.
www.itebooks.info
Machine Translated by Google
Prefacio
El capítulo 2, Primer contacto con C, cubre la relación entre el software y el hardware. Presentaremos
el lenguaje C, entenderemos cómo podemos compilarlo y luego aprenderemos a cargar nuestros programas
en la placa Arduino. También aprenderemos todos los pasos necesarios para transformar una idea pura
en firmware para Arduino.
El capítulo 4, Mejorar la programación con funciones, matemáticas y tiempos, proporciona las primeras
claves para mejorar nuestro código C, especialmente mediante el uso de funciones. Aprendemos a
producir estructuras de programación reutilizables y eficientes.
El capítulo 5, Detección con entradas digitales, presenta las entradas digitales de Arduino. Aprenderemos
a usarlas y a comprender sus entradas y salidas. También veremos cómo Arduino usa electricidad y
pulsos para comunicarse con todo.
El capítulo 6, Sentir el mundo: sentir con entradas analógicas, describe las entradas analógicas de
Arduino a través de diferentes ejemplos concretos y las compara con los pines digitales.
En este capítulo se presentan 6 frameworks como uno de los compañeros ideales para Arduino.
El capítulo 8, Diseño de retroalimentación visual de salida, habla sobre las salidas de Arduino y cómo
podemos usarlas para diseñar sistemas de retroalimentación visual mediante LED y sus sistemas.
Presenta el poderoso concepto PWM y también habla sobre las pantallas LCD.
Capítulo 9, Hacer que las cosas se muevan y crear sonidos, muestra cómo podemos usar las
salidas de Arduino para proyectos relacionados con el movimiento. Hablamos sobre motores y
movimiento y también sobre vibración del aire y diseño de sonido. Describimos algunos conceptos
básicos sobre sonido digital, MIDI y el protocolo OSC, y nos divertimos con una biblioteca PCM muy
agradable que proporciona la función de leer archivos de sonido codificados digitalmente desde
Arduino en sí.
[2]
www.itebooks.info
Machine Translated by Google
Prefacio
El capítulo 10, Algunas técnicas avanzadas, ofrece muchos conceptos avanzados, desde el
almacenamiento de datos en unidades EEPROM y la comunicación entre varias placas Arduino, hasta el
uso de módulos GPS. También aprenderemos a utilizar nuestra placa Arduino con baterías, jugar con
pantallas LCD y utilizar el protector VGA para conectar el microcontrolador a una pantalla de computadora
típica.
El capítulo 11, Redes, presenta los conceptos de redes que debemos comprender para usar nuestro Arduino
en redes Ethernet, cableadas o inalámbricas. También utilizaremos una potente biblioteca que nos brinda una
forma de enviar mensajes por Twitter directamente presionando un botón en nuestro Arduino, sin usar ninguna
computadora.
Capítulo 12, Jugando con el Framework Max 6, enseña algunos consejos y técnicas que podemos usar con el
framework de programación gráfica Max 6. Describiremos completamente el uso del objeto Serial y cómo
analizar y seleccionar datos que vienen de Arduino a la computadora. Diseñaremos un pequeño medidor de
nivel de sonido usando LED reales y Max 6 y terminaremos diseñando un efecto de sonido de cambio de tono
controlado por nuestro
propia mano y un sensor de distancia.
El capítulo 13, Mejorar la programación en C y crear bibliotecas, es el capítulo más avanzado del libro. Describe
algunos conceptos avanzados de C que se pueden utilizar para hacer que nuestro código sea reutilizable, más
eficiente y optimizado, a través de algunos ejemplos del mundo real interesantes y agradables.
El apéndice nos proporciona detalles de los tipos de datos en el lenguaje de programación C, precedencia
de operadores en C y C++, funciones matemáticas importantes, series de Taylor para optimizaciones de
cálculos, una tabla ASCII, instrucciones para instalar una biblioteca y una lista de distribuidores de componentes.
[3]
www.itebooks.info
Machine Translated by Google
Prefacio
En este libro también se utilizan otras bibliotecas. Cada vez que se necesitan, la descripción del ejemplo
explica de dónde descargarlas y cómo instalarlas en nuestro ordenador.
Este libro abre nuevas perspectivas de aprendizaje mediante la creación, que cambiarán la vida de los lectores.
Convenciones
En este libro, encontrará diversos estilos de texto que distinguen distintos tipos de información. A
continuación, se ofrecen algunos ejemplos de estos estilos y una explicación de su significado.
Las palabras clave en el texto se muestran de la siguiente manera: "Podemos incluir otros contextos mediante
el uso de la directiva include ".
[por defecto]
extensión => s,1,Dial(Zap/1|30)
exten => s,2,Buzón de voz(u100)
exten => s,102,Buzón de voz(b100)
exten => i,1,Buzón de voz(s0)
Cuando deseamos llamar su atención sobre una parte particular de un bloque de código, las líneas o
elementos relevantes se muestran en negrita:
[por defecto]
extensión => s,1,Dial(Zap/1|30)
exten => s,2,Buzón de voz(u100)
[4]
www.itebooks.info
Machine Translated by Google
Prefacio
# cp /usr/src/asteriskaddons/configs/cdr_mysql.conf.sample
/etc/asterisk/cdr_mysql.conf
Los términos nuevos y las palabras importantes se muestran en negrita. Las palabras que ve en la pantalla, en los
menús o en los cuadros de diálogo, por ejemplo, aparecen en el texto de la siguiente manera: "haga clic en el botón
Siguiente para pasar a la siguiente pantalla".
Para enviarnos comentarios generales, simplemente envíe un correo electrónico a [email protected] y mencione el
título del libro en el asunto de su mensaje. Si hay un tema en el que usted es experto y está interesado en escribir o contribuir
a un libro, consulte nuestra guía para autores en www.packtpub.com/authors.
Atención al cliente
Ahora que usted es el orgulloso propietario de un libro Packt, tenemos una serie de cosas que pueden ayudarle a
aprovechar al máximo su compra.
[5]
www.itebooks.info
Machine Translated by Google
Prefacio
Errata
Aunque hemos tomado todas las precauciones para garantizar la precisión de nuestro contenido, pueden ocurrir
errores. Si encuentra un error en uno de nuestros libros (tal vez un error en el texto o en el código), le
agradeceríamos que nos lo comunicara. Al hacerlo, podrá evitar frustraciones a otros lectores y nos ayudará a
mejorar las versiones posteriores de este libro. Si encuentra alguna errata, infórmelo visitando http://www.packtpub.
com/submiterrata, seleccionando su libro, haciendo clic en el enlace del formulario de envío de erratas e ingresando
los detalles de sus erratas. Una vez que se verifiquen sus erratas, su envío será aceptado y las erratas se subirán
a nuestro sitio web o se agregarán a cualquier lista de erratas existentes, en la sección Erratas de ese título.
Cualquier errata existente se puede ver seleccionando su título en http://www.packtpub.com/support.
Piratería
La piratería de material protegido por derechos de autor en Internet es un problema constante en todos los medios.
En Packt, nos tomamos muy en serio la protección de nuestros derechos de autor y licencias. Si encuentra copias
ilegales de nuestras obras, en cualquier formato, en Internet, proporciónenos la dirección o el nombre del
sitio web de inmediato para que podamos buscar una solución.
Apreciamos su ayuda para proteger a nuestros autores y nuestra capacidad para brindarle contenido
valioso.
Preguntas
Puede contactarnos a [email protected] si tiene algún problema con cualquier aspecto del libro y
haremos todo lo posible para solucionarlo.
[6]
www.itebooks.info
Machine Translated by Google
Arduino se trata de conectar cosas. Lo haremos en un par de minutos después de haber aprendido un
poco más sobre los microcontroladores en general y especialmente sobre la gran y sorprendente familia
Arduino. Este capítulo te enseñará cómo estar totalmente listo para codificar, cablear y probar cosas con
tu nuevo amigo de hardware. Sí, esto sucederá pronto, muy pronto; ¡ahora vamos a sumergirnos
en el tema!
¿Qué es un microcontrolador?
Un microcontrolador es un circuito integrado (CI) que contiene todas las partes principales de una
computadora típica, que son las siguientes:
• Procesador
• Recuerdos
• Periféricos
• Entradas y salidas
El procesador es el cerebro, la parte donde se toman todas las decisiones y que puede calcular.
Las memorias son a menudo espacios en los que se ejecutan tanto el programa interno central como
los elementos del usuario (generalmente llamados memoria de solo lectura (ROM) y memoria de
acceso aleatorio (RAM)).
Defino periféricos como los propios periféricos contenidos en una placa global; son tipos de
circuitos integrados muy diferentes con un propósito principal: dar soporte al procesador y
ampliar sus capacidades.
www.itebooks.info
Machine Translated by Google
Las entradas y salidas son las formas de comunicación entre el mundo (alrededor del microcontrolador) y el
microcontrolador mismo.
El primer procesador de un solo chip fue construido y propuesto por Intel Corporation en 1971 bajo el nombre
de Intel 4004. Era una unidad central de procesamiento (CPU) de 4 bits.
Desde los años 70, las cosas han evolucionado mucho y tenemos muchos procesadores a nuestro alrededor.
Mira a tu alrededor y verás tu teléfono, tu computadora y tu pantalla. Los procesadores o microprocesadores
controlan casi todo.
En comparación con los microprocesadores, los microcontroladores ofrecen una forma de reducir el
consumo de energía, el tamaño y el coste. De hecho, los microprocesadores, aunque sean más rápidos
que los procesadores integrados en los microcontroladores, requieren una gran cantidad de periféricos para
funcionar. El alto nivel de integración que proporciona un microcontrolador lo convierte en el amigo de los
sistemas integrados, como el controlador del motor del coche, el mando a distancia del televisor, los equipos
de escritorio (incluida la impresora), los electrodomésticos, los juegos de los niños, los teléfonos móviles y podría
seguir...
Hay muchas familias de microcontroladores sobre las que no puedo escribir en este libro, sin mencionar
las líneas de microcontroladores PIC (http://en.wikipedia.org/wiki/PIC_microcontroller) y Parallax
SX . También quiero citar un proyecto de código abierto de desarrollo de hardware musical en
particular: MIDIbox (basado en PIC y luego en STM32, consulte http://www.ucapps.de). Se trata de un
marco muy sólido y robusto, muy modificable. El controlador Protodeck (http://julienbayle.net/protodeck)
se basa en MIDIbox.
Ahora que ya has comprendido que tienes un ordenador completo en tus manos, ¡vamos a describir
específicamente las placas Arduino!
[8]
www.itebooks.info
Machine Translated by Google
Capítulo 1
El proyecto fue iniciado en Italia en 2005 por los fundadores Massimo Banzi y David Cuartielles.
Hoy en día es uno de los ejemplos más bellos del concepto de código abierto, llevado al mundo
del hardware y que a menudo se utiliza solo en el
mundo del software.
Hablamos de la familia Arduino porque hoy en día podemos contar alrededor de 15 placas
"basadas en Arduino", que es un metatérmino divertido para definir diferentes tipos de diseños de
placas, todas ellas realizadas con un procesador AVR de Atmel. Las principales diferencias entre
Esas tablas son las:
• Tipo de procesador
[9]
www.itebooks.info
Machine Translated by Google
Algunas placas Arduino son un poco más potentes en cuanto a velocidad de cálculo, otras
tienen más memoria, algunas tienen muchas entradas/salidas (mira la enorme Arduino Mega),
algunas están pensadas para ser integradas en proyectos más complejos y tienen un formato muy
pequeño con muy pocas entradas y salidas… como les decía a mis alumnos cada uno
puede encontrar su amigo en la familia Arduino. También hay placas que incluyen periféricos
como conectores Ethernet o incluso módulos Bluetooth, incluyendo antenas.
La magia detrás de esta familia es el hecho de que podemos utilizar el mismo Entorno
de Desarrollo Integrado (IDE) en nuestras computadoras con cualquiera de esas placas (http://
en.wikipedia.org/wiki/Integrated_development_environment).
Algunos bits necesitan ser configurados correctamente pero este es el mismo software y
lenguaje que usaremos:
Algunos miembros notables de la familia Arduino: Uno R3, LilyPad, Arduino Ethernet,
Arduino Mega, Arduino Nano, Arduino Pro y un protector de prototipos
Se puede encontrar una página de referencia muy bonita pero no exhaustiva sobre este tema en
http://arduino.cc/en/Main/Hardware.
[ 10 ]
www.itebooks.info
Machine Translated by Google
Capítulo 1
A lo largo de este libro también utilizaré un Arduino Mega y un Arduino Uno; pero no tengas miedo, cuando
domines la programación de Arduino, ¡podrás usar cualquiera de ellos!
Como nosotros, los creadores, estamos totalmente involucrados en prácticas de "hazlo tú mismo", todos
queremos y necesitamos construir y diseñar nuestras propias herramientas, y eso a menudo significa
herramientas de hardware y electrónicas. Queremos ampliar nuestras computadoras con sensores, luces
parpadeantes e incluso crear engranajes independientes.
Incluso para probar cosas muy básicas como hacer parpadear un diodo emisor de luz (LED), se requieren
muchos elementos, desde el suministro de energía hasta la programación de bajo nivel del chipset, desde los
cálculos de los valores de las resistencias hasta la configuración del reloj de cuarzo controlado por voltaje. Todos
esos pasos solo dan dolores de cabeza a los estudiantes e incluso los más motivados pueden desanimarse al hacer
una primera prueba.
Arduino apareció y cambió todo en el panorama al proponer una solución económica y con todo incluido
(tenemos que pagar 30 dólares por el Arduino Uno R3), una cadena de herramientas multiplataforma que
funciona en Windows, OS X y Linux, un lenguaje C de alto nivel muy fácil de usar y una biblioteca que también
puede modificar los bits de bajo nivel, y un marco de código abierto totalmente extensible.
De hecho, con una pequeña y bonita placa todo incluido, un cable USB y tu ordenador, puedes aprender
electrónica, programar hardware integrado usando lenguaje C y hacer parpadear tus LED.
La creación de prototipos de hardware se volvió (casi) tan fácil como la de software debido al alto nivel de
integración entre el software y el hardware que proporciona todo el marco.
[ 11 ]
www.itebooks.info
Machine Translated by Google
Una de las cosas más importantes que hay que entender aquí es el ciclo de creación de prototipos.
Dibujo y cableado
El circuito
Codificación y carga
El firmware
Jugando y disfrutando
Desde nuestra idea hasta nuestro render final, normalmente tenemos que seguir estos pasos.
Si queremos que el LED parpadee, tenemos que definir varias características de parpadeo, por ejemplo. Esto
ayudará a definir con precisión el proyecto, lo cual es clave para el éxito.
Luego tendremos que dibujar un esquema con nuestra placa Arduino y nuestro LED; surgirá la pregunta,
"¿Cómo están conectados entre sí?"
La programación del firmware utilizando el lenguaje C se puede iniciar directamente después de haber
esbozado el circuito porque, como veremos más adelante, está directamente relacionado con el hardware.
Este es uno de los puntos fuertes del desarrollo con Arduino. ¿Recuerdas? El diseño de la placa ha sido
pensado únicamente para hacernos pensar en nuestro proyecto y no para confundirnos con elementos de
aprendizaje abstracto de muy bajo nivel.
[ 12 ]
www.itebooks.info
Machine Translated by Google
Capítulo 1
El paso de carga es muy importante. Nos puede proporcionar mucha información, especialmente
en caso de que tengamos que solucionar problemas más adelante. Aprenderemos que este paso no
requiere más que un par de clics una vez que la placa esté correctamente conectada a nuestro ordenador.
Luego, se realizará la prueba y la reparación del subciclo. Aprenderemos haciendo, probando y, por
supuesto, también fallando. Es una parte importante del proceso y te enseñará mucho. Tengo que
confesar algo importante aquí: cuando comencé mi proyecto Bonome (http://julienbayle.net/bonome),
un dispositivo clon RGB monome, pasé dos horas reparando una matriz LED con cableado inverso. Ahora,
los conozco muy bien porque fallé un día.
El último paso es el más genial. Lo menciono porque debemos tener en mente el objetivo final, el que
nos hará felices al final. ¡Es un secreto para tener éxito!
Toma tu placa Arduino en la mano. Verás un circuito integrado con forma de rectángulo con la palabra
ATMEL escrita en la parte superior; este es el procesador.
Este procesador es el lugar que contendrá todo el programa que escribiremos y que hará que las cosas
sucedan.
Cuando compramos (ver Apéndice G, Lista de Distribuidores de Componentes, y este enlace: http://
arduino.cc/en/Main/Buy) un Arduino, el procesador, también llamado chipset, está pregrabado. Ha sido
programado por personas cuidadosas para hacernos la vida más fácil. El programa que ya está
incluido en el chipset se llama bootloader.
(http://en.wikipedia.org/wiki/Booting). Básicamente, se encarga del primer momento de reactivación
del procesador cuando se le suministra algo de energía.
Pero su papel más importante es la carga de nuestro firmware (http://en.wikipedia.org/wiki/
Firmware), es decir, nuestro preciado programa compilado.
[ 13 ]
www.itebooks.info
Machine Translated by Google
En nuestro IDE
en nuestra computadora
En el Ardulno
corriendo y corriendo y
Firmware binario
ejecutando tareas ejecutando tareas
Me gusta definirlo diciendo que el gestor de arranque es el software del hardware y el firmware es el
software del usuario. De hecho, también tiene cierta importancia porque los espacios de memoria
en el chipset no son iguales para las operaciones de escritura (dentro de un hardware específico,
algo que analizaremos en las próximas secciones de este libro). Si utilizamos un programador, no
podemos sobrescribir el gestor de arranque (lo que es más seguro en este punto de nuestra
lectura), sino solo el firmware. Esto será más que suficiente incluso para propósitos avanzados,
como veremos a lo largo del libro.
No todos los bootloaders de las placas Arduino son equivalentes. De hecho, se han diseñado para
ser muy específicos de la parte hardware, lo que nos proporciona una mayor abstracción del
hardware; podemos centrarnos en niveles superiores de diseño porque el bootloader nos proporciona
servicios como la carga de firmware a través de USB y la monitorización serial.
[ 14 ]
www.itebooks.info
Machine Translated by Google
Capítulo 1
• Procesamiento: http://processing.org/download/
En este libro se utiliza Processing, pero no es necesario para programar y utilizar placas
Arduino.
Sea cual sea la plataforma, el IDE funciona por igual y aunque describiré algunas partes específicas de
tres plataformas diferentes, solo describiré el uso del IDE y mostraré capturas de pantalla de OS X.
[ 15 ]
www.itebooks.info
Machine Translated by Google
Tienes que saber que usando el IDE puedes hacer todo lo que haremos en este libro.
¿Cómo se ve el IDE?
El IDE proporciona una interfaz gráfica en la que puedes escribir tu código, depurarlo,
compilarlo y cargarlo, básicamente.
[ 16 ]
www.itebooks.info
Machine Translated by Google
Capítulo 1
Hay seis iconos de izquierda a derecha que debemos conocer muy bien porque los utilizaremos cada vez:
• Cargar (flecha del lado derecho): Esto compila y carga nuestro código en el
Placa Arduino
• Abrir (flecha hacia arriba): Esto abre una lista de todos los bocetos que ya existen en
Nuestro cuaderno de bocetos
• Guardar (flecha hacia abajo): Esto guarda nuestro boceto en nuestro cuaderno de bocetos.
Cada elemento del menú de la barra superior ofrece más opciones que descubriremos progresivamente a lo largo
de este libro.
• Archivar boceto: Esto comprime todo el boceto actual con todos los archivos
• Puerto serie: proporciona una lista de todos los dispositivos serie del sistema.
[ 17 ]
www.itebooks.info
Machine Translated by Google
• Grabar gestor de arranque: esta es la opción que se utiliza cuando desea sobrescribir (o incluso
escribir) un nuevo gestor de arranque en su placa.
El menú Herramientas
El cuadro de diálogo de preferencias también es una parte que tenemos que aprender ahora mismo. Como
es habitual, el cuadro de diálogo de preferencias es un lugar al que no necesitamos acudir a menudo, pero solo
para cambiar los parámetros globales del IDE. En este cuadro de diálogo puedes elegir la ubicación del
cuaderno de bocetos y el idioma del editor. También puedes cambiar un par de cosas, como la comprobación
automática de las actualizaciones del IDE al iniciar o el tamaño de fuente del editor.
El concepto de cuaderno de bocetos nos hará la vida más fácil. De hecho, el cuaderno de bocetos es una
carpeta donde, básicamente, irán todos tus bocetos. En mi opinión, es muy valioso usarlo así porque realmente
te organiza las cosas y puedes recuperar tus fragmentos de código más fácilmente. Sígueme allí; me lo
agradecerás más tarde.
Cuando iniciamos un sketch desde cero, básicamente tecleamos el código, lo verificamos, lo subimos y lo
guardamos. Al guardarlo la primera vez, el IDE crea una carpeta en la que colocará todos los archivos
relacionados con nuestro sketch actual. Al hacer clic en el archivo del sketch dentro de esta carpeta, se abrirá el
IDE de Arduino y se mostrará el código relacionado en la parte de edición/escritura de la ventana.
[ 18 ]
www.itebooks.info
Machine Translated by Google
Capítulo 1
Hay una gran diferencia entre Windows y OS X: básicamente, OS X no requiere ningún controlador
específico para Arduino Uno o incluso Mega 2560. Si estás usando placas más antiguas, tendrás
que descargar la última versión de los controladores en el sitio web de FTDI, hacer doble clic en
el paquete, seguir las instrucciones y, por último, reiniciar tu computadora.
1. Conecte la placa y espere a que Windows comience el proceso de instalación del controlador.
Después de unos momentos, el proceso falla.
7. Finalmente, navegue y seleccione el archivo del controlador del Uno, llamado ArduinoUNO.inf,
ubicado en la carpeta Controladores de la descarga del software Arduino (tenga cuidado: no
en el subdirectorio Controladores USB FTDI ).
8. Windows finalizará la instalación del controlador desde allí y todo estará listo.
estar maravilloso.
[ 19 ]
www.itebooks.info
Machine Translated by Google
2. Seleccione Instalar desde una lista o ubicación especificada (Avanzado) y haga clic en Siguiente.
3. Asegúrese de que la opción Buscar el mejor controlador en estas ubicaciones esté marcada.
Desmarque Buscar medios extraíbles, marque Incluir esta ubicación en la búsqueda y navegue hasta el
directorio de controladores/controladores USB FTDI de la distribución de Arduino. (La última versión
de los controladores se puede encontrar en el directorio de controladores USB FTDI).
(sitio web.) Haga clic en Siguiente.
5. Aparecerá nuevamente el asistente para hardware nuevo. Siga los mismos pasos y seleccione las mismas
opciones y la misma ubicación para buscar. Esta vez, un puerto serial USB
se encontrará.
Puedes comprobar que los controladores se han instalado abriendo el Administrador de dispositivos de Windows
(en la pestaña Hardware del panel de control del sistema ). Busca un puerto serie USB en la sección Puertos ; esa es
la placa Arduino.
Ahora nuestro ordenador puede reconocer nuestra placa Arduino. Pasemos un poco al mundo físico para unir el
mundo tangible con el intangible.
¿Qué es la electricidad?
Arduino es todo acerca de la electrónica, y la electrónica se refiere a la electricidad. Esta puede ser tu primera inmersión
en este asombroso universo, hecho de cables y voltajes, incluidos LED parpadeantes y señales. Estoy definiendo varias
nociones muy útiles en esta parte; puedes considerar doblar la esquina de esta página y volver a visitarla con
tanta frecuencia como lo necesites.
Aquí utilizo la analogía habitual del agua. Básicamente, los cables son tuberías y el agua es la electricidad en sí
misma.
[ 20 ]
www.itebooks.info
Machine Translated by Google
Capítulo 1
Voltaje
El voltaje es una diferencia de potencial. Básicamente, esta diferencia la crea y mantiene un
generador. Este valor se expresa en unidades de voltios (el símbolo es V).
La analogía directa con los sistemas hidráulicos es comparar el voltaje con la diferencia de
presión del agua en dos puntos de una tubería. Cuanto mayor sea la presión, más rápido se
moverá el agua, siempre y cuando el diámetro de la tubería sea constante.
Trataremos el tema del bajo voltaje a lo largo de este libro, lo que significa nada más que 5 V. Muy
rápidamente, utilizaremos 12 V para alimentar motores y lo precisaré cada vez que lo hagamos.
Corriente y potencia
La corriente se puede comparar con el caudal volumétrico hidráulico, que es la cantidad volumétrica
de agua que fluye durante un intervalo de tiempo.
El valor de la corriente se expresa en amperios (el símbolo es A). Cuanto mayor sea la corriente,
mayor será la cantidad de electricidad en movimiento.
Para medir un caudal no es necesario contar con dos puntos como diferencia de presión, sólo
necesitamos un punto del circuito para realizar nuestra medición con un equipo llamado
Amperímetro.
En todas nuestras aplicaciones, trataremos con corriente continua (CC), que es diferente de la
corriente alternativa (CA).
La potencia es una noción específica, que se expresa en vatios (el símbolo es W).
P=VxI
¿Ya te sientes mejor? Esta analogía debe entenderse como una analogía adecuada, pero
realmente ayuda a entender lo que haremos un poco más adelante.
[ 21 ]
www.itebooks.info
Machine Translated by Google
Las resistencias se definen por su resistencia eléctrica expresada en ohmios (el símbolo es Ω).
Existe una relación matemática directa entre el voltaje medido en los lados de la resistencia, la corriente
y la resistencia, conocida como ley de Ohm:
R=V/I
Existen muchos tipos de resistencias. Algunas tienen una resistencia constante, otras pueden
proporcionar distintos valores de resistencia en función de parámetros físicos como la temperatura o la
intensidad de la luz, por ejemplo.
Un potenciómetro es una resistencia variable. Mueves un control deslizante o giras una perilla y la
resistencia cambia. Supongo que estás empezando a entender lo que quiero decir...
Otro tipo de componente que se utiliza con mucha frecuencia es el condensador . La analogía directa es la
membrana de goma que se coloca en la tubería: el agua no puede pasar a través de ella, pero el agua
puede moverse al estirarla.
También son componentes pasivos de dos terminales, pero pueden polarizarse. Por lo general, los
capacitores pequeños no lo son.
Generalmente decimos que los capacitores almacenan energía potencial al cargarse. De hecho, la propia
membrana de goma almacena energía mientras la estiras; intenta soltar la membrana estirada y encontrará su
primera posición.
La capacidad es el valor que define a cada capacitor. Se expresa en Faradios (el símbolo es F).
[ 22 ]
www.itebooks.info
Machine Translated by Google
Capítulo 1
Aquí nos detendremos en los cálculos de capacitancia porque implican matemáticas avanzadas, que
no son el propósito de este libro. Por cierto, tenga en cuenta que cuanto mayor sea la capacitancia, mayor
será el potencial que puede almacenar el capacitor.
Un diodo es nuevamente un componente pasivo de dos terminales pero está polarizado. Deja pasar la
corriente a través de él solo en un sentido y la detiene en el otro. Veremos que incluso en el caso de
corriente continua, puede ayudar y hacer más seguros nuestros circuitos en
Algunos casos.
Los LED son un tipo específico de diodo. Mientras la corriente pasa a través de ellos en la dirección correcta,
brillan. Esta es una propiedad muy útil que usaremos para verificar si nuestro circuito está correctamente cerrado
en unos minutos.
El transistor es el último elemento que describo aquí porque es un poco más complejo, pero no podemos hablar
de electrónica sin citarlo.
Los transistores son dispositivos semiconductores que pueden amplificar y conmutar señales electrónicas y de
potencia, según el uso que se les dé. Son componentes de tres terminales.
Este es el componente activo clave de casi todos los dispositivos electrónicos modernos que nos rodean.
Los microprocesadores están hechos de transistores y pueden incluso contener más de mil millones de ellos.
Los transistores en el mundo Arduino se utilizan a menudo para conducir corrientes elevadas que no podrían pasar
por la propia placa Arduino sin quemarla. En ese caso, los utilizamos básicamente como interruptores analógicos.
Cuando necesitamos que cierren un circuito de corrientes elevadas para accionar un motor, por ejemplo,
simplemente activamos uno de sus tres terminales con 5 V procedentes del Arduino y la corriente elevada
fluye a través de él como si hubiera cerrado un circuito. En ese caso, amplía las posibilidades de la placa
Arduino, lo que nos permite conducir corrientes más altas con nuestro pequeño trozo de hardware.
Los circuitos se construyen con cables, que son básicamente conductores. Un conductor es un material
con una resistencia cercana a cero; permite que la corriente fluya fácilmente. Los metales suelen ser
buenos conductores. A menudo utilizamos cables de cobre.
Para facilitar las operaciones de cableado, a menudo utilizamos pines y conectores. ¡Es una buena manera de
conectar cosas sin tener que usar un soldador cada vez!
[ 23 ]
www.itebooks.info
Machine Translated by Google
Por cierto, hay muchas formas de conectar diferentes componentes entre sí.
Para nuestro propósito de creación de prototipos, no diseñaremos placas de circuitos impresos ni
utilizaremos nuestro soldador; ¡utilizaremos placas de pruebas!
Una placa de pruebas con sus buses azules y rojos y sus numerosas perforaciones
Las placas de pruebas son el camino hacia la creación rápida de prototipos y este es el camino a seguir aquí.
Básicamente, las placas de pruebas consisten en una pieza de plástico con muchas perforaciones en las
que hay pequeños trozos de conductores que permiten conectar cables y terminales de componentes en su
interior.
La distancia entre dos perforaciones es de 2,54 mm (igual a 0,1"), que es un estándar; por ejemplo, los cables de los
circuitos integrados con paquete dual en línea están todos separados por esta distancia particular y, por lo tanto,
incluso puedes colocar circuitos integrados en placas de pruebas.
Los buses son series de cinco perforaciones en la parte central y colocadas en columna por donde se
conectan los conductores subyacentes. He rodeado un bus con un trazo verde.
Los terminales son buses especiales que se utilizan normalmente para alimentar el circuito y aparecen entre
las líneas azules y rojas. Normalmente, utilizamos el azul para las líneas de tierra y el rojo para la fuente de
tensión (5 V o 3,3 V en algunos casos). Una línea completa de terminales tiene todas sus perforaciones conectadas,
lo que proporciona una fuente de tensión y tierra fácilmente disponibles en toda la placa de pruebas sin tener que
utilizar muchas conexiones al Arduino.
Rodeé 2 de las 4 terminales con trazos rojos y azules.
Las placas de pruebas proporcionan una de las formas más sencillas de crear prototipos sin soldar.
¡También significa que puedes usar y reutilizar tus placas de pruebas a lo largo de los años!
[ 24 ]
www.itebooks.info
Machine Translated by Google
Capítulo 1
¿Qué es Fritzing?
Descubrí el proyecto de código abierto Fritzing (http://fritzing.org) cuando necesitaba una
herramienta para hacer mis primeras presentaciones esquemáticas de clases magistrales en torno
al controlador Protodeck (http://julienbayle.net/protodeck) que construí en 2010.
Fritzing se define como una iniciativa de código abierto para apoyar a diseñadores, artistas, investigadores
y aficionados a trabajar de forma creativa con la electrónica interactiva. Parece que hubiera sido creada
para nosotros, ¿no?
Básicamente, con Fritzing, puedes diseñar y esbozar circuitos electrónicos. Como existen muchas
representaciones de circuitos electrónicos, esta valiosa herramienta proporciona dos de las clásicas y
también una herramienta de diseño de PCB.
Considerando el primer trabajo práctico que vamos a realizar, tendrás que coger tu placa de
pruebas, tu Arduino, y cablear el cable y la resistencia exactamente como se muestra en la
siguiente captura de pantalla:
[ 25 ]
www.itebooks.info
Machine Translated by Google
La vista de la placa de pruebas es la que más se parece a lo que tenemos frente a nosotros en la mesa.
Representas todos los cables y conectas una placa de pruebas virtual a tu Arduino y conectas
directamente los componentes.
En la siguiente captura de pantalla, puedes ver el mismo circuito que antes, pero mostrado en la
vista esquemática:
[ 26 ]
www.itebooks.info
Machine Translated by Google
Capítulo 1
Hay muchos componentes ya diseñados especialmente para Fritzing e incluso puedes crear los
tuyos con bastante facilidad. La página que debes visitar para este propósito es http://fritzing.org/
parts/.
La biblioteca nativa contiene todas las piezas necesarias en todos los esquemas de este libro, desde todas
las placas Arduino hasta cualquier componente discreto y circuito integrado. De hecho, todos los
esquemas de este libro se han realizado con Fritzing.
Ahora que ya sabes cómo cablear cosas sin necesidad de un soldador y cómo dibujar y comprobar
cosas en silencio en tu computadora antes de hacerlo realmente en tu escritorio, aprendamos un poco
sobre fuentes de alimentación.
• Mediante una batería o una fuente de alimentación externa directa (PSU) /adaptador
El cable USB contiene cuatro cables: dos para la comunicación de datos y dos para la alimentación. Estos
últimos se utilizan básicamente para alimentar Arduino cuando lo conectas a la computadora a través de
USB.
USB es un bus de comunicación especial que proporciona 5 V pero no más de 500 mA.
(0,5 A) Significa que tenemos que utilizar otra fuente de suministro en proyectos especiales donde
necesitamos muchos LED, motores y otros dispositivos que manejan mucha corriente.
Por lo general, si te preguntas sobre si usar un adaptador o no, significa que necesitas más corriente que los
500 mA del USB (en la práctica, hazte esta pregunta si necesitas alrededor de 400 mA).
[ 27 ]
www.itebooks.info
Machine Translated by Google
El uso de USB o del conector de alimentación de 2,1 mm con un adaptador son las formas más
seguras de utilizar las placas Arduino por muchas razones. La principal es el hecho de que esas dos
fuentes están (con suerte) limpias, lo que significa que suministran un voltaje regulado.
Sin embargo, si se desea utilizar una u otra fuente es necesario cambiar algo en la placa: hay que
mover un puente a la posición correcta:
A la izquierda, el puente está configurado para la fuente de alimentación USB y a la derecha, está configurado para la fuente de alimentación externa.
Por lo general, una placa Arduino inactiva consume alrededor de 100 mA y, excepto en casos específicos
(consulte el Capítulo 9, Hacer que las cosas se muevan y crear sonidos), utilizaremos la forma de
alimentación USB. Esto es lo que tiene que hacer ahora: conecte el cable USB tanto en Arduino como
en su computadora.
Inicie también el IDE de Arduino y avancemos hacia el hardware Hola Mundo de nuestro sistema, ¡lo
llamo el LED Hola!
¡Hola LED!
Si su Arduino no contiene ningún firmware, el LED probablemente no haga nada.
Si revisas el LED incorporado en la placa Arduino, éste debería parpadear.
Tomemos el control de nuestro simpático LED externo enchufado a la placa de pruebas ahora
mismo.
[ 28 ]
www.itebooks.info
Machine Translated by Google
Capítulo 1
Queremos que nuestro LED parpadee. ¿Pero a qué velocidad de parpadeo? ¿Durante cuánto tiempo?
Digamos que queremos que parpadee cada 250 ms con una pausa de un segundo entre parpadeos.
Y queremos hacerlo infinitamente.
Si revisas el esquema, puedes entender que el LED está colocado entre tierra y la línea hacia el pin
de salida digital número 8.
Hay una resistencia y ahora sabes que puede consumir un poco de energía al oponer resistencia a la
corriente que fluye hacia el LED. Podemos decir que la resistencia protege nuestro LED.
Para que el LED se encienda, tenemos que crear un flujo de corriente. Para ello, podemos enviar +5 V a
la salida digital número 8. De esta forma, habrá una diferencia de potencial en los dos cables del
LED, lo que hará que se encienda. Pero la salida digital no debería estar a +5 V en todo momento. Tenemos
que controlar el momento en el que proporcionará este voltaje. ¿Todavía está bien?
[ 29 ]
www.itebooks.info
Machine Translated by Google
El IDE debe saber con qué placa se va a comunicar. Lo haremos siguiendo los siguientes pasos:
[ 30 ]
www.itebooks.info
Machine Translated by Google
Capítulo 1
2. Una vez que hemos hecho esto, tenemos que elegir el puerto serie correcto. Vamos a la
Menú Herramientas nuevamente y elegir el puerto serial correcto:
[ 31 ]
www.itebooks.info
Machine Translated by Google
Ahora, nuestro IDE puede comunicarse con nuestra placa. Ahora, insertemos el código.
/*
Programa Blink250ms
Enciende un LED conectado al pin digital 8 durante 250 ms y luego lo apaga durante
1s, infinitamente.
[ 32 ]
www.itebooks.info
Machine Translated by Google
Capítulo 1
Escrito por Julien Bayle, este código de ejemplo es Creative Commons CC
PorSA
*/
// la rutina de configuración se ejecuta una vez cuando enciende la placa o presiona el interruptor de reinicio
void configuración()
{ pinMode(ledPin, SALIDA); // inicializa el pin digital como un
salida porque queremos que genere una corriente
}
En primer lugar, todo lo que está entre /* y */, y todo lo que está después de // son solo comentarios.
La primera forma se usa para comentarios de más de una línea a la vez, y la otra es para comentarios
de una sola línea. Puedes escribir comentarios de este tipo y el compilador no los tendrá en cuenta
en absoluto. Te recomiendo encarecidamente que comentes tu código; esta es otra clave para tener
éxito.
Luego, la primera parte del código contiene una declaración de variable e inicialización:
int ledPin = 8;
void configuración()
{ pinMode(ledPin, SALIDA);
}
bucle vacío() {
digitalWrite(ledPin, ALTO); retraso(250);
digitalWrite(ledPin,
BAJO); retraso(1000);
[ 33 ]
www.itebooks.info
Machine Translated by Google
La primera (setup()) es una función que se ejecuta solo una vez cuando el
Se inicia (o reinicia) la placa Arduino; este es el lugar donde le estamos indicando a la placa que
el pin donde está conectado el LED es una salida, es decir, este pin tendrá que
Conduce corriente mientras está activado.
La segunda (loop()) es una función que se ejecuta infinitamente cuando se alimenta la placa
Arduino. Esta es la parte principal de nuestro código en la que podemos encontrar los pasos que
queríamos para encender el LED durante 250 ms y apagarlo durante 1 s, repetidamente.
Simplemente haz clic en el botón Cargar en el IDE. Verás que los LED TX y RX parpadean un
poco y... el LED de tu placa de pruebas debería parpadear como se espera. Este es nuestro
primer ejemplo de HELLO LED! y espero que te haya gustado.
retraso(1000);
retraso(100);
Resumen
En este capítulo aprendimos un poco sobre Arduino y los microcontroladores, y también sobre
electricidad. Eso nos servirá en los próximos capítulos en los que hablaremos mucho sobre circuitos.
También instalamos el IDE que usaremos siempre que programemos placas Arduino e incluso
probamos el primer fragmento de código. Ahora podemos continuar nuestro viaje aprendiendo
más sobre el lenguaje C.
[ 34 ]
www.itebooks.info
Machine Translated by Google
En nuestro caso, se trata de programación de sistemas integrados, que es otro nombre para
programación de hardware; esta primera afirmación también es cierta.
Por supuesto, esta definición es muy sencilla y se aplica también a los microcontroladores, pues ya
sabemos que estos últimos son básicamente un tipo de ordenadores.
www.itebooks.info
Machine Translated by Google
Diseñar un programa es algo en lo que hay que pensar antes de empezar a codificarlo. Generalmente
implica escribir, dibujar y hacer esquemas de todas las acciones que queremos que nuestro procesador
realice por nosotros. A veces, también implica escribir lo que llamamos pseudocódigo. Espero que
recuerdes que esto es lo que creamos en el capítulo anterior cuando queríamos definir con precisión
todos los pasos del comportamiento deseado del LED.
No estoy de acuerdo con que mucha gente lo llame pseudocódigo porque en realidad es más bien un...
Código real.
Lo que llamamos pseudocódigo es algo que ayuda mucho porque es legible para humanos, está
hecho de frases claras y sirve para pensar e ilustrar mejor nuestro propósito, que es la clave del éxito.
Escribir un programa es, por lo general, lo que convierte el pseudocódigo en código real y bien
formado. Implica tener conocimientos de lenguajes de programación, ya que es el paso en el que
realmente se escribe el programa. Esto es lo que aprenderemos en un momento.
La depuración es un paso muy importante cuando intentas averiguar por qué un programa no funciona
como se esperaba. Debes rastrear errores tipográficos, discrepancias lógicas y problemas de
arquitectura global del programa. Deberás monitorear las cosas y, a menudo, modificar un poco tu
programa para rastrear con precisión cómo funciona.
Mantener el código fuente es la parte de la vida del programa que ayuda a evitar
obsolescencia.
[ 36 ]
www.itebooks.info
Machine Translated by Google
Capítulo 2
• Orientado a objetos
• Imperativo
• Funcional
• Programación lógica
No es el propósito de este libro debatir sobre estos temas, pero yo añadiría uno que puede ser una
combinación de ellos y que también describe un concepto particular: la programación visual.
Descubriremos uno de los marcos más potentes en el Capítulo 6, Sensing the World — Feeling with
Analog Inputs, es decir, el marco Max 6 (antes llamado Max/MSP).
Estilo de programación
No existe una forma científica o universal de definir cuál es el mejor estilo de programación. Sin
embargo, puedo citar seis puntos que pueden ayudar a entender lo que intentaremos hacer juntos a lo
largo de este libro para crear buenos programas. Nuestro objetivo será el siguiente:
• Confiabilidad: Esto permite que un código maneje sus propios errores generados
mientras se ejecuta.
• Solidez: Esto proporciona un marco para anticipar problemas del lado del usuario (entradas
incorrectas)
• Ergonomía: Esto ayuda a poder utilizarlo intuitivamente con facilidad.
• Portabilidad: Es el diseño de un programa para una amplia gama de plataformas.
• Mantenibilidad: Es la facilidad de modificarlo incluso si no lo codificaste.
Hazlo tú mismo
• Eficiencia: Esto indica que un programa se ejecuta sin problemas y sin consumir muchos
recursos.
Por supuesto, volveremos a ellos en los ejemplos de este libro y estoy seguro de que mejorarás tu estilo
progresivamente.
[ 37 ]
www.itebooks.info
Machine Translated by Google
¿C y C++?
Dennis Ritchie (http://en.wikipedia.org/wiki/Dennis_Ritchie) En los Laboratorios Bell se desarrolló el
lenguaje de programación C entre 1969 y 1973. A menudo se lo define como un lenguaje de
programación de propósito general y es, de hecho, uno de los lenguajes más utilizados de todos
los tiempos. Se había utilizado inicialmente para diseñar el sistema operativo Unix (http://
en.wikipedia.org/wiki/Unix) que tenía numerosos requisitos, especialmente un alto rendimiento.
Ha influido en muchos lenguajes muy conocidos y utilizados como C++, ObjectiveC, Java,
JavaScript, Perl, PHP y muchos otros.
C es a la vez imperativo y estructurado. Es muy apropiado tanto para procesadores de 8 bits como de 64
bits, para sistemas que no solo tienen unos pocos bytes de memoria sino también terabytes, y también
para proyectos enormes que involucran equipos enormes, hasta los proyectos más pequeños con un solo
desarrollador.
¡Sí, vamos a aprender un lenguaje que te abrirá la mente a conceptos de programación globales
y universales!
Hoy en día, este es el único lenguaje que permite interactuar con el motor de hardware subyacente
tan fácilmente y esta es la razón por la que la cadena de herramientas de Arduino se basa en C.
[ 38 ]
www.itebooks.info
Machine Translated by Google
Capítulo 2
Entraremos juntos en este concepto un poco más adelante en este libro, pero básicamente, en los
programas orientados a objetos, se definen estructuras llamadas clases que son una especie de modelo, y
se crean objetos llamados instancias de esas clases, que tienen vida propia en tiempo de ejecución y que
respetan y heredan la estructura de la clase de la que provienen.
La programación orientada a objetos (POO) proporciona cuatro propiedades que son muy útiles e interesantes:
• Herencia (las clases pueden heredar atributos y comportamientos de sus clases principales)
En programación orientada a objetos, primero definimos clases y luego usamos funciones específicas llamadas constructores.
para crear instancias de esas clases. Imaginemos que una clase es un mapa de un tipo de casa y las instancias
son todas las casas construidas según el mapa.
Casi todas las bibliotecas de Arduino están hechas con C++ para que sean fácilmente reutilizables, lo cual
es una de las cualidades más importantes en la programación.
Una biblioteca de programación es una colección de recursos que están disponibles para que los
utilicen los programas.
• Datos de configuración
• Recursos de ayuda y documentación
• Subrutinas y parte reutilizable del código
• Clases
• Definiciones de tipos
[ 39 ]
www.itebooks.info
Machine Translated by Google
Me gusta decir que las bibliotecas proporcionan una encapsulación del comportamiento; no es necesario
saber cómo se crea el comportamiento para usarlo, simplemente lo usas.
• Utilizar bibliotecas
Incluso si nos gusta codificar cosas, somos más felices si podemos centrarnos en el propósito global de
nuestros diseños, ¿no es así?
En ese caso, intentaremos encontrar librerías ya diseñadas específicamente para los comportamientos
que necesitamos. Por ejemplo, probablemente exista una librería diseñada específicamente para el
control de matrices LED y otra con un propósito de conexión a servidores.
• Estructura (desde estructuras de control condicional globales hasta otras más específicas)
[ 40 ]
www.itebooks.info
Machine Translated by Google
Capítulo 2
Los siguientes pasos se pueden utilizar para encontrar ayuda directamente en IDE:
1. Abra su IDE.
2. Vaya a Archivo | Ejemplos; verá la siguiente captura de pantalla:
En la primera parte del menú (en la captura de pantalla anterior), tienes muchos
ejemplos relacionados únicamente con la biblioteca nativa.
[ 41 ]
www.itebooks.info
Machine Translated by Google
4. Se muestra una nueva ventana. Haga clic derecho en una palabra clave coloreada en el código como
Se muestra en la siguiente captura de pantalla:
Búsqueda de información de referencia para todas las palabras clave reservadas directamente en el IDE de Arduino
5. En la parte inferior de este menú contextual puedes ver Buscar en Referencia. Esta es una
herramienta muy útil que vas a entender ahora mismo, ¡haz clic en ella!
Tu IDE llama directamente a tu navegador predeterminado con una página HTML correspondiente a la
página de ayuda de la palabra clave en la que hiciste clic. Puedes permanecer concentrado dentro de tu
IDE y acceder a la ayuda.
[ 42 ]
www.itebooks.info
Machine Translated by Google
Capítulo 2
• SD proporciona una forma sencilla de leer/escribir tarjetas SD; es una alternativa más fácil de usar
que la solución EEPROM.
www.itebooks.info
Machine Translated by Google
Hay un par de bibliotecas más en la distribución principal. A veces, se incluyen otras nuevas.
• TLC5940: se utiliza para controlar sin problemas un controlador LED de 12 bits y 16 canales.
• MsTimer2: se utiliza para activar una acción que debe ser muy rápida e incluso cada 1 ms (esta
biblioteca también es un buen truco de uno de los temporizadores de hardware incluidos en el
chipset)
Puedes utilizar Google para encontrar más bibliotecas. Encontrarás muchas, pero no todas están
documentadas ni mantenidas de la misma forma. En el último capítulo de este libro veremos cómo crear
nuestra propia biblioteca y, por supuesto, cómo documentarla de forma adecuada para el resto de usuarios.
y nosotros mismos.
[ 44 ]
www.itebooks.info
Machine Translated by Google
Capítulo 2
Fuentes de C y C++
código
Encabezados Preprocesador
Fuentes de C y C++
código con
sustituciones
Analizador sintáctico
Árbol de análisis
Traducción
Asamblea
Ensamblador
Muchos objetos
Archivos
Bibliotecas Enlazador
Binario
Ejecutable
Código
Para llevar el código desde la fuente a la etapa de producción ejecutable se ejecutan los siguientes pasos:
1. El código fuente de C y C++ es exactamente el tipo de código que ya escribiste para el proyecto Blink250ms
en el Capítulo 1, Conectemos cosas.
de clase. Este tipo de diseño, en el que tienes archivos separados para el código fuente (el programa
que estás escribiendo actualmente) y los encabezados (elementos ya creados), proporciona una buena
manera de reutilizar tu código ya escrito.
código.
[ 45 ]
www.itebooks.info
Machine Translated by Google
5. Un archivo de objeto contiene código de máquina que no es ejecutable directamente por ningún
procesador de hardware.
7. Desde el código fuente hasta el archivo objeto, todos los procesos se resumen en
La compilación de nombres.
8. Normalmente, las bibliotecas proporcionan archivos de objetos, listos para ser vinculados por el enlazador.
A veces, especialmente en el mundo del código abierto, las bibliotecas también vienen con el
código fuente. Esto hace que sea más fácil realizar cambios en la biblioteca. En ese
caso, la biblioteca misma tendría que compilarse para producir los archivos de objeto necesarios
que se utilizarían en la compilación del código global.
9. Por lo tanto, definiremos la compilación como todo el proceso desde el código fuente hasta
El programa.
Incluso debería utilizar e introducir otro término: compilación cruzada. De hecho, estamos compilando
el código fuente en nuestro ordenador, pero el procesador final al que se dirige nuestro programa
resultante (firmware) es el procesador de Arduino.
En general, definimos la compilación cruzada como el proceso de compilar código fuente utilizando un
procesador con el fin de crear un programa para otro procesador.
Ahora, avancemos más y aprendamos cómo vamos a probar nuestras piezas iniciales de código C
usando con precisión la consola IDE.
[ 46 ]
www.itebooks.info
Machine Translated by Google
Capítulo 2
En la comunicación serial, los datos se envían secuencialmente, uno después del anterior. Esto
es lo opuesto a la comunicación paralela, donde los datos se envían por más de un canal, todos al
mismo tiempo.
Tasa de baudios
Como las dos entidades que quieren comunicarse mediante comunicaciones seriales tienen que estar
de acuerdo con la respuesta a la pregunta "Oye, ¿qué es una palabra?", tenemos que utilizar la
misma velocidad de transmisión en ambos lados. De hecho, si envío 001010101010, ¿es una palabra
completa o hay muchas palabras? Tenemos que definir, por ejemplo, que una palabra tiene cuatro
dígitos. Entonces, podemos entender que el ejemplo anterior contiene tres palabras: 0010, 1010 y
1010. Esto implica un reloj.
Esa definición de reloj se realiza inicializando la comunicación serial a una velocidad particular
en baudios, también llamada tasa de baudios.
1 baudio significa que se transmite 1 símbolo por segundo. Un símbolo puede tener más de un bit.
¡Es por esto que no tenemos que crear confusión entre bps, bit por segundo y baud!
[ 47 ]
www.itebooks.info
Machine Translated by Google
Hay muchos otros tipos de buses de comunicación en serie que describiremos un poco más adelante en
el Capítulo 10, Algunas técnicas avanzadas, en la sección Uso de I2C y SPI para LCD, LED y otros
juegos divertidos .
Arduino IDE ofrece un monitor serial muy útil que muestra todos los símbolos que envía la placa al
ordenador a través de la interfaz USB. Ofrece una gran variedad de velocidades de transmisión, desde
300 baudios hasta 115.200 baudios. En las siguientes secciones veremos cómo utilizarlo.
Monitoreo en serie
El monitoreo en serie es una forma de crear una comunicación muy básica y sencilla con nuestra placa.
Esto significa que podemos programarla para que nos hable a través del monitor en serie.
Si tienes que depurar algo y el comportamiento de la placa difiere de lo que esperas de ella, y
quieres "verificar si el problema se origina en el firmware o no", puedes crear algunas rutinas que te
escriban mensajes. Estos mensajes se denominan traces. Los traces pueden ser totalmente necesarios
para depurar el código fuente.
[ 48 ]
www.itebooks.info
Machine Translated by Google
Capítulo 2
Nuestro LED no parpadea en absoluto. ¿Cómo podemos estar seguros de que la estructura loop() de nuestro
código se está ejecutando correctamente? Modificaremos un poco el código para poder seguir sus pasos.
3. Modifique el código actual agregando todas las filas que comiencen con Serial
como sigue:
/*
Programa TalkingAndBlink250ms
Enciende un LED conectado al pin digital 8 durante 250 ms y luego lo apaga.
por 1s, infinitamente.
En ambos pasos, la placa Arduino envía datos a la consola del
IDE para fines informativos.
Escrito por Julien Bayle, este código de ejemplo se encuentra en Creative Commons AttributionShare Alike.
Licencia CCBYSA de Commons
*/
[ 49 ]
www.itebooks.info
Machine Translated by Google
configuración vacía() {
pinMode(ledPin, OUTPUT); // inicializa el pin digital como salida
[ 50 ]
www.itebooks.info
Machine Translated by Google
Capítulo 2
Haga clic en el pequeño símbolo de cristal en la esquina superior derecha para activar el Monitor Serial
[ 51 ]
www.itebooks.info
Machine Translated by Google
5. Elija la misma velocidad en baudios que escribió en el código, que se encuentra en el menú en la
parte inferior derecha de la ventana de Monitoreo en serie, y observe lo que
está sucediendo.
Notará que aparecen algunos mensajes en la ventana del Monitor serie, sincronizados
con los estados del LED parpadeantes.
Ahora, podemos estar seguros de que nuestro código está bien porque cada mensaje se envía y
porque todas las filas se procesan secuencialmente; significa que las funciones digitalWrite() también
se llaman correctamente (no hay nada bloqueado). Esta información puede ser una pista, por ejemplo,
para verificar nuestro circuito una vez más para intentar encontrar el error allí en lugar de en el código.
Por supuesto, este es un ejemplo trivial, pero estoy seguro de que entiendes el objetivo y el poder
de rastrear tu código.
[ 52 ]
www.itebooks.info
Machine Translated by Google
Capítulo 2
Serie.begin()
Todo comienza con la función Serial.begin() . Esta función en setup()
La rutina se ejecuta solo una vez, es decir, cuando se inicia el Arduino.
En el código, configuré la placa para iniciar una comunicación en serie a 9.600 baudios.
Serial.print() y Serial.println()
Serial.print() y Serial.println() se comportan de manera casi idéntica: escriben algo en la salida serial,
pero la versión ln también agrega un retorno de carro y una nueva línea.
Investigando un poco…
Si revisaste el código cuidadosamente (y estoy seguro de que lo hiciste), notaste que colocamos
dos grupos de tres filas: un grupo justo después de la función digitalWrite(ledPin,HIGH) que enciende
el LED y el otro grupo después de la fila que lo apaga.
¿Entiendo?
Hemos pedido a la placa Arduino que envíe un mensaje según la última orden pasada al pin
digital número 8, donde el LED sigue conectado. Y la placa envía un mensaje cuando le hemos
pedido al pin que entregue corriente (cuando el LED está encendido), y otro mensaje cuando el pin
no entrega corriente (cuando el LED está apagado).
[ 53 ]
www.itebooks.info
Machine Translated by Google
Esto significa que también podemos usar esa herramienta para enviar datos a la placa desde nuestro ordenador.
Sin embargo, la placa de firmware tiene que implementar algunas otras funciones para poder entender lo
que queremos enviar.
Más adelante en este libro veremos cómo utilizar la ventana Serial Monitor, la genialidad
Marco de procesamiento y el marco Max 6 para enviar mensajes fácilmente a la
Placa Arduino.
Resumen
En este capítulo aprendimos sobre programación usando lenguaje C. También aprendimos a utilizar
la función de monitoreo serial de nuestro IDE Arduino para poder saber un poco más sobre lo que
está sucediendo en tiempo real en nuestro procesador Arduino usando traces.
Hablé de comunicación serial porque es muy útil y también se utiliza en muchos proyectos de la
vida real en los que se necesita que un ordenador y una placa Arduino se comuniquen entre sí.
También se puede utilizar entre dos placas Arduino o entre placas Arduino y otros circuitos.
[ 54 ]
www.itebooks.info
Machine Translated by Google
También iré introduciendo progresivamente nuevos conceptos que utilizaremos más adelante,
como las funciones. No te preocupes si no lo entiendes muy bien, me gusta que mis alumnos escuchen
algunas palabras progresivamente, a veces incluso sin una definición adecuada al principio, porque
ayuda a una mayor explicación.
Así que si no lo defino, pero hablo de ello, relájense, las explicaciones vendrán más adelante. Vamos
a profundizar.
www.itebooks.info
Machine Translated by Google
Algo muy útil con las variables es el hecho de que podemos cambiar su contenido (el valor) en tiempo de
ejecución; es también por eso que se llaman variables, a diferencia de las constantes que también
almacenan valores, pero que no se pueden cambiar mientras el programa se está ejecutando.
¿Qué es un tipo?
Las variables (y constantes) están asociadas a un tipo. Un tipo, también llamado tipo de datos, define
la naturaleza posible de los datos. También ofrece una buena manera de reservar directamente un
espacio con un tamaño definido en la memoria. C tiene alrededor de 10 tipos principales de datos que se
pueden ampliar, como veremos aquí.
Deliberadamente solo estoy explicando los tipos que usaremos mucho en la programación de Arduino.
Esto se adapta a aproximadamente el 80 por ciento de otros tipos de datos C habituales y será más que
suficiente aquí.
Básicamente, usamos un tipo cuando declaramos una variable como se muestra aquí:
int ledPin; // declara una variable del tipo int y llamada "ledPin"
Se reserva en la memoria un espacio de un tamaño determinado (el tamaño relacionado con el tipo int )
y, como puede ver, si solo escribe esa línea, no habrá datos almacenados en esa variable. Pero tenga
en cuenta que se reserva un espacio de memoria, listo para usarse para almacenar valores.
[ 56 ]
www.itebooks.info
Machine Translated by Google
Capítulo 3
entero
Almacena números como datos con signo de 2 bytes, lo que significa 2 bytes (16 bits)
que desde 32.768 hasta 32.767 también puede no estar firmado y luego
almacenar números del 0 al 65.535.
palabra
Almacena números como datos sin signo de 2 bytes exactamente 2 bytes (16 bits)
como lo hace un int sin signo .
largo Almacena números como datos con signo de 4 bytes , lo que significa 4 bytes (32 bits)
desde 2.147.483.648 hasta 2.147.483.647, y puede no estar firmado y luego
almacenar números del 0 al 4.294.967.295.
flotar
Básicamente, almacena números con un punto decimal desde 4 bytes (32 bits)
3.4028235E + 38 hasta 3.4028235E + 38 como números con signo de 4 bytes.
datos.
Tenga cuidado con la precisión requerida; solo tienen entre seis y siete
dígitos decimales y a veces pueden dar resultados de redondeo extraños.
doble Generalmente almacena valores flotantes con una precisión dos veces mayor que 4 bytes (32 bits)
el valor flotante.
Formación Una matriz es una estructura ordenada de elementos consecutivos del mismo Número de
tipo a los que se puede acceder mediante un número de índice. elementos x tamaño
del tipo de
elementos
cadena Almacena cadenas de texto en una matriz de caracteres donde el último número de
Cadena Es una estructura particular de datos, es decir, una clase, que Disponible siempre
Proporciona una forma agradable de utilizar y trabajar con cadenas de texto. con la longitud()
[ 57 ]
www.itebooks.info
Machine Translated by Google
El siguiente es un ejemplo:
Esto sucede en ambas direcciones, restando 1 de una variable int que almacena 32768
El resultado es 32767. Tenlo en cuenta.
Declarando variables
La declaración de una variable es una declaración en la que se especifica un identificador, un tipo
y, finalmente, las dimensiones de la variable.
En C y todos los demás lenguajes fuertemente tipados como Java y Python, debemos
Declara las variables antes de usarlas. De todos modos, el compilador se quejará si olvidas la
declaración.
[ 58 ]
www.itebooks.info
Machine Translated by Google
Capítulo 3
Definición de variables
La siguiente tabla contiene algunos ejemplos de definición de variables:
Tipo Ejemplo
booleano bool myVariable; // declaración de la variable
myVariable = true; // definición de la variable asignándole un valor
carbonizarse char myChar = 'U'; // declaración y definición utilizando el valor ASCII de 'U' (es decir, 85)
char myDefaultChar = 128; // esto da un ERROR porque los caracteres están firmados de 128
a 127
unsigned char myUnsignedChar = 128; // ¡esto es correcto!
largo long myLong = 123; // no olvides que podemos usar números negativos
¡Números también!
doble double myDouble = 1.234567; // La implementación de Arduino de double es la misma que la de float
[ 59 ]
www.itebooks.info
Machine Translated by Google
Tipo Ejemplo
Formación int myIntTable[5]; // declaración de una tabla que puede contener 5 números enteros
myIntTable[5]; // considerando la definición anterior, esto da un ERROR límite de matriz (el índice
comienza desde 0 y, por lo tanto, el último aquí es myIntTable[4])
Definir una variable es el acto de asignar un valor al área de memoria previamente reservada para esa
variable.
Declararemos y definiremos algunas variables de cada tipo. He incluido algunas explicaciones en los
comentarios del código.
Aquí tienes algunos ejemplos que puedes utilizar, pero verás que en cada fragmento de código que se
proporciona en este libro se utilizan distintos tipos de declaraciones y definiciones. Te resultará fácil
hacerlo tan pronto como conectemos la placa.
Cadena
El tipo String merece un subcapítulo entero porque es algo más que un tipo.
De hecho, es un objeto (en el sentido de programación orientada a objetos).
Los objetos tienen propiedades y funciones especiales. Las propiedades y funciones están
disponibles de forma nativa porque String ahora es parte del núcleo de Arduino y se puede
considerar una entidad preexistente incluso si su IDE no contiene ninguna línea.
Nuevamente, el marco se encarga de las cosas por usted, proporcionándole un tipo/objeto con
funciones potentes y ya codificadas que se pueden utilizar directamente.
[ 60 ]
www.itebooks.info
Machine Translated by Google
Capítulo 3
En el caso de los objetos String , me refiero a la construcción en lugar de a la definición , pero puedes
considerar ambos términos como iguales. Declarar un tipo String en el núcleo de Arduino implica un
constructor de objetos, que es un concepto de programación orientada a objetos; afortunadamente, no
tenemos que manejarlo en este momento.
Tenga en cuenta que los índices comienzan en 0 y no en 1. Los objetos String implementan algunas
funciones para este propósito particular.
carácter()
Considerando que un tipo String se declara y define de la siguiente manera:
[ 61 ]
www.itebooks.info
Machine Translated by Google
Conozcamos otras funciones similares. Las usarás muy a menudo porque, como ya hemos
visto, la comunicación a un nivel muy bajo incluye el análisis y procesamiento de datos, que
muy a menudo pueden ser cadenas.
indexOf() y lastIndexOf()
Consideremos la misma declaración/definición:
[ 62 ]
www.itebooks.info
Machine Translated by Google
Capítulo 3
La función lastIndexOf() devuelve la última aparición de una cadena o carácter dentro de una
cadena.
comienzaCon() y terminaCon()
Las funciones startsWith() y endsWith() comprueban si una cadena comienza o termina,
respectivamente, con otra cadena pasada como argumento a la función.
Supongo que ya has empezado a entenderlo. endsWith() también funciona así, pero compara el
patrón de cadena con el final de la cadena probada.
[ 63 ]
www.itebooks.info
Machine Translated by Google
Concatenación
La concatenación de cadenas es una operación en la que se toman dos cadenas y se las pega. El resultado
es una nueva cadena compuesta por las dos cadenas anteriores. El orden es importante; hay que
gestionar qué cadena se quiere añadir al final de la otra.
Concatenación()
El núcleo Arduino viene con la función string.concat() , que está especialmente diseñada para
este propósito.
Este código es el mismo que el anterior. + es un operador que describiré mejor un poco más adelante.
Te doy algo más aquí: una notación condensada para el +
operador:
[ 64 ]
www.itebooks.info
Machine Translated by Google
Capítulo 3
primeraCadena += segundaCadena;
Pruébalo, lo entenderás.
Extraer y reemplazar
La manipulación y alteración de cadenas se puede realizar utilizando algunas funciones muy
útiles que extraen y reemplazan elementos en la cadena.
substring() es el extractor
Quieres extraer una parte de una cadena. Imagina que la placa Arduino envía mensajes con un
protocolo de comunicación específico y definido:
<número de salida>.<valor>
El número de salida se codifica con dos caracteres cada vez, y el valor con tres (45 debe
escribirse como 045). A menudo trabajo así y envío este tipo de mensajes desde el puerto
serie de mi computadora a través del USB cuando lo necesito; por ejemplo, enviar un comando
para encender un LED en particular con una intensidad particular.
Si quiero encender el led de la cuarta salida a 100/127 envío:
04.100
Arduino necesita entender este mensaje. Sin entrar en detalles sobre el diseño del
protocolo de comunicación, que se tratará en el Capítulo 7, Hablar por serial, quiero presentarles
una nueva función: la división de cadenas.
currentOutputNumber = mensajeRecibido.substring(0,2);
currentValueNumber = mensajeRecibido.substring(3);
[ 65 ]
www.itebooks.info
Machine Translated by Google
Este fragmento de código divide el mensaje recibido por Arduino en dos partes.
Imaginemos que quiero usar el punto como separador, porque estoy muy seguro de ello. ¿Cómo puedo hacerlo
usando las cosas que ya hemos aprendido? Necesitaría extraer caracteres. ¡Ahora ya sé qué es substring() !
Pero también necesito un índice para extraer el contenido en un lugar determinado. También sé cómo encontrar el
índice de una ocurrencia de un carácter en una cadena, usando indexOf().
En primer lugar, encuentro el índice del punto de división (el lugar en la cadena donde se encuentra el punto).
En segundo lugar, utilizo este resultado como el último elemento de la subcadena extraída. No te preocupes,
el último elemento no está incluido, lo que significa que currentOutputNumber no contiene el punto.
[ 66 ]
www.itebooks.info
Machine Translated by Google
Capítulo 3
Por último, utilizo splitPointIndex una vez más como inicio de la segunda parte de la cadena que
necesito extraer. ¿Y qué? Le agrego el entero 1 porque, como ya dominas substring() y sabes, el
elemento correspondiente al índice de inicio siempre está incluido en la operación substring() . No
queremos ese punto porque es solo un separador. ¿Verdad?
No os preocupéis si estáis un poco perdidos. Las cosas se aclararán en los siguientes subcapítulos
y sobre todo cuando hagamos que Arduino procese cosas, lo cual vendrá un poco más adelante.
en el libro.
Reemplazo
Los reemplazos se utilizan a menudo cuando queremos convertir un protocolo de comunicación en
otro. Por ejemplo, necesitamos reemplazar una parte de una cadena por otra para preparar un
proceso posterior.
Tomemos nuestro ejemplo anterior. Ahora queremos reemplazar el punto por otro carácter
porque queremos enviar el resultado a otro proceso que solo entiende el carácter de
espacio como separador.
mensajeoriginal = mensajerecibido;
La función replace() reemplaza una parte de una cadena con otra cadena.
Sintaxis: string.replace(substringToReplace, replacedSubstring);
[ 67 ]
www.itebooks.info
Machine Translated by Google
Esta función puede, obviamente, reemplazar un carácter por otro carácter, por supuesto.
Una cadena es una matriz de caracteres. No es extraño que un carácter pueda procesarse como una
cadena con un solo elemento. Pensemos un poco en ello.
aCharArray()
Esta función copia todos los caracteres de la cadena en una matriz de caracteres "real", también
llamada, por razones internas, buffer. Puedes consultar http://arduino.cc/en/
Referencia/StringToCharArray.
toLowerCase() y toUpperCase()
Estas funciones reemplazan las cadenas que procesan por la misma cadena pero con todos los
caracteres en minúsculas y mayúsculas respectivamente. Puedes consultar http://arduino.cc/
en/Reference/StringToLower y http://arduino.cc/en/
Referencia/StringToUpperCase. Tenga cuidado, ya que sobrescribe la cadena procesada con el
resultado de este proceso.
recortar()
Esta función elimina todos los espacios en blanco de la cadena. Puedes consultar http://
arduino.cc/en/Reference/StringTrim. Nuevamente, tenga cuidado, ya que sobrescribe las cadenas
procesadas con el resultado de este proceso.
longitud()
Quería terminar con esta función. Es la que usarás mucho. Proporciona la longitud de una cadena
como un número entero. Puedes consultar http://arduino.cc/en/Reference/
Longitud de cadena.
/*
Programa de variaciones de variables
Este firmware muestra mensajes en serie para una mejor comprensión.
uso de variables.
[ 68 ]
www.itebooks.info
Machine Translated by Google
Capítulo 3
Escrito por Julien Bayle, este código de ejemplo está bajo licencia Creative Commons
Licencia CC BYSA
*/
void setup()
{ Serial.begin(9600); myBoolean
= false; myChar = 'A'; myInt =
1; myFloat = 5.6789 ;
myString =
"¡Hola humano!!";
bucle vacío(){
// comprobando el booleano if
(myBoolean)
{ Serial.println("myBoolean es verdadero");
} demás {
Serial.println("myBoolean es falso");
}
[ 69 ]
www.itebooks.info
Machine Translated by Google
Serie.println();
} de lo
contrario { myBoolean = falso; // restableciendo myBoolean a falso
}
[ 70 ]
www.itebooks.info
Machine Translated by Google
Capítulo 3
Sube este código a tu placa y luego enciende el monitor serial. Por último, reinicia la placa presionando el
botón de reinicio y observa. La placa escribe directamente en tu monitor serial como se muestra en la
siguiente captura de pantalla:
Algunas explicaciones
Todas las explicaciones llegarán progresivamente, pero aquí os dejo un pequeño resumen de lo que está
ocurriendo ahora mismo.
Primero declaro mis variables y luego defino algunas en setup(). Podría haberlas declarado y definido al
mismo tiempo.
Para refrescar tu memoria, setup() se ejecuta solo una vez al iniciar la placa.
Luego, la función loop() se ejecuta infinitamente, ejecutando secuencialmente cada fila de la
declaración.
[ 71 ]
www.itebooks.info
Machine Translated by Google
Luego, jugaré un poco con los tipos char, int y String , imprimiendo algunas variables, luego modificándolas
y reimprimiéndolas.
El punto principal a destacar aquí es la estructura if() y else . Mírela y relájese, las respuestas llegarán
muy pronto.
El concepto de alcance
El ámbito se puede definir como una propiedad particular de una variable (y de las funciones, como
veremos más adelante). Teniendo en cuenta el código fuente, el ámbito de una variable es la parte del
código donde dicha variable es visible y utilizable.
Una variable puede ser global y luego visible y utilizable en cualquier lugar del código fuente.
Pero una variable también puede ser local, declarada dentro de una función, por ejemplo, y que sea
visible sólo dentro de esa función en particular.
Intentar minimizar el alcance de las variables es sin duda una estrategia ganadora. Veamos el siguiente
ejemplo:
// Esta variable se declara en el nivel más alto, haciéndola visible en todas partes.
configuración vacía(){
// …algo de código
}
bucle vacío(){
int a; // a es visible solo dentro de la función de bucle
anotherFunction(); // llamando a la función global anotherFunction
void otraFuncion() {
// … otro código más
int veryLocalVar; // veryLocalVar es visible solo en la función anotherFunction
[ 72 ]
www.itebooks.info
Machine Translated by Google
Capítulo 3
Podríamos representar el alcance del código como una caja más o menos imbricada.
El cuadro externo representa el nivel más alto de alcance del código fuente. Todo lo que se
declara en este nivel es visible y utilizable por todas las funciones; es el nivel global.
Cada cuadro representa un ámbito particular en sí mismo. Cada variable declarada en un ámbito
no puede ser vista ni utilizada en ámbitos superiores ni en los del mismo nivel.
Esta representación es muy útil para mis alumnos que siempre necesitan más elementos visuales.
También utilizaremos esta metáfora cuando hablemos de bibliotecas, en particular. Lo que se
declara en las bibliotecas se puede utilizar en nuestro código si incluimos algunos encabezados
específicos al principio del código, por supuesto.
[ 73 ]
www.itebooks.info
Machine Translated by Google
static Cuando
se utiliza el calificador static para una variable dentro de una función, esto hace que la variable sea
persistente entre dos llamadas a la función. Declarar una variable dentro de una función hace que la
variable, implícitamente, sea local a la función como acabamos de aprender. Esto significa que solo la
función puede conocer y usar la variable. Por ejemplo:
int miVariableGlobal;
configuración vacía()
{}
void loop()
{ miFuncion(digitalPinValue);
}
Esta variable se ve únicamente en la función myFunction . Pero, ¿qué sucede después del primer
bucle? El valor anterior se pierde y, tan pronto como se ejecuta int aLocalVariable;, se configura una
nueva variable con un valor de cero. Vea este nuevo fragmento de código:
void loop()
{ miFuncion(digitalPinValue);
}
Esta variable se ve solo en la función myFunction y, después de agregarle un argumento que la haya
modificado, podemos jugar con su nuevo valor.
[ 74 ]
www.itebooks.info
Machine Translated by Google
Capítulo 3
En este caso, la variable se califica como estática. Esto significa que la variable se declara únicamente
la primera vez. Esto proporciona una forma útil de mantener un registro de algo y, al mismo tiempo,
hacer que la variable que contiene ese registro sea local.
volátil
Cuando se utiliza el calificador volátil en una declaración de variable, esta variable se carga
desde la RAM en lugar de desde el espacio de memoria de registro de almacenamiento de la placa.
La diferencia es sutil y este calificador se utiliza en casos específicos en los que el código en sí no
tiene el control de algo más que se ejecuta en el procesador. Un ejemplo, entre otros, es el uso de
interrupciones. Lo veremos un poco más adelante.
Básicamente, el código se ejecuta con normalidad y algunas instrucciones no las activa este código,
sino otro proceso, como un evento externo. De hecho, nuestro código no sabe cuándo ni qué
hace la rutina de servicio de interrupción (ISR) , pero se detiene cuando ocurre algo así, lo que
permite que la CPU ejecute la ISR y luego continúa. Cargar la variable desde la RAM evita algunas
posibles inconsistencias en el valor de la variable.
constante
El calificador const significa constante. Calificar una variable con const la hace invariable, lo
que puede sonar extraño.
Esto es equivalente a:
#define parece usarse menos que const, probablemente porque no se puede usar para matrices
constantes. Cualquiera sea el caso, siempre se puede usar const . Ahora, sigamos adelante y
aprendamos algunos operadores nuevos.
[ 75 ]
www.itebooks.info
Machine Translated by Google
• % (porcentaje)
•
= (igual)
Para los demás operadores, voy a distinguir dos casos diferentes: los tipos de caracteres, que
incluyen char y String, y los tipos numéricos. Los operadores pueden cambiar un poco su efecto
según los tipos de variables.
Tipos de personajes
Los caracteres y las cadenas solo se pueden procesar con +. Como habrás adivinado, + es el
operador de concatenación:
[ 76 ]
www.itebooks.info
Machine Translated by Google
Capítulo 3
Tipos numéricos
Con todos los tipos numéricos (int, word, long, float, double), puedes utilizar los siguientes
operadores:
• + (adición)
• (resta)
• * (multiplicación)
• / (división)
• % (módulo)
A continuación se muestra un ejemplo básico de multiplicación:
Ejemplo 1:
int miInt1 = 1;
int miInt2 = 2;
[ 77 ]
www.itebooks.info
Machine Translated by Google
Ejemplo 2:
int miInt1 = 1;
int miInt2 = 2;
miInt1 += miInt2;
+, , *, / y % tienen mayor precedencia que =. Esto significa que myInt1 + myInt2 se calcula antes
del operador de asignación y, luego, el resultado se asigna a myInt1.
La segunda es la versión condensada. Es equivalente a la primera versión y, por lo tanto, aquí también
se aplica la precedencia. A continuación se muestra un ejemplo un poco complicado:
int miInt1 = 1;
int miInt2 = 2;
Debes saber que + tiene mayor precedencia que +=. Esto significa que el orden de las
operaciones es: primero, myInt2 + myInt2 luego myInt1 + el resultado del cálculo recién realizado
myInt2 + myInt2. Luego, el resultado del segundo se asigna a myInt1.
Esto significa que es equivalente a:
int miInt1 = 1;
int miInt2 = 2;
int miInt1 = 1;
[ 78 ]
www.itebooks.info
Machine Translated by Google
Capítulo 3
A continuación, se muestra una tabla condensada que puedo brindarle con los casos más utilizados. En
cada grupo, los operadores tienen la misma precedencia. Esto hace que la expresión myInt++ + 3 sea
ambigua. Aquí, el uso de paréntesis ayuda a definir qué cálculo se realizará.
hacerse primero.
() Llamada de función
5 *
Multiplicación
/ División
% Módulo
6 + Suma
Sustracción
16 =
Asignación
+= Asignación por suma
=
Asignación por diferencia
*=
Asignación por producto
/= Asignación por cociente
%= Cesión por remanente
Supongo que te empiezas a sentir un poco mejor con los operadores, ¿no? Continuemos con un paso muy
importante: la conversión de tipos.
Manipulaciones de tipos
Al diseñar un programa, hay un paso importante que consiste en elegir el tipo adecuado para cada
variable.
[ 79 ]
www.itebooks.info
Machine Translated by Google
A veces, tienes que elegirlo tú mismo. Imagina que tienes datos que llegan a la placa desde un
parche del framework Max 6 en la computadora a través de tu conexión serial (usando USB). Debido a
que es lo más conveniente, ya que lo diseñaste así, el parche muestra números flotantes encapsulados
en mensajes de cadena a la placa. Después de haber analizado, corta esos mensajes en partes para
extraer la información que necesitas (que es la parte flotante ), ¿elegirías almacenarlos en int?
Esa pregunta es un poco más difícil de responder, ya que implica un proceso de conversión .
Es una consecuencia del diseño de C que solo podemos convertir los valores almacenados en
variables, los demás mantienen su tipo hasta que termina su vida útil, que es cuando termina la ejecución
del programa.
La conversión de tipos se puede realizar de forma implícita o explícita . Para asegurarme de que todos estén de acuerdo
conmigo, diré que implícitamente significa que no está escrito de forma visible y consciente, en comparación con
explícitamente, que significa que está escrito específicamente en código .
Estoy usando el operador de asignación (=) para poner el contenido de myFloat en myInt.
Provoca el truncamiento del valor float , es decir, la eliminación de la parte decimal. Definitivamente
has perdido algo si continúas trabajando solo con la variable myInt en lugar de myFloat. Puede estar bien,
pero debes tenerlo en cuenta.
Otro ejemplo menos clásico es la conversión implícita del tipo int a float .
No tiene una parte decimal. La conversión implícita a float no producirá nada más que una parte
decimal que sea igual a cero. Esta es la parte fácil.
[ 80 ]
www.itebooks.info
Machine Translated by Google
Capítulo 3
Pero ten cuidado, podrías sorprenderte con la conversión implícita de int a float.
Los números enteros se codifican en 32 bits, pero los números de punto flotante, incluso si
son de 32 bits, tienen una mantisa (también llamada significando) codificada en 23 bits. Si no
recuerdas esto con precisión, no hay problema. Pero quiero que recuerdes este ejemplo:
flotar miFloat;
largo int myInt = 123456789;
configuración vacía(){
Serie.begin(9600);
miFlotador = miInt;
}
bucle vacío(){
Serial.println(myFloat); // muestra un resultado muy extraño
}
Almacené 123456789 en un tipo int largo , lo cual es totalmente legal (los int largos son enteros con signo
de 32 bits que pueden almacenar enteros desde 2147483648 hasta 2147483647).
Después de la tarea, me aparece el resultado: 123456792.00. Esperábamos
123456789.00 por supuesto.
[ 81 ]
www.itebooks.info
Machine Translated by Google
• carácter()
• int()
• flotar()
• palabra()
• byte()
• largo()
Podemos utilizarlos pasando la variable que queremos convertir como argumento de la función. Por
ejemplo, myFloat = float(myInt); donde myFloat es de tipo float y myInt es de tipo int . No te preocupes
por el uso, los utilizaremos un poco más adelante en nuestro firmware.
Expresiones de comparación
Hay seis operadores de comparación:
•
== (igual)
• != (no es igual)
•
< (menor que)
•
> (mayor que)
•
<= (menor o igual a)
•
>= (mayor o igual a)
[ 82 ]
www.itebooks.info
Machine Translated by Google
Capítulo 3
Una expresión como esa no hace nada, pero es legal. Comparar dos elementos produce un
resultado y en este pequeño ejemplo, no se usa para activar o generar nada. myInt1 > myFloat
es una expresión de comparación. El resultado es, obviamente, verdadero o falso, es decir, es
un valor booleano . Aquí es falso porque 4 no es mayor que 5,76. También podemos combinar
expresiones de comparación para crear expresiones más complejas.
• && (y)
•
|| (o)
•
! (no)
Es hora de recordar algunas operaciones lógicas utilizando tres tablas pequeñas. Puedes leer
esas tablas como elemento de columna + operador de comparación + elemento de fila; el
resultado de la operación está en la intersección de la columna y la fila.
|| verdadero FALSO
verdadero FALSO
! FALSO verdadero
[ 83 ]
www.itebooks.info
Machine Translated by Google
Por ejemplo, verdadero && falso = falso, falso || verdadero = verdadero. && y || son operadores
binarios, pueden comparar dos expresiones.
! es un operador unario y sólo puede funcionar con una expresión, negándola lógicamente. &&
es el AND lógico. Es verdadero cuando ambas expresiones comparadas son verdaderas, falso
en todos los demás casos. || es el OR lógico. Es verdadero cuando al menos una expresión es
verdadera, falso cuando ambas son falsas. Es el OR inclusivo. ! es el operador de negación, el NOT.
Básicamente invierte falso y verdadero en verdadero y falso.
Estas diferentes operaciones son realmente útiles y necesarias cuando se desea realizar algunas
pruebas en el código. Por ejemplo, si se desea comparar una variable con un valor específico.
Esto puede resultar muy útil cuando crees condiciones en tu código. Por ejemplo,
consideremos dos expresiones con cuatro variables a, b, c y d:
•a<b
• c >= d
(a < b) && (c >= d) y !((a < b) && (c >= d)) es igual a (!(a < b) || !(c >= d)) es igual a (a >=
b) || (c < d)
A continuación se muestra otro ejemplo de combinación que introduce el concepto de precedencia de operadores :
int miInt1 = 4;
flotar myFloat = 5.76;
int miInt2 = 16;
(miInt1 > miFlotante && miInt2 < miFlotante) ;
( (miInt1 > miFlotante) && (miInt2 < miFlotante) ) ;
[ 84 ]
www.itebooks.info
Machine Translated by Google
Capítulo 3
Ambas afirmaciones son equivalentes. Aquí se da la precedencia y ahora podemos agregar estos
operadores a la tabla de precedencias anterior (consulte el Apéndice B, Precedencia de operadores en
C y C++). Estoy agregando el operador de comparación:
() Llamada de función
5 *
Multiplicación
/ División
% Módulo
6 + Suma
Sustracción
8 < Menos que
<= Menor o igual a
> Más que
>= Mayor o igual a
9 ==
Igual a
!= No es igual a
13 &&
Y lógico
14 || OR lógico
15 ?: Condicional ternario
16 =
Asignación
+= Asignación por suma
=
Asignación por diferencia
*=
Asignación por producto
/= Asignación por cociente
%= Cesión por remanente
Como de costumbre, hice un poco de trampa y agregué el grupo de precedencia 15 que contiene un
operador único, el operador condicional ternario que veremos un poco más adelante. Pasemos a las
estructuras condicionales.
[ 85 ]
www.itebooks.info
Machine Translated by Google
Si el valor de la variable a es menor que el valor de la variable b, encienda el LED. En caso contrario,
apáguelo.
Ahora el código C real, donde simplifico la parte sobre el LED dando un estado de 1 o 0 dependiendo de lo que
quiera hacer más en el código:
entero a;
entero b;
int estadoled;
si (a < b) {
estadoLed = 1; }
demás {
estadoled = 0; }
Supongo que está bastante claro. Aquí está la sintaxis general de esta estructura:
Si (expresión) {
// código ejecutado solo si la expresión es verdadera
}
demás {
// código ejecutado solo si la expresión es falsa
}
La evaluación de expresiones generalmente da como resultado un valor booleano. Pero los valores numéricos
como resultado de una expresión en esta estructura también pueden ser aceptables, incluso si son un poco
menos explícitos, lo que, personalmente, no me gusta. Una expresión que da como resultado el valor numérico 0
es igual a falso en C en el núcleo Arduino, y es igual a verdadero para cualquier otro valor.
[ 86 ]
www.itebooks.info
Machine Translated by Google
Capítulo 3
Ser implícito suele significar hacer que el código sea más breve y atractivo.
En mi humilde opinión, también significa sentirse muy infeliz cuando, varios
meses después, hay que dar soporte y mantener un código que incluye un
montón de cosas implícitas sin ningún comentario.
Insto a mis alumnos a que sean explícitos y verbosos. No estamos aquí
para codificar cosas en una cantidad de memoria demasiado pequeña,
créanme. No estamos hablando de reducir un código de 3 megabytes a 500
kilobytes, sino más bien de reducir un código de 200 kilobytes a 198 kilobytes.
entero a;
entero b;
int estadoled;
si (a < b) {
estadoLed = 1; }
de lo contrario si (b > 0) {
estado del led = 0;
}
demás {
estadoLed = 1; }
La primera prueba if es: si a es menor que b. Si es verdadero, ponemos el valor 1 dentro de la variable
ledState. Si es falso, pasamos a la siguiente sentencia else.
Esto también contiene otra prueba sobre b: ¿ b es mayor que 0? Si lo es, ponemos el valor 0
Dentro de la variable ledState. Si es falso podemos ir al último caso, el último else, y ponemos el valor 1
dentro de la variable ledState.
Un buen consejo es tratar de poner todos los casos en papel y tratar de encontrar los agujeros, es decir,
donde la parte de los valores de las variables no coinciden con las pruebas.
[ 87 ]
www.itebooks.info
Machine Translated by Google
entero a;
entero b;
int estadoled;
si (a < b) { // a < b
estadoLed = 1; }
entero a;
entero b;
int estadoled;
si (a < b || (a >= b && b < 0) ) ledState = 1; } {
Podría considerarse como una versión más condensada donde tienes todas las instrucciones para
encender el LED en un solo lugar, lo mismo para apagarlo.
[ 88 ]
www.itebooks.info
Machine Translated by Google
Capítulo 3
• T < 15
• T > 30
• T<15
• T >15 y T < 30
• T > 30
¿Qué sucede cuando T = 30 o T = 15? Son agujeros en nuestra lógica. Dependiendo de cómo
hayamos diseñado nuestro código, podría suceder. Hacer coincidir todos los casos significaría: incluir
También se pueden utilizar los casos T = 15 y T = 30. Podemos hacerlo de la siguiente manera:
si (T < 15)
{ colorizeLed(azul); } de lo
Incluí estos dos casos en mis comparaciones. 15 grados Celsius están incluidos en el segundo intervalo
de temperatura y 30 grados Celsius en el último. Este es un ejemplo
de cómo podemos hacerlo.
Me gustaría que recordaras utilizar un bolígrafo y un papel en este tipo de casos. Esto te ayudará a diseñar
y, sobre todo, a hacer algunas pausas en el IDE, que es, en los pasos de diseño, realmente bueno.
Exploremos ahora una nueva estructura condicional.
switch…case…break estructura condicional Aquí, vamos a ver una nueva estructura condicional.
// declaraciones
romper;
[ 89 ]
www.itebooks.info
Machine Translated by Google
// las declaraciones
se rompen;
por defecto:
// declaraciones
}
Se compara var para comprobar su igualdad con cada etiqueta de caso. Si var es igual a un valor
de etiqueta en particular, las instrucciones de este caso se ejecutan hasta la siguiente interrupción.
Si no hay coincidencia y ha utilizado el valor opcional default: case, se ejecutan las instrucciones de este
caso. Sin el valor default: case, no se hace nada. La etiqueta debe ser un valor, no un carácter ni una
cadena. Tomemos un ejemplo más concreto:
LedApagado();
}
flotante midiCCMessage; si
(midiCCMessage == 7) changeVolume(); de lo contrario si
(midiCCMessage == 10) changePan(); de lo contrario LedOff();
¿Estás bien?
[ 90 ]
www.itebooks.info
Machine Translated by Google
Capítulo 3
Operador ternario
Esta extraña notación suele ser totalmente desconocida para mis alumnos. Yo solía decir: "¡Oye!
"Esto es más C que Arduino" cuando responden "Por eso nos hemos olvidado de ello". ¡Estudiantes
traviesos! Este operador ternario toma tres elementos como entrada.
La sintaxis es (expresión) ? val1 : val2.
Entero T;
Int ledColor; // 0 significa azul, 1 significa rojo
ledColor = (T < 20) ? 0 : 1;
Puede ser una notación útil, especialmente si no necesita la ejecución de declaraciones en cada
caso, sino solo asignaciones de variables.
• para
• mientras
• hacer…mientras
[ 91 ]
www.itebooks.info
Machine Translated by Google
Este ejemplo básico define un bucle que imprime todos los números enteros del 0 al 99. La
declaración/definición de la variable de tipo entero i es el primer elemento del for
estructura. Luego, la condición describe en qué caso deben ejecutarse las sentencias incluidas en este
bucle. Por último, se produce el incremento i++ .
Rompamos el bucle para los dos primeros y los dos últimos valores i y veamos qué sucede.
La declaración de la variable entera i para la primera y segunda iteración se muestra como
Sigue:
Por supuesto, el índice podría declararse antes de la estructura for y solo definirse dentro de la
estructura for . También podríamos haber declarado y definido la variable antes y tendríamos:
int i = 0;
para ; yo < 100 ; yo++) {
(println(i);
}
Esto parece un poco extraño, pero es totalmente legal en C y también para el núcleo Arduino.
[ 92 ]
www.itebooks.info
Machine Translated by Google
Capítulo 3
Normalmente funciona así para cualquier variable declarada dentro de las declaraciones de un for.
bucle. Esto no es algo que se pueda hacer, incluso si es totalmente legal en C. ¿Por qué no? Porque
significaría que declararías una variable cada vez que se ejecuta el bucle, lo que no es realmente
inteligente. Es mejor declararla fuera del bucle, una vez, y luego usarla dentro de él, sea cual sea el
propósito (índice o variable para trabajar con declaraciones internas).
[ 93 ]
www.itebooks.info
Machine Translated by Google
¿Cómo puedo mezclarlos? La respuesta es la misma que la respuesta a la pregunta: ¿qué es una tabla
de multiplicar? Tengo que mantener un índice constante y multiplicarlo por el otro, yendo del 1 al 10. Luego,
tengo que incrementar el primero y continuar haciendo lo mismo con el otro y así sucesivamente. Así es
como lo hacemos:
println(x*y);
}
}
Este código imprime todos los resultados de x*y, donde x e y son números enteros del 1 al 10, un
resultado en cada línea. Estos son los primeros pasos:
•
x = 1, y = 1… imprime el resultado
•
x = 1, y = 2… imprime el resultado
•
x = 1, y = 3… imprime el resultado
x se incrementa a 2 cada vez que finaliza el bucle for interno (el que contiene y), luego x se fija en 2
e y crece hasta x = 10 e y = 10 donde finaliza el bucle for .
Vamos a mejorarlo un poco, solo por cuestiones estéticas. También es un pretexto para retocar y
jugar con el código para que te sientas más cómodo con él. A menudo, las tablas de multiplicar se
dibujan de la siguiente manera:
[ 94 ]
www.itebooks.info
Machine Translated by Google
Capítulo 3
Necesitamos ir a la siguiente línea cada vez que uno de los índices (y solo uno) alcanza el límite, que es
el valor 10.
imprimir(x*y);
}
println(); // agrega un retorno de carro y una nueva línea
Revisa el código, cada vez que y llega a 10, se crea una nueva línea. El bucle for es una
estructura poderosa para repetir tareas. Revisemos otra estructura.
Mientras (expresión) {
// declaraciones
}
La expresión se evalúa como un valor booleano, verdadero o falso. Mientras la expresión sea
verdadera, se ejecutan las instrucciones; luego, tan pronto como sea falsa, el bucle finalizará.
Obviamente, a menudo, requiere una declaración y una definición fuera de la estructura while .
A continuación se muestra un ejemplo que obtiene los mismos resultados que nuestro primer bucle for, imprimiendo todos
los números enteros del 0 al 99:
int i = 0;
mientras (i < 100) {
imprimirln(i);
yo++;
}
De hecho, tienes que ocuparte del incremento o decremento explícitamente dentro de tus
declaraciones; diré algunas palabras sobre los bucles infinitos un poco más adelante. Podríamos
haber condensado el código un poco más haciendo eso:
int i = 0;
mientras (i < 100) {
println(i++); // imprime el valor actual de i, luego incrementa i
}
La estructura del bucle while prueba la expresión antes de ejecutar la primera instrucción. Veamos
una estructura similar que lo hace de forma diferente.
[ 95 ]
www.itebooks.info
Machine Translated by Google
hacer {
// declaraciones
} mientras (expresión);
int i = 0;
hacer {
imprimirln(i);
yo++;
} mientras (i < 100);
Esto significa que incluso si el primer resultado de la evaluación de la expresión es falso, las
instrucciones se ejecutarán a tiempo. Esto no sucede con la estructura while .
Imaginemos que tenemos un proceso ejecutándose 100 veces en condiciones normales , pero
queremos interrumpirlo o modificarlo en función de otra variable que tenga un alcance
mayor (declarada fuera del bucle, al menos).
Gracias a la sentencia break por hacer esto posible para nosotros. break; es la sintaxis
básica. Cuando se ejecuta break , sale del bucle actual, sea cual sea, según: do, for y
while. Ya viste break cuando hablamos sobre el switch
Estructura condicional. Vamos a ilustrarlo.
Imaginemos un LED. Queremos que su intensidad aumente de 0 a 100 por ciento y luego
vuelva a 0 cada vez. Pero también queremos utilizar un sensor de distancia que restablezca
este bucle cada vez que la distancia entre un usuario y el sensor sea mayor que un valor.
Se basa en una instalación real que hice para un museo, donde un sistema
tiene que hacer parpadear un LED suavemente cuando el usuario está lejos
y apagar el LED cuando el usuario está cerca, como un sistema vivo que
llama a los usuarios a su encuentro.
[ 96 ]
www.itebooks.info
Machine Translated by Google
Capítulo 3
Todo este bucle se incluyó dentro de la función global loop() en la placa Arduino y la prueba completa sobre la
distancia se ejecutó cada vez que se ejecutó el loop().
La función se ejecuta en espera de los usuarios.
Si me entiendes bien, loop() (la función básica del núcleo de Arduino) es un bucle infinito. Pero es un bucle
controlado, bien diseñado y basado en el núcleo de Arduino. Puede (y de hecho lo es) interrumpirse cuando se invocan
funciones u otros eventos especiales, lo que nos permite a nosotros, los usuarios, diseñar lo que necesitamos dentro
de este bucle. Yo solía llamarlo "el controlador y receptor de eventos" porque es el lugar donde se ejecuta nuestro
programa principal.
Existen muchas formas de crear procesos con bucles infinitos. Puedes definir una variable en setup(), hacer que crezca
en loop() y probarla cada vez que loop() se ejecute para restablecerla al valor inicial, por ejemplo. Esto aprovecha
el bucle loop() ya existente . Aquí tienes este ejemplo en C para Arduino:
yo entero;
configuración vacía(){
yo = 0;
}
bucle vacío(){
si (i < umbral) i +=1 ;
de lo contrario i = 0;
// algunas afirmaciones
}
[ 97 ]
www.itebooks.info
Machine Translated by Google
Este i crece desde 0 hasta el umbral – 1 , luego vuelve a 0, crece nuevamente, infinitamente,
aprovechando los beneficios del bucle().
También hay otras formas de ejecutar bucles infinitos de forma controlada que veremos un poco más
adelante en la parte más avanzada del libro, pero estás advertido: ten cuidado con esos bucles
infinitos.
Resumen
Aprendimos muchas cosas abstractas en este importante capítulo. Desde el tipo hasta las precedencias
de los operadores, pasando por la estructura condicional, ahora vamos a aprender nuevas estructuras
y sintaxis que nos ayudarán a crear bloques de código más eficientes y, sobre todo, más reutilizables.
Ahora podemos aprender sobre funciones. Vamos a sumergirnos en los próximos capítulos de
conocimientos de C/C++ y podremos probar nuestro Arduino después de eso.
[ 98 ]
www.itebooks.info
Machine Translated by Google
En este capítulo quiero darte elementos que te harán sentir más cómodo al escribir código fuente que
sea fácilmente legible, reutilizable y, en la medida de lo posible, bonito.
Al igual que el Yin y el Yang, para mí siempre ha habido una cualidad similar al zen en mi lado artístico y
de programación. Aquí es donde puedo ofrecer algunas perlas de sabiduría de programación para brindar
tranquilidad a su lado creativo.
Vamos a aprender algo que ya hemos utilizado un poco antes: las funciones. Contribuyen a mejorar la
legibilidad y la eficiencia al mismo tiempo. Mientras lo hacemos, abordaremos algunos conceptos
matemáticos y trigonométricos que se utilizan a menudo en muchos proyectos.
También hablaremos de algunos enfoques para la optimización del cálculo y finalizaremos este capítulo
con eventos o acciones relacionadas con el tiempo dentro del firmware de Arduino.
Introducción de funciones
Una función es un fragmento de código definido por un nombre y que puede reutilizarse/ejecutarse
desde muchos puntos diferentes en un programa C. El nombre de una función debe ser único.
en un programa C. También es global, lo que significa que, como ya leyó para las variables, se puede
usar en cualquier lugar del programa C que contenga la declaración de función.
definición en su alcance (ver la sección El concepto de alcance en el Capítulo 3,
Conceptos básicos de C: Cómo fortalecerse).
www.itebooks.info
Machine Translated by Google
Una función puede requerir que se le pasen elementos especiales; estos se llaman argumentos.
Una función también puede producir y devolver resultados.
Tomemos un ejemplo sencillo: queremos crear una función que sume dos números enteros y
produzca/devuelva el resultado. Hay dos argumentos que son variables de tipo entero. En este
caso, el resultado de la suma de estos dos valores int (enteros) también es un valor int . No tiene por
qué serlo, pero para este ejemplo lo es. El prototipo en
Ese caso sería:
returnType funciónNombre(argumentos)
returnType es un tipo variable. Supongo que a esta altura ya comprendes mejor el tipo void .
En el caso en que nuestra función no devuelva nada, debemos especificarlo eligiendo returnType
igual a void.
[ 100 ]
www.itebooks.info
Machine Translated by Google
Capítulo 4
functionName debe elegirse de manera que sea fácil de recordar y debe ser lo más autodescriptivo
posible. Imagine que respalda código escrito por otra persona. Encontrar myNiceAndCoolMathFunction requiere
investigación. Por otro lado, mySum se explica por sí solo. ¿Qué ejemplo de código preferiría respaldar?
El núcleo de Arduino (e incluso C) sigue una convención de nombres llamada camel case. La
diferencia entre dos palabras, debido a que no podemos usar el carácter en blanco/espacio en el
nombre de una función, se logra poniendo la primera letra de las palabras como caracteres en mayúscula.
No es necesario, pero se recomienda especialmente si quieres ahorrar tiempo más adelante. Es
más fácil de leer y hace que la función se explique por sí sola.
mysum es menos legible que mySum, ¿no? Los argumentos son una serie de declaraciones de
variables. En nuestro ejemplo de mySum , creamos dos argumentos de función. Pero también podríamos
tener una función sin argumentos. Imagina una función a la que necesitas llamar para producir una acción que
siempre sería la misma, sin depender de variables.
Lo harías así:
int miAccion()
{
// Entre llaves se encuentra el cuerpo
}
Las variables declaradas dentro de una función son conocidas únicamente por la
función que las contiene. Esto es lo que se conoce como "ámbito". No se puede acceder a
dichas variables declaradas dentro de una función desde ningún otro lugar, pero se
pueden "pasar". Las variables que se pueden pasar se conocen como argumentos.
Imagina el cuerpo como un bloque de código fuente real, puro y nuevo. Puedes declarar y
definir variables, añadir condiciones y jugar con bucles. Imagina el cuerpo (de instrucciones)
como el lugar donde se da forma y se moldea la arcilla del escultor y sale al final con el
efecto deseado; tal vez en una sola pieza o en muchas, tal vez en copias idénticas, etc. Es la
manipulación de lo que hay, pero recuerda: ¡basura que entra, basura que sale!
[ 101 ]
www.itebooks.info
Machine Translated by Google
También puedes, como acabamos de presentar, devolver el valor de una variable. Vamos a crear el cuerpo de
nuestro ejemplo mySum :
Por último, return result; es la instrucción que hace que la llamada a la función dé como resultado un valor.
Veamos un ejemplo real del código de Arduino para entenderlo mejor:
configuración vacía() {
Serial.begin(9600); Veamos un ejemplo real de código Arduino para entender esto mejor.
Bucle vacío() {
// sumemos todos los números enteros del 0 al 99, 2 por 2 y mostrémoslos
int resultadoActual; para (int
i = 0 ; i < 100 ; i++)
{
resultadoActual = miSuma(i,i+1); // suma y almacena
Serial.println(ResultadoActual); // mostrar en el monitor serial
}
delay(2000); hacer una pausa de 2 segundos
}
[ 102 ]
www.itebooks.info
Machine Translated by Google
Capítulo 4
En programación, es importante reconocer que todo lo que está a la derecha (contenido) va a la izquierda
(el nuevo contenedor). De acuerdo con las reglas de precedencia, una llamada a una función tiene una
precedencia de 2 contra 16 para el operador de asignación = . Esto significa que la llamada se realiza
primero y la función devuelve el resultado de la operación + , tal como la diseñamos.
Desde este punto de vista, acabas de aprender algo muy importante: la declaración de llamada de una función
que devuelve un resultado es un valor.
[ 103 ]
www.itebooks.info
Machine Translated by Google
El patrón de función/llamada también es más fácil de depurar. Solo tenemos una parte del código
donde se encuentra la función. Si hay un problema, podemos depurar la función en sí misma solo una
vez y todas las llamadas se solucionarán en lugar de modificar toda la parte de la función.
El código.
llamar llamar
función () {
Por el contrario, también puedes tener una función específica cuyo único propósito sea convertir dólares
estadounidenses a francos franceses. Es posible que no la llames muy a menudo, pero si es
necesario ocasionalmente, siempre está lista para realizar esa tarea.
En ambos casos, la función se puede utilizar y, por supuesto, reutilizar. La idea es ahorrar tiempo. También
significa que se pueden tomar algunas funciones ya existentes y reutilizarlas. Por supuesto, esto se debe
hacer siguiendo algunos principios, como:
• Licencia de código •
El tema de la licencia del código es un punto importante. Estamos acostumbrados a tomar, probar y
copiar/pegar cosas, pero el código que encuentras no siempre es de dominio público. Tienes que
ocuparte del archivo de licencia que a menudo se incluye en un archivo de publicación de código y
también en la primera línea del código, donde los comentarios pueden ayudarte a entender las
condiciones para respetar la reutilización del mismo.
[ 104 ]
www.itebooks.info
Machine Translated by Google
Capítulo 4
Interfaz de programación de aplicaciones (API) significa que debes cumplir con cierta documentación
antes de usar el material relacionado con esa API. Entiendo que los puristas considerarían esto un
pequeño abuso, pero es una definición bastante pragmática.
Básicamente, una API define especificaciones para rutinas, estructuras de datos y otras
entidades de código que pueden reutilizarse dentro de otros programas. Una especificación
de API puede ser la documentación de una biblioteca. En ese caso, definiría con precisión lo
que se puede y no se puede hacer.
El principio de buena coincidencia puede parecer obvio, pero a veces, por conveniencia, encontramos
una biblioteca existente y decidimos usarla en lugar de codificar nuestra propia solución.
Lamentablemente, a veces al final solo añadimos más complicaciones de las que pretendíamos
originalmente. Hacerlo nosotros mismos puede satisfacer una necesidad sencilla y, sin duda, evitará
las complejidades e idiosincrasias de una solución más integral. También se evita una posible
reducción del rendimiento; no se compra una limusina cuando lo único que se necesita es caminar
hasta el supermercado que está a la vuelta de la esquina.
Mejor legibilidad
Es una consecuencia de los otros beneficios, pero quiero que entiendas que esto es más vital que
comentar tu código. Una mejor legibilidad significa ahorrar tiempo para enfocarte en otra cosa.
También significa pasos más fáciles de actualización y mejora del código.
Como ya hemos visto, casi todas las entidades estándar de C y C++ admitidas por el compilador
avrg++ deberían funcionar con Arduino. Esto también es válido para las funciones
matemáticas de C.
Este grupo de funciones forma parte de la (famosa) biblioteca estándar de C. Muchas de las funciones de
este grupo se heredan en C++. Existen algunas diferencias entre C y C++ en el uso de números
complejos. C++ no proporciona el manejo de números complejos desde esa biblioteca, sino desde su
propia biblioteca estándar de C++ mediante la plantilla de clase std::complex.
Casi todas estas funciones están diseñadas para trabajar con números de punto flotante y
manipularlos. En C estándar, esta biblioteca se conoce como math.h (un nombre de archivo),
que mencionamos en el encabezado de un programa en C para poder usar sus funciones.
[ 105 ]
www.itebooks.info
Machine Translated by Google
yo
yo
=
a
a
Definición de radián
[ 106 ]
www.itebooks.info
Machine Translated by Google
Capítulo 4
El grado es el 1/360 de una rotación completa (círculo completo). Teniendo en cuenta estas dos
definiciones y el hecho de que una rotación completa equivale a 2π, podemos convertir una en la
otra:
h a
(hipotensa)
(opuesto)
A b do
(adyacente)
• cos(A) = b/h
• sen(A) = a/h
[ 107 ]
www.itebooks.info
Machine Translated by Google
El coseno y el seno evolucionan de 1 a 1 para valores de ángulos en radianes, mientras que la tangente
tiene algunos puntos especiales donde no está definida y luego evoluciona cíclicamente de ∞ a +∞.
Podemos representarlos en el mismo gráfico de la siguiente manera:
0,5
y = sin(x)
0
0 50 100 150 200 250 300 350
0,5
1
0,5
0 y = cos(x)
1
0 y = tan(x)
5
Sí, por supuesto, esas funciones oscilan, reproduciendo infinitamente las mismas evoluciones.
Es bueno tener en cuenta que se pueden utilizar para cálculos puros pero también para evitar una
evolución de valores demasiado lineal en el tiempo sustituyendo la linealidad por oscilaciones más
suaves. Lo veremos un poco más adelante.
[ 108 ]
www.itebooks.info
Machine Translated by Google
Capítulo 4
Sabemos cómo calcular un coseno/seno/tangente cuando tenemos un ángulo, pero ¿cómo calcular
un ángulo cuando ya tenemos el coseno/seno/tangente?
Éstas son las relaciones matemáticas correctas. En la práctica, en los casos habituales, podemos
descartar los casos de rotación completa y olvidarnos de los 2kπ de los casos de coseno y seno
y de kπ del caso de la tangente.
Funciones trigonométricas
Math.h contiene el prototipo de la función de trigonometría, al igual que el núcleo de Arduino:
• double asin (double x); devuelve A, el ángulo correspondiente a sin (A) = • double atan (double incógnita
[ 109 ]
www.itebooks.info
Machine Translated by Google
Por supuesto, hay que respetar las reglas matemáticas, especialmente si se tienen en cuenta
los rangos de valores. Por eso he añadido algunas condiciones de x a la lista.
Todas estas funciones son muy útiles, incluso para resolver pequeños problemas. Un día, estaba
dando clases a alguien en un taller y tuve que explicarle cómo medir la temperatura con un sensor.
Esta alumna estaba bastante motivada, pero no conocía estas funciones porque solo jugaba
con entradas y salidas sin convertir nada (porque básicamente no necesitaba eso). Luego
aprendimos estas funciones y terminó incluso optimizando su firmware, ¡lo que me hizo sentir muy
orgullosa de ella!
Generalmente, diseñamos una idea, codificamos un programa y luego lo optimizamos. Funciona bien para
programas grandes. Para los más pequeños, podemos optimizar mientras codificamos.
Podría añadir algo más ahora mismo: no arruines la legibilidad de tu código con demasiadas soluciones
de optimización crípticas; pensé en algunas sugerencias mientras escribía esto. Agregaré algunas
líneas sobre ellas para que te familiarices, al menos, con el concepto.
[ 110 ]
www.itebooks.info
Machine Translated by Google
Capítulo 4
• Realizar operaciones aritméticas, para potencias de 2, que involucran el operador de multiplicación y división.
Hay cuatro operadores y dos operadores de desplazamiento de bits. Antes de profundizar en el tema, aprendamos un poco más
sobre el sistema de numeración binario.
El sistema de numeración binario es el sistema que se utiliza en los ordenadores y en los dispositivos electrónicos digitales.
También se denomina sistema de base 2. En este sistema contamos de la siguiente manera:
Posiciones 0 1 2 3 4 5
1 0 1 0 1 1
[ 111 ]
www.itebooks.info
Machine Translated by Google
Luego, puedo escribir esta suma de multiplicaciones y es igual a la versión decimal de mi número 110101:
1 x 20 + 0 x 21 + 1 x 22 + 0 x 23 + 1 x 24 + 1 x 25 = 1 + 4 + 16 + 32 = 53
Y
El operador AND bit a bit se escribe con un solo ampersand: &. Este operador actúa en cada
posición de bit de forma independiente según las siguientes reglas:
• 0 y 0 == 0
• 0 y 1 == 0
• 1 y 0 == 0
• 1 y 1 == 1
Tomemos un ejemplo real con números enteros, que son un valor de 16 bits:
Para encontrar el resultado fácilmente, tenemos que comparar cada bit uno por uno para cada posición
siguiendo las reglas anteriores.
O
El operador OR bit a bit se escribe con una sola barra vertical: |. Se puede hacer presionando Alt
+ Shift + l (letra L) en OSX y Shift + \ en otros teclados de PC.
Este operador opera en cada posición de bit de forma independiente de acuerdo con las
siguientes reglas:
• 0 | 0 == 0
• 0 | 1 == 1
• 1 | 0 == 1
• 1 | 1 == 1
[ 112 ]
www.itebooks.info
Machine Translated by Google
Capítulo 4
GRATIS
El operador XOR bit a bit se escribe con un solo símbolo de intercalación: ^. Este operador
actúa sobre cada posición de bit de forma independiente según las siguientes reglas:
• 0 ^ 0 == 0
• 0 ^ 1 == 1
• 1 ^ 0 == 1
• 1 ^ 1 == 0
NO
El operador XOR bit a bit se escribe con el símbolo tilde: ~. Es un operador unario, lo que significa
que, si recuerdas este término correctamente, puede aplicarse a un solo número.
En mis talleres lo llamo el cambiador de bits . Cambia cada bit por su opuesto:
• ~0 == 1
• ~1 == 0
Tomemos un ejemplo real con números enteros, que son valores de 16 bits como ya sabes:
Como ya sabes, el tipo int en C es un tipo con signo (Capítulo 3, Conceptos básicos de C: Haciéndote más
fuerte) que puede codificar números del 32.768 al 32.767 (también números negativos).
Es muy fácil ver cómo funciona. Desplazas todos los bits desde un número determinado de
posiciones hacia la izquierda o hacia la derecha. Algunos de vosotros habréis notado que esto es
lo mismo que multiplicar o dividir por 2. Hacer << 1 significa multiplicar por 2, >> 1 significa dividir por
2. << 3 significa multiplicar por 8 (23), >> 5 significa dividir por 32 (25), y así sucesivamente.
[ 113 ]
www.itebooks.info
Machine Translated by Google
• El uso de una potencia de 2 como tamaño de matriz impulsa el uso de operadores de desplazamiento de bits
internamente/implícitamente mientras la CPU realiza cálculos de índice. Como acabamos de
aprender, la multiplicación/división por 2 se puede realizar de manera muy eficiente y rápida con el
desplazamiento de bits.
• Todas tus multiplicaciones y divisiones por una potencia de 2 deben reemplazarse por
Cambio de bits.
Este es el mejor compromiso entre un código críptico y un código eficiente. Yo solía hacerlo con bastante
frecuencia. Por supuesto, aprenderemos casos reales de su uso. Todavía estamos en la parte más teórica de
este libro, pero todo aquí se aclarará muy pronto.
En tal caso, el compilador produce lo que llamamos una tabla de saltos de etiquetas de casos, en
lugar de generar una enorme cascada ifelseif . La tabla de saltos basada en switch…
El rendimiento de la declaración de caso es independiente del número de entradas de caso en la
declaración de cambio .
Por lo tanto, coloque todas las cajas del interruptor en el rango más estrecho posible.
[ 114 ]
www.itebooks.info
Machine Translated by Google
Capítulo 4
Como se mencionó anteriormente, en los casos en que su declaración switch contiene casos ubicados
muy separados, debido a que no puede manejar eso de otra manera, el compilador reemplaza la
declaración switch y genera cascadas ifelseif . Esto significa que siempre será mejor reducir la
cantidad potencial de comparaciones; esto también significa que si los casos que son más probables se
ubican al principio, maximiza sus posibilidades de hacerlo.
Así, coloca todos los casos ordenados desde el que ocurre con mayor frecuencia hasta el que
ocurre con menor frecuencia.
En el ejemplo que cito, ahorramos memoria y procesamiento; en todos los casos donde
valueToTest no es igual a 1, la variable TemporaryVariable ni siquiera se crea.
[ 115 ]
www.itebooks.info
Machine Translated by Google
¿Qué podría mejorar para intentar evitar el uso de TemporaryVariable? Podría hacer un return directo de la
siguiente manera:
[ 116 ]
www.itebooks.info
Machine Translated by Google
Capítulo 4
En ese caso, ya no es necesario crear más variables temporales. Hay algunos casos en los que puede
resultar más legible escribir muchas variables temporales, pero ahora ya sabe que vale la pena encontrar
un equilibrio entre legibilidad y eficiencia.
Algunas funciones son especialmente costosas, considerando el trabajo de la CPU. Las funciones
trigonométricas son una de esas funciones que pueden tener malas consecuencias, ya que el espacio de
almacenamiento y la memoria son limitados en los sistemas integrados. Por lo general, se obtienen previamente en el código.
Veamos cómo podemos hacerlo.
[ 117 ]
www.itebooks.info
Machine Translated by Google
Inicialización de tabla
Tenemos que calcular previamente la tabla de consulta (LUT) del coseno. Necesitamos crear un sistema de
precisión pequeño. Al llamar a cos(x) podemos tener todos los valores de x que queramos. Pero si queremos
obtener previamente los valores dentro de una matriz, que por diseño tiene un tamaño finito, tenemos que
calcular una cantidad finita de valores. Entonces, no podemos tener nuestro resultado de cos(x) para todos
los valores de punto flotante sino solo para aquellos calculados.
Considero que la precisión es un ángulo de 0,5 grados. Esto significa, por ejemplo, que el resultado del
coseno de 45 grados será igual al coseno de 45 grados 4 minutos en nuestro sistema. Es justo.
configuración vacía()
{
initCosineLUT();
}
bucle vacío()
{
// ¡nada por ahora!
}
vacío initCosineLUT(){
para (int i = 0; i < periodo del coseno; i++)
{
cosLUT[i] = (flotante) cos(i * DEG2RAD * cosinePrecision);
}
}
cosLUT se declara como una matriz del tipo float con un tamaño especial. 360 * 1/
(precisión en grados) es simplemente la cantidad de elementos que necesitamos en nuestra
matriz considerando la precisión. Aquí, la precisión es 0,5 grados y, por supuesto, la declaración
se podría simplificar de la siguiente manera:
flotador cosLUT[720];
[ 118 ]
www.itebooks.info
Machine Translated by Google
Capítulo 4
También declaramos y definimos una constante DEG2RAD que es útil para convertir grados a radianes.
Declaramos cosinePrecision y cosinePeriod para realizar esos cálculos una vez.
Luego, definimos una función initCosineLUT() que realiza el precálculo dentro de la función setup() .
Dentro de su cuerpo, podemos ver un bucle sobre el índice i, desde i=0 hasta el tamaño de la matriz
menos uno. Este bucle precalcula los valores de coseno(x) para todos los valores de x desde 0 hasta 2π.
Escribí explícitamente la x como i * DEG2RAD * precisión para mantener la precisión visible.
Al inicializar la placa, calcula todos los valores de la tabla de búsqueda una vez y los proporciona para
cálculos posteriores mediante una simple operación de índice de matriz.
angle * 1 / cosinePrecision nos da el ángulo considerando la precisión dada de nuestra LUT. Aplicamos
una operación módulo considerando el valor cosinePeriod para envolver los valores de ángulos mayores
al límite de nuestra LUT y tenemos nuestro índice. Devolvemos directamente el valor de la matriz
correspondiente a nuestro índice.
También podríamos usar esta técnica para la precarga de raíz cuadrada. Así es como la usé en otro
lenguaje cuando codifiqué mi primera aplicación para iOS llamada colisiones digitales
(http://julienbayle.net/blog/2012/04/07/digitalcollisions11newfeatures). Si no lo probaste, se trata
de una aplicación sobre música y efectos visuales generativos basados en algoritmos de colisión
física. Necesité muchos cálculos de distancia y rotación. Créeme, esta técnica convirtió el primer
prototipo lento en una aplicación rápida.
[ 119 ]
www.itebooks.info
Machine Translated by Google
Las expansiones de series de Taylor son una forma de aproximar casi todas las expresiones
matemáticas en un punto particular (y alrededor de él) mediante el uso de expresiones polinomiales.
La idea detrás de una serie de Taylor es que podemos aproximar una expresión utilizando el primer
término de las sumas infinitas teóricas que representan esa expresión. Veamos algunos ejemplos.
Por ejemplo, considerando que x evoluciona desde π y π; podemos escribir la función seno de la
siguiente manera:
Podría añadir algunos otros ejemplos aquí, pero podrá encontrarlos en el Apéndice D, Algunas series
de Taylor útiles para la optimización de cálculos. Estas técnicas son algunos trucos poderosos para
ahorrar tiempo de CPU.
• Copiarlo y pasarlo
• Pasarle un puntero
En el primer caso, si la cantidad de datos es demasiado grande, nuestra pila de memoria explotaría
porque todos los datos se copiarían en la pila. No tendríamos otra opción que pasar el puntero.
En este caso tenemos la referencia del lugar donde se almacenan los datos en la memoria.
Podemos operar exactamente como queramos, pero solo mediante el uso de punteros. Los punteros son una
forma inteligente de manejar cualquier tipo de datos, especialmente matrices.
[ 120 ]
www.itebooks.info
Machine Translated by Google
Capítulo 4
También existe una biblioteca muy útil llamada SimpleTimer Library y diseñada como una biblioteca GNU
LGPL 2.1+ por Marcello Romani. Se trata de una buena biblioteca basada en la función principal
millis() , lo que significa que la resolución máxima es de 1 ms. Esto será más que suficiente para el 99 por
ciento de sus proyectos futuros. Marcello incluso hizo una versión especial de la biblioteca para este
libro, basada en micros().
La biblioteca principal de Arduino ahora también incluye una función nativa que puede tener una
resolución de 8 microsegundos, lo que significa que puede medir un delta de tiempo de
1/8.000.000 de segundo; bastante preciso, ¿no?
En el último capítulo del libro también describiré una biblioteca de mayor resolución , FlexiTimer2 , que
proporcionará un temporizador personalizable de alta resolución.
La función millis()
La función principal millis() devuelve la cantidad de milisegundos transcurridos desde que se inició la
placa por última vez. Para su información, 1 milisegundo equivale a 1/1000 de segundo.
La documentación del núcleo de Arduino también establece que este número volverá a cero después de
aproximadamente 50 días (esto se denomina desbordamiento del temporizador). Puedes sonreír ahora,
pero imagina tu última instalación que ilustra artísticamente el concepto de tiempo en el MoMA de Nueva
York que, después de 50 días, quedaría totalmente desordenada. Te interesaría saber esta información,
¿no? El formato de retorno de millis() es unsigned long.
[ 121 ]
www.itebooks.info
Machine Translated by Google
Aquí tienes un ejemplo que tendrás que subir a tu tablero en los próximos minutos.
También puedes encontrar este código en la carpeta Chapter04/ measuringUptime/ :
/*
measuringTime es un pequeño programa que mide el tiempo de actividad y lo imprime.
Escrito por Julien Bayle, este código de ejemplo está bajo licencia Creative Commons
Licencia CC BYSA
Este código está relacionado con el libro "Programación en C para Arduino" escrito
por Julien Bayle
y publicado por Packt Publishing.
http://cprogrammingforarduino.com
*/
configuración vacía(){
Serie.begin(9600);
}
bucle vacío(){
Serial.print("Hora: ");
tiempoMedido = milisegundos();
¿Puedes optimizar esto (sólo por razones pedagógicas ya que es un programa muy pequeño)?
Sí, de hecho, podemos evitar el uso de la variable measuredTime . Sería algo así:
/*
measuringTime es un pequeño programa que mide el tiempo de actividad y lo imprime.
Escrito por Julien Bayle, este código de ejemplo está bajo licencia Creative Commons
Licencia CC BYSA
[ 122 ]
www.itebooks.info
Machine Translated by Google
Capítulo 4
Este código está relacionado con el libro "Programación en C para Arduino" escrito
por Julien Bayle
y publicado por Packt Publishing.
http://cprogrammingforarduino.com
*/
configuración vacía(){
Serie.begin(9600);
}
bucle vacío(){
Serial.print("Hora: ");
Serial.println(millis()); // imprime el tiempo de actividad actual
retraso(250); // pausando el programa 250ms
}
También es hermoso en su simplicidad, ¿no? Estoy seguro de que estará de acuerdo. Así que cargue
este código en su placa, inicie el Monitor serial y mírelo.
La función micros()
Si necesita más precisión, puede utilizar la función micros() . Proporciona un tiempo de actividad
con una precisión de 8 microsegundos, como se escribió anteriormente, pero con un desbordamiento
de aproximadamente 70 minutos (significativamente menos de 50 días, ¿verdad?). Ganamos
precisión, pero perdemos el rango de tiempo de desbordamiento. También puede encontrar el
siguiente código en la carpeta Chapter04/measuringUptimeMicros/ :
/*
measuringTimeMicros es un pequeño programa que mide el tiempo de actividad en ms y
Escrito por Julien Bayle, este código de ejemplo está bajo licencia Creative Commons
Licencia CC BYSA
Este código está relacionado con el libro «Programación en C para Arduino» escrito
por Julien Bayle
y publicado por Packt Publishing.
http://cprogrammingforarduino.com
*/
configuración vacía(){
[ 123 ]
www.itebooks.info
Machine Translated by Google
Serie.begin(9600);
}
bucle vacío(){
Serial.print(«Tiempo en ms: «);
Serial.println(millis()); // imprime el tiempo de actividad actual en ms
Serial.print(«Tiempo en µs: «);
Serial.println(micros()); // imprime el tiempo de actividad actual en µs
Ambas funciones hacen que el programa haga una pausa. La única diferencia es que hay que indicar
un tiempo en milisegundos para delay() y un tiempo en microsegundos para delayMicroseconds().
[ 124 ]
www.itebooks.info
Machine Translated by Google
Capítulo 4
Aquí hay un pequeño diagrama que ilustra lo que sucede cuando encendemos nuestro Arduino:
Encender Apagado
tiempo
Ahora aquí hay un diagrama de la ejecución del firmware en sí, que es la parte con la que
trabajaremos en las siguientes filas:
El ciclo de vida del firmware con la parte principal en bucle y interrumpiéndose cuando se llama a delay()
[ 125 ]
www.itebooks.info
Machine Translated by Google
Podemos observar que todo se realiza de manera secuencial y en tiempo. Si la ejecución de una
instrucción toma mucho tiempo, el chip de Arduino la ejecuta y luego continúa con la siguiente
tarea.
En ese caso tan habitual y común, si una tarea en particular (declaraciones, llamadas de función
o lo que sea) toma mucho tiempo, todo el programa podría bloquearse y producir un problema;
considere la experiencia del usuario.
Imagina ese caso concreto en el que tienes que leer sensores, activar y desactivar
algunos interruptores y escribir información en una pantalla al mismo tiempo. Si lo
haces de forma secuencial y tienes muchos sensores, lo que es bastante habitual, puedes tener
algún retraso y ralentización en la visualización de la información porque esa tarea se ejecuta
después de la otra en loop().
Generalmente enseño a mis alumnos al menos dos conceptos al abordar esa propiedad de una
sola tarea que puede parecer una limitación:
• Hilo
[ 126 ]
www.itebooks.info
Machine Translated by Google
Capítulo 4
Si quisiera crear un código que lea entradas y realice algo cuando se verifique una
condición particular con el valor de estas entradas, escribiría este pseudocódigo:
configuración()
inicializar cosas
bucle()
solicitar un valor de entrada y esperar hasta que esté disponible
prueba esta entrada de acuerdo a algo más
Si la prueba es verdadera, realiza otra cosa y vuelve al principio.
¿Qué podría resultar molesto aquí? Sondeo cíclicamente nueva información y tengo que esperar a que
aparezca.
Durante este paso no se hace nada más, pero imaginemos que el valor de entrada permanece
igual durante mucho tiempo. Solicitaría este valor cíclicamente en el bucle, obligando a las
otras tareas a no esperar nada.
Parece una pérdida de tiempo. Normalmente, el sondeo es suficiente. Hay que escribirlo aquí en
lugar de lo que otros programadores podrían decirte.
Somos creadores, necesitamos que las cosas se comuniquen y funcionen, y podemos y nos
gusta probar, ¿no es así? Entonces, acabas de aprender algo importante aquí.
Un día, le pedí a unas personas que diseñaran un código básico. Por supuesto, como siempre,
estaban conectados a Internet y yo simplemente acepté porque hoy en día casi todos
trabajamos así, ¿no? Algunas personas terminaron antes que otras.
¿Por qué? Muchas de las personas que terminaron más tarde intentaron crear una buena
solución multiproceso utilizando un sistema de mensajería y una biblioteca externa. La intención
era buena, pero en el tiempo que teníamos, no terminaron y solo tenían una buena placa Arduino,
algunos componentes cableados y un código que no funcionaba sobre la mesa.
¿Quieres saber qué tenían los demás en su escritorio? ¡Una rutina basada en sondeos que
controlaba sus circuitos a la perfección! El tiempo perdido por este firmware basado en sondeos
era totalmente irrelevante teniendo en cuenta el circuito.
[ 127 ]
www.itebooks.info
Machine Translated by Google
Imaginemos el ejemplo que hemos dibujado anteriormente con muchas entradas y salidas. Tal vez se trate de un
sistema que tiene que reaccionar en función de una acción del usuario. Por lo general, podemos considerar que las
entradas del usuario son mucho más lentas que la capacidad del sistema para responder.
Esto significa que podríamos crear un sistema que interrumpiera la visualización tan pronto como ocurriera un
evento en particular, como una entrada del usuario. Este concepto se denomina sistema de interrupción
basado en eventos.
La interrupción es una señal. Cuando ocurre un evento en particular, se envía un mensaje de interrupción al
procesador. A veces, se envía externamente al procesador (interrupción de hardware) y, a veces, internamente
(interrupción de software).
Así es como el controlador de disco o cualquier periférico externo informa al procesador de la unidad principal
que tiene que proporcionar esto o aquello en el momento adecuado.
En el caso de nuestra instalación con una gran cantidad de entradas y salidas, podemos plantearnos manejar
las entradas de usuario con una interrupción. Tendríamos que implementar lo que se llama una Interrupt Service
Routine (ISR), que es una rutina que se llama únicamente cuando ocurre un evento del mundo físico, es decir,
cuando cambia el valor de un sensor o algo similar.
[ 128 ]
www.itebooks.info
Machine Translated by Google
Capítulo 4
Arduino ahora ofrece una forma agradable de conectar una interrupción a una función y ahora es fácil
diseñar un ISR (aunque aprenderemos a hacerlo un poco más adelante). Por ejemplo, ahora podemos
reaccionar al cambio del valor de un sensor térmico analógico utilizando ISR. En este caso, no
sondearemos permanentemente la entrada analógica, pero dejaremos que nuestra parte Arduino de bajo
nivel lo haga. Solo cuando un valor cambie (sube o baja) dependiendo de cómo hayamos conectado la
interrupción, esto actuará como un disparador y se ejecutará una función especial (por ejemplo, la
pantalla LCD se actualiza con el nuevo valor).
¿Qué es un hilo?
Un hilo es un flujo de programa en ejecución en el que el procesador ejecuta una serie de tareas,
generalmente en bucle, pero no necesariamente.
Con un solo procesador, normalmente se hace mediante multiplexación por división de tiempo, lo que
significa que el procesador cambia entre los diferentes subprocesos según el tiempo, es decir,
cambio de contexto.
Los procesadores más avanzados ofrecen la función de subprocesos múltiples . Se comportan como si
fueran más de uno, y cada parte se ocupa de una tarea al mismo tiempo.
Sin profundizar en los procesadores de computadoras, ya que no estamos tratando con ellos ahora,
puedo decir que los subprocesos son técnicas útiles para usar en programación para hacer que las
tareas se ejecuten simultáneamente.
[ 129 ]
www.itebooks.info
Machine Translated by Google
Lamentablemente, el núcleo de Arduino no ofrece multihilo, ni tampoco ningún otro microcontrolador. Como Arduino es un
proyecto de hardware de código abierto, algunos hackers han diseñado una variante de la placa Arduino y han creado una
variante de Freeduino que ofrece concurrencia, un lenguaje de programación de código abierto y un entorno diseñado
especialmente teniendo en cuenta el multihilo. Esto no tiene nada que ver aquí, pero al menos ahora tienes algunas pistas
si estás interesado.
Pasemos a la segunda solución para ir más allá de la restricción de una tarea a la vez.
Si lo necesitamos.
Esas acciones son generalmente llamadas de función. Las funciones que se comportan de esa manera se
conocen a veces como funciones de devolución de llamada. Estas funciones se llaman generalmente como
argumento de otro fragmento de código.
Imagínese que quiero que nuestro preciado LED en la placa Arduino parpadee cada 120 milisegundos. Podría usar un
retraso, pero detendría por completo el programa. No es lo suficientemente inteligente.
Podría hackear un temporizador de hardware en la placa, pero eso sería excesivo. Una solución más
práctica que yo usaría es una función de devolución de llamada con la biblioteca SimpleTimer de Marcello . El
sondeo proporciona una forma simple y económica (computacionalmente hablando) de manejar
aplicaciones que no dependen del temporizador, evitando al mismo tiempo el uso de interrupciones que plantean
problemas más complejos como el consumo excesivo del temporizador de hardware (secuestro), lo que conduce a otros
factores complicados.
Sin embargo, si desea llamar a una función cada 5 milisegundos y esa función necesita 9 milisegundos para completarse,
se llamará cada 9 milisegundos. En nuestro caso, con 120 milisegundos necesarios para producir un parpadeo
agradable y visible para la vista, estamos muy seguros.
Para tu información, no necesitas conectar nada más que el cable USB entre la placa y tu computadora. El LED
soldado a la placa en Arduino está conectado al pin digital 13. Vamos a usarlo.
Pero primero, descarguemos la biblioteca SimpleTimer para su primer uso de una biblioteca externa.
[ 130 ]
www.itebooks.info
Machine Translated by Google
Capítulo 4
Ahora, puedes ver por ti mismo lo que son. Dentro de estos archivos, tienes el código fuente. Abre tu carpeta
Sketchbook (ver Capítulo 1, Vamos a conectar cosas) y mueve la carpeta de la biblioteca a la carpeta de
bibliotecas si existe, de lo contrario crea esta carpeta especial:
[ 131 ]
www.itebooks.info
Machine Translated by Google
La próxima vez que inicie su IDE de Arduino, si va a Sketch | Importar biblioteca, verá una
nueva biblioteca en la parte inferior.
Para incluir una biblioteca, puedes hacer clic en ella en este menú y se escribirá
#include <libname.h> en tu código. También puedes escribirlo tú mismo.
configuración vacía() {
currentLEDState = falso;
pinMode(ledPin, SALIDA);
temporizador.setInterval(120, blink);
bucle vacío() {
temporizador.run() ;
}
[ 132 ]
www.itebooks.info
Machine Translated by Google
Capítulo 4
Esta biblioteca es fácil de usar en nuestro caso. Primero hay que incluirla, por supuesto. Luego hay que declarar
una instancia de SimpleTimer, que es una construcción de objeto, declarándola.
Luego, utilizo un valor booleano currentLEDState para almacenar explícitamente el estado actual del LED.
Por último, declaro/defino ledPin con el número de pin que necesito (en este caso, 13) para hacer que el LED
parpadee. setup() se realiza básicamente con algo de inicialización. La más importante aquí es la función
timer.setInterval() .
Tal vez esta sea tu primera llamada a un método. El objeto timer tiene e incorpora algunos métodos que podemos usar.
Uno de ellos es setInterval, que toma dos variables:
• Un intervalo de tiempo
Aquí estamos pasando un nombre de función (un fragmento de código) a otro fragmento de código.
Esta es la estructura de un sistema de devolución de llamada típico.
Luego, loop() se diseña llamando al método run() del objeto temporizador en cada ejecución.
Esto es necesario para poder usarlo. Al menos, la función de devolución de llamada blink() está definida con un
pequeño truco al final.
La comparación es obvia. Pruebo el estado actual del LED, si ya está encendido, lo apago, de lo contrario, lo enciendo.
Luego, invierto el estado, que es el truco. Estoy usando el operador ! (no) unario en esta variable booleana para
invertir su valor, y asigno el valor invertido al booleano en sí. Podría haber hecho esto también:
void parpadear() {
si (!estadoLEDactual) {
digitalWrite(ledPin, ALTO);
currentLEDState = verdadero;
}
demás {
digitalWrite(ledPin, BAJO);
currentLEDState = falso;
}
}
[ 133 ]
www.itebooks.info
Machine Translated by Google
Personalmente, considero que el cambio es una acción general que debe realizarse siempre,
independientemente del estado. Por eso propuse que lo coloques fuera de la estructura de prueba.
Resumen
Con esto finaliza la primera parte de este libro. Espero que hayas podido asimilar y disfrutar de
estos primeros (enormes) pasos. Si no es así, quizá quieras tomarte un tiempo para repasar algo que
no tengas claro; siempre vale la pena para entender mejor lo que estás haciendo.
Sabemos un poco más sobre programación en C y C++, al menos lo suficiente como para pasar
con seguridad las dos partes siguientes. Ahora podemos entender las tareas básicas de Arduino,
podemos cargar nuestro firmware y podemos probarlo con el cableado básico.
Ahora, daremos un paso más hacia un territorio donde las cosas son más prácticas y menos teóricas.
Prepárese para explorar nuevos mundos físicos, donde puede hacer que las cosas hablen y se
comuniquen entre sí, donde su computadora podrá responder a cómo se siente y reacciona, ¡y a veces
sin cables! Nuevamente, es posible que desee tomarse un poco de tiempo para revisar algo que aún no
entiende muy bien: el conocimiento es poder.
[ 134 ]
www.itebooks.info
Machine Translated by Google
• Arduino tiene salidas digitales que también se pueden utilizar para imitar salidas analógicas.
Aprenderemos sobre el concepto global de percepción del mundo. Vamos a conocer un nuevo
compañero llamado Processing porque es una buena manera de visualizar e ilustrar todo lo que vamos a
hacer de una manera más gráfica. También es un pretexto para mostrarles esta herramienta tan poderosa
y de código abierto. Luego, nos impulsará a diseñar el primer protocolo de comunicación serial entre
la placa y un software.
Jugaremos específicamente con interruptores, pero también cubriremos algunos patrones de diseño de
hardware útiles.
Sintiendo el mundo
En nuestro mundo hiperconectado, muchos sistemas ni siquiera tienen sensores. Nosotros, los humanos,
poseemos un montón de sensores biológicos directamente en nuestro cuerpo y sobre él. Somos capaces
de sentir la temperatura con nuestra piel, la luz con nuestros ojos, los componentes químicos con la nariz
y la boca, y el movimiento del aire con los oídos. Gracias a una característica de nuestro mundo, somos
capaces de sentir, integrar esta sensación y, finalmente, reaccionar.
www.itebooks.info
Machine Translated by Google
Si voy un poco más allá, puedo recordar una definición de los sentidos de mis primeros
cursos de fisiología en la universidad (recordarán, fui biólogo en una de mis vidas anteriores):
"Los sentidos son capacidades fisiológicas que proporcionan datos para la percepción"
Este modelo fisiológico básico es una buena manera de entender cómo podemos trabajar con una placa
Arduino para hacer que detecte el mundo.
• Una capacidad
• Algunos datos
• Una percepción
Un termómetro, por ejemplo, es un sensor capaz de medir la temperatura local y traducirla en una
señal. Los termómetros a base de alcohol o de mercurio tienen una escala escrita en ellos y la
contracción/dilatación de la materia química en función de la temperatura hace que sean fáciles
de leer.
Para que nuestro Arduino pueda detectar el mundo, la temperatura por ejemplo, tendríamos que
conectar un sensor.
• Temperatura
• Humedad
• Presión
[ 136 ]
www.itebooks.info
Machine Translated by Google
Capítulo 5
• Luz
• Distancia
• Capacitancia
• Movimiento
Esta lista no es exhaustiva. Para casi cada magnitud, podemos encontrar un sensor. De hecho,
para cada fenómeno físico o químico cuantificable, existe una manera de medirlo y seguirlo.
Cada uno de ellos proporciona datos relacionados con la magnitud medida.
En efecto, los termómetros convierten una cantidad (en este caso, un volumen) relacionada
con la temperatura en un valor legible en la escala del termómetro. De hecho, aquí tenemos una
doble conversión. El volumen es una función que depende de la temperatura.
La altura del líquido dentro del termómetro es una función que depende del volumen del líquido. Por
lo tanto, podemos entender que la altura y la temperatura están relacionadas. Esta es la doble conversión.
De todas formas, el termómetro es un módulo muy útil que integra toda esta magia matemática
y física para proporcionar un dato, un valor: la temperatura. Como se muestra en la siguiente
figura, se utiliza el volumen para proporcionar una temperatura:
100 100
80 80
60 60
40 40
20 20
0 0
20 20
[ 137 ]
www.itebooks.info
Machine Translated by Google
Todos los sensores funcionan así. Son módulos que miden fenómenos físicos y
proporcionan un valor. Más adelante veremos que esos valores pueden ser muy
diferentes y, eventualmente, también codificarse.
De hecho, tomemos un sensor térmico electrónico. En primer lugar, este debe recibir
alimentación eléctrica para funcionar. Luego, si podemos alimentarlo pero no podemos
medir físicamente el potencial eléctrico que genera desde sus pines, no podremos apreciar el
valor principal que intenta proporcionarnos: la temperatura.
[ 138 ]
www.itebooks.info
Machine Translated by Google
Capítulo 5
Digital
Cosa análoga
• Arduino proporciona pines digitales que pueden ser tanto de entrada como de salida.
Las entradas y salidas son pines proporcionados por la placa para comunicarse con periféricos
externos.
A menudo hablamos de leer pines para las entradas y escribir pines para las salidas. De hecho, desde el
punto de vista de la placa Arduino, estamos leyendo del mundo y escribiendo para el mundo, ¿no es así?
Una entrada digital es un pin digital configurado como una entrada y que proporciona la capacidad de
lectura de potencial eléctrico y conversión a 0 o 1 a la placa Arduino. Lo ilustraremos muy pronto
utilizando interruptores.
[ 139 ]
www.itebooks.info
Machine Translated by Google
Este importante proyecto de código abierto fue iniciado en 2001 por Ben Fry y Casey Reas, dos gurús y
antiguos alumnos de John Maeda en el Grupo de Estética y Computación del MIT Media Lab.
Probablemente también encontrarás el término Processing escrito como Proce55ing ya que el nombre
de dominio processing.org ya estaba tomado en el momento de su creación.
La programación con Processing normalmente se realiza utilizando el IDE nativo que viene con la descarga
como veremos en esta sección.
Processing utiliza el lenguaje Java, pero ofrece una sintaxis y una programación gráfica simplificadas.
También simplifica todos los pasos de compilación en una acción de un solo clic, como en Arduino IDE.
Al igual que Arduino Core, ofrece un gran conjunto de funciones listas para usar. Puede encontrar todas
las referencias en http://processing.org/reference.
Ahora hay más de una forma de utilizar Processing. De hecho, debido a que los entornos de
ejecución de JavaScript integrados en los navegadores web se volvieron cada vez más potentes, podemos
utilizar un proyecto derivado de JavaScript. Sigues codificando con Java, incluyes este código en tu
página web y, como dice el sitio web oficial, "Processing.js hace el resto. No es magia, pero casi". El sitio
web es http://processingjs.org.
También hay algo muy interesante: puedes empaquetar aplicaciones codificadas con Processing
para el sistema operativo móvil Android. Si te interesa, puedes leerlo en http://processing.org/learning/
android.
[ 140 ]
www.itebooks.info
Machine Translated by Google
Capítulo 5
Evitaré extenderme en el tema de JS y las aplicaciones de Android, pero consideré que era lo suficientemente
importante mencionar estos usos.
Primero, descargue el paquete correspondiente a su sistema operativo. Consulte el sitio web para conocer el
proceso de instalación para su sistema operativo específico.
Icono de procesamiento
[ 141 ]
www.itebooks.info
Machine Translated by Google
Esto es totalmente normal porque el IDE de Arduino es una bifurcación del IDE de Processing. Ahora,
vamos a comprobar que también nos sentiremos cómodos con el IDE de Processing.
[ 142 ]
www.itebooks.info
Machine Translated by Google
Capítulo 5
2. A continuación, haz clic en el primer icono (la flecha con el símbolo de reproducción). Deberías ver la
siguiente captura de pantalla:
[ 143 ]
www.itebooks.info
Machine Translated by Google
3. Ahora haz clic en el cuadrado pequeño (símbolo de parada). Sí, este nuevo patio de juegos es
muy familiar
• Ejecutar (flecha pequeña): se utiliza para compilar y ejecutar el programa • Detener (cuadrado
pequeño): se utiliza para detener el programa cuando se está ejecutando • Nuevo proyecto (página
pequeña): se utiliza para abrir un lienzo en blanco • Abrir proyecto (flecha superior): se utiliza
[ 144 ]
www.itebooks.info
Machine Translated by Google
Capítulo 5
Por supuesto, no hay botón de carga. No es necesario cargar nada aquí; estamos en la computadora y
solo queremos codificar aplicaciones, compilarlas y ejecutarlas.
Puedes tener algunas pestañas si usas más de un archivo en tu proyecto (especialmente si usas
algunas clases Java separadas).
En esta zona de pestañas, tienes el área de texto donde escribes tu código. El código está
coloreado como en el IDE de Arduino, y esto es muy útil.
Por último, en la parte inferior, tienes el área de la consola de registro donde se pueden mostrar todos los
mensajes, desde errores hasta nuestros propios mensajes de seguimiento.
El control de versiones es un concepto muy interesante que ofrece una forma sencilla de realizar un
seguimiento de las versiones de su código. Por ejemplo, puede codificar algo, probarlo, hacer una copia de
seguridad en su sistema de control de versiones y luego continuar con el diseño de su código. Si lo ejecuta y
tiene un fallo agradable y gracioso en algún momento, puede comprobar fácilmente las diferencias entre
su código funcional y el nuevo que no funciona y hacer que la resolución de problemas sea mucho más sencilla.
No describiré los sistemas de control de versiones en detalle, pero quiero presentarles los dos sistemas
principales que se utilizan ampliamente en todo el mundo:
• SVN: http://subversion.apache.org
• Git: http://gitscm.com
Comprobando un ejemplo
A continuación se muestra un pequeño fragmento de código que muestra algunos patrones de diseño económicos
y sencillos. También puede encontrar este código en la carpeta Chapter05/processingMultipleEasing/ en el
paquete de código:
[ 145 ]
www.itebooks.info
Machine Translated by Google
// bucle for que inicializa las facilitaciones y los radios para todas las partículas
para (int i=0 ; i < partículasNumber ; i++)
{
easings[i] = 0.04 * i / particleNumber; // rellenando el easing
formación
radios[i] = 30 * i / partículasNumber ; // llenando los radios
formación
}
}
posicionesX[i] += dx * facilitaciones[i];
}
posicionesY[i] += dy * facilitaciones[i];
}
[ 146 ]
www.itebooks.info
Machine Translated by Google
Capítulo 5
// dibuja la partícula i
elipse(posicionesX[i], posicionesY[i], radios[i], radios[i]);
}
}
Puedes ejecutar este fragmento de código. Luego, puedes mover el mouse sobre el lienzo y
disfrutar de lo que sucede.
Código de processingMultipleEasing ejecutándose y mostrando una extraña serie de partículas que siguen al mouse
Primero, revisa el código. Básicamente, esto es Java. Supongo que no te sorprenderá demasiado,
¿verdad? De hecho, Java deriva de C.
[ 147 ]
www.itebooks.info
Machine Translated by Google
• Declaraciones/definiciones de variables
Ok. Puedes ver que las funciones setup() en el núcleo de Arduino y Processing tienen roles similares,
y loop() y draw() también.
Este fragmento de código muestra algunos patrones de diseño habituales con Processing. Primero inicio
una variable que almacena la cantidad global de partículas y luego inicio algunas matrices para cada
partícula que quiero crear. ¡Tenga en cuenta que todas estas matrices están vacías en este paso!
Este patrón es habitual porque ofrece una buena legibilidad y funciona bien también. Podría haber
utilizado clases o incluso matrices multidimensionales, pero en este último caso, ni siquiera tendría
beneficios excepto un código más corto (pero menos legible). En todas esas matrices, el valor Nésimo
indexado representa la partícula N. Para almacenar/recuperar los parámetros de la partícula N,
tengo que manipular el valor Nésimo de cada matriz. Los parámetros están repartidos dentro de
cada matriz, pero son fáciles de almacenar y recuperar, ¿no es así?
En setup(), defino y creo una instancia del lienzo y su tamaño de 600 x 600. Luego, defino que no
habrá trazos en ninguno de mis dibujos. El trazo de un círculo, por ejemplo, es su borde.
Luego, lleno las matrices de suavizado y radios usando una estructura de bucle for . Este es un patrón
muy habitual en el que podemos usar setup() para inicializar un montón de parámetros al principio.
Luego podemos verificar el bucle draw() . Estoy definiendo un color para el fondo. Esta función
también borra el lienzo y lo rellena con el color del argumento. Revisa la función de fondo en la
página de referencia para entender cómo podemos usarla. Este borrado/relleno es una buena manera de
borrar cada cuadro y restablecer el lienzo.
Después de este borrado/relleno, estoy almacenando la posición actual del mouse para cada coordenada
en las variables locales targetX y targetY.
El núcleo del programa se encuentra en el bucle for . Este bucle recorre cada partícula y crea algo para
cada una de ellas. El código se explica por sí solo. Puedo agregar aquí que estoy verificando la distancia
entre el mouse y cada partícula para cada cuadro (cada ejecución de draw()), y dibujo cada partícula
moviéndolas un poco, de acuerdo con su facilidad.
Este es un ejemplo muy simple pero bueno que utilicé para mostrar para ilustrar el poder de Processing.
[ 148 ]
www.itebooks.info
Machine Translated by Google
Capítulo 5
Procesamiento y Arduino
Processing y Arduino son muy buenos amigos.
En primer lugar, ambos son de código abierto, una característica muy amigable que trae consigo muchas
ventajas como el intercambio de código fuente y comunidades gigantescas, entre otras. Están disponibles
para todos los sistemas operativos: Windows, OS X y Linux. También podemos descargarlos gratis y
ejecutarlos en un par de clics.
Comencé a programar principalmente con Processing y lo utilizo mucho para algunos de mis propios
proyectos de visualización de datos y también para arte. Luego, podemos ilustrar flujos de datos
complejos y abstractos mediante formas suaves y primitivas en una pantalla.
Lo que vamos a hacer ahora juntos es mostrar la actividad de Arduino en el lienzo de Processing. De
hecho, este es un uso común de Processing como software amigable para la vista.
para Arduino.
Vamos a diseñar un protocolo de comunicación muy trivial y barato entre el hardware y el software. Esto
te mostrará el camino que seguiremos en los próximos capítulos de este libro. De hecho, si quieres que
tu Arduino se comunique con otro framework de software (estoy pensando en Max 6, openFrameworks,
Cinder y muchos otros), tendrás que seguir los mismos pasos de diseño.
[ 149 ]
www.itebooks.info
Machine Translated by Google
Suelo decir que Arduino puede funcionar como un órgano de software muy inteligente. Si
quieres conectar algún software con el mundo físico real, Arduino es la solución. De hecho, de esa
manera, el software puede percibir el mundo y proporcionarle a tu computadora nuevas funciones.
Continuemos mostrando algunos eventos del mundo físico en la computadora.
Presionando el botón
Nos vamos a divertir. Sí, este es el momento más especial en el que vamos a unir el mundo físico con
el mundo virtual. Arduino es el protagonista de todo esto.
Para actuar sobre el circuito, el interruptor se puede empujar y soltar cada vez que se quiera actuar
y al soltarlo la acción continúa.
Por lo general, todos los interruptores que tenemos en casa son de palanca, excepto el de la batidora,
que hay que pulsar para cortar y soltar para pararla, lo que significa que es momentáneo.
Un circuito básico
Aquí hay un circuito básico con un Arduino, un interruptor momentáneo y una resistencia.
[ 150 ]
www.itebooks.info
Machine Translated by Google
Capítulo 5
Arduino1
3V3 5V Venir
Fuerza
D13
ARÉF D11
Arduino
Modulación por ancho de pulso (PWM)
Yo ref. D10
Modulación por ancho de pulso (PWM)
D8
D7
Modulación por ancho de pulso (PWM)
D6
Entrada/
salida
digital
Modulación por ancho de pulso (PWM)
D5
Entrada analógica
A0 D4
Modulación por ancho de pulso (PWM)
A1 D3
A2 D2
Tejas
A3 D1
Recepción
A4 D0
A5 LCC
10k
Adventista del Séptimo Día
rands
Tierra
Un pequeño circuito
Cables
Cada línea representa un enlace entre dos componentes. Por definición, una línea es un cable y
no hay potencial eléctrico de un lado al otro. También se puede definir de la siguiente manera: un
cable tiene una resistencia de 0 ohmios. Entonces podemos decir que dos puntos unidos por un
cable tienen el mismo potencial eléctrico.
mostrarles el siguiente diagrama directamente. Ahora tenemos que construir el circuito real,
así que tomen algunos cables, su placa de pruebas y el interruptor momentáneo y
conecten todo el circuito como se muestra en el siguiente diagrama.
[ 151 ]
www.itebooks.info
Machine Translated by Google
Puedes utilizar una resistencia de unos 10 Kohms. Explicaremos el propósito de la resistencia en las siguientes
páginas.
Recordemos el cableado de la placa de pruebas; estoy usando rieles fríos y calientes en la parte superior de la
placa de pruebas (el frío es azul y significa tierra, el caliente es rojo y significa +5 V). Después de haber cableado
la tierra y los +5 V del Arduino a los rieles, estoy usando rieles para cablear las otras partes de la placa; es más
fácil y requiere cables más cortos.
Hay una resistencia entre la tierra y el pin digital 2. También hay un interruptor momentáneo entre la línea de
+5 V y el pin 2. El pin 2 se configurará como entrada, lo que significa que podrá absorber corriente.
[ 152 ]
www.itebooks.info
Machine Translated by Google
Capítulo 5
Por lo general, los interruptores se activan al presionarlos. Al presionarlos, se cierra el circuito y se permite el flujo de corriente.
Por lo tanto, en ese caso, si no presiono el interruptor, no hay corriente desde +5 V hasta el pin 2.
Mientras se mantiene presionado, el circuito se cierra. Luego, la corriente fluye desde el +5 V al pin 2. Es un poco metafórico
y abusivo, y debería decir que hemos creado un potencial eléctrico entre el +5 V y el pin 2, pero necesito ser más breve para
llegar al punto.
Un pin digital configurado como entrada proporciona la capacidad de absorber corriente. Esto significa que se comporta
como la tierra. De hecho, internamente, funciona exactamente como si el pin en cuestión estuviera conectado a tierra.
Con un firmware correctamente codificado, tendríamos la capacidad de verificar el pin 2. Esto significa que podríamos
probarlo y leer el valor del potencial eléctrico. Debido a que es una entrada digital, un potencial eléctrico cercano a +5 V
se traduciría como el valor ALTO, y si está cerca de 0 V, se traducirá como el valor BAJO. Ambos valores son constantes
definidas dentro del núcleo de Arduino. Pero si todo parece totalmente perfecto en un mundo digital perfecto, no es cierto.
De hecho, el ruido de la señal de entrada podría potencialmente leerse como una pulsación de botón.
Para mayor seguridad, utilizamos lo que llamamos resistencia pulldown. Esta suele ser una resistencia
de alta impedancia que proporciona un sumidero de corriente al pin digital considerado, lo que la
hace más segura en el valor 0 V si no se presiona el interruptor. Pulldown para que se reconozca de
manera más consistente como un valor BAJO, pullup para que se reconozca de manera más consistente
como el valor ALTO.
Por supuesto, el consumo energético global aumenta un poco. En nuestro caso, esto no es importante, pero hay que
saberlo. Siguiendo este mismo concepto, se puede utilizar una resistencia pullup para conectar los +5 V a la salida digital.
En general, hay que saber que la E/S de un chipset no debería estar en estado flotante.
[ 153 ]
www.itebooks.info
Machine Translated by Google
Diseñemos un firmware
Queremos presionar un interruptor y, en particular, esta acción tiene que encender el LED.
Primero vamos a escribir un pseudocódigo.
El pseudocódigo
Aquí hay un posible pseudocódigo. A continuación se muestran los pasos que queremos que tenga nuestro firmware.
Para seguir:
El código
Aquí hay una traducción de este pseudocódigo en código C válido:
configuración vacía() {
pinMode(ledPin, OUTPUT); // el pin led está configurado como salida
pinMode(switchPin, INPUT); // el pin del interruptor está configurado como entrada
}
bucle vacío(){
[ 154 ]
www.itebooks.info
Machine Translated by Google
Capítulo 5
}
demás {
digitalWrite(ledPin, LOW); // apaga el LED si está presionado actualmente
}
}
Sube el archivo y mira qué pasa. Deberías tener un sistema genial en el que puedas pulsar un interruptor
y encender un LED. ¡Espléndido!
Ahora vamos a hacer que la placa Arduino y Processing se comuniquen entre sí.
Podríamos diseñar un protocolo como biblioteca de comunicación. Por el momento, solo diseñamos un
protocolo utilizando el núcleo nativo de Arduino. Luego, más adelante en este libro, diseñaremos una
biblioteca.
El protocolo de comunicación
Un protocolo de comunicación es un sistema de reglas y formatos diseñados para intercambiar mensajes
entre dos entidades. Esas entidades pueden ser seres humanos, computadoras y quizás más.
[ 155 ]
www.itebooks.info
Machine Translated by Google
De hecho, utilizaría una analogía básica con nuestro idioma. Para entendernos, tenemos que seguir algunas
reglas:
Podría citar muchas otras reglas, como la velocidad de la conversación, la distancia entre dos entidades,
etc. Si se acuerdan y se verifican todas las reglas, podemos hablar juntos.
Antes de diseñar un protocolo, tenemos que definir nuestros requisitos.
• El protocolo debe ser ampliable sin tener que reescribir todo cada vez.
Es hora de agregar nuevos tipos de mensajes.
• El protocolo debe ser fácil de entender y estar bien comentado, especialmente para proyectos de código
abierto y colaborativos.
Diseño de protocolo
Cada mensaje tendrá un tamaño de 2 bytes. Este es un tamaño de paquete de datos común y propongo organizar
los datos de esta manera:
El hecho de que haya definido el byte 1 como representación del número de conmutador se debe, por lo
general, al requisito de capacidad de expansión. Con un conmutador, el número será 0.
[ 156 ]
www.itebooks.info
Machine Translated by Google
Capítulo 5
El código de procesamiento
Processing viene con un conjunto de bibliotecas muy útil ya integradas en su núcleo.
En concreto, vamos a utilizar la biblioteca serial.
Dibujar un pseudocódigo
¿Qué queremos que haga el programa?
Propongo tener un círculo grande. Su color representará el estado del interruptor. El color oscuro significará
que está liberado y el verde significará que está presionado.
2. Si los datos indican que el estado está desactivado, cambie el dibujo actual de color
a oscuro.
Dado que el IDE de Processing funciona como el IDE de Arduino y necesita crear todos los archivos de proyecto
guardados en una carpeta, te sugiero que guardes directamente el lienzo, incluso vacío, en el lugar correcto de
tu disco. Llámalo processingOneButtonDisplay.
[ 157 ]
www.itebooks.info
Machine Translated by Google
Para incluir la biblioteca serial desde el núcleo de Processing, puedes ir a Sketch | Import
Library… | serial. Agrega esta fila a tu código: processing.serial.*;
procesamiento de importación.serial.*;
[ 158 ]
www.itebooks.info
Machine Translated by Google
Capítulo 5
configuración vacía(){
void dibujar(){
[ 159 ]
www.itebooks.info
Machine Translated by Google
// Restablecer bytesCount:
bytesCount = 0;
}
}
}
Definiciones de variables
theSerialPort es un objeto de la biblioteca Serial . Primero tengo que crearlo.
serialBytesArray es una matriz de dos números enteros que se utiliza para almacenar
mensajes que llegan desde Arduino. ¿Te acuerdas? Cuando diseñamos el protocolo,
hablamos de mensajes de 2 bytes.
switchState y switchID son variables globales pero temporales que se utilizan para almacenar
el estado del conmutador y el ID del conmutador correspondiente al mensaje que proviene de la placa.
El ID del conmutador se ha colocado allí para una implementación futura (cercana) para distinguir los
diferentes conmutadores en caso de que usemos más de uno.
[ 160 ]
www.itebooks.info
Machine Translated by Google
Capítulo 5
bytesCount es una variable útil que rastrea la posición actual en nuestra lectura de mensajes.
init se define como falso al principio y se convierte en verdadero cuando se recibe por primera vez el
primer byte de Arduino (y uno especial, Z). Es una especie de propósito de primer contacto.
Luego, mantenemos un rastro del color de relleno y el inicial es 40. 40 es solo un entero
y se usará un poco más adelante como argumento de la función fill().
configuración()
Imprimimos una lista de todos los puertos serie disponibles en su computadora. Esta es
información de depuración para la siguiente instrucción donde almacenamos el nombre del primer
puerto serie en una cadena. De hecho, podría verse obligado a cambiar el elemento de la matriz
de 0 al correcto según la posición del puerto de su Arduino en la lista impresa.
Esta cadena se utiliza luego en la declaración muy importante que instancia la comunicación en
serie a 9600 baudios.
dibujar()
La función de dibujo es muy ligera aquí.
Pasamos la variable fillColor a la función fill() , configurando el color con el que se rellenarán todas
las formas siguientes.
Luego, dibujamos el círculo con la función elipse. Esta función toma cuatro argumentos:
[ 161 ]
www.itebooks.info
Machine Translated by Google
Tenga en cuenta que una elipse con los mismos valores de ancho y alto es un círculo (!). Vale. Pero, ¿dónde está
la magia aquí? Solo dibujará un círculo, siempre el mismo (tamaño y posición). fillColor es la única variable de la
función draw() . Veamos esa extraña función de devolución de llamada llamada serialEvent().
Aquí tenemos un método de devolución de llamada puro en Processing. Se trata de una devolución de
llamada basada en eventos. Resulta útil y eficiente no tener que sondear cada vez que nuestro puerto serial quiere
saber si hay algo para leer. De hecho, los eventos relacionados con las interfaces de usuario son totalmente
menos numerosos que el número de ciclos del procesador de la placa Arduino. Es más inteligente implementar
una devolución de llamada en ese caso; tan pronto como se produce un evento serial (es decir, se
recibe un mensaje), ejecutamos una serie de instrucciones.
myPort.read() leerá primero los bytes recibidos. Luego, haremos la prueba con la variable init . De hecho,
si este es el primer mensaje, queremos comprobar si la comunicación ya ha comenzado.
En el caso en que se trate del primer saludo (init == false), si el mensaje que llega desde la placa Arduino es Z,
el programa Processing limpia su propio puerto serial, almacena el hecho de que la comunicación acaba de
comenzar y reenvía Z a la placa Arduino. No es tan complicado.
Imagina que podemos empezar a hablar sólo si empezamos por decirnos "hola". No nos miramos (no hay
evento). Entonces empiezo a hablar. Tú giras la cabeza hacia mí (ocurre el evento serial) y escuchas. ¿Te estoy
diciendo "hola"? (¿Si el mensaje es Z?). Si no es así, simplemente giras la cabeza hacia atrás (no hay declaración
else ). Si es así, respondes "hola" (envías Z de vuelta) y comienza la comunicación.
Tan pronto como el número de bytes sea igual a 2, tendremos un mensaje completo y podremos "dividirlo"
en las variables switchID y switchState. Así es como lo hacemos:
[ 162 ]
www.itebooks.info
Machine Translated by Google
Capítulo 5
La siguiente declaración es de depuración: imprimimos cada variable. Luego, el núcleo del método
es la prueba de la variable switchState . Si es 0, significa que se libera el interruptor y modificamos
fillColor a 40 (color oscuro, 40 significa el valor 40 para cada componente RGB; consulte el método color()
en la referencia de Processing en http://
processing.org/reference/color_.html). Si no es 0, modificamos el color de relleno.
hasta 255, lo que significa blanco. Podríamos ser un poco más seguros si no solo usáramos else, sino
también else if (switchState ==1) .
¿Por qué? Porque si no estamos seguros de todos los mensajes que se pueden enviar (falta de
documentación o cualquier otra cosa que nos genere dudas), podemos modificar el color a blanco
solo si switchState es igual a 1. Este concepto también se puede aplicar en el estado de optimización,
pero aquí es bastante claro, por lo que podemos dejarlo así.
Vale, es una pieza bonita y pesada, ¿verdad? Ahora, veamos cómo tenemos que modificar el
código de Arduino. ¿Te acuerdas? Todavía no está preparado para la comunicación.
configuración vacía() {
pinMode(switchPin, INPUT); // el pin del interruptor está configurado como entrada
}
bucle vacío(){
switchState = digitalRead(pin del interruptor);
}
¿Qué tenemos que añadir? Todo lo de Serial . También quiero añadir una pequeña función dedicada
al primer "hola".
int enByte = 0;
configuración vacía() {
[ 163 ]
www.itebooks.info
Machine Translated by Google
Serial.begin(9600);
pinMode(switchPin, INPUT); // el pin del interruptor está configurado como entrada sayHello();
bucle vacío(){
// si se recibe un byte válido del procesamiento, lee la entrada digital. if (Serial.available() > 0) { // obtener el
byte entrante: inByte = Serial.read(); switchState
= digitalRead(switchPin);
void decirhola() {
mientras (Serial.available() <= 0) { Serial.print('Z'); //
envía una Z mayúscula a Arduino para decir
"¡HOLA!"
retraso(200);
}
}
Primero defino una nueva variable: inByte. Esta almacena los bytes leídos. Luego,
dentro del método setup() , creo una instancia de comunicación serial como ya
aprendimos a hacer con Arduino. Configuro el método pinMode del pin del interruptor
y luego llamo a sayHello().
[ 164 ]
www.itebooks.info
Machine Translated by Google
Capítulo 5
Estoy llamando a esta función en setup(). Esta es una llamada simple , no una devolución de
llamada ni nada por el estilo. Esta función contiene un bucle while mientras Serial.available()
sea menor o igual a cero. ¿Qué significa esto? Significa que esta función pausa setup()
mientras el primer byte llega al puerto serial de la placa Arduino. El loop() done no se
ejecuta mientras el setup() done ha terminado, por lo que este es un buen truco para esperar el
primer evento externo; en este caso, la primera comunicación. De hecho, la placa está enviando
el mensaje Z (es decir, el "hola") mientras Processing no responde.
[ 165 ]
www.itebooks.info
Machine Translated by Google
El circuito
A continuación se muestra el diagrama del circuito necesario para trabajar con múltiples interruptores:
Aquí hay una pequeña actualización de memoria: ¿Por qué no utilicé los pines digitales 0 o 1?
[ 166 ]
www.itebooks.info
Machine Translated by Google
Capítulo 5
Como estoy usando la comunicación serial desde Arduino, no podemos usar los pines digitales 0
y 1 (cada uno corresponde respectivamente a RX y TX utilizados en la comunicación serial). Incluso
si estamos usando el enlace USB como soporte físico para nuestros mensajes seriales, la placa Arduino
está diseñada así y debemos tener mucho cuidado con ella.
Aquí está la vista del circuito con la placa de pruebas. No alineé todos los cables voluntariamente.
¿Por qué? ¿No recuerdas que quiero que seas totalmente autónomo después de leer este libro y sí,
encontrarás muchos esquemas en el mundo real hechos a veces de esa manera? También tienes
que familiarizarte con ellos. Podría ser una tarea (fácil).
El circuito anterior muestra los tres interruptores, las tres resistencias pulldown y la placa Arduino.
Ambos códigos fuente deben modificarse para proporcionar soporte para el nuevo circuito.
[ 167 ]
www.itebooks.info
Machine Translated by Google
El código Arduino
Aquí está el nuevo código; por supuesto, puedes encontrarlo en el Capítulo 05/
Carpeta MultipleSwitchesWithProcessing/ disponible para descargar junto con
otros archivos de código en el sitio de Packt:
int enByte = 0;
vacío configuración()
{ Serial.begin(9600);
cambiaEstados[i] = 0 ;
}
bucle vacío(){
// Si se recibe un byte válido del procesamiento, lea todas las entradas digitales. if (Serial.available() > 0) {
[ 168 ]
www.itebooks.info
Machine Translated by Google
Capítulo 5
}
}
}
void decirhola() {
mientras (Serial.available() <= 0) {
Serial.print('Z'); // envía una Z mayúscula a Arduino para decir
"¡HOLA!"
retraso(200);
}
}
Primero, definí una constante switchesNumber con el número 3. Este número se puede cambiar a cualquier
otro número entre 1 y 12. Este número representa la cantidad actual de interruptores conectados a la placa
desde el pin digital 2 al pin digital 14. Todos los interruptores deben estar vinculados sin un pin vacío
entre ellos.
Luego, definí una matriz para almacenar los estados de los interruptores. La declaré utilizando la
constante switchesNumber como longitud. Tengo que llenar esta matriz con ceros en el método setup() ,
que creé con un bucle for . Proporciona una forma segura de estar seguro de que todos los interruptores tienen
un estado de liberación en el código.
Todavía uso la función sayHello() para configurar el inicio de la comunicación con Processing.
De hecho, tengo que completar cada estado del interruptor en la matriz switchesStates , por lo que agregué
el bucle for . Observe el truco del índice en cada bucle for . De hecho, debido a que parece ser más
conveniente comenzar desde 0 y debido a que en el mundo real no debemos usar los pines digitales 0 y 1
mientras usamos comunicaciones en serie, agregué 2 tan pronto como traté con el número real del pin digital,
es decir, con las dos funciones pinMode() y digitalRead().
[ 169 ]
www.itebooks.info
Machine Translated by Google
El código de procesamiento
Aquí está el nuevo código; lo puedes encontrar en el Capítulo 05/
Carpeta MultipleSwitchesWithProcessing/ disponible para descargar junto con otros archivos de
código en el sitio de Packt:
procesamiento de importación.serial.*;
int switchesNumber = 2;
Serial theSerialPort; // crea el objeto de puerto serial int[] serialBytesArray = new int[2]; // matriz que almacena el mensaje actual // índice del conmutador int
int bytesCount = 0; // número actual de bytes relativos a los mensajes boolean init = false; int fillColor = 40; color
// estado inicial //
definición del relleno inicial
configuración vacía() {
fondo(70); noStroke();
distanciaCirculos
= ancho / switchesNumber; radios = distanciaCirculos/2;
cambiaEstados[i] = 0;
[ 170 ]
www.itebooks.info
Machine Translated by Google
Capítulo 5
}
}
void dibujar() {
}
}
[ 171 ]
www.itebooks.info
Machine Translated by Google
// Restablecer bytesCount:
bytesCount = 0;
}
}
}
A continuación se muestra una captura de pantalla de la representación de este código utilizado con cinco
interruptores mientras presionaba el cuarto botón:
Siguiendo el mismo concepto que con el código de Arduino, agregué una variable (no una constante aquí),
llamada switchesNumber. Una buena evolución podría ser agregar algo al protocolo sobre el número del
interruptor. Por ejemplo, la placa Arduino podría informar a Processing sobre el número del interruptor de
acuerdo con una única constante definida en el firmware de Arduino. Esto ahorraría la actualización manual del
código de Processing cuando cambiamos este número.
[ 172 ]
www.itebooks.info
Machine Translated by Google
Capítulo 5
Aquí calculo la distancia entre dos círculos dividiendo el ancho del lienzo por la cantidad de círculos.
Luego, calculo los radios de cada círculo usando la distancia entre ellos dividida por 2. Estos números se
pueden cambiar. Podrías tener una elección estética muy diferente.
La gran diferencia aquí es también el bucle for . Estoy llenando toda la matriz
switchesStates con ceros para inicializarla. Al principio, no se pulsa ninguno de los interruptores. La
función draw() ahora también incluye un bucle for . Preste atención aquí. Eliminé el método
fillColor porque moví la opción de color de relleno al draw. Esta es una alternativa que muestra la
flexibilidad del código.
En el mismo bucle for, estoy dibujando el círculo número i. Te dejaré comprobar por ti mismo
cómo he colocado los círculos. El método serialEvent() tampoco cambia mucho. Eliminé el
cambio de color de relleno como escribí antes. También utilicé la matriz switchesStates y el índice
proporcionado por el primer byte del mensaje que almacené en switchID.
Ahora, puedes ejecutar el código en cada lado después de haber cargado el firmware en
La placa Arduino.
¿Magia? Supongo que ahora sabes que no es magia en absoluto, pero sí hermosa, tal vez.
Vamos a ir un poco más allá hablando de algo importante sobre los switches, pero también relacionado
con otros switches.
[ 173 ]
www.itebooks.info
Machine Translated by Google
Un interruptor está hecho con piezas de metal y plástico. Cuando se presiona la tapa, una pieza de
metal se mueve y entra en contacto con otra pieza de metal, cerrando el circuito. Microscópicamente
y durante un intervalo de tiempo muy pequeño, las cosas no son tan limpias. De hecho, la pieza de
metal en movimiento rebota contra la otra parte. Con un osciloscopio que mide el potencial eléctrico
en el pin digital del Arduino, podemos ver algo de ruido en la curva de voltaje alrededor de 1 ms después
de la pulsación.
Estas oscilaciones podrían generar entradas incorrectas en algunos programas. Imagine que desea
contar las transiciones de estados para, por ejemplo, ejecutar algo cuando el usuario presionó el interruptor
siete veces. Si tiene un sistema de rebote, al presionar solo una vez, el programa podría contar muchas
transiciones incluso si el usuario presionó el interruptor solo una vez.
Observa el siguiente gráfico. Representa el voltaje en relación con el tiempo. Las pequeñas flechas en
el eje del tiempo muestran el momento en el que se presionó el interruptor:
• El circuito en sí
• El firmware
[ 174 ]
www.itebooks.info
Machine Translated by Google
Capítulo 5
El circuito en sí se puede modificar. Podría citar algunas soluciones como añadir diodos,
condensadores y algunos inversores de disparo Schmitt. No explicaré esa solución en detalle porque
lo vamos a hacer en software, pero puedo explicar el concepto global. En ese caso, el condensador
se cargará y descargará mientras el interruptor rebota, suavizando esos picos de ruido. Por supuesto,
se necesitan algunas pruebas para encontrar los componentes perfectos que se ajusten a sus
necesidades precisas.
Básicamente, podemos utilizar un filtro basado en el tiempo, porque el rebote ocurre durante
un período de tiempo particular.
configuración vacía() {
pinMode(ledPin, OUTPUT); // el pin led está configurado como salida
pinMode(switchPin, INPUT); // el pin del interruptor está configurado como entrada
}
bucle vacío(){
// si el tiempo transcurrido desde el último rebote es mayor que el retraso del rebote
[ 175 ]
www.itebooks.info
Machine Translated by Google
}
demás
{
digitalWrite(ledPin, LOW); // apaga el LED si está presionado actualmente
}
}
• debounceDelay: Este es el valor durante el cual nada se toma como un valor seguro
Aquí usamos millis() para medir el tiempo. Ya hablamos de esta función de tiempo en el Capítulo 4,
Mejorar la programación con funciones, matemáticas y cronometraje.
Luego, en cada ciclo loop() , leo la entrada pero básicamente no la guardo en la variable
switchState que se usa para probar si se enciende o apaga el LED.
Básicamente, solía decir que switchState es la variable oficial que no quiero modificar antes del
proceso de eliminación de rebotes. Si utilizo otros términos, puedo decir que estoy almacenando
algo en switchState solo cuando estoy seguro del estado, no antes.
[ 176 ]
www.itebooks.info
Machine Translated by Google
Capítulo 5
Luego, verificamos si el tiempo transcurrido desde el último rebote es mayor que nuestro retraso. Si lo es,
podemos considerar el último readInput en este ciclo como el estado de conmutación real y podemos
almacenarlo en la variable correspondiente. En el otro caso, almacenamos el último valor leído en
lastSwitchState para conservarlo para la siguiente comparación de ciclos.
Podemos encontrar aquí y allá algunos ejemplos de software antirrebote utilizados no solo para
conmutadores sino también para entradas ruidosas. En todo lo relacionado con un evento controlado por
el usuario, recomendaría utilizar este tipo de antirrebote. Pero para todo lo relacionado con la comunicación
del sistema, el antirrebote puede ser muy inútil e incluso un problema, porque podemos ignorar algunos
mensajes y datos importantes. ¿Por qué? Porque un sistema de comunicación es mucho más rápido que
cualquier usuario, y si podemos utilizar 50 ms como el tiempo durante el cual nada se considera como
un impulso real o una liberación real con los usuarios, no podemos hacer eso para señales de chipset
muy rápidas y otros eventos que podrían ocurrir entre los propios sistemas.
Resumen
Hemos aprendido un poco más sobre las entradas digitales. Las entradas digitales se pueden utilizar
directamente, como acabamos de hacer, o también indirectamente. Utilizo este término porque, en efecto,
podemos utilizar otros periféricos para codificar datos antes de enviarlos a las entradas digitales. He
utilizado unos sensores de distancia que funcionaban así, utilizando entradas digitales y no analógicas.
Codificaron la distancia y la extrajeron utilizando el protocolo I2C. Se requirieron algunas operaciones
específicas para extraer y utilizar la distancia. De esta manera, estamos haciendo un uso indirecto de las
entradas digitales.
Otra forma interesante de percibir el mundo es mediante el uso de entradas analógicas. De hecho, esto
abre un nuevo mundo de valores continuos. Sigamos adelante.
[ 177 ]
www.itebooks.info
Machine Translated by Google
www.itebooks.info
Machine Translated by Google
Este capítulo es bueno, pero muy extenso. No tengas miedo. También analizaremos muchos
conceptos nuevos mientras escribimos y diseñamos código C++ puro.
Vamos a describir juntos qué son las entradas analógicas. También os voy a presentar a un nuevo
y poderoso amigo digno de respeto, el framework Max 6. De hecho, nos ayudará un poco
como lo hizo Processing: a comunicarnos con la placa Arduino.
Te darás cuenta de lo importante que es esto para los ordenadores, especialmente cuando
tienen que sentir el mundo. Un ordenador con el framework Max 6 es muy potente, pero
un ordenador con el framework Max 6 y el plugin Arduino puede sentir muchas
características del mundo físico, como la presión, la temperatura, la luz, el color y muchas más.
Arduino, como ya hemos visto, se comporta un poco como un órgano muy potente capaz de...
sentir.
Si te gusta este concepto de sentir cosas, y especialmente el de hacer que otras cosas
reaccionen a estos sentimientos, te encantará este capítulo.
www.itebooks.info
Machine Translated by Google
Aquí, en el mundo continuo de las entradas analógicas, podemos percibir un flujo entre los
diferentes valores, mientras que las entradas digitales solo pueden proporcionar pasos. Esta
es una de las razones por las que siempre utilizo el término "sensación". Sí, cuando se pueden
medir muchos valores, esto se acerca a la percepción y la sensación. Esto es un poco la
humanización del hardware electrónico, y lo asumo totalmente.
¿Por qué 1024? La razón es fácil de entender si comprendes cómo Arduino puede detectar valores continuos.
Como el chip Arduino trabaja en el dominio digital para todos los cálculos, tenemos que convertir
valores analógicos de 0 V a 5 V a uno digital. El propósito del conversor analógicodigital, alojado
dentro del propio chipset, es exactamente ese. Este dispositivo también se conoce con el acrónimo
ADC.
[ 180 ]
www.itebooks.info
Machine Translated by Google
Capítulo 6
Los ADC de Arduino tienen una resolución de 10 bits. Esto significa que cada valor analógico se
codifica y asigna a un valor entero codificado de 10 bits. El número máximo que se puede codificar
con este sistema de codificación es 1111111111 en el sistema binario, lo que significa 1023 en el
sistema decimal. Si considero que el primer número es 0, tenemos un total de 1024 valores
representados. Una resolución de 1024 valores proporciona un campo de detección muy cómodo, como
veremos en las próximas páginas.
Teniendo en cuenta la ley de Ohm, que relaciona el valor de la tensión, la corriente y la resistencia,
podemos entender que, para una corriente constante, podemos hacer que la tensión varíe modificando
el valor de la resistencia del potenciómetro. De hecho, como algunos de nosotros no hemos desempolvado
nuestro libro de texto de electrónica elemental en muchos años, ¿qué tal si hacemos un repaso? Aquí
está la ley de Ohm:
V = R * yo
Recuerde siempre:
¡Utilice una resolución de 10 bits y será el maestro de las entradas analógicas!
[ 181 ]
www.itebooks.info
Machine Translated by Google
Arduino1
3V3 5V Venir
Fuerza
D13
ARÉF
Modulación por ancho de pulso (PWM)
D11
Arduino
Modulación por ancho de pulso (PWM)
Yo ref. D10
Modulación por ancho de pulso (PWM)
D8
D7
Modulación por ancho de pulso (PWM)
D6
Modulación por ancho de pulso (PWM)
D5
Entrada/
salida
digital
A0 D4
Entrada analógica
A1 D3
A2 D2
Tejas
A3 D1
Recepción
A4 D0
A5 LCC
Tierra
[ 182 ]
www.itebooks.info
Machine Translated by Google
Capítulo 6
Al igual que la función digitalRead(), que puede leer el valor de las entradas digitales en Arduino,
existe analogRead() para hacer lo mismo con las entradas analógicas.
La intención aquí es leer el valor como un valor de pausa en nuestro programa con el fin
de controlar la velocidad de parpadeo de un LED. En el código, usaremos delay()
función.
He aquí un ejemplo:
int potPin = 0; int ledPin // numero de pin donde esta conectado el potenciometro
= 13; int potValue = 0; // // número de pin del LED integrado
variable que almacena el valor de voltaje medido en el pin potPin
configuración vacía() {
pinMode(ledPin, OUTPUT); // define el pin ledPin como una salida
}
bucle vacío(){
potValue = analogRead(potPin); // lee y almacena el valor leído en el pin potPin
Primero leo el valor en el pin potPin . Como ya comentamos, el valor que devuelve esta
función es un número entero entre 0 y 1023. Lo guardo en la variable potValue para
mantener el LED encendido, pero también para mantenerlo apagado.
[ 183 ]
www.itebooks.info
Machine Translated by Google
Luego, apago y enciendo el LED con cierto retraso entre los cambios de estado.
Lo más inteligente aquí es utilizar potValue como retardo. Si se gira completamente un lado, el potenciómetro
proporciona un valor de 0. Si se gira completamente el otro lado, proporciona 1023, que es un valor de
retardo razonable y fácil de usar en milisegundos.
Para asegurarme de que hayas entendido la parte física de esto, me gustaría explicarte un poco más sobre
el voltaje.
Los pines de +5 V y de tierra del Arduino suministran el voltaje al potenciómetro. Su tercera pata proporciona
una forma de variar el voltaje al variar la resistencia. Las entradas analógicas del Arduino pueden leer este
voltaje. Tenga en cuenta que los pines analógicos del Arduino son solo entradas. Esta es también la
razón por la que, con los pines analógicos, no tenemos que preocuparnos por la precisión en el código como
lo hacemos con los pines digitales.
Así que vamos a modificar un poco el código para poder leer un valor de voltaje.
Si queremos usarlo como un potenciómetro real, también tenemos que suministrar Vcc a otra parte del
circuito y luego conectar nuestro pin A0 a otro punto del circuito.
Como vimos, la función analogRead() solo proporciona números enteros de 0 a 1023. ¿Cómo podemos tener
medidas eléctricas reales mostradas en algún lugar?
El rango de 0 a 1023 está asignado a 0 a 5 V. Esto viene integrado en Arduino. Podemos calcular el voltaje de
la siguiente manera:
[ 184 ]
www.itebooks.info
Machine Translated by Google
Capítulo 6
int potPin = 0; int ledPin // numero de pin donde esta conectado el potenciometro
= 13; int potValue = 0; // // número de pin del LED integrado
variable que almacena el valor de voltaje medido en el pin potPin
configuración vacía() {
Serie.begin(9600);
pinMode(ledPin, OUTPUT); // define el pin ledPin como una salida
}
bucle vacío(){
potValue = analogRead(potPin); // lee y almacena el valor leído en el pin potPin
Para poder ver el resultado en el ordenador, por supuesto, hay que encender el monitor serial.
Luego, se pueden leer los valores de voltaje.
[ 185 ]
www.itebooks.info
Machine Translated by Google
Calculando la precisión
Tenga en cuenta que aquí utilizamos un ADC para convertir un valor analógico en digital;
luego, realizamos un pequeño cálculo sobre ese valor digital para obtener un valor de voltaje.
Este es un método muy costoso en comparación con un controlador de voltaje analógico básico.
Esto significa que nuestra precisión depende del propio ADC, que tiene una resolución de 10 bits.
Esto significa que solo podemos tener 1024 valores entre 0 V y 5 V. 5 dividido por 1024 es igual
a 0,00488, que es un valor aproximado.
Básicamente significa que no podremos distinguir entre valores como 2,01 V y 2,01487 V, por
ejemplo. Sin embargo, debería ser lo suficientemente preciso para los fines de nuestro
aprendizaje.
[ 186 ]
www.itebooks.info
Machine Translated by Google
Capítulo 6
La versión original de Max fue escrita por Miller Puckette; inicialmente se trataba de un editor
llamado Patcher para Macintosh. La escribió en el Instituto Europeo de Investigación y
Coordinación Acústica/Música (IRCAM), un instituto científico de vanguardia con sede
cerca del Centro Pompidou en París, Francia.
En 1989, el software fue licenciado por IRCAM a Opcode Systems, una empresa
privada, y desde entonces ha sido desarrollado y ampliado por David Zicarelli.
A mediados de los años 90, Opcode Systems cesó todo desarrollo para este dispositivo.
Puckette lanzó una versión de Max totalmente gratuita y de código abierto llamada
Pure Data (a menudo conocida como Pd). Esta versión es muy utilizada y la mantiene la
comunidad que la utiliza.
[ 187 ]
www.itebooks.info
Machine Translated by Google
Desde 1999, el framework comúnmente conocido como Max/MSP ha sido desarrollado y distribuido por Cycling
'74, la empresa del Sr. Zicarelli.
Como la arquitectura del framework era muy flexible, se fueron añadiendo progresivamente algunas
extensiones, como Jitter (una síntesis visual enorme y eficiente), Processing, módulos de cálculos
matriciales en tiempo real y también un motor 3D. Esto ocurrió alrededor de 2003. En ese momento, se lanzó Jitter
y se podía adquirir por separado, pero requería Max, por supuesto.
En 2008, se lanzó una actualización importante con el nombre Max 5. Esta versión tampoco incluía Jitter de forma
nativa, sino como un módulo complementario.
Max 4 ya era totalmente utilizable y eficiente, pero tengo que dar mi opinión sobre Max 6 aquí. Cualquier cosa
que tengas que construir, interfaces, protocolos de comunicación complejos o sencillos, incluidos dispositivos USB
basados en HID (HID=dispositivo de interfaz humana) , como Kinect, MIDI, OSC, serial, HTTP y cualquier otra
cosa, motores de sonido basados en 3D o aplicaciones básicas independientes para la plataforma Windows o OS
X, puedes hacerlo con Max 6, y es una forma segura de construir.
Aquí les cuento mi breve historia personal con Max: comencé a jugar con Max 4. Construí especialmente
algunas interfaces MIDI macro para mis primeros controladores MIDI de hardware con el fin de controlar mis
herramientas de software de maneras muy específicas. Me enseñó mucho y me abrió la mente a nuevos
conceptos. Lo uso todo el tiempo, para casi todas las partes de mi creación artística.
[ 188 ]
www.itebooks.info
Machine Translated by Google
Capítulo 6
Conceptos globales
Por supuesto, dudé en comenzar la parte sobre Max 6 en la sección anterior, pero supongo que la
pequeña historia fue un buen punto de partida para describir el marco en sí.
Los marcos que utilizan este fuerte paradigma gráfico incluyen muchas formas de
programación en las que podemos encontrar datos, tipos de datos, operadores y funciones, entrada y
salida, y también una forma de conectar hardware.
En lugar de escribir códigos fuente largos, se agregan objetos y se conectan entre sí para construir
arquitecturas de software. Piense en juguetes de Tinker o Legos.
Si bien este paradigma puede entenderse en primer lugar como una forma de simplificación, no es el
primer propósito, quiero decir que no sólo es más fácil, sino que también proporciona un enfoque
totalmente nuevo para programadores y no programadores por igual. También proporciona un nuevo tipo
de tarea de soporte. De hecho, si no programamos de la misma manera que parcheamos, tampoco
solucionamos los problemas de la misma manera.
• Usine: Este es un software de audio universal para grabación en vivo y en estudio y está disponible
en http://www.sensomusic.com/usine
[ 189 ]
www.itebooks.info
Machine Translated by Google
• vvvv: Esta es una herramienta de síntesis de video en tiempo real para Windows y está disponible en
http://vvvv.org
Me gustaría hacer una mención especial a Usine. Es un framework muy interesante y potente que
proporciona programación gráfica para diseñar parches que se pueden utilizar dentro del propio
software de Usine o incluso como binarios independientes. Pero una de las características
particularmente potentes es el hecho de que puedes exportar tu parche como un complemento
VST totalmente funcional y optimizado. VST (Virtual Studio Technology) es un estándar potente
creado por la empresa Steinberg. Proporciona una enorme lista de especificaciones y se implementa
en casi todas las estaciones de trabajo de audio digital. Usine proporciona una función de exportación con
un solo clic que empaqueta tu parche programado gráficamente en un complemento VST estándar
para personas que ni siquiera han oído hablar de Usine o de los estilos de parcheo. La característica
multitáctil única de Usine también lo convierte en un framework muy potente. Luego, incluso puedes
codificar tus propios módulos utilizando sus SDK de C++ (kits de desarrollo de software).
Utilice un gran parche que conecte el mundo real con muchos objetos virtuales
[ 190 ]
www.itebooks.info
Machine Translated by Google
Capítulo 6
Aquí hay una captura de pantalla con un parche muy básico diseñado para ayudarlo a comprender dónde
van las cosas:
Como describí, con un marco de programación gráfica no necesitamos escribir código para
que sucedan cosas. Aquí, simplemente estoy activando un cálculo.
Puedes ver otros dos numboxes que muestran básicamente los números resultantes enviados
por los objetos con los signos + y – .
¿Sigues conmigo? Supongo que sí. Max 6 ofrece un sistema de ayuda muy bien
documentado con todas las referencias a cada objeto y está directamente disponible en el área de juegos.
Es bueno decirles esto a los estudiantes cuando les enseñas este marco, porque realmente les ayuda
a aprender por sí solos. De hecho, pueden ser casi autónomos en la búsqueda de respuestas a pequeñas
preguntas y sobre cosas que han olvidado pero que no se atreven a preguntar.
[ 191 ]
www.itebooks.info
Machine Translated by Google
La parte Max proporciona un programador de tareas bastante avanzado, y algunos objetos incluso pueden
modificar la prioridad, por ejemplo, para diferir y diferir lentamente para obtener una granularidad ordenada de prioridades
dentro de su parche, por ejemplo, para el aspecto de la interfaz de usuario y el aspecto del núcleo de cálculo, que
requieren cada uno una programación muy diferente.
Max también nos brinda un ingenioso sistema de depuración con una ventana similar a una consola
llamada ventana Max.
La ventana Max que muestra información de depuración sobre el error del objeto expr en el parche
Max controla muchas cosas. De hecho, es Max quien posee y dirige el acceso a todos los módulos, activados
o no, proporciona autocompletado cuando creas nuevos objetos y también da acceso a muchas cosas que pueden
ampliar el poder de Max, como:
• Java a través del objeto mxj que se instancia directamente dentro de las clases Java Max 6
• Motor central MSP para todo lo relacionado con la velocidad de la señal, incluido el audio.
• Motor central Jitter para todo lo relacionado con el procesamiento de matrices y mucho más,
como elementos visuales y vídeos
• Motor Gen para una compilación de código eficiente y sobre la marcha directamente desde el
parche
Esta no es una lista exhaustiva, pero te dará una idea de lo que ofrece Max.
[ 192 ]
www.itebooks.info
Machine Translated by Google
Capítulo 6
Aunque podemos conectar objetos MSP de la misma forma que los objetos Max puros, el concepto subyacente
es diferente. En cada momento, se calcula un elemento de señal, lo que genera un flujo de datos casi continuo
a través de lo que llamamos una red de señales. La red de señales es fácil de identificar en la ventana del
parcheador; los cables son diferentes.
Aquí hay una imagen de un parche muy simple que produce una onda de audio basada en coseno en sus
oídos:
De hecho, incluso los cables de conexión tienen un aspecto diferente, mostrando colores frescos, con rayas
amarillas y negras, similares a las de las abejas, y los nombres de los objetos MSP contienen una tilde ~ como
sufijo, que simboliza… ¡una ola, por supuesto!
[ 193 ]
www.itebooks.info
Machine Translated by Google
La ventana Estado de audio es el lugar donde se configuran algunos parámetros importantes de MSP
Proporciona un marco muy eficiente de procesamiento matricial diseñado inicialmente para cálculos rápidos de
valores de píxeles para mostrar imágenes, animadas o no.
[ 194 ]
www.itebooks.info
Machine Translated by Google
Capítulo 6
Hablamos de cálculo matricial para todo lo relacionado con el procesamiento de matrices Jitter.
Y, de hecho, si necesitas activar cálculos muy rápidos de matrices enormes en Max 6, puedes
usar Jitter para eso, incluso si no necesitas mostrar ningún elemento visual.
Jitter ofrece mucho más que un simple cálculo de matrices. Proporciona acceso completo a
una implementación de OpenGL (http://en.wikipedia.org/wiki/OpenGL) que funciona a la
velocidad de la luz. También proporciona una forma de diseñar y manejar sistemas de partículas,
mundos 3D, materiales OpenGL y animación basada en la física. El procesamiento de
píxeles es también una de las potentes funciones que se proporcionan con muchos objetos
diseñados y optimizados para el procesamiento de píxeles.
Un parche básico basado en Jittercore que genera un mapa de píxeles de ruido de buena resolución de 400x400
Para resumir esta enorme carga de información, Max programa eventos o espera a que el
usuario active algo, MSP (para procesamiento de señales de audio), tan pronto como se activa,
calcula elementos de señal en cada instante en sus redes de señal, y Jitter procesa cálculos
cuando los objetos Jitter son activados por explosiones.
De hecho, los objetos Jitter necesitan ser activados para realizar su trabajo, que puede
ser muy diferente, como por ejemplo, generar una matriz que contiene valores de color de
píxeles, procesar una matriz para cada celda de una matriz y generar la matriz resultante.
[ 195 ]
www.itebooks.info
Machine Translated by Google
Los flequillos son mensajes especiales que se utilizan para decir "¡Oye, comencemos tu trabajo!" a los objetos.
Los objetos en Max pueden comportarse de manera diferente, pero casi todos pueden entender el mensaje
de explosión.
En Patch003 (que se muestra en la captura de pantalla anterior), el objeto Max qmetro envía un mensaje cada
20 ms desde una cola de programación de baja prioridad a un objeto Jitter llamado jit.noise. Este último
objeto calcula una matriz llena de un valor aleatorio en cada celda. Luego, el resultado pasa a través de un
nuevo cable de conexión con rayas verdes y negras a un objeto UI en el que podemos ver un nombre,
jit.pwindow, una especie de pantalla que podemos incluir en nuestros parcheadores.
El jitter se puede controlar a través de potentes API de Java y JavaScript para algunas tareas que requieren
,
escribir grandes bucles en código que son fáciles de diseñar usando código.
¿Aún aquí?
Para los más valientes entre los valientes, algunas otras filas sobre Gen, el último y más eficiente
módulo de Max 6.
Por cierto, hay muchas maneras de diseñar parches usando código, con JavaScript por ejemplo. Directamente
dentro de Max Patcher, puedes crear un objeto .js y poner tu código JavaScript dentro; de hecho, se compila
sobre la marcha (se llama compilador JS JIT , por compilador de JavaScript justo a tiempo). Es realmente
rápido. Créeme, lo probé mucho y lo comparé con muchos otros frameworks. Entonces, como dice la
documentación, "no estamos limitados a escribir elementos externos de Max en C", aunque es totalmente
posible usando el SDK de Max 6 (http://cycling74.com/products/sdk).
Gen ofrece una forma de aplicar parches a los fragmentos de parches que se compilan sobre la marcha, y
esta es una compilación real de su parche. Ofrece un nuevo tipo de parcheador con objetos específicos,
bastante similar a los objetos Max.
Funciona para MSP, con el objeto gen~ Max, lo que proporciona una forma elegante de diseñar la arquitectura
de parches de audio relacionados con la velocidad de la señal. Puede diseñar DSP y generadores de sonido de
esa manera. Los parches gen~ son como un zoom en el tiempo; debe considerarlos como procesadores
de muestras. Cada muestra es procesada por esos parches dentro de gen~
Parches. Hay objetos inteligentes que acumulan cosas a lo largo del tiempo, por supuesto, para tener ventanas
de tiempo de procesamiento de señales.
[ 196 ]
www.itebooks.info
Machine Translated by Google
Capítulo 6
• jit.gen es el procesador de matrices rápido, que procesa cada celda de una matriz en cada
doblar
• jit.pix es el procesador de píxeles basado en CPU, que procesa cada píxel de un sistema de píxeles.
mapa
• jit.gl.pix es la versión basada en GPU de jit.pix
Una GPU (unidad de procesamiento gráfico) es básicamente un procesador gráfico dedicado en la tarjeta de
video. Por lo general (y este es un universo completamente diferente), la canalización OpenGL proporciona
una manera fácil de modificar píxeles desde las definiciones de software hasta la pantalla justo antes de
que se muestren en la pantalla. Se llama proceso de sombreado.
Quizás ya conozcas este término en relación con el mundo de los videojuegos. Se trata de esos shaders
que son uno de los últimos pasos para mejorar los gráficos y los renders visuales también en nuestros
juegos.
Los shaders son básicamente pequeños programas que se pueden modificar sobre la marcha al pasar
argumentos procesados por la propia GPU. Estos pequeños programas utilizan lenguajes específicos y se
ejecutan con mucha velocidad en procesadores dedicados de nuestras tarjetas gráficas.
Max 6 + Gen proporciona acceso directo a esta parte del pipeline solo mediante parches; si no queremos
escribir sombreadores basados en OpenGL GLSL (http://www.opengl.
org/documentation/glsl), Microsoft DirectX HLSL (http://msdn.microsoft.
com/enus/library/bb509635(v=VS.85).aspx) o Nvidia Cg (http://http.
developer.nvidia.com/CgTutorial/cg_tutorial_chapter01.html), Gen es tu amigo.
Luego puedes diseñar tus propios sombreadores de fragmentos (o sombreadores de píxeles) mediante
parches e incluso puedes obtener el código fuente en lenguaje GLSL o WebGL para usarlo en otro marco,
por ejemplo.
Los sombreadores de geometría no están disponibles usando Gen, pero con otros objetos Jitter ya
existen.
Supongo que he perdido a algunos de ustedes. ¡Relájense, no les haré preguntas sobre Gen en los
exámenes de Arduino!
[ 197 ]
www.itebooks.info
Machine Translated by Google
Max El patio de recreo Gris por defecto y sin rayas Nombres básicos
MSP Todo lo relacionado con audio y velocidad Rayas amarillas y negras ~ sufijo al
de señal nombre
procesamiento de
velocidad de señal
Estar nervioso Todo lo relacionado con visuales y Rayas verdes y negras para jit. prefijado al nombre
matrices. cables de matriz
Instalación de Max 6
Max 6 está disponible como prueba de 30 días. Instalar Max 6 es bastante fácil, ya que viene
con un instalador para ambas plataformas, Windows y OS X, que se puede descargar en http://
cycling74.com/downloads. Descárguelo e instálelo. Luego, ejecútelo. Eso es todo.
(Los siguientes ejemplos solo funcionarán cuando haya instalado Max).
[ 198 ]
www.itebooks.info
Machine Translated by Google
Capítulo 6
La ansiedad de tener que quedarse con 6 páginas en blanco puede ocurrir ahora mismo, ¿no es así?
El primer parche
Aquí hay un parche básico que también puedes encontrar en la carpeta Chapter06/ con el
nombre Patcher004_Arduino.maxpat. Por lo general, si haces doble clic en él, Max 6 lo
abre directamente.
¡Este parche es muy básico, pero en realidad no tanto!
Se trata de un secuenciador básico basado en ruido que modifica la frecuencia de un oscilador
de forma regular en tiempo real. Esto produce una secuencia de sonidos extraños, más o
menos bonitos, en la que las modificaciones de la frecuencia se controlan al azar. Así pues, enciende
los altavoces y el parche producirá sonidos.
[ 199 ]
www.itebooks.info
Machine Translated by Google
Básicamente, los parches se almacenan en archivos. Puedes compartir parches con otros amigos con
bastante facilidad. Por supuesto, los proyectos más grandes implicarían algunos problemas de
dependencia; si agregaste algunas bibliotecas a tu marco Max 6, si las usas en un parche o si
básicamente envías tus archivos de parche a un amigo que no tiene esas bibliotecas instaladas, tu
amigo tendrá algunos errores en la ventana Max. No describiré este tipo de problemas aquí, pero
quería advertirte.
Otras formas interesantes de compartir parches en el mundo de Max 6 son las funciones de copiar/
pegar y copiar comprimidos. De hecho, si seleccionas objetos en tu parcheador (cualquiera que
sea la capa, incluido un subparcheador, dentro de un subparcheador, etc.) y vas a Editar | Copiar, el
contenido basado en texto se coloca en tu portapapeles. Luego, esto se puede volver a pegar en otro
parcheador o dentro de un archivo de texto.
La forma más inteligente es utilizar copy compress, que como su nombre bien elegido significa,
copia y comprime el código JSON a algo mucho más compacto y fácil de copiar en el área de texto de
los foros, por ejemplo.
Simplemente seleccioné todos los objetos en mi parche y fui a Editar | Copiar comprimido.
[ 200 ]
www.itebooks.info
Machine Translated by Google
Capítulo 6
Aquellos familiarizados con HTML notarán algo gracioso: los desarrolladores de Cycling '74
incluyen dos etiquetas HTML (pre y code) para proporcionar directamente código que se
pueda pegar dentro de un campo de texto en (cualquier) foro de la Web.
También puedes copiar ese código en el portapapeles y pegarlo en un nuevo parche. Puedes crear
un nuevo parche vacío yendo a Archivo | Nuevo (o presionando Ctrl + N en Windows y Comando +
N en OS X).
[ 201 ]
www.itebooks.info
Machine Translated by Google
Antes de comenzar, asegúrese de bloquear el parche haciendo clic en el icono del candado en la
esquina inferior izquierda. Para escuchar los resultados del parche, también deberá hacer clic en el
icono del altavoz. Para alejar la imagen, vaya al menú Ver y haga clic en Alejar.
En primer lugar, observe y verifique el interruptor en la parte superior. Enviará el valor 1 al objeto
conectado metro.
Un metro es un objeto Max puro que envía un bang cada n milisegundos. Aquí, he codificado
un argumento: 100. Tan pronto como el metro recibe el mensaje 1 del conmutador, comienza a estar
activo y, siguiendo el programador de tiempo Max, enviará sus bangs cada 100 ms al siguiente objeto
conectado.
Cuando el objeto aleatorio recibe un golpe, genera un número entero aleatorio dentro de un rango.
Aquí puse 128, lo que significa que el objeto aleatorio enviará valores de 0 a 127.
Inmediatamente después de la función aleatoria, coloqué un objeto zmap que funciona como un
escalador. Codifiqué cuatro argumentos: valores mínimos y máximos para las entradas y valores mínimos
y máximos para las salidas.
Básicamente, aquí, zmap asigna mis valores 0 a 127 enviados aleatoriamente a otros valores de 20 a 100.
Produce un estiramiento implícito y una pérdida de resolución que me gusta.
Luego, este número resultante se envía al famoso e importante objeto mtof , que convierte un estándar
de tono de nota MIDI en una frecuencia de acuerdo con el estándar MIDI.
Se utiliza a menudo para pasar del mundo MIDI al mundo del sonido real. También puede leer la
frecuencia en el objeto de interfaz de usuario flonum, que muestra la frecuencia como un número
flotante en Hz (hertz, una medida de frecuencia).
Por último, esta frecuencia se envía al objeto cycle~ , lo que produce una señal (observe el cable con
rayas amarillas y negras). Al enviar números a este objeto, se modifica la frecuencia de la señal
producida. Esta se multiplica por un operador de multiplicación de señal *~, lo que produce otra
señal pero con una amplitud menor para proteger nuestros preciados oídos.
El último destino de esa señal es el gran cuadro gris sobre el que hay que hacer clic una vez para escuchar
o no los sonidos que produce la red de señales superior.
Ahora estás listo para marcar la casilla de activación. Activa el icono del altavoz haciendo clic en el
cuadro gris y podrás bailar. En realidad, los sonidos electrónicos que se producen son un poco aleatorios
en cuanto a la frecuencia (es decir, la nota), pero pueden ser interesantes.
Por supuesto, controlar este parche barato con el Arduino para no usar el mouse/cursor sería genial.
[ 202 ]
www.itebooks.info
Machine Translated by Google
Capítulo 6
Pero, ¿por qué necesitamos este tipo de interfaces? A veces, el viejo ratón y el teclado
QWERTY no son suficientes. Nuestros ordenadores son rápidos, pero estas interfaces para
controlar nuestros programas son lentas y torpes.
Necesitamos interfaces entre el mundo real y el mundo virtual. Sean cuales sean, necesitamos
que se centren en nuestro propósito final, que normalmente no es la interfaz o el mundo virtual.
Incluso el propio software.
Personalmente, escribo libros y doy cursos de tecnología relacionados con el arte, pero como
intérprete en vivo, necesito concentrarme en la interpretación final. Mientras actúo, quiero ocultar lo
más posible la tecnología que hay debajo. Quiero sentir más de lo que quiero calcular. Quiero una
interfaz de controlador que me ayude a operar a la velocidad y con el nivel de flexibilidad necesarios
para realizar los tipos de cambios que quiero.
Como ya dije en este libro, necesitaba un controlador MIDI enorme, pesado, sólido y complejo para poder
controlar un solo software en mi computadora. Así que construí Protodeck (http://julienbayle.net/protodeck) Esta
era mi interfaz.
Entonces, ¿cómo podemos usar Arduino para controlar software? Supongo que solo tienes una parte
de la respuesta porque ya enviamos datos a nuestra computadora al girar un potenciómetro.
Mejoremos nuestro parche Max 6 para que reciba los datos de nuestro Arduino mientras giramos el
potenciómetro.
Vamos a crear un proyecto muy básico y económico que utilizará nuestra placa Arduino como un
pequeño controlador de sonido. De hecho, utilizaremos directamente el firmware que acabamos
de diseñar con el potenciómetro y luego modificaremos nuestro parche. Esta es una base muy útil para
que puedas seguir construyendo cosas e incluso crear máquinas controladoras más grandes.
[ 203 ]
www.itebooks.info
Machine Translated by Google
Vamos a modificarlo un poco y hacer que envíe solo el valor analógico leído, dentro del rango 0
hasta 1023. Aquí está el código, disponible en Chapter06/maxController:
int potPin = 0; int potValue // numero de pin donde esta conectado el potenciometro
= 0; // variable que almacena el valor de voltaje medido en el pin potPin
configuración vacía() {
Serie.begin(9600);
}
bucle vacío(){
potValue = analogRead(potPin); // lee y almacena el valor leído en el pin potPin
Eliminé todo lo innecesario y agregué un retraso de 2 ms al final del bucle (antes de que el bucle se
reinicie). Esto se usa a menudo con entrada analógica y especialmente con ADC.
Proporciona un descanso para que se estabilice un poco. No lo hice en el código anterior que involucraba
lectura analógica porque ya había dos métodos delay() involucrados en el parpadeo del LED.
Este básico envía el valor leído al pin de entrada analógica donde está conectado el potenciómetro. Ni
más ni menos.
Ahora, aprendamos cómo recibir eso en algún lugar que no sea el Monitor Serial de nuestro preciado
IDE, especialmente en Max 6.
La siguiente figura describe el nuevo parche Max 6 incluida la parte necesaria para
comunicarse con nuestro pequeño controlador de hardware.
[ 204 ]
www.itebooks.info
Machine Translated by Google
Capítulo 6
Luego hay otro parche que puedes encontrar, también en la carpeta Chapter06/ , con el nombre
Patcher005_Arduino.maxpat.
Todo lo necesario para comprender los mensajes de Arduino y convertirlos en términos fácilmente
comprensibles para nuestro parche secuenciador está en verde. Algunos asistentes muy útiles
que pueden escribir en la ventana de Max en cada paso del flujo de datos, desde los datos sin
procesar hasta los datos convertidos, están en naranja.
[ 205 ]
www.itebooks.info
Machine Translated by Google
Los objetos de impresión son la forma de enviar mensajes directamente a la ventana de Max. Todo lo que
se les envía se escribe en la ventana de Max tan pronto como se recibe. El argumento que se
puede pasar a estos objetos también es muy útil; ayuda a discernir qué objeto de impresión envía qué
en los casos en que se utilizan más de un objeto de impresión . Este es el caso aquí y compruébelo:
Nombro todos mis objetos de impresión teniendo en cuenta el objeto del que proviene el mensaje:
• fromSerial: Esto es para todos los mensajes que vienen del propio objeto serial .
• fromZl: Esto es para todos los mensajes que vienen del objeto zl
• fromitoa: Esto es para todos los mensajes que vienen del objeto itoa
• fromLastStep: Esto es para todos los mensajes que vienen del objeto fromsymbol
Los objetos de puerta son simplemente pequeñas puertas, puertas que podemos habilitar o deshabilitar enviando 1
o 0 a la entrada más a la izquierda. Los objetos de alternancia son buenos objetos de interfaz de usuario para
hacer eso haciendo clic. Tan pronto como marque la opción de alternancia, el objeto de puerta relacionado permitirá
que cualquier mensaje enviado a la entrada derecha pase a través de ellos a la única salida.
He codificado de forma rígida algunos parámetros relacionados con la comunicación serial con Arduino:
[ 206 ]
www.itebooks.info
Machine Translated by Google
Capítulo 6
Es necesario golpear este objeto para proporcionar el contenido actual del búfer del puerto
serie. Esta es la razón por la que lo alimento mediante el objeto qmetro .
El objeto serial genera una lista de valores sin procesar. Es necesario analizar y organizar un poco
esos valores antes de leer el valor analógico enviado. Esto es lo que representan los objetos
select, zl, itoa y fromsymbol .
[ 207 ]
www.itebooks.info
Machine Translated by Google
Luego, también agregué este extraño objeto loadbang y el de impresión . loadbang es el objeto específico
que envía un bang tan pronto como Max 6 abre el parcheador. A menudo se usa para inicializar alguna
variable dentro de nuestro parcheador, un poco como lo estamos haciendo con el
declaraciones en las primeras filas de nuestros bocetos de Arduino.
print es solo texto dentro de un objeto llamado mensaje. Por lo general, cada objeto Max 6 puede
comprender mensajes específicos. Puede crear un nuevo mensaje vacío escribiendo m
en cualquier parte de un parche. Luego, con la función de autocompletar, puede rellenarlo con texto
seleccionándolo y haciendo clic en él nuevamente.
Aquí, tan pronto como se carga el parche y comienza a ejecutarse, el objeto serial recibe el mensaje de
impresión activado por loadbang. El objeto serial puede enviar la lista de todos los mensajes del puerto
serial a la computadora que ejecuta el parche a la consola (es decir, la ventana Max). Esto sucede
cuando le enviamos el mensaje de impresión. Verifique la ventana Max de la figura que muestra el
parche Patcher005_Arduino.maxpat .
Podemos ver una lista de… cosas. serial muestra una lista de abreviaturas de letras de puertos seriales,
donde los puertos seriales correspondientes a menudo representan el nombre del hardware. Aquí,
como ya vimos en el IDE de Arduino, el que corresponde al Arduino es
usbmodemfa131.
Resultado del mensaje de impresión enviado al objeto serial: la lista de letras de puerto / nombres de puertos seriales
Cambiemos la letra codificada que se coloca como argumento para el objeto serial en el parche.
Selecciona el objeto serial . Luego, vuelve a hacer clic dentro y cambia a por la letra
correspondiente al puerto serial de Arduino en tu computadora. Tan pronto como presiones Enter, el objeto
se instancia nuevamente con nuevos parámetros.
[ 208 ]
www.itebooks.info
Machine Translated by Google
Capítulo 6
Cambiar la letra de referencia en el objeto serial para que coincida con la correspondiente al puerto serial del Arduino
Ahora, todo está listo. Marca el toggle, activa el cuadro gris con el altavoz y gira tu potenciómetro. Vas
a escuchar tus ruidos extraños del secuenciador y ahora puedes cambiar la frecuencia de nota (me
refiero al intervalo entre cada sonido) porque usé abusivamente el término nota para que se ajuste
mejor a la definición habitual del secuenciador.
[ 209 ]
www.itebooks.info
Machine Translated by Google
Cuando utiliza la función Serial.println() en el código fuente del firmware de su Arduino, Arduino no envía
solo el valor pasado como argumento a la función.
Compruebe el primer interruptor naranja en la parte superior de la serie de sistemas de interruptor/puerta.
En la primera columna denominada Objeto se puede ver el nombre del objeto de impresión y en la
columna Mensaje el mensaje enviado por el objeto relacionado. Y podemos ver que el objeto serial va
generando una serie extraña de números de manera repetitiva: 51, 53, 48, 13, 10, etc.
Esto es muy importante. Veamos el Apéndice E, Tabla ASCII, para encontrar los caracteres
correspondientes:
• 51 significa el carácter 3
• 53 significa 5
• 48 significa 0
Por supuesto, hice un poco de trampa al ordenar la serie como lo hice. Sabía que existían los números 10 y
13. Es un marcador habitual que significa un retorno de carro seguido de una nueva línea.
[ 210 ]
www.itebooks.info
Machine Translated by Google
Capítulo 6
• Construir el mensaje
• Envíe el mensaje después de que esté completamente construido (usando Serial.println())
función.)
Tenemos que acumular cada código ASCII en el mismo mensaje, y cuando detectamos la
secuencia <CR><LF> , tenemos que sacar el bloque de mensaje y luego reiniciar el proceso.
select puede detectar mensajes que sean iguales a uno de sus argumentos. Cuando select 10
13 recibe un 10, enviará un mensaje a la primera salida. Si es un 13, enviará un mensaje a la
segunda salida. Luego, si llega cualquier otra cosa, simplemente pasará el mensaje de la última
salida a la derecha.
[ 211 ]
www.itebooks.info
Machine Translated by Google
zl es un procesador de listas tan potente con tantos escenarios de uso que daría para un libro
por sí solo. Si utilizamos el operador de argumento, incluso podemos usarlo para analizar los datos,
cortar listas en partes y mucho más. Aquí, con el argumento del grupo 4, zl
Recibe un mensaje inicial y lo almacena; cuando recibe un segundo mensaje, almacena el
mensaje, y así sucesivamente, hasta el cuarto mensaje. En el momento preciso en que lo
recibe, enviará un mensaje más grande compuesto por los cuatro mensajes recibidos y
almacenados. Luego, borra su memoria.
El objeto zl hace un gran trabajo; pasa todos los caracteres ASCII excepto <CR> y <LF>, y tan
pronto como recibe <LF>, zl envía un mensaje de advertencia. Acabamos de crear un
procesador de mensajes que reinicia el búfer zl cada vez que recibe <LF>, es decir, cuando
se va a enviar un nuevo mensaje.
[ 212 ]
www.itebooks.info
Machine Translated by Google
Capítulo 6
Pero mira esto, ¿dónde está el valor entre 0 y 1023 que tanto esperábamos? Tenemos que
convertir el mensaje entero ASCII en uno de carácter real. Esto se puede hacer usando el
objeto itoa (que significa entero a ASCII).
Este valor es el importante; es el mensaje que envía Arduino a través del cable y se transmite
como un símbolo. No se puede distinguir un símbolo de otro tipo de mensaje, como un número
entero o un valor de punto flotante en la ventana Max.
Coloqué dos mensajes vacíos en el parche. También son muy útiles para fines de
depuración. Los conecto a los objetos itoa y fromsymbol en su entrada derecha.
Cada vez que envías un mensaje a otro mensaje en su entrada derecha, el valor del mensaje
de destino se modifica según el contenido del otro. De esta forma, podemos mostrar qué
mensaje se envía realmente mediante itoa y fromsymbol.
[ 213 ]
www.itebooks.info
Machine Translated by Google
fromsymbol transforma cada símbolo en sus partes componentes, que aquí forman un
número entero, 350.
Este valor final es el que podemos utilizar con cualquier objeto capaz de entender y procesar
números. Este valor es escalado por el objeto escala y enviado, por último, al objeto metro. Al
girar el potenciómetro cambia el valor enviado y, dependiendo del valor, el metro envía bangs
más rápido o más lento.
Ahora, pasemos a algunos otros ejemplos relacionados con las entradas analógicas.
Te daré algunos ejemplos aquí, pero no cubriré todos los tipos de sensores por la razón
mencionada anteriormente.
Medición de distancias
Cuando diseño instalaciones para otros o para mí mismo, a menudo tengo la idea de medir la
distancia entre objetos en movimiento y un punto fijo. Imagina que quieres crear un sistema con
una intensidad de luz variable en función de la proximidad de algunos visitantes.
[ 214 ]
www.itebooks.info
Machine Translated by Google
Capítulo 6
Este sensor analógico tan interesante ofrece buenos resultados para distancias de entre 20 y 150 cm. Hay
otros tipos de sensores en el mercado, pero me gusta este por su estabilidad.
Como ocurre con cualquier sensor de distancia, el sujeto/objetivo tiene que estar teóricamente perpendicular a
la dirección del haz infrarrojo para lograr la máxima precisión, pero en el mundo real funciona bien
incluso en caso contrario.
No es necesario que entiendas todo. Sé que algunos compañeros me culparán por no explicar la hoja de
datos, pero quiero que mis estudiantes se relajen al respecto. Tienes que filtrar la información.
¿Listo? ¡Vamos!
[ 215 ]
www.itebooks.info
Machine Translated by Google
Aquí podemos ver que este sensor parece ser bastante independiente en cuanto al color
del objetivo. Bien. El tipo de salida de distancia es muy importante aquí. De hecho, significa
que emite la distancia directamente y no necesita circuitos adicionales para utilizar su salida
de datos analógicos.
Suele haber algunos esquemas de todas las dimensiones del contorno del sensor. Esto puede resultar
muy útil si desea asegurarse de que el sensor se ajuste a su caja o instalación antes de realizar el
pedido.
En la siguiente figura podemos ver un gráfico, se trata de una curva que ilustra cómo
varía el voltaje de salida en función de la distancia al objetivo.
Como medimos el voltaje con la entrada analógica de nuestra placa Arduino, necesitamos
saber cómo funciona la conversión. Voy a utilizar un atajo porque hice el cálculo por ti.
[ 216 ]
www.itebooks.info
Machine Translated by Google
Capítulo 6
Básicamente, utilicé otro gráfico similar al que vimos pero generado matemáticamente.
Necesitamos una fórmula para codificar nuestro firmware.
(a + bV)
D=
2
(1 + cV + dV )
www.itebooks.info
Machine Translated by Google
Arduino1
3V3 5V Venir
Fuerza
D13
ARÉF D11
Modulación por ancho de pulso (PWM)
D9
Modulación por ancho de pulso (PWM)
D8
J1 D7
D6
Modulación por ancho de pulso (PWM)
Entrada/
salida
digital
D5
Modulación por ancho de pulso (PWM)
Entrada analógica
A0 D4
A1 D3
Modulación por ancho de pulso (PWM)
A2 D2
Tejas
A3 D1
Recepción
A4 D0
A5 LCC
Tierra
El rango del sensor lo suministra el propio Arduino y envía voltaje a la entrada analógica 0
int sensorValue = 0
int distanciaCalculada = 0; calculada // variable que almacena la distancia
[ 218 ]
www.itebooks.info
Machine Translated by Google
Capítulo 6
configuración vacía() {
Serie.begin(9600);
}
bucle vacío(){
sensorValue = analogRead(sensorPin); v = 5. *
(sensorValue / 1023.) ; // Calcular el voltaje distanceCalculated = ((a + b * v) / (1. + c * v
+ d * v * v) );
Serial.println(distanciaCalculada);
retraso(2);
}
¿No es gratificante saber que entendiste cada línea de este código? Por si acaso, te daré una
breve explicación.
Necesito algunas variables para almacenar el valor del sensor (es decir, los valores de 0 a 1023) que
proviene del ADC. Luego, necesito almacenar el voltaje calculado a partir del valor del sensor y, por
supuesto, la distancia calculada a partir del valor del voltaje.
Solo inicio la comunicación serial en la función setup() . Luego, realizo todos los cálculos en el
método loop() .
Comencé leyendo el valor actual del ADC medido y codificado desde el pin del sensor. Utilizo este valor
para calcular el voltaje utilizando la fórmula que ya usamos en un firmware anterior. Luego, inyecto este
valor de voltaje en la fórmula para el Sharp
sensor y tengo la distancia.
Por último, envío la distancia calculada a través de la comunicación serial con la función
Serial.println() .
[ 219 ]
www.itebooks.info
Machine Translated by Google
Como aprendimos anteriormente, este parcheador contiene todo el patrón de diseño para leer los mensajes provenientes
de la placa Arduino.
Lo único nuevo aquí es el extraño elemento de la interfaz de usuario que aparece en la parte inferior. Se llama control deslizante.
Por lo general, los controles deslizantes se utilizan para controlar cosas. De hecho, cuando haces clic y arrastras un objeto
deslizante, aparecen valores. Parecen controles deslizantes en mesas de mezclas o reguladores de intensidad de iluminación,
que permiten controlar algunos parámetros.
Obviamente, como quiero transmitir muchos datos yo mismo, utilizo este objeto deslizante como dispositivo de visualización y
no como dispositivo de control. De hecho, el objeto deslizante también posee un puerto de entrada. Si envía un número a un
control deslizante, este lo toma y actualiza su valor actual interno; también transmite el valor recibido. Aquí solo lo utilizo como
pantalla.
[ 220 ]
www.itebooks.info
Machine Translated by Google
Capítulo 6
Cada objeto de Max 6 tiene sus propios parámetros. Por supuesto, muchos parámetros son
comunes a todos los objetos, pero algunos no lo son. Para comprobar esos parámetros:
• Seleccione el objeto
• Verifique el inspector eligiendo la pestaña Inspector o escribiendo Ctrl + I en
Windows o comando + I en OS X
La ventana del inspector que muestra los atributos y propiedades del objeto deslizante seleccionado
No describiré todos los parámetros, solo los dos que se encuentran en la parte inferior. Para
producir un resultado relevante, tuve que escalar el valor que proviene del objeto fromsymbol .
Conozco el rango de valores transmitidos por Arduino (aunque esto podría requerir alguna
verificación personal), habiéndolos calculado a partir de la hoja de datos de Sharp. Consideré este
rango como de 20 a 150 cm. Me refiero a un número entre 20 y 150.
[ 221 ]
www.itebooks.info
Machine Translated by Google
Tomé este rango y lo comprimí y traduje un poco, usando el objeto de escala , en un rango de 0 a 100 de
números de punto flotante. Elegí el mismo rango para mi objeto de control deslizante. Al hacer eso, el resultado
que muestra el control deslizante es coherente y representa el valor real.
No escribí ninguna marca de incremento en el control deslizante, pero solo hice dos comentarios: cerca
y lejos. Es un poco poético en este mundo de números.
Medición de la flexión
Los sensores flexibles también se utilizan mucho. El sensor de distancia puede convertir una distancia medida
en voltaje, mientras que el sensor flexible mide la flexión y proporciona un voltaje.
Básicamente, la flexión del dispositivo está relacionada con una resistencia variable capaz de hacer variar un
voltaje según la cantidad de flexión.
[ 222 ]
www.itebooks.info
Machine Translated by Google
Capítulo 6
Me gusta usarlo para informar a la computadora a través de Arduino sobre la posición de las
puertas en las instalaciones digitales que diseño. Al principio, la gente solo quería saber si las
puertas estaban abiertas o cerradas, pero propuse usar un flexi y obtuve muy buena información
sobre el ángulo de apertura.
Coloqué una resistencia pulldown. Si no leíste el Capítulo 5, Detección con entradas digitales,
sobre resistencias pullup y pulldown, te sugiero que lo hagas ahora.
[ 223 ]
www.itebooks.info
Machine Translated by Google
Arduino1
3V3 5V Venir
Fuerza
D13
ARÉF D11
Modulación por ancho de pulso (PWM)
R1
Yo ref. Arduino D10
Modulación por ancho de pulso (PWM)
D9
Modulación por ancho de pulso (PWM)
D8
D7
D6
Modulación por ancho de pulso (PWM)
Entrada/
salida
digital
D5
Modulación por ancho de pulso (PWM)
R2
Entrada analógica
A0 D4
A1 D3
Modulación por ancho de pulso (PWM)
A2 D2
Tejas
A3 D1
Recepción
A4 D0
A5 LCC
Tierra
Cálculos de resistencia
Para este proyecto no les voy a dar el código porque es muy similar al anterior, salvo por las fórmulas de
cálculo. Son estas fórmulas de cálculo de resistencia las que me gustaría comentar aquí.
¿Qué hacemos si no tenemos el gráfico que Sharp Co. tuvo la amabilidad de incluir con su sensor infrarrojo?
Tenemos que recurrir a algunos cálculos.
Por lo general, la documentación del sensor flexible proporciona valores de resistencia para cuando no
está doblado y cuando está doblado a 90 grados. Digamos que algunos valores habituales son 10K Ω y
20K Ω, respectivamente.
¿Cuáles son los valores de voltaje que podemos esperar para estos valores de resistencia, incluido también
el de pulldown?
[ 224 ]
www.itebooks.info
Machine Translated by Google
Capítulo 6
Si elegimos la misma resistencia para el pulldown que para el flexi cuando no está flexionado, podemos esperar que
el voltaje se comporte de acuerdo con esta fórmula:
10k
VA0= * 5 = VV1.7
10k + 20k
10k
VA0= * 5 = 2,5 V
10k + 10k
Ahora podemos convertir eso en valores digitales codificados de 10 bits, me refiero al famoso rango de 0 a
1023 del ADC de Arduino.
• 347 cuando el voltaje es 1,7 (cuando el cable flexible está doblado en un ángulo de
aproximadamente 90 grados)
Como el voltaje en el pin de Arduino depende de la inversa de la resistencia, no tenemos una variación
perfectamente lineal.
La experiencia me dice que casi puedo aproximar esto a una variación lineal, y utilicé una función de
escala en el firmware de Arduino para mapear [347,511] a un rango simple de [0,90]. map(value,
fromLow, fromHigh, toLow, toHigh) es la función a utilizar aquí.
¿Recuerdas el objeto de escala en Max 6? map() funciona básicamente de la misma manera, pero para Arduino. La
instrucción aquí sería map(347,511,90,0). Esto daría un valor bastante aproximado para el ángulo físico de curvatura.
La función de mapa funciona en ambas direcciones y puede mapear segmentos de números que van en la dirección
opuesta. Supongo que comienzas a ver qué pasos seguir cuando tienes que trabajar con entradas analógicas en
Arduino.
[ 225 ]
www.itebooks.info
Machine Translated by Google
• Intensidad de radiactividad •
Humedad
• Presión
• Flexión
• Nivel de líquido •
Brújula y dirección relacionada con el norte magnético • Detección
específica de gas • Intensidad de
vibración • Aceleración en
tres ejes (x, y, z) • Temperatura • Distancia
Los precios varían mucho, desde unos pocos dólares hasta 50 o 60 dólares. Encontré uno de los
contadores Geiger más baratos por unos 100 dólares. En el Apéndice G, Lista de distribuidores de
componentes, encontrará una lista enorme de empresas disponibles en Internet para comprar sensores.
Ahora, avancemos un poco más. ¿Cómo podemos manejar múltiples sensores analógicos? La
primera respuesta es conectar todo a muchas entradas analógicas del Arduino. Veamos si
Podemos ser más inteligentes que eso.
[ 226 ]
www.itebooks.info
Machine Translated by Google
Capítulo 6
En el mundo real, solemos tener muchas limitaciones. Una de ellas puede ser la cantidad de Arduinos
disponibles. Esta limitación también puede deberse a que el ordenador solo tiene un puerto USB. Sí, esto
ocurre en la vida real y mentiría si dijera que puedes tener todos los conectores que quieras, cuando
quieras y con el presupuesto que quieras.
Imagina que tienes que conectar más de ocho sensores a la entrada analógica de tu Arduino.
¿Cómo lo harías?
Conceptos de multiplexación
La multiplexación es bastante común en el mundo de las telecomunicaciones. La multiplexación define
técnicas que proporcionan formas eficientes de hacer que múltiples señales compartan un único medio.
1 1
2 2
medio compartido mux manifestación
3 3
4 4
Esta técnica proporciona un concepto muy útil en el que sólo se necesita un medio compartido para
traer muchos canales de información como podemos ver en la figura anterior.
www.itebooks.info
Machine Translated by Google
1 1
2 2
mismo cable multipar
3 3
4 4
La multiplexación por división espacial aglomera físicamente todos los cables en el mismo lugar
Tus cables telefónicos salen al exterior, al igual que los de tus vecinos, y todos esos cables se
unen en un gran cable multipar blindado que contiene, por ejemplo, todos los cables telefónicos de todo
el edificio en el que vives. Este enorme cable multipar llega hasta la calle y es más fácil conectarlo
como un único cable global que si tuvieras que conectar cada cable que viene de tus vecinos más el
tuyo.
Este concepto es fácilmente trasladable a las comunicaciones WiFi. De hecho, algunos routers Wi
Fi actuales ofrecen más de una antena WiFi. Cada antena podría, por ejemplo, gestionar un enlace Wi
Fi. Todas las comunicaciones se transmitirían utilizando el mismo medio: el aire, que transporta ondas
electromagnéticas.
1 1 1 1
mismo canal
2 2 123 123 2 2
3 3 3 3
La multiplexación por división de frecuencia juega con frecuencias de transmisión y anchos de banda.
[ 228 ]
www.itebooks.info
Machine Translated by Google
Capítulo 6
Imaginemos que las bandas de frecuencia 1, 2 y 3 de la figura son tres servicios diferentes: 1
podría ser voz, 2 podría ser Internet y 3 televisión. La realidad no está muy lejos de esto.
1 1
2 2
mux manifestación
3 3
4 4
paso 1/4
1 1
2 2
mux manifestación
3 3
4 4
paso 2/4
1 1
2 2
mux manifestación
3 3
4 4
paso 3/4
1 1
2 2
mux manifestación
3 3
4 4
paso 4/4
Multiplexación por división de tiempo ilustrada con un ejemplo de un ciclo de cuatro pasos
Este tipo de sistema suele incluir un reloj, que ayuda a establecer el ciclo correcto para cada
participante, de modo que sepa en qué etapa de la comunicación nos encontramos. Es
fundamental preservar la seguridad e integridad de las comunicaciones.
[ 229 ]
www.itebooks.info
Machine Translated by Google
Las comunicaciones en serie funcionan así, y por muchas razones (incluso si crees que las conoces
mucho después de los capítulos anteriores), las analizaremos un poco más en profundidad en el próximo
capítulo.
Veamos cómo podemos trabajar con ocho sensores y una sola entrada analógica para nuestra placa
Arduino.
Utilizado como multiplexor, puedes conectar, digamos, ocho potenciómetros al CD4051B y solo una
entrada analógica de Arduino, y podrás, mediante código, leer los 8 valores.
Si se utiliza como demultiplexor, se pueden escribir ocho salidas analógicas escribiendo desde
un solo pin de Arduino. Hablaremos de eso un poco más adelante en este libro, cuando abordemos el
pin de salida y, especialmente, el truco de modulación por ancho de pulso (PWM) con LED.
Básicamente, no podemos hablar de circuitos integrados sin tener en cuenta su pequeño tamaño, una de
las características más interesantes de los CI.
La otra es lo que yo llamo la abstracción de caja negra. También la defino como las clases similares a la
programación del mundo del hardware. ¿Por qué? Porque no tienes que saber exactamente cómo funciona,
sino solo cómo puedes usarlo. Esto significa que todos los circuitos internos realmente no importan si las
patas externas tienen sentido para tu propio propósito.
[ 230 ]
www.itebooks.info
Machine Translated by Google
Capítulo 6
Los circuitos integrados más utilizados son sin duda los DIP, también llamados de orificio pasante.
Podemos manipularlos y conectarlos fácilmente a una placa de pruebas o a una placa de circuito
impreso (PCB).
Aquí está el frente de este bonito circuito integrado. La hoja de datos es fácil de encontrar en Internet.
Aquí hay una de Texas Instruments:
http://www.ti.com/lit/ds/symlink/cd4051b.pdf
E/S 4 Vdd
E/S 6 Entrada 2
E/S 7 entrada 0
CD4051B
E/S 5 E/S 3
Agua B
Vss do
[ 231 ]
www.itebooks.info
Machine Translated by Google
También hay un pequeño orificio en forma de semicírculo. Cuando colocas el CI con este semicírculo en la
parte superior (como se muestra en la figura anterior), sabes cuál es el pin número 1; el primer pin al lado
del pin número 1 es el pin número 2, y así sucesivamente, hasta el último pin de la columna de la izquierda
que, en nuestro caso, es el pin número 8. Luego, continúa con el pin opuesto al último de la columna de la
izquierda; este es el pin número 9, y el siguiente pin es el pin número 10, y así sucesivamente, hasta la parte
superior de la columna de la derecha.
alfiler 1 alfiler 16
alfiler 2 alfiler 15
alfiler 3 alfiler 14
alfiler 4 alfiler 13
CD4051B
alfiler 5 alfiler 12
alfiler 6 alfiler 11
alfiler 7 alfiler 10
alfiler 8 alfiler 9
Por supuesto, sería demasiado simple si la primera entrada fuera el pin 1. La única forma real de saberlo
con certeza es verificar las especificaciones.
Suministro del IC
Es necesario alimentar el propio CI para activarlo, pero también, en algunos casos, para generar
corriente.
Si elige utilizar el CD4051B como multiplexor, tendrá múltiples entradas analógicas y una salida
común.
[ 232 ]
www.itebooks.info
Machine Translated by Google
Capítulo 6
Por otro lado, si eliges usarlo como demultiplexor, tendrás una entrada común y
múltiples salidas analógicas.
Hay tres pines, llamados A (pin 11), B (pin 10) y C (pin 9), que deben ser controlados por
pines digitales del Arduino. ¿Qué? ¿No estamos en la parte de entradas analógicas?
Totalmente que sí, pero vamos a introducir un nuevo método de control utilizando estos tres
pines seleccionados.
Básicamente, enviamos una señal para que el CD4051B conmute las entradas a la salida
común. Si quisiéramos usarlo como demultiplexor, los tres pines seleccionados tendríamos
que controlarlos exactamente de la misma manera.
En la hoja de datos encontré una tabla de verdad. ¿Qué es eso? Es simplemente una tabla
donde podemos verificar qué combinaciones A, B y C conmutan las entradas a la salida común.
ESTADOS DE ENTRADA
0 0 0 1 1
0 0 1 0 2
0 0 1 1 3
0 1 0 0 4
0 1 0 0 5
0 1 1 0 6
0 1 1 1 7
1 incógnita incógnita incógnita Ninguno
[ 233 ]
www.itebooks.info
Machine Translated by Google
Por supuesto, hay algo bueno en esto. Si lees el número binario correspondiente a las entradas
en C, B y A (en ese orden), tendrás una agradable sorpresa: será equivalente al número decimal del pin de
entrada conmutado por la salida común.
De hecho, 0 0 0 en binario equivale a 0 en decimal. Consulta la tabla para conocer los valores binarios de
los números decimales:
000 0
001 1
010 2
011 3
100 4
101 5
110 6
111 7
El circuito incluye el multiplexor CD4051B con su salida común conectada al pin analógico 0
[ 234 ]
www.itebooks.info
Machine Translated by Google
Capítulo 6
El diagrama eléctrico
Todos los dispositivos que nos gustaría leer con este sistema deben estar conectados a E/S 0, 1, 2,
etc., en el CD4051B.
Teniendo en cuenta lo que sabemos sobre la tabla de verdad y cómo funciona el dispositivo, si
queremos leer secuencialmente todos los pines del 0 al 7, tendremos que hacer un bucle que contenga
ambos tipos de declaraciones:
[ 235 ]
www.itebooks.info
Machine Translated by Google
int currentInput = 0 ; // mantiene la entrada analógica actual conmutada a la salida común del CD4051B
configuración vacía() {
Serie.begin(9600);
// configurando los 3 pines digitales relacionados con los selectores A, B y C como salidas
pinMode(controlPinA, SALIDA);
pinMode(controlPinB, SALIDA);
pinMode(controlPinC, SALIDA);
}
bucle vacío(){
para (entradaActual = 0; entradaActual < númeroDeDispositivos 1;
entrada actual++)
{
//seleccionando las entradas que se conmutan a la salida común de
El CD4051B
digitalWrite(controlPinA, bitRead(entradaActual,0));
digitalWrite(controlPinB, bitRead(entradaActual,1));
digitalWrite(controlPinC, bitRead(entradaActual,2));
[ 236 ]
www.itebooks.info
Machine Translated by Google
Capítulo 6
Después de haber definido todas las variables, configuramos el puerto serial en setup() y también los
tres pines relacionados con el pin selector del CD4051B como salidas. Luego, en cada ciclo, primero
selecciono la entrada conmutada ya sea impulsando la corriente o no a los pines A, B y C del CD4051B.
Estoy usando una función anidada en mi declaración para
Guarda algunas filas.
bitRead(number,n) es una nueva función capaz de devolver el bit n de un número. Es la función perfecta
para nuestro caso.
Al escribir esos bits en los pines A, B y C del dispositivo CD4051B, selecciona la entrada analógica en
cada vuelta y muestra el valor leído en el puerto serial para su posterior procesamiento en Processing o
Max 6 o cualquier software que desee utilizar.
Resumen
En este capítulo, aprendimos al menos cómo abordar un entorno de marco gráfico muy poderoso
llamado Max 6. Lo usaremos en varios ejemplos adicionales en este libro a medida que sigamos
usando Processing también.
Aprendimos algunos reflejos para cuando queremos manejar sensores que proporcionen variaciones
continuas de voltaje a nuestras entradas analógicas de Arduino.
[ 237 ]
www.itebooks.info
Machine Translated by Google
www.itebooks.info
Machine Translated by Google
Al igual que con muchos otros conceptos de este libro, ya hemos utilizado la comunicación serial y el
protocolo serial subyacente un par de veces como una herramienta de caja negra, es decir, una
herramienta que he presentado pero no explicado.
En este pequeño capítulo nos adentraremos en este tema. Descubriremos que la comunicación
serial se utiliza no solo para la comunicación entre máquinas y humanos, sino también para las
conversaciones "componente a componente" dentro de las máquinas. Cuando digo componentes,
me refiero a sistemas pequeños, y podría utilizar el término periférico para describirlos.
Comunicación en serie
Normalmente, la comunicación en serie en informática y telecomunicaciones es un tipo de comunicación
en el que los datos se envían bit a bit a través de un bus de comunicación.
Hoy en día, podemos ver comunicaciones seriales a nuestro alrededor y, a menudo, ni siquiera
nos damos cuenta de ello. La "S" en el acrónimo USB significa Serial (USB significa Universal
Serial Bus) y representa el bus de comunicación serial subyacente que utilizan todos los protocolos
superiores.
www.itebooks.info
Machine Translated by Google
Canales paralelos
0 0
1 1
1 1
0 0 oyente
vocero
0 0
0 0
1 1
1 1
Desde las comunicaciones de corta distancia hasta las de larga distancia, incluso si el
enfoque paralelo parece más rápido a primera vista porque se envía más de un
bit de datos al mismo tiempo durante un ciclo de reloj, la comunicación en serie ha superado
progresivamente a otras formas de comunicación.
La primera razón es la cantidad de cables que se utilizan. Por ejemplo, el método paralelo que se utiliza
en nuestro pequeño ejemplo requiere ocho canales para manejar nuestros ocho bits de datos al mismo
tiempo, mientras que el método serial requiere solo uno. Hablaremos de qué es un canal muy pronto,
pero con un solo cable, la relación 1:8 nos ahorraría dinero si utilizáramos la comunicación serial.
[ 240 ]
www.itebooks.info
Machine Translated by Google
Capítulo 7
La segunda razón principal es que finalmente hemos logrado que la comunicación serial sea muy
rápida. Esto se ha logrado gracias a lo siguiente:
• En primer lugar, el tiempo de propagación es más fácil de manejar con un número menor de cables.
• En segundo lugar, la diafonía es menor con menos canales que con una mayor densidad de
canales como los que se encuentran en los enlaces paralelos
• En tercer lugar, debido a que hay menos cables involucrados, podemos ahorrar espacio (y dinero) y,
a menudo, utilizar este espacio ahorrado para proteger mejor nuestros cables.
En la actualidad, los anchos de banda de las comunicaciones en serie varían desde varios megabits por segundo
hasta más de un terabit por segundo (lo que significa 1000 gigabits por segundo), y se pueden utilizar muchos
medios, desde fibras ópticas hasta sistemas inalámbricos, y desde cables de cobre hasta fibras ópticas. Como
puede sospechar, se utilizan muchos protocolos en serie.
Sincrónico o asincrónico
La comunicación en serie puede ser sincrónica o no.
La comunicación sincrónica implica la existencia de un reloj, al que podemos llamar reloj maestro, que lleva
un tiempo de referencia para todos los participantes de la comunicación. El primer ejemplo que me viene a la
mente es la comunicación telefónica.
La comunicación asincrónica no requiere que los datos del reloj se envíen a través de los canales seriales;
esto facilita la comunicación, pero a veces puede generar algunos problemas de comprensión. El correo
electrónico y los mensajes de texto son tipos de comunicación asincrónica.
Modo dúplex
El modo dúplex es una característica particular de un canal de comunicación. Puede ser:
• Simplex: Unidireccional solamente (los datos pasan sólo en una dirección, entre
dos puntos)
[ 241 ]
www.itebooks.info
Machine Translated by Google
Obviamente, el halfduplex es más útil que el simplex, pero debe ejecutar un proceso de detección
de colisiones y retransmisión. De hecho, cuando estás hablando con tu amigo, también estás
compartiendo el mismo medio (la habitación y el aire dentro de la habitación que lleva las vibraciones
desde tu boca hasta sus oídos), y si estás hablando al mismo tiempo, generalmente uno de ellos
lo comprueba, se detiene y le dice al otro que repita.
El modo fullduplex requiere más canales. De esa manera, no se producen colisiones y se pueden omitir
todos los procesos de detección y retransmisión de colisiones. La detección de otros errores y su
reparación siguen siendo necesarias, pero normalmente es mucho más fácil.
Peering y bus
En un sistema de peering , los hablantes están conectados con los oyentes ya sea física o lógicamente.
No hay maestro y este tipo de interfaces suelen ser asincrónicas.
Bus de control
Dirección de bus
Bus de datos
Hay muchas soluciones que se pueden implementar para resolver estos problemas, como utilizar
múltiples tipos de enlaces físicos y protocolos de comunicación preexistentes específicos.
Veamos algunos de ellos, y especialmente aquellos que podemos utilizar con Arduino, por supuesto.
[ 242 ]
www.itebooks.info
Machine Translated by Google
Capítulo 7
Codificación de datos
Los aspectos más importantes a definir cuando utilizamos protocolos seriales para nuestra
comunicación son los siguientes:
• Si hay un bit de paridad presente o no (define la solución basada en código y con detección de
errores más simple)
En la primera figura de este capítulo, envié ocho bits de datos por el canal. Esto equivale a 1 byte.
No voy a describir el bit de paridad en su totalidad, pero debes saber que es básicamente una suma
de comprobación. Usando este concepto, transmitimos una palabra y una suma de comprobación,
después de lo cual verificamos la suma binaria de todos los bits en mi palabra recibida. De esta
manera, el oyente puede verificar la integridad de las palabras que se recibieron con bastante
facilidad, pero de una manera muy primitiva. Puede ocurrir un error, pero esta es la forma más barata;
puede evitar muchos errores y es estadísticamente correcta.
Una trama global de datos con la comunicación serial tipo 8N1 contiene 10 bits:
• Un bit de inicio
• Un bit de parada
De hecho, solo el 80 por ciento de los datos enviados son la carga útil real. Siempre intentamos reducir
la cantidad de datos de control de flujo que se envían porque puede ahorrar ancho de banda y, en
última instancia, tiempo.
[ 243 ]
www.itebooks.info
Machine Translated by Google
Debo decir que Samuel FB Morse no solo fue un inventor, sino también un artista y pintor
consumado. Es importante mencionarlo aquí porque estoy realmente convencido de que el arte y la
tecnología son finalmente una misma cosa que solíamos ver desde dos puntos de vista diferentes.
Podría citar a más artistas/inventores, pero supongo que me desviaría un poco del tema.
Al enviar pulsos largos y cortos separados por espacios en blanco, los operadores de Morse pueden
enviar palabras, oraciones e información. Esto puede suceder a través de múltiples tipos de medios,
como:
Hay algunas reglas sobre la duración de los pulsos, que van desde largos a cortos o en blanco,
pero esto sigue siendo asincrónico porque en realidad no hay un reloj compartido entre ambos
participantes.
El famoso RS232
RS232 es una interfaz común que encontrará en todas las computadoras personales. Define
un estándar completo para las características eléctricas y físicas (y eléctricas y mecánicas), como el
hardware de conexión, los pines y los nombres de las señales. RS232 se introdujo en 1962 y todavía
se usa ampliamente. Esta interfaz punto a punto puede transmitir datos a una velocidad de hasta 20
Kbps (kilobits por segundo = 20 000 bits por segundo) para distancias moderadas. Aunque no
se especifica en el estándar, generalmente encontraremos casos en los que la velocidad es
mayor a 115,2 Kbps en cables cortos y blindados.
Yo mismo utilizo cables de 20 metros de longitud con sensores que transmiten sus datos por serial
a Arduino para distintas instalaciones. Algunos amigos utilizan cables de 50 metros de longitud, pero
yo no lo hago y prefiero otras soluciones como Ethernet.
[ 244 ]
www.itebooks.info
Machine Translated by Google
Capítulo 7
De 25 cables a 3
Si el estándar define un conector y enlace de 25 pines, podemos reducir esta enorme cantidad necesaria
para el control de flujo de hardware múltiple, detección de errores y más a solo tres cables:
Pero, ¿cómo podemos omitir una gran cantidad de cables/señales y mantener el buen
funcionamiento de la comunicación serial? Básicamente, como sucede con muchos estándares,
se ha diseñado para adaptarse a muchos casos de uso. Por ejemplo, en la versión completa de
DB25, hay pines 8 y 22 que están dedicados a líneas telefónicas: el primero es el Data Carrier
Detect y el segundo es el Ring Indicator. La señal enviada a través de los pines 4 y 5 se utiliza para un
protocolo de enlace entre los participantes.
El conector DB25
[ 245 ]
www.itebooks.info
Machine Translated by Google
El conector DB9
Nuestro preciado Arduino ofrece esta alternativa serial de tres cables. Por supuesto, cada tipo de placa
no ofrece la misma cantidad de interfaces seriales, pero el principio sigue siendo el mismo: está disponible
una interfaz serial basada en tres cables.
Arduino Uno y Leonardo proporcionan los tres cables TX, RX y tierra, mientras que los recién
lanzados Arduino Mega 2560 y Arduino Due (http://arduino.cc/en/
Main/ArduinoBoardDue) proporciona cuatro nombres de interfaz de comunicación serial
diferentes, desde RX0 y TX0 hasta RX3 y TX3.
Vamos a describir otro tipo de estándar de interfaz serial y volveremos a RS232 con el famoso
circuito integrado fabricado por FTDI que proporciona una forma muy eficiente de convertir
RS232 a USB.
El elegante I2C
El bus de computadora serial de un solo extremo multimaster I2C ha sido diseñado por Philips y
requiere una licencia para cualquier implementación de hardware.
Una de sus ventajas es el hecho de que utiliza sólo dos cables: SDA (Serial Data Line)
con un sistema de direccionamiento de 7 bits y SCL (Serial Clock Line).
Esta interfaz es realmente buena teniendo en cuenta su sistema de direccionamiento. Para poder
utilizarla, tenemos que construir el bus de dos cables de Arduino, que es el maestro aquí.
[ 246 ]
www.itebooks.info
Machine Translated by Google
Capítulo 7
Para saber qué pines se deben utilizar para cada placa Arduino, puedes consultar directamente
la información en http://www.arduino.cc/en/Reference/Wire.
ParpadeoM Los módulos (http://thingm.com/products/blinkm) son módulos LED RGB con un formato
pequeño que son bastante fáciles de manipular en buses I2C. También los usé mucho para controlar
más o menos grandes LCD con Arduino.
Esta es también la página de la biblioteca Wire para Arduino. Actualmente, esta biblioteca está
incluida con el núcleo de Arduino. Considerando la complejidad del estándar, el costo aumenta cuando
tienes muchos elementos en los buses. Debido a sus dos cables y la precisión de la integridad de los
datos, esta sigue siendo una solución elegante para la comunicación intermitente y de corta distancia
dentro de la misma caja. La interfaz de dos cables (TWI)
Es básicamente el mismo estándar que I2C. Se conocía con otro nombre cuando las patentes de
I2C todavía estaban vigentes.
I2C ha sido la base de muchos otros protocolos de interfaz, como VESA DDC (un enlace digital
entre pantallas y tarjetas gráficas), SMBus de Intel y algunos otros.
El SPI sincrónico
SPI son las siglas de Serial Peripheral Interface, que fue desarrollado por Motorola y utiliza los siguientes
cuatro cables:
[ 247 ]
www.itebooks.info
Machine Translated by Google
Es muy útil en la comunicación punto a punto donde sólo hay un maestro y un esclavo, incluso si
encontramos muchas aplicaciones con más de un esclavo en el bus SPI.
Dado que SPI es una interfaz basada en modos y fullduplex, podemos lograr velocidades de datos
más altas que con I2C. A menudo se utiliza para la comunicación entre un codificador/decodificador y un
procesador de señales digitales; esta comunicación consiste en enviar muestras hacia dentro y hacia
fuera al mismo tiempo. El hecho de que SPI no tenga direccionamiento de dispositivos también es una gran
ventaja, ya que lo hace mucho más liviano y, por lo tanto, más rápido en caso de que no necesite esta
función. De hecho, I2C y SPI son realmente complementarios entre sí, dependiendo de lo que
desee lograr.
Hay información disponible en línea sobre SPI en las placas Arduino (http://
arduino.cc/es/Referencia/SPI), pero debes saber que podemos usar fácilmente cualquier pin digital como
uno de los cuatro cables incluidos en SPI.
El USB omnipresente
USB es el estándar Universal Serial Bus. Probablemente sea el que más utilizas.
La principal ventaja de este estándar es la función Plug and Play de los dispositivos USB.
Puede conectar y desconectar dispositivos sin reiniciar el ordenador.
El USB ha sido diseñado para estandarizar la conexión de una amplia variedad de periféricos de
computadora, incluidos los siguientes:
• Inalámbrico (infrarrojos)
[ 248 ]
www.itebooks.info
Machine Translated by Google
Capítulo 7
Y hay muchos más tipos. El estándar es la versión 3.0. Un bus USB puede contener hasta 127
periféricos y puede suministrar un máximo de 500 a 900 mA para dispositivos generales.
Los concentradores USB se pueden incluir en los niveles, lo que permite la ramificación hasta en cinco niveles. Esto da
como resultado una topología de árbol. Por eso es posible apilar concentradores sobre concentradores.
Las clases de dispositivos proporcionan una forma de tener un host adaptable e independiente del
dispositivo para admitir nuevos dispositivos. Un ID que el host puede reconocer define cada clase.
Puede encontrar todas las clases aprobadas en http://www.usb.org/developers/devclass en el sitio web
oficial del estándar USB.
• Vcc (+5 V)
• Datos
• Datos+
• Suelo
+ D
D+ D +
12
4321 43
D+
Norma A Norma B
Los cables están blindados y su longitud máxima habitual es de entre dos y cinco metros.
Ya he utilizado un cable de 12 metros para el puerto USB. Funcionó perfectamente con un
cable que yo mismo soldé en un entorno electromagnético seguro, es decir, en un lugar
donde mi cable estaba solo detrás de una pared y no mezclado con muchos otros cables,
especialmente los que suministran energía.
[ 249 ]
www.itebooks.info
Machine Translated by Google
Hay otros tipos de enchufes que son algo más grandes, pero el requisito de tener al menos cuatro cables sigue
siendo el mismo.
Esto proporciona la función de suministro de energía básica para una computadora o los concentradores
conectados a una computadora, y también se utiliza para la comunicación.
El circuito integrado FTDI EEPROM denominado FT232 proporciona una forma de convertir USB en una
interfaz RS232. Por eso podemos utilizar la comunicación serial
Características de las placas Arduino a través de USB sin necesidad de un puerto serie externo.
Interfaz de puerto de los pines de Arduino relacionados con la comunicación serial, que son TX y
RX. Las nuevas placas incluyen un Atmega16U2 que brinda funciones de comunicación
serial.
De hecho, tan pronto como conectes tu placa Arduino a un ordenador, tendrás disponible una función de
comunicación en serie. Ya la hemos utilizado con:
Supongo que también recuerdas que no pudimos usar el Monitor serial mientras usábamos la función de sondeo
de objetos seriales de Max 6.
¿Entiendes por qué ahora? Solo puede haber un enlace punto a punto activo al mismo tiempo en los cables y
en el mundo virtual de las computadoras. Lo mismo ocurre con los enlaces físicos. Te advertí que no usaras
los pines digitales 0 y 1 tan pronto como necesitaras usar la comunicación en serie con la placa Arduino,
especialmente la versión Diecimilla.
Estos pines están conectados directamente a los pines RX y TX correspondientes del chip serial FTDI USB a
TTL.
[ 250 ]
www.itebooks.info
Machine Translated by Google
Capítulo 7
Resumen
En este capítulo, hablamos sobre la comunicación serial. Se trata de un modo de comunicación
muy común tanto dentro como entre dispositivos electrónicos. Este capítulo también es una
buena introducción a otros protocolos de comunicación en general y estoy seguro de que ahora
está listo para comprender funciones más avanzadas.
En el próximo capítulo, utilizaremos algunos de los diferentes tipos de protocolos seriales que
se presentaron aquí. En particular, vamos a hablar sobre las salidas de Arduino; esto
significa que no solo podremos agregar retroalimentación y reacciones a nuestras placas
Arduino, considerando diseños de patrones de comportamiento como estímulo y respuesta
para formas deterministas, sino que también veremos comportamientos más caóticos
como aquellos que incluyen el azar restringido, por ejemplo.
[ 251 ]
www.itebooks.info
Machine Translated by Google
www.itebooks.info
Machine Translated by Google
Diseño visual
Retroalimentación de salida
La interacción tiene que ver con el control y la retroalimentación. Usted controla un sistema al realizar
acciones sobre él. Incluso puede modificarlo. El sistema le brinda retroalimentación al proporcionarle información
útil sobre lo que hace cuando lo modifica.
En el capítulo anterior, aprendimos más sobre cómo nosotros controlamos Arduino que sobre cómo
Arduino nos da retroalimentación. Por ejemplo, usamos botones y perillas para enviar datos a Arduino, lo que
hace que trabaje para nosotros. Por supuesto, hay muchos puntos de vista y podemos considerar fácilmente
cómo controlar un LED y dar retroalimentación a Arduino. Pero, por lo general, hablamos de retroalimentación
cuando queremos calificar un retorno de información del sistema hacia nosotros.
"Información sobre la brecha entre el nivel real y el nivel de referencia de un parámetro del
sistema que se utiliza para alterar la brecha de alguna manera".
Ya hablamos de algunos resultados visuales en el Capítulo 5, Detección de entradas digitales, cuando intentamos
visualizar el resultado de nuestros eventos de pulsación de botones. Esta representación visual resultante
de nuestros eventos de pulsación fue la retroalimentación.
Ahora vamos a hablar del diseño de sistemas de feedback visual basados especialmente en LEDs
controlados por la placa Arduino. Los LEDs son los sistemas más sencillos con los que proporcionar
feedback visual desde Arduino.
www.itebooks.info
Machine Translated by Google
Uso de LED
Los LED pueden ser monocromáticos o policromáticos. De hecho, existen muchos tipos de LED. Antes
de ver algunos ejemplos, descubramos algunos de estos tipos de LED.
• LED básicos
• AMOLED (Active Matrix OLED proporciona una alta densidad de píxeles para grandes
tamaño de pantalla)
[ 254 ]
www.itebooks.info
Machine Translated by Google
Capítulo 8
Aquí sólo hablaremos de LED básicos. Con el término "básico" me refiero a un LED con componentes
discretos como el de la imagen anterior.
El paquete puede variar desde componentes de dos patas con una lente moldeada similar a epoxi en la parte
superior, hasta componentes de superficie que proporcionan muchos conectores, como se muestra en la
siguiente captura de pantalla:
También podemos clasificarlos, según las características del color de su luz, en:
• LED monocromáticos
• LED policromáticos
En cada caso, el color visible de un LED viene dado por el color de la tapa de epoxi moldeada; el LED en sí
emite la misma longitud de onda.
LED monocromáticos
Los LED monocromáticos emiten un solo color.
Los LED monocromáticos más habituales emiten colores constantes en cada necesidad de voltaje.
LED policromáticos
Los LED policromáticos pueden emitir más de un color, dependiendo de varios parámetros como el voltaje pero
también dependiendo de la pata alimentada con corriente en el caso de un LED con más de una pata.
La característica más importante aquí es la controlabilidad. Los LED policromáticos deben ser fácilmente
controlables. Esto significa que debemos poder controlar cada color encendiéndolo o apagándolo.
[ 255 ]
www.itebooks.info
Machine Translated by Google
Aquí hay un LED RGB clásico con cátodo común y tres ánodos diferentes:
Este tipo de LED es el indicado para nuestros equipos Arduino. No son caros (alrededor de 1,2
euros por 100 LED), teniendo en cuenta que podemos controlarlos fácilmente y producir una
gama de colores muy amplia con ellos.
En las siguientes páginas vamos a entender cómo podemos trabajar con LED múltiples y
también con LED RGB policromáticos.
[ 256 ]
www.itebooks.info
Machine Translated by Google
Capítulo 8
void setup()
{ pinMode(ledPin, SALIDA); salida // inicializa el pin digital como un
Intuitivamente, en los siguientes ejemplos vamos a intentar utilizar más de un LED, jugando tanto
con LED monocromáticos como policromáticos.
[ 257 ]
www.itebooks.info
Machine Translated by Google
[ 258 ]
www.itebooks.info
Machine Translated by Google
Capítulo 8
Como sabéis, los pines digitales de Arduino se pueden utilizar como entradas o salidas. Vemos
que hay dos interruptores conectados por un lado a un pin de 5 V de Arduino y por el otro a
los pines digitales 2 y 3, con una resistencia pulldown relacionada con cada uno de estos
últimos pines, que conduce la corriente al pin de tierra de Arduino.
También podemos ver que un LED está conectado cada uno al pin digital 8 y 9 en un lado; ambos
están conectados al pin de tierra de Arduino.
Antes de diseñar un firmware dedicado, es necesario cubrir brevemente algo muy importante:
el acoplamiento. Es imprescindible saberlo para cualquier diseño de interfaz; en general, para
el diseño de interacción.
[ 259 ]
www.itebooks.info
Machine Translated by Google
Sea cual sea el tipo de sistema externo, desde el punto de vista de Arduino suele considerarse
humano. En cuanto quieras diseñar un sistema de interacción, tendrás que lidiar con eso.
Podemos resumir este concepto con un esquema muy simple para fijar las cosas en la mente.
De hecho, hay que entender que el firmware que estamos a punto de diseñar creará un acoplamiento
controlretroalimentación.
Pero, imagina que quieres controlar otro sistema con Arduino. En ese caso, es posible que quieras
realizar el acoplamiento fuera del propio Arduino.
[ 260 ]
www.itebooks.info
Machine Translated by Google
Capítulo 8
Vea la segunda figura SISTEMA EXTERNO 2, donde coloco el acoplamiento fuera de Arduino.
Normalmente, SISTEMA EXTERNO 1 somos nosotros y SISTEMA EXTERNO 2 es un ordenador:
Ahora podemos citar un ejemplo de la vida real. Como muchos usuarios de interfaces y controladores
remotos, me gusta y necesito controlar software complejo en mi computadora con dispositivos de
hardware minimalistas.
Me gusta la interfaz minimalista y de código abierto de Monome (http://monome.org) diseñada por Brian
Crabtree. La usé mucho y todavía la uso a veces. Es básicamente una matriz de LED y botones. El truco
sorprendente es que NO hay acoplamiento dentro del engranaje.
La imagen anterior es de Monome 256 de Brian Crabtree y su estuche de madera muy bien hecho.
[ 261 ]
www.itebooks.info
Machine Translated by Google
Si no está escrito directamente así en todos los documentos, me gustaría definirlo para mis amigos
y estudiantes de esta manera: "El concepto de Monome es la interfaz más minimalista que
necesitarás porque solo proporciona una forma de controlar los LED; además de eso, tienes
muchos botones, pero no hay enlaces lógicos o físicos entre los botones y los LED".
Si Monome no proporciona un acoplamiento real, ya realizado, entre botones y LED es porque sería muy
restrictivo e incluso eliminaría toda la creatividad.
Esta breve digresión no estaría completa sin otro esquema sobre el Monome.
[ 262 ]
www.itebooks.info
Machine Translated by Google
Capítulo 8
Aquí se muestra un esquema de la interfaz Monome 64, en la configuración habitual basada en computadora
dentro de la cual se produce el acoplamiento. Esta es la configuración real que utilicé en el escenario para
una presentación musical muchas veces ( https://vimeo.com/20110773).
Este es un sistema muy poderoso que controla cosas y proporciona retroalimentación con la que
básicamente puedes construir tu acoplamiento desde cero y transformar tu interfaz cruda y minimalista en lo
que necesites.
Esta fue una pequeña parte de un monólogo más global sobre el diseño de interacción.
Construyamos este firmware de acoplamiento ahora mismo y veamos cómo podemos acoplar controles y
retroalimentación en un código de muestra básico.
El firmware de acoplamiento
Aquí solo utilizamos interruptores y LED de Arduino y en realidad no utilizamos ninguna computadora.
•
Si presiono el interruptor 1, el LED 1 se enciende, y si lo suelto, el LED 1 se apaga.
•
Si presiono el interruptor 2, el LED 2 se enciende, y si lo suelto, el LED 2 se enciende.
Apagado
Para manipular nuevos elementos e ideas, vamos a utilizar una biblioteca llamada Bounce. Proporciona una
forma sencilla de anular el rebote de las entradas de pines digitales. Ya hablamos sobre el anular el rebote
en la sección Comprender el concepto de anular el rebote del Capítulo 5, Detección de entradas
digitales. Recordaremos un poco esto: si ningún botón absorbe el rebote por completo cuando lo presionas,
podemos suavizarlo y filtrar los saltos de valores bruscos no deseados mediante el uso de software.
[ 263 ]
www.itebooks.info
Machine Translated by Google
configuración vacía() {
pinMode(BUTTON01, INPUT); // el pin 2 del interruptor está configurado como una entrada
pinMode(BUTTON02, INPUT); // el pin 3 del interruptor está configurado como una entrada
pinMode(LED01, OUTPUT); // el pin 8 del interruptor está configurado como salida pinMode(LED02,
OUTPUT); // el pin 9 del interruptor está configurado como salida
}
bucle vacío(){
Este código incluye el archivo de encabezado Bounce, es decir, la biblioteca Bounce, al principio.
Luego definí cuatro constantes según los pines de entrada y salida digitales, donde colocamos interruptores y
LED en el circuito.
La biblioteca Bounce requiere crear una instancia de cada debouncer, de la siguiente manera:
[ 264 ]
www.itebooks.info
Machine Translated by Google
Capítulo 8
Elegí un tiempo de rebote de 7 ms. Esto significa que, si recuerdas correctamente, el sistema no tendrá
en cuenta dos cambios de valores que se produzcan (voluntaria o involuntariamente) muy rápido en un
intervalo de tiempo inferior a 7 ms, lo que evitará rebotes extraños y extraños.
El bloque setup() no es realmente difícil, solo define pines digitales como entradas para botones y
salidas para LED (recuerde que los pines digitales pueden ser ambos y que debe elegir en algún momento).
loop() comienza con la actualización de ambos antirrebote, después de lo cual leemos el valor
del estado de cada botón antirrebote.
Por último, manejamos los controles LED, dependiendo del estado de los botones. ¿Dónde ocurre el
acoplamiento? Por supuesto, en este último paso. Acoplamos nuestro control (botones presionados) a
nuestra retroalimentación (luces LED) en ese firmware. Vamos a cargarlo y probarlo.
¿Más LED?
Básicamente, acabamos de ver cómo conectar más de un LED a nuestro Arduino. Por supuesto, podríamos
hacer lo mismo con más de dos LED. Puedes encontrar el código que maneja seis LED y seis
interruptores en la carpeta Chapter05/feedbacks_6x6/ .
Pero bueno, tengo una pregunta para ti: ¿cómo manejarías más LED con un Arduino Uno? Por favor,
no me respondas diciendo "me compraré un Arduino MEGA" porque entonces te preguntaría cómo
manejarías más de 50 LED.
Multiplexación de LED
El concepto de multiplexación es interesante y eficaz. Es la clave para tener un montón de periféricos
conectados a nuestras placas Arduino.
La multiplexación permite utilizar pocos pines de E/S en la placa y al mismo tiempo utilizar muchos
componentes externos. El vínculo entre Arduino y estos componentes externos se realiza mediante un
multiplexor/demultiplexor (también conocido como mux/demux).
Aquí vamos a utilizar el componente 74HC595. Su hoja de datos se puede encontrar en http://
www.nxp.com/documents/data_sheet/74HC_HCT595.pdf.
Este componente es un dispositivo de entrada serial/salida serial o paralela de 8 bits. Esto significa
que se controla a través de una interfaz serial, básicamente usando tres pines con Arduino y puede
funcionar con ocho de sus pines.
[ 265 ]
www.itebooks.info
Machine Translated by Google
Voy a mostrarte cómo puedes controlar ocho LED con solo tres pines de tu Arduino.
Dado que Arduino Uno contiene 12 pines digitales utilizables (no estoy usando 0 y 1, como
es habitual), podemos imaginar fácilmente el uso de 4 x 75HC595 para controlar 4 x 8 =
32 LED monocromáticos con este sistema. También te proporcionaré el código para hacerlo.
Tenemos el Arduino suministrando energía a la placa de pruebas. Cada resistencia proporciona 220 ohmios.
Básicamente, el 74HC595 debe conectarse a través de los pines 11, 12 y 14 para poder ser
controlado por un protocolo serial manejado aquí por Arduino.
[ 266 ]
www.itebooks.info
Machine Translated by Google
Capítulo 8
• El pin 10 se llama Master Reset y para activarlo hay que conectarlo a tierra, por eso en estados de funcionamiento
normales lo llevamos a 5 V.
• El pin 13 es el pin de entrada de habilitación de salida y debe mantenerse activo para que todo
el dispositivo genere corriente. Para ello, conectándolo a tierra.
• El pin 12 es la entrada del reloj del registro de almacenamiento, también llamado Latch.
Nuestro pequeño y económico enlace serial al Arduino, manejado por los pines 11, 12 y 14, proporciona una manera
fácil de controlar y básicamente cargar ocho bits en el dispositivo. Podemos recorrer los ocho bits y enviarlos
serialmente al dispositivo que los almacena en sus registros.
Este tipo de dispositivos generalmente se denominan registros de desplazamiento: desplazamos bits de 0 a 7 mientras
los cargamos.
[ 267 ]
www.itebooks.info
Machine Translated by Google
Luego, cada estado se envía a la salida correcta de Q0 a Q7, transponiendo los estados
transmitidos previamente en serie.
Una matriz de ocho LED con resistencias conectadas al registro de desplazamiento 74HC595
Como quiero enseñarte cada vez un poco más que el contenido exacto que evoca el título de
cada capítulo, he creado para ti una máquina de groove aleatoria muy económica y pequeña.
Su finalidad es generar bytes aleatorios. Estos bytes se enviarán luego al registro de
desplazamiento para alimentar o no cada LED. Así tendrás un patrón aleatorio ordenado de LED.
[ 268 ]
www.itebooks.info
Machine Translated by Google
Capítulo 8
Vamos a comprobarlo:
// 595 pin de entrada de datos en serie que se conecta al pin 2 int DATA_595
= 2;
configuración vacía() {
// utiliza una semilla proveniente del ruido electrónico del ADC randomSeed(analogRead(0));
bucle vacío(){
bitWrite(estados_LED, i, aleatorio(2));
}
// Coloque el pin del pestillo en BAJO (tierra) mientras transmite datos a 595 digitalWrite(LATCH_595,
LOW);
// Desplazamiento de bits, es decir, uso de bytes aleatorios para los estados de los LED
shiftOut(DATA_595, CLOCK_595, MSBFIRST, LED_states);
// Coloque el pin del pestillo en ALTO (5 V) y todos los datos se envían a las salidas
digitalWrite(LATCH_595, HIGH);
[ 269 ]
www.itebooks.info
Machine Translated by Google
// cada 5000 ejecuciones de loop(), toma una nueva semilla para la función aleatoria
{
semillaAleatoria(lectura analógica(0)); // lee un nuevo valor del pin analógico
0
contador = 0; // reiniciar el contador
}
Primero defino los tres pines del registro de desplazamiento 595. Luego, configuro cada uno de
ellos como salida en el bloque setup() .
• Pasador de cierre BAJO = "Hola, vamos a guardar lo que estoy a punto de enviarte".
• Latchpin HIGH = "Ok, ahora usa los datos que acabo de enviar para conmutar a tus
salidas o no".
Luego, tenemos esta función shiftOut(). Esta función proporciona una manera sencilla de enviar
datos en paquetes de bytes completos a un pin específico (el pin de datos) utilizando una velocidad
de reloj/frecuencia específica en un pin particular (el pin de reloj) y dado un orden de
transmisión (MSBFIRST o LSBFIRST).
Aunque no vamos a describir los detalles aquí, es necesario comprender el concepto de MSB y LSB.
[ 270 ]
www.itebooks.info
Machine Translated by Google
Capítulo 8
Consideremos un byte: 1 0 1 0 0 1 1 0.
MSB es la abreviatura de Most Significant Bit (bit más significativo ) . Este bit se encuentra en la
posición más a la izquierda (la del bit que tiene el mayor valor). Aquí, su valor es 1.
El bit menos significativo (LSB) es el bit que se encuentra en la posición más a la derecha (el bit de
menor valor). Es el bit que se encuentra más a la derecha (el bit que tiene el menor valor). Aquí, su
valor es 0.
Para una semilla particular, un generador de números pseudoaleatorios genera las mismas secuencias
de números cada vez que se generan las mismas secuencias de números.
Pero podemos usar un truco aquí para perturbar un poco más el determinismo.
Imagina que haces que la semilla varíe a veces. También puedes introducir un factor externo de
aleatoriedad en tu sistema. Como ya explicamos antes en este libro, siempre hay algún ruido electrónico
que va y viene del ADC incluso si no hay nada conectado a las entradas analógicas. Puedes usar
ese ruido externo/físico leyendo la entrada analógica 0, por ejemplo.
Como ya sabemos bien, la función analógica analogRead() proporciona un número entre 0 y 1023. Esta es
una resolución enorme para nuestro propósito aquí.
Definí una variable de contador y un byte. Primero leo el valor que proviene del ADC para el pin
analógico 0 en setup() . Luego, genero un byte aleatorio con un bucle for() y la función bitWrite() .
[ 271 ]
www.itebooks.info
Machine Translated by Google
Estoy escribiendo cada bit del byte LED_states usando números generados por la función de
número random(2) , que da 0 o 1, aleatoriamente. Luego, uso el byte generado pseudoaleatorio en la
estructura descrita anteriormente.
Estoy redefiniendo cada ejecución del bucle 5000() de la semilla leyendo el ADC para el pin analógico
0.
Podemos utilizar muchos registros de desplazamiento 74HC595 para el manejo de LED, pero imaginemos que
necesitamos ahorrar algunos pines digitales más. Bien, hemos visto que podemos ahorrar mucho utilizando
registros de desplazamiento. Un registro de desplazamiento requiere tres pines digitales y controla ocho LED.
Esto significa que ahorramos cinco pines con cada registro de desplazamiento, considerando que conectamos ocho LED.
¿Qué pasa si necesitas MUCHO más? ¿Qué pasa si necesitas guardar todos los demás pines
para manejar interruptores, por ejemplo?
De hecho, como ya entendemos un poco más sobre cómo funcionan los registros de desplazamiento,
podríamos tener la idea de extender esto a múltiples registros de desplazamiento conectados entre
sí, ¿no es así?
Te voy a mostrar cómo hacer esto usando la librería ShiftOutX de Juan Hernández. Tuve
muy buenos resultados con la versión 1.0 y te aconsejo que
usa este
[ 272 ]
www.itebooks.info
Machine Translated by Google
Capítulo 8
El reloj serial, el latch y los datos son los puntos de información necesarios que deben transmitirse a lo
largo de la cadena del dispositivo. Veamos un esquema:
Dos registros de desplazamiento conectados en cadena que controlan 16 LED monocromáticos con solo tres pines digitales en Arduino
Utilicé los mismos colores que en el circuito anterior para el reloj (azul), el pestillo (verde) y los datos en
serie (naranja).
El reloj y el pestillo en serie se comparten entre los registros de desplazamiento. El comando/orden que
llega desde Arduino para sincronizar la comunicación en serie con el reloj y para indicar a los registros de
desplazamiento que almacenen o apliquen los datos recibidos a su salida tiene que ser coherente.
Los datos seriales que llegan desde Arduino primero pasan al primer registro de desplazamiento,
que envía los datos seriales al segundo. Este es el núcleo del concepto de encadenamiento.
[ 273 ]
www.itebooks.info
Machine Translated by Google
Diagrama de circuito de dos registros de desplazamiento conectados en cadena que controlan 16 LED monocromáticos
Firmware que maneja dos registros de desplazamiento y 16 LED El firmware incluye la biblioteca
ShiftOutX ShiftOutX como se escribió anteriormente. Proporciona un manejo muy fácil y fluido para la
conexión en cadena de registros de desplazamiento.
#include <ShiftOutX.h>
#include <NúmeroDePinDeMayús.h>
[ 274 ]
www.itebooks.info
Machine Translated by Google
Capítulo 8
int RELOJ_595 = 4; int // primer pin del reloj 595 que se conecta al pin 4
LATCH_595 = 3; int // primer pasador de pestillo 595 que se conecta al pin 3
DATOS_595 = 2; pin 2 // primer pin de entrada de datos en serie 595 que se conecta a
configuración vacía() {
// utiliza una semilla proveniente del ruido electrónico del ADC randomSeed(analogRead(0));
bucle vacío(){
// cada 5000 ejecuciones de loop(), toma una nueva semilla para la función aleatoria
[ 275 ]
www.itebooks.info
Machine Translated by Google
{
semillaAleatoria(lectura analógica(0)); // lee un nuevo valor del pin analógico
0
contador = 0; // reiniciar el contador
}
La biblioteca ShiftOutX se puede utilizar de muchas maneras. La utilizaremos aquí de la misma forma que lo
hicimos con ShiftOut, la biblioteca que forma parte del núcleo y es adecuada para el uso de un solo registro de
desplazamiento.
Primero, tenemos que incluir la biblioteca usando Sketch | Importar biblioteca | ShiftOutX.
Luego, definimos una nueva variable que almacena el número de registros de desplazamiento en la cadena.
El código en setup() cambió un poco. De hecho, ya no hay más instrucciones de configuración para pines
digitales. Esta parte la maneja la biblioteca, lo que puede parecer extraño, pero es muy habitual. De hecho,
cuando creaste una instancia de la biblioteca anteriormente, pasaste tres pines de Arduino como argumentos
y, de hecho, esta instrucción también configura los pines como salidas.
El bloque loop() es casi el mismo que antes. De hecho, incluí nuevamente la pequeña máquina de ritmo
aleatorio con el truco de lectura analógica. Pero esta vez estoy creando dos bytes aleatorios. De hecho, esto
se debe a que necesito 16 valores y quiero usar la función shiftOut_16 para enviar todos mis datos en
la misma declaración. Es bastante fácil y habitual generar bytes y luego agregarlos en un tipo de datos int corto
sin signo mediante el uso de operadores bit a bit.
[ 276 ]
www.itebooks.info
Machine Translated by Google
Capítulo 8
Cuando generamos bytes aleatorios, tenemos dos series de 8 bits. Tomemos el siguiente ejemplo:
01110100
11010001
Si queremos guardarlos en un solo lugar, ¿qué podemos hacer? Podemos mover uno y luego agregar el que se
ha movido al otro, ¿no?
0 1 1 1 0 1 0 0 << 8 = 0 1 1 1 0 1 0 0 0 0 0 0 0 0 0 0
0111010000000000
| 11010001
= 0111010011010001
Esto es lo que estamos haciendo en esta parte del código. Luego usamos shiftOut_16() para enviar todos los
datos a los dos registros de desplazamiento. ¿Qué deberíamos hacer con los cuatro registros de
desplazamiento? ¡Lo mismo de la misma manera!
Probablemente tendríamos que cambiar más usando << 32, << 16 y nuevamente <<8, para
poder almacenar todos nuestros bytes en una variable que pudiéramos enviar usando shiftOut_32()
funciones.
Al utilizar esta biblioteca, puede tener dos grupos, cada uno de los cuales contiene ocho registros
de desplazamiento.
Esto significa que puedes controlar 2 x 8 x 8 = 128 salidas utilizando solo cuatro pines (dos pestillos pero reloj
serial y datos comunes). Suena loco, ¿no?
En la vida real es totalmente posible utilizar un solo Arduino para realizar este tipo de arquitectura,
pero tendríamos que tener en cuenta algo muy importante, la cantidad de corriente. En este caso
particular de 128 LEDs, deberíamos imaginar lo peor.
caso en el que todos los LED estarían encendidos. La cantidad de corriente impulsada podría
Incluso quemar la placa Arduino, que se protegería reiniciándose, a veces.
Pero personalmente, ni siquiera lo intentaría.
[ 277 ]
www.itebooks.info
Machine Translated by Google
No hicimos estas consideraciones ni los cálculos siguientes porque en nuestros ejemplos solo utilizamos
unos pocos dispositivos y componentes, pero a veces podrías tener la tentación de construir un
dispositivo enorme como el que hice yo a veces, por ejemplo, con el controlador Protodeck.
Tomemos un ejemplo para analizar con más detalle algunos cálculos actuales.
Imagina que tienes un LED que necesita alrededor de 10 mA para encenderse correctamente (¡sin
quemarse en el segundo parpadeo!)
Esto significaría que tendrías 8 x 10 mA para una matriz de ocho LED, impulsada por un registro de
desplazamiento 595, si todos los LED se encendieran al mismo tiempo.
80 mA sería la corriente global impulsada por un registro de desplazamiento 595 desde la fuente Vcc de Arduino.
Si hubiera más registros de desplazamiento 595, la magnitud de la corriente aumentaría. Hay que saber que
todos los circuitos integrados también consumen corriente. Su consumo no suele tenerse en cuenta,
porque es muy pequeño. Por ejemplo, el circuito de registro de desplazamiento 595 solo consume unos 80
microamperios, lo que supone 0,008 mA. En comparación con nuestros LED, es insignificante. Las
resistencias también consumen corriente, aunque a menudo se utilizan para proteger los LED, son muy
útiles.
De todos modos, estamos a punto de aprender otro truco muy útil e inteligente que se puede utilizar para
LED monocromáticos o RGB.
[ 278 ]
www.itebooks.info
Machine Translated by Google
Capítulo 8
No hablo de los LED que pueden cambiar de color según el voltaje que se les aplique. Los
LED de este tipo existen, pero hasta donde he podido experimentar, no son la mejor opción,
especialmente si todavía estás aprendiendo los pasos.
Es necesario poder aplicar una corriente a sus patas. Más precisamente, es necesario poder
crear una diferencia de potencial entre sus patas.
Podemos discutir las diferentes formas de controles, y lo entenderás muy rápidamente con la
siguiente imagen.
Para que una salida digital genere corriente, necesitamos escribirle con digitalWrite
un valor ALTO. En este caso, la salida digital considerada estará conectada internamente a
una batería de 5 V y producirá un voltaje de 5 V. Esto significa que el LED cableado entre él y
la tierra se alimentará con corriente.
[ 279 ]
www.itebooks.info
Machine Translated by Google
Básicamente hay tres LED en un paquete, con diferentes tipos de cableado en su interior.
La forma de hacer este paquete no tiene que ver realmente con el cableado en su interior, pero no voy a
debatirlo aquí.
[ 280 ]
www.itebooks.info
Machine Translated by Google
Capítulo 8
Si me has entendido bien, es posible que hayas adivinado que necesitamos más salidas digitales para
conectar LED RGB. De hecho, en la sección anterior hablamos sobre cómo ahorrar pines digitales. Supongo
que entiendes por qué puede ser importante ahorrar pines y planificar cuidadosamente las arquitecturas de
nuestros circuitos.
int pinR = 4; // pin relacionado con el rojo del LED RGB int pinG = 3; // pin
relacionado con el verde del LED RGB int pinB = 2; // pin relacionado con el
azul del LED RGB
configuración vacía() {
pinMode(pinR, SALIDA);
pinMode(pinG, SALIDA);
pinMode(pinB, SALIDA);
}
[ 281 ]
www.itebooks.info
Machine Translated by Google
bucle vacío() {
Tenemos una lista ordenada de tres elementos, cada uno de los cuales puede estar encendido o apagado. Por lo tanto, hay 23
Solo activando o desactivando cada componente de color podemos cambiar el estado global del LED RGB.
[ 282 ]
www.itebooks.info
Machine Translated by Google
Capítulo 8
Primero, definimos tres variables que almacenan los diferentes colores de los conectores LED.
• 1er paso: r = 0, g = 0 y b = 0 implica que todo está APAGADO, luego se detiene por
150ms en ese estado
• 2do paso: r = 0, g = 0 y b = 1 implica que solo está encendido el AZUL, luego se detiene
durante 150 ms en ese estado
• 3er paso: r = 0, g = 1 y b = 0 implica que solo está encendido el VERDE, luego se detiene
durante 150 ms en ese estado
También habrás notado que no escribí HIGH ni LOW como argumentos para la función digitalWrite() . De
hecho, HIGH y LOW son constantes definidas en la biblioteca principal de Arduino y solo reemplazan
los valores 1 y 0, respectivamente.
Para probar esto, y especialmente para mostrarle por primera vez dónde se encuentran los archivos
principales de Arduino, el archivo importante a verificar aquí es Arduino.h.
En OS X, está en Arduino.app/Contents/Resources/Java/hardware/arduino/
cores/arduino/Arduino.h. Podemos ver el contenido de un paquete de aplicación haciendo clic derecho
sobre el paquete en sí.
En este archivo podemos leer una gran lista de constantes, entre muchas otras definiciones.
[ 283 ]
www.itebooks.info
Machine Translated by Google
Sí, las palabras clave HIGH y LOW son solo constantes para 1 y 0.
Esta es la razón por la que estoy alimentando directamente digitalWrite() con 0 y 1 a través
de los bucles imbricados, recorriendo todos los estados posibles para cada LED y, como
consecuencia, todos los estados para el LED RGB.
Utilizando este concepto, vamos a profundizar más y crear una matriz de LED.
Vamos a construir juntos una matriz de LED de 3 x 3. No es tan difícil y abordaremos esta
tarea con un concepto muy bueno, ordenado e inteligente que realmente puede optimizar sus
diseños de hardware.
Un LED puede parpadear cuando lo alimenta una corriente, cuando se aplica un voltaje a sus patas.
Para apagar el LED que se muestra en la captura de pantalla anterior, podemos dejar de
generar la corriente de 5 V en su nodo. Sin tensión, no hay suministro de corriente. También
podemos cortar el circuito para apagar el LED. Y, por último, podemos cambiar la conexión a
tierra añadiendo una corriente de fuente de 5 V.
Esto significa que tan pronto como se cancela la diferencia de potencial, el LED se apaga.
[ 284 ]
www.itebooks.info
Machine Translated by Google
Capítulo 8
Los transistores son los componentes más utilizados en el mundo. No sólo se utilizan como
componentes discretos (independientes), sino que también se combinan con muchos otros
para formar un sistema de alta densidad, por ejemplo, en procesadores.
[ 285 ]
www.itebooks.info
Machine Translated by Google
http://www.ti.com/lit/ds/symlink/uln2003a.pdf.
Contiene siete pines denominados entradas y siete pines denominados salidas. También podemos
ver un pin de 0 V (el número 8) y el pin COM 9.
Esto se puede utilizar fácilmente como un conjunto de interruptores que absorben la corriente.
[ 286 ]
www.itebooks.info
Machine Translated by Google
Capítulo 8
Un caso en el que se alimentan las entradas 1 y 2, lo que da como resultado la conmutación de las salidas 1 y 2 (pin 16 y 14)
La matriz LED
Veamos cómo podemos cablear nuestra matriz, teniendo en cuenta que debemos poder controlar
cada LED independientemente, por supuesto.
Este tipo de diseño es muy habitual. Se pueden encontrar fácilmente matrices de LED ya preparadas
y cableadas de esta manera, que se venden en paquetes con conectores disponibles en relación
con las filas y columnas.
• De cada fila aparece un conector relacionado con todos los ánodos de esa fila.
• De cada columna surge un conector relacionado con todos los cátodos de esa columna.
[ 287 ]
www.itebooks.info
Machine Translated by Google
• Conecte ROW 1 a 5 V
Vayamos más allá. Imaginemos que, si queremos encender el LED 2 y el LED 4, tenemos que:
• Conecte ROW 1 a 5 V
[ 288 ]
www.itebooks.info
Machine Translated by Google
Capítulo 8
¿Notaste algo?
Vamos a ver que no es nada difícil y que simplemente se trata de un pequeño truco relacionado con
nuestra persistencia en la visión.
Ciclismo y POV
Podemos solucionar el problema encontrado en la sección anterior ciclando nuestra matriz rápidamente.
El truco consiste en activar solo una columna a la vez. Esto también podría funcionar activando
solo una fila a la vez, por supuesto.
Tomemos nuestro problema anterior: si queremos encender el LED 2 y el LED 4, tenemos que:
Si hacemos esto muy rápido, nuestros ojos no verán que solo hay un LED encendido a la vez.
El pseudocódigo sería:
Encender la columna
[ 289 ]
www.itebooks.info
Machine Translated by Google
El circuito En
primer lugar, hay que diseñar el circuito. Así es como queda:
Arduino conectado a un registro de desplazamiento 595 que controla cada fila y columna a través de un ULN2003
[ 290 ]
www.itebooks.info
Machine Translated by Google
Capítulo 8
Éste está conectado a un registro de desplazamiento ULN2003 y a las filas de la matriz, estando
conectado el ULN2003 a las columnas de la matriz.
El registro de desplazamiento toma datos de los mensajes basados en protocolo serial enviados
por Arduino desde su pin digital 2. Como probamos antes, el registro de desplazamiento está
sincronizado con Arduino, y tan pronto como su pin de cierre está conectado a ALTO (=(igual a 5
V), impulsa una salida a 5 V o no, dependiendo de los datos que le envía Arduino. Como consecuencia,
podemos controlar cada fila de la matriz, alimentándolas con 5 V o no a través de los datos enviados
al registro de desplazamiento.
Para encender los leds, tenemos que cerrar el circuito en el que están enchufados, es decir, la línea
eléctrica. Podemos alimentar la fila 1 con una corriente de 5 V, pero si no ponemos a tierra esta o
aquella columna, el circuito no se cerrará y no se encenderá ningún led. ¿Verdad?
El ULN2003 fue creado precisamente para la conmutación a tierra, como ya vimos. Y si alimentamos
5 V a una de sus entradas, conmuta el pin n de salida correspondiente a tierra. De modo que, con
nuestros registros de desplazamiento 595, podemos controlar la conmutación de 5 V para las
filas y la conmutación a tierra para las columnas.
Ahora tenemos control total sobre nuestra matriz.
int RELOJ_595 = 4; int // primer pin del reloj 595 que se conecta al pin 4
LATCH_595 = 3; int // primer pasador de pestillo 595 que se conecta al pin 3
DATOS_595 = 2; // primer pin de datos seriales 595 que se conecta al pin 2
configuración vacía() {
pinMode(LATCH_595, SALIDA);
[ 291 ]
www.itebooks.info
Machine Translated by Google
pinMode(RELOJ_595, SALIDA);
pinMode(DATOS_595, SALIDA);
// utiliza una semilla proveniente del ruido electrónico del ADC randomSeed(analogRead(0));
bucle vacío() {
LED_states[i] = aleatorio(2);
}
// SI ese LED tiene que estar encendido, de acuerdo con la matriz LED_states // escribe el 1 en
el lugar de bit correcto (= fila actual) if (LED_states[currentLed]) dataRow = 1 << (4 c);
// suma los dos medios bytes dando como resultado los datos a enviar data = dataRow |
dataColumn;
// Coloque el pin del pestillo en BAJO (tierra) mientras transmite datos a 595 digitalWrite(LATCH_595,
LOW);
// Desplazamiento de bits
shiftOut(DATA_595, CLOCK_595, MSBFIRST, data);
[ 292 ]
www.itebooks.info
Machine Translated by Google
Capítulo 8
// Coloque el pin del pestillo en ALTO (5 V) y todos los datos se envían a las salidas
digitalWrite(LATCH_595, ALTO);
// cada 5000 ejecuciones de loop(), toma una nueva semilla para la función aleatoria
{
semillaAleatoria(lectura analógica(0)); // lee un nuevo valor del pin analógico
0
contador = 0; // reiniciar el contador
}
Este código se explica por sí solo con comentarios, pero veámoslo un poco más.
Tenemos una matriz de números enteros llamada LED_states. Almacenamos datos para
cada estado de LED dentro de ella. El bloque setup() es bastante fácil, define cada pin digital
utilizado en la comunicación con el registro de desplazamiento 595 y luego toma una semilla
aleatoria del ADC. El loop() es un poco más complicado. Primero, generamos nueve valores
aleatorios y los almacenamos en la matriz LED_states. Luego, inicializamos/definimos algunos valores:
[ 293 ]
www.itebooks.info
Machine Translated by Google
Para cada columna (primer bucle for()), activamos el bucle utilizando un operador bit a bit pequeño,
económico y rápido:
Los primeros tres bits (comenzando por la izquierda, el bit MSB) manejan las filas de nuestra matriz.
De hecho, las tres filas están conectadas a los pines Q0, Q1 y Q2 del registro de desplazamiento
595.
El segundo grupo de tres bits maneja el ULN2003, que a su vez maneja las columnas.
En cada giro de columna del bucle for(), movemos el bit correspondiente a la columna hacia la derecha,
conmutando cada columna al suelo cíclicamente.
Luego, para cada columna, hacemos un ciclo de la fila en el mismo modo, probando el estado del LED
correspondiente que tenemos que empujar al 595. Si el LED tiene que estar encendido, almacenamos el
bit correspondiente en la variable dataRow con el mismo truco de operación bit a bit.
Luego, sumamos esas dos partes, dando como resultado la variable de datos.
Por ejemplo, si estamos en la segunda fila y la segunda columna y el LED tiene que estar encendido,
entonces los datos almacenados serán:
0 1 0 0 1 0 0 0.
Si estamos en (1,3), entonces los datos almacenados serán los datos que se almacenarán:
1 0 0 0 0 1 0 0.
[ 294 ]
www.itebooks.info
Machine Translated by Google
Capítulo 8
Luego, tenemos el patrón que agrega Latch a BAJO, desplazando los bits almacenados en los datos al
registro de desplazamiento y luego colocando agrega Latch a ALTO para confirmar los datos en las
salidas Q0 a Q7, alimentando los elementos correctos en los circuitos.
Al final de cada fila manejada, reiniciamos los tres bits correspondientes a las tres primeras filas e
incrementamos la variable currentLed .
Al final de cada columna manejada, reiniciamos los tres bits correspondientes a las siguientes tres columnas.
Esta estructura imbricada global nos asegura que tendremos un solo LED.
encendido a la vez.
Solo tendremos un LED alimentado, lo que significa que nuestro consumo máximo se dividirá
potencialmente por nueve. ¡Sí, eso suena genial!
Luego, tenemos el patrón de captura que captura una nueva semilla, cada 5000 vueltas de loop().
Acabamos de aprender a manejar matrices LED con bastante facilidad y a reducir nuestro consumo
energético al mismo tiempo.
Pero no estoy satisfecho. Normalmente, los creadores y artistas nunca estamos del todo satisfechos,
pero aquí, créeme, es diferente; podríamos hacer cosas mejores que simplemente encender
y apagar los LED. También podríamos atenuarlos y cambiarlos de una intensidad muy baja a una muy
alta, creando diferentes tonos de luz.
También sabemos cómo leer estados de pines digitales configurados como entradas, e incluso valores
de 0 a 1023 de las entradas analógicas del ADC.
¿Qué aportaría una salida analógica? Proporcionaría una forma de escribir valores distintos de 0 y
1, es decir, 0 V y 5 V. Esto sería bueno, pero requeriría un DAC costoso.
[ 295 ]
www.itebooks.info
Machine Translated by Google
Nuestras salidas digitales solo pueden estar a 0 V o 5 V. Pero en un intervalo de tiempo particular, si las
encendemos/apagamos rápidamente, entonces podemos calcular un valor medio dependiendo del
tiempo transcurrido a 0 V o 5 V. Esta media se puede utilizar fácilmente como un valor.
Consulte el siguiente esquema para saber más sobre el concepto de ciclo de trabajo:
La media del tiempo transcurrido a 5 V define el ciclo de trabajo. Este valor es el tiempo medio en el que el
pin está a 5 V y se expresa como porcentaje.
analogWrite() es una función especial que puede generar una onda cuadrada constante en un ciclo
de trabajo específico hasta la próxima llamada.
Según la documentación principal de Arduino, la señal PWM pulsa a una frecuencia de 490 Hz. No lo he
verificado (todavía), pero realmente solo sería posible con un osciloscopio, por ejemplo.
[ 296 ]
www.itebooks.info
Machine Translated by Google
Capítulo 8
Atenuación de un LED
Vamos a comprobar un circuito básico para poder probar PWM:
[ 297 ]
www.itebooks.info
Machine Translated by Google
Usaremos el ejemplo Fading de David A. Mellis y modificado por Tom Igoe. Compruébelo en
Archivo | Ejemplos | 03. Analógico | Fading. Vamos a cambiar el ledPin
Valor del 9 al 11 para adaptarse a nuestro circuito.
void setup() { // no
pasa nada en la configuración
}
bucle vacío() {
// Aparece gradualmente del mínimo al máximo en incrementos de 5 puntos:
para (int valorDeFlare = 0; valorDeFlare <= 255; valorDeFlare +=5) {
// establece el valor (rango de 0 a 255):
analogWrite(ledPin, fadeValue); // espera 30
milisegundos para ver el efecto de atenuación delay(30);
}
}
[ 298 ]
www.itebooks.info
Machine Translated by Google
Capítulo 8
Ten cuidado, es un driver de sumidero de corriente constante. Esto significa que absorbe la corriente y no
la alimenta. Por ejemplo, tendrías que conectar los cátodos de tus LED a los pines OUT0 y OUT15 , no los
ánodos. Si quieres usar un driver específico como ese, no usarás analogWrite(), por supuesto. ¿Por qué? Porque
este driver funciona como un registro de desplazamiento, conectado a través de una conexión serial con
nuestro Arduino.
Sugeriría utilizar una buena biblioteca llamada tlc5940arduino, disponible en Google Code en
http://code.google.com/p/tlc5940arduino/
Veremos, en la tercera parte de este libro, cómo escribir mensajes en matrices LED.
Pero también hay una forma interesante de utilizar las pantallas de mayor resolución: LCD.
[ 299 ]
www.itebooks.info
Machine Translated by Google
Hoy en día podemos encontrar una gran cantidad de placas de circuitos impresos que incluyen una pantalla
LCD y los conectores para interconectarlas con Arduino y otros sistemas por poco dinero.
Ahora hay una biblioteca incluida en Arduino Core que es realmente fácil de usar. Se llama
LiquidCrystal y funciona con todas las pantallas LCD que sean compatibles con el controlador Hitachi
HD44780. Este controlador es muy común.
Hitachi lo desarrolló como un driver muy dedicado, que incluye un microcontrolador en sí mismo,
específicamente para manejar LCDs de caracteres alfanuméricos y para conectarse al mundo
externo fácilmente también, lo que se puede hacer mediante un enlace específico usando,
usualmente, 16 conectores, incluyendo fuente de alimentación para el propio circuito externo y también
la fuente de luz de fondo:
[ 300 ]
www.itebooks.info
Machine Translated by Google
Capítulo 8
Una pantalla LCD de 16 x 2 caracteres conectada a Arduino y un potenciómetro que controla su contraste.
[ 301 ]
www.itebooks.info
Machine Translated by Google
Los LED+ y LED no son necesarios siempre que haya suficiente luz. Con el
potenciómetro también se puede ajustar el contraste de la pantalla LCD para que
tenga la legibilidad suficiente.
#include <LiquidCrystal.h>
// Inicializa la biblioteca con el número de pines del circuito // Modo de 4 bits aquí sin RW
configuración vacía() {
bucle vacío() {
// cada 5s
[ 302 ]
www.itebooks.info
Machine Translated by Google
Capítulo 8
Primero, tenemos que incluir la biblioteca LiquidCrystal . Luego, definimos dos variables:
•
manyMessages es una matriz de cadenas para el almacenamiento de mensajes
En la configuración(), definimos el tamaño de la pantalla LCD según el hardware, aquí serían 16 columnas
y dos filas.
Luego, almacenamos la hora actual para poder medir el tiempo transcurrido desde que se mostró
el último mensaje aleatorio.
Luego, colocamos el cursor en la primera columna de la segunda fila, luego, imprimimos un String
compuesto por partes constantes y variables mostrando el tiempo en milisegundos desde
El último reinicio de la placa Arduino.
[ 303 ]
www.itebooks.info
Machine Translated by Google
Resumen
En este extenso capítulo, aprendimos a manejar muchas cosas, desde LED monocromáticos hasta LED
RGB, utilizando registros de desplazamiento y matrices de transistores, e incluso presentamos la pantalla
LCD. Profundizamos un poco más en la visualización de las respuestas visuales del Arduino sin
necesidad de utilizar necesariamente una computadora.
En muchos casos de diseño de la vida real, podemos encontrar proyectos que utilizan placas Arduino de
forma totalmente autónoma y sin necesidad de ordenador. Mediante el uso de librerías especiales y
componentes específicos, ahora sabemos que podemos hacer que nuestro Arduino sienta, se exprese y reaccione.
En el siguiente capítulo vamos a explicar y profundizar en algunos otros conceptos, como hacer que Arduino
se mueva y eventualmente también genere sonidos.
[ 304 ]
www.itebooks.info
Machine Translated by Google
• Movimientos de objetos
Vamos a aprender cómo podemos controlar pequeños motores llamados servo y cómo podemos manejar
el control de alta corriente mediante el uso de transistores.
A continuación, comenzaremos a hablar sobre los conceptos básicos de la generación de sonido. Este es
un requisito previo para intentar producir cualquier sonido, incluso los más simples. Esta es la parte en la
que describiremos los conceptos analógicos y digitales.
Por último, diseñaremos un sintetizador aleatorio muy básico que se pueda controlar mediante MIDI.
También presentaremos una biblioteca muy útil llamada PCM que ofrece una forma sencilla de agregar
funciones de reproducción de muestras a su microcontrolador de 8 bits.
www.itebooks.info
Machine Translated by Google
Esta es la primera acción tangible básica que diseñamos aquí. Por supuesto, ya hemos
diseñado muchos de los comentarios visuales, pero este es nuestro primer objeto del mundo
real que mueve el firmware.
Este tipo de feedback puede ser muy útil en contextos no visuales. Diseñé un pequeño proyecto para
una persona que quería enviar un feedback a los visitantes en su instalación reactiva. El visitante
tenía que ponerse una camiseta que incluía algunos dispositivos electrónicos, como un LilyPad y
algunos sensores piezoeléctricos. El feedback LED no era la solución que usábamos antes para enviar
feedback al usuario, y decidimos enviar una vibración. Estos sensores piezoeléctricos se distribuyeron en
cada lado de la camiseta para producir diferentes feedbacks en respuesta a diferentes interacciones.
El sensor piezoeléctrico
Un sensor piezoeléctrico es un componente que utiliza el efecto piezoeléctrico.
Este efecto se define como la interacción electromecánica lineal entre el estado mecánico y
eléctrico en algunos materiales específicos.
Básicamente, una acción mecánica sobre este dispositivo genera electricidad, lo que lo hace útil para
detectar movimiento y vibraciones. Pero lo bueno es que el efecto es recíproco: si se le aplica una
corriente, vibrará.
Los sensores piezoeléctricos también se utilizan a menudo como generadores de tonos. Más adelante
profundizaremos en la relación entre las vibraciones del aire y el sonido, pero es importante mencionarlo
también aquí.
[ 306 ]
www.itebooks.info
Machine Translated by Google
Capítulo 9
Por supuesto, debes comprobar la hoja de datos adecuada del dispositivo que vas a utilizar.
He tenido buenos resultados con el de Sparkfun (https://www.sparkfun.com/
productos/10293). El cableado no podría ser más sencillo: solo hay dos patas. La siguiente
imagen muestra cómo se conecta el sensor/vibrador piezoeléctrico a Arduino a través de un
pin digital con capacidad PWM:
Tenga en cuenta que he conectado el dispositivo piezoeléctrico a un pin digital compatible con
PWM. Expliqué el PWM en el capítulo anterior.
[ 307 ]
www.itebooks.info
Machine Translated by Google
Aquí está el esquema del circuito. Este componente piezoeléctrico se muestra como un pequeño
zumbador/altavoz:
Por supuesto, dado que vamos a utilizar PWM, significa que vamos a simular una corriente de
salida analógica. Teniendo en cuenta el concepto de ciclo de trabajo, podemos alimentar el
dispositivo piezoeléctrico utilizando la función analogWrite() y luego alimentarlo con
diferentes voltajes.
configuración vacía() {
[ 308 ]
www.itebooks.info
Machine Translated by Google
Capítulo 9
bucle vacío() {
Aquí volvemos a utilizar la función analogWrite() . Esta función toma el pin digital como argumento y valor. Este
valor, de 0 a 255, es el ciclo de trabajo. Básicamente, simula una salida analógica.
Este incremento cambia cuando el valor alcanza sus límites, 0 o 255, y se invierte, lo que proporciona
una forma económica de realizar un ciclo de 0 a 255, luego a 0, luego a 255, y así sucesivamente.
Este firmware hace que el dispositivo piezoeléctrico vibre cíclicamente desde una frecuencia baja a una
frecuencia más alta.
Puedes encontrar transistores prácticamente en cualquier sitio y son bastante baratos. Puedes encontrar la
hoja de datos completa en http://www.fairchildsemi.com/ds/BC/BC547.pdf.
[ 309 ]
www.itebooks.info
Machine Translated by Google
• El coleccionista
• La base
• El emisor
Si saturamos la base aplicándole una fuente de alimentación de 5 V, toda la corriente que viene del
colector se transmitirá a través del emisor.
Cuando se utiliza de esta manera, el transistor NPN es una buena manera de activar o desactivar una
corriente alta que Arduino no habría podido controlar por sí solo. Por cierto, este interruptor se puede
controlar con Arduino porque solo requiere que se suministre una cantidad muy pequeña de corriente a
la base del transistor.
En cualquier caso, cuando es necesario disponer de una fuente de alimentación externa para accionar motores,
utilizamos este tipo de patrón de diseño.
Ahora aprendamos sobre servos de pequeña corriente y luego avancemos más utilizando transistores.
[ 310 ]
www.itebooks.info
Machine Translated by Google
Capítulo 9
Controlar un servo
Un servomotor también se define como un actuador rotatorio que permite un control muy fino de posiciones
angulares.
Hay muchos servos disponibles y a un precio bastante económico. He obtenido buenos resultados con un
servo 43 R de Spring Model Electronics. Puede encontrar la hoja de datos en http://www.
sparkfun.com/datasheets/Robotics/servo360_e.pdf.
Los servos pueden manejar una gran cantidad de corriente, lo que significa que no podrás usar más de
uno o dos en tu placa Arduino sin usar una fuente de alimentación externa.
Los servos no sólo se pueden utilizar para mover piezas pequeñas y hacer que los objetos giren, sino que
también se pueden utilizar para mover el objeto, incluidos ellos. Los robots funcionan de esta manera y hay
muchos proyectos de robots relacionados con Arduino en la Web que son muy interesantes.
En el caso de los robots, la carcasa del dispositivo servo está fijada a una parte de un brazo, por ejemplo,
y la otra parte del brazo está fijada a la parte giratoria del servo.
Esta biblioteca admite hasta 12 motores en la mayoría de las placas Arduino y 48 en Arduino
Mega.
Al utilizar otras placas Arduino en lugar de Mega, podemos solucionar algunas limitaciones del
software. Por ejemplo, los pines 9 y 10 no se pueden utilizar para analogWrite() de PWM.
método (http://arduino.cc/es/Referencia/analogWrite).
•5V
• Suelo
Básicamente, la fuente de alimentación se puede proporcionar fácilmente mediante una batería externa,
y el pulso sigue estando en la placa Arduino.
[ 311 ]
www.itebooks.info
Machine Translated by Google
Cableado de un servo
El siguiente diagrama es el de un servo conectado a un Arduino tanto para alimentación como para control:
[ 312 ]
www.itebooks.info
Machine Translated by Google
Capítulo 9
Un servo y Arduino
#include <Servo.h>
configuración vacía()
{
[ 313 ]
www.itebooks.info
Machine Translated by Google
bucle vacío() {
myServo.write(angulo);
retraso(20);
myServo.write(angulo);
retraso(20);
}
}
En el bloque loop() , tenemos dos bucles for() y se parece al ejemplo anterior con el dispositivo
piezoeléctrico. Definimos un ciclo, incrementando progresivamente la variable de ángulo de 0 a 180 y luego
disminuyéndola de 180 a 0, y cada vez hacemos una pausa de 20 ms.
También hay una función que no se utiliza aquí y que quiero mencionar, Servo.read().
Esta función lee el ángulo actual del servo (es decir, el valor pasado a la última llamada a write()). Esto puede ser
útil si estamos creando algo dinámico sin almacenarlo en cada giro.
[ 314 ]
www.itebooks.info
Machine Translated by Google
Capítulo 9
Si tu proyecto Arduino requiere una computadora, puedes suministrarle energía a través del
USB siempre y cuando no superes el límite de 500 mA. Más allá de esto, necesitarás usar una
fuente de alimentación externa para algunas o todas las partes de tu circuito.
Aquí vamos a utilizar pilas AA básicas. Esta es también una forma de alimentar Arduino si no
necesitas un ordenador y quieres que Arduino sea autónomo. Consideraremos esta opción en
la tercera parte de este libro sobre conceptos más avanzados.
[ 315 ]
www.itebooks.info
Machine Translated by Google
En casos como este, tenemos que conectar las tomas de tierra. Por supuesto, solo hay una fuente de alimentación
de corriente para los servos: las dos pilas AA.
#include <Servo.h>
Servicio servicio01;
Servoservo02;
Servoservo03;
int ángulo;
configuración vacía()
{
[ 316 ]
www.itebooks.info
Machine Translated by Google
Capítulo 9
servo01.adjuntar(9);
servo02.adjuntar(10);
servo03.adjuntar(11);
}
bucle vacío() {
servo01.write(angulo);
servo02.write(135ángulo/2);
servo03.write(angulo 180);
retraso(15);
}
}
Primero instanciamos nuestros tres servos y conectamos un pin para cada uno en el bloque setup() .
En loop(), jugamos con ángulos. Como nuevo enfoque para la creación generativa, definí una variable
solo para el ángulo. Esta variable va cíclicamente de 0 a 180 en cada vuelta de loop() .
El servo conectado al pin 10 se activa con el valor [135(ángulo/2)], variando de 135 a 45.
Luego, el servo conectado al pin 11 se acciona con el valor [180ángulo], que es el movimiento
opuesto del servo conectado al pin 9.
Este también es un ejemplo para mostrarle cómo podemos controlar fácilmente una sola variable
y programar variaciones alrededor de esta variable cada vez; aquí, estamos haciendo que los
ángulos varíen y estamos combinando la variable ángulo en diferentes expresiones.
Por supuesto, podríamos controlar la posición del servo mediante un parámetro externo, como la
posición de un potenciómetro o la distancia medida. Esto combinará los conceptos enseñados aquí
con los del Capítulo 5, Detección con entradas digitales, y el Capítulo 6, Detección del mundo:
sensaciones con entradas analógicas.
[ 317 ]
www.itebooks.info
Machine Translated by Google
La rotación completa se divide en una serie de pasos iguales y las posiciones de los motores se
pueden controlar para moverse y mantenerse en uno de estos pasos fácilmente con un alto grado de
precisión, sin ningún mecanismo de retroalimentación.
Hay una serie de bobinas electromagnéticas que pueden cargarse positiva o negativamente
en una secuencia específica. Controlar la secuencia permite controlar el movimiento, hacia adelante
o hacia atrás en pequeños pasos.
[ 318 ]
www.itebooks.info
Machine Translated by Google
Capítulo 9
Necesitamos suministrar energía al motor paso a paso desde una fuente externa. Una de las mejores
prácticas en este caso es el uso de un adaptador de pared. Los pines 5 y 6 deben recibir una fuente
de corriente.
Luego, necesitamos controlar cada pin del 1 al 4 con Arduino. Esto se hará usando el sistema de
corriente de sumidero ULN2004, que es muy similar al ULN2003 que usamos en el capítulo anterior
con nuestra matriz de LED. ULN2004 es adecuado para voltaje de 6 V a 15 V. Cuando ULN2003 es de 5 V,
la hoja de datos del motor paso a paso muestra que tenemos que usar este sistema en lugar de ULN2003.
Un motor paso a paso unipolar conectado a Arduino a través de la matriz de transistores Darlington, ULN2004
[ 319 ]
www.itebooks.info
Machine Translated by Google
Diagrama de circuito que muestra Arduino, la matriz de transistores Darlington ULN2004 y el motor paso a paso.
Aquí volvemos a utilizar una fuente de alimentación externa. Todas las conexiones a tierra también están
conectadas entre sí.
Tenga en cuenta que el pin COM (pin número 9) debe estar conectado a la fuente de alimentación (+V).
Si recuerdas correctamente el capítulo anterior, cuando alimentamos una entrada del conjunto de transistores
Darlington ULN200x, la salida correspondiente envía la corriente a tierra.
En nuestro caso, cada pin de Arduino conectado al registro de desplazamiento ULN2004 puede conmutar cada pin
del motor paso a paso a tierra.
[ 320 ]
www.itebooks.info
Machine Translated by Google
Capítulo 9
Para controlar movimientos precisos, normalmente tenemos que trabajar con secuencias
específicas. Estas secuencias suelen estar descritas en la hoja de datos.
Podemos ver una tabla similar a la siguiente, denominada Drive Sequence Model:
PASO A B do D
1 ALTO ALTO BAJO BAJO
2 BAJO ALTO ALTO BAJO
3 BAJO BAJO ALTO ALTO
4 ALTO BAJO BAJO ALTO
Si desea realizar una rotación en el sentido de las agujas del reloj, deberá generar una secuencia del 1 al 4, luego al
1, y así sucesivamente, de forma cíclica. Las rotaciones en el sentido contrario a las agujas del reloj requieren
generar secuencias del 4 al 1, y así sucesivamente.
En lugar de escribir muchas secuencias como estas, con alguna función, podemos usar directamente
la biblioteca llamada Stepper, que ahora está incluida en Arduino Core.
Aquí está el código, seguido de la discusión. También está disponible en el Capítulo 09/
Motor paso a paso/ carpeta.
configuración vacía()
{
stepper.setSpeed(30); // establece la velocidad a 30 RPM
}
bucle vacío()
{
[ 321 ]
www.itebooks.info
Machine Translated by Google
paso a paso.paso(multiplicador);
Luego definimos el número de pasos que equivalen a una vuelta completa. En nuestra hoja de
datos, podemos ver que el primer paso es un ángulo de 1,8 grados, con un margen de error del 5
por ciento. No consideraremos ese error; tomaremos 1,8 grados. Esto significa que necesitamos 200
pasos (200 * 1,8 = 360°) para dar una vuelta completa.
Luego, creamos una instancia de un objeto Stepper ingresando cinco argumentos, que son los números
de paso para una vuelta completa y los cuatro pines del Arduino conectados al stepper.
Luego declaramos dos variables auxiliares para rastrear y, a veces, cambiar la dirección de rotación.
En el bloque setup() , normalmente definimos la velocidad de la instancia actual que maneja el motor
paso a paso. Aquí, he establecido 30 (que significa 30 vueltas por minuto). Esto también se puede
cambiar en el bloque loop() , teniendo en cuenta condiciones específicas o lo que sea.
Por último, en el bloque loop() , movemos el motor paso a paso a una cantidad igual al valor del
multiplicador, que inicialmente es 1. Esto significa que en cada ejecución del método loop() , el
motor paso a paso gira desde el paso 1 (es decir, 1,8 grados) en el sentido de las agujas del reloj.
Añadí un test lógico, que comprueba cada vez si el contador ha completado el número de pasos
necesarios para dar una vuelta completa. Si no lo ha hecho, lo incremento; de lo contrario, en cuanto
llega al límite (es decir, el motor da una vuelta completa desde el inicio de la ejecución del programa),
reinicio el contador e invierto el multiplicador para que el motor siga su recorrido, pero en el otro sentido.
Este es otro patrón que debes tener en cuenta, son todos patrones pequeños que te darán muchas
ideas económicas y eficientes para usar en cada uno de tus proyectos futuros.
Con servos y motores paso a paso, ahora podemos hacer que las cosas se muevan.
[ 322 ]
www.itebooks.info
Machine Translated by Google
Capítulo 9
En algunos de mis proyectos, utilicé dos máquinas de dibujo, con una cuerda atada a cada una y ambas
cuerdas atadas a un lápiz colgante. Podemos dibujar en una pared controlando la cantidad de cuerda que
cuelga de cada lado.
Si puedes hacer que las cosas se muevan con Arduino, probablemente podrás hacer que el aire también se
mueva.
Esta parte es sólo una breve introducción a algunas definiciones y no un curso completo sobre síntesis de
sonido. Estos son los elementos básicos que utilizaremos en las siguientes secciones del libro y, en la medida
de lo posible, se proporcionarán referencias a sitios web o libros a los que podrá recurrir si está interesado
en aprender más sobre esas partes específicas.
Nuestro oído, combinado con otros procesos cerebrales, es un asombroso sensor de presión del aire.
Es capaz de evaluar lo siguiente:
Por supuesto, todos estos procesos son en tiempo real, asumiendo que frecuencias más altas o más bajas
se mezclan en ese momento particular.
Te recomiendo que leas la sorprendente y eficiente introducción a How Digital Audio Works? (¿Cómo
funciona el audio digital ?), de Cycling 74, el creador del marco Max 6. Puedes leerla en línea en http://
www.cycling74.com/docs/max6/dynamic/c74_docs.
html#mspdigitalaudio.
[ 323 ]
www.itebooks.info
Machine Translated by Google
Un sonido puede contener más de una frecuencia y, generalmente, es una combinación del contenido de
frecuencia y la percepción global de cada amplitud de frecuencia lo que da la sensación de lo que
llamamos el timbre de un sonido. La psicoacústica estudia la percepción del sonido.
• Variación de la amplitud a lo largo del tiempo. Esta descripción se puede plasmar en un gráfico y
definir como una representación de los sonidos en el dominio del tiempo.
Existe una operación matemática que proporciona una forma sencilla de pasar de uno a otro, conocida
como transformada de Fourier (http://en.wikipedia.org/wiki/
Existen muchas implementaciones de esta operación disponibles en las computadoras, en forma de
Transformada Rápida de Fourier ( FFT), que es un método eficiente que proporciona cálculos aproximados
rápidos.
Consideremos una variación sinusoidal de la presión del aire. Esta es una de las más simples
ondas sonoras
Dos representaciones del mismo sonido elemental producido por una variación sinusoidal de la presión del aire
[ 324 ]
www.itebooks.info
Machine Translated by Google
Capítulo 9
En la representación del dominio del tiempo, podemos ver una variación cíclica con un período.
El período es el equivalente temporal de la longitud de onda espacial.
El período es el tiempo necesario para completar un ciclo vibracional completo. Básicamente, si puedes
describir la variación a lo largo de un período, puedes dibujar totalmente la representación del sonido
en el tiempo. Aquí, es un poco obvio porque estamos viendo un sonido basado en una onda
sinusoidal pura.
Si dibujas y observas un sonido producido por una fuente, la variación de amplitud a lo largo del tiempo
corresponderá directamente a una variación de la presión del aire.
Teniendo en cuenta la orientación del eje, tenemos primero lo que llamamos un frente de alta presión. Esta
es la parte de la curva por encima del cero (representada por el eje del tiempo). Esto significa que la
presión es alta y nuestro tímpano está empujado un poco más hacia adentro.
Nuestro oído.
Luego, después de un semiperíodo, la curva cruza el cero y desciende, lo que significa que la presión del
aire es inferior a la presión atmosférica normal. Nuestro tímpano también siente esta variación. Se estira
un poco.
En la representación en el dominio de la frecuencia, solo hay una línea vertical. Este gráfico en
forma de pulso de la figura anterior representa la frecuencia única contenida en este sonido
de base sinusoidal. Está directamente relacionada con su período mediante una ecuación
matemática, como sigue:
Cuanto más alta sea la frecuencia, más agudo será el sonido. Cuanto más baja sea, más grave será el sonido.
Por supuesto, una frecuencia alta significa un período corto y oscilaciones más rápidas a lo largo del tiempo.
Estos son los pasos básicos para comprender cómo se puede representar y sentir el sonido.
Micrófonos y altavoces
Los micrófonos son dispositivos sensibles a las variaciones sutiles de la presión del aire. Sí, son sensores.
Pueden traducir las variaciones de la presión del aire en variaciones de voltaje.
Los altavoces son dispositivos que incorporan una pieza que puede moverse, empujando y tirando de
masas de aire, haciéndolas vibrar y producir sonidos. El movimiento es inducido por variaciones de voltaje.
[ 325 ]
www.itebooks.info
Machine Translated by Google
• Una membrana
En la caja del micrófono, cambiamos la presión del aire y eso produce una señal eléctrica.
En el caso del altavoz, cambiamos la señal eléctrica y eso produce una variación de presión de
aire.
¿Y cómo podemos describir algo analógico en ese caso? Ya hablamos de esta situación cuando
describimos los pines de entrada y salida analógicos y digitales de Arduino.
El sistema es capaz de leer el valor analógico a intervalos regulares de tiempo. Toma un valor, lo
mantiene constante hasta el siguiente valor, y así sucesivamente.
Un teorema matemático nos proporciona un límite que debemos tener en cuenta: la frecuencia de
Nyquist.
Para mantener nuestro sistema de muestreo procesado como un artefacto seguro inducido por el propio
sistema, tenemos que muestrear a un mínimo de dos veces la frecuencia más alta en nuestra señal
analógica original.
[ 326 ]
www.itebooks.info
Machine Translated by Google
Capítulo 9
Una mayor frecuencia de muestreo no sólo implica mayor precisión y fidelidad a la onda analógica
original, sino también más puntos para almacenar en el sistema digital. El resultado sería un archivo más
pesado, en términos de discos y sistemas de archivos.
De hecho, hemos muestreado un valor a lo largo del tiempo, pero ¿cómo se puede representar el
valor en sí, la amplitud? Utilizamos un sistema de codificación basado en bits, como es
habitual con los equipos digitales.
[ 327 ]
www.itebooks.info
Machine Translated by Google
La profundidad de bits es la resolución de los valores de amplitud de 1 (el mínimo posible) a 1 (el máximo
posible).
Cuanto mayor sea la profundidad de bits, más variaciones sutiles podremos codificar y registrar en nuestros
sistemas digitales. Por el contrario, si tenemos un sampler con una profundidad de bits muy baja y realizamos
una variación de amplitud progresivamente decreciente, el sonido disminuirá considerablemente de forma similar
al efecto Doppler. Por ejemplo, no podríamos distinguir valores de 0,5 a 0,6; todo sería solo 0,5 o 0,7 pero nunca
0,6. El sonido perdería sutileza.
Las frecuencias de muestreo y la profundidad de bits habituales dependen del propósito de la representación final.
Algunos estudios de grabación y masterización utilizan interfaces de audio y procesamiento interno a 96 kHz y 24
bits. Algunas personas a las que les encantan los motores de sonido de la vieja escuela todavía utilizan sistemas lo
fi para producir su propio sonido y música a 16 kHz y 8 bits.
El proceso de conversión de analógico a digital lo realiza el conversor analógico a digital (ADC). Su calidad es
la clave para lograr una buena conversión. Este proceso es similar al que se lleva a cabo en Arduino cuando
utilizamos una entrada analógica. Su ADC es de 10 bits y puede leer un valor cada 111 microsegundos, lo que
supone una frecuencia de muestreo de 9 kHz.
Los buffers se utilizan para procesar los tiempos sin problemas y hacer que las cosas sean más fluidas en el tiempo.
Si el procesador envía bits de datos del sonido codificado al DAC como un flujo continuo de valores
discretos, el DAC toma todos estos valores y los convierte en una señal eléctrica analógica. Interpola valores entre
cada valor digital, lo que a menudo implica algunos procesos (por ejemplo, filtrado de paso bajo), para eliminar algunos
artefactos como los armónicos por encima de la frecuencia de Nyquist.
En el mundo del audio digital, la potencia y la calidad de los DAC son uno de los aspectos más
importantes de nuestra estación de trabajo de audio. Deben ofrecer altas resoluciones, una alta
frecuencia de muestreo, una distorsión armónica total y un ruido reducidos y un gran rango dinámico.
[ 328 ]
www.itebooks.info
Machine Translated by Google
Capítulo 9
Arduino puede leer y escribir señales digitales. También puede leer señales analógicas y simular
señales de salida analógicas mediante PWM.
¿No sería capaz de producir sonidos e incluso de escucharlos? Por supuesto que sí.
Incluso podemos utilizar algunos componentes dedicados para mejorar las cosas. Por ejemplo, podemos
utilizar un ADC con una mayor frecuencia de muestreo para almacenar sonidos y también un DAC de alta
calidad, si es necesario. Hoy en día, a menudo utilizamos equipos de hardware electrónico para controlar
el software. Podemos, por ejemplo, construir un dispositivo basado en Arduino, lleno de perillas y
botones e interconectarlo con un software en la computadora. Esto es algo que hay que mencionar aquí.
También podemos utilizar Arduino como disparador de sonido. De hecho, es bastante fácil convertirlo en
un pequeño secuenciador, enviando mensajes MIDI u OSC específicos a un sintetizador externo, por
ejemplo. Vayamos más allá y profundicemos en los conceptos de audio específicamente con la placa
Arduino.
De forma nativa, Arduino es capaz de producir sonidos de reproducción de audio de 8 kHz y 8 bits en
pequeños altavoces de PC.
Vamos a utilizar la función tone() disponible de forma nativa en Arduino Core. Como está escrito en http://
arduino.cc/en/Reference/Tone, debemos tener cuidado con los pines utilizados al utilizar esta función, ya
que interferirá con la salida PWM en los pines 3 y 11 (excepto en Arduino MEGA).
Esta técnica también se denomina bitbanging y se basa en la alternancia de pines de E/S a una
frecuencia específica.
[ 329 ]
www.itebooks.info
Machine Translated by Google
Las conexiones realizadas aquí garantizan un sonido audible. Ahora programemos el chip.
[ 330 ]
www.itebooks.info
Machine Translated by Google
Capítulo 9
En este ejemplo no utilizamos notas sino frecuencias para definir y activar nuestra música
electrónica.
bucle vacío() {
[ 331 ]
www.itebooks.info
Machine Translated by Google
La función tone() genera una onda cuadrada de la frecuencia especificada en un pin como
se explica en su página de referencia en http://arduino.cc/en/Reference/Tone.
• No hay sonido puro: Las ondas cuadradas son una suma de todos los armónicos impares en el
frecuencia fundamental
• No hay control de amplitud disponible: cada nota suena al mismo volumen
[ 332 ]
www.itebooks.info
Machine Translated by Google
Capítulo 9
Vamos a utilizar una biblioteca muy útil llamada Mozzi, de Tim Barrass. El sitio web oficial está
alojado directamente en GitHub en http://sensorium.github.com/Mozzi/. Incluye la biblioteca TimerOne ,
un controlador de temporizador muy rápido.
Mozzi ofrece una salida de audio de 8 bits y 16 384 kHz muy buena. También incluye un kit de
herramientas de audio básico que contiene osciladores, muestras, líneas y envolventes, y también filtros.
Todo está disponible sin hardware externo y utilizando únicamente dos pines del Arduino.
Para escuchar a Mozzi, conecta un conector de audio de 3,5 mm con el cable central a
la salida PWM del pin digital 9* de Arduino y la conexión a tierra negra a la conexión a tierra
de Arduino. Úsalo como una salida de línea que puedes conectar a tu computadora y
escuchar con un programa de sonido como Audacity.
Es muy fácil configurar el hardware. Puedes encontrar muchos conectores jack de audio
de 3,5 mm como ese en Internet. En el siguiente diagrama de circuito, puse un altavoz
en lugar de un conector jack, pero funciona exactamente igual con un conector jack,
este último tiene 2 pines, uno de tierra y otro relacionado con la señal. La tierra debe conectarse
a la tierra del Arduino y el otro pin al pin digital 9 del Arduino.
Arduino.
Luego ponlo como siempre en el lugar donde pones tus librerias, en mi caso es:
/Usuarios/julien/Documentos/Arduino/bibliotecas/
[ 333 ]
www.itebooks.info
Machine Translated by Google
[ 334 ]
www.itebooks.info
Machine Translated by Google
Capítulo 9
Hay muchos ejemplos, y estos son útiles para aprender a diseñar nuestro propio firmware paso a
paso. Obviamente, no describiré todos estos ejemplos, sino solo aquellos en los que tomaré
elementos para hacer tu propio generador de sonido.
configuración vacía(){
startMozzi(CONTROL_RATE); // establece una tasa de control de 64 (potencias de 2, por favor) aSin.setFreq(440u); // establece la
frecuencia
void loop()
{ audioHook(); // requerido aquí
}
[ 335 ]
www.itebooks.info
Machine Translated by Google
Osciladores
En el mundo de la síntesis de sonido, un oscilador es una unidad básica capaz de producir oscilaciones. Suele
emplearse no solo para la generación directa de sonido con frecuencias que varían de 20 Hz a 20 kHz (espectro
audible), sino también como modulador (normalmente con frecuencias inferiores a 50 Hz). En este caso se ha
utilizado como este último. Un oscilador suele denominarse Oscilador de Baja Frecuencia (LFO).
Tablas de ondas
Una tabla de ondas es una forma muy agradable y eficiente de almacenar fragmentos enteros de sonidos,
generalmente sonidos cíclicos o en bucle.
En lugar de calcular nuestro valor de seno a lo largo del tiempo en tiempo real, básicamente precalculamos
cada valor de un período completo y luego agregamos los resultados en una tabla; cada vez que lo
necesitamos, solo tenemos que escanear la tabla desde el principio hasta el final para recuperar
cada valor.
Por supuesto, esto ES definitivamente una aproximación, pero ahorra mucho trabajo de CPU.
Una tabla de ondas se define por su tamaño, la frecuencia de muestreo relacionada y, por supuesto, los
valores completos.
[ 336 ]
www.itebooks.info
Machine Translated by Google
Capítulo 9
De hecho, podemos encontrar el número de celdas: 2048 (es decir, hay 2048 valores en la tabla).
Entonces, la frecuencia de muestreo se define como 2048.
Volvamos al ejemplo.
[ 337 ]
www.itebooks.info
Machine Translated by Google
El bloque setup() inicia la biblioteca Mozzi en la velocidad de control específica definida anteriormente.
Luego, configuramos el oscilador definido anteriormente a una frecuencia de 440 Hz. 440 Hz es la
frecuencia de la nota A universal. En este contexto, se puede considerar como el equivalente de audio
del ejemplo de Hello World.
Devolvemos aSin.next() en updateAudio(). Lee y devuelve la siguiente muestra, que se entiende como
el siguiente elemento, que es el siguiente bit de sonido.
El patrón global es el habitual. Incluso si utilizas otra librería relacionada con el sonido, dentro o fuera del
mundo Arduino, tendrás que lidiar con este tipo de patrón en cuatro pasos (generalmente, pero puede
variar):
• Funciones de actualización para renderizar cosas antes de una confirmación y luego en el gancho
Si subes esto, oirás una agradable nota A440, que puede hacerte tararear un poco.
[ 338 ]
www.itebooks.info
Machine Translated by Google
Capítulo 9
[ 339 ]
www.itebooks.info
Machine Translated by Google
[ 340 ]
www.itebooks.info
Machine Translated by Google
Capítulo 9
configuración vacía(){
iniciarMozzi(CONTROL_RATE);
aCos.setFreq(mtof(aleatorio(21,80)));
aVibrato.setFreq((float) mapa(potValue, 0, 1024, 0, intensityMax));
}
bucle vacío(){
gancho de audio();
}
vacío updateControl(){
potValue = analogRead(potPin);
}
int actualizaciónAudio(){
vibrato largo = map(potValue, 0, 1024, 0, intensityMax) * aVibrato.
próximo();
devuelve (int)aCos.phMod(vibrato);
}
En este ejemplo, utilizamos dos osciladores, ambos basados en una tabla de ondas de coseno:
• aVibrato es el modulador
Intensidad máxima es la intensidad máxima del efecto de modulación. Elegí 500 después de probarlo
yo mismo.
A menudo utilizamos la siguiente técnica para escalar cosas: utilizamos una constante (o incluso una
variable "real") y luego la multiplicamos por el valor que podemos variar. Esto se puede hacer en una
sola pasada utilizando la función map() . Ya la utilizamos en el Capítulo 6, Sensing the World –
Feeling with Analog Inputs, con el mismo propósito: escalar una entrada analógica.
valor.
En ese caso, en el valor máximo, su potenciómetro (más generalmente su entrada) cambia el parámetro
que desea alterar a su valor máximo.
En el bloque setup() iniciamos Mozzi. Definimos la frecuencia del oscilador como aCos. La frecuencia
en sí es el resultado de la función mtof() . mtof significa MIDI to Frequency.
[ 341 ]
www.itebooks.info
Machine Translated by Google
Como describiremos un poco más adelante, el protocolo MIDI codifica muchos bytes de valores, incluido
el tono de las notas que utiliza para transportar desde los secuenciadores a los instrumentos.
Cada nota MIDI se corresponde con valores de notas reales en el mundo real y cada nota se corresponde
con una frecuencia determinada. Existen tablas que muestran la frecuencia de cada nota MIDI y Mozzi la
incluye para nosotros.
Podemos pasar un tono de nota MIDI como argumento a la función mtof() y devolverá la frecuencia correcta.
Aquí, usamos la función random(21,80) para generar un tono de nota MIDI de 21 a 79, es decir, de A0 a
A5.
Por supuesto, este caso de uso es un pretexto para comenzar a introducir el MIDI. Podríamos
haber utilizado directamente una función random() para generar una frecuencia.
Luego leemos el valor actual de la entrada analógica A0 y lo usamos para calcular un valor escalado de la
frecuencia del oscilador modulador, aVibrato. Esto es solo para brindar más aleatoriedad y rareza. De hecho,
si su potenciómetro no está en el mismo lugar cada vez que reinicia Arduino, tendrá una frecuencia de
modulación diferente.
Luego, el bloque loop() ejecuta el método audioHook() constantemente para producir audio.
Esta situación se da con mucha frecuencia en muchos marcos de trabajo y puede confundirte la
primera vez. Todo tiene que ver con la tarea y su programación. Sin hacer ingeniería inversa de
los conceptos de Mozzi, me gustaría decir únicamente que los eventos críticos en el tiempo
deben manejarse con más cuidado que las acciones humanas.
De hecho, aunque parezca que podemos ser muy rápidos al girar un potenciómetro, es realmente lento
en comparación con la frecuencia de muestreo de Mozzi, por ejemplo (16.384 kHz). Esto significa que
no podemos detener todo el proceso solo para probar y verificar, si cambiamos el valor de este
potenciómetro constantemente. Las cosas están separadas; tenga esto en cuenta y use el marco con
cuidado.
[ 342 ]
www.itebooks.info
Machine Translated by Google
Capítulo 9
Este valor se utiliza luego en un nuevo método llamado phMod. Este método aplica una modulación de fase al
oscilador para el que se lo llama. Esta modulación es una buena manera de producir un efecto de modulación
de frecuencia.
Ahora, cargue el firmware, agregue el auricular y gire el potenciómetro. Debería poder escuchar el efecto
y controlarlo con el potenciómetro.
Ahora podemos diseñar pequeños fragmentos de un motor de sonido con Mozzi. Existen otras bibliotecas y lo
que hemos aprendido se utilizará con ellas. De hecho, son patrones.
Veamos cómo podemos controlar nuestro motor de sonido basado en Arduino utilizando un protocolo
estándar desde un ordenador u otro dispositivo. De hecho, sería interesante poder activar notas para cambiar
los parámetros del sonido utilizando un ordenador, por ejemplo.
Ambos son protocolos utilizados en proyectos y trabajos relacionados con la música y los nuevos medios.
MIDI puede transportar los siguientes datos a través de un enlace serial básico:
Apareció un nuevo protocolo que hoy en día se utiliza ampliamente: OSC. Por cierto, no es un protocolo
propiamente dicho.
[ 343 ]
www.itebooks.info
Machine Translated by Google
OSC son las siglas de Open Sound Control y es un formato de contenido desarrollado por dos personas
del Centro de Nueva Música y Tecnologías de Audio (CNMAT) de la Universidad de Berkeley,
California. En un principio, estaba pensado para compartir gestos, parámetros y secuencias de notas
durante interpretaciones musicales. Hoy en día, se utiliza mucho como sustituto del MIDI, ya que ofrece una
mayor resolución y una transferencia más rápida. Su principal característica es la posibilidad de
transporte en red nativo. OSC se puede transportar a través de UDP o TCP en un entorno IP, lo que
facilita su uso a través de redes WiFi e incluso a través de Internet.
Generando sobres
En el campo del audio, una envolvente es una forma que se utiliza para modificar algo. Por ejemplo,
imaginemos una envolvente de amplitud que da forma a una forma de onda.
Primero tienes una forma de onda. Generé esta onda sinusoidal con el sintetizador Operator en
Ableton Live (https://www.ableton.com), la famosa estación de trabajo de audio digital.
Aquí hay una captura de pantalla:
Una onda sinusoidal básica generada por un operador en el sintetizador Operator FM de Ableton Live
[ 344 ]
www.itebooks.info
Machine Translated by Google
Capítulo 9
La onda sinusoidal no se muestra muy bien debido al aliasing; aquí hay otra captura de pantalla, que es
la misma onda pero más ampliada:
Esta onda sinusoidal tiene una amplitud constante global. Por supuesto, la presión del aire empuja y
tira constantemente, pero los máximos y mínimos globales son constantes a lo largo del tiempo.
Los músicos siempre quieren que sus sonidos evolucionen con el tiempo, de forma sutil o áspera.
Apliquemos a esta misma onda una envolvente que hará que aumente progresivamente el
volumen global, luego lo disminuya un poco, y luego disminuya rápidamente hasta cero:
Una onda sinusoidal alterada por una envolvente con un ataque largo
[ 345 ]
www.itebooks.info
Machine Translated by Google
Una onda sinusoidal alterada por una envolvente con un ataque muy corto
Básicamente, una envolvente es una serie de puntos en el tiempo. En cada momento, multiplicamos el
valor de la señal original por el valor de la envolvente.
Podemos utilizar las envolventes en muchos casos porque pueden modular la amplitud, como acabamos
de aprender. También podemos utilizarlas para alterar el tono (es decir, la frecuencia) de un sonido.
Generalmente, las envolventes se activan (es decir, se aplican al sonido) al mismo tiempo que se activa el
sonido, pero, por supuesto, podemos usar la función de reactivación por desplazamiento para reactivar la
envolvente durante el mismo sonido activado y hacer mucho más.
A continuación, se muestra un último ejemplo que muestra una envolvente de tono. La envolvente hace que
la frecuencia del sonido disminuya. Como puede ver, las ondas son más estrechas en el lado izquierdo
que en el derecho. El sonido cambia de agudo a grave.
[ 346 ]
www.itebooks.info
Machine Translated by Google
Capítulo 9
La parte MIDI será manejada por la biblioteca y la envolvente será explicada y codificada.
Puedes consultar el siguiente código. Este código también está disponible en la carpeta Chapter09/
MozziMIDI/ .
#include <MIDI.h>
#include <MozziGuts.h>
#include <Oscil.h> // plantilla del oscilador #include <Line.h> //
para la envolvente #include <utils.h> // para mtof
#include <tables/sin2048_int8.h> // tabla de
senos para el oscilador
// declara un oscilador usando una tabla de ondas de tono sinusoidal // usa: Oscil
<table_size, update_rate> oscilName (wavetable)
Oscil < SIN2048_NUM_CELDAS , VELOCIDAD_DE_AUDIO > aSin( SIN2048_DATOS );
// para sobre
Línea <unsigned int> aGain; unsigned
int release_control_steps = CONTROL_RATE; // 1 segundo de
control
unsigned int release_audio_steps = 16384; // 1 segundo de audio int fade_counter;
unsigned int freq; // para transmitir información de control desde el controlador MIDI a updateControl()
[ 347 ]
www.itebooks.info
Machine Translated by Google
// Velocidad de escala para desvanecimiento lineal de alta resolución en Noteoff más tarde
frecuencia = mtof(tono);
aGain.set(velocity<<8); // podría ser necesario un fundido de entrada para evitar clics
// Velocidad de escala para desvanecimiento lineal de alta resolución en Noteoff más tarde
aGain.set(0,liberar_pasos_de_audio);
contador_de_desvanecimiento = pasos_de_control_de_liberación;
}
configuración vacía() {
vacío updateControl(){
// Lo ideal es llamar a MIDI.read lo más rápido que pueda para tiempo real
actuación.
// En la práctica, se requiere un equilibrio entre el tiempo real
[ 348 ]
www.itebooks.info
Machine Translated by Google
Capítulo 9
int actualizaciónAudio(){
// aGain se reduce a un rango utilizable
devuelve (int) ((aGain.next()>>8) * aSin.next() * vol )>>8; // >>8
Desplaza el resultado multiplicado de nuevo al rango de salida utilizable
}
bucle vacío() {
audioHook(); // requerido aquí
}
Por supuesto, los elementos correctos de Mozzi a incluir son un poco diferentes para cada proyecto.
Estudiar ejemplos ayuda a entender qué va en cada lugar. Aquí, no solo necesitamos a Oscil para las
características básicas del oscilador, sino que también necesitamos a Line. Line está relacionado con
las funciones de interpolación en Mozzi. La generación de una envolvente se ocupa de esto. Básicamente,
elegimos dos valores y una duración de tiempo, y comienza desde el primero y llega al segundo en la
duración de tiempo que elijas.
Definimos una tasa de control más alta que antes, en 128. Eso significa que updateControl()
La función se llama 128 veces por segundo.
Después de estos bits, definimos un sobre declarando una instancia del objeto Línea.
Definimos dos variables que almacenan la parte de liberación de la duración de la envolvente, una para
la parte de control en un segundo (es decir, el número de pasos será el valor de CONTROL_RATE) y una
para la parte de audio en un segundo también (es decir, 16.384 pasos).
Por último, se define una variable llamada fade_counter .
[ 349 ]
www.itebooks.info
Machine Translated by Google
• Canal MIDI
• Número de CC
• Valor
Esta es una forma muy común de utilizar controladores de eventos. Casi todos los marcos
de escucha de eventos están hechos de esta manera. Tienes algunas funciones y puedes usarlas
y poner lo que quieras dentro de ellas. El marco en sí mismo maneja las funciones que deben
llamarse, ahorrando tanto tiempo de CPU como sea posible.
Aquí, agregamos una declaración de cambio con un solo caso sobre la variable CCNumber .
Esto significa que si envía un mensaje MIDI Control Change 100, en este caso, se procesará
el valor de CC y se alterará y modificará la variable vol . Este Control Change controlará el volumen
de salida maestro del sintetizador.
Básicamente, se envía un mensaje de nota MIDI activada cuando presionas una tecla en tu
teclado MIDI. Tan pronto como sueltas esa tecla, aparece un mensaje de nota MIDI desactivada.
[ 350 ]
www.itebooks.info
Machine Translated by Google
Capítulo 9
De esta manera, tenemos un sistema que responde a los mensajes MIDI Note On y MIDI Note Off. Cuando
pulsamos una tecla, se produce un sonido hasta que soltamos la tecla. Cuando la soltamos, el sonido
disminuye linealmente hasta 0, tardando un segundo.
Este es el lugar perfecto para leer nuestro flujo MIDI, con la función MIDI.read() .
Aquí es donde podemos activar nuestra envolvente decreciente a 0 tan pronto como se desvanezca.
el contador llega a 0 y no antes, emitiendo el sonido en un segundo, como ya hemos
comprobado anteriormente.
Por último, la función updateAudio() devuelve el valor del oscilador multiplicado por el valor de la envolvente.
Este es el propósito de la envolvente. Luego, vol multiplica el primer resultado para agregar una tecla para
controlar el volumen de salida principal.
Las expresiones <<8 y >>8 aquí son para configurar un desvanecimiento lineal de alta resolución en
Note Off, y este es un buen truco proporcionado por el propio Tim Barrass.
[ 351 ]
www.itebooks.info
Machine Translated by Google
[ 352 ]
www.itebooks.info
Machine Translated by Google
Capítulo 9
Como puedes ver, el pin digital 0 (entrada serial) está involucrado. Esto significa que no podremos
usar la comunicación serial a través de USB. De hecho, queremos usar nuestra interfaz MIDI.
[ 353 ]
www.itebooks.info
Machine Translated by Google
El secuenciador barato para chips dispara notas MIDI y cambios de control MIDI
El secuenciador se explica por sí solo. Activa el botón de alternancia en la parte superior izquierda y
se iniciará el secuenciador, que leerá cada paso en el objeto multislider. Cuanto más alto esté el control
deslizante, más alto será el tono de esta nota en ese paso.
Puede hacer clic en el botón debajo del control deslizante múltiple a la izquierda y se generará una
secuencia aleatoria de 16 elementos.
Seleccione el bus de salida MIDI correcto en el menú de lista en la parte superior derecha.
Conecta tu circuito Arduino y tu interfaz MIDI con un cable MIDI y escucha la música. Cambia el contenido
del multislider y la secuencia que se reproduce. Si giras el dial, cambiará el volumen.
Aquí todo se transmite por MIDI. El ordenador es un secuenciador y un mando a distancia y el Arduino
es el sintetizador.
[ 354 ]
www.itebooks.info
Machine Translated by Google
Capítulo 9
Las muestras de audio definen contenido digital, a menudo almacenados como archivos en sistemas de
archivos que pueden leerse y convertirse en sonido audible.
Las muestras pueden ser muy pesadas desde el punto de vista del tamaño de la memoria.
Vamos a utilizar la biblioteca PCM creada por David A. Mellis del MIT. Al igual que otros colaboradores,
está feliz de formar parte de este libro.
La biblioteca PCM
Comprueba este código. También está disponible en la carpeta Chapter09/PCMreader/ .
[ 355 ]
www.itebooks.info
Machine Translated by Google
Hay una matriz de tipos de datos de caracteres sin signo declarados como const, y especialmente con la palabra
clave PROGMEM denominada sample.
PROGMEM obliga a que esta constante se coloque en el espacio del programa en lugar de en la RAM,
porque esta última es mucho más pequeña. Básicamente, este es el ejemplo. La función startPlayback()
La función puede reproducir una muestra de una matriz. El método sizeof() calcula el tamaño de la memoria
de la matriz.
Si bien la lectura dinámica del archivo de audio desde una tarjeta SD parece más inteligente, PCM ofrece una forma
aún más sencilla de hacerlo: leer directamente una conversión analógica de una matriz mientras se almacena una
forma de onda en un sonido.
David Ellis creó un pequeño programa de código abierto basado en procesamiento que proporciona una forma
de hacer esto; se puede encontrar en https://github.com/damellis/EncodeAudio.
Puedes descargarlo desde la página del proyecto de referencia compilado directamente para tu sistema operativo.
Ejecútalo, elige un archivo WAV (muestra codificada basada en PCM) y luego copiará algo enorme en tu
portapapeles.
Luego solo tienes que copiar y pegar este contenido en la matriz definida anteriormente.
[ 356 ]
www.itebooks.info
Machine Translated by Google
Capítulo 9
Aquí está el contenido copiado del portapapeles después de convertir una muestra wav que hice yo
mismo:
En la misma carpeta he metido un archivo .wav que he diseñado. Es un ritmo corto grabado en 16 bits.
[ 357 ]
www.itebooks.info
Machine Translated by Google
[ 358 ]
www.itebooks.info
Machine Translated by Google
Capítulo 9
Puedes encontrar muchos en Internet, pero ten cuidado porque algunos de ellos requieren algunos
protectores, como el que se encuentra en el sitio web de Sparkfun en https://www.sparkfun.com/
productos/10628.
Esto proporciona un escudo con un lector de tarjetas SD, un conector para auriculares estéreo de 3,5
mm, un registro de desplazamiento VS1053 y chips decodificadores muy versátiles para MP3, WMA,
AAC y otros formatos.
[ 359 ]
www.itebooks.info
Machine Translated by Google
Es una solución muy dedicada y solo tenemos que interconectar el shield con Arduino.
Arduino solo envía y recibe bits del shield, que se encarga de la decodificación de los archivos
codificados, la conversión a señales analógicas, etc.
Resumen
Aprendimos cómo hacer que las cosas se muevan aquí con Arduino. En particular, aprendimos sobre:
Por supuesto, lamentablemente no puedo describir más sobre cómo hacer que las cosas se muevan.
Este es el final de la segunda parte del libro. Descubrimos muchos conceptos juntos y ahora vamos
a profundizar en algunos temas más avanzados.
Somos capaces de comprender el diseño del firmware y las entradas y salidas, así que
avancemos.
Vamos a profundizar en ejemplos precisos con comunicación I2C/SPI para utilizar módulos GPS,
sistemas LED de 7 segmentos y más. También vamos a profundizar en Max 6, y especialmente en cómo
podemos usar Arduino para controlar algunos elementos visuales OpenGL en la computadora.
Descubriremos protocolos de red y cómo usar Arduino incluso sin cables de red, con WiFi. Por último,
diseñaremos una pequeña biblioteca juntos y revisaremos algunos buenos consejos y trucos para mejorar
nuestro código C.
[ 360 ]
www.itebooks.info
Machine Translated by Google
También vamos a probar las comunicaciones entre las propias placas Arduino, utilizar módulos GPS,
hacer autónomas nuestras placas, y más.
Como hemos observado, cuando los apagamos, se pierden todas las variables y datos vivos.
Afortunadamente, el firmware no lo es.
• Memoria flash
• Memoria RAM
• Memoria EEPROM
www.itebooks.info
Machine Translated by Google
ATmega168 tiene:
Lo interesante aquí es el espacio EEPROM. Nos permite almacenar datos en Arduino y eso no
lo sabíamos hasta ahora. Probemos la librería nativa EEPROM.
#include <EEPROM.h>
configuración vacía()
{
// inicializa el serial y espera que se abra el puerto:
Serie.begin(9600);
}
bucle vacío()
{
// lee un byte de la dirección actual de la EEPROM
valor = EEPROM.read(dirección);
[ 362 ]
www.itebooks.info
Machine Translated by Google
Capítulo 10.
Serial.print(dirección);
Serie.print("\t");
Serial.print(valor, DEC);
Serie.println();
retraso(500);
}
Este código es de dominio público y se proporciona como ejemplo para la biblioteca EEPROM. Puede
encontrarlo en la carpeta de ejemplos del menú Archivo del IDE de Arduino, en la carpeta Ejemplos | EEPROM.
Primero, incluimos la biblioteca en sí. Luego, definimos una variable para almacenar la dirección de lectura
actual. La inicializamos en 0, el comienzo del registro de memoria. También definimos una variable
como un tipo de byte.
En la función setup() , inicializamos la comunicación serial. En loop(), leemos el byte en la dirección actual
y lo almacenamos en la variable value. Luego, imprimimos el resultado en el puerto serial. Observe el
valor \t en el segundo Serial.print()
Declaración. Esto significa tabulación (como en la tecla Tab en un teclado de computadora).
Esto escribe una tabulación en el puerto serial entre la dirección actual impresa y el valor en sí para que las
cosas sean más legibles.
Añadimos un pequeño retardo. Podemos escribir bytes de la misma forma utilizando EEPROM.
write(addr, val); donde addr es la dirección donde desea escribir el
valor val.
Tenga cuidado, son bytes (8 bits = 256 valores posibles). Las operaciones de lectura y escritura son
bastante fáciles en la EEPROM interna, así que veamos cómo funciona con las EEPROM externas
conectadas mediante una conexión I2C.
[ 363 ]
www.itebooks.info
Machine Translated by Google
[ 364 ]
www.itebooks.info
Machine Translated by Google
Capítulo 10.
3V3 5V Venir
Fuerza
D13
ARÉF D11
Modulación por ancho de pulso (PWM)
D9
Modulación por ancho de pulso (PWM)
D8
D7
24LC1025 D6
Modulación por ancho de pulso (PWM)
Entrada/
salida
digital
D5
Modulación por ancho de pulso (PWM)
Entrada analógica
1 8
A0 +V A0 D4
2 7
A1 A1 D3
Modulación por ancho de pulso (PWM)
Trabajo en equipo
3 6
A2 (CS) LCC A2 D2
4 5 Tejas
VO Adventista del Séptimo Día A3 D1
Recepción
A4 D0
A5 LCC
Tierra
Describamos la EEPROM.
SCL y SDA son los dos cables que intervienen en la comunicación I2C y están conectados a SDA / SCL.
SDA significa Serial Data Line y SCL significa Serial Clock Line.
Tenga cuidado con los pines SDA/SCL. Lo siguiente depende de su placa:
[ 365 ]
www.itebooks.info
Machine Translated by Google
La biblioteca Wire se encarga de muchas cosas por nosotros. Veamos el código en la carpeta
Chapter10/readWriteI2C:
#include <Cable.h>
Wire.requestFrom(dirección, 1);
si(Cable.disponible())
devuelve Wire.read();
demás
devuelve 0xFF;
}
configuración vacía() {
Cable.begin();
Serial.begin(9600);
[ 366 ]
www.itebooks.info
Machine Translated by Google
Capítulo 10.
Serie.print(i);
Serie.print("\t");
Serie.print(val);
Serie.print("\n");
retraso(1000);
}
}
• eepromWrite()
• eepromLectura()
Estas funciones escriben y leen bytes hacia y desde la EEPROM externa utilizando la biblioteca Wire .
La función Setup() crea una instancia de la comunicación por cable y por serie . Luego, mediante un
bucle for , escribimos datos en una dirección específica. Estos datos son básicamente un carácter "a" más
un número. Esta estructura escribe caracteres desde a hasta a + 9, lo que significa "j".
Este es un ejemplo para mostrar cómo podemos almacenar cosas rápidamente, pero, por supuesto,
podríamos haber escrito datos más significativos.
Luego imprimimos un mensaje en el Monitor Serial para avisarle al usuario que Arduino ha terminado
de escribir en la EEPROM.
Obviamente, todavía no hemos hablado de direcciones. Aquí hay un formato de mensaje I2C:
Bit de lectura/escritura
S 1 0 1 0 A2 A1 A0 R/W ACK
Dirección de esclavo
Un mensaje I2C
[ 367 ]
www.itebooks.info
Machine Translated by Google
La biblioteca de cables se encarga del bit de inicio y del bit de reconocimiento. El código de control es fijo y
puedes cambiar los bits de selección de chip conectando los pines A0, A1 y A2 a tierra o +V. Eso significa que
hay 8 posibilidades de direcciones de 0 a 7.
1010000 1010001… hasta 1010111. 1010000 en binario significa 0x50 en hexadecimal, y 1010111 significa
0x57.
En nuestro caso, conectamos A0, A1 y A2 a tierra, por lo que la dirección de la EEPROM en el bus I2C es
0x50. Podríamos usar más de uno en el bus I2C, pero solo si necesitamos más capacidad de
almacenamiento. De hecho, tendríamos que direccionar los diferentes dispositivos dentro de nuestro firmware.
Ahora podríamos imaginar almacenar muchas cosas en ese espacio EEPROM, desde muestras para
reproducir audio PCM hasta, eventualmente, enormes tablas de búsqueda o cualquier cosa que requiera
más memoria que la disponible en Arduino.
Básicamente, un receptor que recibe señales de al menos cuatro satélites con un reloj atómico especial
incorporado puede, calculando el tiempo de propagación de estas señales entre ellos y él mismo, calcular
con precisión su posición tridimensional. Eso suena mágico, pero es simplemente trigonométrico.
[ 368 ]
www.itebooks.info
Machine Translated by Google
Capítulo 10.
1,42"
(36,2 mm)
Receptor GPS
1,93" 1,67"
(9,0 mm) (42,5 mm)
Estrella polar
Tierra
CCV
NO
/
0,1"
O 0,134"
(2,54 mm)
(3,4 mm)
1,17"
(29,7 mm)
Proporciona cadenas NMEA01823 estándar sin procesar o incluso datos específicos solicitados
por el usuario a través de la interfaz de comandos en serie. Puede rastrear 12 satélites e incluso
WAAS (sistema disponible solo en EE. UU. y Hawái para ayudar al cálculo de la señal GPS).
El módulo proporciona hora actual, fecha, latitud, longitud, altitud, velocidad y dirección/rumbo
de viaje, entre otros datos.
Podemos escribir datos en los módulos GPS para solicitar cadenas específicas. Sin embargo, si
bajamos el pin /RAW , los módulos transmiten automáticamente algunas cadenas. Estas
cadenas son:
[ 369 ]
www.itebooks.info
Machine Translated by Google
Arduino debe obtener estos datos y, en última instancia, utilizarlos. Primero, verifiquemos el cableado:
El receptor GPS Parallax conectado al Arduino en modo automático bajando el pin /RAW
Sí, el receptor GPS Parallax solo consume un pin de datos: el pin digital 0. Detengámonos aquí por dos
segundos. ¿No hablamos del hecho de que no podemos usar el puerto USB para monitoreo serial y los pines 0
y 1 para otras funciones seriales al mismo tiempo en Arduino?
Con la comunicación en serie utilizando 2 cables Rx/Tx, la implementación del software en serie puede ser full
duplex.
En nuestro caso, el dispositivo GPS envía datos al pin Rx de Arduino. Este pin (pin digital 0) está
conectado al pin USB Rx. Al mismo tiempo, Arduino envía datos al ordenador mediante el pin USB Tx que
está conectado al pin digital 1.
¿Hay algún problema en nuestro caso? No. Solo tenemos que ocuparnos de las interferencias.
No debemos enviar datos desde el ordenador vía USB al Arduino porque éste ya recibe datos en su pin serial 0
desde el dispositivo GPS. Esto es lo único que tenemos que hacer.
ten cuidado con
La función Serial.write() escribirá en el pin digital 1, y el pin digital 1 del transmisor USB no está conectado
a ningún dispositivo. Por lo tanto, no hay problema, los datos se enviarán al USB.
La función Serial.read() lee desde el pin digital 0 y USB y no enviamos nada desde la computadora al USB,
por lo que puede leer el pin digital 0 sin ningún problema.
Ponemos el pin /RAW en modo bajo. En este modo, el dispositivo envía datos al Arduino automáticamente, es
decir, sin necesidad de solicitarlo.
[ 370 ]
www.itebooks.info
Machine Translated by Google
Capítulo 10.
$GPRMC,220516,A,5133.82,N,00042.24,W,173.8,231.8,130694,004.2,W*70
$GPRMC define el tipo de secuencia de información enviada. La coma es un separador que separa cada campo de datos.
Una vez que sabemos qué datos se envían, podemos codificar un analizador sintáctico en nuestro firmware. A continuación
se muestra un posible firmware. Puede encontrarlo en la carpeta Chapter10/locateMe:
[ 371 ]
www.itebooks.info
Machine Translated by Google
configuración vacía() {
pinMode(rxPin, ENTRADA);
Serial.begin(4800);
bucle vacío() {
contador=0;corrección=0;
}
}
if(correctness==6){ // Estamos
seguros de que el comando está bien aquí.
//
para (int i=0;i<300;i++){
[ 372 ]
www.itebooks.info
Machine Translated by Google
Capítulo 10.
índice[contador]=i;
contador++;
}
// almacena la posición de "*" si (línea[i]=='*') separador que significa el último byte // ... y el "*"
{ índice[12]=i; contador++;
}
}
caso 1 :
Serial.print("Estado (A=OK,V=KO): "); break; caso 2 :
caso 4 :
Serial.print("Longitud: "); break; caso 5 : Serial.print("Dirección
(E/O): ");
break;
caso 6 :
Serial.print("Velocidad en nudos: "); break; case 7 :
caso 9 :
Serial.print("Grados magnéticos: "); break;
[ 373 ]
www.itebooks.info
Machine Translated by Google
caso 10 :
caso 11 :
Serial.print("Modo: "); break; caso 12 :
}
serie.println("");
}
Serie.println("");
}
// Restablecer el buffer
lineCounter=0; for (int
i=0;i<300;i++){ line[i]=' ';
}
}
}
}
[ 374 ]
www.itebooks.info
Machine Translated by Google
Capítulo 10.
En la función setup() , primero definimos el pin digital 0 como entrada y luego iniciamos la comunicación serial
con una velocidad de 4800 baudios según lo requerido por la interfaz serial del receptor GPS Parallax (recuerde
siempre verificar sus hojas de datos). Luego, limpiamos nuestro buffer de matriz lineal llenándolo con un
carácter de espacio.
En la función loop() , comenzamos leyendo bytes de la entrada serial, siendo el pin digital 0. Si el puerto no
está vacío, lo ingresamos en la segunda parte de la prueba condicional if definida por el bloque else . Si está
vacío, simplemente esperamos 100 ms y luego intentamos leerlo nuevamente.
En primer lugar, el análisis comienza colocando los datos leídos en el buffer de línea en este
índice particular de la matriz: lineCounter. Luego, incrementamos este último para almacenar los datos
recibidos.
A continuación, imprimimos los datos leídos como una línea sin procesar en el puerto USB. Es en este momento
que el Serial Monitor puede recibirlos y mostrarlos como la fila de datos sin procesar que citamos anteriormente
como ejemplo.
Luego, probamos los datos en sí, comparándolos con 13. Si es igual a 13, significa que la
comunicación de datos ha finalizado y podemos comenzar a analizarlos.
Este es un patrón clásico. De hecho, si todas las pruebas son verdaderas, significa que la corrección es igual a 6
al final. Luego solo tenemos que verificar si la corrección es igual a 6 para ver si todas las pruebas han sido
verdaderas y si los primeros 6 caracteres son iguales a $GPRMC.
Si este es el caso, podemos estar seguros de que tenemos una secuencia sin procesar NMEA correcta del tipo
$GPRMC y podemos comenzar a analizar realmente la parte de carga útil de los datos.
Primero, dividimos nuestra cadena sin procesar almacenando la posición en la cadena de cada separador de
coma. Luego hacemos lo mismo con el último separador de parte, el carácter "*". En este punto, podemos
distinguir qué carácter pertenece a qué parte de la cadena, es decir, a qué parte del mensaje sin procesar.
Es un bucle entre cada valor del mensaje sin procesar, y probamos cada valor utilizando una estructura switch/
case para mostrar la oración correcta que introduce cada valor del mensaje de datos GPS.
La parte más complicada, finalmente, es el último bucle for() . No empezamos como de costumbre. De hecho,
iniciamos el índice j en el bucle utilizando el índice de la matriz en la posición específica i.
[ 375 ]
www.itebooks.info
Machine Translated by Google
A continuación se muestra un pequeño esquema que muestra los índices alrededor del mensaje sin procesar:
yo
$GPRMC,220516,5133.82,N,00042.24,W,173.8,231.8,130694,004.2,W*70
línea[j+1]
Incrementamos progresivamente según la posición de cada separador y mostramos cada valor. Esta es
una forma de analizar y utilizar datos de ubicación mediante un módulo GPS.
Estos datos se pueden utilizar de muchas maneras, según el propósito. A mí me gusta la
visualización de datos, y realicé pequeños proyectos para estudiantes con un módulo GPS que capta la
ubicación cada 30 segundos mientras caminamos por la calle y la escribe en una EEPROM. Luego, utilicé
estos datos para hacer algunos gráficos. Uno que me gustó mucho es el siguiente:
Visualización de datos diseñada con Processing a partir de un conjunto de datos proporcionado por un módulo GPS Arduino
[ 376 ]
www.itebooks.info
Machine Translated by Google
Capítulo 10.
Cada línea es una marca de tiempo. El tamaño de la línea representa el tiempo que transcurrió entre dos
mediciones de mi módulo GPS basado en Arduino. Cuanto más larga es la línea, más tiempo transcurrió en este
paso del viaje.
Tu pregunta podría ser: ¿Cómo alimentaste tu módulo Arduino + GPS caminando por la calle?
Ahora veamos cómo podemos hacer que el Arduino sea autónomo usando baterías.
Ya hemos utilizado el USB para suministrar energía al Arduino desde el principio de esta sección. Es una buena
manera de empezar (e incluso de hacer un gran proyecto). Es fácil y funciona para muchos propósitos.
También podemos utilizar una fuente de alimentación externa cuando necesitemos más autonomía y
movilidad con nuestros dispositivos Arduino.
En cualquier caso, debemos tener en cuenta que tanto nuestro Arduino como nuestros circuitos conectados a él
necesitan alimentación. Por lo general, el consumo de Arduino no supera los 50 mA. Añade algunos LED y verás que
el consumo aumenta.
Obviamente, si necesitamos que nuestro ordenador esté conectado a nuestro Arduino para
fines de comunicación de datos, naturalmente podemos suministrar energía al Arduino a través del USB.
También hay algunos casos en los que no podemos tener muchas tomas de corriente. A veces, hay muchas
limitaciones en los proyectos de diseño de instalaciones y no tenemos muchas tomas de corriente. Este es también
un caso de suministro de energía mediante USB.
[ 377 ]
www.itebooks.info
Machine Translated by Google
Básicamente lo primero que debemos tener en cuenta antes de utilizar la energía suministrada por el puerto USB es
el consumo global de nuestro circuito.
De hecho, como ya hemos visto, la corriente máxima que puede suministrar un puerto USB ronda los
500 mA. Hay que tener cuidado de no superar este valor. Por encima de este límite de consumo, las cosas se
vuelven totalmente impredecibles y algunos ordenadores pueden incluso reiniciarse mientras que otros pueden
desactivar todos los puertos USB. Hay que tenerlo en cuenta.
• Baterías
• Adaptadores de corriente
Suministro de baterías
Si recordamos correctamente, el Arduino Uno y Mega, por ejemplo, pueden funcionar con una fuente de alimentación
externa de 6 V a 20 V. Para un uso estable, el rango recomendado es de 7 V a 12 V. 9 V es un voltaje ideal.
Para poder configurar la placa para alimentación externa, hay que tener cuidado con el puente de
alimentación. Tenemos que ponerlo en el lado de la alimentación externa, llamado EXT.
Esta configuración es para Arduino Diecimilla y placas Arduino más antiguas:
El puente de la fuente de alimentación se coloca en el lado EXT, lo que significa que está configurado para una fuente de alimentación externa.
[ 378 ]
www.itebooks.info
Machine Translated by Google
Capítulo 10.
Este sencillo cableado proporciona una forma de suministrar energía a la placa Arduino. Si conecta otros
circuitos a Arduino, la batería los alimentará a través de Arduino.
También existen otros tipos de baterías que podemos utilizar. Las baterías tipo botón son una buena
manera de ahorrar espacio y, al mismo tiempo, suministrar energía externa:
[ 379 ]
www.itebooks.info
Machine Translated by Google
Existen muchos tipos de soportes para pilas de botón para utilizar este tipo de batería en nuestros circuitos.
Por lo general, las baterías tipo botón proporcionan 3,6 V a 110 mAh. Si esto no puede suministrar energía al
Arduino Uno, puede suministrar fácilmente energía al Arduino Pro Mini que funciona a un voltaje
de 3,3 V:
La placa Arduino Pro Mini es realmente interesante ya que se puede integrar en muchos circuitos
que necesitan ser discretos y a veces ocultos en paredes para instalaciones de arte digital o
colocarse en una pequeña caja de plástico que se puede llevar en un bolsillo cuando se usan como
herramienta móvil.
También podemos utilizar baterías de iones de litio de polímero. Las utilicé un par de veces para un proyecto de
dispositivo autónomo.
Sin embargo, podemos tener algunos proyectos que requieran más potencia.
• Capaz de generar una corriente mínima de 250 mA, pero con un objetivo de 500 mA como mínimo o
Preferiblemente 1A
[ 380 ]
www.itebooks.info
Machine Translated by Google
Capítulo 10.
Estos son los patrones que debes buscar en tu adaptador antes de conectar el Arduino.
En primer lugar, el centro del conector debe ser la parte positiva; consulta el siguiente diagrama. Deberías ver
eso en un adaptador compatible con Arduino:
Luego, las características de voltaje y corriente. Esto debe mostrar algo como: SALIDA: 12 VCC 1 A.
Este es un ejemplo; 12 VCC y 5 A también está bien. No olvide que la corriente solo se activa según lo que haya
en su circuito. Un adaptador de corriente que emita una corriente más alta no dañará su circuito, porque un
circuito solo consumirá lo que necesita.
Hay muchos adaptadores disponibles en el mercado que se pueden utilizar con nuestras
placas Arduino.
Cuando revisas la hoja de datos de un componente, como un LED, puedes ver la corriente que pasa a
través de él.
Verifiquemos el cátodo común del LED RGB con esta hoja de datos: https://www.
sparkfun.com/datasheets/Components/YSLR596CR3G4B5CC10.pdf
Podemos ver una corriente directa de 20 mA y una corriente directa máxima de 30 mA. Si tenemos cinco LED
como ese encendidos con el brillo máximo (es decir, rojo, azul y verde encendidos), tenemos: 5 x (20 + 20 +
20) = 300 mA necesarios para un uso normal e incluso los picos consumirían 5 x (30 + 30 + 30) = 450 mA.
Esto ocurre en el caso en que todos los LED están completamente encendidos al mismo tiempo.
[ 381 ]
www.itebooks.info
Machine Translated by Google
No describiré aquí los cálculos para cada caso, pero habría que consultar las normas de
electricidad para calcular con precisión el consumo.
Por experiencia, no hay nada mejor que el voltímetro y el amperímetro, el primero midiendo el voltaje
entre dos puntos y el segundo midiendo la corriente en algunos puntos a lo largo del circuito.
• No anule el límite de 450 mA del USB, en caso de utilizar una fuente de alimentación USB
Luego de esto, comience a cablear y medir al mismo tiempo con un voltímetro y un amperímetro.
Por fin, una referencia clásica para la mayoría de las placas Arduino está disponible en esta página:
http://playground.arduino.cc/Main/ArduinoPinCurrentLimitations.
Podemos encontrar las limitaciones de consumo de corriente para cada parte del Arduino.
Existen muchos tipos de pantallas LCD. Los dos tipos principales son las de caracteres y las gráficas.
Estamos hablando del tipo gráfico aquí, especialmente de aquellos basados en el controlador solo gráfico
KS0108 utilizado en muchos dispositivos gLCD normales.
Vamos a utilizar una biblioteca muy útil que está disponible en Google. Tiene código de Michael Margolis
y Bill Perry y se llama glcdarduino. Esta biblioteca tiene licencia GNU Lesser GPL.
Descomprímelo, colócalo en el lugar donde están todas tus librerías y reinicia o inicia tu IDE de
Arduino.
No revisaremos aquí todas las características y funciones interesantes que ofrece esta biblioteca, pero
puedes consultar esta página en el sitio web de Arduino: http://playground.arduino.cc/
Código/GLCDks0108.
[ 382 ]
www.itebooks.info
Machine Translated by Google
Capítulo 10.
Un montón de cables que conectan el gLCD a Arduino y el potenciómetro para ajustar el contraste del LCD.
20 20 K()
Alta definición de 128 x 64
19 A(+)
R2
Salida de 18 V
3V3 5V Venir
17 RESTABLECER
Fuerza
D13
16 CS2
Primera vez D12
15 CS1
ARÉF D11
Modulación por ancho de pulso (PWM)
D9 13 DB6
Modulación por ancho de pulso (PWM)
D8 12 DB5
D7 11 DB4
D6
Modulación por ancho de pulso (PWM)
10 DB3
Entrada/
salida
digital
D5
Modulación por ancho de pulso (PWM)
9 DB2
A0 D4
Entrada analógica
8 DB1
A1 D3
Modulación por ancho de pulso (PWM)
7 DB0
A2 D2
A3 D1
Tejas
6 HABILITAR
Recepción
A4 D0 5 R/E
A5 LCC 4 DI
R1
Adventista del Séptimo Día
3 pulgadas
Tierra
2 Vdc
1 vs
[ 383 ]
www.itebooks.info
Machine Translated by Google
Son muchos cables. Por supuesto, podemos multiplicar las cosas. También podemos utilizar un
Arduino MEGA y seguir utilizando el otro pin digital disponible para otros fines, pero ese no es el
objetivo aquí. Veamos algunas de las funciones de esta potente librería.
Demostración de la biblioteca
Tomemos el ejemplo llamado GLCDdemo. En él se muestran casi todas las funciones disponibles
en la biblioteca.
Junto con la biblioteca se incluye una documentación en formato PDF muy útil que explica cada
método disponible. Puede encontrarla en la carpeta de la biblioteca , en la subcarpeta doc :
[ 384 ]
www.itebooks.info
Machine Translated by Google
Capítulo 10.
Primero, tenemos que incluir glcd.h para poder usar la biblioteca. Luego, tenemos que
incluir otros encabezados, en este ejemplo, fuentes y mapa de bits para poder usar los
métodos tipográficos de fuentes y también los objetos de mapa de bits.
• Métodos de dibujo
• Métodos de texto
La función SetDisplayMode() es útil porque configura el uso de la pantalla LCD como normal
(escritura en negro sobre fondo blanco) o invertida. Blanco simplemente significa que no es
negro. El color real depende del color de la luz de fondo, por supuesto.
La función ClearScreen() borra la pantalla, llenándola de fondo blanco en modo normal, o negro
en modo invertido.
Las funciones ReadData() y WriteData() son realmente métodos básicos que obtienen y establecen
el byte de datos en coordenadas particulares.
Métodos de dibujo
Se trata de un conjunto de funciones dedicadas a dibujar en la pantalla.
[ 385 ]
www.itebooks.info
Machine Translated by Google
Función Descripción
Ir a XY() Mueve el cursor a coordenadas específicas
DibujarVLine() Dibuja una línea vertical desde un punto a otro punto en la misma columna de
píxeles pero por encima o por debajo del punto inicial
DibujarHLine() Funciona igual que DrawVLine() pero en la misma fila de píxeles
Dibujar línea() Dibuja una línea entre dos coordenadas
Funciones Descripciones
DibujarRect() Dibuja un rectángulo a partir de un punto cuando
se le proporciona un ancho y una altura.
RellenarRect() Funciona igual que DrawRect(), pero rellenando la
forma del rectángulo con píxeles negros (o blancos).
Con este conjunto de funciones, básicamente puedes dibujar cualquier cosa que quieras.
Métodos de texto
Se trata de un conjunto de funciones dedicadas a la tipografía en pantalla:
Funciones Descripciones
SeleccionarFuente() En primer lugar, esto elige la fuente que se utilizará en las próximas llamadas de
funciones.
[ 386 ]
www.itebooks.info
Machine Translated by Google
Capítulo 10.
Una característica importante que conviene conocer es que las funciones de impresión de Arduino se
pueden utilizar con la biblioteca gLCD; por ejemplo, GLCD.print() funciona bien. También hay un par de
funciones más disponibles que se pueden encontrar en el sitio web oficial.
Por último, te sugiero que pruebes el ejemplo llamado vida. Está basado en el Juego de la vida de
John Conway. Es un buen ejemplo de lo que puedes hacer e implementar una lógica útil y agradable.
Dibujar en gLCD es bueno, pero también podríamos usar un pequeño módulo que maneje VGA.
Las Arduino Shields son circuitos prefabricados que incluyen componentes y, a veces, también
procesadores. Agregan funciones a nuestra placa Arduino al manejar algunas tareas
específicas.
Aquí, Gameduino agregará capacidades de dibujo VGA a nuestro Arduino que no se pueden
hecho por si solo
Gameduino incluye un puerto VGA, un miniconector para el sonido y también incluye un FPGA Xilling
Spartan3A. El FPGA Xilling Spartan3A puede procesar datos gráficos más rápido que el propio Arduino.
Arduino puede controlar este controlador de hardware gráfico mediante la interfaz SPI.
[ 387 ]
www.itebooks.info
Machine Translated by Google
Las placas Arduino Shield se pueden conectar directamente a las placas Arduino. Consulta la siguiente
captura de pantalla:
[ 388 ]
www.itebooks.info
Machine Translated by Google
Capítulo 10.
No podemos describir todos los ejemplos en este libro, pero quiero orientarle en la dirección
correcta. En primer lugar, el sitio web oficial: http://excamera.com/sphinx/
juegoduino/.
Para su información, actualmente estoy diseñando una pieza de instalación de arte digital
basada en este escudo. Tengo la intención de describirla en mi propio sitio web http://julienbayle.net
Y también se proporcionarán todos los esquemas.
Resumen
En este primer capítulo avanzado, aprendimos un poco más sobre cómo manejar nuevos
conceptos concretos como almacenar datos en memorias no volátiles (EEPROM interna
y externa), usar receptores de módulos GPS, dibujar en LCD gráficos y usar una linda
Arduino Shield llamada Gameduino para agregarle nuevas funciones y potencia a nuestro
Arduino. Esto le permitió mostrar una señal VGA y también producir audio. También aprendimos
el uso de Arduino como un dispositivo muy portátil y móvil, autónomo desde el punto de vista
de la fuente de alimentación.
[ 389 ]
www.itebooks.info
Machine Translated by Google
www.itebooks.info
Machine Translated by Google
Redes
En este capítulo vamos a hablar sobre cómo vincular objetos y hacerlos hablar mediante la creación de
redes de comunicación. Vamos a aprender cómo podemos hacer que varios Arduinos y ordenadores se
comuniquen mediante enlaces y protocolos de red.
Después de definir qué es una red (en concreto, una red de datos), describiremos las formas de
utilizar enlaces Ethernet cableados entre Arduinos y ordenadores. Esto abrirá el mundo Arduino a
Internet. A continuación, descubriremos cómo crear comunicaciones Bluetooth.
Aprenderemos cómo utilizar Ethernet WiFi para conectar el Arduino a computadoras u otros
Arduinos sin estar atados por cables de red.
Por último, estudiaremos un par de ejemplos, desde aquel en el que enviaremos un mensaje al
servicio de microblogging Twitter hasta aquel en el que analizaremos y reaccionaremos a los datos recibidos
de Internet.
www.itebooks.info
Machine Translated by Google
Redes
Antes de profundizar en los detalles de las implementaciones de redes para placas Arduino, vamos a
describir un modelo llamado modelo OSI. Es una representación muy útil de lo que es una red de datos y lo
que implica.
Básicamente, se trata de un modelo basado en capas que describe qué características son necesarias
para diseñar sistemas de comunicación. A continuación, se muestra el modelo OSI con siete capas:
Modelo OSI que describe los requisitos del sistema de comunicación con siete capas de abstracción
Protocolos y comunicaciones
Un protocolo de comunicaciones es un conjunto de formatos de mensajes y reglas que proporcionan
una forma de comunicación entre al menos dos participantes. Dentro de cada capa, una o más entidades
implementan su funcionalidad y cada entidad interactúa directamente y únicamente con la capa que se
encuentra justo debajo de ella y, al mismo tiempo, proporciona funciones para que las utilice la capa que
se encuentra por encima de ella. Un protocolo permite que una entidad de un host interactúe con una
entidad correspondiente de la misma capa en otro host. Esto se puede representar mediante el siguiente
diagrama:
[ 392 ]
www.itebooks.info
Machine Translated by Google
Capítulo 11
protocolo
Solicitud Solicitud
protocolo
Presentación Presentación
protocolo
Sesión Sesión
protocolo
Transporte Transporte
protocolo
Red Red
protocolo
Enlace de datos Enlace de datos
protocolo
Físico Físico
ANFITRIÓN 1 ANFITRIÓN 2
El receptor debe hacer que los datos suban progresivamente por la pila de capas, pasando datos de
una capa a otra superior y dirigiéndolos a las entidades adecuadas en cada capa mediante
encabezados y pies de página añadidos previamente. Estos encabezados y pies de página se eliminan
a lo largo de todo el recorrido; esto se denomina desencapsulación.
[ 393 ]
www.itebooks.info
Machine Translated by Google
Redes
Al final del recorrido, la aplicación del receptor recibe sus datos y puede procesarlos. Todo este
proceso se puede representar mediante el siguiente diagrama:
Solicitud Solicitud
Presentación Presentación
Sesión Sesión
encapsulamiento
Red Red
Enlace físico
Físico Físico
ANFITRIÓN 1 ANFITRIÓN 2
También podemos representar estos procesos como se muestra en la siguiente figura. El pequeño
rectángulo gris es la carga de datos para la capa N+1.
N+1 N+1
norte norte
N1 N1
Agregar y eliminar encabezados y pies de página específicos según los protocolos utilizados
En cada nivel, dos hosts interactúan mediante un protocolo transmitido, al que llamamos Unidad de
Datos de Protocolo o PDU. También lo llamamos Unidad de Datos de Servicio o SDU, una unidad
específica de datos que se transmite desde una capa a una capa inferior y que aún no ha sido encapsulada.
Cada capa considera los datos recibidos como datos para ella y agrega/elimina encabezados y pies de
página según el protocolo utilizado.
[ 394 ]
www.itebooks.info
Machine Translated by Google
Capítulo 11
En esta capa se definen la disposición de los pines, los voltajes y la impedancia de línea, la sincronización de
la señal, los adaptadores de red o los adaptadores de bus host. Básicamente, esta capa realiza tres
funciones o servicios principales:
Podemos citar algunos estándares conocidos que se encuentran en esta capa física:
Ambos son responsables de transferir datos entre entidades de red y de detectar errores que puedan
ocurrir en la capa física, y eventualmente solucionarlos. Básicamente, esta capa proporciona estas
funciones/servicios:
• Enmarcado •
Direccionamiento físico •
Control de flujo
• Control de errores
• Control de acceso
• Control de acceso a los medios
• Ethernet
• WiFi
• APP
• I2C
[ 395 ]
www.itebooks.info
Machine Translated by Google
Redes
Hay que tener en cuenta que la segunda capa también es el dominio de las redes de área local con
solo direcciones físicas. Puede federarse mediante conmutadores LAN.
Por cierto, a menudo necesitamos segmentar redes y también comunicarnos más ampliamente, por lo que
necesitamos otro concepto de direccionamiento; esto introduce la capa de red.
Capa de red
Esta capa proporciona la manera de transferir secuencias de datos entre hosts que pueden estar en redes
diferentes. Proporciona las siguientes funciones/servicios:
• Enrutamiento
• Fragmentación y reensamblaje
El enrutamiento proporciona una manera de hacer que los hosts de una red diferente puedan comunicarse
mediante un sistema de direcciones de red.
En este nivel también se producen la fragmentación y el reensamblado, que permiten cortar los flujos de
datos en fragmentos y volver a ensamblar las partes después de la transmisión. Podemos citar algunos
estándares conocidos en esta capa:
• BOOTP (que proporciona una forma para que el host arranque a través de la red)
Los routers son generalmente los equipos donde se produce el enrutamiento. Están conectados
a más de una red y hacen que los datos pasen de una red a otra. También es el lugar donde podemos
colocar algunas listas de acceso para controlar el acceso en función de las direcciones IP.
Capa de transporte
Esta capa se encarga de la transferencia de datos entre usuarios finales, siendo el punto de unión entre las
capas de red y las capas de aplicación. Esta capa proporciona las siguientes funciones/servicios:
[ 396 ]
www.itebooks.info
Machine Translated by Google
Capítulo 11
• Orientado al Estado
• Orientado a la conexión
Esto significa que esta capa puede realizar un seguimiento de los segmentos emitidos y eventualmente retransmitirlos
en caso de una transmisión fallida previa.
• Protocolo universal
TCP está orientado a la conexión. Mantiene la comunicación confiable al verificar muchos elementos en cada
transmisión o en cada x segmentos transmitidos.
El protocolo UDP es más simple y sin estado. No proporciona un control del estado de la comunicación y, por lo
tanto, es más liviano. Es más adecuado para protocolos de consulta/respuesta orientados a transacciones, como
DNS (sistema de nombres de dominio) o NTP (protocolo de tiempo de red). Si hay algún error, como un segmento
que no se transmite bien, la capa superior debe encargarse de reenviar una solicitud, por ejemplo.
Capas de aplicación/host
Agrupé las tres capas más altas bajo los términos aplicación y host.
De hecho, no se consideran capas de red, pero son parte del modelo OSI porque a menudo son el propósito
final de cualquier comunicación de red.
También encontramos muchos estándares relacionados con el cifrado y la seguridad, como TLS (Transport
Layer Security). Nuestro firmware, un código de procesamiento en ejecución y Max 6 parches en ejecución se
encuentran en esta capa.
Si queremos que se comuniquen a través de una amplia variedad de redes, necesitamos una pila OSI, es decir,
necesitamos un protocolo de transporte y de red y un medio para transportar nuestros datos.
[ 397 ]
www.itebooks.info
Machine Translated by Google
Redes
Si nuestros ordenadores modernos tienen toda la pila de red lista para usar, tendremos que
incorporarla más adelante en el firmware de nuestro Arduino si queremos que puedan comunicarse con el
mundo. Esto es lo que vamos a hacer en el siguiente subcapítulo.
Este es el protocolo de red más utilizado en el mundo tanto para usuarios finales como para empresas.
Vamos a explicar un poco más sobre el sistema de direcciones IP, máscaras de subred y puertos de comunicación.
No voy a describir un curso completo de redes.
La dirección IP
Una dirección IP es una dirección numérica a la que hacen referencia todos los dispositivos que desean
comunicarse a través de una red IP. Actualmente, IP se utiliza en dos versiones: IPv4 e IPv6.
Estamos considerando IPv4 aquí porque actualmente es el único utilizado por los usuarios finales.
Las direcciones IPv4 están codificadas en 32 bits. Suelen escribirse como un conjunto legible por humanos de 4 bytes
separados por un punto. 192.168.1.222 es la dirección IP actual de mi computadora. Hay posibles direcciones
únicas y no todas son enrutables a través de Internet. Algunas están reservadas para uso privado. Algunas empresas
asignan direcciones enrutables a través de Internet. De hecho, no podemos utilizar ambas direcciones, ya que esto lo
gestionan organizaciones globales. Cada país tiene conjuntos de direcciones atribuidas para sus propios fines.
La subred
Una subred es una forma de segmentar nuestra red en varias redes más pequeñas. La configuración de red de
un dispositivo generalmente contiene la dirección, la máscara de subred y una puerta de enlace.
La dirección y la máscara de subred definen el alcance de la red. Es necesario saber si un transmisor puede comunicarse
directamente con un receptor. En efecto, si este último se encuentra dentro de la misma red, la comunicación puede
producirse directamente; si se encuentra en otra red, el transmisor debe enviar sus datos a la pasarela que los encaminará
al siguiente nodo correcto de la red para llegar, si es posible, al receptor.
La puerta de enlace conoce las redes a las que está conectada. Puede enrutar datos a través de diferentes redes y,
eventualmente, filtrar algunos datos de acuerdo con ciertas reglas.
Normalmente, la máscara de subred también se escribe como un conjunto de 4 bytes legible para humanos.
Obviamente hay un poco de notación, más difícil para aquellos que no están acostumbrados a manipular
los números.
[ 398 ]
www.itebooks.info
Machine Translated by Google
Capítulo 11
El puerto de comunicación
Un puerto de comunicación es algo definido y relacionado con la capa 4, la capa de transporte.
Imagina que quieres enviar un mensaje a un host para una aplicación en particular. El receptor debe estar
en modo de escucha para el mensaje que desea recibir.
Esto significa que debe abrir y reservar un socket específico para la conexión, es decir, un puerto de
comunicación. Por lo general, las aplicaciones abren puertos específicos para sus propios fines y, una vez
que una aplicación abre y reserva un puerto, no puede ser utilizado por otra aplicación mientras esté abierto
por la primera.
Esto proporciona un sistema potente para el intercambio de datos. De hecho, si queremos enviar datos a un
host para más de una aplicación, podemos dirigir nuestros mensajes específicamente a este host en un puerto
diferente para llegar a diferentes aplicaciones.
Por supuesto, era necesario definir estándares para las comunicaciones globales.
El puerto TCP 80 se utiliza para el protocolo HTTP relacionado con el intercambio de datos con la web.
servidores.
Si tienes curiosidad, puedes leer el siguiente archivo de texto oficial enorme que contiene todos los
puertos declarados y reservados y los servicios relacionados: http://www.ietf.org/
asignaciones/nombresdeservicionumerosdepuerto/nombresdeservicionumerosdepuerto.txt.
Se trata de convenciones. Alguien puede ejecutar fácilmente un servidor web en un puerto distinto del 80.
Luego, los clientes específicos de este servidor web tendrían que saber cuál es el puerto utilizado.
Por eso son útiles las convenciones y los estándares.
Las placas Arduino habituales no ofrecen la posibilidad de conectarse a Ethernet. Existe una placa llamada
Arduino Ethernet que ofrece funciones nativas de Ethernet y red. Por cierto, no ofrece ninguna función nativa
de USB.
[ 399 ]
www.itebooks.info
Machine Translated by Google
Redes
Vamos a utilizar el Arduino Ethernet Shield y un cable 100BASET con el Arduino UNO R3. Mantiene
las características USB y añade conectividad de red Ethernet y proporciona una buena forma de conectar
nuestro ordenador al Arduino con un cable mucho más largo que los USB.
Si buscas el módulo Ethernet Arduino, debes saber que se venden con o sin el módulo PoE.
[ 400 ]
www.itebooks.info
Machine Translated by Google
Capítulo 11
PoE significa Power over Ethernet y es una forma de suministrar energía a dispositivos a través
de conexiones Ethernet. Esto requiere dos partes:
Aquí, vamos a utilizar una placa Arduino conectada a nuestra computadora mediante Ethernet.
Pulsamos un botón que hace que Arduino envíe un mensaje por UDP al applet de Processing en
la computadora. El applet reacciona dibujando algo y envía un mensaje al Arduino, que enciende
su LED integrado.
Cableado básico
Aquí, estamos conectando un interruptor y utilizando la placa LED incorporada. Tenemos que conectar
nuestra placa Arduino a nuestra computadora mediante un cable Ethernet.
Este cableado es muy similar al proyecto MonoSwitch del Capítulo 5, excepto que aquí estamos
cableando el Arduino Ethernet Shield en lugar de la placa Arduino en sí.
[ 401 ]
www.itebooks.info
Machine Translated by Google
Redes
El diagrama del circuito correspondiente es el siguiente:
Fuerza
(primera vez) CCC
(REF) MISO
Arduino
Modulación por ancho de pulso (PWM)
DINERO
Ethernet Espartano
Modulación por ancho de pulso (PWM)
(D9)
(D8)
R2
(D7)
10k
Entrada/
salida
digital
Modulación por ancho de pulso (PWM)
(D6)
Entrada analógica
(A0) (D5)
(A1) Espartano
(A2) (D3)
(A3) (D2)
Tejas
(A4) (D1)
Recepción
(A5) (D0)
(tierra)
darle a nuestro Arduino la capacidad de comunicarse a través del cable Ethernet, y más generalmente
a través de una red Ethernet, tenemos que implementar los estándares requeridos en el firmware.
Existe una biblioteca llamada Ethernet que puede proporcionar una gran cantidad de funciones.
Como es habitual, tenemos que incluir esta biblioteca nativa. Puedes elegir hacerlo navegando a
Sketch | Importar biblioteca, que incluye casi todo lo que necesitas.
Sin embargo, a partir de la versión 0018 de Arduino, debido a la implementación de SPI y a que
el Arduino Ethernet Shield se comunica con la placa Arduino a través de SPI, tenemos que incluir algo
más. Ten cuidado con eso.
[ 402 ]
www.itebooks.info
Machine Translated by Google
Capítulo 11
// una dirección MAC, una dirección IP y un puerto para el Arduino byte mac[] = { 0xDE, 0xAD, 0xBE,
0xEF, 0xFE, 0xED };
configuración vacía() {
pinMode(ledPin, OUTPUT); // el pin del led está configurado como una salida pinMode(switchPin, INPUT); //
el pin del interruptor está configurado como una entrada
[ 403 ]
www.itebooks.info
Machine Translated by Google
Redes
Ethernet.begin(mac,ipArduino);
Udp.begin(PuertoArduino);
}
bucle vacío(){
lastDebounceTime = milisegundos();
}
switchState = leerInput;
}
} demás
{
// Si se presiona el interruptor, se envía un paquete a Processing Udp.beginPacket(ipComputer,
ComputerPort); Udp.write('Released'); Udp.endPacket();
retraso(10);
}
En el bloque de código anterior, primero incluimos la biblioteca Ethernet . Luego declaramos el conjunto
completo de variables relacionadas con el rebote del conmutador y el manejo de los LED. Después de
estas declaraciones, definimos algunas variables relacionadas con las características de la red.
[ 404 ]
www.itebooks.info
Machine Translated by Google
Capítulo 11
En primer lugar, tenemos que configurar la dirección MAC relacionada con nuestro propio shield.
Este identificador único suele estar indicado en una pegatina en el shield Ethernet. No olvides poner el tuyo
en el código.
Luego configuramos la dirección IP del Arduino. Podemos utilizar cualquier dirección siempre que
respete el esquema de direcciones IP y que sea accesible desde nuestro ordenador.
Es decir, en la misma red o en otra red, pero con un router entre ambas. Sin embargo, ten cuidado, ya
que la dirección IP que elijas tiene que ser única en un segmento de red local.
También elegimos un puerto UDP para nuestra comunicación. Usamos la misma definición con los
parámetros de red relacionados con nuestra computadora, el segundo grupo de participantes en la
comunicación.
Declaramos un buffer para almacenar los mensajes recibidos en cada momento. Observe la constante
UDP_TX_PACKET_MAX_SIZE. Está definida en la biblioteca Ethernet. Básicamente, está definida como
24 bytes para ahorrar memoria. Podríamos cambiar eso. Luego, instanciamos el objeto EthernetUDP
para recibir y enviar datagramas a través de UDP. El bloque de función setup() contiene instrucciones
para el conmutador y el LED, y luego para Ethernet en sí.
Iniciamos la comunicación Ethernet utilizando las direcciones MAC e IP. Luego abrimos y escuchamos
en el puerto UDP definido en la definición, que en nuestro caso es el 9999.
La función loop() parece un poco gruesa, pero podemos dividirla en 2 partes.
Luego verificamos si esta variable es igual a Claro u Oscuro y actuamos en consecuencia cambiando
Encender o apagar el LED en la placa Arduino.
En la segunda parte, podemos ver la misma estructura antirrebote que hemos visto en el Capítulo 5.
Al final de esta parte, verificamos si el interruptor está presionado o liberado y, dependiendo del
estado, enviamos un mensaje UDP a la computadora.
[ 405 ]
www.itebooks.info
Machine Translated by Google
Redes
importar hypermedia.net.*;
udp = new UDP( this, 10000 ); // crear socket UDP // esperar mensaje entrante
udp.listen( true );
}
void dibujar() {
mensajeActual += datos[i];
}
[ 406 ]
www.itebooks.info
Machine Translated by Google
Capítulo 11
Primero importamos la biblioteca. Luego definimos el objeto UDP y una variable String para el
mensaje recibido actualmente.
Aquí también tenemos que definir la dirección IP del participante remoto, el Arduino.
También definimos el puerto abierto y disponible para la comunicación en el lado de Arduino, aquí es
9999.
Por supuesto, esto tiene que coincidir con el definido en el firmware de Arduino. En la
función setup() , definimos algunos parámetros de dibujo y luego instanciamos el socket UDP
en el puerto UDP 10000 y lo configuramos en modo de escucha, esperando mensajes
entrantes.
Tan pronto como una de estas longitudes coincida, concatenamos cada byte en la variable
String currentMessage. Esto proporciona una manera sencilla de comparar el contenido con
cualquier otra cadena.
Acabamos de diseñar nuestro primer protocolo de comunicación básico utilizando Ethernet y UDP.
[ 407 ]
www.itebooks.info
Machine Translated by Google
Redes
Las clases Servidor y Cliente se pueden utilizar especialmente para este propósito, implementando
pruebas de funciones para comprobar si se ha abierto una conexión, si aún es válida, etc.
Comunicaciones Bluetooth
Bluetooth es un estándar de tecnología inalámbrica que permite intercambiar datos a corta distancia
mediante transmisiones de radio de longitud de onda corta en la banda de 2400 a 2480 MHz.
Permite crear PAN (Personal Area Networks) con el nivel de seguridad “correcto”. Se
implementa en varios tipos de dispositivos como computadoras, teléfonos inteligentes, sistemas
de sonido que pueden leer audio digital desde una fuente remota, etc.
En mi opinión, la mejor manera de proceder en muchos proyectos es mantener una placa de propósito
general como núcleo de nuestros diseños y agregar nuevas funciones agregando solo lo que
necesitamos como módulos externos. A continuación, vamos a utilizar el Arduino UNO R3 con un módulo
Bluetooth externo.
Vamos a realizar un pequeño proyecto utilizando Processing nuevamente. Haces clic en algún lugar sobre
el lienzo de Processing y la aplicación Processing envía un mensaje por Bluetooth al Arduino,
que reacciona encendiendo o apagando su LED integrado.
[ 408 ]
www.itebooks.info
Machine Translated by Google
Capítulo 11
CCV
REINICIAR UARTTX
3V3 5V Venir Bluetooth
UARTRX
Fuerza D13 Módulo
10 UARTRTS
Fugarse
Primera vez D12
Pio2 Errabundo UARTCTS
ARÉF
Modulación por ancho de pulso (PWM)
D11
Pio3 Redes
Modulación por ancho de pulso (PWM)
Yo ref. D10
Arduino (RN41)
PIO4 ESPIMOSI
Modulación por ancho de pulso (PWM)
D6
PIO10
Modulación por ancho de pulso (PWM)
D5
Entrada/
PIO11
salida
digital
A0 D4
Tierra
Entrada analógica
A1 D3
A2 D2
Tejas
A3 D1
A4 D0 Recepción
A5 LCC
Tierra
[ 409 ]
www.itebooks.info
Machine Translated by Google
Redes
Aquí estamos utilizando la comunicación de enlace serial básica entre el propio Arduino y el módulo
Bluetooth.
Suponemos que nuestro ordenador tiene capacidades Bluetooth y que éstas están activadas.
// Cosas LED
const int ledPin = 13; // pin del LED incorporado en la placa
configuración vacía() {
pinMode(ledPin, OUTPUT); // el pin led está configurado como salida
bucle vacío() {
si (Serial.available() > 0) {
entranteByte = Serial.read();
Básicamente, creamos una instancia de la comunicación serial con el módulo Bluetooth, luego verificamos
si hay bytes disponibles y los analizamos. Si hay un mensaje disponible y es igual a 1, encendemos el
LED; si es igual a 0, apagamos el LED.
configuración vacía() {
[ 410 ]
www.itebooks.info
Machine Translated by Google
Capítulo 11
tamaño(700, 700);
fondo(0); trazo(255);
color_fondo = 0;
color_fondo = 255;
} void draw()
{ fondo(bgcolor); trazo(fgcolor);
relleno(fgcolor); rect(100,
100, 500, 500);
vacío mousePressed() {
si (ratónX > 100 y ratónX < 600 y ratónY > 100 y ratónY < 600) {
}
}
bgcolor = 0; fgcolor
= 255; puerto.write('0');
Primero incluimos la biblioteca serial. En la función setup() , definimos algunos bits de dibujo, luego
imprimimos la lista de dispositivos seriales en el área de registro de procesamiento. Esto muestra
una lista y tenemos que encontrar el módulo Bluetooth correcto de nuestra computadora. En mi caso,
Este fue el tercero y lo usé para instanciar la comunicación serial en la última declaración de la función
setup() :
puerto = nuevo Serial(este, Serial.list()[2], 9600);
[ 411 ]
www.itebooks.info
Machine Translated by Google
Redes
Si pulsamos el botón del cuadrado se produce un feedback visual que nos indica que se ha recibido el
pedido, pero lo más importante es el digitalWrite('1')
función del curso.
De la misma manera, en cuanto soltamos el botón del ratón, se escribe un “0” en el módulo Bluetooth
del ordenador. Por supuesto, estos mensajes se envían al Arduino y este último enciende o apaga el LED.
Como hemos observado, no tenemos que utilizar una biblioteca en particular para este fin, ya que el módulo
en sí mismo es capaz de conectarse y enviar/recibir datos por sí solo solo si le enviamos datos en serie. De
hecho, la comunicación entre Arduino y el módulo es una comunicación en serie básica.
¿Qué es WiFi?
WiFi es un conjunto de protocolos de comunicación inalámbrica impulsados por estándares del IEEE.
802.11. Estos estándares describen las características de las redes de área local inalámbricas.
(WLAN).
Básicamente, varios hosts que tienen módulos WiFi pueden comunicarse usando sus pilas de IP sin
necesidad de cables. WiFi utiliza varios modos de red.
[ 412 ]
www.itebooks.info
Machine Translated by Google
Capítulo 11
Este punto de acceso y los hosts deben configurarse con el mismo Identificador de conjunto de
servicios (SSID), que es un nombre de red utilizado como referencia.
Este modo es interesante porque proporciona seguridad por el hecho de que cada host tiene que pasar
por el punto de acceso para poder acceder a la red global. Podemos configurar
algunas listas de acceso para controlar qué host puede conectarse y cuál no.
Anfitrión de WiFi 1
Anfitrión wifi 2
modo, cada host puede conectarse directamente con el otro sin necesidad de puntos de acceso. Es
muy útil para conectar rápidamente dos hosts con el fin de compartir documentos e intercambiar datos.
Anfitrión de WiFi 1
Anfitrión wifi 2
[ 413 ]
www.itebooks.info
Machine Translated by Google
Redes
Otros modos
También hay otros dos modos. El modo puente es una forma de vincular varios puntos de acceso.
Podemos imaginar un grupo de trabajo disperso en dos edificios; podríamos utilizar dos puntos
de acceso diferentes y conectarlos entre sí mediante un modo puente.
También existe un modo trivial llamado modo extensor de rango. Se utiliza para repetir la
señal y proporcionar una conexión entre dos hosts, dos puntos de acceso o un host y un punto
de acceso cuando estos están demasiado lejos.
[ 414 ]
www.itebooks.info
Machine Translated by Google
Capítulo 11
Una biblioteca nativa dedicada llamada WiFi Library nos proporciona todo lo que necesitamos para
conectar nuestra placa de forma inalámbrica a cualquier red. La referencia se encuentra en http://arduino.
cc/es/Referencia/WiFi.
Este protector está disponible en muchos distribuidores, así como en la tienda Arduino: http://
store.arduino.cc/ww/index.php?main_page=product_
información&cPath=11_5&products_id=237.
El punto de aceptación debe proporcionar un servidor DHCP; este último entregará una dirección IP a
nuestro sistema basado en Arduino.
#include <WiFi.h>
configuración vacía() {
//Inicialice el serial y espere a que se abra el puerto:
Serie.begin(9600);
mientras(verdadero)
retraso(30) ;
}
[ 415 ]
www.itebooks.info
Machine Translated by Google
Redes
retraso(10000);
}
bucle vacío() {
// comprobar la conexión de red una vez cada 10 segundos: delay(10000);
printCurrentNet();
WiFi.macAddress(mac);
Serial.print("Dirección MAC: ");
Serial.print(mac[5],HEX); Serial.print(":);
Serial.print(mac[4],HEX);
Serial.print(":); Serial.print(mac[3],HEX);
Serial.print(":);
Serial.print(mac[2],HEX); Serial.print(":);
Serial.print(mac[1],HEX);
Serial.print(":); Serial.println(mac[0],HEX);
[ 416 ]
www.itebooks.info
Machine Translated by Google
Capítulo 11
vacío printCurrentNet() {
// imprime el SSID de la red a la que estás conectado: Serial.print("SSID: ");
Serial.println(WiFi.SSID());
// imprime la dirección MAC del enrutador al que estás conectado: byte bssid[6];
WiFi.BSSID(bssid);
Serial.print("BSSID: ");
Serial.print(bssid[5],HEX); Serial.print(":);
Serial.print(bssid[4],HEX); Serial.print(":);
Serial.print(bssid[3],HEX);
Serial.print(":); Serial.print(bssid[2],HEX);
Serial.print(":);
Serial.print(bssid[1],HEX); Serial.print(":);
Serial.println(bssid[0],HEX);
Primero incluimos la librería WiFi . Luego, configuramos el nombre de nuestra red, el SSID.
Tenga cuidado de cambiarlo a su propio SSID.
Si este último devuelve el valor WL_NO_SHIELD (que es una constante definida dentro
de la biblioteca WiFi), significa que no hay protección. En ese caso, se ejecuta un bucle
infinito con una sentencia while(true) sin la palabra clave break dentro.
[ 417 ]
www.itebooks.info
Machine Translated by Google
Redes
Si devuelve un valor distinto a WL_CONNECTED, entonces imprimimos una sentencia para informar que está
intentando conectarse. Entonces, WiFi.begin() intenta conectarse. Esta es una estructura habitual que
proporciona una forma de intentar conectarse mientras no está conectado, de forma constante y cada 10 s,
considerando que se llama a la función delay() .
Luego, si se produce la conexión, el estado pasa a ser WL_CONNECTED, salimos del bucle while y
continuamos.
También hay algo impreso en serie que dice que la placa ha alcanzado el estado de conexión.
También llamamos a dos funciones. Estas funciones imprimen en serie muchos elementos relacionados
con los parámetros y el estado de la red. Te dejaré descubrir cada una de ellas utilizando la referencia
http://arduino.cc/en/Reference/WiFi citada anteriormente.
Después de esta conexión, podemos empezar a intercambiar datos. Como probablemente sepas, utilizar una
red WiFi sin seguridad puede acarrear problemas. De hecho, es muy fácil capturar paquetes de una red
WiFi sin protección.
Reemplazamos la llamada a WiFi.begin(), que tenía un solo argumento, por dos nuevos argumentos
relacionados con el cifrado WEP. Esta es la única diferencia.
Por muchas razones que no analizaremos aquí, WEP se considera demasiado débil en términos
de seguridad, por lo que la mayoría de personas y organizaciones han optado por la alternativa
WPA2, más segura.
En ambos casos que acabamos de comprobar, solo tuvimos que pasar algunos argumentos adicionales con
WiFi.begin() para asegurar las cosas un poco más.
[ 418 ]
www.itebooks.info
Machine Translated by Google
Capítulo 11
En este ejemplo, Arduino actúa como un servidor web después de haber sido conectado a una WEP.
o red WiFi WPA.
#include <WiFi.h>
servidor WiFiServer(80);
configuración vacía() {
//Inicialice el serial y espere a que se abra el puerto:
Serial.begin(9600); mientras (!
Serial) {
; // Esperar a que se conecte el puerto serial. Necesario solo para Leonardo
}
mientras(verdadero);
}
} servidor.begin();
// Ahora estás conectado, así que imprime el estado:
imprimirEstadoWifi();
}
[ 419 ]
www.itebooks.info
Machine Translated by Google
Redes
void loop() { //
escucha a los clientes entrantes WiFiClient client
= server.available(); if (client) { Serial.println("new client"); // una
solicitud http termina
con una línea en blanco boolean
currentLineIsBlank = true; while (client.connected()) { if
(client.available()) { char c = client.read(); Serial.write(c); //
si has llegado al final de la línea (has recibido
un carácter de nueva línea) y la línea
está en blanco, la solicitud http ha
terminó,
// para que puedas enviar una respuesta
si (c == '\n' && currentLineIsBlank) {
// envía un encabezado de respuesta http estándar
client.println("HTTP/1.1 200 OK"); client.println("Content
Type: text/html"); client.println("Connnection: close"); client.println();
client.println("<!DOCTYPE HTML>"); client.println("<html>"); //
agrega una etiqueta de
actualización meta, para que el navegador la extraiga
nuevamente cada
5 segundos:
cliente.println("<meta httpequiv=\"actualizar\"
contenido="5">");
// genera el valor de cada pin de entrada analógica para (int
analogChannel = 0; analogChannel < 6;
canalanalogico++) {
int sensorReading = analogRead(analogChannel); cliente.print("entrada
analógica "); cliente.print(analogChannel);
cliente.print("es "); cliente.print(sensorReading);
cliente.println("<br />");
} cliente.println("</html>");
romper;
} if (c == '\n') { // estás
iniciando una nueva línea currentLineIsBlank =
true;
} de lo contrario si (c != '\r') {
[ 420 ]
www.itebooks.info
Machine Translated by Google
Capítulo 11
}
}
} // darle tiempo al navegador web para recibir los datos delay(1); // cerrar
la conexión:
client.stop(); Serial.println("cliente
desconectado");
}
}
vacío imprimirWifiStatus() {
// imprime el SSID de la red a la que estás conectado: Serial.print("SSID: ");
Serial.println(WiFi.SSID());
Explicamos sólo la parte nueva del código, no las declaraciones de conexión automática y cifrado,
porque eso ya lo hicimos antes.
En la función loop() , verificamos si hay un cliente entrante en nuestro servidor web integrado en Arduino.
Esto se hace con WiFiClient client = server.available();
[ 421 ]
www.itebooks.info
Machine Translated by Google
Redes
Luego, tenemos una condición en la instancia del cliente. Si no hay ningún cliente, básicamente no
hacemos nada y ejecutamos el bucle nuevamente hasta que tengamos un cliente.
Tan pronto como tenemos uno, lo imprimimos en serial para dar retroalimentación. Luego, verificamos
si el cliente está efectivamente conectado y si hay datos en el buffer de lectura. Luego imprimimos
estos datos si están disponibles y respondemos al cliente enviando el encabezado de respuesta HTTP
estándar. Esto se hace básicamente imprimiendo bytes en la propia instancia del cliente.
El código incluye algunas características dinámicas y envía algunos valores leídos en la propia placa, como
el valor que proviene del ADC de cada entrada analógica.
Podríamos intentar conectar algunos sensores y proporcionar valores de cada uno de ellos a través de una
página web gestionada directamente por el propio Arduino. Os dejo que comprobéis la otra parte del código.
Ésta trata de mensajes HTTP estándar.
Vamos a utilizar el mismo circuito que usamos en la sección Cableado de Arduino a Ethernet cableado,
excepto que aquí estamos usando el Arduino MEGA relacionado con algunas restricciones de memoria
con una placa más pequeña.
Por ejemplo, podríamos definir una API en nuestro firmware Arduino que explicaría cómo y qué enviar para
que el LED de la placa se encienda y apague.
No describiremos todo el firmware, pero sí facilitaremos al mundo un documento básico que explique con
precisión el formato y los datos a enviar desde Internet, por ejemplo, para utilizarlo de forma remota. Eso
sería una API.
API de Twitter
Twitter, al igual que muchos otros sistemas relacionados con redes sociales en Internet, ofrece una API.
Otros programadores pueden utilizarla para obtener y enviar datos. Todas las especificaciones de
datos relacionadas con la API de Twitter están disponibles en https://dev.twitter.com.
[ 422 ]
www.itebooks.info
Machine Translated by Google
Capítulo 11
Para poder utilizar la API, tenemos que crear una aplicación en el sitio web para desarrolladores de
Twitter. Hay que configurar algunos parámetros de seguridad especiales y acordar algunas reglas
de uso que respeten la tasa de solicitudes de datos y otras especificaciones técnicas.
Esto nos proporcionará cierta información de credenciales, en particular un token de acceso y un token
secreto. Se trata de cadenas de caracteres que se deben utilizar siguiendo algunos protocolos para
poder acceder a la API.
Esta librería debe utilizarse con una placa con más memoria de la habitual. Arduino MEGA la ejecuta
perfectamente.
Básicamente, se trata de una forma de permitir que una aplicación de terceros obtenga acceso limitado a un
servicio HTTP. Al enviar una cadena de caracteres específica, podemos otorgar acceso a un host y hacer
que se comunique con la API.
Esto es lo que vamos a hacer juntos como un buen ejemplo que podría reutilizar para otras API en la Web.
Debes tener a mano el token de acceso y el secreto del token de acceso, ya que los incluiremos en nuestro
firmware.
[ 423 ]
www.itebooks.info
Machine Translated by Google
Redes
#incluir <SPI.h>
#include <Ethernet.h>
#incluir <sha1.h>
#include <Tiempo.h>
#include <EEPROM.h>
#incluir <Twitter.h>
// Cambiar
constante int switchPin = 2; int switchState
= 0; int lastSwitchState = BAJO;
largo lastDebounceTime = 0;
largo debounceDelay = 50;
// Dirección IP de Twitter
Dirección IP twitter_ip(199, 59, 149, 232);
uint16_t puerto_twitter = 80;
búfer de caracteres[512];
Twitter twitter(buffer, tamañode(buffer));
configuración vacía() {
Serie.begin(9600);
Serial.println("Demostración de Twitter de Arduino");
[ 424 ]
www.itebooks.info
Machine Translated by Google
Capítulo 11
retraso(500);
}
void loop() { if
(twitter.is_ready()) // si la conexión de Twitter está bien {
lastDebounceTime = milisegundos();
}
switchState = leerInput;
}
carácter msg[32];
[ 425 ]
www.itebooks.info
Machine Translated by Google
Redes
last_tweet = ahora;
si (twitter.post_status(msg))
Serial.println("Estado actualizado");
demás
Serial.println("La actualización falló");
Vamos a explicar las cosas aquí. Tenga en cuenta que este es un código que incluye muchas cosas
que ya descubrimos y aprendimos juntos:
Hora para funciones específicas de hora y fecha utilizadas por la biblioteca de Twitter
• EEPROM para almacenar credenciales en la EEPROM de la placa
Configuramos los parámetros de red. Ten en cuenta que aquí debes poner tus propios elementos,
teniendo en cuenta tu red y el escudo Ethernet. Luego, definimos la dirección IP de Twitter.
[ 426 ]
www.itebooks.info
Machine Translated by Google
Capítulo 11
Definimos la constante TWEET_DELTA para su posterior uso, en relación con el uso de la API de Twitter
que nos prohíbe enviar demasiados tweets a la vez. Luego, almacenamos nuestras credenciales. Utilice las
suyas, relacionadas con la aplicación que creó en el sitio web de Twitter para nuestro propósito. Por último,
creamos el objeto twitter.
En la función setup() iniciamos la conexión serial para que nos envíen algún feedback. Configuramos
el pin digital del switch e iniciamos la conexión Ethernet. Luego, tenemos toda la magia de Twitter.
Primero elegimos el punto de entrada definido por la propia documentación de la API de Twitter. Tenemos
que poner aquí también nuestro token de acceso y el secreto del token. Luego, tenemos una condición
de compilación: #if TOKEN_IN_MEMORY.
Para poder almacenar las credenciales en la EEPROM de la placa, primero tenemos que poner el valor 0.
Lo compilamos y lo ejecutamos en la placa. El firmware se ejecuta y escribe los tokens en la memoria.
Luego, cambiamos el valor a 1 (porque los tokens ahora están en la memoria) y lo compilamos y lo
ejecutamos en la placa. A partir de ahora, el firmware leerá las credenciales de la EEPROM.
Primero probamos si la conexión de Twitter a la API es correcta. Si es así, almacenamos la hora y la hora del
último tweet en un valor inicial. Leemos el valor de rebote de la entrada digital.
Por último, almacenamos un mensaje en la matriz de caracteres msg y lo tuiteamos mediante la función
twitter.post_status() . Mientras la usamos, también probamos lo que devuelve. Si devuelve 1, significa que
se produjo el tuit. Esto proporciona esta información al usuario a través del monitor serial.
Todos los proveedores de API funcionan de la misma manera. En este caso, nos resultó muy útil la biblioteca
de Twitter que utilizamos, pero también existen otras bibliotecas para otros servicios en Internet.
Además, cada servicio proporciona la documentación completa para utilizar su API. Los recursos de la API
de Facebook están disponibles aquí: https://developers.facebook.com/. Los recursos de la API de Google+
están disponibles aquí: https://developers.google.com/+/api/.
Los recursos de la API de Instagram están disponibles aquí: http://instagram.com/developer.
Y podríamos encontrar muchos otros.
[ 427 ]
www.itebooks.info
Machine Translated by Google
Redes
Resumen
En este capítulo aprendimos a ampliar el área de comunicación de nuestras placas Arduino.
Estábamos acostumbrados a realizar conexiones muy locales; ahora podemos conectar nuestra
placa a Internet y potencialmente comunicarnos con todo el planeta.
Describimos conexiones Ethernet cableadas, WiFi, Bluetooth y cómo utilizar la API de Twitter.
Podríamos haber descrito la placa Xbee, que también utiliza frecuencias de radio, pero
preferí describir las cuestiones relacionadas con IP porque considero que son la forma más
segura de transmitir datos. Por supuesto, la solución Xbee Shield también es muy buena y la
he utilizado en muchos proyectos.
[ 428 ]
www.itebooks.info
Machine Translated by Google
Jugando con
Marco de trabajo Max 6
En este capítulo nos enseñaremos algunos consejos y técnicas que podemos utilizar con el
framework de programación gráfica Max 6 y las placas Arduino.
Presentamos este increíble marco en el Capítulo 6, Sense the World – Feeling with Analog
Inputs, mientras aprendimos sobre el manejo de entradas analógicas de Arduino. Leer el
capítulo anterior es un requisito para comprender y aprender mejor las técnicas
desarrolladas en este capítulo. Incluso te sugiero que leas nuevamente la parte de introducción de Max 6.
En este capítulo, aprenderemos cómo enviar datos a Arduino desde Max 6. También
describiremos cómo podemos manejar y analizar los datos que recibimos de Arduino.
Arduino añade muchas funciones a los programas de Max 6. De hecho, ofrece una forma
de conectar Max 6 al mundo físico real. A través de dos ejemplos, vamos a entender una
forma agradable de trabajar con Arduino, la computadora y el marco de programación más
avanzado que existe.
Vamos.
www.itebooks.info
Machine Translated by Google
Vamos a utilizar nuevamente nuestra conexión USB básica entre Arduino y nuestra
computadora para intercambiar datos aquí.
El objeto [serial]
Debemos recordar las características del objeto [serial] . Proporciona una forma de
enviar y recibir datos desde un puerto serial. Para ello, existe un parche básico que incluye
bloques básicos. Lo iremos mejorando progresivamente a lo largo de este subcapítulo.
El objeto [serial] es como un buffer que tenemos que sondear tanto como necesitemos. Si se
envían mensajes desde Arduino al puerto serial de la computadora, tenemos que
pedirle al objeto [serial] que los extraiga. Vamos a hacer esto en las siguientes páginas.
Por supuesto, este capítulo también es un pretexto para darte algunos de mis consejos y
trucos para Max 6. Tómalos y úsalos; te harán la vida más fácil con los parches.
[ 430 ]
www.itebooks.info
Machine Translated by Google
Capítulo 12
Tenemos que recordar el objeto [loadbang] . Dispara una explosión, es decir, una (impresión)
mensaje al siguiente objeto tan pronto como se carga el parche. Es útil configurar las cosas e
inicializar algunos valores como podríamos hacerlo dentro de nuestro bloque setup() en nuestro
Firmware de la placa Arduino.
Aquí, lo hacemos para llenar el menú del selector de puerto serie. Cuando el [serie]
El objeto recibe el mensaje (imprimir) , muestra una lista de todos los puertos seriales disponibles en la
computadora desde su salida derecha, precedida por la palabra puerto. Luego procesamos el
resultado utilizando [route port] que solo analiza listas precedidas por la palabra puerto.
El objeto [t] es una abreviatura de [trigger]. Este objeto envía el mensaje entrante a muchas
ubicaciones, como está escrito en la documentación, si se asume el uso de los siguientes argumentos:
• b significa explosión
• f significa número flotante
• i significa entero
•
s significa símbolo
• l significa lista (es decir, al menos un elemento)
También podemos usar constantes como argumentos y tan pronto como se reciba la entrada, la
constante se enviará tal como está.
Por último, el [trigger] envía mensajes de salida en un orden particular: desde el extremo derecho
salida hacia la más a la izquierda.
Aquí tomamos la lista de puertos seriales que se reciben desde el objeto [route] ; enviamos el
mensaje de borrado al objeto [umenu] (el menú de lista del lado izquierdo) para borrar toda la lista.
Luego, la lista de puertos seriales se envía como una lista (debido al primer argumento) a [iter]. [iter]
divide una lista en sus elementos individuales.
[ 431 ]
www.itebooks.info
Machine Translated by Google
Esto significa que el proceso global envía mensajes al objeto [umenu] similares a los siguientes:
• adjuntar xxxxxx
• añadir aaaaaa
Aquí xxxxxx y yyyyyy son los puertos seriales que están disponibles.
Esto crea el menú de selección de puerto serie al completar la lista con los nombres de los puertos
serie. Esta es una de las formas típicas de crear algunos ayudantes, en este caso el menú, en nuestros
parches utilizando elementos de la interfaz de usuario.
Tan pronto como cargues este parche, el menú se llenará y solo tendrás que elegir el puerto serial
correcto que quieras usar. Tan pronto como selecciones un elemento en el menú, el número del
elemento en la lista se enviará a su salida más a la izquierda. Anteponemos este número por puerto y lo
enviamos a [serial], configurándolo en el puerto serial de la derecha.
Sistema de votación
Uno de los objetos más utilizados en Max 6 para enviar explosiones regulares con el fin de activar
cosas o contar el tiempo es [metro].
Tenemos que usar al menos un argumento: este es el tiempo entre dos explosiones.
en milisegundos.
Si queremos enviar datos de forma continua desde Arduino y procesarlos con Max 6, es necesario activar
el objeto [metro] . Entonces enviamos un bang regular y podemos tener una actualización de todas las
entradas leídas por Arduino dentro de nuestro parche Max 6.
Elegir un valor entre 15 ms y 150 ms es bueno, pero depende de sus propias necesidades.
Veamos ahora cómo podemos leer, analizar y seleccionar datos útiles que recibimos de Arduino.
[ 432 ]
www.itebooks.info
Machine Translated by Google
Capítulo 12
configuración vacía()
{
Serial.begin(9600);
pinMode(13,ENTRADA);
}
bucle vacío() {
// Si se recibe una 'r' entonces lea todos los pines si (Serial.read() == 'r') {
// Leer y enviar valores de los pines digitales 213 para (int pin= 2;
pin<=13; pin++){ val = digitalRead(pin); sendValue
(val);
Serial.println();// Retorno de carro para marcar el final del flujo de datos. delay(5); // evitar la
sobrecarga del búfer
}
}
[ 433 ]
www.itebooks.info
Machine Translated by Google
Ahora, mejoremos nuestro parche Max 6 para manejar este paquete de datos que se reciben desde
Arduino.
[ 434 ]
www.itebooks.info
Machine Translated by Google
Capítulo 12
Agregamos un par de cosas más a los bloques de construcción básicos en el parche anterior.
Esta estructura proporciona una manera de enviar el carácter r al objeto [serial] , es decir, a
Arduino, cada vez que se activa el metro. Como ya vemos en el firmware, activa
Arduino para leer todas sus entradas, luego empaquetar los datos y luego enviar el paquete al
puerto serial para el parche Max 6.
Para resumir lo que el metro dispara en cada explosión, podemos escribir esta secuencia:
1. Envía el carácter r a Arduino.
2. Envíe un retorno de carro a Arduino.
3. Golpee el objeto [serie] .
Esto hace que Arduino envíe todos sus datos al parche Max.
Aquí no queremos considerar un nuevo salto de línea (código ASCII 10). Por eso lo ponemos
como argumento, pero no hacemos nada si es el que se ha seleccionado. Es un buen truco
para evitar que este mensaje active algo e incluso que no aparezca en la salida correcta de
[select].
Aquí, enviamos todos los mensajes recibidos de Arduino, excepto 10 o 13, al objeto [zl
group 78] . Este último es una lista poderosa para procesar muchas características. El
argumento group facilita la agrupación de los mensajes recibidos en una lista. El último
argumento es para asegurarnos de que no tengamos demasiados elementos en la lista.
Tan pronto como [zl group] se activa con un bang o la longitud de la lista alcanza el valor
del argumento length, saca toda la lista desde su salida izquierda.
[ 435 ]
www.itebooks.info
Machine Translated by Google
Aquí, "acumulamos" todos los mensajes recibidos desde Arduino, y tan pronto como se envía un
retorno de carro (recuerde que estamos haciendo eso en las últimas filas del bucle()
bloque en el firmware), se envía un sonido y todos los datos se pasan al siguiente objeto.
Actualmente tenemos una gran lista con todos los datos dentro de ella, con cada valor separado
del otro por un carácter de espacio (el famoso código ASCII 32 que agregamos en la última función del
firmware).
Esta lista se pasa al objeto [itoa] . itoa significa conversión de enteros a ASCII. Este objeto convierte
enteros a caracteres ASCII.
Finalmente, después de este objeto [fromsymbol] tenemos nuestra gran lista de valores separados por
espacios y totalmente legibles.
Luego tenemos que descomprimir la lista. [unpack] es un objeto muy útil que proporciona una forma
de cortar una lista de mensajes en mensajes individuales. Podemos observar aquí que implementamos
exactamente el proceso opuesto en el firmware de Arduino mientras comprimíamos cada valor en un
mensaje grande.
[unpack] toma tantos argumentos como queramos. Requiere saber la cantidad exacta de elementos en la
lista que se le envía. Aquí enviamos 12 valores desde Arduino, por lo que ponemos 12 argumentos i . i
representa un entero. Si enviamos un flotante, [unpack] lo convertiría en un entero. Es importante
saber esto. Demasiados estudiantes se quedan atascados con la resolución de este problema en
particular.
Aquí solo estamos jugando con números enteros. De hecho, el ADC de Arduino proporciona datos de
0 a 1023 y la entrada digital proporciona solo 0 o 1.
Adjuntamos un cuadro numérico a cada salida del objeto [unpack] para mostrar cada valor.
Luego usamos un objeto [change] . Este último es un objeto muy útil. Cuando recibe un valor, lo pasa a su
salida solo si es diferente del valor recibido anteriormente. Proporciona una forma eficaz de evitar
enviar el mismo valor cada vez que no es necesario.
Aquí, elegí el argumento 1 porque este no es un valor enviado por el firmware de Arduino y estoy
seguro de que se analizará el primer elemento enviado.
Ahora tenemos todos nuestros valores disponibles. Podemos utilizarlos para diferentes trabajos.
Pero propongo utilizar un método más inteligente y esto también introducirá un nuevo concepto.
[ 436 ]
www.itebooks.info
Machine Translated by Google
Capítulo 12
Truco inalámbrico
A menudo tenemos que utilizar algunos datos en nuestros parches. Los mismos datos deben alimentar más
de un objeto.
Una buena forma de evitar parches desordenados con muchos cables y alambres por todos lados es
usar los objetos [send] y [receive] . Estos objetos se pueden abreviar con [s]
y [r], y generan buses de comunicación y proporcionan una forma inalámbrica de comunicarse dentro
de nuestros parches.
El primero es un cable básico. En cuanto enviamos datos desde el cuadro numérico superior, se
transmiten al que está al otro lado del cable.
El segundo genera un bus de datos llamado busA. Tan pronto como envíes datos a [send busA], cada
objeto [receive busA] en tu parche mostrará esos datos.
El tercer ejemplo es igual que el segundo, pero genera otro bus llamado busB.
A menudo utilizo esto para mi reloj maestro, por ejemplo. Tengo un solo reloj maestro que hace sonar
un reloj para [enviar reloj maestro], y donde sea que necesite tener ese reloj, utilizo [recibir reloj maestro]
y me proporciona los datos que necesito.
[ 437 ]
www.itebooks.info
Machine Translated by Google
Si revisas el parche global, puedes ver que distribuimos datos a las estructuras en la parte inferior del
parche. Pero estas estructuras también podrían estar ubicadas en otros lugares. De hecho, una de las
fortalezas de cualquier marco de programación visual como Max 6 es el hecho de que puedes
organizar visualmente cada parte de tu código exactamente como quieras en tu parcheador. Y
hazlo tanto como puedas. Esto te ayudará a brindar soporte y mantenimiento a tu parche durante
los largos meses de desarrollo.
Consulta la captura de pantalla anterior. Podría haber vinculado el objeto [r A1] en la esquina
superior izquierda al objeto [p process03] directamente. Pero tal vez esto sea más legible si mantengo
las cadenas de procesos separadas. Suelo trabajar de esta manera con Max 6.
Este es uno de los múltiples trucos que enseño en mi curso de Max 6. Y, por supuesto,
introduje el objeto [p] , que es la abreviatura de [patcher] .
Revisemos un par de consejos antes de continuar con algunos buenos ejemplos que involucran Max 6 y
Arduino.
Encapsulación y subparcheo
Cuando abres Max 6 y vas a Archivo | Nuevo parcheador, se abre un parcheador en blanco. Este
último, si recuerdas, es el lugar donde colocas todos los objetos. Hay otra característica interesante
llamada subpatching. Con esta característica, puedes crear nuevos parcheadores dentro de
parcheadores e incrustar parcheadores dentro de parcheadores también.
[ 438 ]
www.itebooks.info
Machine Translated by Google
Capítulo 12
Hay cuatro nuevos objetos que reemplazan todas las estructuras que diseñamos antes.
Estos objetos son subparches. Si haces doble clic en ellos en el modo de bloqueo de parches
o si pulsas la tecla de comando (o Ctrl para Windows), haz doble clic en ellos en el modo de
edición de parches y los abrirás. Veamos qué hay dentro de ellos.
[ 439 ]
www.itebooks.info
Machine Translated by Google
El subpatcher [solicitante] contiene la misma arquitectura que diseñamos antes, pero puedes ver
los objetos marrones 1 y 2 y otro objeto azul 1. Estos son entradas y salidas. De hecho, son
necesarios si quieres que tu subpatcher pueda comunicarse con el patcher que lo contiene.
Por supuesto, también podríamos usar los objetos [enviar] y [recibir] para este propósito. Vamos a
verlo en las siguientes páginas.
Y ahora, comprueba el parche raíz que contiene este subparche. Invierte automáticamente las
entradas, manteniendo la relevancia de todo.
[ 440 ]
www.itebooks.info
Machine Translated by Google
Capítulo 12
El subparcheador [p portHandler]
El subparcheador [p dataHandler]
El subpatchador [p dataDispatcher]
[ 441 ]
www.itebooks.info
Machine Translated by Google
En la última figura, podemos ver solo una entrada y ninguna salida. De hecho, simplemente
encapsulamos el sistema de distribución de datos global dentro del subpatcher. Y este último genera sus
buses de datos con objetos [send] . Este es un ejemplo en el que no necesitamos e incluso no queremos
usar salidas. Usar salidas sería un lío porque tendríamos que vincular cada elemento que solicita este o
aquel valor de Arduino con muchos cables.
Para crear un subpatcher, solo tienes que escribir n para crear un nuevo objeto,
escribir p, un espacio y el nombre de tu subpatcher.
Mientras diseñaba estos ejemplos, utilicé algo que funciona más rápido que crear un
subpatch, copiar y pegar la estructura en el interior, quitar la estructura del exterior y
agregar entradas y salidas.
Tienes que seleccionar la parte del parche que quieres encapsular dentro de un
subpaquete, luego hacer clic en Encapsular y listo. Acabas de crear un subpaquete
que incluye tus estructuras conectadas a entradas y salidas en el orden correcto.
[ 442 ]
www.itebooks.info
Machine Translated by Google
Capítulo 12
Podemos imaginar que tenemos que diseñar un parche completo con mucha magia y trucos dentro de él. Este
es una unidad de procesamiento, y tan pronto como sabemos qué hace, después de haberlo terminado, no
queremos saber cómo lo hace , sino solo usarlo.
Esto proporciona un buen nivel de abstracción al mantener algunas unidades de procesamiento cerradas dentro de
cajas y sin alterar el parche principal.
Puede copiar y pegar los subpatchers. Esta es una forma eficaz de duplicar rápidamente las unidades de proceso si
es necesario. Pero cada subpatcher es totalmente independiente de los demás.
Esto significa que si necesitas modificar uno porque quieres actualizarlo, tendrás que hacerlo individualmente en
cada subparcheador de tu parche.
Permítanme presentarles el último concepto puro de Max 6, ahora llamado abstracciones , antes de continuar con
Arduino.
Abstracciones y reutilización
Cualquier parche creado y guardado puede ser utilizado como un nuevo objeto en otro parche. Podemos hacer
esto creando un nuevo objeto escribiendo n en un parcheador; luego solo tenemos que escribir el nombre de
nuestro parche creado y guardado anteriormente.
Para poder llamar a un parche como abstracción en un parcheador, el parche debe estar en la ruta de Max 6 para
que este lo pueda encontrar. Puede comprobar la ruta que conoce Max 6 yendo a Opciones | Preferencias de
archivo. Por lo general, si coloca el parche principal en una carpeta y los otros parches que desea utilizar como
abstracciones en esa misma carpeta, Max 6 los encuentra.
De hecho, imagina que necesitas y tienes muchas estructuras de parches pequeños (o grandes) que usas todos
los días, en todo momento y en casi todos los proyectos. Puedes colocarlas en una carpeta específica en tu disco
incluida en la ruta de Max 6 y luego puedes llamarlas (decimos crear una instancia) en cada parche que estés
diseñando.
Dado que cada parche que lo utiliza solo tiene una referencia al parche que fue instanciado, solo necesita mejorar
su abstracción; cada vez que carga un parche que lo utiliza, el parche tendrá abstracciones actualizadas cargadas
en su interior.
Por supuesto, si cambias totalmente la abstracción para que se ajuste a un proyecto o parche específico, tendrás
algunos problemas al utilizarla con otros parches. Debes tener cuidado de mantener una documentación,
incluso breve, de tus abstracciones.
[ 443 ]
www.itebooks.info
Machine Translated by Google
Max puede escuchar fácilmente sonidos y convertirlos del dominio analógico al digital.
Vamos a construir un pequeño visualizador de nivel de sonido usando Arduino, algunos LED,
y Max 6.
El circuito
Vamos a utilizar el mismo circuito que diseñamos en el Capítulo 8, Diseño de retroalimentaciones
de salida visual, mientras multiplexamos LED con una conexión en cadena de registros de desplazamiento
del tipo 595.
[ 444 ]
www.itebooks.info
Machine Translated by Google
Capítulo 12
Arduino1
3V3 5V Venir
Fuerza
D13
ARÉF D11
Modulación por ancho de pulso (PWM)
LED09 R1
D9
Modulación por ancho de pulso (PWM)
LED10 D8
R2 74HC595
U1 D7
LED11 R3 1 16 D6
Modulación por ancho de pulso (PWM)
Q1 Vcc
Entrada/
salida
digital
LED12 2 15 D5
Modulación por ancho de pulso (PWM)
R4 Q2 Q0
Entrada analógica
3 14 A0 D4
LED13 T3 DS
R5
_ A1 D3
Modulación por ancho de pulso (PWM)
4 13
Q4 ERES
A2 D2
LED14 R6
5 12 Tejas
Q5 ST_CP A3 D1
LED15 R7 6 11 Recepción
Q6 SH_CP A4 D0
_
LED16 7 10 A5 LCC
R9 Q7 SEÑOR
Tierra Q7'
Tierra
LED09 R9
LED10 R10
74HC595
LED11 R11 U2
1 16
Q1 Vcc
LED12 R12
2 15
Q2 Q0
LED13 R13 3 14
T3 DS
4
_ 13
LED14 R14 Q4 ERES
5 12
LED15 Q5 ST_CP
R15
6 11
Q6 SH_CP
LED16 R16
_
7 10
Q7 SEÑOR
8 9
Tierra Q7'
• Utilice cada serie de ocho LED para cada canal de sonido (izquierdo y derecho) • Muestre
Para cada canal, cuanto mayor sea el número de LED encendidos, mayor será el nivel de sonido.
[ 445 ]
www.itebooks.info
Machine Translated by Google
Aquí estamos usando la parte MSP del marco Max 6 que está relacionada con las señales de sonido.
Tenemos dos fuentes (denominadas fuente 1 y fuente 2) en el parche. Cada una genera dos señales.
Conecté cada una a uno de los objetos [selector~] .
Estos últimos son interruptores para señales. El selector de fuente en la parte superior izquierda
proporciona una manera de cambiar entre la fuente 1 y la fuente 2.
No voy a describir la magia barata de las fuentes de sonido; implicaría tener conocimientos de
síntesis y eso estaría fuera del alcance de este tema.
[ 446 ]
www.itebooks.info
Machine Translated by Google
Capítulo 12
Luego, tenemos una conexión entre cada salida [selector~] y un pequeño símbolo como un altavoz. Esto
está relacionado con la salida de sonido de tu interfaz de audio.
Por último, agregué un objeto [flonum] para mostrar el valor actual del nivel cada vez.
También tenemos los objetos [zmap 0. 1. 0 255] . Estos toman un valor que se pretende que esté entre
0. 1, como se configuró en los argumentos, y lo escalan al rango 0 255. Esto proporciona un byte de
datos para cada canal.
Estamos utilizando dos buses de datos para enviar un valor desde cada canal a un objeto [pak] .
Este último recoge los mensajes entrantes y crea una lista con ellos. La diferencia entre [pack] y [pak]
es que [pak] envía los datos tan pronto como recibe un mensaje en una de sus entradas, no solo cuando
recibe un mensaje de su entrada izquierda, como ocurre con [pack].
[ 447 ]
www.itebooks.info
Machine Translated by Google
De esta forma, tenemos listas de mensajes que se envían desde la computadora a Arduino tan pronto
como cambian los valores de nivel.
#include <ShiftOutX.h>
#include <NúmeroDePinDeMayús.h>
int RELOJ_595 = 4; int // primer pin del reloj 595 que se conecta al pin 4
LATCH_595 = 3; int // primer pasador de pestillo 595 que se conecta al pin 3
DATOS_595 = 2; pin 2 // primer pin de entrada de datos en serie 595 que se conecta a
configuración vacía() {
// NO MÁS configuraciones para cada pin digital del Arduino
// TODO lo hace la biblioteca :)
}
bucle vacío(){
si (Serial.available() > 0) {
CanalIzquierdo = (byte)Serial.parseInt();
CanalDerecho = (byte)Serial.parseInt();
unsigned short int data; // declarando el contenedor de datos como una variable muy local
[ 448 ]
www.itebooks.info
Machine Translated by Google
Capítulo 12
Este es el mismo firmware que el del Capítulo 8, Diseño de retroalimentación de salida visual, excepto
que aquí estamos leyendo valores reales y no generando valores aleatorios.
Esto significa que tan pronto como los datos estén en el buffer serial de Arduino, los leeremos.
En realidad, estamos leyendo dos valores y almacenándolos, después de una conversión de bytes, en
LeftChannel y RightChannel.
Luego procesamos los datos en el registro de desplazamiento para encender los LED de acuerdo con el
valor enviado por el parche Max 6.
Vamos a utilizar el mismo circuito que en el Capítulo 6, Sentir el mundo: sensaciones con entradas
analógicas.
[ 449 ]
www.itebooks.info
Machine Translated by Google
El ADC de Arduino proporciona una resolución de 10 bits, lo que dará números del 0 al 1023. Vamos a
utilizar este valor para calibrar nuestro sistema.
configuración vacía() {
Serie.begin(9600);
}
bucle vacío(){
sensorValue = analogRead(sensorPin); // leer/almacenar el valor de
sensor
Serial.println(valorSensor);
retraso(20);
}
Tan pronto como Arduino ejecuta este firmware, envía valores al puerto serie.
[ 450 ]
www.itebooks.info
Machine Translated by Google
Capítulo 12
Como describimos antes, tenemos que elegir el puerto serial correcto y luego
golpear el objeto [serial] para que aparezcan los valores en su buffer.
[ 451 ]
www.itebooks.info
Machine Translated by Google
Aquí, utilizamos el objeto [scale] . Es similar a [zmap], que ya utilizamos, porque asigna un rango a
otro, pero también puede funcionar con rangos invertidos y no recorta valores.
Aquí, estoy asignando valores que se reciben desde el ADC de Arduino de 0 a 1023 a algo que se ajuste a
nuestra necesidad de 12,0 a 0,5.
Si colocamos nuestra mano cerca del sensor, la distancia es pequeña, y si alejamos nuestra mano, la
distancia cambia y el efecto se modula.
Resumen
Este capítulo nos enseñó cómo manejar Arduino usando Max 6.
Aprendimos un poco más sobre algunas técnicas habituales en Max 6 y practicamos algunos conceptos
aprendidos previamente en este libro. Obviamente, hay más que aprender en Max 6 y me gustaría darte
algunos buenos consejos para aprender mejor.
En primer lugar, te sugiero que leas todos los tutoriales, empezando por los de Max, después los de
MSP, después los de sonido digital y, por último, los de Jitter si te interesan los elementos visuales y
OpenGL. Parece obvio, pero todavía hay dos o tres personas al día que me preguntan por dónde
empezar con Max 6. La respuesta es: los tutoriales.
Luego, te sugiero que diseñes un sistema pequeño. Menos es definitivamente más. Un sistema pequeño
ofrece formas sencillas de mantenimiento, modificación y soporte. El uso de comentarios también es una
buena forma de recordar rápidamente lo que intentaste hacer en esta o aquella parte.
Por último, la clave del éxito es aplicar un poco de parche todos los días. Lleva tiempo, pero ¿acaso no
queremos convertirnos en maestros?
[ 452 ]
www.itebooks.info
Machine Translated by Google
Mejorando tu
Programación en C y
Creando bibliotecas
Este es el último capítulo de este libro y es el más avanzado, pero no el más complejo.
Aprenderás sobre la optimización de código C a través de varios ejemplos típicos que te acercarán un
poco más y te harán más capaz para tus futuros proyectos con Arduino. Voy a hablar sobre las librerías
y cómo pueden mejorar la reutilización de tu código para ahorrar tiempo en el futuro. Describiré
algunos consejos para mejorar el rendimiento de tu código utilizando el desplazamiento de bits
en lugar de los operadores habituales, y utilizando algunas técnicas de gestión de memoria.
Luego, hablaré sobre la reprogramación del propio chip Arduino y la depuración de nuestro código
utilizando un programador de hardware externo.
Vamos.
Bibliotecas de programación
Ya he hablado de bibliotecas en el Capítulo 2, Primer contacto con C. Podemos definirlas como un
conjunto de implementaciones de comportamiento ya escritas usando un lenguaje particular que
proporciona algunas interfaces mediante las cuales se pueden llamar todos los comportamientos disponibles.
Básicamente, una biblioteca es algo ya escrito y reutilizable en nuestro propio código siguiendo
ciertas especificaciones. Por ejemplo, podemos citar algunas bibliotecas incluidas en el
núcleo de Arduino. Históricamente, algunas de esas bibliotecas se habían escrito de forma
independiente y, con el tiempo, el equipo de Arduino, así como toda la comunidad de Arduino,
las incorporaron al núcleo en crecimiento como bibliotecas disponibles de forma nativa.
www.itebooks.info
Machine Translated by Google
Tomemos la biblioteca EEPROM. Para comprobar los archivos relacionados con ella, tenemos
que encontrar la carpeta correcta en nuestro ordenador. En OS X, por ejemplo, podemos explorar el
contenido del propio archivo Arduino.app . Podemos ir a la carpeta EEPROM en Contenido/
Recursos/Java/bibliotecas/. En esta carpeta, tenemos tres archivos y una carpeta llamada ejemplos que
contiene todos los ejemplos relacionados con la biblioteca EEPROM:
• keywords.txt, que contiene algunos parámetros para colorear las palabras clave de
La biblioteca
Debido a la ubicación de estos archivos en la jerarquía de carpetas, están disponibles como parte de
la biblioteca EEPROM principal. Esto significa que podemos incluir esta biblioteca tan pronto como
tengamos el entorno Arduino instalado en nuestra computadora sin necesidad de descargar nada más.
La simple declaración include <EEPROM.h> incluye la biblioteca en nuestro código y hace que todas
las características de esta biblioteca estén disponibles para su uso posterior.
[ 454 ]
www.itebooks.info
Machine Translated by Google
Capítulo 13
El archivo de encabezado
Abramos EEPROM.h:
En este archivo, podemos ver algunas directivas de preprocesador que comienzan con el carácter # .
Esta es la misma que usamos para incluir bibliotecas en nuestro código Arduino. Aquí, esta es una
buena manera de no incluir el mismo encabezado dos veces. A veces, mientras codificamos,
incluimos muchas bibliotecas y en el momento de la compilación, tendríamos que verificar que
no incluimos el mismo código dos veces. Estas directivas y especialmente la directiva ifndef
significan: "Si la constante EEPROM_h no se ha definido, entonces haga las siguientes declaraciones".
[ 455 ]
www.itebooks.info
Machine Translated by Google
Este es un truco conocido comúnmente como protección de inclusión. Lo primero que haremos después
de esta prueba será definir la constante EEPROM_h . Si en nuestro código nosotros u otras bibliotecas
incluimos la biblioteca EEPROM, el preprocesador no reprocesará lo siguiente.
declaraciones la segunda vez que ve esta directiva.
Tenemos que terminar la directiva #ifndef con la directiva #endif . Este es un bloque común en los archivos
de encabezado y lo verás muchas veces si abres otros archivos de encabezado de biblioteca. ¿Qué
contiene este bloque? Tenemos otra inclusión relacionada con los tipos enteros de C: #include <inttypes.h>.
El IDE de Arduino contiene todos los encabezados C necesarios en la biblioteca. Como ya hemos
mencionado, podríamos usar código C y C++ puro en nuestro firmware. Hasta ahora no lo hicimos
porque las funciones y los tipos que hemos estado usando ya se han codificado en el núcleo de Arduino.
Pero tenga en cuenta que tiene la opción de incluir otro código C puro en su firmware y, en este último
capítulo, también hablaremos sobre el hecho de que también puede seguir el código de tipo procesador
AVR puro.
Ahora tenemos una definición de clase. Esta es una característica de C++. Dentro de esta clase,
declaramos dos prototipos de función:
• uint8_t leer(int)
Hay una función para leer algo, que toma un entero como argumento y devuelve un entero sin
signo de 8 bits (que es un byte). Luego, hay otra función para escribir algo que toma un entero y un
byte y no devuelve nada. Estos prototipos hacen referencia a la definición de estas funciones en el
otro archivo EEPROM.cpp .
[ 456 ]
www.itebooks.info
Machine Translated by Google
Capítulo 13
[ 457 ]
www.itebooks.info
Machine Translated by Google
A continuación incluimos la cabecera Arduino.h para tener acceso a los tipos y constantes estándar del
propio lenguaje Arduino. Por último, por supuesto, incluimos la cabecera de la propia librería EEPROM.
En las siguientes instrucciones, definimos ambas funciones. Llaman a otras funciones dentro de su
definición de bloque:
• eeprom_read_byte()
• eeprom_write_byte()
Esas funciones provienen de la propia biblioteca EEPROM del AVR. La biblioteca EEPROM de Arduino
es solo una interfaz con la propia biblioteca EEPROM del AVR. ¿Por qué no intentaríamos crear una
biblioteca nosotros mismos?
[ 458 ]
www.itebooks.info
Machine Translated by Google
Capítulo 13
3V3 5V Venir
Fuerza
D13
ARÉF D11
Modulación por ancho de pulso (PWM)
D9
Modulación por ancho de pulso (PWM)
D8
D7
D6
Modulación por ancho de pulso (PWM)
Entrada/
salida
digital
D5
Modulación por ancho de pulso (PWM)
Entrada analógica
A0 D4
A1 D3
Modulación por ancho de pulso (PWM)
A2 D2
Tejas
A3 D1
Recepción
A4 D0
A5 LCC
Tierra
No voy a hablar del circuito en sí, excepto para mencionar que puse una resistencia de 1 kΩ. Tomé el peor caso en el que
todos los LED se encenderían al mismo tiempo. Esto generaría mucha corriente y, por lo tanto, funciona como una
medida de seguridad para nuestro Arduino. Algunos autores no lo usarían. Preferiría que algunos LED se atenuaran
un poco para proteger mi Arduino.
configuración vacía() {
pinMode(i, SALIDA);
}
}
bucle vacío(){
[ 459 ]
www.itebooks.info
Machine Translated by Google
retraso(3000);
retraso(3000);
retraso(3000);
retraso(3000);
}
Este código funciona correctamente, pero ¿cómo podríamos hacerlo más elegante y, sobre
todo, más reutilizable? Podríamos incrustar los bloques for() en funciones, pero estos solo
estarían disponibles en este código, tendríamos que copiarlos y pegarlos recordando el
proyecto en el que los diseñamos para poder reutilizarlos en otro proyecto.
Al crear una pequeña biblioteca que podamos usar una y otra vez, podemos ahorrar tiempo en
el futuro, tanto en la codificación como en el procesamiento. Con algunas modificaciones
periódicas, podemos llegar al módulo perfecto para la tarea prevista, que mejorará cada vez
más hasta que no sea necesario ni siquiera tocarlo porque funciona mejor que cualquier otra
cosa que exista. Al menos eso es lo que esperamos.
[ 460 ]
www.itebooks.info
Machine Translated by Google
Capítulo 13
/*
LEDpatterns Biblioteca para crear lindos patrones de LED.
Creado por Julien Bayle, 10 de febrero de 2013. */ #ifndef
LEDpatterns_h #define
LEDpatterns_h
#include "Arduino.h"
clase LEDpatterns {
público:
LEDpatterns(int primerPin, int ledsNumber); void switchOnAll(); void
switchOffAll(); void switchEven();
};
#finsi
Primero escribimos nuestras protecciones de inclusión. Luego incluimos la biblioteca Arduino. Luego, definimos
una clase llamada LEDpatterns con las funciones públicas que incluyen un constructor que tiene el mismo nombre
que la clase misma.
También tenemos dos variables internas (privadas) relacionadas con el primer pin en el que están conectados los
LED y relacionadas con la cantidad total de LED cableados. En ese ejemplo, los LED tendrían que estar
[ 461 ]
www.itebooks.info
Machine Translated by Google
#include "Arduino.h"
#include "patronesLED.h"
pinMode(i, SALIDA);
}
vacío LEDpatterns::switchOnAll() {
}
}
vacío LEDpatterns::switchOffAll() {
}
}
vacío LEDpatterns::switchEven() {
vacío LEDpatterns::switchOdd()
[ 462 ]
www.itebooks.info
Machine Translated by Google
Capítulo 13
{
para (int i = _firstPin ; i < _ledsNumber + _firstPin ; i++)
{
si ( i % 2 != 0 ) digitalWrite(i, HIGH);
de lo contrario digitalWrite(i, BAJO);
}
}
En primer lugar, recuperamos todas las librerías incluidas . Luego tenemos el constructor, que es un
método especial con el mismo nombre que la librería. Este es el punto importante aquí. Toma dos
argumentos. Dentro de su cuerpo, ponemos todos los pines desde el primero hasta el último considerando
el número de LED como una salida digital. Luego, almacenamos los argumentos del constructor dentro
de las variables privadas previamente definidas en el encabezado LEDpatterns.h.
Luego podemos declarar todas nuestras funciones relacionadas con las creadas en el primer ejemplo
sin la biblioteca. Observe el prefijo LEDpatterns:: para cada función. No analizaré aquí esta sintaxis
puramente relacionada con la clase, pero tenga en cuenta la estructura.
#######################################
# Mapa de colores de sintaxis para Messenger
#######################################
#######################################
#Tipos de datos (PALABRA CLAVE1)
#######################################
#######################################
# Métodos y funciones (PALABRA CLAVE2)
#######################################
Encender todo PALABRA CLAVE2
#######################################
[ 463 ]
www.itebooks.info
Machine Translated by Google
#######################################
# Constantes (LITERAL1)
#######################################
[ 464 ]
www.itebooks.info
Machine Translated by Google
Capítulo 13
Ahora vamos a comprobar el nuevo código que utiliza esta biblioteca. Puede encontrarla en la carpeta
Chapter13/ LEDLib :
configuración vacía()
{}
bucle vacío(){
ledpattern.switchOnAll(); retraso(3000);
ledpattern.switchOffAll(); retraso(3000);
ledpattern.switchEven(); retraso(3000);
ledpattern.switchOdd();
retraso(3000);
}
En el primer paso incluimos la librería LEDpatterns . Luego creamos la instancia de LEDpatterns llamada
ledpattern. Llamamos al constructor que diseñamos previamente con dos argumentos:
ledpattern es una instancia de la clase LEDpatterns . Se hace referencia a ella en todo nuestro código y, sin
#include, no funcionaría. También hemos invocado cada método de esta instancia.
Si el código parece más limpio, el verdadero beneficio de un diseño de este tipo es el hecho de que
podemos reutilizar esta biblioteca dentro de cualquiera de nuestros proyectos. Si queremos modificar y
mejorar la biblioteca, solo tenemos que modificar cosas en el encabezado y el archivo fuente de nuestra biblioteca.
[ 465 ]
www.itebooks.info
Machine Translated by Google
Gestión de la memoria
Esta sección es muy breve pero no por ello menos importante. Debemos recordar que en Arduino
tenemos los siguientes tres grupos de memoria:
• Memoria de acceso aleatorio estático (SRAM), donde el boceto crea y manipula variables en
tiempo de ejecución
La memoria flash y la EEPROM, a diferencia de la SRAM, no son volátiles, lo que significa que los
datos persisten incluso después de apagar la alimentación. Cada placa Arduino tiene una cantidad
de memoria diferente:
° SRAM 2k bytes
° EEPROM 1k bytes
° SRAM 8k bytes
° EEPROM 4k bytes
Eso ocupa 32 bytes en la SRAM. No parece mucho, pero con la UNO, solo tienes 2048 bytes disponibles.
Imagina que utilizas una tabla de búsqueda grande o una gran cantidad de texto.
A continuación se ofrecen algunos consejos para ahorrar memoria:
•
Si su proyecto utiliza tanto Arduino como una computadora, puede intentar mover algunos pasos
de cálculo desde Arduino a la computadora, haciendo que Arduino solo active los cálculos en la
computadora y solicite resultados, por ejemplo.
• Utilice siempre el tipo de datos más pequeño posible para almacenar los valores que necesita. Si
necesita almacenar algo entre 0 y 255, por ejemplo, no utilice un int
tipo que ocupa 2 bytes, pero utiliza un tipo de byte en su lugar
•
Si utiliza algunas tablas de búsqueda o datos que no se modificarán, puede almacenarlos en la
memoria Flash en lugar de en la SRAM. Debe utilizar el programa PROGMEM.
Palabra clave para hacer eso.
[ 466 ]
www.itebooks.info
Machine Translated by Google
Capítulo 13
•
<< es el operador de desplazamiento a la izquierda
•
>> es el operador de desplazamiento a la derecha
Estos pueden ser muy útiles especialmente en la memoria SRAM, y a menudo pueden optimizar su código. << puede
entenderse como una multiplicación del operando izquierdo por 2 elevado a la potencia del operando derecho.
>> es lo mismo pero es similar a una división. La capacidad de manipular bits suele ser muy útil y puede hacer que su
código sea más rápido en muchas situaciones.
La segunda fila multiplica la variable a por 2 elevado a la tercera potencia, por lo que b ahora contiene 32. Siguiendo
la misma línea, la división se puede realizar de la siguiente manera:
int a = 12;
int b = a >> 2;
b contiene 3 porque >> 2 es igual a la división por 4. El código puede ser más rápido usando estos operadores
porque son un acceso directo a operaciones binarias sin usar ninguna función del núcleo Arduino como pow() o
incluso los otros operadores.
[ 467 ]
www.itebooks.info
Machine Translated by Google
{0,0,1,0,1,0,0},
{0,0,0,1,0,0,0},
{0,0,1,0,1,0,0},
{1,1,0,0,0,1,1} };
En el primer caso, se necesitan 7 x 5 = 35 bytes por mapa de bits. En el segundo, se necesitan solo 5 bytes.
Supongo que acabas de descubrir algo enorme, ¿no?
vacío configuración() {
int pin;
}
}
configuración vacía() {
DDRB = B00111111 ; // DDRB son los pines del 8 al 15
}
En una sola pasada, hemos configurado todo el paquete en una variable directamente en la
memoria, y no es necesario compilar ninguna función, estructura o nombre de variable pinMode .
[ 468 ]
www.itebooks.info
Machine Translated by Google
Capítulo 13
Usé este un par de veces para programar una placa tipo Arduino FIO para aplicaciones inalámbricas
específicas en un proyecto que conecta ciudades llamado The Village en 2013.
[ 469 ]
www.itebooks.info
Machine Translated by Google
Para reprogramar el procesador de Arduino, primero tenemos que cerrar el IDE de Arduino y luego revisar el
archivo de preferencias (preferences.txt en Mac, ubicado en Contenidos/Recursos/Java/lib dentro del
propio paquete Arduino.app ).
En una PC con Windows 7 o superior, este archivo se encuentra en: c:\Users\<NOMBREDEUSUARIO>\
AppData\Local\Arduino\preferences.txt. En Linux se encuentra en: ~/arduino/
preferencias.ard.
Tenemos que cambiar el valor upload.using que se establece inicialmente en bootloader por el identificador
correcto que se ajuste a tu programador. Esto se puede encontrar en el contenido del paquete de la aplicación
Arduino en OS X o dentro de las carpetas de Arduino en Windows.
Por ejemplo, si muestra el contenido de Arduino.app , puede encontrar este archivo: Arduino.
app/Contenidos/Recursos/Java/hardware/arduino/programmers.txt.
Luego podemos iniciar el IDE de Arduino para cargar el sketch usando nuestro programador.
Para volver al comportamiento normal del gestor de arranque, primero tenemos que volver a cargar
el gestor de arranque que se adapta a nuestro hardware. Luego, tenemos que volver a modificar el
archivo de preferencias.txt y funcionará como la placa inicial.
[ 470 ]
www.itebooks.info
Machine Translated by Google
Capítulo 13
Resumen
En este capítulo, aprendimos más sobre el diseño de bibliotecas y ahora podemos diseñar nuestros
proyectos de una manera un poco diferente, teniendo en cuenta la reutilización del código o parte del
código en proyectos futuros. Esto puede ahorrar tiempo y también mejora la legibilidad.
También podemos explorar las bibliotecas existentes y disfrutar del mundo del código abierto,
tomándolas, modificándolas y adaptándolas a nuestras necesidades. Este es un mundo realmente
abierto en el que apenas hemos dado nuestros primeros pasos.
Conclusión
Hemos llegado al final de este libro. Probablemente hayas leído todo y también hayas probado
algunos fragmentos de código con tu propio hardware, y estoy seguro de que ahora eres capaz de
imaginar tus futuros proyectos avanzados con Arduino.
Quería agradecerte por estar tan concentrado e interesado. Sé que ahora estás casi en la misma
situación que yo, quieres aprender más, probar más y comprobar y usar nuevas tecnologías para lograr
tu proyecto más loco. Me gustaría decirte una última cosa: ¡hazlo y hazlo ahora!
En la mayoría de los casos, la gente tiene miedo de la enorme cantidad de trabajo que se imaginan en
los primeros pasos justo antes de empezar. Pero tienes que confiar en mí, no pienses demasiado en
los detalles ni en la optimización. Intenta hacer algo sencillo, algo que funcione. Entonces tendrás
formas de optimizarlo y mejorarlo.
Un último consejo para ti: no pienses demasiado y haz mucho. He visto demasiados proyectos
inacabados de gente que ha querido pensar, pensar y pensar en lugar de simplemente empezar y hacer.
[ 471 ]
www.itebooks.info
Machine Translated by Google
www.itebooks.info
Machine Translated by Google
Índice
Símbolos Corriente
alterna (CA) alfa 106 21
Proyecto universo 3D con AMOLED 254
Max 6 187 amperios 21
Matriz LED 3 x 3 código 291295 analógico 138
75HC595 dominio analógico 326
conectando a Arduino 266268 entradas
conectando a LEDs 266268 analógicas
Cable 100 Base T 400 lectura 181
[fromsymbol] objeto 436 [iter] detección 180 serie de E/S
objeto 431 [loadbang] analógicas 232
objeto 431 [metro] objeto salidas analógicas simulación, con
432 + operador using, PWM 295 función analogRead() 183, 184, 342
en cadenas convertidor analógico a digital (ADC) 180, 328 función
64 [pack] objeto 447 [pak] analogWrite() 296, 308, 309
objeto 447 [prepend] Operador AND 112 capa
objeto 431 [requester] de aplicación 397
subpatcher 440 [scale] Programación de aplicaciones
objeto 452 [serial] objeto 430 Interfaz (API) 105, 422
[trigger] objeto 431 arcocoseno 109
[umenu] objeto 431, concepto de arquitectura, matriz LED 288, 289 arcoseno
432 [unpack] objeto 436 109
[zmap] objeto 452 arcotangente 109
Arduino
75HC595, conectando a 266268 acerca
de 79 y
A Procesando 149, 150
comunicando 49
Ableton en vivo
conectando, a Max 6 203, 204 datos,
URL 344
solicitando de 435 controladores,
abstracciones 443
instalando 19 entorno,
Matriz activa OLED. Ver AMOLED ADC 180
lanzando 16
modo ad
IDE, instalando 15
hoc 413 ADSL 395
IDE, interfaz 1618
funciones matemáticas 105
movimiento del aire 323
Conector MIDI, cableado a 352354
www.itebooks.info
Machine Translated by Google
Estructura 40 conversión de
variables 40 números binarios a números decimales 111
Fuente de alimentación Arduino, adaptador de corriente 380, 381 sistema de numeración binario 111
Arduino Uno 10 técnica de bitbanging 329, 332 profundidad
Controladores Arduino de bits 328
[ 474 ]
www.itebooks.info
Machine Translated by Google
[ 475 ]
www.itebooks.info
Machine Translated by Google
[ 476 ]
www.itebooks.info
Machine Translated by Google
[ 477 ]
www.itebooks.info
Machine Translated by Google
401 conversión de tipo explícita 80, 82 usado, para convertir RS232 a USB 250 modo full
funciones exponenciales 110 duplex 242 función acerca de
cableado EEPROM externo 364, 365 bibliotecas 99 beneficios
externas 103105
MsTimer2 44 cuerpo 101103
TLC5940 44 encabezado 100,
Instalación 101 nombre 100, 101
de la biblioteca declaraciones
externa Tone 44 131, 132 101103
Estructura 100
F Creación de prototipos de
funciones , IDE Arduino utilizado 100
Transformada rápida de Fourier (FFT) 324
Función FillCircle() 386 variable GRAMO
[ 478 ]
www.itebooks.info
Machine Translated by Google
inmersión 230
[ 479 ]
www.itebooks.info
Machine Translated by Google
Yo
75HC595, conectando a 266268 multiplexación
265 tipos 254 utilizados,
Java 38
para crear un
JavaScript 38 medidor de nivel de sonido 444 utilizando 254 cableado,
Máquina virtual Java 15 jit.gen 197
a la placa
jit.gl.pix 197 458, 459 función length() 68 diodo
jit.pix 197 Jitter emisor de luz (LED) sobre
acerca de 194, 11, 28, 29 control 279 atenuación
198 297, 298 patrones de
para elementos
luz creando 459, 460
visuales 195, 196
enlace 46 programa
Compilador JS JIT 196 enlazador 46
LiquidCrystal 300
K
Pantalla de
cristal líquido. Ver LCD
Archivo keywords.txt 454
largo 57 Tabla de
Archivo keywords.txt
búsqueda (LUT) 118 tablas de búsqueda
Escritura 463, 464
Kinect 188 acerca de
117 inicialización de tabla 118, 119
yo función loop() 97,
103, 125, 183
[ 480 ]
www.itebooks.info
Machine Translated by Google
[ 481 ]
www.itebooks.info
Machine Translated by Google
Nvidia Cg
URL 197 variable 405 del paquete buffer
Frecuencia de Nyquist 326 PAN 408
paradigma 37
EL Módulo receptor GPS Parallax
cableado 368370
Compatibilidad con OAuth Microcontrolador Parallax SX, líneas 8,
Biblioteca de Twitter, utilizando el archivo
comunicación paralela 47, 240, función
de objeto 423 46
parsePacket() 405
ObjetivoC 38 Parche del
Propiedades de la programación orientada a
objetos (POO) 39 analizador 46 sobre 189, 199201
Ohmios 22
Mensajes de Arduino, análisis 450, 452
Ley de Ohm 181
[ 482 ]
www.itebooks.info
Machine Translated by Google
[ 483 ]
www.itebooks.info
Machine Translated by Google
S
aproximadamente 106 versus grado 106, 107
Memoria de acceso aleatorio (RAM) 7 Función Número de serie 247
[ 484 ]
www.itebooks.info
Machine Translated by Google
205 220
selección de puerto serial SPI 431, 432 SMBus 247 , hardware utilizado 203
Serial.print() función 53 Serial.println() función 53, arquitectura de software 13, 14
210 SONET 395
329 cableado
servomotores del circuito de
[ 485 ]
www.itebooks.info
Machine Translated by Google
[ 486 ]
www.itebooks.info
Machine Translated by Google
[ 487 ]
www.itebooks.info
Machine Translated by Google
WiFi 395
acerca de
412 modo ad hoc 413
modo puente 414 modo
infraestructura 413 modo extensor
de rango 414 WiFi.begin() 418
biblioteca WiFi acerca
de 415 WEP,
usando con
418 WPA2, usando con 418
WiFi Shield acerca de 414
características
414, 415 Red
de área local
inalámbrica (WLAN) 412 cables 20 Plataforma de cableado
acerca de 8
URL 8 palabra 57
WPA2
usando,
con
biblioteca
WiFi 418
Función WriteData() 385
incógnita
[ 488 ]
www.itebooks.info
Machine Translated by Google
Nuestros libros y publicaciones comparten las experiencias de sus colegas profesionales de TI en la adaptación y
personalización de los sistemas, aplicaciones y marcos de trabajo actuales. Nuestros libros basados en
soluciones le brindan el conocimiento y el poder para personalizar el software y las tecnologías que utiliza para
realizar su trabajo. Los libros de Packt son más específicos y menos generales que los libros de TI que ha visto en
el pasado. Nuestro modelo de negocios único nos permite brindarle información más enfocada, brindándole más de
lo que necesita saber y menos de lo que no necesita saber.
Packt es una editorial moderna y única, cuyo objetivo es producir libros de calidad y de vanguardia para
comunidades de desarrolladores, administradores y principiantes. Para obtener más información, visite nuestro
sitio web: www.packtpub.com.
No solo buscamos autores publicados; si tiene sólidas habilidades técnicas pero no tiene experiencia en escritura,
nuestros editores experimentados pueden ayudarlo a desarrollar una carrera como escritor o simplemente a obtener
una recompensa adicional por su experiencia.
www.itebooks.info
Machine Translated by Google
Por favor, consulte www.PacktPub.com para obtener información sobre nuestros títulos.
www.itebooks.info
Machine Translated by Google
Redes Raspberry Pi
Libro de cocina
ISBN: 9781849694605 Tapa blanda: 204 páginas
Procesamiento 2: Creativo
Libro de recetas de programación
ISBN: 9781849517942 Tapa blanda: 436 páginas
Por favor, consulte www.PacktPub.com para obtener información sobre nuestros títulos.
www.itebooks.info