0% encontró este documento útil (0 votos)
4 vistas

C Programming for Arduino by Julien Bayle_español

El libro 'Programación en C para Arduino' de Julien Bayle enseña a programar y utilizar placas Arduino a través de ejemplos prácticos. Publicado por Packt Publishing en 2013, aborda desde conceptos básicos de microcontroladores hasta programación en C y el uso de bibliotecas. Además, incluye información sobre el autor y su trayectoria en el ámbito del arte y la tecnología.

Cargado por

José Tenorio
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
4 vistas

C Programming for Arduino by Julien Bayle_español

El libro 'Programación en C para Arduino' de Julien Bayle enseña a programar y utilizar placas Arduino a través de ejemplos prácticos. Publicado por Packt Publishing en 2013, aborda desde conceptos básicos de microcontroladores hasta programación en C y el uso de bibliotecas. Además, incluye información sobre el autor y su trayectoria en el ámbito del arte y la tecnología.

Cargado por

José Tenorio
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
Está en la página 1/ 512

Machine Translated by Google

www.bookbenefits.com
Machine Translated by Google

Programación en C para Arduino

Aprenda a programar y utilizar placas Arduino


con una serie de ejemplos atractivos que ilustran
cada concepto central.

Julien Bayle

BIRMINGHAM ­ BOMBAY

www.bookbenefits.com
Machine Translated by Google

Programación en C para Arduino

Derechos de autor © 2013 Packt Publishing

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.

Primera publicación: mayo de 2013

Referencia de producción: 1070513

Publicado por Packt Publishing Ltd.


Livery Place 35
Livery Street
Birmingham B3 2PB, Reino Unido.

Número de publicación: 978­1­84951­758­4

www.packtpub.com

Imagen de portada de Asher Wishkerman ([email protected])

www.bookbenefits.com
Machine Translated by Google

Créditos

Autor Editores de copias

Julien Bayle Laxmi Subramanian

Sajeev Raghavan
Revisores
India Morbiwala
Darwin Grosse
Brandt D’Mello
Pradumn Joshi
Aditya Nair
Phillip Mayhew
Alfida Paiva
Glenn D. Reuther

Steve Spence Coordinador de proyectos


Leena Purkait

Editor de adquisiciones
Edward Gordon Correctores de pruebas

Erol Staveley Claire Cresswell­Lane

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

Baet de Sharvari Coordinador de producción

Pooja Chiplunkar

Trabajo de portada

Pooja Chiplunkar

www.bookbenefits.com
Machine Translated by Google

Acerca del autor

Julien Bayle se licenció en Biología y Ciencias de la Computación en 2000. Después


de varios años trabajando en el diseño de sistemas informáticos, fundó Design the
Media a principios de 2010 para ofrecer sus propios cursos, formación y herramientas
para el ámbito artístico. Como artista digital, ha diseñado algunas enormes instalaciones
de arte en nuevos medios, como la exposición permanente de La Maison des
Cinématographies de la Méditerranée (Château de la Buzine) en Marsella, Francia,
en 2011. También ha trabajado como consultor de tecnología de nuevos medios para
algunas entidades públicas y privadas. Como artista audiovisual en directo, toca su
fría música electrónica desde Nueva York hasta Marsella, donde vive. El marco
Arduino es uno de sus primeros estudios de hardware electrónico desde principios de
2005, y también diseñó el famoso controlador protodeck con varios marcos de código
abierto. Como profesor de Arte y Tecnología también certificado por Ableton en 2010,
imparte numerosos cursos relacionados con la estación de trabajo de audio digital
Ableton Live, el framework de programación gráfica en tiempo real Max 6, y Processing y Arduino.

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.

Está muy involucrado en la comunidad de código abierto y le encanta compartir y


brindar talleres y clases magistrales en línea y en el sitio. Su sitio web personal es http://
julienbayle.net.

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
glcd­arduino) 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

Acerca de los revisores

Darwin Grosse es el director de Educación y Servicios de Cycling '74, el desarrollador


del sistema de programación multimedia Max. También es profesor adjunto en la
Universidad de Denver y enseña arte sonoro, programación e interfaz de hardware en
el departamento de Prácticas digitales emergentes.

Pradumn Joshi actualmente está cursando su licenciatura en Ingeniería Eléctrica


en NIT Surat. Es un entusiasta de la oratoria y el debate, y también está interesado en la
economía, la escritura independiente y la música occidental. Su área de
especialización técnica se centra en el desarrollo de hardware de código abierto y los
sistemas integrados.

Phillip Mayhew es licenciado en Ciencias de la Computación por la Universidad


Estatal de Carolina del Norte. Es el fundador y director general de Rextency Technologies
LLC, con sede en Statesville, Carolina del Norte. Su principal especialidad es la
supervisión y el análisis del rendimiento de aplicaciones de software.

www.bookbenefits.com
Machine Translated by Google

El viaje personal y la fascinación de Glenn D. Reuther por la tecnología musical comenzaron


en la década de 1970, con clases particulares de "Teoría de la música electrónica y física
acústica". Luego asistió al Five Towns College of Music en Nueva York y ha sido operador
de estudio en casa desde 1981, tocando varios instrumentos y diseñando algunos dispositivos
para la configuración de su estudio.

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.

También es autor de "One Complete Revelation", un diario fotográfico de su viaje de nueve


meses por Europa a principios de los años 90.

Me gustaría agradecer al autor por su amistad, y también me gustaría agradecer


a mi maravillosa esposa Alice y a mi hijo Glenn por su paciencia, comprensión y
apoyo durante el proceso de edición de este libro.

Steve Spence es un veterano de la industria de TI desde hace más de 20 años,


especializado en diseño y seguridad de redes. Actualmente diseña controles de procesos
basados en microcontroladores y sitios web basados en bases de datos. Vive fuera de la red
y enseña talleres sobre generación de energía solar y eólica. Es un ex bombero y miembro
del equipo de rescate, y actualmente es un operador de radioaficionado.

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

Archivos de soporte, libros electrónicos, ofertas de


descuento y más
Quizás desee visitar www.PacktPub.com para obtener archivos de soporte y descargas relacionadas con su
libro.

¿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.

¿Por qué suscribirse?


• Búsqueda completa en todos los libros publicados por Packt
• Copiar y pegar, imprimir y marcar contenido
• A pedido y accesible a través del navegador web

Acceso gratuito para titulares de cuentas Packt


Si tiene una cuenta en Packt en www.PacktPub.com, puede usarla para acceder a PacktLib hoy mismo y
ver nueve libros totalmente gratis. Simplemente use sus credenciales de inicio de sesión para obtener acceso
inmediato.

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

Capítulo 2: Primer contacto con C Una 35


introducción a la programación Diferentes 35
paradigmas de programación ¿Estilo de 37
programación C y C++? 37
38
C se utiliza en todas partes donde 38
Arduino está programado con C y C++ La biblioteca nativa de 39
Arduino y otras bibliotecas Descubriendo la biblioteca nativa de Arduino 39
Otras bibliotecas incluidas y no proporcionadas 40
directamente Algunas bibliotecas incluidas muy útiles Algunas bibliotecas 43
externas
43
44

Comprobando todos los pasos básicos de desarrollo 44


Usando el monitor serial Tasa de 46
Baudios 47
Comunicación serial con Arduino Monitoreo 47
serial Haciendo que 48
Arduino nos hable Añadiendo 49
comunicación serial a Blink250ms Funciones seriales 49
con más detalle Serial.begin() 53
53
Serial.print() y Serial.println() 53

Investigando un poco… 53
Hablar con la pizarra desde la computadora 54
Resumen 54

Capítulo 3: Conceptos básicos de C: Cómo fortalecerse Abordaje 55


de variables y tipos de datos ¿Qué es una variable? 55
56
¿Qué es un tipo? 56
El concepto de roll over/wrap 58

Declaración y definición de variables 58


Declaración de 58
variables Definición 59

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

Concatenación, extracción y reemplazo 63


Concatenación 64
Extraer y reemplazar 65

[ ii ]

www.bookbenefits.com
Machine Translated by Google

Tabla de contenido

Otras funciones de cadena 68


toCharArray() 68
toLowerCase() y toUpperCase() 68
trim() 68
length() 68

Probando variables en el tablero 68


Algunas explicaciones 71

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

Notaciones condensadas y precedencia 77


Operadores de incremento y decremento 78
Manipulaciones de tipos 79
Elegir el tipo adecuado 79
Conversiones de tipos implícitas y explícitas 80
Conversión de tipo implícita 80
Conversión de tipo explícita 82

Comparación de valores y operadores booleanos 82


Expresiones de comparación 82
Combinación de comparaciones con operadores booleanos 83
Combinando negación y comparaciones 84

Agregar condiciones en el código 86


Estructura condicional if y else Estructura 86
condicional switch…case…break Operador ternario 89
Crear bucles 91
inteligentes para tareas repetitivas Estructura de bucle 91
for 91
Jugando con 93
incrementos Usando bucles for imbricados 93

o dos índices while loop 95


structure do…while loop 96
structure Rompiendo 96
los bucles Los bucles infinitos no son tus 97
amigos Resumen 98

[ iii ]

www.bookbenefits.com
Machine Translated by Google

Tabla de contenido

Capítulo 4: Mejorar la programación con funciones,


Matemáticas y tiempo 99
Introducción de funciones 99
Estructura de una función 100
Creación de prototipos de funciones utilizando el IDE de Arduino 100
Encabezado y nombre de funciones 100
Cuerpo y enunciados de funciones 101

Beneficios de utilizar funciones 103


Codificación y depuración más sencillas 103
Una mejor modularidad favorece la reutilización 104
Mejor legibilidad 105

Funciones matemáticas estándar de C y Arduino 105


Funciones trigonométricas C en el núcleo Arduino 106
106
Algunos requisitos
109
previos Funciones
trigonométricas Funciones exponenciales y algunas 110
otras Acercándose a la optimización del cálculo El 110
poder de la operación de desplazamiento de 111
111
bits ¿Qué son las operaciones de bits?
111
Sistema de numeración
112
binario Operadores AND, OR, XOR y NOT
113
Operaciones de
114
desplazamiento de bits Todo es
cuestión de rendimiento Técnicas de optimización de etiquetas de casos de conmutación 114
Optimización de la gama de casos 114
Optimización de casos según su frecuencia 115

Cuanto menor sea el alcance, mejor será el tablero. 115


El Tao de los retornos 116
El concepto de retorno directo 116
Utilice void si no necesita devolución 117

Secretos de las tablas de búsqueda 117


Inicialización de tabla 118
Reemplazar el cálculo puro con operaciones de índice de matriz 119

El truco de la expansión de la serie de Taylor 119


El núcleo Arduino incluso proporciona punteros 120
Medida del tiempo 121
¿La placa Arduino posee un reloj? 121
121
La función millis() La
123
función micros() El
concepto de retardo y el flujo del programa 124
¿Qué hace el programa durante el retraso? 124
El concepto de sondeo: un caso especial de interrupción 127
El concepto de controlador de 128
interrupciones ¿Qué es un hilo? 129
Un ejemplo de biblioteca de encuestas de la vida real 130

Resumen 134
[ iv ]

www.bookbenefits.com
Machine Translated by Google

www.bookbenefits.com

Tabla de contenido

Capítulo 5: Detección con entradas digitales Detección 135


del mundo Los sensores 135
proporcionan nuevas capacidades 136
Algunos tipos de 136

sensores La cantidad se convierte 137


en datos Los datos deben 138
percibirse ¿Qué significa digital? 138
Conceptos digitales y analógicos 138
Entradas y salidas de Arduino 139
Presentando un nuevo amigo: Processing ¿Es 140
Processing un lenguaje? 140
Vamos a instalarlo y ejecutarlo 141
Un IDE muy familiar IDE 142
alternativos y versiones 145

Comprobando un ejemplo 145


Processing y Arduino Pulsando 149
el botón ¿Qué es un 150
botón, un interruptor? 150
Diferentes tipos de interruptores 150
Un circuito básico 150
Cables 151
El circuito en el mundo real 151

El concepto de pull­up y pull­down 153


El pseudocódigo 154
El código 154

Haciendo que Arduino y Processing hablen 155


El protocolo de comunicación 155
El código de procesamiento 157
El nuevo firmware Arduino listo para hablar 163

Jugando con varios botones 165


El circuito 166
El código Arduino 168
El código de procesamiento 170
Entendiendo el concepto de rebote ¿Qué? ¿Quién 173
está rebotando? 173
Resumen de cómo 174
eliminar rebotes 177

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

¿Cómo convertir el Arduino en un voltímetro de bajo voltaje? 184

Presentación de Max 6, el marco de programación gráfica Una breve historia 186


de Max/MSP Conceptos globales 187
¿Qué es un marco 189
de programación gráfica? 189
Max, para el patio de 190
juegos MSP, 193
para sonido Jitter, 194
para elementos visuales Gen, para un nuevo 196
enfoque en la generación de código 198

Resumiendo todo 198


en una tabla Instalación 199
de Max 6 El primer parche 201

Reproduciendo sonidos con el parche Controlando 203


el software usando hardware Mejorando el secuenciador y conectando Arduino 203
Conectemos Arduino a Max 6 203
El objeto serial en Max 6 204
Rastreo y depuración fácil en Max 6 206
Entendiendo los mensajes de Arduino en Max 6 206
¿Qué se envía realmente por el cable? 209
¿Extraer sólo la carga útil? 211
Conversiones y símbolos ASCII 212
Jugando con sensores 214
Midiendo distancias 214
¿Leyendo una hoja de datos? 215
Conectemos 217
cosas Codificando el 218
firmware Leyendo la distancia en 220
Max 6 Medición de flexión 222
Cálculos de resistencia 224

Detección de casi todo Multiplexación con 226


un multiplexor/demultiplexor CD4051 Conceptos de multiplexación Técnicas de 226
multiplexación/demultiplexación 227
múltiple Multiplexación por división espacial Multiplexación por división de 227
frecuencia Multiplexación por 228
división de tiempo El multiplexor 228
analógico CD4051B ¿Qué es un 229

circuito integrado? 230


230
¿Cómo cablear el IC CD4051B? 231
Alimentación de la 232
serie de E/S analógicas de IC y de la E/S 232
común Selección del pin 233
digital Resumen 237

[ nosotros ]

www.bookbenefits.com
Machine Translated by Google

Tabla de contenido

Capítulo 7: Hablando sobre Serial 239


Comunicación en serie 239
Comunicación serial y paralela 240
Tipos y características de las comunicaciones seriales 241
Sincrónico o asincrónico 241
Modo dúplex 241
Peering y bus 242
Codificación de datos 243
Interfaces seriales múltiples 244
El poderoso antepasado de la telegrafía en código Morse 244
El famoso RS­232 244
El elegante I2C 246
El SPI sincrónico 247
El USB omnipresente 248
Resumen 251

Capítulo 8: Diseño de retroalimentación de salida visual mediante LED Diferentes 253


tipos de LED LED 254
monocromáticos LED policromáticos 254
Recordando el ejemplo del 255
LED Hello Múltiples LED 255
monocromáticos Dos botones y dos LED Acoplamiento de 256
control y retroalimentación en el diseño de 258
interacción El firmware de 258
acoplamiento ¿Más LED? 260
263
265
Multiplexación de LED 265
Conexión del 75HC595 a Arduino y LED 266
Firmware para el manejo de registros de desplazamiento 268
Patrón de programación de registro de desplazamiento global 270
Jugando con el azar y semillas aleatorias 271
Conexión en cadena de varios registros de desplazamiento 74HC595 272
Vinculación de múltiples registros de desplazamiento 273
Firmware que maneja dos registros de desplazamiento y 16 LED 274
Consideraciones breves actuales 278
Uso de LED RGB 279
Algunos conceptos de control 279
Diferentes tipos de LED RGB 280
Encender un LED RGB 281
Componentes y colores de la luz roja, verde y azul 282
Múltiples bucles for() imbricados 283
Construcción de matrices de LED 284
Un nuevo amigo llamado transistor 285
Matriz de transistores Darlington, ULN2003 286

[ vii ]

www.it­ebooks.info
Machine Translated by Google

Tabla de contenido

La matriz LED 287


Ciclismo y POV 289
El circuito 290
El código de matriz LED 3 x 3 291
Simulación de salidas analógicas con PWM 295
El concepto de modulación por ancho de pulso 296
Atenuación de un LED 297
Un componente de controlador PWM de mayor resolución 298
Introducción rápida a la pantalla LCD 299
Circuito de pantalla LCD compatible con HD44780 301
Mostrando algunos mensajes aleatorios 302
Resumen 304
Capítulo 9: Hacer que las cosas se muevan y crear sonidos 305
Haciendo que las cosas vibren 306
El sensor piezoeléctrico 306
Cableado de un motor de 307
vibración Firmware generador de 308
vibraciones Manejo de corrientes más altas y 309
transistores Control de un 311
servo ¿Cuándo necesitamos servos? 311
Cómo controlar servos con Arduino Cableado 311
de un servo Firmware 312
que controla un servo usando la biblioteca Servo 313
Múltiples servos con una fuente de alimentación externa Tres 314
servos y una fuente de alimentación externa Controlar 315
tres servos con firmware Controlar motores 316
paso a paso Cablear un motor paso 318
a paso unipolar a Arduino Firmware que 318
controla el motor paso a paso Movimiento del aire 320
y sonidos ¿Qué es realmente el 323
sonido? 323
Cómo describir el sonido 324
Micrófonos y altavoces Dominios 325
digitales y analógicos Cómo 326
digitalizar el sonido 326
Cómo reproducir bits digitales como 328

sonidos Cómo Arduino ayuda a producir 329


sonidos Reproducir bits básicos 329
de sonido Cableado del circuito de sonido 330
más barato Reproducir tonos aleatorios 331
Mejorando el motor de sonido con Mozzi 332

[ viii ]

www.it­ebooks.info
Machine Translated by Google

Tabla de contenido

Configuración de un circuito y una biblioteca Mozzi 333


Un ejemplo de onda sinusoidal 335
Osciladores 336
Tablas de ondas 336

Modulación de frecuencia de una onda sinusoidal 338


Añadiendo una olla 339
Actualización del firmware para el manejo de entradas 340

Controlar el sonido mediante envolventes y MIDI 343


Una descripción general de MIDI 343
Librerías MIDI y OSC para Arduino 344
Generando sobres 344
Implementando envolventes y MIDI 346
Cableado de un conector MIDI a Arduino 352
Reproducción de archivos de audio con la biblioteca PCM 355
La biblioteca PCM 355
WAV2C – conversión de su propia muestra 356
Cableado del circuito 358
Otras bibliotecas de lectores 359
Resumen 360

Capítulo 10: Algunas técnicas avanzadas 361


Almacenamiento de datos con EEPROM 361
Tres reservas nativas de memoria en el
Placas Arduino 361
Escritura y lectura con la biblioteca central EEPROM 362

Cableado de EEPROM externa 364


Lectura y escritura en la EEPROM 366
Uso de módulos GPS 368
Cableado del módulo receptor GPS Parallax 368
Análisis de datos de ubicación GPS 371
Arduino, batería y autonomía 377
Casos clásicos de alimentación por USB 377
Suministro de energía externa 378
Suministro de baterías 378

Adaptador de corriente para fuente de alimentación Arduino 380


Cómo calcular el consumo actual 381
Dibujo sobre gLCD 382
Cableado del dispositivo 383
Demostración de la biblioteca 384
Algunas familias de métodos útiles 385
Métodos GLCD globales 385
Métodos de dibujo 385
Métodos de texto 386

[ ix ]

www.it­ebooks.info
Machine Translated by Google

Tabla de contenido

Uso de VGA con Gameduino Shield 387


Resumen 389
Capítulo 11: Redes 391
Una visión general de las redes 391
Descripción general del modelo OSI 392
Protocolos y comunicaciones 392
Encapsulación y desencapsulación de datos 393
Los roles de cada capa 394
Capa física 394
Capa de enlace de datos 395
Capa de red 396
Capa de transporte 396
Capas de aplicación/host 397

Algunos aspectos de las direcciones IP y los puertos 398


La dirección IP 398
La subred 398
El puerto de comunicación 399

Conexión de Arduino a Ethernet por cable 399


Cómo hacer que Processing y Arduino se comuniquen a través de Ethernet 401
Cableado básico 401
Implementación de la codificación de conectividad de
red en Arduino 402
Codificación de una aplicación de procesamiento que se comunica a
través de Ethernet 406
Algunas palabras sobre TCP 407
Comunicaciones Bluetooth 408
Cableado del módulo Bluetooth 409
Codificación del firmware y del applet de Processing 410
Jugando con Wi­Fi ¿Qué 412
es Wi­Fi? 412
Modo infraestructura 413
De este modo 413
Otros modos 414
El shield wifi de Arduino 414
Conexión Wi­Fi básica sin cifrado 415
Conexión wifi de Arduino mediante WEP o WPA2 418
Uso de WEP con la biblioteca Wi­Fi 418
Uso de WPA2 con la biblioteca Wi­Fi 418

Arduino tiene un servidor web (ligero) 419


Tuitear pulsando un interruptor 422
Una descripción general de las API 422
API de Twitter 422
Uso de la biblioteca de Twitter con soporte OAuth 423
Obteniendo credenciales de Twitter 423

[x]

www.it­ebooks.info
Machine Translated by Google

Tabla de contenido

Codificación de un firmware que se conecta a Twitter 423

Resumen 428

Capítulo 12: Jugando con el Framework Max 6 429


Comunicarse fácilmente con Max 6 – el objeto [serial] 429
El objeto [serial] 430
Seleccionar el puerto serie correcto 431
El sistema de votación 432
Analizar y seleccionar datos provenientes de
Arduino 432
El firmware readAll 433
El parche ReadAll Max 6 434
Solicitando datos de Arduino 435
Analizando los datos recibidos 435
Distribuir los datos recibidos y otros trucos 437

Creación de un medidor de nivel de sonido con LED 444


El circuito 444
El parche Max 6 para calcular los niveles de sonido 446
El firmware para leer bytes 448
El efecto de cambio de tono controlado manualmente 449
El circuito con el sensor y el firmware El parche para 449
alterar el sonido y analizar los mensajes de Arduino Resumen Capítulo 13: 450
Mejorar su 452

programación en C y crear bibliotecas Bibliotecas de programación El


archivo de encabezado El 453
archivo fuente Crear su propia 453
biblioteca de matriz 455
de LED Cablear 457
seis LED a la placa Crear algunos patrones de 458
luz agradables Diseñar una pequeña 458
biblioteca de patrones de LED Escribir el 459
encabezado LEDpatterns.h Escribir la fuente 461
LEDpatterns.cpp Escribir el archivo 461
keyword.txt Usar la biblioteca 462
LEDpatterns Gestión de 463

memoria Dominar el desplazamiento 464


de bits Multiplicar/dividir por 466
múltiplos de 2 Empaquetar 467
múltiples elementos de datos en bytes 467
Activar/desactivar bits individuales en un 467
registro de control y puerto 468
Reprogramación de la placa Arduino 469

[ xi ]

www.it­ebooks.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.it­ebooks.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.it­ebooks.info
Machine Translated by Google

Prefacio

De qué trata este libro


El capítulo 1, Let's Plug Things, es tu primer contacto con Arduino y la programación de
microcontroladores. Aprenderemos a instalar el entorno de desarrollo integrado de Arduino en nuestra
computadora y a conectar y probar la cadena de herramientas de desarrollo para preparar el estudio
posterior.

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 3, Conceptos básicos de C: cómo fortalecerse, aborda directamente el lenguaje C. Al


aprender los conceptos básicos, aprendemos a leer y escribir programas en C, descubriendo los
tipos de datos, las estructuras básicas y los bloques de programación.

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 7, Hablar por medio de la comunicación serial, presenta el concepto de comunicación,


especialmente enseñando sobre la comunicación serial. Aprenderemos a usar la consola de
comunicación serial como una poderosa herramienta de depuración.

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.it­ebooks.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.

El apéndice se puede descargar desde http://www.packtpub.com/sites/default/


archivos/descargas/7584OS_Appendix.pdf.

Lo que necesitas para este libro


Si desea aprovechar los beneficios de cada ejemplo de este libro, necesitará el siguiente software:

• El entorno Arduino (gratuito, http://arduino.cc/en/main/software).


Esto es necesario para todas las operaciones relacionadas con la programación de Arduino.

• Fritzing (gratis, http://fritzing.org/download). Es un programa de código abierto.


entorno que nos ayuda a diseñar circuitos.

• Procesamiento (gratis, http://processing.org/download). Es un programa abierto.


Marco de código fuente para la creación rápida de prototipos con Java. Algunos ejemplos lo utilizan
como socio de comunicación para nuestras placas Arduino.

[3]

www.it­ebooks.info
Machine Translated by Google

Prefacio

• El marco Max 6 (versión de prueba de 30 días, http://cycling74.com/


Este marco es un entorno enorme que también se utiliza en este libro.

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.

Para quién es este libro


Este libro está dirigido a aquellas personas que desean dominar la creación de hardware electrónico
con placas Arduino. Enseña todo lo que necesitamos saber para programar firmware usando C y cómo
conectar Arduino al mundo físico, en gran profundidad. Desde estudiantes de escuelas de arte de
diseño interactivo hasta aficionados puros, desde diseñadores de instalaciones interactivas hasta personas
que desean aprender electrónica ingresando a una comunidad enorme y en crecimiento de programadores
de computación física, este libro ayudará a todos aquellos interesados en aprender nuevas formas de diseñar
objetos inteligentes, objetos parlantes, dispositivos eficientes y engranajes reactivos autónomos o conectados.

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 ".

Un bloque de código se establece de la siguiente manera:

[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.it­ebooks.info
Machine Translated by Google

Prefacio

exten => s,102,Buzón de voz(b100)


exten => i,1,Buzón de voz(s0)

Cualquier entrada o salida de línea de comando se escribe de la siguiente manera:

# cp /usr/src/asterisk­addons/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".

Las advertencias o notas importantes aparecen en un cuadro como éste.

Los consejos y trucos aparecen así:

Comentarios de los lectores


Los comentarios de nuestros lectores siempre son bienvenidos. Cuéntenos qué piensa de este libro, qué le gustó y qué
no. Los comentarios de los lectores son importantes para que podamos desarrollar títulos que realmente le resulten útiles.

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.

Descargando el código de ejemplo


Puede descargar los archivos de código de ejemplo de todos los libros de Packt que haya adquirido desde su cuenta
en http://www.packtpub.com. Si compró este libro en otro lugar, puede visitar http://www.packtpub.com/support y
registrarse para recibir los archivos directamente por correo electrónico.

[5]

www.it­ebooks.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/submit­errata, 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.

Comuníquese con nosotros a [email protected] con un enlace al material presuntamente


pirateado.

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.it­ebooks.info
Machine Translated by Google

Vamos a enchufar las cosas

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.it­ebooks.info
Machine Translated by Google

Vamos a enchufar las cosas

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!

Presentando la gran familia Arduino


Arduino es un microcontrolador de código abierto (http://en.wikipedia.org/wiki/Open_source) basado en
una única placa. Es una plataforma muy popular derivada de la plataforma Wiring (http://www.wiring.org.co/)
y diseñada inicialmente para popularizar el uso de la electrónica en proyectos de diseño de interacción de
estudiantes universitarios.

[8]

www.it­ebooks.info
Machine Translated by Google

Capítulo 1

Mi Arduino MEGA en mi mano

Se basa en el procesador Atmel AVR (http://www.atmel.com/products/


microcontrollers/avr/default.aspx) y proporciona muchas entradas y salidas en un solo
dispositivo de hardware autosuficiente. El sitio web oficial del proyecto es http://www.arduino.cc.

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

• Número de entradas y salidas


• Factor de forma

[9]

www.it­ebooks.info
Machine Translated by Google

Vamos a enchufar las cosas

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.

Quiero especialmente que revises los siguientes modelos:

• Arduino Uno es el básico con un chipset reemplazable


• Arduino Mega, 2560 proporciona un montón de entradas y salidas
• Arduino LilyPad, se puede llevar puesto como ropa
• Arduino Nano, es muy pequeño

[ 10 ]

www.it­ebooks.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!

Acerca de la creación de prototipos de hardware


Hoy en día podemos programar y crear software con bastante facilidad utilizando una gran cantidad de
marcos de código abierto para los que se pueden encontrar muchas comunidades útiles en la Web. Estoy
pensando en Processing (basado en Java, consulte http://processing.org) y openFrameworks (basado
en C++, consulte http://www.openframeworks.cc), pero hay muchos otros que a veces utilizan
paradigmas muy diferentes, como lenguajes de programación gráfica como Pure Data (http://puredata.info),
Max 6
(http://cycling74.com/products/max/), o vvvv (http://vvvv.org)
para ventanas.

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.it­ebooks.info
Machine Translated by Google

Vamos a enchufar las cosas

Una de las cosas más importantes que hay que entender aquí es el ciclo de creación de prototipos.

Escribiendo precisamente lo que


quiero hacer en un papel

Dibujo y cableado
El circuito

Codificación y carga
El firmware

Prueba y corrección de iteraciones

Jugando y disfrutando

Una sencilla lista de pasos para crear un prototipo de hardware

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.it­ebooks.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!

Comprender la arquitectura del software


Arduino
Para entender cómo hacer que nuestra bonita placa Arduino funcione exactamente como queremos,
tenemos que comprender la arquitectura de software global y la cadena de herramientas que utilizaremos
muy pronto.

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.it­ebooks.info
Machine Translated by Google

Vamos a enchufar las cosas

Veamos un pequeño diagrama para una mejor comprensión:

En nuestro IDE

en nuestra computadora

Código C escrito por nosotros

Firmware binario compilado por nosotros

subido por nosotros


a través de USB

En el Ardulno

corriendo y corriendo y
Firmware binario
ejecutando tareas ejecutando tareas

prefabricado cargar el firmware


Cargador de arranque
prequemado al inicio

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.it­ebooks.info
Machine Translated by Google

Capítulo 1

Ahora descarguemos algunos programas necesarios:

• Controladores USB FTDI : http://www.ftdichip.com/Drivers/VCP.htm

• IDE de Arduino: http://arduino.cc/en/Main/Software

• Procesamiento: http://processing.org/download/

En este libro se utiliza Processing, pero no es necesario para programar y utilizar placas
Arduino.

¿Qué es la cadena de herramientas de Arduino?

Por lo general, llamamos a la cadena de herramientas de Arduino un conjunto de herramientas


de software necesarias para gestionar todos los pasos desde el código C que estamos
escribiendo en el IDE de Arduino en nuestra computadora hasta el firmware cargado en la placa.
De hecho, el código C que escribe debe prepararse antes del paso de compilación con los
compiladores avr­gcc y avr­g++. Una vez que los archivos del objeto resultante están
vinculados por otros programas de la cadena de herramientas, generalmente en un solo archivo, ya está todo listo.
Esto se puede cargar más tarde en la placa. Hay otras formas de utilizar las placas Arduino
y las presentaremos en el último capítulo de este libro.

Instalación del entorno de


desarrollo Arduino (IDE)
Busquemos el archivo comprimido descargado desde http://arduino.cc/en/Main/
Software de la parte anterior y vamos a descomprimirlo en nuestro ordenador.

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.

Instalación del IDE


No existe una instalación típica del IDE porque se ejecuta en la máquina virtual de Java. Esto
significa que solo tienes que descargarlo, descomprimirlo en algún lugar de tu sistema y luego iniciarlo y
JAVA ejecutará el programa. Es posible usar solo la CLI (interfaz de línea de comandos, la famosa ventana
g33ks en la que puedes escribir el comando directamente al sistema) para construir tus binarios en lugar
de la interfaz gráfica, pero en este momento, no lo recomiendo.

[ 15 ]

www.it­ebooks.info
Machine Translated by Google

Vamos a enchufar las cosas

Por lo general, Windows y OS X vienen con Java instalado. Si no es así, instálelo


desde la página web java.com en http://www.java.com/en/download/.

En Linux, el proceso realmente depende de la distribución que estés usando, por lo


que te sugiero que consultes la página http://www.arduino.cc/playground/Learning/
Linux y si quieres verificar e instalar todo el entorno y las dependencias desde las
fuentes, también puedes consultar la página http://www.arduino.cc/playground/Linux/All.

¿Cómo lanzar el entorno?


En Windows, hagamos clic en el archivo .exe incluido en la carpeta sin comprimir. En
OS X, hagamos clic en el paquete global autónomo con el bonito logotipo de Arduino.
En Linux, tendrás que iniciar el script de Arduino desde la GUI o escribiendo en la CLI.

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.

El famoso ejemplo de código Blink abierto en el IDE de Arduino

[ 16 ]

www.it­ebooks.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:

• Verificar (símbolo de verificación): Esto permite verificar el código en busca de errores.

• Cargar (flecha del lado derecho): Esto compila y carga nuestro código en el
Placa Arduino

• Nuevo (pequeña página en blanco): Esto crea un nuevo boceto en blanco.

• 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.

• Monitor serial (pequeña lupa): proporciona el monitoreo serial

Cada elemento del menú de la barra superior ofrece más opciones que descubriremos progresivamente a lo largo
de este libro.

Sin embargo, el menú Herramientas merece más atención:

• Formato automático: Esto proporciona formato de código correcto y


sangrías estándar

• Archivar boceto: Esto comprime todo el boceto actual con todos los archivos

• Tablero: proporciona una lista de todos los tableros compatibles

• Puerto serie: proporciona una lista de todos los dispositivos serie del sistema.

• Programador: Proporciona una lista de todos los dispositivos programadores compatibles y


utilizados en caso de reprogramación total del chipset AVR.

[ 17 ]

www.it­ebooks.info
Machine Translated by Google

Vamos a enchufar las cosas

• 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.it­ebooks.info
Machine Translated by Google

Capítulo 1

¡Ya casi terminamos!

Instalemos los controladores de la interfaz USB de Arduino en nuestro sistema.

Instalación de controladores de Arduino


Las placas Arduino disponen de una interfaz USB. Antes de conectar el cable USB y conectar la placa a
nuestro ordenador, tenemos que instalar unos controladores específicos en este último.

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.

Describamos cómo funciona en sistemas basados en Windows, es decir, Windows 7, Vista,


y XP.

Instalación de controladores para Arduino Uno R3


Es importante seguir los pasos que se mencionan a continuación para poder utilizar el Arduino Uno
R3 y otras placas. Consulta el sitio web de Arduino para obtener referencias actualizadas.

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.

2. Haga clic en el menú Inicio y abra el Panel de control.

3. En el Panel de control, dirígete a Sistema y seguridad. A continuación, haz clic en Sistema.


Una vez que aparezca la ventana Sistema , abra el Administrador de dispositivos.

4. Busque en Puertos (COM y LPT) el puerto abierto llamado Arduino UNO


(COMxx).

5. Haga clic derecho en el puerto Arduino UNO (COMxx) y elija Actualizar


Opción de software del controlador .

6. A continuación, elija la opción Buscar software de controlador en mi computadora .

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.it­ebooks.info
Machine Translated by Google

Vamos a enchufar las cosas

Instalación de controladores para Arduino


Duemilanove, Nano o Diecimilla
Cuando conecte la placa, Windows debería iniciar el proceso de instalación del controlador (si no ha utilizado la
computadora con una placa Arduino antes).

En Windows Vista, el controlador debería descargarse e instalarse automáticamente.


(¡Realmente funciona!)

En Windows XP, se abrirá el asistente para Agregar nuevo hardware :

1. Cuando se le pregunte si Windows puede conectarse a Windows Update para buscar


¿software? Seleccione No, esta vez no. Haga clic en Siguiente.

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.

4. El asistente buscará el controlador y luego le dirá que es un puerto serie USB.


Se encontró el convertidor . Haga clic en Finalizar.

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.it­ebooks.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.

Cuando se enciende el generador de circuitos cerrados, se produce y se mantiene esta


diferencia de potencial. El voltaje es una diferencia y debe medirse entre dos puntos de un
circuito. Para medir el voltaje utilizamos voltímetros.

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).

A continuación se muestra una relación matemática entre voltaje, corriente y potencia:

P=VxI

donde, P es la potencia en vatios, V el voltaje en V e I la corriente en amperios.

¿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.it­ebooks.info
Machine Translated by Google

Vamos a enchufar las cosas

¿Y qué son las resistencias, condensadores,


etc.?
Siguiendo la misma analogía, las resistencias son pequeños componentes que ralentizan el flujo de corriente.
Son más resistivas que cualquier trozo de cable que puedas utilizar; generalmente la disipan en forma de calor.
Son dos componentes terminales pasivos y no están polarizados, lo que significa que puedes conectarlos en
ambas direcciones.

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

donde R es la resistencia eléctrica en ohmios, V el voltaje en voltios e I la corriente en amperios.

Para un valor constante de voltaje, si la resistencia es alta, la corriente es baja y viceversa. Es


importante tener esto en cuenta.

En cada resistencia, hay un código de color que muestra el valor de la resistencia.

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.it­ebooks.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.

Cableado de cosas y fricciones


Con la analogía anterior podemos entender bien que un circuito necesita estar cerrado para dejar pasar la corriente.

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.it­ebooks.info
Machine Translated by Google

Vamos a enchufar las cosas

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.

Como vimos en la captura de pantalla anterior, hay buses y franjas terminales.

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.it­ebooks.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?

Puede encontrar las últimas versiones de Fritzing en http://fritzing.org/download/.

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:

La vista de la placa de pruebas que muestra nuestro primer circuito.

[ 25 ]

www.it­ebooks.info
Machine Translated by Google

Vamos a enchufar las cosas

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.

La magia reside en el hecho de que el esquema se construye automáticamente mientras estás


dibujando en la vista de la placa de pruebas. ¡Y funciona en ambos sentidos! Puedes crear un
esquema y conectar los componentes mediante Fritzing en la vista de la placa de pruebas. Por
supuesto, probablemente tendrías que colocar la pieza de una manera más conveniente o estética, pero
funciona perfectamente bien. En particular, el Autorouter te ayuda a hacer que todos los cables sean
más lineales y simples.

En la siguiente captura de pantalla, puedes ver el mismo circuito que antes, pero mostrado en la
vista esquemática:

La vista esquemática que representa el diagrama del circuito.

[ 26 ]

www.it­ebooks.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.

Fundamentos de la fuente de alimentación


Aprendimos un poco más sobre electricidad antes, pero ¿cómo puedo alimentar todos mis circuitos en la
vida real?

Las placas Arduino se pueden suministrar de tres maneras diferentes:

• Mediante nuestro ordenador a través del cable USB (se suministra 5 V)

• Mediante una batería o una fuente de alimentación externa directa (PSU) /adaptador

• Conectando una tensión regulada de 5 V al pin +5 V

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.

¿Qué adaptador puedo usar con mi Arduino?


Arduino Uno y Mega pueden ser alimentados directamente por el adaptador
DC pero éste debe respetar algunas características:
• El voltaje de salida debe estar entre 9 V y 12 V
• Debe poder conducir al menos 250 mA de corriente.

Debe tener un enchufe de alimentación de 2,1 mm con centro positivo.

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.it­ebooks.info
Machine Translated by Google

Vamos a enchufar las cosas

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.it­ebooks.info
Machine Translated by Google

Capítulo 1

¿Qué queremos hacer exactamente?


Si recuerdas bien, esta es la primera pregunta que tenemos que hacer. Por supuesto, nos saltamos un
poco este paso, especialmente en lo que respecta a la parte del hardware, porque tuve que explicarte
algunas cosas mientras estabas cableando, pero sigamos con el proceso de creación de prototipos, que
se explica en parte, comprobando el código y cargándolo.

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?

Resumamos lo que tenemos que hacer:

1. Coloque los 5 V en la salida digital 8 durante 250ms.

2. Detener el accionamiento de la salida digital 8 durante 1 s.

3. Reinicie esto cada vez que se encienda el Arduino.

¿Cómo puedo hacer eso usando código C?


Si seguiste la página anterior correctamente, ya tienes tu placa Arduino conectada a la computadora a
través de tu cable USB en un lado, y conectada a la placa de pruebas en el otro lado.

Ahora, inicie su IDE de Arduino.

[ 29 ]

www.it­ebooks.info
Machine Translated by Google

Vamos a enchufar las cosas

Empezar con una nueva página en blanco


Si ya has probado tu IDE cargando algunos ejemplos, o si ya has escrito algún fragmento de código,
tienes que hacer clic en el icono Nuevo para cargar una página en blanco, lista para alojar nuestro código
Blink250ms :

Una bonita y atractiva página en blanco.

Configurando el entorno según el tablero que estemos utilizando

El IDE debe saber con qué placa se va a comunicar. Lo haremos siguiendo los siguientes pasos:

1. Vaya al menú Herramientas y elija la placa correcta. La primera es Arduino Uno:

[ 30 ]

www.it­ebooks.info
Machine Translated by Google

Capítulo 1

Elige el tablero que estás usando

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:

° En OS X, el correcto comienza con /dev/tty.usbmodem tanto para Uno como para


Mega 2560 y con /dev/tty.usbserial para placas más antiguas.

° En Windows, el puerto correcto suele ser COM3 (COM1 y COM2


A menudo, el sistema operativo los reserva). Por cierto, también puede ser COM4,
COM5 o cualquier otro. Para estar seguro, consulte el administrador de
dispositivos.

[ 31 ]

www.it­ebooks.info
Machine Translated by Google

Vamos a enchufar las cosas

° En Linux, el puerto suele ser /dev/ttyUSB0:

Elige el puerto serial correspondiente a tu placa

Ahora, nuestro IDE puede comunicarse con nuestra placa. Ahora, insertemos el código.

Vamos a escribir el código


A continuación se muestra el código completo. Puede encontrarlo en el archivo zip de la carpeta Chapter01/Blink250ms/ :

Descarga del código de ejemplo


Puede descargar los archivos de código de ejemplo de todos los libros de
Packt que haya comprado desde su cuenta en http://www.packtpub.com. Si
compró este libro en otro lugar, puede visitar http://www.packtpub.com/
support y registrarse para recibir los archivos directamente por correo electrónico.

/*
Programa Blink250ms
Enciende un LED conectado al pin digital 8 durante 250 ms y luego lo apaga durante
1s, infinitamente.

[ 32 ]

www.it­ebooks.info
Machine Translated by Google

Capítulo 1

Escrito por Julien Bayle, este código de ejemplo es Creative Commons CC­
Por­SA
*/

// El pin 8 es el que está conectado a nuestro LED


en 8 // ledPin es una variable entera int ledPin = 8; inicializada

// ­­­­­­­­­ 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
}

// ­­­­­­­­­ la rutina de bucle se ejecuta para siempre


bucle vacío() {
digitalWrite(ledPin, HIGH); // enciende el LED (HIGH es una constante
es decir, un voltaje de 5 V)
delay(250); //esperar 250ms en el estado actual
digitalWrite(ledPin, LOW); es decir, un // apaga el LED (BAJO es una constante
voltaje de 5 V)
retraso(1000); //esperar 1 s en el estado actual
}

Vamos a comentarlo un poco. De hecho, aprenderemos a codificar nuestro propio código C en el


próximo capítulo, luego solo describiré este y les daré algunos pequeños consejos.

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;

Luego podemos ver dos estructuras particulares entre llaves:

void configuración()
{ pinMode(ledPin, SALIDA);
}
bucle vacío() {
digitalWrite(ledPin, ALTO); retraso(250);
digitalWrite(ledPin,
BAJO); retraso(1000);

[ 33 ]

www.it­ebooks.info
Machine Translated by Google

Vamos a enchufar las cosas

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.

¡Por fin subamos el código!


Si siguió y manipuló correctamente el hardware y el IDE como se explicó anteriormente, ahora
estamos listos para cargar el código en la placa.

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.

Si desea modificar un poco el código, puede reemplazar la siguiente línea:

retraso(1000);

Con la siguiente línea, por ejemplo:

retraso(100);

Ahora cargue este nuevo código nuevamente y vea qué sucede.

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.it­ebooks.info
Machine Translated by Google

Primer contacto con C


En mi vida como programador, me he encontrado con muchos lenguajes basados en
compiladores y scripts. Uno de los mínimos comunes siempre ha sido el lenguaje C.

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.

Vamos a comprobar qué es realmente la programación en C y adentrarnos en un nuevo mundo, es


decir, el ámbito de la programación con Arduino. También utilizaremos una función muy necesaria
llamada monitorización serial. Esto nos ayudará mucho en nuestro aprendizaje de C, y comprenderás
que esta función también se utiliza en proyectos de la vida real.

Una introducción a la programación


La primera pregunta es ¿ qué es un programa?

Un programa es un texto que se escribe utilizando un lenguaje de programación que contiene


comportamientos que se necesitan que adquiera un procesador. Básicamente, crea una forma de manejar
entradas y producir salidas de acuerdo con estos comportamientos.

Según Wikipedia (http://en.wikipedia.org/wiki/Computer_


programación):

La programación es el proceso de diseñar, escribir, probar, depurar y mantener el


código fuente de los programas de computadora.

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.it­ebooks.info
Machine Translated by Google

Primer contacto con C

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.

Un ejemplo de la definición de mi pseudocódigo de firmware podría ser el siguiente:

1. Mida el valor actual del sensor térmico.

2. Verifique si la temperatura es mayor a 30° C y emita un sonido si es así.


3. En caso contrario, encienda el LED azul.

4. Y hacer que esos pasos anteriores sean permanentes en un bucle.

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 prueba es el paso obvio cuando se ejecuta el programa después de haber realizado


algunas modificaciones al código. Es un momento emocionante en el que también se tiene un poco de
miedo a los errores, esas cosas molestas que hacen que la ejecución del programa sea totalmente
diferente de lo que se esperaba al principio.

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.

El programa funciona y lo vas mejorando progresivamente, lo vas actualizando teniendo en cuenta


las evoluciones del hardware y, a veces, lo vas depurando porque el usuario tiene ese fallo aún no
descubierto. Este paso aumenta la duración de vida de tu programa.

[ 36 ]

www.it­ebooks.info
Machine Translated by Google

Capítulo 2

Diferentes paradigmas de programación


Un paradigma es una manera de describir algo. Puede ser una representación o un modelo teórico de
algo.

Aplicado a la programación, un paradigma de programación es un estilo fundamental de programación


informática.

Los siguientes son cuatro paradigmas de programación principales:

• Orientado a objetos
• Imperativo
• Funcional

• Programación lógica

Algunos idiomas siguen no uno sino varios paradigmas.

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.it­ebooks.info
Machine Translated by Google

Primer contacto con C

¿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++, Objective­C, 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!

C se usa en todas partes


De hecho, el lenguaje C ofrece muchas ventajas, entre ellas:

Es pequeño y fácil de aprender.

Es independiente del procesador porque existen compiladores para casi todos los
procesadores del mundo. Esta independencia proporciona algo muy útil a los
programadores: pueden centrarse en los algoritmos y los niveles de aplicación de su trabajo
en lugar de pensar en el nivel de hardware en cada fila de código.

Es un lenguaje de alto nivel y muy "de bajo nivel".

Esta es su principal fortaleza. Dennis M. Ritchie, en su libro El lenguaje de programación C


escrito con Brian W. Kernighan, comentó sobre C como:

C es un lenguaje de "nivel relativamente bajo". Esta caracterización no es peyorativa;


simplemente significa que C maneja el mismo tipo de objetos que la mayoría de las computadoras.
Estos pueden combinarse y moverse con los operadores aritméticos y lógicos implementados
por máquinas reales.

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.it­ebooks.info
Machine Translated by Google

Capítulo 2

Arduino está programado con C y C++


C++ puede considerarse como un superconjunto de C. Esto significa que C++ aporta nuevos conceptos
y elementos a C. Básicamente, C++ puede definirse como C con implementación orientada a
objetos (http://en.wikipedia.org/wiki/Object­oriented_
programación), que es una característica de nivel superior. Esta es una característica muy buena que aporta y
proporciona nuevas formas de diseño.

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)

• Encapsulación de datos (cada instancia conserva sus datos y funciones)

• Identidad del objeto (cada instancia es un individuo)


• Polimorfismo (cada comportamiento puede depender del contexto)

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.

La biblioteca nativa de Arduino y otras bibliotecas

Una biblioteca de programación es una colección de recursos que están disponibles para que los
utilicen los programas.

Pueden incluir diferentes tipos de cosas, como las siguientes:

• Datos de configuración
• Recursos de ayuda y documentación
• Subrutinas y parte reutilizable del código
• Clases

• Definiciones de tipos

[ 39 ]

www.it­ebooks.info
Machine Translated by Google

Primer contacto con C

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.

Las bibliotecas pueden ser muy específicas o tener un propósito global.

Por ejemplo, si desea diseñar un firmware que conecte el Arduino a la


Para poder obtener información de un servidor de correo en Internet y reaccionar haciendo parpadear
una matriz de LED de una forma u otra según el contenido de la respuesta del servidor de correo,
tienes las dos soluciones siguientes:

• Codificar todo el firmware desde cero

• 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.

Descubriendo la biblioteca nativa de Arduino


La biblioteca nativa está diseñada para un propósito muy básico y global. Esto significa que puede que
no sea suficiente, pero también significa que la usará siempre en todo el diseño de su
firmware.

Puedes encontrarla en http://arduino.cc/en/Reference/HomePage. ¡Esta página ya te resultará familiar!

Se divide en las siguientes tres partes:

• Estructura (desde estructuras de control condicional globales hasta otras más específicas)

• Variables (relacionadas con tipos y conversiones entre tipos)

• Funciones (desde funciones de E/S hasta funciones de cálculo matemático y más)

[ 40 ]

www.it­ebooks.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.

3. Seleccione el botón 02.Digital .

[ 41 ]

www.it­ebooks.info
Machine Translated by Google

Primer contacto con C

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.it­ebooks.info
Machine Translated by Google

Capítulo 2

Los útiles archivos de ayuda local que están disponibles

Otras bibliotecas incluidas y no proporcionadas


directamente
La biblioteca Arduino ha ido incluyendo progresivamente otras bibliotecas necesarias
y útiles. Hemos visto en el capítulo anterior que las bibliotecas utilizadas ahora están
integradas en el núcleo de la distribución Arduino, lo cual es un poco abusivo, pero resume
bien el hecho de que estén disponibles cuando se instala únicamente el paquete Arduino IDE.

Algunas bibliotecas incluidas muy útiles • EEPROM


proporciona funciones y clases para leer/escribir en componentes de almacenamiento
de hardware. Es muy útil para almacenar algo más allá del estado de energía
del Arduino, es decir, incluso cuando está apagado.
• Ethernet ayuda a realizar comunicaciones de capa 2 y capa 3 a través de Ethernet.
red.
• Firmata se utiliza para la comunicación en serie.

• SD proporciona una forma sencilla de leer/escribir tarjetas SD; es una alternativa más fácil de usar
que la solución EEPROM.

• Servo ayuda a controlar los servomotores.


[ 43 ]

www.it­ebooks.info
Machine Translated by Google

Primer contacto con C

Hay un par de bibliotecas más en la distribución principal. A veces, se incluyen otras nuevas.

Algunas bibliotecas externas


Te sugiero que consultes otras bibliotecas citadas y referenciadas en la misma página en el enlace http://
arduino.cc/en/Reference/Libraries.

Utilicé especialmente muchas de las siguientes bibliotecas:

• 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)

• Tono: Se utiliza para generar ondas cuadradas audibles.

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.

Comprobación de todos los pasos básicos de desarrollo


No estamos aquí para entender todos los detalles de la compilación de código, pero quiero darte una
explicación global que te ayudará a entender mejor cómo funciona en profundidad. También te ayudará a
entender cómo depurar tu código fuente y por qué algo no funcionaría en cualquier caso aleatorio.

Comencemos con un diagrama de flujo que muestra todo el proceso.

[ 44 ]

www.it­ebooks.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

Del código fuente al código binario ejecutable

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.

2. Los encabezados generalmente se incluyen al comienzo de su código y son:


hacen referencia a otros archivos con la extensión .h en los que hay algunas definiciones y declaraciones

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.it­ebooks.info
Machine Translated by Google

Primer contacto con C

3. El preprocesador es una rutina que básicamente sustituye elementos de texto en su código,


considerando los encabezados y las definiciones de otras constantes .

4. El analizador prepara un archivo que se traducirá y ese archivo se ensamblará para


producir múltiples archivos de objeto .

5. Un archivo de objeto contiene código de máquina que no es ejecutable directamente por ningún
procesador de hardware.

6. El último paso importante es la vinculación que realiza el programa enlazador . El enlazador


toma todos los objetos producidos por los pasos de compilación anteriores y los combina
en un único archivo ejecutable llamado programa.

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.

Uso del monitor serial


La propia placa Arduino puede comunicarse fácilmente utilizando protocolos básicos de comunicación
serial.

[ 46 ]

www.it­ebooks.info
Machine Translated by Google

Capítulo 2

Básicamente, la comunicación serial es el proceso de enviar elementos de datos a través de


un canal, a menudo llamado bus. Por lo general, los elementos de datos son bytes, pero todo
depende de la implementación de la comunicación serial.

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!

Comunicación serial con Arduino


Cada placa Arduino tiene al menos un puerto serial. Se puede utilizar mediante los pines
digitales 0 y 1, o directamente mediante la conexión USB cuando se desea utilizar comunicación
serial con el ordenador.

Puedes consultar http://arduino.cc/en/Reference/serial.

En la placa Arduino, puedes leer RX y TX en ambos pines digitales 0 y 1 respectivamente.


TX significa transmisión y RX significa recepción; de hecho, la comunicación serial más básica requiere
dos cables.

[ 47 ]

www.it­ebooks.info
Machine Translated by Google

Primer contacto con C

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 .

Si utiliza comunicación serial en su placa


Arduino, no podrá utilizar los pines digitales 0 y 1.

Verifique TX y RX en los pines digitales 1 y 0

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.

Los rastros se describirán en detalle en el próximo capítulo.

[ 48 ]

www.it­ebooks.info
Machine Translated by Google

Capítulo 2

Haciendo que Arduino nos hable


Imagina que has seguido atentamente el proyecto Blink250ms , todo está conectado correctamente, lo has
comprobado dos veces y el código también parece correcto, pero no funciona.

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.

Añadiendo comunicación serial a Blink250ms


Aquí, en el siguiente código, agregaremos comunicación en serie para que el LED parpadee cada 250 ms:

1. Abra su código anterior.

2. Utilice Guardar como para crear otro proyecto con el nombre


TalkingAndBlink250ms.

Es una buena práctica partir de un código ya


existente, guardarlo con otro nombre y modificarlo
según sus necesidades.

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 Attribution­Share Alike.
Licencia CC­BY­SA de Commons

*/

// El pin 8 es el que está conectado a nuestro bonito LED


int ledPin = 8; // ledPin es una variable entera inicializada en 8

// ­­­­­­­­­ rutina de configuración

[ 49 ]

www.it­ebooks.info
Machine Translated by Google

Primer contacto con C

configuración vacía() {
pinMode(ledPin, OUTPUT); // inicializa el pin digital como salida

Serial.begin(9600);baud // Configuración de comunicación en serie en 9600

}// ­­­­­­­­­ rutina de bucle


bucle vacío() {
digitalWrite(ledPin, HIGH); // enciende el LED

Serial.print("el pin "); Serial.print(ledPin); //imprime "el pin"


// imprimir el valor de ledPin (actualmente
8)
Serial.println("está activado"); // imprimir "está activado"

retraso(250); // esperar 250ms en la corriente


estado

digitalWrite(ledPin, BAJO); // apaga el LED

Serial.print("el pin "); Serial.print(ledPin); //imprime "el pin"


Serial.println("está apagado"); // imprime el valor de ledPin (aún 8)
// print "está desactivado

retraso(1000); // esperar 1s en el actual


estado

[ 50 ]

www.it­ebooks.info
Machine Translated by Google

Capítulo 2

Tenga en cuenta que resalto un poco el código del comentario cada


vez para que sea más legible. En los siguientes pasos, por ejemplo,
no escribiré el siguiente comentario:
// ­­­­­­­­­­ rutina de bucle
También puedes encontrar el código completo en el archivo zip
en la carpeta Chapter02/TalkingAndBlink250ms/.

4. Haga clic en el botón Serial Monitor en el IDE de Arduino:

Haga clic en el pequeño símbolo de cristal en la esquina superior derecha para activar el Monitor Serial

[ 51 ]

www.it­ebooks.info
Machine Translated by Google

Primer contacto con C

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.

¡Parece que tu placa Arduino te está hablando!

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.it­ebooks.info
Machine Translated by Google

Capítulo 2

Funciones seriales con más detalle


Veamos lo que hemos añadido en el código.

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.

La sintaxis de esta función es Serial.print(val) o Serial.print(val,format).

Puedes pasar uno o dos argumentos.

Básicamente, si Serial.print(5) imprime el número 5 como un símbolo decimal codificado en ASCII,


Serial.print(5,OCT) imprime el número 5 como un octal codificado en ASCII.

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).

Acabas de escribir tu primera rutina de rastreo.

[ 53 ]

www.it­ebooks.info
Machine Translated by Google

Primer contacto con C

Hablando con la pizarra desde la computadora


Probablemente hayas notado un campo de texto y un botón Enviar en la ventana del Monitor Serial:

Podemos enviar símbolos a nuestra placa Arduino usando comunicación serial

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.

En el próximo capítulo, ingresaremos código C utilizando la ventana de monitoreo en serie para


hacer las cosas un poco menos abstractas.

[ 54 ]

www.it­ebooks.info
Machine Translated by Google

Conceptos básicos de C: creación

Eres más fuerte

La programación en C no es tan difícil, pero requiere bastante trabajo al principio.


Afortunadamente, estoy contigo y tenemos un muy buen amigo desde hace tres capítulos: nuestra placa
Arduino. Ahora nos adentraremos en el lenguaje C y haré todo lo posible para ser
más concreto y no abstracto.

Este capítulo y el siguiente están verdaderamente orientados al lenguaje C, ya que el diseño de


programas Arduino requiere conocimientos de lógica de programación. Después de estos dos capítulos,
podrá leer cualquier código de este libro; estos sólidos conceptos básicos también le ayudarán en
proyectos posteriores, incluso aquellos que no estén relacionados con Arduino.

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.

Aproximación a variables y tipos de datos


Ya hemos utilizado variables en los ejemplos de los capítulos anteriores. Ahora, entendamos mejor este
concepto.

www.it­ebooks.info
Machine Translated by Google

Conceptos básicos de C: cómo hacerte más fuerte

¿Qué es una variable?


Una variable es una ubicación de almacenamiento de memoria limitada a un nombre simbólico. Esta
área de memoria reservada puede llenarse o dejarse vacía. Básicamente, se utiliza para almacenar
diferentes tipos de valores. En nuestros ejemplos anteriores, utilizamos la variable ledPin con la palabra clave int.

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.

Tipo Definición Tamaño en memoria


vacío Este tipo en particular se utiliza únicamente en declaraciones de
funciones y al definir punteros con tipos desconocidos. Lo veremos en
el próximo capítulo.
booleano Almacena falso o verdadero. 1 byte (8 bits)
carbonizarse
Almacena caracteres entre comillas simples, como 'a', como 1 byte
números, siguiendo la tabla ASCII (http://
en.wikipedia.org/wiki/ASCII_chart).

Es un tipo con signo y almacena números del ­128 al 127; puede no


tener signo y luego almacenar números del 0 al 255.

[ 56 ]

www.it­ebooks.info
Machine Translated by Google

Capítulo 3

Tipo Definición Tamaño en memoria


byte Almacena números como datos sin signo de 8 bits, es decir, desde 8 bits
0 a 255.

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.

Tenga cuidado, en el IDE de Arduino y la placa, la implementación


doble es exactamente la misma que float; es decir, con solo seis a siete
dígitos decimales de precisión.

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

elemento es nulo y es un carácter particular (código ASCII 0). elementos * 1

Tenga cuidado con la "s" en minúscula al principio de la cadena. byte

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()

Incluye métodos y funciones para concatenar cadenas, dividirlas y mucho


método
más fácilmente. Tenga cuidado con la "S" mayúscula al comienzo de
String.

[ 57 ]

www.it­ebooks.info
Machine Translated by Google

Conceptos básicos de C: cómo hacerte más fuerte

El concepto de roll over/wrap


Si se exceden los límites posibles de un tipo, la variable pasa al otro lado del límite.

El siguiente es un ejemplo:

int myInt = 32767; //el valor int máximo


myInt = myInt + 1; // myInt ahora es ­32768

Esto sucede en ambas direcciones, restando 1 de una variable int que almacena ­32768
El resultado es 32767. Tenlo en cuenta.

Declaración y definición de variables


Vamos a describir cómo declarar y luego definir variables y aprender cómo hacer ambas cosas al mismo
tiempo.

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.

Un identificador es lo que llamamos el nombre de la variable. También sabes cuál es el tipo.


Las dimensiones son útiles para matrices, por ejemplo, pero también para cadenas (que se
procesan como matrices internamente).

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.it­ebooks.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

bool myOtherVariable = false; // declaración y definición dentro de la misma declaración !

carbonizarse char myChar = 'U'; // declaración y definición utilizando el valor ASCII de 'U' (es decir, 85)

char myOtherChar = 85; // es igual a la declaración anterior

char myDefaultChar = 128; // esto da un ERROR porque los caracteres están firmados de ­128
a 127
unsigned char myUnsignedChar = 128; // ¡esto es correcto!

byte byte myByte = B10111; // 23 en notación binaria con la notación B

byte myOtherByte = 23; // es igual a la declaración anterior

entero int ledPin = 8; // clásico para nosotros, ahora :) unsigned myUint =


32768; // ¡muy bien con el prefijo unsigned!

palabra palabra miPalabra = 12345;

largo long myLong = ­123; // no olvides que podemos usar números negativos
¡Números también!

largo miOtroLargo = 345;


unsigned myUlong = 2147483648; // correcto debido al prefijo sin signo

flotar float myFloat = ­123456.1; // pueden ser negativos.


flotar miOtroFloat = 1.234567; //
float myNoDecimalPointedFloat = 1234; // pueden tener una parte decimal igual a cero

doble double myDouble = 1.234567; // La implementación de Arduino de double es la misma que la de float

[ 59 ]

www.it­ebooks.info
Machine Translated by Google

Conceptos básicos de C: cómo hacerte más fuerte

Tipo Ejemplo
Formación int myIntTable[5]; // declaración de una tabla que puede contener 5 números enteros

boolean myOtherTab[] = { false, true, true}; // declaración y definición de 3 matrices booleanas

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])

myOtherTab[1]; // estos elementos se pueden manipular como un booleano, ES un


booleano con el valor verdadero

cadena char mystring[3]; // una cadena de 3 caracteres


char mystring2[4] = {'b','y','t','e'}; // declaración y definición

char mystring3[4] = "byte"; // es igual a mystring2;


char mystring4[ ] = "byte"; // es igual a mystring3;

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.

Profundicemos un poco más en el tipo String .

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.

Consulte http://arduino.cc/en/Reference/StringObject en el sitio web de Arduino.

[ 60 ]

www.it­ebooks.info
Machine Translated by Google

Capítulo 3

La definición de cadena es una construcción


Hablamos sobre la definición de variables, pero los objetos tienen un concepto similar llamado construcción.

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.

String myString01 = "Hola mi amigo"; // cadena constante habitual para construirlo

String myString02 = String('U'); // convierte el carácter U en un objeto String

// concatenando 2 cadenas y colocando el resultado en otra


String myString03 = String(myString01 + ", estamos intentando jugar con
Instrumentos de cuerda));

// convertir el valor actual de un entero en un objeto String


int myNiceInt = 8; // define un entero
String myString04 = String(myNiceInt); // convertir a un objeto String

// convertir el valor actual de un entero con una base en un objeto String

int myNiceInt = 47; // define un entero


Cadena myString05 = Cadena(myNiceInt, DEC);
Cadena myString06 = Cadena(myNiceInt, HEX);
Cadena myString07 = Cadena(myNiceInt, BIN);

Uso de índices y búsqueda dentro de String


Las cadenas son matrices de elementos de tipo char . Esto significa que podemos acceder a cualquier
elemento de tipo String a través de sus índices.

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:

Cadena myString = "¡Hola mundo!!";

[ 61 ]

www.it­ebooks.info
Machine Translated by Google

Conceptos básicos de C: cómo hacerte más fuerte

La instrucción myString.charAt(3) devuelve el cuarto elemento de la cadena, que es: l.


Observe la notación específica utilizada aquí: tenemos el nombre de la variable String , un
punto, luego el nombre de la función (que es un método del objeto String ) y el parámetro 3
que se pasa a la función.

La función charAt() devuelve un carácter en una posición


particular dentro de una cadena.
Sintaxis: string.charAt(int);
int es un entero que representa un índice del valor de la cadena.
Tipo de retorno: char

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:

Cadena myString = "¡Hola mundo!!";

myString.indexOf('r') es igual a 8. De hecho, r está en el noveno lugar del valor de la cadena


myString.indexOf (val) y busca la primera aparición del valor val.

Si desea comenzar su búsqueda desde un punto en particular, puede especificar un


punto de inicio de la siguiente manera: indexOf(val,start), donde start es el índice
desde donde la función comienza a buscar el carácter val en la cadena. Como
probablemente haya entendido, el segundo argumento de esta función (start) se puede
omitir, la búsqueda comienza desde el primer elemento de la cadena por defecto, que es 0.

La función indexOf() devuelve la primera aparición de una cadena o


carácter dentro de una cadena.
Sintaxis: string.indexOf(val, from);
val es el valor a buscar, que puede ser una cadena o un carácter. from
es el índice desde el cual iniciar la búsqueda, que es de tipo int.
Este argumento puede omitirse. La búsqueda continúa.
Tipo de retorno: int

De manera similar, lastIndexOf(val,start) busca la última ocurrencia de val, buscando hacia


atrás desde start, o desde el último elemento si omite start.

[ 62 ]

www.it­ebooks.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.

Sintaxis: string.lastIndexOf(val, from);


val es el valor a buscar, que es una cadena o un carácter. from es
el índice desde el cual iniciar la búsqueda, que es de tipo int.
Este argumento se puede omitir. La búsqueda se realiza en sentido inverso.
Tipo de retorno: int

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.

Cadena myString = "¡Hola mundo!!";


Cadena anotherString="Infierno" ;
myString.startsWith(anotherString); // esto devuelve verdadero
myString.startsWith("World"); // esto devuelve falso

La función startsWith() devuelve verdadero si una cadena comienza con los


mismos caracteres que otra cadena.
Sintaxis: string.startsWith(string2);
string2 es el patrón de cadena con el que desea probar la cadena.
Tipo de retorno: booleano

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.

La función endsWith() devuelve verdadero si una cadena termina con


los mismos caracteres que otra cadena.
Sintaxis: string.endsWith(string2);
string2 es el patrón de cadena con el que desea probar la cadena.

Tipo de retorno: booleano

Concatenación, extracción y reemplazo


Las operaciones anteriores también introducen nuevos operadores de C. Los estoy usando aquí
con cadenas, pero aprenderá un poco más sobre ellos en un contexto más global más adelante.

[ 63 ]

www.it­ebooks.info
Machine Translated by Google

Conceptos básicos de C: cómo hacerte más fuerte

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.

Cadena firstString = "Hola ";


Cadena secondString="¡Mundo!";

// agregando el segundo al primero y poniendo el resultado en el primero


primeraCadena.concat(segundaCadena);

La función concat() añade una cadena a otra (es decir, la concatena en un


orden definido).
Sintaxis: string.concat(string2);
string2 es una cadena y se añade al final de la cadena.
Recuerde que el contenido anterior de la cadena se sobrescribe
como resultado de la concatenación.

Tipo de retorno: int (la función devuelve 1 si la concatenación se realiza


correctamente).

Uso del operador + en cadenas


Existe otra forma de concatenar dos cadenas. Esta no utiliza una función sino un operador: +.

Cadena firstString = "Hola ";


Cadena secondString="¡Mundo!";

// añadiendo el segundo al primero y poniendo el resultado en el primero

primeraCadena = primeraCadena + segundaCadena;

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:

primeraCadena = primeraCadena + segundaCadena;

[ 64 ]

www.it­ebooks.info
Machine Translated by Google

Capítulo 3

Esto también se puede escribir como:

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.

Cadena receivedMessage = "04.100";


Cadena currentOutputNumber;
Cadena currentValueNumber;

// extrayendo una parte de receivedMessage del índice 0 (incluido) al 1 (excluido)

currentOutputNumber = mensajeRecibido.substring(0,2);

// extrayendo una parte de receivedMessage desde el índice 3 (incluido) hasta el final

currentValueNumber = mensajeRecibido.substring(3);

[ 65 ]

www.it­ebooks.info
Machine Translated by Google

Conceptos básicos de C: cómo hacerte más fuerte

Este fragmento de código divide el mensaje recibido por Arduino en dos partes.

La función substring() extrae una parte de una cadena de un índice


de inicio (incluido) a otro (no incluido).
Sintaxis: string.substring(desde, hasta);
from es el índice de inicio. El resultado incluye el contenido del from
elemento de cadena. to es el índice final. El resultado no incluye el
contenido del elemento de cadena final, se puede omitir.
Tipo de retorno: cadena

Ampliemos el concepto de extracción de cadenas y dividámoslo un poco más.

Dividir una cadena usando un separador


Vamos a ponernos a prueba un poco. Imaginemos que no sé o no estoy seguro del formato del mensaje (dos
caracteres, un punto y tres caracteres, que acabamos de ver).
Este es un caso de la vida real; mientras aprendemos a hacer cosas, a menudo nos encontramos con casos
extraños en que las cosas no se comportan como se espera.

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().

Así es como lo hacemos:

Cadena receivedMessage = "04.100";


Cadena currentOutputNumber;
Cadena currentValueNumber;
int índicePuntoDividido;

// almacenando el índice del separador en la cadena splitPointIndex =


receivedMessage.indexOf('.');

//extrayendo mis dos elementos


currentOutputNumber = mensajeRecibido.substring(0, splitPointIndex);
currentValueNumber = receivedMessage.substring(splitPointIndex + 1);

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.it­ebooks.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.

Cadena receivedMessage = "04.100";


Cadena mensajeoriginal;

// manteniendo un rastro del mensaje anterior poniéndolo en otra variable

mensajeoriginal = mensajerecibido;

// Reemplazar el punto por el carácter de espacio en el mensaje recibido


mensajeRecibido.replace('.',' ');

En primer lugar, coloco el contenido de la variable receivedMessage en otra variable llamada


originalMessage porque sé que la función replace() definitivamente modificará la cadena
procesada. Luego, proceso receivedMessage con la función replace() .

La función replace() reemplaza una parte de una cadena con otra cadena.
Sintaxis: string.replace(substringToReplace, replacedSubstring);

from es el índice inicial. El resultado incluye el contenido de un elemento de cadena from.


to es el índice final. El resultado no incluye el contenido de un elemento de cadena final,
que se puede omitir. Recuerde que, como resultado del reemplazo, el contenido anterior
de la cadena se sobrescribe (cópielo a otra variable de cadena si desea conservarlo).

Tipo de retorno: int (la función devuelve 1 si la concatenación se realiza


correctamente).

[ 67 ]

www.it­ebooks.info
Machine Translated by Google

Conceptos básicos de C: cómo hacerte más fuerte

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.

Otras funciones de cadena


Hay algunas otras funciones de procesamiento de cadenas que me gustaría citar rápidamente aquí.

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.

Probando variables en el tablero


El siguiente es un fragmento de código que también puedes encontrar en la carpeta Chapter03/
VariablesVariaciones/:

/*
Programa de variaciones de variables
Este firmware muestra mensajes en serie para una mejor comprensión.
uso de variables.

[ 68 ]

www.it­ebooks.info
Machine Translated by Google

Capítulo 3

Encienda la ventana de Monitoreo en serie y reinicie la placa después de eso.

Observa y comprueba el código :)

Escrito por Julien Bayle, este código de ejemplo está bajo licencia Creative Commons
Licencia CC BY­SA

*/

// ¡declarar variables antes de divertirse! boolean myBoolean; char


myChar; int myInt; float
myFloat; String
myString;

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");
}

// jugando con char & int Serial.print("myChar


es actualmente "); Serial.write(myChar); Serial.println();

Serial.print("myInt es actualmente "); Serial.print(myInt);

[ 69 ]

www.it­ebooks.info
Machine Translated by Google

Conceptos básicos de C: cómo hacerte más fuerte

Serie.println();

Serial.print("Entonces, aquí está myChar + myInt : "); Serial.write(myChar +


myInt); Serial.println();

// jugando con float & int Serial.print("myFloat


es : "); Serial.print(myFloat); Serial.println();

// colocando el contenido de myFloat en myInt myInt = myFloat;


Serial.print("Puse myFloat
en myInt, y aquí está myInt ahora: "); Serial.println(myInt);

// jugando con String


Serial.print("myString es actualmente: "); Serial.println(myString);

myString += myChar; // concatenando myString con myChar Serial.print("myString tiene


una longitud de "); Serial.print(myString.length());// imprimiendo la
longitud de myString Serial.print(" y ahora es igual a: "); Serial.println(myString);

// myString se vuelve demasiado largo, más de 15, eliminando los últimos 3


elementos
si (miCadena.length() >= 15){
Serial.println("myString es demasiado largo... ¡vamos, vamos a limpiarlo!
");
myInt = myString.lastIndexOf('!'); // encontrando el lugar del '!' myString = myString.substring(0,myInt+1); //
eliminando caracteres

Serial.print("myString ahora está más limpio: "); Serial.println(myString);

// Poniendo verdadero en myBoolean

} de lo
contrario { myBoolean = falso; // restableciendo myBoolean a falso
}

retraso(5000); //hagamos una pausa

[ 70 ]

www.it­ebooks.info
Machine Translated by Google

Capítulo 3

//pongamos 2 lineas en blanco para tener una lectura clara


Serie.println();
Serie.println();
}

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:

El monitor serial que le muestra lo que dice su placa

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.

En loop(), primero estoy probando myBoolean, introduciendo la declaración condicional if() .


Aprenderemos esto también en este capítulo.

[ 71 ]

www.it­ebooks.info
Machine Translated by Google

Conceptos básicos de C: cómo hacerte más fuerte

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.

La propiedad de alcance se establece de manera implícita según el lugar de la declaración de la variable


en el código. Probablemente ya hayas comprendido que cada variable se puede declarar de manera global.
Generalmente sigo mi propio haiku digital.

Deja que cada parte de tu código conozca sólo las


variables que necesita conocer, nada más.

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.

int cadena global;

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

// … algún otro código


}

void otraFuncion() {
// … otro código más
int veryLocalVar; // veryLocalVar es visible solo en la función anotherFunction

[ 72 ]

www.it­ebooks.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 alcance del código visto como cuadros

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.

Calificadores estáticos, volátiles y constantes


Los calificadores son las palabras clave que se utilizan para cambiar el comportamiento del
procesador teniendo en cuenta la variable calificada . En realidad, el compilador utilizará estos
calificadores para cambiar las características de las variables consideradas en el firmware binario producido.
Vamos a aprender acerca de tres calificadores: estático, volátil y constante.

[ 73 ]

www.it­ebooks.info
Machine Translated by Google

Conceptos básicos de C: cómo hacerte más fuerte

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);
}

void myFunction(argument){ int


aLocalVariable; aLocalVariable
= aLocalVariable + argument; // jugando con aLocalVariable

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:

int miVariableGlobal; void


configuración(){ }

void loop()
{ miFuncion(digitalPinValue);
}

void myFunction(argumento){ static int


aStaticVariable; aStaticVariable =
aStaticVariable + argumento;
// jugando con una variable estática
}

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.it­ebooks.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.

Si intenta escribir un valor en una variable constante después de su declaración/definición,


el compilador arroja un error. El concepto de ámbito también se aplica aquí; podemos calificar una
variable declarada dentro de una función o globalmente. Esta declaración define y
declara la variable masterMidiChannel como una constante:

constante int masterMidiChannel = 10;

Esto es equivalente a:

#define el canal maestro Midi 10

No hay punto y coma después de una declaración #define.

#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.it­ebooks.info
Machine Translated by Google

Conceptos básicos de C: cómo hacerte más fuerte

Operadores, estructuras de operadores


y precedencia
Ya hemos visto muchos operadores. Veamos primero los operadores aritméticos.

Operadores aritméticos y tipos


Los operadores aritméticos son:

+ (signo más)

­ (menos)
• * (asterisco)
• / (barra oblicua)

• % (porcentaje)

= (igual)

Empiezo por el último: =. Es el operador de asignación . Ya lo hemos utilizado mucho para


definir una variable, lo que no es más que asignarle un valor. Por ejemplo:

int frecuenciadeloscilador = 440;

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:

Cadena myString = "Hola ";


Cadena myString2 = "Mundo";

Cadena myResultString = myString + myString2;


miCadena.concat(miCadena2);

En este código, la concatenación de myResultString y myString da como resultado la cadena


Hello World .

[ 76 ]

www.it­ebooks.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:

float Amplitud del oscilador de salida = 5.5;


int multiplicador = 3;
Amplitud del oscilador de salida = Amplitud del oscilador de salida * multiplicador

Tan pronto como utilice un tipo float o double como


uno de los operandos, se utilizará el proceso de
cálculo de punto flotante.

En el código anterior, el resultado de OutputOscillatorAmplitude * multiplicador es un valor de punto flotante .


Por supuesto, la división por cero está prohibida; la razón es matemática en lugar de C o Arduino.

Módulo es simplemente el resto de la división de un entero por otro.


Lo usaremos mucho para mantener las variables dentro de un rango controlado y elegido. Si
haces que una variable crezca hasta el infinito pero manipulas su módulo por 7, por ejemplo,
el resultado siempre estará entre 0 (cuando la variable creciente será un múltiplo de 7) y 6, lo
que restringe el crecimiento de la variable.

Notaciones condensadas y precedencia


Como habrás notado, existe una forma condensada de escribir una operación con estos
operadores explicados anteriormente. Veamos dos notaciones equivalentes y expliquemos esto.

Ejemplo 1:
int miInt1 = 1;
int miInt2 = 2;

miInt1 = miInt1 + miInt2;

[ 77 ]

www.it­ebooks.info
Machine Translated by Google

Conceptos básicos de C: cómo hacerte más fuerte

Ejemplo 2:

int miInt1 = 1;
int miInt2 = 2;

miInt1 += miInt2;

Estos dos fragmentos de código son equivalentes. El primero te enseña sobre la


precedencia de los operadores. En el Apéndice B, Precedencia de operadores en C y C++, se incluye
una tabla con todas las precedencias. Aprendamos algunas ahora mismo.

+, ­, *, / 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;

miInt1 += miInt2 + miInt2;

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;

miInt1 = miInt1 + miInt2 + miInt2;

Operadores de incremento y decremento


Quiero señalarte otra notación condensada que encontrarás a menudo: el operador doble.

int miInt1 = 1;

myInt++; // myInt1 ahora contiene 2


myInt­­; // myInt1 ahora contiene 1

++ es equivalente a +=1, ­­ es equivalente a ­=1. Estos se denominan incrementos de sufijo.


(++) y el sufijo decrementa (­­). También se pueden utilizar como prefijo. ++ y ­­ como prefijos
tienen menor precedencia que su equivalente utilizado como sufijo, pero en ambos casos la
precedencia es mucho mayor que +, ­, /, * e incluso = y +=.

[ 78 ]

www.it­ebooks.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.

Grupos de precedencias Operadores Nombres


2 ++ Incremento de sufijo
­­
Decremento de sufijo

() Llamada de función

[] Acceso a elementos de matriz


3 ++ Incremento de prefijo
­­
Decremento de prefijo

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.

Elegir el tipo adecuado


A veces, la elección está limitada por factores externos. Esto sucede cuando, por ejemplo, utilizas
Arduino con un sensor externo capaz de enviar datos codificados como números enteros en 10 bits
(210 = 1024 pasos de resolución). ¿Elegirías el tipo byte sabiendo que solo proporciona una forma
de almacenar números del 0 al 255? ¡Probablemente no! Elegirás int.

[ 79 ]

www.it­ebooks.info
Machine Translated by Google

Conceptos básicos de C: cómo hacerte más fuerte

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 .

Conversiones de tipos implícitas y explícitas


La conversión de tipos es el proceso que cambia el tipo de datos de una entidad por otro. Tenga en
cuenta que no hablé de variables, sino de entidades.

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 .

Conversión de tipo implícita


A veces, también se denomina coerción. Esto sucede cuando no se especifica nada para el compilador
que tiene que realizar una conversión automática siguiendo sus propias reglas básicas (pero a menudo
lo suficientemente inteligentes). El ejemplo clásico es la conversión de un valor flotante.
valor en un valor int .

flotar myFloat = 12345.6789;


entero miInt;
miInt = miFlotador;

println(myInt); // muestra 12345

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.it­ebooks.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
}

La salida del código se muestra a continuación:

Resultados extraños de la conversión implícita de int a float

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.

Reglas de conversión de tipos implícitos:

• Un valor int largo a flotante puede generar resultados erróneos


• float a int elimina la parte decimal
• doble para flotar rondas dígitos de doble
• long int a int elimina los bits codificados superiores

[ 81 ]

www.it­ebooks.info
Machine Translated by Google

Conceptos básicos de C: cómo hacerte más fuerte

Conversión de tipo explícita


Si desea tener resultados predecibles, siempre puede convertir los tipos explícitamente.
Hay seis funciones de conversión incluidas en el núcleo Arduino:

• 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.

Mi regla sobre la conversión: ten cuidado con cada conversión de


tipo que hagas. Ninguna debe ser obvia para ti y puede causar un
error en tu lógica, incluso si la sintaxis es totalmente correcta.

Comparación de valores y operadores booleanos


Ahora sabemos cómo almacenar entidades en variables, convertir valores y elegir el
método de conversión adecuado. Ahora aprenderemos a comparar valores de variables.

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.it­ebooks.info
Machine Translated by Google

Capítulo 3

La siguiente es una expresión de comparación en código:


int miInt1 = 4;
flotar myFloat = 5.76;
(miInt1 > miFlotante);

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.

Combinación de comparaciones con operadores


booleanos
Hay tres operadores booleanos:

• && (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.

El operador binario AND, también escrito como &&:

&& verdadero FALSO

verdadero verdadero FALSO

FALSO FALSO FALSO

Entonces el operador binario OR, también escrito como ||:

|| verdadero FALSO

verdadero verdadero verdadero

FALSO verdadero FALSO

Por último, el operador unario NOT, también escrito como !:

verdadero FALSO

! FALSO verdadero

[ 83 ]

www.it­ebooks.info
Machine Translated by Google

Conceptos básicos de C: cómo hacerte más fuerte

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.

Combinando negación y comparaciones


Considerando dos expresiones A y B:

• NO(A && B) = (NO A || NO B)


• NO (A || B) = (NO A && NO B)

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

¿Cuál es el significado de !(a < b)? Es la negación de la expresión, donde:

!(a < b) es igual a (a >= b)

El opuesto de a estrictamente menor que b es a mayor o igual que b. De la misma manera:

!(c >= d) es igual a (c < d)

Ahora, combinemos un poco. Neguemos la expresión global:

(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.it­ebooks.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:

Grupos de precedencias Operadores Nombres


2 ++ Incremento de sufijo
­­
Decremento de sufijo

() Llamada de función

[] Acceso a elementos de matriz


3 ++ Incremento de prefijo
­­
Decremento de prefijo

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.it­ebooks.info
Machine Translated by Google

Conceptos básicos de C: cómo hacerte más fuerte

Añadiendo condiciones en el código


Como estudié biología y tengo un máster, estoy familiarizado con los comportamientos orgánicos y vivos. Me
gusta decirles a mis alumnos que el código, especialmente en los campos de trabajo de diseño de interacción,
tiene que estar vivo. Con Arduino, a menudo construimos máquinas que pueden "sentir" el mundo real e
interactuar con él actuando sobre él. Esto no se podría hacer sin declaraciones de condición . Este tipo de
declaración se llama estructura de control. Usamos una estructura condicional mientras probamos nuestro
gran código, incluida la visualización de variables y más.

Estructura condicional if y else


Este es el que usamos sin explicar. Solo aprendiste paciencia y zen.
Las cosas empiezan a salir, ¿no? Ahora, vamos a explicarlo. Esta estructura es muy intuitiva porque es muy
similar a cualquier pseudocódigo condicional. Aquí hay uno:

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.it­ebooks.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.

Encadenamiento de una estructura if…else a otra estructura if…else


El siguiente es el ejemplo modificado:

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 error frecuente: omitir algunos casos


A veces, la cadena if…else es tan complicada y larga que podemos pasar por
alto algún caso y no verificar ninguno. Sea claro e intente comprobar todo el
universo de casos y codificar las condiciones en función de ello.

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.it­ebooks.info
Machine Translated by Google

Conceptos básicos de C: cómo hacerte más fuerte

Estructura if…else con expresiones de comparación combinadas


El siguiente es el ejemplo anterior donde comenté un poco más:

entero a;
entero b;
int estadoled;
si (a < b) { // a < b

estadoLed = 1; }

de lo contrario si (b > 0) { // a >= b y b > 0


estadoled = 0; }

de lo contrario { // a >= b y b < 0


estadoLed = 1; }

También podemos escribirlo de la siguiente manera teniendo en cuenta el comentario que


escribí anteriormente en el código:

entero a;
entero b;
int estadoled;
si (a < b || (a >= b && b < 0) ) ledState = 1; } {

de lo contrario si (a >= b && b > 0) {


estadoled = 0; }

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.

Encontrar todos los casos para una estructura condicional


Supongamos que quieres probar un valor de temperatura. Tienes dos límites/puntos específicos en los que
quieres que Arduino reaccione y, por ejemplo, te alerte encendiendo un LED o cualquier evento para
interactuar con el mundo real. Por ejemplo, los dos límites son: 15 grados Celsius y 30 grados Celsius.
¿Cómo puedo estar seguro de que tengo todas mis carcasas? La mejor manera es usar un bolígrafo, un
papel y dibujar un poco.

Comprobación de todos los valores T posibles

[ 88 ]

www.it­ebooks.info
Machine Translated by Google

Capítulo 3

Tenemos tres partes:

• T < 15

• T > 15 pero T < 30

• T > 30

Así que tenemos tres casos:

• 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:

float T ; // mi variable de temperatura

si (T < 15)
{ colorizeLed(azul); } de lo

contrario si (T >= 15 && T < 30)


{ colorizeLed(blanco); } de lo

contrario si (T >= 30)


{ colorizeLed(rojo); }

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.

Se muestra la sintaxis estándar


como sigue:

switch (var) { etiqueta de


caso:

// declaraciones
romper;

[ 89 ]

www.it­ebooks.info
Machine Translated by Google

Conceptos básicos de C: cómo hacerte más fuerte

Etiqueta del caso:

// 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:

flotar midiCCMessage; cambiar


(midiCCMessage) {
caso 7:
cambiarVolumen();
romper;
caso 10:
changePan();
romper;
por defecto:

LedApagado();
}

Este código es equivalente a:

flotante midiCCMessage; si
(midiCCMessage == 7) changeVolume(); de lo contrario si
(midiCCMessage == 10) changePan(); de lo contrario LedOff();

¿Estás bien?

Lo que quiero decir es que, cuando quieras comparar una


variable con muchos valores únicos, usa switch…case…
break, de lo contrario, usa if…else.

Cuando tienes intervalos de comparación, if…else es más conveniente porque puedes


usar < y > , mientras que en switch…case…break no puedes. Por supuesto, podríamos
combinar ambos. Pero recuerda mantener tu código lo más simple posible.

[ 90 ]

www.it­ebooks.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.

Se prueba la expresión. Si es verdadera, toda la declaración devuelve (o es igual a) val1, si es falsa, es


igual a val2.

Imaginemos nuevamente nuestro Arduino, el sensor de temperatura y un único límite que es 20


grados Celsius. Quiero que el LED se vuelva azul si T es menor que el límite y rojo si T es mayor o igual
a 20 grados Celsius. Así es como utilizaríamos los dos operadores ternarios:

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.

Creando bucles inteligentes para tareas repetitivas


Un bucle es una serie de eventos que se repiten en el tiempo. Básicamente, las computadoras fueron
diseñadas, en un principio, para realizar muchos cálculos repetidamente para ahorrar tiempo a los humanos.
Diseñar un bucle para repetir tareas que deben repetirse parece una idea natural. C implementa de
forma nativa algunas formas de diseñar bucles. El núcleo de Arduino incluye naturalmente tres
estructuras de bucle:

• para
• mientras

• hacer…mientras

Estructura de bucle for


La instrucción del bucle for es bastante fácil de usar. Se basa en, al menos, un contador que
comienza a partir de un valor particular que usted define y lo incrementa o decrementa hasta otro
valor definido. La sintaxis es:

para (declaración y definición; condición; incremento) {


// declaraciones
}

[ 91 ]

www.it­ebooks.info
Machine Translated by Google

Conceptos básicos de C: cómo hacerte más fuerte

El contador también se llama índice. Aquí te muestro un ejemplo real:

para (int i = 0; i < 100; i++) {


imprimirln(i);
}

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++ .

Preste atención al elemento de incremento. Se define con el incremento como sufijo.


significa aquí que el incremento ocurre después del final de la ejecución de las instrucciones para un valor i
considerado .

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:

• i = 0, ¿es i menor que 100? Sí, println(0), incrementa i

• i = 1, ¿es i menor que 100? Sí, println(1), incrementa i

Para las dos últimas iteraciones el valor de i se muestra de la siguiente manera:

• i = 99, ¿es i menor que 100? Sí, println(99), incrementa i


• i = 100, ¿es i menor que 100? No, detén el bucle.

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.

El alcance del índice


Si el índice se ha declarado dentro del paréntesis del bucle for,
su alcance es solo el bucle for. Esto significa que esta variable no es
conocido o no utilizable fuera del bucle.

[ 92 ]

www.it­ebooks.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).

Jugando con incremento


El incremento puede ser algo más complejo que simplemente utilizar el operador de incremento.

Incrementos más complejos


En primer lugar, en lugar de escribir i++, podríamos haber escrito i = i + 1. También podemos utilizar
otro tipo de operaciones como resta, multiplicación, división, módulo o combinaciones. Imagina
que quieres imprimir solo números impares. Los números impares son todos de la forma 2n + 1, donde n
es un entero. Aquí está el código para imprimir números impares del 1 al 99:

para (int i = 0; i < 50; i = 2 * i + 1) {


imprimirln(i);
}

Los primeros valores de i son: 1, 3, 5, y así sucesivamente.

Los decrementos son incrementos negativos


Solo quiero remezclar el código anterior para que no entiendas demasiado sobre incrementos y
decrementos. Aquí hay otro código que hace lo mismo pero imprime números impares del 99 al 1:

para (int i = 50; i > 0; i = 2 * i ­ 1) {


imprimirln(i);
}

¿De acuerdo? Compliquemos las cosas un poco.

Usando bucles for imbricados o dos índices


También es posible utilizar más de un índice en una estructura for . Imaginemos que queremos
Calcular una tabla de multiplicar hasta 10 x 10. Tenemos que definir dos variables enteras de 1 a 10 (siendo
0 trivial). Estos dos índices tienen que variar de 1 a 10. Podemos empezar con un bucle con el índice x:

para (int x = 1; x <= 10; x++) {

[ 93 ]

www.it­ebooks.info
Machine Translated by Google

Conceptos básicos de C: cómo hacerte más fuerte

Esto es para el primer índice. El segundo es totalmente similar:

para (int y = 1; y <= 10; y++) {

¿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:

para (int x = 1; x <= 10; x++) {

para (int y = 1; y <= 10; y++) {

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:

Vista clásica de una tabla de multiplicar

[ 94 ]

www.it­ebooks.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.

para (int x = 1; x <= 10; x++) {

para (int y = 1; y <= 10; y++) {

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.

Estructura del bucle while


La estructura del bucle while es un poco más sencilla. Esta es la sintaxis:

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.it­ebooks.info
Machine Translated by Google

Conceptos básicos de C: cómo hacerte más fuerte

Estructura del bucle do…while


La estructura del bucle do…while es muy similar a la estructura while , pero realiza la
evaluación de la expresión al final del bucle, es decir, después de la ejecución de la
sentencia. Esta es la sintaxis:

hacer {
// declaraciones
} mientras (expresión);

A continuación se muestra un ejemplo del mismo modelo:

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 .

Rompiendo los bucles


Aprendimos a crear bucles controlados por índices que definen con precisión cómo se
ejecutarán estos bucles. Pero, ¿cómo podemos detener un bucle cuando ocurre un evento
externo ? El término "externo" se toma en el sentido de "externo" al bucle en sí, incluidos sus
índices. En ese caso, la condición del bucle en sí no incluiría el elemento externo.

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.it­ebooks.info
Machine Translated by Google

Capítulo 3

Lo diseñé de forma muy sencilla, de la siguiente manera:

para ( intensidad = 0 ; intensidad < 100 ; intensidad++ ){


ledIntensity (intensidad);
if (distancia > maxDistancia) { // si el usuario está lejos
intensidad = 0; ruptura; //apaga el LED
// sale del bucle
}
}

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.

Los bucles infinitos no son tus amigos


Tenga cuidado con los bucles infinitos. El problema no es realmente el estado infinito de los bucles, sino el hecho de
que un sistema, cualquiera que sea, incluido Arduino, que está ejecutando un bucle infinito, ¡solo hace eso! Nada de lo
que está después del bucle se puede ejecutar porque el programa no saldrá del bucle.

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.it­ebooks.info
Machine Translated by Google

Conceptos básicos de C: cómo hacerte más fuerte

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.it­ebooks.info
Machine Translated by Google

Mejore la programación con


Funciones, matemáticas y tiempo
Como artista digital, necesito unas condiciones especiales para poder trabajar. Todos necesitamos
nuestro propio entorno y ambiente para ser productivos. Aunque cada uno tiene su manera, hay muchas
cosas en común.

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.

¡Será un capítulo muy interesante antes de sumergirnos realmente en los proyectos de


Arduino puro!

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.it­ebooks.info
Machine Translated by Google

Mejore la programación con funciones, matemáticas y tiempo

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.

Estructura de una función


Una función es un bloque de código que tiene un encabezado y un cuerpo. En C estándar, la declaración
y la definición de una función se realizan por separado. La declaración de la función se denomina
específicamente declaración del prototipo de la función y debe realizarse en el archivo de encabezado
(consulte el Capítulo 2, Primer contacto con C).

Creación de prototipos de funciones utilizando el IDE de Arduino


El IDE de Arduino nos facilita la vida, ya que crea prototipos de funciones para nosotros. Pero en
casos especiales, si necesitas declarar un prototipo de función, puedes hacerlo en el mismo archivo
de código al principio del código. Esto proporciona una buena forma de centralizar el código
fuente.

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:

int miSuma(int m, int n);

Encabezado y nombre de funciones


Es interesante saber cómo se ve el prototipo porque es similar a lo que llamamos encabezado. El
encabezado de una función es la definición de su primera declaración. Avancemos escribiendo la
estructura global de nuestra función mySum:

int mySum(int m, int n) // esta fila es el encabezado


{
// Entre llaves se encuentra el cuerpo
}

El encabezado tiene la forma global:

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.it­ebooks.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.

Cuerpo y enunciados de funciones


Como probablemente hayas entendido intuitivamente, el cuerpo es el lugar donde todo
sucede; es donde se construyen todos los pasos de instrucción de una función.

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.it­ebooks.info
Machine Translated by Google

Mejore la programación con funciones, matemáticas y tiempo

También puedes, como acabamos de presentar, devolver el valor de una variable. Vamos a crear el cuerpo de
nuestro ejemplo mySum :

int mySum(int m, int n) // esta fila es el encabezado


{
int resultado; // esta es la variable para almacenar el resultado
resultado = m + n; // hace la suma y la almacena en resultado
retorna resultado; // devuelve el valor de la variable resultado
}

int result; declara la variable y la nombra result. Su alcance es el mismo que


el de los argumentos. result = m + n; contiene dos operadores y ya sabes que
+ tiene mayor precedencia que =, lo cual es bastante bueno, ya que la operación
matemática se realiza primero y luego el resultado se almacena en el resultado.
variable. Aquí es donde ocurre la magia: tome dos operadores y haga uno con ellos. Recuerde que, en una
combinación de múltiples operaciones matemáticas, no olvide el orden de precedencia; es fundamental para
no obtener resultados inesperados.

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.it­ebooks.info
Machine Translated by Google

Capítulo 4

int mySum(int m, int n) // esta fila es el encabezado


{
int resultado; // esta es la variable para almacenar el resultado
resultado = m + n; // hace la suma y la almacena en resultado
retorna resultado; // devuelve el valor de la variable resultado
}

Como acabas de ver, la función mySum se ha definido y llamado en el ejemplo. La declaración


más importante es currentResult = mySum(i,i+1);. Por supuesto, el truco de i e i+1 es interesante, pero lo
más importante que hay que reconocer aquí es el uso de la variable currentResult que se declaró al
principio de la función loop() .

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.

Puede consultar el Apéndice B, Precedencia de operadores en C y C++ para obtener la lista


completa de precedencias. Al igual que con todos los valores dentro de una variable, podemos
almacenarlos en otra, aquí dentro de la variable entera result.

Beneficios de utilizar funciones


Programar consiste en escribir fragmentos de código para propósitos generales y específicos.
El uso de funciones es una de las mejores maneras de segmentar su código.

Codificación y depuración más sencillas


Las funciones pueden ayudarnos mucho a organizarnos mejor. Al diseñar un programa, solemos utilizar
pseudocódigos y este es también el paso en el que nos damos cuenta de que hay muchas declaraciones
comunes. Estas declaraciones comunes suelen estar dentro de funciones.

[ 103 ]

www.it­ebooks.info
Machine Translated by Google

Mejore la programación con funciones, matemáticas y tiempo

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

muchas llamadas de funciones


llamar
llamar llamar

función () {

Solo un lugar para depurar


}

Las funciones hacen que sea más fácil depurar su código

Una mejor modularidad favorece la reutilización


Algunas partes de su código serán de alto nivel y generales. Por ejemplo, en algún momento, puede
necesitar una serie de instrucciones que puedan cortar una matriz en partes y luego reagrupar todos los
valores siguiendo una regla básica. Esta serie podría ser el cuerpo de una función. De otra manera,
codificar una función que convierta unidades Fahrenheit en Celsius podría interesarle. Estos dos
ejemplos son funciones de propósito general.

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 •

Respetar la API de la función que puede ser parte de una biblioteca

• Buen ajuste para su propósito

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.it­ebooks.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.

Funciones matemáticas estándar de C y Arduino

Como ya hemos visto, casi todas las entidades estándar de C y C++ admitidas por el compilador
avr­g++ 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.it­ebooks.info
Machine Translated by Google

Mejore la programación con funciones, matemáticas y tiempo

Funciones trigonométricas C en el núcleo Arduino


A menudo necesitamos realizar algunos cálculos trigonométricos, desde determinar las distancias que
se ha movido un objeto hasta la velocidad angular y muchas otras propiedades del mundo real.
A veces, necesitarás hacer eso dentro de Arduino porque lo usarás como una unidad inteligente
autónoma sin ninguna computadora en el vecindario.

El núcleo de Arduino proporciona las funciones trigonométricas clásicas que se pueden


resumir escribiendo sus prototipos. Una gran parte de ellas devuelven resultados en radianes.
¡Comencemos repasando un poco nuestra trigonometría!

Algunos requisitos previos


Prometo que seré breve y ligero, pero las siguientes líneas de texto te ahorrarán tiempo a la hora
de buscar tu viejo y desgastado libro de texto. Cuando aprendo conocimientos de campos
específicos, personalmente me gusta tener todo lo que necesito a mano.

Diferencia entre radianes y grados


El radián es la unidad que utilizan muchas funciones trigonométricas. Luego, tenemos que tener claro qué
son los radianes y los grados, y sobre todo cómo convertir uno en otro. Aquí está la definición oficial de
radián: Alfa es un cociente entre dos distancias y se expresa en unidades de radianes.

yo

yo
=
a
a

Definición de radián

[ 106 ]

www.it­ebooks.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:

ánguloradián = ángulogrado x π/180


ángulogrado = ánguloradián x 180/π

Coseno, seno y tangente


Veamos el ejemplo del triángulo trigonométrico:

h a
(hipotensa)
(opuesto)

A b do

(adyacente)

Considerando el ángulo A en radianes, podemos definir coseno, seno y tangente.


como sigue:

• cos(A) = b/h

• sen(A) = a/h

• tan(A) = sin(A)/cos(A) = a/b

[ 107 ]

www.it­ebooks.info
Machine Translated by Google

Mejore la programación con funciones, matemáticas y tiempo

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)

0 50 100 150 200 250 300 350


­0,5

­1

0 y = tan(x)

0 50 100 150 200 250 300 350

­5

Representación gráfica del coseno, seno y tangente

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.it­ebooks.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?

Arco coseno, arco seno y arco tangente


El arcocoseno, el arcoseno y el arcotangente se denominan funciones trigonométricas inversas. Estas
funciones se utilizan para calcular un ángulo cuando ya se tienen las relaciones de distancias que
mencioné antes.

Se denominan funciones inversas porque se trata del proceso inverso/recíproco de la función


trigonométrica vista anteriormente. Básicamente, estas funciones te proporcionan un ángulo, pero
considerando la periodicidad, proporcionan muchos ángulos. Si k es un entero, podemos escribir:

• sen (A) = x ó A = arcsin(x) + 2kπ o y = π – arcsin(x) + 2kπ


• cos(A) = x o A = arcos(x) + 2kπ o y = 2π – arcos(x) + 2kπ
• tan (A) = x ó A = arctan(x) + kπ

É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 cos (double x); devuelve el coseno de x radianes


• doble seno (doble x); devuelve el seno de x radianes

• doble tan (doble x); devuelve la tangente de x radianes


• double acos (double x); devuelve A, el ángulo correspondiente
a cos (A) = incógnita

• double asin (double x); devuelve A, el ángulo correspondiente a sin (A) = • double atan (double incógnita

x); devuelve A, el ángulo correspondiente a sin ( A) =


broncearse (A) = incógnita

• doble atan2 (doble y, doble x); devuelve arctan (y/x)

[ 109 ]

www.it­ebooks.info
Machine Translated by Google

Mejore la programación con funciones, matemáticas y tiempo

Funciones exponenciales y algunas otras


Para realizar cálculos, incluso los más básicos, se utilizan otros tipos de funciones matemáticas, como
potencias, valores absolutos, etc. El núcleo Arduino las implementa.
Algunas funciones matemáticas se dan como sigue:

• double pow (doble x, doble y); devuelve x elevado a la potencia y


• double exp (double x); devuelve el valor exponencial de x
• doble logaritmo (doble x); devuelve el logaritmo natural de x con x > 0
• double log10 (doble x); devuelve el logaritmo de x en base 10 con x > 0
• doble cuadrado (doble x); devuelve el cuadrado de x
• double sqrt (doble x); devuelve la raíz cuadrada de x con x >= 0
• double fabs (double x); devuelve el valor absoluto de x

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!

Ahora, abordemos algunos métodos de optimización.

Acercándose a la optimización del cálculo


Esta sección es una aproximación, es decir, no contiene todos los consejos y trucos
avanzados para optimizar la programación, sino optimizaciones basadas en cálculos puros.

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.

Normalmente, nuestro firmware es pequeño, por lo que te sugiero


que consideres esto como una nueva regla: escribe cada
declaración teniendo en cuenta la optimización.

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.it­ebooks.info
Machine Translated by Google

Capítulo 4

El poder de la operación de cambio de bits


Si considero una matriz para almacenar cosas, casi siempre elijo el tamaño como una potencia de dos. ¿Por qué? Porque
el compilador, en lugar de realizar la indexación de la matriz mediante una operación de multiplicación que consume mucho
CPU, puede utilizar la operación de desplazamiento de bits, que es más eficiente.

¿Qué son las operaciones de bits?


Algunos de vosotros ya habréis entendido mi forma de trabajar, utilizo muchos pretextos para enseñaros cosas
nuevas. Los operadores bit a bit son operadores específicos para bits.
Algunos casos requieren este tipo de cálculo. Puedo citar dos casos que aprenderemos en la siguiente parte de este libro:

• Uso de registros de desplazamiento para multiplexación

• 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.

Sistema de numeración binario


Estamos acostumbrados a contar utilizando el sistema decimal, también llamado sistema de numeración decimal o
sistema de numeración de base 10. En este sistema, podemos contar como:

0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12...

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:

0, 1, 10, 11, 100, 101, 110, 111...

Convertir fácilmente un número binario a un número decimal


Un buen truco para convertir de binario a decimal es empezar contando la posición de 0 y 1, empezando por el índice 0.

Tomemos el número 110101. Se puede representar de la siguiente manera:

Posiciones 0 1 2 3 4 5
1 0 1 0 1 1

[ 111 ]

www.it­ebooks.info
Machine Translated by Google

Mejore la programación con funciones, matemáticas y tiempo

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

Cada bit decide si debemos considerar la potencia de 2, considerando su posición.

Operadores AND, OR, XOR y NOT


Echemos un vistazo a estos cuatro operadores.

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:

int a = 35; // en binario: 00000000 00100011


int b = 49; int c = // en binario: 00000000 00110001
a & b; // en binario: 00000000 00100001 y en decimal 33

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.it­ebooks.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

Es la versión exclusiva de OR, de ahí el nombre XOR.

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:

int a = 35; int b = // en binario: 00000000 00100011


~a ; // en binario: 11111111 11011100 y en decimal ­36

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).

Operaciones de desplazamiento de bits

En C++, los operadores de desplazamiento a la izquierda y a la derecha se simbolizan


respectivamente con << y >>. Es fácil de recordar: el doble << va a la izquierda y el otro >> a
la derecha. Básicamente, funciona así:

int a = 36; int b // en binario 00000000 00100100


= a << 2; // en binario 00000000 10010000, decimal 144
int c = a >> 1; // en binario 00000000 00010010, decimal 18

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.it­ebooks.info
Machine Translated by Google

Mejore la programación con funciones, matemáticas y tiempo

Todo es cuestión de rendimiento


Las operaciones bit a bit son acciones primitivas soportadas directamente por el procesador.
Especialmente en sistemas integrados, que aún no son tan potentes como las computadoras normales,
el uso de operaciones bit a bit puede mejorar drásticamente el rendimiento.
Puedo escribir dos nuevas reglas:

• 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.

Técnicas de optimización de etiquetas de casos


de conmutación
La estructura condicional switch…case también se puede optimizar mientras la escribes.

Optimización de la gama de casos


La primera regla es colocar todos los casos del interruptor considerado en el rango más estrecho
posible.

En tal caso, el compilador produce lo que llamamos una tabla de saltos de etiquetas de casos, en
lugar de generar una enorme cascada if­else­if . 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.it­ebooks.info
Machine Translated by Google

Capítulo 4

Optimización de casos según su frecuencia


La segunda regla es colocar todos los casos ordenados desde el que ocurre con mayor frecuencia hasta el
que ocurre con menor frecuencia cuando se conoce la frecuencia.

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 if­else­if . 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.

Cuanto menor sea el alcance, mejor será el tablero.


Como ya mencioné cuando hablamos sobre el alcance de las variables, siempre use el alcance más
pequeño posible para cualquier variable. Veamos este ejemplo con una función llamada myFunction:

int miFuncion( int valorAProbar )


{
si (valorAProbar == 1)
{
int VariableTemporal;
// algunos cálculos con TemporaryVariable
devuelve variabletemporal;
}
demás {
devuelve ­1;
}
}

TemporaryVariable solo se requiere en un caso, cuando ValueToTest es igual a 1. Si declaro


TemporaryVariable fuera de la declaración if , sea cual sea el valor de ValueToTest, se creará
TemporaryVariable .

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.

Utilice el alcance más pequeño posible para todas sus variables.

[ 115 ]

www.it­ebooks.info
Machine Translated by Google

Mejore la programación con funciones, matemáticas y tiempo

El Tao de los retornos


Las funciones suelen diseñarse con una idea particular en mente, son módulos de código capaces de realizar
operaciones específicas a través de las sentencias que incluyen y también pueden devolver un resultado.
Este concepto proporciona una forma agradable de olvidarnos de todas esas operaciones específicas que se
realizan dentro de la función cuando estamos fuera de ella. Sabemos que la función ha sido diseñada para
proporcionarte un resultado cuando le das argumentos.

Nuevamente, esta es una buena manera de centrarse en el núcleo de su programa.

Concepto de retorno directo


Como ya habrás comprendido, al declarar una variable se crea un lugar en la memoria. Ese lugar, por
supuesto, no puede ser utilizado por otra cosa. El proceso que crea la variable consume tiempo de procesador.
Tomemos el mismo ejemplo anterior con más detalle:

int miFuncion( int valorAProbar )


{
si (valorAProbar == 1)
{
int VariableTemporal;
VariableTemporal += VariableGlobal;
VariableTemporal *= 7;
devuelve variabletemporal;
}
demás {
devuelve ­1;
}
}

¿Qué podría mejorar para intentar evitar el uso de TemporaryVariable? Podría hacer un return directo de la
siguiente manera:

int miFuncion( int valorAProbar )


{
si (valorAProbar == 1)
{
devuelve ( (globalVariable + 1)*7 );
}
demás {
devuelve ­1;
}
}

[ 116 ]

www.it­ebooks.info
Machine Translated by Google

Capítulo 4

En la versión más larga:

• Estábamos dentro del caso valueToTest == 1 por lo tanto valueToTest es igual a 1



Pongo directamente el cálculo en la declaración de retorno

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.

Utilice un retorno directo en lugar de muchas variables temporales.

Utilice void si no necesita devolución


A menudo leo códigos que incluyen funciones con un tipo de retorno que no devuelve nada.
El compilador puede advertirle sobre esto, pero en caso de que no lo haga, debe tener cuidado. Una llamada
a una función que proporciona un tipo de retorno siempre pasará el valor de retorno, incluso si no se
devuelve nada dentro del cuerpo de la función. Esto tiene un costo de CPU.

Utilice void como tipo de retorno para sus funciones si no


devuelven nada.

Secretos de las tablas de búsqueda


Las tablas de búsqueda son uno de los trucos más poderosos en el universo de la programación.
Son matrices que contienen valores precalculados y, por lo tanto, reemplazan los cálculos pesados en
tiempo de ejecución por una operación de índice de matriz más simple. Por ejemplo, imagine que desea
rastrear las posiciones de algo leyendo distancias provenientes de un conjunto de sensores de distancia.
Tendrá que realizar cálculos trigonométricos y, probablemente, de potencia .
Dado que pueden consumir mucho tiempo para el procesador, sería más inteligente y económico utilizar
la lectura del contenido de la matriz en lugar de esos cálculos. Esta es la ilustración habitual del uso de
tablas de búsqueda.

Estas tablas de búsqueda se pueden precalcular y almacenar en la memoria de almacenamiento de un


programa estático, o calcular en la fase de inicialización del programa (en ese caso, las llamamos
tablas de búsqueda precalculadas).

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.it­ebooks.info
Machine Translated by Google

Mejore la programación con funciones, matemáticas y tiempo

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.

Consideremos el código de Arduino. Puede encontrarlo en la carpeta


Chapter04/CosLUT/ :

flotante cosLUT[(int) (360.0 * 1 / 0.5)] ;


constante flotante DEG2RAD = 180 / PI ;

constante float cosinePrecision = 0.5;


const int cosinePeriod = (int) (360.0 * 1 / cosinePrecision);

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.it­ebooks.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.

Reemplazar el cálculo puro con operaciones de


índice de matriz
Ahora, recuperemos nuestros valores de coseno. Podemos recuperarlos fácilmente accediendo a nuestra
LUT a través de otra función, que se muestra a continuación:

flotar myFastCosine(ángulo flotante){

devuelve cosLUT[(int) (ángulo * 1 / cosinePrecision) % cosinePeriod];


}

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/digital­collisions­1­1­new­features). 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.

Truco de expansión de la serie de Taylor


Hay otra forma interesante de ahorrar trabajo de CPU que requiere algo de matemática. Me refiero a
una matemática un poco más avanzada. Las siguientes palabras están muy simplificadas. Pero sí, tenemos
que centrarnos en el lado C de las cosas, y no solo en las matemáticas.

[ 119 ]

www.it­ebooks.info
Machine Translated by Google

Mejore la programación con funciones, matemáticas y tiempo

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.

Una expresión polinomial es similar a la siguiente expresión:


P(x) = a + bx + cx2 + dx3

P(x) es una función polinómica de grado 3. a, b, c y d son números flotantes.

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:

sen(x) ≈ x ­ x3/6 + x5/120 ­ x7/5040

El signo ≈ significa "aproximadamente igual". Dentro de un rango razonable, podemos reemplazar


sen(x) por x ­ x3/6 + x5/120 ­ x7/5040. No hay magia, solo teoremas matemáticos.
También podemos escribir x evolucionando de ­2 a 3 de la siguiente manera:

ex ≈ 1 + x + x2/2 + x3/6 + x4/24

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.

El núcleo Arduino incluso proporciona punteros


Los punteros son técnicas más complicadas para principiantes en programación en C, pero quiero
que entiendas el concepto. No son datos, pero apuntan al punto de partida de un dato. Hay al menos
dos formas de pasar datos a una función o a otra cosa:

• 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.it­ebooks.info
Machine Translated by Google

Capítulo 4

Medida del tiempo


El tiempo es siempre algo interesante de medir y de manejar, especialmente en software integrado,
que es, obviamente, nuestro objetivo principal aquí. El núcleo de Arduino incluye varias funciones de
tiempo de las que voy a hablar ahora.

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 placa Arduino tiene reloj propio?


El chip de la placa Arduino proporciona su tiempo de actividad. El tiempo de actividad es el tiempo
transcurrido desde que la placa se ha puesto en marcha. Esto significa que no se puede almacenar
de forma nativa la fecha y la hora absolutas sin mantener la placa encendida y encendida. Además,
será necesario que configure la hora absoluta una vez y luego mantenga encendida la placa Arduino.
Es posible mantener la placa encendida de forma autónoma. También hablo de eso más adelante en este libro.

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.it­ebooks.info
Machine Translated by Google

Mejore la programación con funciones, matemáticas y tiempo

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.

al monitor serial cada 250ms para no ser demasiado verboso.

Escrito por Julien Bayle, este código de ejemplo está bajo licencia Creative Commons
Licencia CC BY­SA

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
*/

tiempo medido sin signo largo; // almacenar el tiempo de actividad

configuración vacía(){
Serie.begin(9600);
}

bucle vacío(){
Serial.print("Hora: ");
tiempoMedido = milisegundos();

Serial.println(measuredTime); // imprime el tiempo de actividad actual

retraso(250); // pausando el programa 250ms


}

¿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.

al monitor serial cada 250ms para no ser demasiado verboso.

Escrito por Julien Bayle, este código de ejemplo está bajo licencia Creative Commons
Licencia CC BY­SA

[ 122 ]

www.it­ebooks.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

µs e imprimiéndolo en el monitor serial cada 250ms para no


ser demasiado verboso

Escrito por Julien Bayle, este código de ejemplo está bajo licencia Creative Commons
Licencia CC BY­SA

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.it­ebooks.info
Machine Translated by Google

Mejore la programación con funciones, matemáticas y tiempo

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

retraso(250); // pausando el programa 250ms


}

Subelo y verifica el Monitor Serial.

Concepto de retardo y flujo del programa


Al igual que Le Bourgeois Gentilhomme, que hablaba en prosa sin siquiera darse cuenta, ya ha
utilizado la función principal delay() y no se ha dado cuenta. El retraso de un programa Arduino se puede
realizar utilizando las funciones delay() y delayMicroseconds() directamente en la función loop() .

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().

¿Qué hace el programa durante el retraso?


Nada. Espera. Esta subsección no es una broma. Quiero que te centres en este punto en
particular porque más adelante será bastante importante.

Cuando llamas a delay o delayMicroseconds en un programa, detiene su ejecución durante


una cierta cantidad de tiempo.

[ 124 ]

www.it­ebooks.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

El cargador de arranque se ejecuta Ejecución del firmware

Manejo básico de hardware setup() se ejecuta una vez


carga de firmware loop() se ejecuta y repite indefinidamente
lanzamiento de firmware

tiempo

Un ciclo de vida del firmware de un Arduino

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

Si aceptamos el hecho de que cuando setup() se detiene, la función loop() comienza


a repetirse, todo en loop() es continuo. Ahora observemos lo mismo cuando se producen
demoras:

El ciclo de vida del firmware con la parte principal en bucle y interrumpiéndose cuando se llama a delay()

Todo el programa se interrumpe cuando se llama a delay() . La duración de la interrupción


depende del parámetro que se pasa a delay().

[ 125 ]

www.it­ebooks.info
Machine Translated by Google

Mejore la programación con funciones, matemáticas y tiempo

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().

Una placa Arduino ocupada con muchas entradas y salidas

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

• Manejador de interrupciones (y concepto de rutina de servicio de interrupciones subsiguiente)

Obviamente enseño otra: el sondeo. El sondeo es un caso especial de interrupción desde


donde comenzaremos.

[ 126 ]

www.it­ebooks.info
Machine Translated by Google

Capítulo 4

El concepto de sondeo: un caso especial de interrupción


Ya conoces el término de la encuesta. Lo puedo resumir como "pregunta, espera una respuesta y
guárdala en algún lugar".

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í.

No diseñe soluciones alternativas a programas complejos antes de haber probado


las básicas.

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.it­ebooks.info
Machine Translated by Google

Mejore la programación con funciones, matemáticas y tiempo

Piense en optimizaciones extremas, pero primero pruebe su código básico.

El concepto de manejador de interrupciones


El sondeo es bueno, pero consume un poco de tiempo, como acabamos de descubrir. La mejor manera sería poder
controlar cuándo el procesador tendría que lidiar con las entradas o salidas de una manera más inteligente.

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.

El manejador de interrupciones es una rutina que maneja la interrupción haciendo algo.


Por ejemplo, cuando el ratón se mueve, el sistema operativo del ordenador (comúnmente llamado SO) tiene que
volver a dibujar el cursor en otro lugar. Sería una locura dejar que el propio procesador comprobara cada milisegundo
si el ratón se ha movido, porque la CPU estaría funcionando al 100 por ciento de su capacidad. Parece más
inteligente tener una parte del hardware para ese propósito. Cuando se produce el movimiento del ratón, envía
una interrupción al procesador, y este posteriormente vuelve a dibujar el ratón.

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.it­ebooks.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).

Encuestas, ISR y ahora, vamos a iniciar los hilos. ¡Un momento!

¿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.

La multiplexación por división de tiempo permite realizar múltiples tareas

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.

El multiprocesamiento real permite que las tareas se realicen 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.it­ebooks.info
Machine Translated by Google

Mejore la programación con funciones, matemáticas y tiempo

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.

Un ejemplo de biblioteca de encuestas de la vida real


Como se presenta en la primera línea de esta sección, la biblioteca de Marcello es muy bonita.
Proporciona un método basado en encuestas para iniciar acciones cronometradas.

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.it­ebooks.info
Machine Translated by Google

Capítulo 4

Instalación de una biblioteca externa


Descárguelo de http://playground.arduino.cc/Code/SimpleTimer y extráigalo en algún lugar de su
computadora. Normalmente verá una carpeta con al menos dos archivos dentro:

• Un archivo de encabezado (extensión .h )

• Un archivo de código fuente ( extensión .cpp )

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:

El encabezado y el código fuente de SimpleTimer de Marcello Romani

[ 131 ]

www.it­ebooks.info
Machine Translated by Google

Mejore la programación con funciones, matemáticas y tiempo

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.

Vamos a probar el código


Sube el siguiente código y reinicia Arduino; te voy a explicar cómo funciona.
También puedes encontrar este código en la carpeta Chapter04/simpleTimerBlinker/ :

#include <SimpleTimer.h> // incluye la biblioteca de Marcello

temporizador SimpleTimer; // la construcción del objeto temporizador


booleano currentLEDState;
int ledPin = 13;

configuración vacía() {
currentLEDState = falso;
pinMode(ledPin, SALIDA);
temporizador.setInterval(120, blink);

bucle vacío() {
temporizador.run() ;
}

[ 132 ]

www.it­ebooks.info
Machine Translated by Google

Capítulo 4

// una función que se ejecutará periódicamente


void parpadear() {
si (!currentLEDState) digitalWrite(ledPin, ALTO);
de lo contrario digitalWrite(ledPin, LOW);
currentLEDState = !currentLEDState ; // invierte el booleano
}

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

• Una función de devolución de llamada

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.it­ebooks.info
Machine Translated by Google

Mejore la programación con funciones, matemáticas y tiempo

En realidad, no hay ninguna mejora en el rendimiento, ni en un sentido ni en otro. Es simplemente


una decisión personal: usa el que prefieras.

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.

¡El futuro es ahora!

[ 134 ]

www.it­ebooks.info
Machine Translated by Google

Detección con entradas digitales


Las placas Arduino tienen entradas y salidas. De hecho, este es también uno de los puntos fuertes de esta
plataforma: proporcionar directamente los conectores que conectan las patas del chipset ATMega. De
esta forma, podemos cablear directamente una entrada o una salida a cualquier otro componente o circuito
externo sin necesidad de soldar.

Por si lo necesitas aquí te recuerdo algunos puntos:

• Arduino tiene entradas digitales y analógicas.

• Arduino tiene salidas digitales que también se pueden utilizar para imitar salidas analógicas.

Vamos a hablar sobre las entradas digitales en este capítulo.

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.it­ebooks.info
Machine Translated by Google

Detección con entradas digitales

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.

De hecho, introduce tres elementos que necesitamos:

• Una capacidad
• Algunos datos

• Una percepción

Los sensores aportan nuevas capacidades


Un sensor es un convertidor físico, capaz de medir una cantidad física y traducirla en una señal
comprensible directa o indirectamente por humanos o máquinas.

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.

Algunos tipos de sensores


Podemos encontrar varios tipos de sensores. A menudo pensamos en sensores ambientales cuando
utilizamos el término sensor.

Comenzaré citando algunas magnitudes ambientales:

• Temperatura

• Humedad
• Presión

• Sensores de gas (específicos para gas o no, humo)


• Campos electromagnéticos
• Anemómetro (velocidad del viento)

[ 136 ]

www.it­ebooks.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.

La cantidad se convierte en datos


Cuando utilizamos sensores, la razón es que necesitamos tener un valor numérico que
provenga de un fenómeno físico, como la temperatura o el movimiento. Si pudiéramos medir
directamente la temperatura con los sensores térmicos de nuestra piel, habríamos podido entender
la relación entre el volumen de los componentes químicos y la temperatura en sí. Como
conocemos esta relación a partir de otras medidas o cálculos físicos, hemos podido diseñar
termómetros.

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.it­ebooks.info
Machine Translated by Google

Detección con entradas digitales

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.

Los datos deben ser percibidos


Los datos que proporciona un sensor tienen más sentido si se leen. Esto puede resultar obvio,
pero imaginemos que el lector no es un humano, sino un instrumento, una máquina o, en
nuestro caso, una placa Arduino.

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.

En nuestro caso, el Arduino sería el dispositivo capaz de convertir el potencial eléctrico en


algo legible o al menos más fácil de entender para nosotros, los humanos.
Se trata de nuevo de una conversión. Del fenómeno físico que queremos traducir al dispositivo
que muestra el valor que explica el fenómeno físico, hay conversiones y percepciones.

Puedo simplificar el proceso como se muestra en la siguiente figura:

físico usuario final


medida conversión datos percepción
fenómeno consumidor de datos

¿Qué significa digital?


Definamos con precisión qué significa aquí el término digital.

Conceptos digitales y analógicos


En el mundo de la informática y la electrónica, digital significa discreto, lo que es lo opuesto a
analógico/continuo. También es una definición matemática. A menudo hablamos de
dominios para definir los casos de uso de lo digital y lo analógico.

Generalmente, el dominio analógico es el dominio relacionado con las medidas físicas.


Nuestra temperatura puede tener todos los valores posibles y existentes, incluso si
nuestros equipos de medición no tienen una resolución infinita.

[ 138 ]

www.it­ebooks.info
Machine Translated by Google

Capítulo 5

El dominio digital es el de las computadoras. Debido a la codificación y al tamaño finito de la


memoria, las computadoras traducen valores analógicos/continuos en representaciones
digitales.

En un gráfico esto podría visualizarse de la siguiente manera:

Digital

Cosa análoga

Entradas y salidas de Arduino


Arduino posee entradas y salidas. También podemos distinguir pines analógicos y digitales.

Debes recordar los siguientes puntos:

• Arduino proporciona pines digitales que pueden ser tanto de entrada como de salida.

• Arduino solo proporciona entrada analógica, no salida.

Las entradas y salidas son pines proporcionados por la placa para comunicarse con periféricos
externos.

Las entradas proporcionan la capacidad de sentir el mundo.

Los resultados proporcionan la capacidad de alterar el mundo.

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.

Pero antes de manipularlo directamente, permítanme presentarles a un nuevo amigo llamado


Processing. Lo usaremos para ilustrar fácilmente nuestras pruebas de Arduino más adelante en el libro.

[ 139 ]

www.it­ebooks.info
Machine Translated by Google

Detección con entradas digitales

Presentando a un nuevo amigo – Procesando


Processing es un lenguaje de programación de código abierto y un entorno de desarrollo integrado (IDE)
para personas que desean crear imágenes, animaciones e interacción.

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.

Es un framework de programación muy utilizado por los no programadores. De hecho, ha sido


diseñado principalmente para este propósito. Uno de los primeros objetivos de Processing es
proporcionar una forma sencilla de programar para los no programadores mediante la gratificación
instantánea de la retroalimentación visual. De hecho, como sabemos, la programación puede ser
muy abstracta. Processing proporciona de forma nativa un lienzo en el que podemos dibujar, escribir y hacer
más. También proporciona un IDE muy fácil de usar que vamos a ver en el sitio web oficial en http://
processing.org.

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.

¿Es Processing un lenguaje?


Processing no es un lenguaje en el sentido estricto. Es un subconjunto de Java con algunas
bibliotecas externas y un IDE personalizado.

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.it­ebooks.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.

Vamos a instalarlo y ejecutarlo.


Al igual que el framework Arduino, el framework Processing no incluye un programa de instalación. Solo hay que
colocarlo en algún lugar y ejecutarlo desde allí.

La URL de descarga es: http://processing.org/download.

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.

En OS X, debes descomprimir el archivo zip y ejecutar el archivo resultante con el ícono:

Icono de procesamiento

Haz doble clic en el icono y verás una bonita pantalla de presentación:

[ 141 ]

www.it­ebooks.info
Machine Translated by Google

Detección con entradas digitales

Luego verás el IDE de Processing como se muestra en la siguiente imagen:

El IDE de Processing se parece a otros

Un IDE muy familiar


De hecho, el IDE de Processing se parece al de Arduino. El IDE de Processing es como el padre del IDE de
Arduino.

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.it­ebooks.info
Machine Translated by Google

Capítulo 5

Vamos a explorarlo y ejecutar un pequeño ejemplo:

1. Vaya a Archivos | Ejemplos básicos | Matrices | MatricesObjetos.

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:

Ejemplo nativo de ejecución de ArrayObjects en Processing

[ 143 ]

www.it­ebooks.info
Machine Translated by Google

Detección con entradas digitales

3. Ahora haz clic en el cuadrado pequeño (símbolo de parada). Sí, este nuevo patio de juegos es
muy familiar

Ejemplo de procesamiento IDE con ArrayObjects abierto

En la parte superior podemos ver algunos iconos familiares.

De izquierda a derecha son los siguientes:

• 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

para abrir un proyecto existente

[ 144 ]

www.it­ebooks.info
Machine Translated by Google

Capítulo 5

• Guardar proyecto (flecha hacia abajo): se utiliza para guardar un proyecto.


• Exportar aplicación (flecha derecha): se utiliza para crear una aplicación.

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.

Con Processing, tienes todo a mano para codificar, compilar y ejecutar.

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.

IDE alternativos y control de versiones


Si estás interesado en explorar alternativas a los IDE, te sugiero que utilices el entorno de desarrollo
de software universal y de código abierto Eclipse. Se lo recomiendo a todos los estudiantes que conozco
que quieran profundizar en los campos del desarrollo puro. Este potente IDE se puede configurar
fácilmente para que admita el control de versiones.

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://git­scm.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:

// algunas declaraciones / definiciones


int partículasNumber = 80; // número de partículas
float[] positionsX = new float[particlesNumber]; // almacenar partículas
Coordenadas X float[] positionsY = new float[particlesNumber]; // almacena las coordenadas Y de las
partículas

[ 145 ]

www.it­ebooks.info
Machine Translated by Google

Detección con entradas digitales

float[] radios = new float[partículasNumber]; radios // almacenar partículas

float[] easings = new float[particlesNumber]; cantidad de easing // almacenar partículas

// la configuración se ejecuta una vez al principio


configuración vacía() {
tamaño(600, 600); // define el patio de juegos
sin trazo(); // No definir trazo para todas las formas dibujadas

// 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

}
}

// el sorteo se ejecuta infinitamente


void dibujar() {
background(34); // define el color de fondo del patio de juegos

// almacenemos la posición actual del mouse


flotante objetivoX = ratónX; flotante
objetivoY = ratónY;

// bucle for en todas las partículas


para (int i=0 ; i < partículasNumber ; i++)
{

float dx = targetX ­ positionsX[i]; // Calcular la distancia X del ratón/partícula

si (abs(dx) > 1) { posición // si la distancia > 1, actualizar

posicionesX[i] += dx * facilitaciones[i];
}

flotante dy = objetivoY ­ posicionesY[i]; si (abs(dy) > 1) { // lo mismo para Y

posicionesY[i] += dy * facilitaciones[i];
}

[ 146 ]

www.it­ebooks.info
Machine Translated by Google

Capítulo 5

// cambia el color del lápiz para la partícula i fill(255 * i / particleNumber);

// 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.it­ebooks.info
Machine Translated by Google

Detección con entradas digitales

Puedes ver tres partes principales en tu código:

• Declaraciones/definiciones de variables

• La función setup() que se ejecuta solo una vez al principio

• La función draw() que se ejecuta infinitamente hasta que presionas detener

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.it­ebooks.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.

Arduino y algunos amigos del software

[ 149 ]

www.it­ebooks.info
Machine Translated by Google

Detección con entradas digitales

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.

¿Qué es un botón, un interruptor?


Un interruptor es un componente eléctrico que puede interrumpir un circuito eléctrico.
Hay muchos tipos diferentes de interruptores.

Diferentes tipos de interruptores


Algunos interruptores se denominan conmutadores de palanca. Los conmutadores de palanca también se denominan interruptores continuos.

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.

Otros se denominan momentáneos. Los momentáneos también se denominan pulsadores de acción .


Para actuar sobre el circuito, hay que pulsar y mantener pulsado el interruptor para que continúe la
acción. Si se suelta, la acción se detiene.

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.

Queremos encender el LED incorporado de la placa cuando presionamos el interruptor momentáneo


y apagarlo cuando lo liberemos.

[ 150 ]

www.it­ebooks.info
Machine Translated by Google

Capítulo 5

Arduino1

3V3 5V Venir

Fuerza
D13

Primera vez D12


Modulación por ancho de pulso (PWM)

ARÉF D11

Arduino
Modulación por ancho de pulso (PWM)

Yo ref. D10
Modulación por ancho de pulso (PWM)

CAROLINA DEL NORTE D9

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

Os presento el circuito sobre el que vamos a trabajar ahora mismo.


Este también es un buen pretexto para familiarizarte más con los diagramas de circuitos.

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.

El circuito en el mundo real Por supuesto, no quería

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.it­ebooks.info
Machine Translated by Google

Detección con entradas digitales

Puedes utilizar una resistencia de unos 10 Kohms. Explicaremos el propósito de la resistencia en las siguientes
páginas.

El interruptor momentáneo en un circuito real

Vamos a explicar las cosas un poco más.

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.it­ebooks.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.

Y esta resistencia, ¿por qué está aquí?

El concepto de pull­up y pull­down


Si bien el circuito global es sencillo, la parte de la resistencia puede resultar un poco complicada a primera vista.

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 pull­down. 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. Pull­down para que se reconozca de
manera más consistente como un valor BAJO, pull­up 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 pull­up 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.it­ebooks.info
Machine Translated by Google

Detección con entradas digitales

Esto es lo que debes recordar:

Tipo de entrada de pin digital Producción


Resistencia de tracción Resistencia pull­down Resistencia pull­up

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:

1. Define los pines.


2. Defina una variable para el estado actual del interruptor.

3. Configure el pin LED como salida.

4. Configure el pin del interruptor como entrada.

5. Crea un bucle infinito. En el bucle infinito, haz lo siguiente:

1. Lea el estado de entrada y guárdelo.

2. Si el estado de entrada es ALTO, encienda el LED.


3. De lo contrario, apague el LED.

El código
Aquí hay una traducción de este pseudocódigo en código C válido:

const int switchPin = 2; el interruptor // pin de la entrada digital relacionada con

constante int ledPin = 13; // pin del LED incorporado en la placa

int estado de conmutación = 0; // variable de almacenamiento para el interruptor actual


estado

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.it­ebooks.info
Machine Translated by Google

Capítulo 5

switchState = digitalRead(switchPin); // lee el estado del


pin digital 2

si (switchState == ALTO) { // prueba si el interruptor está presionado o


no

digitalWrite(ledPin, HIGH); // enciende el LED si está presionado actualmente

}
demás {
digitalWrite(ledPin, LOW); // apaga el LED si está presionado actualmente

}
}

Como de costumbre, también puedes encontrar el código en la carpeta Chapter05/MonoSwitch/ disponible


para descargar junto con otros archivos de código en el sitio de Packt Publishing.

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í.

Haciendo que Arduino y Processing hablen


Digamos que queremos visualizar las manipulaciones de nuestro interruptor en la computadora.

Tenemos que definir un pequeño protocolo de comunicación entre Arduino y Processing.


Por supuesto, utilizaremos un protocolo de comunicación en serie porque es bastante fácil de configurar y
es ligero.

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.it­ebooks.info
Machine Translated by Google

Detección con entradas digitales

De hecho, utilizaría una analogía básica con nuestro idioma. Para entendernos, tenemos que seguir algunas
reglas:

• Reglas sintácticas y gramaticales (tengo que usar palabras que conozcas)

• Reglas físicas (tengo que hablar lo suficientemente alto)

• Reglas sociales (no debo insultarte justo antes de preguntarte la hora)

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.

Requisitos del protocolo


¿Qué queremos hacer?

Necesitamos un protocolo de comunicación entre nuestro Arduino y Processing dentro de la computadora.


¡Correcto! Estos requisitos suelen ser los mismos para muchos de los protocolos de comunicación que diseñarás.

A continuación una breve lista de los más importantes:

• El protocolo debe ser ampliable sin tener que reescribir todo cada vez.
Es hora de agregar nuevos tipos de mensajes.

• El protocolo debe poder enviar suficientes datos con bastante rapidez.

• 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:

• Byte 1: número de interruptor

• Byte 2: estado del interruptor

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.

Puedo crear fácilmente una comunicación en serie entre la placa y la computadora.


De hecho, ya lo hicimos cuando usamos Serial Monitoring al menos en el
Lado de Arduino.

¿Cómo podemos hacer esto usando Processing?

[ 156 ]

www.it­ebooks.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.

Primero, como de costumbre, esbocemos un pseudocódigo.

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.

El pseudocódigo se puede crear de la siguiente manera:

1. Defina e instancia el puerto serie.

2. Defina un color de dibujo actual como oscuro.

3. En el bucle infinito, haga lo siguiente:

1. Verifique si se han recibido los datos del puerto serie y de captura.

2. Si los datos indican que el estado está desactivado, cambie el dibujo actual de color
a oscuro.

3. De lo contrario, cambie el color del dibujo actual a verde.

4. Dibuja el círculo con el color de dibujo actual.

Vamos a escribir ese código


Abramos un nuevo lienzo de procesamiento.

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.it­ebooks.info
Machine Translated by Google

Detección con entradas digitales

Puede encontrar el código en la carpeta Chapter05/processingOneButtonDisplay/


disponible para descargar junto con otros archivos de código en el sitio de Packt.

Cómo incluir una biblioteca en su código

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.*;

También puedes escribir esta declaración tú mismo.

A continuación el código, con muchos comentarios:

procesamiento de importación.serial.*;

Serial theSerialPort; int[] // crea el objeto del puerto serie


serialBytesArray = new int[2]; // matriz que almacena el mensaje actual
int estado del interruptor; // estado actual del interruptor
int ID del interruptor; // índice del conmutador

[ 158 ]

www.it­ebooks.info
Machine Translated by Google

Capítulo 5

int bytesCount = 0; a mensajes // número actual de bytes relativo

booleano init = falso; int fillColor = // estado inicial


40; // definiendo el color de relleno inicial

configuración vacía(){

// define algunos parámetros de lienzo y dibujo


tamaño(500,500);
fondo(70);
sin trazo();

// imprimir la lista de todos los dispositivos seriales (propósito de depuración)


println(Serie.lista());

// En OSX, el puerto Arduino es el primero en la lista.


Cadena thePortName = Serial.list()[0];

// Instantánea la comunicación serial


theSerialPort = new Serial(this, thePortName, 9600);
}

void dibujar(){

// establece el color de relleno


rellenar(colorDeRelleno);

// dibuja un círculo en el medio de la pantalla


elipse(ancho/2, alto/2, 230, 230);
}

void serialEvent(Serial myPort) {

// lee un byte del puerto serial


int inByte = miPuerto.read();

si (init == falso) { // si no hubiera habido el primer hola


si (inByte == 'Z') { // si el byte leído es Z
miPuerto.clear(); init = // limpia el buffer del puerto serial
verdadero; // almacenamos el hecho de que tuvimos el primero
Hola
miPuerto.write('Z'); //¡Dile al Arduino que envíe más!
}

[ 159 ]

www.it­ebooks.info
Machine Translated by Google

Detección con entradas digitales

} demás { // si ya hubo el primer hola

// Agrega el último byte del puerto serial a la matriz


serialBytesArray[bytesCount] = enByte;
bytesCount++;

// si el mensaje tiene una longitud de 2 bytes


si (bytesCount > 1) {
switchID = serialBytesArray[0]; // almacena el ID del conmutador
switchState = serialBytesArray[1]; // almacena el estado del conmutador

// imprimir los valores (para fines de depuración):


println(switchID + "\t" + switchState);

// modificar el color de relleno según el mensaje recibido de


Arduino
si (switchState == 0) fillColor = 40;
de lo contrario fillColor = 255;

// Envíe una Z mayúscula para solicitar nuevas lecturas del sensor


miPuerto.write('Z');

// 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.it­ebooks.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()

Definimos el lienzo (tamaño, color de fondo y sin trazo).

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.

Esta función setup() , por supuesto, sólo se ejecuta una vez.

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:

• coordenadas x del centro de la elipse (aquí ancho/2)



Coordenadas y del centro de la elipse (aquí altura/2)
• Ancho de la elipse (aquí 230)
• Altura de la elipse (aquí 230)

El ancho y el alto coloreados en azul en el IDE de Processing son el ancho y el alto


actuales del lienzo. Es muy útil usarlos porque si cambias el parámetro setup()
Declaración al elegir un nuevo tamaño para el lienzo, todo el ancho y la altura en su código se
actualizarán automáticamente sin necesidad de cambiarlos todos manualmente.

[ 161 ]

www.it­ebooks.info
Machine Translated by Google

Detección con entradas digitales

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().

La devolución de llamada serialEvent()


Hablamos sobre las devoluciones de llamadas en el Capítulo 4, Mejorar la programación con funciones,
matemáticas y tiempo.

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.

Se puede ilustrar de la siguiente manera:

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.

¿Qué pasa entonces?

Si la comunicación ya ha comenzado, tenemos que almacenar los bytes leídos en serialBytesArray


e incrementar el bytesCount. Mientras se reciben bytes y el bytesCount es menor o igual a 1, esto significa que
no tenemos un mensaje completo (un mensaje completo tiene dos bytes) y almacenamos más bytes en la
matriz.

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:

switchID = serialBytesArray[0]; switchState =


serialBytesArray[1];

[ 162 ]

www.it­ebooks.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.

El nuevo firmware Arduino listo para hablar


Como ahora tenemos una forma agradable de mostrar el estado de nuestro interruptor, eliminaré todo
lo relacionado con el LED incorporado de la placa y el siguiente es el resultado:

const int switchPin = 2; el interruptor // pin de la entrada digital relacionada con

int estado de conmutación = 0; // variable de almacenamiento para el interruptor actual


estado

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".

Aquí está el resultado, luego veremos las explicaciones:

const int switchPin = 2; el interruptor // pin de la entrada digital relacionada con

int switchState = 0; estado // variable de almacenamiento para el interruptor actual

int enByte = 0;

configuración vacía() {

[ 163 ]

www.it­ebooks.info
Machine Translated by Google

Detección con entradas digitales

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);

// envía el estado del interruptor a Arduino


Serial.write("0");
Serial.write(switchState);
}
}

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().

Esta función solo espera algo. Concéntrese en esto.

[ 164 ]

www.it­ebooks.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.

La consecuencia es que cuando puedes conectar tu placa, envía Z continuamente mientras


ejecutas tu programa de Processing. Entonces comienza la comunicación y puedes
presionar el interruptor y ver qué está sucediendo. De hecho, tan pronto como
comienza la comunicación, loop() comienza su bucle infinito. Al principio se realiza una
prueba en cada ciclo y solo probamos si se está recibiendo un byte. Cualquiera que sea el
byte recibido (Processing solo envía Z a la placa), leemos el pin digital del interruptor y
enviamos de vuelta dos bytes. Aquí también, presta atención: cada byte se escribe en el
puerto serie utilizando Serial.write(). Tienes que enviar 2 bytes, por lo que apilas dos
Serial.write(). El primer byte es el número (ID) del interruptor que se presiona/
liberado; aquí, no es una variable porque tenemos un único interruptor, por lo que es un entero 0. El
segundo byte es el estado del interruptor. Acabamos de ver aquí un bonito patrón de diseño que
involucra la placa, un programa externo que se ejecuta en una computadora y una comunicación
entre ambos.

Ahora, vayamos más allá y juguemos con más de un interruptor.

Jugando con varios botones


Podemos extrapolar nuestra lógica previamente diseñada con más de un interruptor.

Existen muchas formas de utilizar varios interruptores y, en general, varias entradas en


Arduino. Ahora vamos a ver una primera forma barata y sencilla. Esta forma no implica
multiplexar muchas entradas en solo un par de entradas de Arduino, sino un cableado
básico uno a uno en el que cada interruptor está conectado a una entrada. Aprenderemos
sobre multiplexación un poco más adelante (en el próximo capítulo).

[ 165 ]

www.it­ebooks.info
Machine Translated by Google

Detección con entradas digitales

El circuito
A continuación se muestra el diagrama del circuito necesario para trabajar con múltiples interruptores:

Cableado de tres interruptores momentáneos a la placa Arduino

El esquema es una extrapolación del anterior que mostraba solo un interruptor.


Podemos ver los tres interruptores entre los +5 V y las tres resistencias pull­down.
Luego también podemos ver los tres cables yendo a las entradas digitales 2 a 4 nuevamente.

Aquí hay una pequeña actualización de memoria: ¿Por qué no utilicé los pines digitales 0 o 1?

[ 166 ]

www.it­ebooks.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 pull­down y la placa Arduino.

Ambos códigos fuente deben modificarse para proporcionar soporte para el nuevo circuito.

Agreguemos cosas allí.

[ 167 ]

www.it­ebooks.info
Machine Translated by Google

Detección con entradas digitales

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:

#define switchesNumber 3 // define el número de conmutadores


como una constante

int switchesStates[switchesNumber] ; // matriz que almacena los interruptores actuales


Estados

int enByte = 0;

vacío configuración()
{ Serial.begin(9600);

// iniciando cada pin como entrada y llenando switchesStates con


ceros
para (int i = 0; i < numeroDeCambios; i++) {

// TENGA CUIDADO CON ESE ÍNDICE


pinMode(i + 2, INPUT); // el pin del interruptor está configurado como entrada

cambiaEstados[i] = 0 ;
}

sayHello(); // esperando la respuesta del hola del programa de procesamiento


}

bucle vacío(){

// Si se recibe un byte válido del procesamiento, lea todas las entradas digitales. if (Serial.available() > 0) {

// obtener el byte entrante inByte =


Serial.read();

para (int i = 0; i < numeroDeCambios; i++) {

switchesStates[i] = digitalRead(i+2); // TEN CUIDADO CON ESO


ÍNDICE

// ¡EMPEZAMOS DESDE EL PIN 2!

[ 168 ]

www.it­ebooks.info
Machine Translated by Google

Capítulo 5

serie.write(i); // 1er byte = número de interruptor (0


a 2)
Serial.write(switchesStates[i]); // 2do byte = el conmutador i
estado

}
}
}

void decirhola() {
mientras (Serial.available() <= 0) {
Serial.print('Z'); // envía una Z mayúscula a Arduino para decir
"¡HOLA!"

retraso(200);
}
}

Vamos a explicar este código.

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().

Ahora, actualicemos también el código de procesamiento.

[ 169 ]

www.it­ebooks.info
Machine Translated by Google

Detección con entradas digitales

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

switchID; int[] switchesStates = new int[switchesNumber]; // estado actual del conmutador

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

// los círculos muestran cosas int


distanceCircles; int radios;

configuración vacía() {

// define algunos parámetros de lienzo y dibujo size(500, 500);

fondo(70); noStroke();
distanciaCirculos
= ancho / switchesNumber; radios = distanciaCirculos/2;

// imprimiendo la lista de todos los dispositivos seriales (propósito de depuración)


println(Serial.list());

// En osx, el puerto Arduino es el primero en la lista String thePortName = Serial.list()[0];

// Instanciar la comunicación en serie theSerialPort = new


Serial(this, thePortName, 9600);

para (int i = 0; i < switchesNumber; i++) {

cambiaEstados[i] = 0;

[ 170 ]

www.it­ebooks.info
Machine Translated by Google

Capítulo 5

}
}

void dibujar() {

para (int i = 0; i < switchesNumber; i++)


{
si (cambiaEstados[i] == 0) rellenar(0);
de lo contrario rellenar(255);

// dibuja un círculo en el medio de la pantalla


elipse(distanciaCírculos * (i + 1) ­ radios, altura/2, radios, radios);

}
}

void serialEvent(Serial myPort) {

// lee un byte del puerto serial


int inByte = miPuerto.read();

si (init == falso) { // si este es el primer hola


si (inByte == 'Z') { myPort.clear(); // si el byte leído es Z
init = true; // limpia el buffer del puerto serial
// almacenamos el hecho de que tuvimos el primero
Hola
miPuerto.write('Z'); //¡Dile al Arduino que envíe más!
}
}
demás { // si ya hubo el primer hola

// Agrega el último byte del puerto serial a la matriz


serialBytesArray[bytesCount] = enByte;
bytesCount++;

// si el mensaje tiene una longitud de 2 bytes


si (bytesCount > 1) switchID = {
serialBytesArray[0]; cambiar // almacena el ID del

switchesStates[switchID] = serialBytesArray[1]; // almacena el estado del conmutador

// imprimir los valores (para fines de depuración):


println(switchID + "\t" + switchesStates[switchID]);

[ 171 ]

www.it­ebooks.info
Machine Translated by Google

Detección con entradas digitales

// Envíe una Z mayúscula para solicitar nuevas lecturas del sensor


miPuerto.write('Z');

// 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:

Entonces ¿qué cambié?

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.it­ebooks.info
Machine Translated by Google

Capítulo 5

También transformé la variable switchState en una matriz de enteros switchesStates.


Esta almacena todos los estados de los interruptores. Agregué dos variables relacionadas con la
visualización: distanceCircles y radii. Se utilizan para mostrar dinámicamente la posición de los círculos
según la cantidad de interruptores. De hecho, queremos un círculo por interruptor.

La función setup() es casi la misma que antes.

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.

Entendiendo el concepto de rebote


A continuación presentamos una pequeña sección que es bastante interesante y liviana en comparación con las entradas
analógicas, en las que profundizaremos en el próximo capítulo.

Vamos a hablar de algo que sucede cuando alguien presiona un botón.

¿Qué? ¿Quién está rebotando?


Ahora tenemos que usar nuestros ojos biocibernéticos microscópicos para hacer zoom en el
Estructura del conmutador.

[ 173 ]

www.it­ebooks.info
Machine Translated by Google

Detección con entradas digitales

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:

¿Cómo podemos afrontar estas oscilaciones?

Cómo eliminar el rebote


Disponemos de dos elementos diferenciados sobre los que podemos actuar:

• El circuito en sí

• El firmware

[ 174 ]

www.it­ebooks.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.

El firmware también se puede modificar.

Básicamente, podemos utilizar un filtro basado en el tiempo, porque el rebote ocurre durante
un período de tiempo particular.

A continuación el código, luego vendrán las explicaciones:

const int switchPin = 2; el interruptor // pin de la entrada digital relacionada con

constante int ledPin = 13; // pin del LED incorporado en la placa

int estado de conmutación = 0; // variable de almacenamiento para el interruptor actual


estado
int lastSwitchState= BAJO;

// variables relacionadas con el sistema antirrebote


largo lastDebounceTime = 0;
largo debounceDelay = 50;

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(){

// lee el estado del pin digital


int lecturaInput = digitalRead(switchPin);

// si el estado recién leído es diferente del último valor sin rebotes


si (leerEntrada != lastSwitchState){
// restablece el contador de rebotes almacenando el tiempo de actividad actual en ms
lastDebounceTime = milisegundos();
}

// si el tiempo transcurrido desde el último rebote es mayor que el retraso del rebote

si ( (millis() ­ lastDebounceTime) > debounceDelay ){

[ 175 ]

www.it­ebooks.info
Machine Translated by Google

Detección con entradas digitales

// almacena el valor porque es un valor sin rebote y estamos seguros


switchState = leerInput;
}

// almacena el último estado leído para el próximo propósito de comparación de bucle


lastSwitchState = leerEntrada;

// modificar el estado del LED según el estado del interruptor


si (switchState == ALTO)
{ // prueba si el interruptor está presionado o no

digitalWrite(ledPin, HIGH); // enciende el LED si está presionado actualmente

}
demás

{
digitalWrite(ledPin, LOW); // apaga el LED si está presionado actualmente

}
}

A continuación se muestra un ejemplo del ciclo antirrebote.

Al principio definí algunas variables:

• lastSwitchState: almacena el último estado leído


• lastDebounceTime: almacena el momento en el que se produjo el último rebote.

• 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.

Entonces leo la entrada en cada ciclo y la guardo en readInput. Comparo readInput


a la variable lastSwitchState que es el último valor leído. Si ambas variables son diferentes, ¿qué
significa? Significa que se produce un cambio, pero puede ser un rebote (evento no deseado) o un
push real. De todas formas, en ese caso, reiniciamos el contador poniendo el tiempo actual
proporcionado por millis() en lastDebounceTime.

[ 176 ]

www.it­ebooks.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.

Este método es un concepto general utilizado para suavizar las entradas.

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.it­ebooks.info
Machine Translated by Google

www.it­ebooks.info
Machine Translated by Google

Sentir el mundo: sentir con entradas


analógicas
El mundo real no es digital. Mi visión basada en el arte digital me muestra Matrix detrás de las
cosas y enormes cascadas digitales entre ellas. Sin embargo, en este capítulo necesito
transmitirles la relación entre lo digital y lo analógico, y necesitamos
Entiendolo bien.

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.it­ebooks.info
Machine Translated by Google

Sentir el mundo: sentir con entradas analógicas

Detección de entradas analógicas y valores continuos No hay mejor forma de


definir lo
analógico que comparándolo con lo digital. Acabamos de hablar de las entradas
digitales en el capítulo anterior, y ahora conoces bien los únicos dos valores que
pueden leer ese tipo de entradas. Es un poco agotador escribirlo, y me disculpo
porque esto es de hecho más una restricción del procesador que una limitación pura
de la entrada. Por cierto, el resultado es que una entrada digital solo puede proporcionar
0 o 1 a nuestro firmware binario ejecutado.

El funcionamiento analógico es totalmente diferente. De hecho, las entradas analógicas pueden


proporcionar valores variables de forma continua midiendo la tensión de 0 V a 5 V. Esto significa
que un valor de 1,4 V y otro valor de 4,9 V se interpretarían como valores totalmente diferentes.
Esto es muy diferente de una entrada digital que podría interpretarlos como... 1. De hecho, como
ya vimos, un valor de tensión mayor que 0 se entiende normalmente como 1 por las entradas
digitales. 0 se entiende como 0, pero 1,4 se entendería como 1; esto lo podemos entender como
ALTO, el valor ON, en contraposición al OFF, que proviene de la medida de 0 V.

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.

¿Cuántos valores podemos distinguir?


El término "mucho" no es preciso. Aunque nos encontramos en un nuevo campo de medida continuo,
seguimos en el mundo digital, el de los ordenadores. ¿Cuántos valores se pueden distinguir por
las entradas analógicas de Arduino? 1024.

¿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ógico­digital, alojado
dentro del propio chipset, es exactamente ese. Este dispositivo también se conoce con el acrónimo
ADC.

[ 180 ]

www.it­ebooks.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.

Veamos cómo podemos utilizar estas valiosas entradas con Arduino.

Lectura de entradas analógicas


Como ahora estamos más familiarizados con los circuitos y el código, podemos trabajar con un proyecto
pequeño y, al mismo tiempo, explicar los conceptos. Voy a describir un ejemplo sencillo de circuitos
y código utilizando solo un potenciómetro .

El verdadero propósito del potenciómetro


En primer lugar, vamos a coger un potenciómetro. Un potenciómetro es, si recuerdas correctamente el
primer capítulo de este libro, una resistencia variable.

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

Aquí, V es el voltaje en voltios, R la resistencia en ohmios e I la corriente en amperios.

Así que ahora, para definir el propósito de un potenciómetro:

El potenciómetro es su manera de cambiar continuamente una


variable en su código en ejecución desde el mundo físico.

Recuerde siempre:
¡Utilice una resolución de 10 bits y será el maestro de las entradas analógicas!

[ 181 ]

www.it­ebooks.info
Machine Translated by Google

Sentir el mundo: sentir con entradas analógicas

Cambiar el retardo de parpadeo de un LED con


un potenciómetro
La siguiente figura es el circuito más básico para ilustrar el concepto de entradas analógicas con la placa
Arduino:

Un potenciómetro conectado a la placa Arduino

Consulte el esquema eléctrico correspondiente para ver las conexiones:

Arduino1

3V3 5V Venir
Fuerza
D13

Primera vez D12

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)

CAROLINA DEL NORTE D9

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

Modulación por ancho de pulso (PWM)

A1 D3

A2 D2
Tejas
A3 D1
Recepción

A4 D0

A5 LCC

Adventista del Séptimo Día

Tierra

La entrada analógica 0 mide el voltaje.

[ 182 ]

www.it­ebooks.info
Machine Translated by Google

Capítulo 6

Ahora veamos el código que tenemos que utilizar.

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

digitalWrite(ledPin, HIGH); delay(potValue); // enciende el LED


milisegundo // pausa el programa durante potValue

digitalWrite(ledPin, LOW); delay(potValue); //apaga el LED


milisegundo // pausa el programa durante potValue

Sube el código. Luego gira un poco el potenciómetro y observa el resultado.

Después de la definición de la variable, defino el pin ledPin como salida en setup()


función para poder enviar corriente a este pin. En realidad, estoy usando el pin 13 para simplificar nuestras
pruebas. No olvides que el pin 13 es el LED montado en la superficie de la placa Arduino.

Entonces, la magia sucede en la función loop() .

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.it­ebooks.info
Machine Translated by Google

Sentir el mundo: sentir con entradas analógicas

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.

Cuanto mayor sea el valor, mayor será el retraso.

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.

¿Cómo convertir el Arduino en un voltímetro de bajo


voltaje?
Para medir el voltaje se necesitan dos puntos diferentes en un circuito. De hecho, un voltaje es un potencial
eléctrico. Aquí, tenemos (solo) ese pin analógico involucrado en nuestro circuito para medir el voltaje.
¡¿Qué es eso?!

¡Sencillo! Usamos la fuente de +5 V de Vcc como referencia. Controlamos la resistencia


proporcionada por el potenciómetro y suministramos el voltaje desde el pin Vcc para tener algo que demostrar.

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?

Así es como funciona:

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:

V = 5 * (valor de analogRead() / 1023)

[ 184 ]

www.it­ebooks.info
Machine Translated by Google

Capítulo 6

Vamos a implementarlo y visualizarlo en nuestra computadora usando el monitor serial del


IDE de Arduino:

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

float voltageValue = 0.; // variable que almacena el voltaje calculado

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

digitalWrite(ledPin, HIGH); delay(potValue); // enciende el LED


milisegundo // pausa el programa durante potValue

digitalWrite(ledPin, LOW); delay(potValue); //apaga el LED


milisegundo // pausa el programa durante potValue

voltageValue = 5. * (potValue / 1023.) ; // calcula el voltaje

Serial.println(voltageValue); // escribe el valor del voltaje


retorno de carro
}

El código es casi el mismo que el código anterior.

Agregué una variable para almacenar el voltaje calculado. También agregué el


componente de comunicación serial, que se ve todo el tiempo: Serial.begin(9600) para crear una
instancia de la comunicación serial y Serial.println() para escribir el valor de voltaje calculado
actual en el puerto de comunicación serial, seguido de un retorno de carro.

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.it­ebooks.info
Machine Translated by Google

Sentir el mundo: sentir con entradas analógicas

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.

Nuevamente fue un ejemplo porque quería señalarles la precisión/


Concepto de resolución. Debes conocerlo y tenerlo en cuenta. Será muy importante y podría
dar resultados extraños en algunos casos. Al menos, estás advertido.

Descubramos otra forma interesante de interactuar con la placa Arduino.

Presentamos Max 6, el marco de


programación gráfica
Ahora, déjame presentarte el marco conocido como Max 6. Este es todo un universo en sí
mismo, pero quería escribir algunas páginas sobre él en este libro porque probablemente te
encontrarás con él en tus proyectos futuros; tal vez seas un Max 6.
Desarrollador algún día, como yo, o tal vez tendrás que interconectar tus objetos físicos
inteligentes con sistemas basados en Max 6.

[ 186 ]

www.it­ebooks.info
Machine Translated by Google

Capítulo 6

El siguiente es uno de los parches de mi proyecto de universo 3D con Max 6:

Una breve historia de Max/MSP


Max es un lenguaje de programación visual para fines multimedia. En realidad, fue
desarrollado y mantenido por Cycling '74. ¿Por qué se llama Max? Recibió su nombre
en honor a Max Matthews (http://en.wikipedia.org/wiki/Max_Mathews), uno de los grandes
pioneros de la música por computadora.

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.it­ebooks.info
Machine Translated by Google

Sentir el mundo: sentir con entradas analógicas

Alrededor de 1997, se añadió un módulo completo dedicado al procesamiento y generación de sonido,


llamado MSP, por Max Signal Processing y, al parecer, por las iniciales de Miller S. Puckette.

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.

Y la actualización más grande, en mi humilde opinión, lanzada en noviembre de 2011 como


Max 6, incluyó Jitter de forma nativa y proporcionó enormes mejoras como:

• Una interfaz de usuario rediseñada

• Un nuevo motor de audio compatible con sistemas operativos de 64 bits

• Características de diseño de filtro de sonido de alta calidad.


• Una nueva estructura de datos

• Nuevo manejo de movimiento para modelos 3D

• Nuevo manejo de materiales 3D


• La extensión Gen

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.

Ahora, entendamos un poco más qué es Max.

[ 188 ]

www.it­ebooks.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í.

¿Qué es un marco de programación gráfica?


Un marco de programación gráfica es un lenguaje de programación que proporciona a los usuarios
una forma de crear programas manipulando elementos gráficamente en lugar de escribir texto.

Por lo general, los lenguajes de programación gráfica también se denominan lenguajes de


programación visual, pero utilizaré "gráfico" porque, para muchos, "visual" se utiliza para el producto
renderizado por los frameworks; me refiero a la escena 3D, por ejemplo. Gráfico está más relacionado
con GUI, es decir, la interfaz gráfica de usuario, que es, desde el punto de vista del desarrollador,
nuestra interfaz de edición (me refiero a la parte IDE).

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.

En Max, la arquitectura de software global, que es un sistema de objetos conectados y relacionados


en nuestra pantalla 2D, se denomina Patch . Por cierto, otros marcos de programación gráfica
también utilizan este término.

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.

Puedo citar otros programas de programación gráfica importantes en nuestro campo:

• Quartz Composer: es un marco de renderizado gráfico para OS X y está disponible en https://


developer.apple.com/technologies/mac/
gráficos­y­animaciones.html

• Reaktor: Este es un marco de procesamiento MIDI y DSP de Native


Los instrumentos están disponibles en http://www.native­instruments.com/#/
es/productos/productor/reaktor­5

• 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.it­ebooks.info
Machine Translated by Google

Sentir el mundo: sentir con entradas analógicas

• vvvv: Esta es una herramienta de síntesis de video en tiempo real para Windows y está disponible en
http://vvvv.org

• SynthMaker: Este es un diseño de dispositivo VST para Windows y está disponible en


http://synthmaker.co.uk

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

Max, para el patio de recreo


Max es el área de juegos y la estructura central en la que se colocará, depurará y mostrará todo. Es el
lugar donde se colocan los objetos, se los conecta, se crea una interfaz de usuario (UI) y también
se proyecta una representación visual.

[ 190 ]

www.it­ebooks.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:

Un pequeño y sencillo parche para el sistema de cálculo con Max 6

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.

El cuadro con el número 17 en su interior es un numbox. Contiene un número entero y también


es un objeto de interfaz de usuario, lo que proporciona una forma sencilla de cambiar el valor
arrastrando y soltando con el ratón. A continuación, conecta la salida de un objeto a la
entrada de otro. Ahora, cuando cambia el valor, se envía a través del cable al objeto conectado
a los numboxes. ¡Mágico!

Ves otros dos objetos. Uno con:

• Signo + dentro seguido del número 5



­ cartel en el interior seguido del número 3

Cada uno toma el número que le envían y hace el cálculo de + 5 y ­ 3 respectivamente.

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.it­ebooks.info
Machine Translated by Google

Sentir el mundo: sentir con entradas analógicas

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:

• API de JavaScript para Max en sí y partes específicas, como Jitter, también

• 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.

Revisemos los otros módulos.

[ 192 ]

www.it­ebooks.info
Machine Translated by Google

Capítulo 6

MSP, para sonido


Mientras que los objetos Max se comunican enviando mensajes activados por el usuario o por el propio
programador, MSP es el motor central que calcula las señales en cualquier instante particular, como
está escrito en la documentación.

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.it­ebooks.info
Machine Translated by Google

Sentir el mundo: sentir con entradas analógicas

La velocidad de la señal depende de la frecuencia de muestreo de audio y de algunos parámetros oscuros


en la ventana de configuración principal de MSP. No voy a describir eso, pero debes saber que Max
generalmente proporciona, de forma predeterminada, parámetros relacionados con tu tarjeta de sonido, que
incluyen la frecuencia de muestreo (44110 Hz, la frecuencia de muestreo estándar para CD de audio, significa
una velocidad de procesamiento rápida de 44100 veces por segundo para cada canal de audio).

La ventana Estado de audio es el lugar donde se configuran algunos parámetros importantes de MSP

Jitter, para elementos visuales


Jitter es el motor principal para todo lo relacionado con el procesamiento y la síntesis visual en Max 6.

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.it­ebooks.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 Jitter­core 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.it­ebooks.info
Machine Translated by Google

Sentir el mundo: sentir con entradas analógicas

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.

Gen, por un nuevo enfoque para la generación de código


Si entendieran que detrás de nuestros parches hay algún tipo de compilación/ejecución, les decepcionaría
diciendo que no funciona así. Incluso si todo funciona en tiempo real, no hay una compilación real.

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 es un concepto totalmente nuevo.

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.it­ebooks.info
Machine Translated by Google

Capítulo 6

También funciona para Jitter con tres objetos Max principales:

• 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/en­us/library/bb509635(v=VS.85).aspx) o Nvidia Cg (http://http.
developer.nvidia.com/CgTutorial/cg_tutorial_chapter01.html), Gen es tu amigo.

Todos los parches basados en jit.gl.pix se compilan y envían específicamente para su


ejecución basada en GPU.

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.it­ebooks.info
Machine Translated by Google

Sentir el mundo: sentir con entradas analógicas

Resumiendo todo en una tabla


Todo lo relacionado con Max 6 está en el sitio web de Cycling 74 en http://cycling74.
com. Además, casi el 99 por ciento de la documentación también está en línea, en http://
Cycling74.com/docs/max6/dynamic/c74_docs.html#docintro.

La siguiente tabla resume todo lo que hemos hecho hasta ahora:

Partes ¿Qué? Color del cable Signo distintivo

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

Rayas azules y negras para cables


de mapas de píxeles
Gen Parches específicos (relacionados con Al igual que MSP para ¡Muy muy rápido!
DSP y procesamiento de
gen~ y Jitter para jit.gen, jit.
matriz y textura) compilados sobre la marchapix y jit.gl.pix

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).

Deberías ver un patio de juegos vacío

[ 198 ]

www.it­ebooks.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.

El secuenciador basado en ruido

[ 199 ]

www.it­ebooks.info
Machine Translated by Google

Sentir el mundo: sentir con entradas analógicas

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.

Espera, déjame mostrarte cómo se ve.

Simplemente seleccioné todos los objetos en mi parche y fui a Editar | Copiar comprimido.

La función de copia comprimida

[ 200 ]

www.it­ebooks.info
Machine Translated by Google

Capítulo 6

Y la siguiente figura es el resultado de pegar directamente en un archivo de texto.

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.

Código comprimido y copiado

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).

Reproducir sonidos con el parche


Como puedes ver, puse algunos comentarios en el parche. Puedes seguirlos para producir algunos
sonidos electrónicos desde tu computadora.

[ 201 ]

www.it­ebooks.info
Machine Translated by Google

Sentir el mundo: sentir con entradas analógicas

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.

Hagámoslo con el mismo circuito que diseñamos anteriormente.

[ 202 ]

www.it­ebooks.info
Machine Translated by Google

Capítulo 6

Controlar software mediante hardware


Al venir de ámbitos puramente digitales donde todo se puede agrupar en software y mundos
virtuales, a menudo necesitamos interfaces físicas. Esto puede parecer una paradoja: queremos que
todo esté en un solo lugar, pero ese lugar es tan pequeño y poco amigable para todo lo
relacionado con la creación y los sentimientos puros que necesitamos interfaces externas (físicas)
más o menos grandes. Me encanta esta paradoja.

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.

Mejorando el secuenciador y conectando el Arduino

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.

Conectemos el Arduino al Max 6


Arduino puede comunicarse mediante el protocolo serial. Ya lo hicimos. Nuestro último firmware ya
lo hace, enviando el valor de voltaje.

[ 203 ]

www.it­ebooks.info
Machine Translated by Google

Sentir el mundo: sentir con entradas analógicas

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

Serial.println(potValue); // escribe el valor de voltaje en un carro


devolver

delay(2); de uso // esta pequeña pausa espera a que el ADC se estabilice.


frecuente

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.

El objeto serial en Max 6


Hay un objeto Max llamado serial. Proporciona una forma de comunicarse mediante un puerto serial
con cualquier otro tipo de dispositivo que utilice comunicación serial.

La siguiente figura describe el nuevo parche Max 6 incluida la parte necesaria para
comunicarse con nuestro pequeño controlador de hardware.

Ahora, conectemos el Arduino, si aún no lo hemos hecho, y carguemos el firmware maxController .

[ 204 ]

www.it­ebooks.info
Machine Translated by Google

Capítulo 6

Tenga cuidado de desactivar la monitorización en serie para el IDE.


De lo contrario, se produciría un conflicto en su computadora; solo se puede
instanciar una comunicación serial en un puerto.

Luego hay otro parche que puedes encontrar, también en la carpeta Chapter06/ , con el nombre
Patcher005_Arduino.maxpat.

El parche Max que incluye el módulo de comunicación Arduino

Haga doble clic en el archivo y verá este parche.

Vamos a describirlo un poco. Agregué todo en verde y naranja.

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.

Describamos ambas partes, empezando por los ayudantes.

[ 205 ]

www.it­ebooks.info
Machine Translated by Google

Sentir el mundo: sentir con entradas analógicas

Rastreo y depuración fáciles en Max 6


Max 6 ofrece muchas formas de depurar y rastrear cosas. No las describiré todas en este libro de
Arduino, pero algunas requieren algunas palabras.

Revisa tu parche, especialmente los objetos de color naranja.

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.

Vamos a utilizar este sistema de rastreo en unos minutos.

Comprender los mensajes de Arduino en Max 6


Lo que se necesita entender es que el conmutador anterior ahora también está conectado a un nuevo
objeto qmetro . Este es el equivalente de metro de baja prioridad . De hecho, este sondeará el objeto
serial cada 20 ms y, considerando cómo funciona actualmente el firmware de nuestro Arduino enviando
el valor analógico leído en cada vuelta del bucle, incluso si este sondeo se retrasa un poco, no importará; en
la siguiente vuelta, se producirá la actualización.

El objeto serial es el importante aquí.

He codificado de forma rígida algunos parámetros relacionados con la comunicación serial con Arduino:

• 9600 establece el reloj en 9600 baudios

• 8 establece la longitud de la palabra en 8 bits

• 1 significa que hay un bit de parada



0 significa que no hay paridad (la paridad a veces es útil para comprobar errores)

[ 206 ]

www.it­ebooks.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 .

Lea directamente la información de ayuda de cualquier


objeto en Max 6 presionando la tecla Alt en su teclado y
luego haciendo clic en el objeto.

El parche de ayuda del objeto serial

Cada 20 ms, si se ha instanciado la comunicación serial, el objeto serial proporcionará lo que


será enviado por Arduino, el valor analógico actual y más recientemente leído del pin donde
está conectado el potenciómetro. Este valor va de 0 a 1023, estoy usando un objeto de
escala como lo hice con el objeto zmap para la parte secuenciador/sonido del parche. Este
objeto de escala reformula la escala de valores de 0 a 1023 en la entrada a un rango invertido
de 300 a 20, dejando que el rango vaya en dirección opuesta (tenga cuidado, parcheadores
Max actuales y futuros, zmap no se comporta así). Hice eso para definir el rango máximo
de la tasa de notas por minuto. El objeto expr calcula esto. qmetro necesita el intervalo entre
dos golpes. Estoy haciendo que esto varíe entre 400 ms y 20 ms mientras giro mi
potenciómetro. Luego, calculo la tasa de notas por minuto y la muestro en otro objeto de
UI de flonum .

[ 207 ]

www.it­ebooks.info
Machine Translated by Google

Sentir el mundo: sentir con entradas analógicas

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.

La referencia correspondiente en Max es la letra c de mi computadora. Esta es solo una referencia


interna.

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.it­ebooks.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.

¿Qué es lo que realmente se envía por cable?


Habrás notado que, como es habitual, mencioné la serie de objetos: select, zl,
itoa y fromsymbol. Ha llegado el momento de explicarlos.

[ 209 ]

www.it­ebooks.info
Machine Translated by Google

Sentir el mundo: sentir con entradas analógicas

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.

El objeto serial genera una extraña serie de números.

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.

Arduino transmite sus valores como ASCII, exactamente como si los


estuviéramos escribiendo en nuestro ordenador.

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

• 13 significa un retorno de carro


• 10 significa salto de línea, lo que a su vez significa nueva línea.

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.it­ebooks.info
Machine Translated by Google

Capítulo 6

Entonces parece que mi Arduino envió un mensaje como este:


350<CR><LF>

Aquí, <CR> y <LF> son caracteres de retorno de carro y nueva línea.

Si hubiera utilizado la función Serial.print() en lugar de Serial.println(), no habría obtenido el mismo


resultado. De hecho, la versión Serial.print() no agrega el <CR>
y los caracteres <NL> al final de un mensaje. ¿Cómo podría haber sabido si 3, 5 o 0 sería el primer
carácter si no tenía un marcador de fin?

El patrón de diseño a tener en cuenta es el siguiente:

• Construir el mensaje
• Envíe el mensaje después de que esté completamente construido (usando Serial.println())
función.)

Si deseas enviarlo mientras lo construyes, esto es lo que puedes usar:

• Envíe el primer byte utilizando Serial.print()


• Envíe el segundo byte utilizando Serial.print()
• Continuar enviando hasta el final

• Envíe el <CR><LF> al final utilizando Serial.println() sin argumentos

¿Extraer sólo la carga útil?


En muchos campos relacionados con la comunicación, hablamos de carga útil. Esto es el mensaje,
el propósito de la comunicación en sí. Todo lo demás es muy importante, pero se puede entender
como un portador; sin estas señales y semáforos, el mensaje no podría viajar. Sin embargo, nos
interesa el mensaje en sí.

Necesitamos analizar el mensaje que proviene del objeto serial.

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.

Esto se hace con los objetos select y zl .

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.it­ebooks.info
Machine Translated by Google

Sentir el mundo: sentir con entradas analógicas

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.

Aquí, si marcamos el interruptor correspondiente y observamos la ventana Max, podemos ver


51 53 48 repetido varias veces y enviado por el objeto zl .

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.

El procesador de listas zl genera una serie de números enteros

Conversiones y símbolos ASCII


Ahora tenemos una serie de tres números enteros que equivalen directamente al mensaje ASCII
enviado por el Arduino, en mi caso, 51 53 48.

Si giras el potenciómetro, cambiarás esta serie, por supuesto.

[ 212 ]

www.it­ebooks.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).

Verifique el interruptor relacionado y observe la ventana Máx.

Aquí está nuestro valor importante

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.

"350" no equivale exactamente a 350

[ 213 ]

www.it­ebooks.info
Machine Translated by Google

Sentir el mundo: sentir con entradas analógicas

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.

Este largo ejemplo te enseñó dos cosas principales:

• Hay que saber con cuidado lo que se envía y se recibe.


• Cómo se comunica un Arduino

Ahora, pasemos a algunos otros ejemplos relacionados con las entradas analógicas.

Jugando con sensores


Lo que no quiero escribir en este libro es un gran catálogo. En lugar de eso, quiero darles las claves y
la sensación de todos los conceptos. Por supuesto, tenemos que ser precisos y aprender sobre
técnicas particulares que no inventaron ustedes mismos, pero sobre todo quiero que aprendan las
mejores prácticas, que piensen en grandes proyectos por sí mismos y que sean capaces de tener una
visión global.

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.

Solía jugar con un sensor infrarrojo de largo alcance Sharp GP2Y0A02YK.

[ 214 ]

www.it­ebooks.info
Machine Translated by Google

Capítulo 6

El sensor infrarrojo de la familia Sharp GP2Y0A

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.

La hoja de datos es el primer objeto a tener en cuenta.

¿Está leyendo una hoja de datos?


En primer lugar, tienes que encontrar la hoja de datos. Un motor de búsqueda puede resultar de gran
ayuda. La hoja de datos de este sensor se encuentra en http://sharp­world.com/products/devvice/lineup/data/pdf/
hoja de datos/gp2y0a02_e.pdf.

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!

Generalmente, en la primera página tienes todas las características resumidas.

[ 215 ]

www.it­ebooks.info
Machine Translated by Google

Sentir el mundo: sentir con entradas analógicas

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.

Relación matemática entre la distancia y el voltaje de salida analógico del sensor

Esta información es muy valiosa. De hecho, como ya comentamos en el capítulo


anterior, un sensor convierte un parámetro físico en algo medible mediante Arduino (o
cualquier otro tipo de equipo). En este caso, una distancia se convierte en un voltaje.

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.it­ebooks.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.

Si el voltaje de salida aumenta, la distancia disminuye siguiendo una especie de función


exponencial. En algún momento estuve en contacto con algunos ingenieros de Sharp y
confirmaron mis ideas sobre el tipo de fórmula, proporcionándome esto:

(a + bV)
D=
2
(1 + cV + dV )

Aquí, D es la distancia en centímetros y V el voltaje medido; y a = 0,008271, b = 939,65, c =


­3,398 y d = 17,339

Esta fórmula se incluirá en la lógica de Arduino para que proporcione directamente la


distancia a cualquiera que quiera saberla. También podríamos hacer este cálculo en el
otro lado de la cadena de comunicación, en un parche de Max 6, por ejemplo, o incluso en
Processing. De cualquier manera, querrá asegurarse de que los datos del parámetro de
distancia se ajusten bien al comparar la salida del sensor con la entrada.
Dónde se utilizarán dichos datos.

Vamos a cablear cosas


Este próximo circuito te recordará mucho al anterior. De hecho, el sensor de rango reemplaza
al potenciómetro, pero está cableado exactamente de la misma manera:

• El Vcc y tierra de la placa Arduino conectados respectivamente a +5 V


y tierra
• Las patas de señal conectadas a la entrada analógica 0

El sensor Sharp conectado a la placa Arduino


[ 217 ]

www.it­ebooks.info
Machine Translated by Google

Sentir el mundo: sentir con entradas analógicas

El diagrama del circuito es el siguiente:

Arduino1

3V3 5V Venir
Fuerza
D13

Primera vez D12

ARÉF D11
Modulación por ancho de pulso (PWM)

Yo ref. Arduino D10


Modulación por ancho de pulso (PWM)

D9
Modulación por ancho de pulso (PWM)

CAROLINA DEL NORTE

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

Adventista del Séptimo Día

Tierra

El rango del sensor lo suministra el propio Arduino y envía voltaje a la entrada analógica 0

Codificación del firmware


El siguiente código es el firmware que diseñé:

int sensorPin = 0; // número de pin donde está conectado el SHARP GP2Y0A02YK

int sensorValue = 0
int distanciaCalculada = 0; calculada // variable que almacena la distancia

int v = 0; // variable que almacena el voltaje calculado

[ 218 ]

www.it­ebooks.info
Machine Translated by Google

Capítulo 6

// las constantes de nuestra fórmula


constante int a = 0,008271;
constante int b = 939,65;
constante int c = ­3.398;
constante int d = 17.339;

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.it­ebooks.info
Machine Translated by Google

Sentir el mundo: sentir con entradas analógicas

Leyendo la distancia en Max 6


Patcher006_Arduino.maxpat es el parche relacionado con este proyecto de medición de
distancia. Aquí está:

El parche de lectura a distancia

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.it­ebooks.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.it­ebooks.info
Machine Translated by Google

Sentir el mundo: sentir con entradas analógicas

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.

Veamos otros ejemplos de sensores capaces de generar variaciones de voltaje continuas.

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.

Un sensor flexible estándar con solo dos conectores

Un sensor flexible se puede utilizar para muchos propósitos.

[ 222 ]

www.it­ebooks.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.

La siguiente figura ilustra cómo funciona el sensor:

Plana (resistencia nominal)


45 Curvatura (mayor resistencia)
90 Bend (resistencia aumentada aún más)

Ahora os dejo directamente el esquema de cableado realizado nuevamente con Fritzing:

Sensor flexible conectado a la placa Arduino con la resistencia pull­down

Coloqué una resistencia pull­down. Si no leíste el Capítulo 5, Detección con entradas digitales,
sobre resistencias pull­up y pull­down, te sugiero que lo hagas ahora.

Normalmente utilizo resistencias de unos 10K Ω y funcionan bien.

[ 223 ]

www.it­ebooks.info
Machine Translated by Google

Sentir el mundo: sentir con entradas analógicas

El diagrama del circuito se muestra en la siguiente figura:

Arduino1

3V3 5V Venir
Fuerza
D13

Primera vez D12

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)

CAROLINA DEL NORTE

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

Adventista del Séptimo Día

Tierra

El sensor flexible y su resistencia pull­down conectados al Arduino

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.it­ebooks.info
Machine Translated by Google

Capítulo 6

Considerando el esquema eléctrico, el voltaje en el pin analógico 0 es:

Si elegimos la misma resistencia para el pull­down 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

Obviamente, utilizando la misma fórmula cuando no está doblado, podemos esperar:

10k
VA0= * 5 = 2,5 V
10k + 10k

Esto significa que encontramos nuestro rango de valores de voltaje.

Ahora podemos convertir eso en valores digitales codificados de 10 bits, me refiero al famoso rango de 0 a
1023 del ADC de Arduino.

Un pequeño y sencillo cálculo nos proporciona los valores:

• 511 cuando el voltaje es 2,5 (cuando el cable flexible no está doblado)

• 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.

Ahora vamos a conocer algunos otros sensores.

[ 225 ]

www.it­ebooks.info
Machine Translated by Google

Sentir el mundo: sentir con entradas analógicas

Sintiendo casi todo


Cualquiera que sea el parámetro físico que desee medir, hay un sensor para ello.

Aquí hay una pequeña lista:

• Color de la luz e intensidad de la luz •


Volumen del sonido

• 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

• Peso (diferente para un sensor de flexión pura)

No es una lista exhaustiva, pero sí bastante completa.

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.

Multiplexación con un multiplexor/


demultiplexor CD4051
Vamos a explorar una técnica llamada multiplexación. Este es un subcapítulo importante porque vamos a
aprender cómo hacer que nuestro proyecto de la vida real sea más concreto, más real.

[ 226 ]

www.it­ebooks.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?

Aprenderemos a multiplexar señales.

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

Concepto básico de multiplexación que muestra el medio compartido

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.

Por supuesto, implica procesos de multiplexación (llamados mux en la figura) y demultiplexación


(demux).

Profundicemos un poco en esos procesos.

Múltiples técnicas de multiplexación/


demultiplexación
Cuando tenemos que multiplexar/demultiplexar señales, básicamente tenemos que encontrar una
manera de separarlas utilizando cantidades físicas que podamos controlar.

Puedo enumerar al menos tres tipos de técnicas de multiplexación:

• multiplexación por división espacial


• multiplexación por división de frecuencia
• multiplexación por división de tiempo
[ 227 ]

www.it­ebooks.info
Machine Translated by Google

Sentir el mundo: sentir con entradas analógicas

Multiplexación por división espacial


Esto es lo más fácil de entender.

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

Este concepto es la multiplexación básica de la red telefónica de tu piso, por ejemplo.

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 Wi­Fi. De hecho, algunos routers Wi­
Fi actuales ofrecen más de una antena Wi­Fi. 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.

Multiplexación por división de frecuencia


Este tipo de multiplexación es muy común en todo lo relacionado con conexiones DSL y TV por cable.

Los proveedores de servicios pueden (y lo hacen) proporcionar más de un servicio en el mismo


cable utilizando esta técnica.

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.it­ebooks.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.

Por supuesto, lo que multiplexamos en un extremo, lo tenemos que demultiplexar en el otro


para poder direccionar nuestras señales correctamente. No intentaría convertir una señal
de TV modulada en voz, pero supongo que no sería una experiencia muy fructífera.

Multiplexación por división de tiempo Este es el


caso en el que vamos a profundizar más porque es el que vamos a utilizar con Arduino para
multiplexar muchas señales.

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

Secuencialmente, sólo un canal entre el multiplexor y el demultiplexor se utiliza completamente


para la primera señal, luego para la segunda, y así sucesivamente, hasta la última.

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.it­ebooks.info
Machine Translated by Google

Sentir el mundo: sentir con entradas analógicas

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.

El multiplexor analógico CD4051B


El multiplexor analógico CD4051B es muy barato y muy útil. Básicamente es un multiplexor y demultiplexor
analógico y digital. Esto no significa que se pueda utilizar como multiplexor y demultiplexor al mismo
tiempo. Hay que identificar en qué caso se está y cablear y diseñar el código para ese caso en particular.
Pero siempre es útil tener un par de dispositivos CD4051B.

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.

¿Qué es un circuito integrado?


Un circuito integrado (CI) es un circuito electrónico miniaturizado que se encuentra completamente incluido
en una pequeña caja de plástico. Esta es la definición más simple.

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.

A continuación se muestran dos de varios tipos de paquetes de circuitos integrados:

• Paquete dual en línea (DIP, también llamado DIL)

• Pequeño contorno (SO)

Puede encontrar una guía útil en http://how­to.wikia.com/wiki/Guide_to_IC_


paquetes.

[ 230 ]

www.it­ebooks.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).

SO requiere mayor destreza y herramientas más finas.

¿Cómo cablear el IC CD4051B?


La primera pregunta es ¿qué aspecto tiene? En este caso, la respuesta es que parece un paquete DIP.

La versión en caja DIP del CD4051B

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

Redibujé el paquete global en la siguiente figura.

E/S 4 Vdd

E/S 6 Entrada 2

o/i común Entrada 1

E/S 7 entrada 0

CD4051B
E/S 5 E/S 3

Instituto Nacional de Salud A

Agua B

Vss do

Un esquema del CD4051B con todas las descripciones de los pines.

[ 231 ]

www.it­ebooks.info
Machine Translated by Google

Sentir el mundo: sentir con entradas analógicas

Identificación del pin número 1


Es muy fácil averiguar cuál es el pin número 1. Como norma, hay un pequeño círculo grabado delante
de uno de los pines de las esquinas. Este es el pin número 1.

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

Numeración de los pines de un CI

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.

• Vdd es el pin de voltaje de suministro positivo. Debe conectarse a la fuente de alimentación de 5 V.

• Vee es el pin de voltaje de suministro negativo. Aquí, lo conectaremos a tierra.

• Vss es el pin de tierra, conectado a tierra también.

Serie de E/S analógicas y E/S común


Comprueba el orden de la I y la O en este título.

Si elige utilizar el CD4051B como multiplexor, tendrá múltiples entradas analógicas y una salida
común.

[ 232 ]

www.it­ebooks.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.

¿Cómo funciona la selección/conmutación? Veamos los pines digitales del selector, A, B y C.

Seleccionar el pin digital Ahora viene la


parte más importante.

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.

El motor multiplexor debajo del capó no es tan difícil de entender.

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.

La siguiente tabla describe la combinación:

ESTADOS DE ENTRADA

INHIBIR do B A “EN CANAL(ES)”


CD4051B
0 000 0

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

La tabla de verdad para el CD4051B

[ 233 ]

www.it­ebooks.info
Machine Translated by Google

Sentir el mundo: sentir con entradas analógicas

En otras palabras, significa que, si escribimos 1 en la salida digital de Arduino correspondiente a


A, 1 en la correspondiente a B y 0 en la correspondiente a C, la entrada conmutada sería el tercer canal.

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

Así es como podríamos cablear las cosas:

El circuito incluye el multiplexor CD4051B con su salida común conectada al pin analógico 0

[ 234 ]

www.it­ebooks.info
Machine Translated by Google

Capítulo 6

Y la siguiente figura es el diagrama eléctrico:

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:

• Uno para conmutar el multiplexor


• Uno para leer la entrada analógica 0 de Arduino

El código fuente se vería así (puedes encontrarlo en el Capítulo 6/


carpeta analogMuxReader ):

int muxOutputPin = 0 ; // pin conectado a la salida común del


CD4051B
int devicesNumber = 8 ; // número de dispositivo // TEN CUIDADO, conéctalos desde 0

[ 235 ]

www.it­ebooks.info
Machine Translated by Google

Sentir el mundo: sentir con entradas analógicas

int controlPinA = 2 ; // pin conectado al pin de selección A del


CD4051B
int controlPinB = 3 ; // pin conectado al pin de selección B del
CD4051B
int controlPinC = 4 ; // pin conectado al pin de selección C del
CD4051B

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));

// lectura y almacenamiento del valor de currentInput


Serial.println(analogRead(muxOutputPin));
}
}

[ 236 ]

www.it­ebooks.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.

Hacemos un bucle sobre la entrada conmutada de 0 a 7, más precisamente a


dispositivosNumber ­ 1.

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.

Luego, también descubrimos una técnica muy importante, la multiplexación/


desmultiplexación.

Hablaremos de ello en el próximo capítulo sobre la comunicación serial.


Profundizaremos más en este tipo de comunicación ahora que ya hemos empleado mucho tiempo.

[ 237 ]

www.it­ebooks.info
Machine Translated by Google

www.it­ebooks.info
Machine Translated by Google

Hablando sobre Serial


Ya hemos visto que el uso de Arduino consiste en hablar y compartir señales. De hecho, desde el
componente más básico de Arduino, que reacciona a algunos valores del mundo físico modificando
su entorno y propagando el cambio como un mensaje básico a sus vecinos, hasta la comunicación
serial, ahora clásica, las entidades electrónicas se comunican entre sí y con nosotros.

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.

Vamos a profundizar en ello ahora mismo.

www.it­ebooks.info
Machine Translated by Google

Hablando sobre Serial

Comunicación serial y paralela


La comunicación en serie suele definirse por su forma opuesta de comunicación, la
comunicación paralela, en la que se envían varios bits de datos a través de un enlace formado
por varios canales paralelos al mismo tiempo. Observe la siguiente figura:

Orador 0 1 1 0 0 0 1 1 Canal de comunicación 0 1 1 0 0 0 1 1 oyente

Comunicación serial básica unidireccional entre un hablante y un oyente

Ahora comparemos esto con un caso paralelo:

Canales paralelos
0 0
1 1
1 1
0 0 oyente
vocero
0 0
0 0
1 1
1 1

Comunicación paralela básica unidireccional entre un hablante y un oyente

En estas dos figuras, un altavoz está enviando el siguiente byte de datos: 0 1 1 0 0 0 1 1.


Estos ocho bits de datos se envían secuencialmente a través de un canal en el caso en que
se ha utilizado comunicación en serie, y simultáneamente a través de ocho canales
diferentes en el caso en que se ha utilizado comunicación paralela.

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.it­ebooks.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.

Tipos y características de las comunicaciones


seriales
Ya sea sincronismo, modo dúplex, bus o peering, la comunicación serial se puede definir de manera diferente, y
tenemos que profundizar en ese punto aquí.

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)

• Half­duplex : Bidireccional, pero sólo en una dirección al mismo tiempo

• Full­duplex : Bidireccional simultáneamente

[ 241 ]

www.it­ebooks.info
Machine Translated by Google

Hablando sobre Serial

Obviamente, el half­duplex 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 full­duplex 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.

En un autobús, todos se conectarán físicamente en algún momento y se producirán algunas


conmutaciones lógicas.

UPC Memoria E/S

Bus de control

Dirección de bus

Bus de datos

Un ejemplo de un sistema multibus

Buses maestros y esclavos


En los buses maestro/esclavo, un dispositivo es el maestro y los demás son los esclavos, y
esto generalmente implica sincronismo donde el participante maestro genera el reloj de
sincronización.

La principal dificultad de la comunicación en serie es evitar colisiones y


malentendidos.

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.it­ebooks.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:

• La longitud de la palabra en bits

• Si hay un bit de parada presente o no (define un momento en blanco en el tiempo)

• 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)

De hecho, especialmente en la comunicación asincrónica, ¿cómo podría un oyente saber dónde


comienza o termina una palabra sin estas propiedades? Por lo general, codificamos este
comportamiento en los cerebros de ambos participantes para asegurarnos de que contamos con un
protocolo de comunicación válido.

En la primera figura de este capítulo, envié ocho bits de datos por el canal. Esto equivale a 1 byte.

A menudo escribimos los tipos de comunicación serial como <longitud de


palabra><paridad><parada>. Por ejemplo, 8 bits sin paridad pero una parada se escribe
como 8N1.

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

• Ocho bits para cada carácter

• 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.it­ebooks.info
Machine Translated by Google

Hablando sobre Serial

Interfaces seriales múltiples


No describiré todos los protocolos seriales, pero me gustaría hablar de algunos importantes y
clasificarlos en familias.

El poderoso antepasado de la telegrafía en código Morse


Os presento uno de los protocolos seriales más antiguos: el protocolo de telegrafía en código Morse.
Los operadores de telecomunicaciones lo vienen utilizando desde la segunda mitad del siglo XIX.

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:

• Cables (pulsos eléctricos)

• Aire (portadores de ondas electromagnéticas, luz, sonidos)

Se puede clasificar en un sistema de comunicación peered, half­duplex y


asincrónico.

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 RS­232
RS­232 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. RS­232 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.it­ebooks.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:

• Transmitir datos (normalmente escritos como TX)

• Recibir datos (normalmente escritos como RX)


• Suelo

El conector con 25 pines/cables se denomina DB25 y se ha utilizado mucho para periféricos


como impresoras. Existe otro tipo de conector denominado DB9 con solo 9 pines/cables. Se trata de
una variante que omite más cables que el DB25. Este DB9 se ha utilizado mucho para conectar
dispositivos de ratón.

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.

En este estándar, el pin 7 es la tierra común y el 2 y el 3 son TX y RX respectivamente.


Con solo estos tres, podemos realizar nuestra comunicación serial asíncrona correctamente.

El conector DB25

[ 245 ]

www.it­ebooks.info
Machine Translated by Google

Hablando sobre Serial

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 RS­232 con el famoso
circuito integrado fabricado por FTDI que proporciona una forma muy eficiente de convertir
RS­232 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.it­ebooks.info
Machine Translated by Google

Capítulo 7

Módulos BlinkM conectados como bus I2C al Arduino Uno R3

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:

• SCLK: Este es el reloj serial controlado por el maestro

• MOSI: Esta es la salida maestra/entrada esclava impulsada por el maestro

• MISO: Esta es la entrada maestra/salida esclava impulsada por el maestro


• SS: Este es el cable de selección de esclavos

[ 247 ]

www.it­ebooks.info
Machine Translated by Google

Hablando sobre Serial

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 full­duplex, 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.

Personalmente lo he usado a menudo en proyectos que involucran muchos registros de desplazamiento


que están todos conectados en cadena para tener muchas entradas y/o salidas con Arduino Uno e
incluso Arduino Mega, este último ofreciendo más salidas y entradas de forma nativa.

Describiremos el uso de registros de desplazamiento en el próximo capítulo, cuando le muestre cómo


multiplexar salidas con bastante facilidad con algunos circuitos integrados inteligentes y, en última
instancia, muy simples, vinculados a Arduino a través de 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:

• Audio (altavoz, micrófono, tarjeta de sonido, MIDI)

• Comunicaciones (módem, Wi­Fi y Ethernet)

• Dispositivo de interfaz humana (HID, teclado, ratón, joystick)

• Imagen y vídeo (webcam, escáner)


• Impresora

• Almacenamiento masivo (unidad flash, tarjeta de memoria, unidad)

• Inalámbrico (infrarrojos)

[ 248 ]

www.it­ebooks.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.

Diseño de sistema USB


La arquitectura del USB es una topología asimétrica que consta de un host y una multitud
de puertos USB descendentes y múltiples dispositivos periféricos conectados en una
topología de estrella escalonada.

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.

Conectores y cables USB


Un enchufe USB estándar contiene cuatro cables (http://en.wikipedia.org/wiki/
Bus serie universal):

• Vcc (+5 V)
• Datos­
• Datos+
• Suelo

+ D­
­ D+ D­ +
12

4321 43

­ D+
Norma A Norma B

Los conectores USB estándar A y 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.it­ebooks.info
Machine Translated by Google

Hablando sobre Serial

Hay otros tipos de enchufes que son algo más grandes, pero el requisito de tener al menos cuatro cables sigue
siendo el mismo.

IC FTDI que convierte RS­232 a USB


A excepción de algunas versiones, como el Arduino Pro Mini, las placas Arduino proporcionan un conector
USB, como ya conoces y has utilizado.

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 RS­232. 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:

• IDE de Arduino (Monitor en serie)

• Procesamiento (con la biblioteca serial)

• Máximo 6 (con el objeto serial)

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.

Si utiliza la comunicación en serie a través de la función USB, deberá evitar


utilizar los pines digitales 0 y 1.

[ 250 ]

www.it­ebooks.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.it­ebooks.info
Machine Translated by Google

www.it­ebooks.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.

Arkalgud Ramaprasad, Profesor del Departamento de Información y Toma de Decisiones


Ciencias en la Facultad de Administración de Empresas de la Universidad de Illinois, Chicago,
define la retroalimentación de la siguiente manera:

"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.it­ebooks.info
Machine Translated by Google

Diseño de retroalimentación de salida visual

Vamos a aprender lo siguiente:

• Cómo utilizar LED monocromáticos básicos

• Cómo hacer matrices de LED y cómo multiplexar LED


• Cómo utilizar los LED RGB

Terminaremos el capítulo presentando el dispositivo de pantalla LCD.

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.

Diferentes tipos de LED


Generalmente, los LED se utilizan tanto para bloquear la corriente que llega desde una línea a su pata de
cátodo como para dar retroalimentación luminosa cuando la corriente pasa a su ánodo:

Los diferentes modelos que podemos encontrar son los siguientes:

• LED básicos

• OLED (LED orgánico fabricado mediante la superposición de la parte semiconductora orgánica)

• AMOLED (Active Matrix OLED proporciona una alta densidad de píxeles para grandes
tamaño de pantalla)

• FOLED (OLED flexible)

[ 254 ]

www.it­ebooks.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.it­ebooks.info
Machine Translated by Google

Diseño de retroalimentación de salida visual

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.

Recordando el ejemplo del LED Hola


En Hello LED, hicimos que un LED parpadeara durante 250 ms de cada 1000 ms que pasan.
Veamos nuevamente su vista esquemática para mantener el flujo de su lectura:

[ 256 ]

www.it­ebooks.info
Machine Translated by Google

Capítulo 8

El código para Hello LED es el siguiente:

// El pin 8 es el que está conectado a nuestro bonito LED


en 8 // ledPin es una variable entera int ledPin = 8; inicializada

void setup()
{ pinMode(ledPin, SALIDA); salida // inicializa el pin digital como un

// ­­­­­­­­­ la rutina de bucle se ejecuta para siempre


bucle vacío() {
digitalWrite(ledPin, HIGH); // enciende el LED
retraso(250); //esperar 250ms en el estado actual
digitalWrite(ledPin, BAJO); retraso(1000); // apaga el LED
//esperar 1 s en el estado actual
}

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.it­ebooks.info
Machine Translated by Google

Diseño de retroalimentación visual de salida

Múltiples LED monocromáticos


Dado que aquí estamos hablando de retroalimentación y no solo de salida pura, crearemos un
pequeño ejemplo que le mostrará cómo manejar varios botones y varios LED. No se preocupe si
no puede comprender esto en este momento; simplemente continúe leyendo.

Dos botones y dos LED


Ya hablamos sobre cómo jugar con varios botones en el Capítulo 5, Detección de entradas
digitales. Construyamos ahora un nuevo circuito.

Aquí están los esquemas:

[ 258 ]

www.it­ebooks.info
Machine Translated by Google

Capítulo 8

Es preferible continuar dibujando el diagrama eléctrico relacionado con cada esquema.

Básicamente, el ejemplo de botones múltiples del Capítulo 5, Detección de entradas


digitales; sin embargo, hemos eliminado un botón y agregado dos LED en su lugar.

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 pull­down 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.

No hay nada realmente increíble en eso.

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.it­ebooks.info
Machine Translated by Google

Diseño de retroalimentación de salida visual

Acoplamiento de control y retroalimentación en el diseño de interacción


Esta sección se considera un subcapítulo por dos razones principales:

• En primer lugar, suena genial y es clave para mantener la motivación.


• En segundo lugar, esta parte es la clave para todo el diseño futuro de la interfaz
hombre­máquina.

Como ya sabéis, Arduino (gracias a su firmware) vincula el lado de control y el de


retroalimentación. Es muy importante tener esto en cuenta.

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
control­retroalimentación.

Un acoplamiento control/retroalimentación es un conjunto de reglas que definen cómo se comporta un


sistema cuando recibe órdenes nuestras y cómo reacciona dándonos (o no) retroalimentación.

Es muy importante comprender este conjunto de reglas codificadas.

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.it­ebooks.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.it­ebooks.info
Machine Translated by Google

Diseño de retroalimentación visual de salida

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.

Ya que existe un protocolo muy básico y eficiente diseñado (http://monome.org/


data/monome256_protocol.txt) para controlar especialmente los LED y leer las pulsaciones de los
botones, podemos crear y diseñar nuestro propio acoplamiento. Monome también se suministra con el
Monome Serial Router, que es una aplicación muy pequeña que básicamente traduce el protocolo en bruto
a OSC (http://archive.cnmat.berkeley.
edu/OpenSoundControl/) o MIDI (http://www.midi.org/). Los analizaremos en secciones posteriores de este
capítulo. Son muy comunes en el diseño de interacción multimedia; OSC se puede transportar a través
de redes, mientras que MIDI es muy adecuado para enlaces entre equipos relacionados con la música,
como secuenciadores y sintetizadores.

Esta breve digresión no estaría completa sin otro esquema sobre el Monome.

Compruébelo y aprendamos más sobre ello después de eso:

La interfaz inteligente y minimalista de Monome en su configuración habitual basada en computadora

[ 262 ]

www.it­ebooks.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).

Diseñé un acoplamiento específico dentro de Max 6, traduciendo mensajes específicos desde/hacia el


propio Monome, pero también desde/hacia el software, especialmente Ableton Live (https://
www.ableton.com).

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.

Diseñemos un firmware básico, incluyendo acoplamiento, basado en este pseudocódigo:


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.

Puede encontrar instrucciones sobre la biblioteca Bounce en http://arduino.cc/


patio de juegos/código/rebote.

Revisemos ese fragmento de código:

#include <Bounce.h> // incluye la biblioteca Bounce (mágica)

#define BOTÓN01 2 // pin del botón #1


#define BOTÓN02 3 // pin del botón #2

#define LED01 8 // pin del botón #1

[ 263 ]

www.it­ebooks.info
Machine Translated by Google

Diseño de retroalimentación visual de salida

#define LED02 9 // pin del botón #2

// Instanciemos los 2 antirrebote con un tiempo de antirrebote de 7 ms


Rebote bouncer_button01 = Rebote (BUTTON01, 7);
Rebote bouncer_button02 = Rebote (BUTTON02, 7);

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(){

// Actualicemos los dos antirrebote


bouncer_button01.update();
bouncer_button02.update();

// ¡leamos el estado de cada botón, sin rebotes! int button01_state


= bouncer_button01.read(); int button02_state =
bouncer_button02.read();

// probemos el estado de cada botón y encendamos o apaguemos los LED if


( button01_state == HIGH ) digitalWrite(LED01, HIGH); else digitalWrite(LED01,
LOW);

si ( botón02_estado == ALTO ) digitalWrite(LED02, ALTO); de lo contrario


digitalWrite(LED02, BAJO);
}

Lo puedes encontrar en la carpeta Chapter08/feedbacks_2x2/ .

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:

Rebote bouncer_button01 = Rebote (BUTTON01, 7);


Rebote bouncer_button02 = Rebote (BUTTON02, 7);

[ 264 ]

www.it­ebooks.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.

La respuesta correcta es la multiplexación. Veamos cómo podemos manejar muchos 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).

Hablamos sobre la multiplexación de entradas en el Capítulo 6, Jugando con entradas analógicas.

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.it­ebooks.info
Machine Translated by Google

Diseño de retroalimentación visual de salida

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.

Conexión del 75HC595 a Arduino y LED


Como aprendimos con el CD4051 y la multiplexación de entradas analógicas, vamos a
conectar el chip a un registro de desplazamiento 75HC595 para multiplexar/desmultiplexar
ocho pines de salida digital. Veamos el cableado:

Tenemos el Arduino suministrando energía a la placa de pruebas. Cada resistencia proporciona 220 ohmios.

El 75HC595 toma el potencial GND y 5 V para su propio suministro y configuración.

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.it­ebooks.info
Machine Translated by Google

Capítulo 8

Comprobemos el propio 74HC595:

• Los pines 8 y 16 se utilizan para la fuente de alimentación interna.

• 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 11 es la entrada del reloj del registro de desplazamiento.

• El pin 12 es la entrada del reloj del registro de almacenamiento, también llamado Latch.

• El pin 14 es la entrada de datos en serie.

• El pin 15 y los pines 1 a 7 son los pines de salida.

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.it­ebooks.info
Machine Translated by Google

Diseño de retroalimentación visual de salida

Luego, cada estado se envía a la salida correcta de Q0 a Q7, transponiendo los estados
transmitidos previamente en serie.

Esta es una ilustración directa de la conversión de serie a paralelo de la que hablamos en el


capítulo anterior. Teníamos un flujo de datos que llegaba secuencialmente, se retenía hasta que
el registro se cargaba globalmente y luego se enviaba a muchos pines de salida.

Ahora, visualicemos el diagrama de cableado:

Una matriz de ocho LED con resistencias conectadas al registro de desplazamiento 74HC595

Firmware para el manejo de registros de desplazamiento


Vamos a aprender a diseñar un firmware específico para este tipo de registros de desplazamiento.
Este firmware está hecho básicamente para el 595, pero no requiere muchas modificaciones
para usarse con otros circuitos integrados. Deberás tener especial cuidado con tres pines seriales:
Latch, Clock y Data.

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.it­ebooks.info
Machine Translated by Google

Capítulo 8

Puede encontrar el código para esto en la carpeta Chapter08/Multiplexing_8Leds/ .

Vamos a comprobarlo:

// pin de reloj 595 que se conecta al pin 4 int CLOCK_595


= 4;

// 595 pin de pestillo que se conecta al pin 3 int LATCH_595


= 3;

// 595 pin de entrada de datos en serie que se conecta al pin 2 int DATA_595
= 2;

// variables aleatorias de la máquina de ranura int


contador = 0; byte
LED_states = B00000000 ;

configuración vacía() {

// Establezcamos todos los pines relacionados con la serie como salidas


pinMode(LATCH_595, OUTPUT);
pinMode(CLOCK_595, OUTPUT);
pinMode(DATA_595, OUTPUT);

// utiliza una semilla proveniente del ruido electrónico del ADC randomSeed(analogRead(0));

bucle vacío(){

// generar un byte aleatorio para (int i =


0; i < 8; i++) {

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.it­ebooks.info
Machine Translated by Google

Diseño de retroalimentación visual de salida

// cada 5000 ejecuciones de loop(), toma una nueva semilla para la función aleatoria

si (contador < 5000) contador++;


demás

{
semillaAleatoria(lectura analógica(0)); // lee un nuevo valor del pin analógico
0
contador = 0; // reiniciar el contador
}

// haz una breve pausa antes de cambiar el estado de los LED


retraso(45);
}

Patrón de programación de registro de desplazamiento global


Primero, revisemos la estructura global.

Primero defino los tres pines del registro de desplazamiento 595. Luego, configuro cada uno de
ellos como salida en el bloque setup() .

Entonces, tengo un patrón que se parece al siguiente:

digitalWrite(pin de cierre, BAJO)


shiftOut(pin de datos, pin de reloj, MSBFIRST, mis_estados)
digitalWrite(pasador de cierre, ALTO)

Este es el patrón habitual para las operaciones de registro de desplazamiento.


El pasador de cierre, como se explicó anteriormente, es el que nos proporciona una forma de informar
al circuito integrado sobre el hecho de que queremos cargarlo con datos, y luego queremos que
aplique estos datos a sus salidas.

Esto es un poco como decir:

• Pasador de cierre BAJO = "Hola, vamos a guardar lo que estoy a punto de enviarte".
• Latch­pin 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.it­ebooks.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.

Al fijar este argumento en la función shiftOut() , proporcionamos información especial sobre el


sentido de la transmisión. De hecho, podemos enviar el byte anterior enviando estos bits: 1 , luego, 0,
luego 1 0 0 1 1 0 (MSBFIRST), o enviando estos bits: 0 1 1 0 0 1 0 1 (LSBFIRST).

Jugando con el azar y semillas aleatorias


Me gustaría ofrecer un ejemplo de mi forma personal de programar. Aquí voy a describir un sistema
económico y pequeño que genera bytes aleatorios.
Luego, estos bytes se enviarán al 595 y nuestra matriz de ocho LED tendrá un estado muy aleatorio.

En informática, lo aleatorio no es realmente aleatorio. De hecho, la función random() es un


generador de números pseudoaleatorios. También se lo puede denominar generador de bits aleatorios
determinista (DRBG). De hecho, la secuencia está (totalmente) determinada por un pequeño conjunto de
valores iniciales, incluida la semilla.

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í.

Esto es lo que he puesto en el firmware.

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.it­ebooks.info
Machine Translated by Google

Diseño de retroalimentación visual de salida

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.

Si desea utilizar random() con computadoras,


incluidos Arduino y sistemas integrados,
obtenga algo de ruido físico y externo.

Ahora, sigamos adelante.

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?

¡Vamos a conectar en cadena ahora!

Conexión en cadena de varios registros de


desplazamiento 74HC595
Una conexión en cadena es un esquema de cableado utilizado para vincular varios dispositivos en una secuencia o incluso en
un anillo.

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

Puedes descargarlo aquí: http://arduino.cc/playground/Main/ShiftOutX. Puedes instalarlo siguiendo el


procedimiento explicado en el apéndice.

[ 272 ]

www.it­ebooks.info
Machine Translated by Google

Capítulo 8

Vinculación de múltiples registros de desplazamiento


¿Qué necesitaría saber cada registro de desplazamiento?

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.it­ebooks.info
Machine Translated by Google

Diseño de retroalimentación visual de salida

Revisemos el diagrama del circuito para tener esto en cuenta:

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.

Aquí está el código para el firmware.

Puedes encontrarlo en la carpeta Chapter08/Multiplexing_WithDaisyChain/ :

#include <ShiftOutX.h>
#include <NúmeroDePinDeMayús.h>

[ 274 ]

www.it­ebooks.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

int SR_Number = 2; // número de registros de desplazamiento en la cadena

// instanciar y habilitar la biblioteca shiftOutX con nuestros parámetros de circuito

shiftOutX regGroupOne(LATCH_595, DATOS_595, RELOJ_595, MSBFIRST, SR_;


Número);

// variables aleatorias de la máquina de ranura


int contador = 0;
byte LED0to7_states = B00000000;
byte LED8to15_states = B00000000;

configuración vacía() {

// NO MÁS configuraciones para cada pin digital del Arduino


// TODO lo hace la biblioteca :­)

// utiliza una semilla proveniente del ruido electrónico del ADC randomSeed(analogRead(0));

bucle vacío(){

// generar 2 bytes aleatorios


para (int i = 0; i < 8; i++)
{
bitWrite(LED0to7_estados, i, aleatorio(2));
bitWrite(LED8to15_estados, i, aleatorio(2));
}

unsigned long int data; // declarando el contenedor de datos como muy


variable local

datos = LED0to7_estados | (LED8to15_estados << 8); // agregando los 2


bytes aleatorios
shiftOut_16(DATA_595, CLOCK_595, MSBFIRST, data); // empujando el
datos completos a SR

// cada 5000 ejecuciones de loop(), toma una nueva semilla para la función aleatoria

[ 275 ]

www.it­ebooks.info
Machine Translated by Google

Diseño de retroalimentación visual de salida

si (contador < 5000) contador++;


demás

{
semillaAleatoria(lectura analógica(0)); // lee un nuevo valor del pin analógico
0
contador = 0; // reiniciar el contador
}

// haz una breve pausa antes de cambiar el estado de los LED


retraso(45);
}

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.

Incluye dos archivos de encabezado al principio, a saber, ShiftOutX.h y


ShiftPinNo.h.

Luego, definimos una nueva variable que almacena el número de registros de desplazamiento en la cadena.

Por último, instanciamos la biblioteca ShiftOutX usando el siguiente código:

shiftOutX regGroupOne(LATCH_595, DATOS_595, RELOJ_595, MSBFIRST, SR_;


Número);

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.

Vamos a detallar un poco esta operación.

[ 276 ]

www.it­ebooks.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

Luego, si agregamos un byte usando el operador bit a bit (|), obtenemos:

0111010000000000
| 11010001
= 0111010011010001

El resultado parece ser una concatenación de todos los bits.

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.

¿Qué significa eso?

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.it­ebooks.info
Machine Translated by Google

Diseño de retroalimentación de salida visual

Consideraciones breves actuales


La placa Arduino, que utiliza una fuente de alimentación USB, no puede manejar más de 500 mA. Todos
los pines combinados no pueden manejar más de 200 mA y ningún pin puede manejar más de 40 mA.
Puede variar un poco de un tipo de placa a otro, pero estos son valores máximos reales y absolutos.

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.

Pasemos a un mundo lleno de colores.

[ 278 ]

www.it­ebooks.info
Machine Translated by Google

Capítulo 8

Uso de LED RGB


RGB significa rojo, verde y azul, como probablemente estabas adivinando.

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.

Estoy hablando de LED RGB de cátodo común y ánodo común.

Algunos conceptos de control


¿Qué necesitas para controlar un LED?

Es necesario poder aplicar una corriente a sus patas. Más precisamente, es necesario poder
crear una diferencia de potencial entre sus patas.

La aplicación directa de este principio es lo que ya hemos probado en la primera parte de


este capítulo, que nos recuerda cómo podemos encender un LED: necesitamos controlar la
corriente usando los pines de salida digitales de nuestro Arduino, sabiendo que el LED que
queremos controlar tiene su nodo cableado al pin de salida y su cátodo cableado a tierra, con
una resistencia en la línea también.

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.

En el otro caso, si aplicamos 5 V a un LED y queremos encenderlo, necesitaremos escribir un


valor LOW en el pin digital al que está vinculado. En este caso, el pin digital estará conectado
internamente a tierra y absorberá la corriente.

Estas son las dos formas de controlar la corriente.

[ 279 ]

www.it­ebooks.info
Machine Translated by Google

Diseño de retroalimentación de salida visual

Compruebe el siguiente diagrama:

Diferentes tipos de LED RGB


Veamos los dos LED RGB más comunes:

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.it­ebooks.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.

Encender un LED RGB


Comprueba este circuito básico:

Un LED RGB conectado a Arduino

Comprueba el código ahora. Puedes encontrarlo en la carpeta Chapter08/One_RGB_LED/ .

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.it­ebooks.info
Machine Translated by Google

Diseño de retroalimentación de salida visual

bucle vacío() {

para (int r = 0; r < 2; r++)


{
para (int g = 0 ; g < 2 ; g++)
{
para (int b = 0; b < 2; b++)
{
digitalWrite(pinR,r); // convirtiendo el pin rojo en valor r
digitalWrite(pinG,g); // convirtiendo el pin verde en valor g
digitalWrite(pinB,b); // convirtiendo el pin azul en valor b

delay(150); // pausando un poco


}
}
}

Nuevamente, algunos consejos están presentes dentro de este código.

Componentes y colores de la luz roja, verde y azul


En primer lugar, ¿cuál es el objetivo? Quiero que el LED RGB pase por todos los estados posibles. Un poco de matemática
puede ayudar a enumerar todos los estados.

Tenemos una lista ordenada de tres elementos, cada uno de los cuales puede estar encendido o apagado. Por lo tanto, hay 23

estados, lo que significa ocho estados en total:

R GRAMO B Color resultante


Apagado Apagado Apagado APAGADO

Apagado Apagado En Azul


Apagado En Apagado Verde
Apagado En En Cian
En Apagado Apagado Rojo
En Apagado En Púrpura
En En Apagado
Naranja
En En En Blanco

Solo activando o desactivando cada componente de color podemos cambiar el estado global del LED RGB.

[ 282 ]

www.it­ebooks.info
Machine Translated by Google

Capítulo 8

No olvidemos que el sistema funciona exactamente como si estuviéramos controlando tres


LEDS monocromáticos a través de tres salidas digitales de Arduino.

Primero, definimos tres variables que almacenan los diferentes colores de los conectores LED.

Luego, en la configuración(), establecemos esos tres pines como salida.

Múltiples bucles for() imbricados


Por último, el bloque loop() contiene bucles for() triplemente imbricados . ¿Qué es eso? Es una forma
eficiente y agradable de asegurarse de que coincidan todos los casos posibles. También es una forma
sencilla de hacer un ciclo de cada número posible. Veamos los primeros pasos para comprender mejor
este concepto de bucles imbricados:

• 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

El bucle más interno es siempre el que se ejecuta el mayor número de veces.

¿Está bien? ¡Por supuesto que sí!

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 un sistema Windows, se puede encontrar en la carpeta Arduino dentro de algunos


subdirectorios, dependiendo de la versión del IDE.

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.

Y finalmente podemos recuperar lo siguiente:

#define ALTO 0x1


#define BAJO 0x0

[ 283 ]

www.it­ebooks.info
Machine Translated by Google

Diseño de retroalimentación de salida visual

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.

Construcción de matrices de LED


Las matrices de LED son básicamente LED conectados como una matriz.

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.

Veamos el esquema más sencillo de este libro:

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.it­ebooks.info
Machine Translated by Google

Capítulo 8

Una matriz de LED se basa en estos controles dobles posibles.

Vamos a introducir un nuevo componente aquí, el transistor.

Un nuevo amigo llamado transistor Un transistor es un componente

especial que presentamos un poco en la primera parte de este libro.

El transistor NPN habitual con sus tres patas

Este componente se suele utilizar en tres casos principales:

• Como interruptor digital en un circuito lógico


• Como amplificador de
señal • Como estabilizador de voltaje combinado con otros componentes

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.it­ebooks.info
Machine Translated by Google

Diseño de retroalimentación de salida visual

Matriz de transistores Darlington, ULN2003


Vamos a utilizar un transistor, incluido en un circuito integrado llamado ULN2003. ¡Qué nombre
más bonito! Un nombre más explícito es matriz de transistores Darlington de alta corriente.
Vale, ¡sé que eso no ayuda!

Su hoja de datos se puede encontrar en

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.

El principio es simple y sorprendente:

• 0 V debe estar conectado a tierra



Si aplica 5 V a la entrada n, la salida n se conmuta a tierra.

Si aplica 0 V a la entrada n, la salida n se desconectará.

Esto se puede utilizar fácilmente como un conjunto de interruptores que absorben la corriente.

[ 286 ]

www.it­ebooks.info
Machine Translated by Google

Capítulo 8

Combinado con 74HC595, controlaremos nuestra matriz LED 3 x 3 ahora mismo:

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.

Una matriz LED es básicamente una matriz donde:

• 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.it­ebooks.info
Machine Translated by Google

Diseño de retroalimentación de salida visual

Esto no es una ley y he encontrado algunas matrices conectadas de forma totalmente


opuesta y, a veces, de forma bastante extraña. Así que ten cuidado y consulta la hoja de datos.
Aquí vamos a estudiar una matriz LED muy básica para profundizar en ese concepto:

Una matriz LED básica de 3 x 3

Veamos el concepto de arquitectura de matriz LED.

¿Cómo podemos controlarlo? Por controlar, me refiero a dirigir el LED a un buen


comportamiento, ya sea encendido o apagado.

Imaginemos que si queremos encender el LED 2 tenemos que:

• Conecte ROW 1 a 5 V

• Conecte la COLUMNA 2 a tierra

¡Bien! Podemos encender ese LED 2.

Vayamos más allá. Imaginemos que, si queremos encender el LED 2 y el LED 4, tenemos que:

• Conecte ROW 1 a 5 V

• Conecte la COLUMNA 2 a tierra • Conecte


la FILA 2 a 5 V

• Conecte la COLUMNA 1 a tierra

[ 288 ]

www.it­ebooks.info
Machine Translated by Google

Capítulo 8

¿Notaste algo?

Si sigues los pasos cuidadosamente, deberías tener algo extraño en tu matriz:

Se encenderían los LED 1, LED 2, LED 4 y LED5.

Apareció el problema: si ponemos 5 V en la FILA 1, ¿cómo podemos distinguir la COLUMNA 1 y la


COLUMNA 2?

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:

• Conecte la FILA 1 a 5 V y la COLUMNA 1 a 5 V únicamente

• Luego, conecte la FILA 2 a 5 V y la COLUMNA 2 a 5 V solamente

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:

Para cada columna

Encender la columna

Para cada fila

Encienda la fila si se debe encender el LED correspondiente

[ 289 ]

www.it­ebooks.info
Machine Translated by Google

Diseño de retroalimentación de salida visual

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

Ahora revisemos el diagrama del circuito:

Diagrama de circuito que muestra el manejo de filas y columnas de la matriz.

[ 290 ]

www.it­ebooks.info
Machine Translated by Google

Capítulo 8

Tenemos el ahora conocido registro de desplazamiento 74HC595.

É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.

¿Qué es ese patrón de diseño?

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.

En particular, vamos a comprobar el código, incluido el ciclo de encendido y apagado de las


columnas explicado anteriormente.

El código de matriz LED 3 x 3


Puede encontrar el siguiente código de matriz LED 3 x 3 en el Capítulo 08/
LedMatrix3x3/ carpeta:

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

// variables aleatorias de la máquina de ranura


int contador = 0;
booleano LED_states[9] ;

configuración vacía() {

pinMode(LATCH_595, SALIDA);

[ 291 ]

www.it­ebooks.info
Machine Translated by Google

Diseño de retroalimentación de salida visual

pinMode(RELOJ_595, SALIDA);
pinMode(DATOS_595, SALIDA);

// utiliza una semilla proveniente del ruido electrónico del ADC randomSeed(analogRead(0));

bucle vacío() {

// generar un estado aleatorio para cada 9 LED para (int i = 0; i <


9; i++) {

LED_states[i] = aleatorio(2);
}

// inicializar datos en cada bucle() byte data = 0; byte


dataRow = 0; byte
dataColumn = 0; int
currentLed = 0;

// columnas cíclicas para (int


c = 0; c < 3; c++) {

// escribe el 1 en el lugar de bit correcto (= columna actual) dataColumn = 1 << (4 ­ c);

// filas cíclicas para (int


r = 0; r < 3; r++) {

// 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.it­ebooks.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);

dataRow = 0; // restableciendo los bits de fila para el próximo turno


currentLed++;// incrementando al siguiente LED a procesar
}

dataColumn = 0;// restableciendo los bits de la columna para el próximo turno


}

// cada 5000 ejecuciones de loop(), toma una nueva semilla para la función aleatoria

si (contador < 5000) contador++;


demás

{
semillaAleatoria(lectura analógica(0)); // lee un nuevo valor del pin analógico
0
contador = 0; // reiniciar el contador
}

// pausa un momento para dar un efecto más lindo


retraso(150);
}

Este código se explica por sí solo con comentarios, pero veámoslo un poco más.

La estructura global recuerda a la de Multiplexing_8Leds.

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:

• los datos son el byte enviado al registro de desplazamiento

• dataRow es la parte del estado de la fila de manejo de bytes (conmutada a 5 V o no)


• dataColumn es la parte del estado de la columna de manejo de bytes (conmutada a tierra
o no)
• currentLed mantiene el rastro de la corriente manejada por el LED

[ 293 ]

www.it­ebooks.info
Machine Translated by Google

Diseño de retroalimentación de salida visual

Luego se producen esos bucles imbricados.

Para cada columna (primer bucle for()), activamos el bucle utilizando un operador bit a bit pequeño,
económico y rápido:

columnaDeDatos = 1 << (4 – c);

(4 – c) va de 4 a 2, todo a lo largo de este primer bucle() ; función; luego, dataColumn


va de: 0 0 0 1 0 0 0 0 a 0 0 0 0 1 0 0 0, y por último 0 0 0 0 0 1 0 0.

¿Qué está pasando aquí? Todo es cuestión de codificación.

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.

Al suministrar 5 V desde Q0, Q1 y Q2 del 595, manejamos las filas. Al suministrar 5 V


desde Q3, Q4 y Q5 del 595, manejamos las columnas a través del ULN2003.
¡Bien!

Todavía tenemos dos bits no utilizados aquí, los dos últimos.

Veamos nuestro código nuevamente.

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.it­ebooks.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.

¿Cuál es la consecuencia del consumo actual?

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.

Simulación de salidas analógicas con PWM


Como ya sabemos muy bien, está bien encender/apagar LEDs, y como veremos en el próximo capítulo,
encender/apagar muchas cosas también usando pines digitales como salida en Arduino.

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.

Hasta donde sabemos, no hay salida analógica en el Arduino.

¿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.

De hecho, no hay un DAC en las placas Arduino.

[ 295 ]

www.it­ebooks.info
Machine Translated by Google

Diseño de retroalimentación de salida visual

El concepto de modulación por ancho de pulso


La modulación por ancho de pulso es una técnica muy común utilizada para imitar el comportamiento
de la salida analógica.

Digámoslo de otra manera.

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:

El concepto de ciclo de trabajo y PWM

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.it­ebooks.info
Machine Translated by Google

Capítulo 8

Tenga cuidado: ¡PWM no está disponible en todos los pines de su placa!


Por ejemplo, Arduino Uno y Leonardo proporcionan PWM en los pines digitales
números 3, 5, 6, 9, 10 y 11.
Debes saber esto antes de intentar cualquier cosa.

Atenuación de un LED
Vamos a comprobar un circuito básico para poder probar PWM:

Veamos el diagrama del circuito, aunque parezca obvio:

[ 297 ]

www.it­ebooks.info
Machine Translated by Google

Diseño de retroalimentación de salida visual

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.

Aquí está, modificado:

int ledPin = 11; // LED conectado al pin digital 11 (!!)

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);

// se desvanece del máximo al mínimo en incrementos de 5 puntos:


para (int valorDeFlare = 255; valorDeFlare >= 0; 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);

}
}

¡Súbelo, pruébalo y ámalo!

Un componente de controlador PWM de mayor resolución


Por supuesto, existen componentes que ofrecen resoluciones de PWM más altas. En este caso,
con placas Arduino nativas, tenemos una resolución de 8 bits (256 valores). Quería destacar el
Texas Instrument, TLC5940. Puedes encontrar su hoja de datos aquí: http://www.ti.com/
lit/ds/symlink/tlc5940.pdf.

[ 298 ]

www.it­ebooks.info
Machine Translated by Google

Capítulo 8

TLC5950, el controlador LED de 16 canales que proporciona control PWM

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.

Introducción rápida a la pantalla LCD


LCD significa pantalla de cristal líquido. Usamos tecnología LCD todos los días en relojes, pantallas de códigos
digitales, etc. Mire a su alrededor y observe estas pantallas LCD grandes o pequeñas.

[ 299 ]

www.it­ebooks.info
Machine Translated by Google

Diseño de retroalimentación de salida visual

Existen dos grandes familias de pantallas LCD:

• La pantalla LCD de caracteres se basa en una matriz de caracteres (columnas x filas)

• Pantalla LCD gráfica , se basa en una matriz de píxeles

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:

Una pantalla LCD de 16 x 2 caracteres

Lo conectaremos y mostraremos algunos mensajes en él.

[ 300 ]

www.it­ebooks.info
Machine Translated by Google

Capítulo 8

Circuito de pantalla LCD compatible con HD44780


Aquí está el circuito básico de la pantalla LCD compatible con HD44780:

Una pantalla LCD de 16 x 2 caracteres conectada a Arduino y un potenciómetro que controla su contraste.

El diagrama del circuito correspondiente es el siguiente:

Diagrama de circuito de la pantalla LCD de caracteres, el potenciómetro y la placa Arduino

[ 301 ]

www.it­ebooks.info
Machine Translated by Google

Diseño de retroalimentación de salida visual

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.

Por cierto, LED+ y LED­ son, respectivamente, el ánodo y el cátodo de la


retroiluminación del LED interno utilizado para la retroiluminación. Puedes controlarlos
desde Arduino, pero puede provocar un mayor consumo. Lee atentamente las instrucciones
y la hoja de datos de la pantalla LCD.

Mostrando algunos mensajes aleatorios


Aquí hay un firmware interesante. Puedes encontrarlo en la carpeta Chapter08/basicLCD/ :

#include <LiquidCrystal.h>

Cadena manyMessages[4]; int


contador = 0;

// Inicializa la biblioteca con el número de pines del circuito // Modo de 4 bits aquí sin RW

LCD de cristal líquido (12, 11, 5, 4, 3, 2);

configuración vacía() {

// configura el número de columnas y filas de la pantalla LCD lcd.begin(16, 2);

manyMessages[0] = "Yo soy Arduino"; manyMessages[1] =


"Puedo hablar"; manyMessages[2] = "Puedo
sentir"; manyMessages[3] = "Puedo reaccionar";

// ¡Agitando los dados!


randomSeed(analogRead(0);
}

bucle vacío() {

// establece el cursor en la columna 0 y la fila 0


lcd.setCursor(0, 0);

// cada 5s

[ 302 ]

www.it­ebooks.info
Machine Translated by Google

Capítulo 8

si (milisegundos() ­ contador > 5000)


{
lcd.clear(); // limpia toda la pantalla LCD
lcd.print(manyMessages[random(4)]); // muestra un mensaje aleatorio
contador = millis(); // almacena la hora actual
}

// establece el cursor en la columna 0 y la fila 1


lcd.setCursor(0, 1);
// imprime el valor de millis() en cada ejecución de loop()
lcd.print("en activo desde: " + millis() + "ms");
}

Primero, tenemos que incluir la biblioteca LiquidCrystal . Luego, definimos dos variables:

manyMessages es una matriz de cadenas para el almacenamiento de mensajes

• El contador es una variable utilizada para el seguimiento del tiempo.

Luego, inicializamos la biblioteca LiquidCrystal pasando algunas variables a su


constructor, correspondientes a cada pin utilizado para conectar la pantalla LCD al
Arduino. Por supuesto, el orden de los pines importa. Es: rs, enable, d4, d5, d6 y d7.

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 estáticamente algunos mensajes en cada elemento de la matriz de cadenas.

En el bloque loop() , primero colocamos el cursor en el primer lugar de la pantalla LCD.

, borramos toda la pantalla


Probamos la expresión (millis() – contador > 5000) y si es verdadera,
LCD. Luego, imprimo un mensaje definido por azar. De hecho, random(4)
produce un número pseudoaleatorio entre 0 y 3 y como ese índice , es aleatorio, imprimimos un
mensaje aleatorio en la pantalla LCD de entre los cuatro definidos en setup() en la pantalla LCD,
en la primera fila.

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.it­ebooks.info
Machine Translated by Google

Diseño de retroalimentación de salida visual

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.it­ebooks.info
Machine Translated by Google

Hacer que las cosas se muevan y


Creando sonidos
Si la placa Arduino puede escuchar y sentir con sensores, también puede reaccionar haciendo que las
cosas se muevan.

Por el concepto de movimiento me refiero a ambos aspectos siguientes:

• Movimientos de objetos

• Movimientos del aire que producen sonidos.

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.it­ebooks.info
Machine Translated by Google

Hacer que las cosas se muevan y suenen

Haciendo que las cosas vibren


Uno de los proyectos más sencillos que podemos presentar aquí es el uso de un pequeño
sensor piezoeléctrico.

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.

¿Pero no habría cometido un error al hablar de sensores que vibran?

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á.

Por eso utilizamos un sensor piezoeléctrico. Lo utilizamos como generador de vibraciones.

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.it­ebooks.info
Machine Translated by Google

Capítulo 9

Cableado de un motor de vibración


Los sensores piezoeléctricos suelen consumir alrededor de 10 mA a 15 mA, lo cual es muy poco.

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.it­ebooks.info
Machine Translated by Google

Hacer que las cosas se muevan y suenen

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.

Firmware que genera vibraciones


Verifique el firmware. También está disponible en la carpeta Chapter09/vibrations/ .

int piezoPin = 9; int value


= 0; // almacena el valor de alimentación actual
int incdec = 1; // almacena la dirección de la variación

configuración vacía() {

[ 308 ]

www.it­ebooks.info
Machine Translated by Google

Capítulo 9

bucle vacío() {

// Pruebe el valor actual y cambie la dirección si es necesario


si (valor == 0 || valor == 255) incdec *= ­1;

analogWrite(piezoPin, valor + incdec);


retraso(30);
}

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.

Lo usamos de la forma habitual con el parámetro incdec (que significa incremento­decremento).


Almacenamos el valor de incremento que queremos usar en cada ejecución de loop() .

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.

Ahora controlemos motores más grandes.

Conducción de corriente más alta y transistores


En el capítulo anterior hablamos de los transistores, que se utilizan como interruptores digitales.
También se pueden utilizar como amplificadores, estabilizadores de tensión y muchas otras aplicaciones
relacionadas.

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.it­ebooks.info
Machine Translated by Google

Hacer que las cosas se muevan y suenen

El siguiente es un diagrama básico que explica cómo funcionan los transistores:

El transistor utilizado como interruptor digital en circuitos lógicos.

Un transistor tiene las siguientes patas:

• 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.

Al enviar 5 V a la base del transistor se cierra el circuito. Al poner la base del


transistor a tierra se abre el circuito.

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.it­ebooks.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/servo­360_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.

¿Cuándo necesitamos servos?


Siempre que necesitemos una forma de controlar una posición relacionada con un ángulo de rotación, podemos
Utilice servos.

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.

Cómo controlar servos con Arduino


Hay una biblioteca muy interesante que debería usarse primero, llamada 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).

Los servos se proporcionan en paquetes de tres pines:

•5V

• Suelo

• Pulso; es decir, pin de control

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.it­ebooks.info
Machine Translated by Google

Hacer que las cosas se muevan y suenen

Revisemos el cableado básico.

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.it­ebooks.info
Machine Translated by Google

Capítulo 9

El diagrama del circuito correspondiente es el siguiente:

Un servo y Arduino

Básicamente estamos en un patrón de control basado en salida digital muy común.

Revisemos el código ahora.

Firmware que controla un servo mediante el


Biblioteca de servomotores
Aquí hay un firmware que proporciona un movimiento cíclico de 0 grados a 180 grados. También está
disponible en la carpeta Chapter09/OneServo/ .

#include <Servo.h>

Servo myServo; // instancia el objeto Servo


int angle = 0; // almacena el ángulo actual

configuración vacía()
{

[ 313 ]

www.it­ebooks.info
Machine Translated by Google

Hacer que las cosas se muevan y suenen

// pin 9 al objeto Servo myServo


miServo.attach(9);
}

bucle vacío() {

para(ángulo = 0; ángulo < 180; ángulo += 1) {

myServo.write(angulo);
retraso(20);

} para(ángulo = 180; ángulo >= 1; ángulo ­=1) {

myServo.write(angulo);
retraso(20);
}
}

Primero incluimos el encabezado de la biblioteca Servo .

Luego, creamos una instancia de objeto Servo llamada myServo.

En el bloque setup() tenemos que hacer algo especial. Conectamos el pin 9 al


Objeto myServo . Esto define explícitamente el pin como el pin de control para el servo.
instancia myServo.

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.

Servos múltiples con fuente de alimentación


externa
Imaginemos que necesitamos tres servos. Como ya hemos explicado, los servos son motores y los
motores convierten la corriente en movimiento, lo que hace que se transmita más corriente que otros
tipos de dispositivos, como los LED o los sensores.

[ 314 ]

www.it­ebooks.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.

Veamos cómo va con tres servos.

Tres servos y una fuente de alimentación externa.


Una fuente de alimentación externa pueden ser baterías o un adaptador de pared.

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.

Revisemos el cableado por ahora:

Tres servos conectados a un Arduino y alimentados por dos pilas AA

[ 315 ]

www.it­ebooks.info
Machine Translated by Google

Hacer que las cosas se muevan y suenen

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.

Revisemos el diagrama del circuito:

Tres servos, dos pilas AA y un Arduino

Conducción de tres servos con firmware


A continuación se muestra un ejemplo de firmware para controlar tres servos:

#include <Servo.h>

Servicio servicio01;
Servoservo02;
Servoservo03;

int ángulo;

configuración vacía()
{

[ 316 ]

www.it­ebooks.info
Machine Translated by Google

Capítulo 9

servo01.adjuntar(9);
servo02.adjuntar(10);
servo03.adjuntar(11);
}

bucle vacío() {

para(ángulo = 0; ángulo < 180; ángulo += 1) {

servo01.write(angulo);
servo02.write(135­ángulo/2);
servo03.write(angulo 180);

retraso(15);
}
}

Este firmware mínimo también está disponible en la carpeta Chapter09/Servos/ .

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 9 se activa con el propio valor del ángulo.

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.

Aprendamos un poco más sobre los motores paso a paso.

[ 317 ]

www.it­ebooks.info
Machine Translated by Google

Hacer que las cosas se muevan y suenen

Control de motores paso a paso


Motor paso a paso es el nombre común de un motor paso a paso. Son motores que se pueden
controlar mediante pequeños pasos.

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.

Por supuesto, podemos hacerlo usando placas Arduino.

Aquí examinaremos el motor paso a paso unipolar.

Conexión de un motor paso a paso unipolar a Arduino


Los motores paso a paso unipolares suelen estar formados por un eje central y cuatro bobinas
electromagnéticas. Los llamamos unipolares porque la energía entra por un polo. Podemos dibujarlos
de la siguiente manera:

Un motor paso a paso unipolar de seis pines

[ 318 ]

www.it­ebooks.info
Machine Translated by Google

Capítulo 9

Veamos cómo se puede conectar a nuestro Arduino.

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.it­ebooks.info
Machine Translated by Google

Hacer que las cosas se muevan y suenen

Veamos el diagrama del circuito correspondiente:

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.

Diseñemos firmware para el control del motor paso a paso.

Firmware que controla el motor paso a paso


Hay una librería muy linda que nos puede ahorrar el tener que proporcionar secuencias de los pines ALTO y BAJO,
teniendo en cuenta los movimientos que queremos realizar.

[ 320 ]

www.it­ebooks.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.

Veamos el que está disponible en http://www.sparkfun.com/datasheets/Robotics/


Motor paso a paso.pdf.

Sparkfun Electronics lo proporciona para un modelo diseñado por Robotics.

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.

#include <Paso a Paso.h>


#define PASOS 200

// crea una instancia de la clase stepper


Paso a paso paso a paso(PASOS, 8, 9, 10, 11);

int contador = 0; // almacena el número de pasos desde el último cambio de dirección


int multiplicador = 1; // un multiplicador básico

configuración vacía()
{
stepper.setSpeed(30); // establece la velocidad a 30 RPM
}

bucle vacío()
{

// moverse aleatoriamente desde al menos 1 paso

[ 321 ]

www.it­ebooks.info
Machine Translated by Google

Hacer que las cosas se muevan y suenen

paso a paso.paso(multiplicador);

// contando cuantos pasos ya recorrimos


// entonces si llegamos a un turno completo, reiniciamos el contador y retrocedemos
si (contador < PASOS) contador++ ;
demás {
contador = 0;
multiplicador *= ­1;
}
}

Primero incluimos la biblioteca Stepper .

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.it­ebooks.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.

Movimiento del aire y sonidos


Hacer que el aire se mueva puede generar sonidos audibles agradables, y vamos a aprender un poco más
sobre esto en las siguientes secciones.

Si puedes hacer que las cosas se muevan con Arduino, probablemente podrás hacer que el aire también se
mueva.

De hecho, ya lo hemos hecho, pero probablemente no lo movimos lo suficiente para producir un


sonido.

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.

¿Qué es realmente el sonido?


El sonido se puede definir como una onda mecánica. Esta onda es una oscilación de presión y puede
transmitirse a través de un sólido, un líquido o un gas. Por extensión, podemos definir el sonido como
el resultado audible de estas oscilaciones en nuestro oído.

Nuestro oído, combinado con otros procesos cerebrales, es un asombroso sensor de presión del aire.
Es capaz de evaluar lo siguiente:

• Amplitud de un sonido (relacionada con la cantidad de aire en movimiento)

• Frecuencia de un sonido (relacionada con la cantidad de oscilación del aire)

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.it­ebooks.info
Machine Translated by Google

Hacer que las cosas se muevan y suenen

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.

Cómo describir el sonido


Podemos describir el sonido de muchas maneras.

Generalmente existen dos representaciones 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.

• Variación de la amplitud en función del contenido de frecuencia. Esto se denomina representación de


los sonidos en el dominio de la frecuencia.

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

Aquí están las dos representaciones en los dos dominios:

Dos representaciones del mismo sonido elemental producido por una variación sinusoidal de la presión del aire

Describamos los dos gráficos de la imagen anterior.

[ 324 ]

www.it­ebooks.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:

Aquí, T es el período en segundos y f es la frecuencia en hercios.

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.it­ebooks.info
Machine Translated by Google

Hacer que las cosas se muevan y suenen

En ambos casos tenemos:

• Una membrana

• Un sistema transductor eléctrico

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.

En cada caso, tenemos señales analógicas.

Dominios digitales y analógicos


Las fuentes de sonido pueden ser muy diferentes. Si golpeas una mesa, oirás un sonido.
Se trata de un sonido básico analógico y físico. En este caso, haces vibrar un poco la mesa, empujando
y tirando del aire a su alrededor; y como estás cerca de ella, tu tímpano siente estas variaciones sutiles.

Cuando hablamos de equipos digitales, tenemos algunas limitaciones en cuanto a almacenamiento y


memoria. Si bien estos son grandes y suficientes en la actualidad, no son infinitos.

¿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.

Cómo digitalizar el sonido


Imagine un sistema que pudiera muestrear la variación de voltaje de sus micrófonos periódicamente.
Un concepto de muestreo que se utiliza habitualmente es el de muestreo y retención.

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.

Hablamos de la frecuencia de muestreo para definir la frecuencia de muestreo. Si la frecuencia de


muestreo es baja, tendremos una aproximación menor de la señal analógica que la que hubiéramos tenido
si la frecuencia de muestreo fuera alta.

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.it­ebooks.info
Machine Translated by Google

Capítulo 9

Ejemplo que ilustra la frecuencia de muestreo al muestrear una onda sinusoidal

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.

Otro elemento a tener en cuenta durante el muestreo es la profundidad de bits.

Lo omití voluntariamente en la figura anterior para no sobrecargar los dibujos.

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.it­ebooks.info
Machine Translated by Google

Hacer que las cosas se muevan y suenen

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.

A continuación se presentan dos estándares de calidad comúnmente utilizados:

• La calidad del CD es de 44,1 kHz y 16 bits.

• La calidad DAT es de 48 kHz y 16 bits.

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.

Cómo reproducir bits digitales como sonidos


También podemos convertir sonidos codificados digitalmente en sonidos analógicos. Este proceso se logra
mediante el conversor digital a analógico (DAC).

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.it­ebooks.info
Machine Translated by Google

Capítulo 9

Cómo Arduino ayuda a producir sonidos


Volvamos a Arduino.

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.

Reproducción de fragmentos de sonido básicos


Para reproducir un sonido se necesita una fuente de sonido y un altavoz. Por supuesto, también se
necesita un oyente que sea capaz de oír sonidos.

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 bit­banging y se basa en la alternancia de pines de E/S a una
frecuencia específica.

[ 329 ]

www.it­ebooks.info
Machine Translated by Google

Hacer que las cosas se muevan y suenen

Cableado del circuito de sonido más barato


Vamos a diseñar el generador de sonido más barato jamás creado con un pequeño altavoz
de 8 ohmios, una resistencia y una placa Arduino.

Un pequeño generador de sonido

Las conexiones realizadas aquí garantizan un sonido audible. Ahora programemos el chip.

[ 330 ]

www.it­ebooks.info
Machine Translated by Google

Capítulo 9

El diagrama del circuito correspondiente es el siguiente:

El diagrama del generador de sonido.

Tocando tonos aleatorios Como artista digital y,


específicamente, como músico electrónico, me gusta liberarme de las notas. A menudo utilizo
frecuencias en lugar de notas; si te interesa, puedes leer sobre el concepto microtonal en http://
en.wikipedia.org/wiki/Microtonal_
música.

En este ejemplo no utilizamos notas sino frecuencias para definir y activar nuestra música
electrónica.

El código también está disponible en la carpeta Chapter09/ToneGenerator/ .

void setup() { // iniciar


el generador de números pseudoaleatorios randomSeed(analogRead(0));

bucle vacío() {

[ 331 ]

www.it­ebooks.info
Machine Translated by Google

Hacer que las cosas se muevan y suenen

// generar tono y duración aleatorios int pitch =


random(30,5000); int duration = 1000 /
(random(1000) + 1);

// reproduce un tono en el pin digital PWM número 8 tone(8, pitch, duration);

// hacer una pausa


delay(duration * 1.30);

// detener la reproducción del tono


noTone(8);
}

Primero inicializamos el generador de números pseudoaleatorios leyendo la entrada


analógica 0.

En el bucle, generamos dos números:

• El tono es un número de 30 a 4.999; esta es la frecuencia del sonido • La duración


es un número de 1 ms a 1 s; esta es la duración del sonido

Estos dos argumentos son requeridos por la función tone() .

Luego, llamamos a tone(). El primer argumento es el pin donde alimentamos el altavoz.

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.

Si no proporcionamos una duración, el sonido continúa hasta que se llama a la función


noTone() . Esta última toma un argumento que también fue utilizado por el pin.

Ahora, escucha y disfruta de esta melodía pseudoaleatoria microtonal que proviene de tu


chip de 8 bits.

Mejorando el motor de sonido con Mozzi


La técnica de golpear la broca es muy barata y es bueno aprender cómo funciona.
Sin embargo, puedo citar algunas cosas molestas aquí:

• 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.it­ebooks.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.

Vamos a diseñar un pequeño motor de sonido basado en él.

Configuración de un circuito y una biblioteca Mozzi


Configurar el circuito es fácil; es el mismo que el último excepto que se debe usar el pin 9.

La documentación de Mozzi dice:

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 tenemos que instalar la librería en sí.

Descárguelo desde su sitio web: http://sensorium.github.com/Mozzi

Descomprímalo y cambie el nombre de la carpeta a Mozzi.

Luego ponlo como siempre en el lugar donde pones tus librerias, en mi caso es:

/Usuarios/julien/Documentos/Arduino/bibliotecas/

Reinicie o simplemente inicie su IDE de Arduino y podrá ver la biblioteca en el IDE.

Se proporciona con un montón de ejemplos.

Vamos a utilizar el de la onda sinusoidal.

[ 333 ]

www.it­ebooks.info
Machine Translated by Google

Hacer que las cosas se muevan y suenen

Así es como se ve la biblioteca Mozzi:

Una instalación de Mozzi que revela muchos ejemplos

[ 334 ]

www.it­ebooks.info
Machine Translated by Google

Capítulo 9

Un ejemplo de onda sinusoidal


Como en cualquier biblioteca, tenemos que aprender a utilizar la onda sinusoidal.

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.

Veamos el ejemplo de onda sinusoidal. También está disponible en la carpeta Chapter09/


MozziSoundGenerator/ .

#include <MozziGuts.h> #include


<Oscil.h> // plantilla del oscilador #include <tables/sin2048_int8.h> //
tabla de senos para el oscilador

// uso: Oscil <tamaño_de_tabla, tasa_de_actualización> oscilName (tabla de ondas)


Oscil < SIN2048_NUM_CELDAS , VELOCIDAD_DE_AUDIO > aSin( SIN2048_DATOS );

// use #define para CONTROL_RATE, no una constante #define


CONTROL_RATE 64 // potencias de 2 por favor

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

con un int sin signo o un float

void updateControl(){ // coloca


los controles cambiantes aquí
}

int updateAudio(){ return


aSin.next(); // devuelve una señal int centrada alrededor de 0
}

void loop()
{ audioHook(); // requerido aquí
}

[ 335 ]

www.it­ebooks.info
Machine Translated by Google

Hacer que las cosas se muevan y suenen

Al principio se realizan algunas inclusiones.

MozziGuts.h es el encabezado básico que debe incluirse en cualquier caso.

Oscil.h es el encabezado a utilizar si necesita un oscilador.

Luego incluimos una tabla de ondas (onda sinusoidal).

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.

Básicamente, lo usamos como tabla de búsqueda. ¿Recuerdas haberlo usado?

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.it­ebooks.info
Machine Translated by Google

Capítulo 9

Veamos qué podemos encontrar en el archivo sin2048_int8.h :

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.

Luego definimos el objeto Oscil que crea un oscilador.

Después de la segunda palabra clave de definición relacionada con la frecuencia de actualización de la


variable, tenemos la estructura habitual de setup() y loop().

[ 337 ]

www.it­ebooks.info
Machine Translated by Google

Hacer que las cosas se muevan y suenen

También tenemos updateControl() y updateAudio() , que no están definidas en el código. De


hecho, están relacionadas con Mozzi y están definidas en los archivos de la biblioteca.

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.

Nada más sobre updateControl() aquí.

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.

En loop(), llamamos a la función audioHook() .

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):

• Definiciones en el encabezado con algunas inclusiones

• Inicio del motor de audio

• Bucle permanente de un gancho

• 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.

Modulación de frecuencia de una onda sinusoidal


Ahora fusionemos algunos conceptos: generación de ondas sinusoidales, modulación
y lectura de entrada.

Vamos a utilizar dos osciladores, uno modulando la frecuencia del otro.

Con un potenciómetro podemos controlar la frecuencia del oscilador modulador.

Primero mejoraremos el circuito agregando un potenciómetro.

[ 338 ]

www.it­ebooks.info
Machine Translated by Google

Capítulo 9

Añadiendo una olla


En el siguiente diagrama de circuito, hemos agregado un potenciómetro en el circuito
generador de sonido:

[ 339 ]

www.it­ebooks.info
Machine Translated by Google

Hacer que las cosas se muevan y suenen

El diagrama del circuito es el siguiente:

Mejorando el generador de sonido

Actualización del firmware para el manejo de entradas


Este código también está disponible en la carpeta Chapter09/MozziFMOnePot/ .

#include <MozziGuts.h> #include


<Oscil.h> #include <tables/
cos8192_int8.h> // tabla para que Oscils la reproduzca #include <utils.h> // para mtof

#define CONTROL_RATE 64 // potencias de 2 por favor

Oscil<COS8192_NUM_CELDAS, VELOCIDAD_DE_AUDIO> aCos(COS8192_DATOS);


Oscil<COS8192_NUM_CELDAS, VELOCIDAD_DE_AUDIO> aVibrato(COS8192_DATOS);

const long intensidadMáx = 500;

int potPin = A0; int potValue


= 0;

[ 340 ]

www.it­ebooks.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:

• aCos representa el sonido en sí

• aVibrato es el modulador

Como tenemos un potenciómetro aquí, necesitamos escalar las cosas un poco.

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.

Continuemos con la revisión del código.

Definimos el pin n del potenciómetro y la variable potPin. También definimos potValue


a 0.

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.it­ebooks.info
Machine Translated by Google

Hacer que las cosas se muevan y suenen

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.

Y lo más inteligente aquí es el método updateControl() . Agregamos la función analogRead()


que lee el valor de la entrada analógica. Hacer esto en updateControl() es mejor, considerando el
propósito de esta función. De hecho, el marco de trabajo de Mozzi separa las tareas críticas en el
tiempo de renderizado de audio de las partes del código de control (especialmente el control humano).

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.

Aquí, leemos el valor en updateControl() y lo almacenamos en la variable potValue .

Luego, en updateAudio(), calculamos el valor del vibrato como el valor de potValue


escalado desde 0 hasta el valor de intensityMax, multiplicado por el siguiente valor del oscilador en
su tabla de ondas.

[ 342 ]

www.it­ebooks.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.

Controlar el sonido mediante envolventes y MIDI

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.

Una descripción general de MIDI


MIDI es la abreviatura de Musical Instrument Digital Interface (Interfaz digital para instrumentos musicales). Se
trata de un estándar de especificación que permite que los instrumentos musicales digitales, los
ordenadores y todos los dispositivos necesarios se conecten y se comuniquen entre sí. Se introdujo en
1983 y, en el momento de redactar este artículo, acaba de celebrar su 30.º aniversario. El sitio web de
referencia es http://www.midi.org.

MIDI puede transportar los siguientes datos a través de un enlace serial básico:

• Notas (activación/desactivación, después del toque)

• Cambios de parámetros (cambio de control, cambio de programa)

• Mensajes en tiempo real (reloj, estado del transporte como inicio/detención/continuación)

• Exclusivas del sistema, que permiten a los fabricantes crear su mensaje

Apareció un nuevo protocolo que hoy en día se utiliza ampliamente: OSC. Por cierto, no es un protocolo
propiamente dicho.

[ 343 ]

www.it­ebooks.info
Machine Translated by Google

Hacer que las cosas se muevan y suenen

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 Wi­Fi e incluso a través de Internet.

Librerías MIDI y OSC para Arduino


Sugeriría dos bibliotecas. Las he probado yo mismo y son estables y eficientes.
Puedes consultar el artículo sobre MIDI en http://sourceforge.net/projects/
arduinomidilib. Puedes consultar este sobre OSC en https://github.com/
recotana/ArdOSC. No deberías tener demasiadas dificultades para instalarlos ahora.
Instalemos al menos MIDI y reiniciemos el IDE.

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.it­ebooks.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:

Una onda sinusoidal

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.it­ebooks.info
Machine Translated by Google

Hacer que las cosas se muevan y suenen

Aquí está el resultado con otro sobre:

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.

Esto produce una sólida evolución a lo largo del tiempo.

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.

Una envolvente que modula el tono de un sonido.

Implementando envolventes y MIDI


Vamos a diseñar un sintetizador de sonido muy económico que podrá disparar notas cuando reciba un
mensaje de nota MIDI y alterar el sonido cuando reciba un mensaje de cambio de control MIDI particular.

[ 346 ]

www.it­ebooks.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

// use #define para CONTROL_RATE, no una constante #define


CONTROL_RATE 128 // potencias de 2 por favor

// 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;

float vol= 1. ; // almacena el volumen de salida maestro

unsigned int freq; // para transmitir información de control desde el controlador MIDI a updateControl()

void HandleControlChange(byte canal, byte número CC, byte valor) {


switch(CCnumber){ caso 100:

vol = map(valor,0, 127, 0., 1.);


romper;
}
}

void HandleNoteOn(canal de byte, tono de byte, velocidad de byte) {

[ 347 ]

www.it­ebooks.info
Machine Translated by Google

Hacer que las cosas se muevan y suenen

// Velocidad de escala para desvanecimiento lineal de alta resolución en Note­off más tarde
frecuencia = mtof(tono);
aGain.set(velocity<<8); // podría ser necesario un fundido de entrada para evitar clics

void HandleNoteOff(canal de byte, tono de byte, velocidad de byte) {

// Velocidad de escala para desvanecimiento lineal de alta resolución en Note­off más tarde
aGain.set(0,liberar_pasos_de_audio);
contador_de_desvanecimiento = pasos_de_control_de_liberación;
}

configuración vacía() {

// Iniciar comunicaciones MIDI, escuchar todos los canales


MIDI.begin(MIDI_CHANNEL_OMNI);

// Conecte la función HandleControlChange a la biblioteca, de modo que sea


llamado al recibir un NoteOn.
MIDI.setHandleControlChange(HandleControlChange); // Coloque solo el
nombre de la función

// Conecte la función HandleNoteOn a la biblioteca, de modo que se llame al recibir un


NoteOn.
MIDI.setHandleNoteOn(HandleNoteOn); // Coloque solo el nombre de la función

// Conecte la función HandleNoteOn a la biblioteca, de modo que se llame al recibir un


NoteOn.
MIDI.setHandleNoteOff(HandleNoteOff); // Coloque solo el nombre de la función

aSin.setFreq(440u); // frecuencia predeterminada


iniciarMozzi(CONTROL_RATE);
}

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.it­ebooks.info
Machine Translated by Google

Capítulo 9

// Generación de audio y control de frecuencia midi sensible.


MIDI.leer();

if (fade_counter­­ <=0) aGain.set(0,0,2); // una línea a lo largo de 0


}

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í
}

Primero incluimos la biblioteca MIDI. Luego incluimos la biblioteca Mozzi.

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.

También incluimos la tabla de ondas relacionada con un seno.

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.

Luego definimos el oscilador como aSin.

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.it­ebooks.info
Machine Translated by Google

Hacer que las cosas se muevan y suenen

HandleControlChange() es una función que se llama cuando se envía un mensaje de cambio


de control MIDI a Arduino. El mensaje incluye estos bytes:

• Canal MIDI
• Número de CC
• Valor

Estos argumentos se pasan a la función HandleControlChange() y puedes acceder a ellos


directamente en tu código.

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.

De la misma manera, HandleNoteOn() y HandleNoteOff() manejan mensajes de notas


MIDI.

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.

Aquí tenemos dos funciones que manejan estos mensajes.

HandleNoteOn() analiza el mensaje, toma la parte de velocidad, la desplaza a la izquierda


hasta 8 bits y la pasa a aGain a través del método set() . Cuando se recibe un mensaje MIDI
Note On, la envolvente aGain se activa hasta su valor máximo. Cuando se recibe un mensaje
MIDI Note Off, la envolvente se activa hasta llegar a 0 en un segundo a través de la
cantidad de pasos de audio discutidos anteriormente. El contador de desvanecimiento
también se restablece a su valor máximo en el momento en que se suelta la tecla.

[ 350 ]

www.it­ebooks.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.

El método setup() incluye la configuración de la biblioteca MIDI:

• MIDI.begin() instancia la comunicación

• MIDI.setHandleControlChange() le permite definir el nombre de la función llamada cuando llega un


mensaje de cambio de control.

• MIDI.setHandleNoteOn() le permite definir el nombre de la función llamada cuando llega un mensaje


de Note On

• MIDI.setHandleNoteOff() le permite definir el nombre de la función llamada cuando llega un mensaje


de Note Off

También incluye la configuración de Mozzi.

La función loop() nos resulta bastante familiar ahora.

La función updateControl() no contiene la parte crítica en cuanto al tiempo del generador de


sonido. Esto no significa que esta función se llame con poca frecuencia; se llama menos que
updateAudio(): 128 veces por segundo para el control y 16.384 veces por segundo para el audio, como
hemos visto antes.

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.it­ebooks.info
Machine Translated by Google

Hacer que las cosas se muevan y suenen

Cableado de un conector MIDI a Arduino


Este esquema se basa en el diagrama de especificación eléctrica MIDI en http://
www.midi.org/techspecs/electrispec.php.

El generador de sonido con funciones MIDI basado en Arduino

[ 352 ]

www.it­ebooks.info
Machine Translated by Google

Capítulo 9

El diagrama del circuito correspondiente es el siguiente:

El conector MIDI conectado al generador de sonido basado en Arduino

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.it­ebooks.info
Machine Translated by Google

Hacer que las cosas se muevan y suenen

Subamos el código e iniciemos este pequeño secuenciador en Max 6.

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.it­ebooks.info
Machine Translated by Google

Capítulo 9

Reproducción de archivos de audio con la biblioteca PCM


Otra forma de reproducir sonidos es leyendo sonidos ya digitalizados.

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 página de referencia es http://hlt.media.mit.edu/?p=1963.

Descargue la biblioteca e instálela.

Imaginemos que tenemos suficiente espacio en la memoria de Arduino. ¿Cómo podemos


realizar la instalación si queremos convertir una muestra de nuestros discos en una
estructura compatible con C?

La biblioteca PCM
Comprueba este código. También está disponible en la carpeta Chapter09/PCMreader/ .

Nuestro lector PCM

[ 355 ]

www.it­ebooks.info
Machine Translated by Google

Hacer que las cosas se muevan y suenen

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.

WAV2C – conversión de su propia muestra


Como ya hemos jugado con wavetable, y esto es lo que haremos a continuación, podemos almacenar
nuestras formas de onda de muestra en el código Arduino directamente.

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.

Primero tenemos que transformar una muestra en datos C.

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.

Tenga cuidado de pegarlo correctamente entre las llaves.

[ 356 ]

www.it­ebooks.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:

Una gran cantidad de datos para pegar en una matriz C

En la misma carpeta he metido un archivo .wav que he diseñado. Es un ritmo corto grabado en 16 bits.

[ 357 ]

www.it­ebooks.info
Machine Translated by Google

Hacer que las cosas se muevan y suenen

Cableado del circuito


El circuito es similar al de la sección Reproducción de bits de sonido básicos , excepto que
aquí tenemos que usar el pin digital 11. Y no podemos usar PWM en los pines 3, 9 y 10
porque los temporizadores involucrados en la biblioteca los consumen.

Cableado de nuestro lector PCM

[ 358 ]

www.it­ebooks.info
Machine Translated by Google

Capítulo 9

El diagrama del circuito también es fácil.

No olvides utilizar el pin 11 con la librería PCM

Ahora, vamos a tocar la música.

Otras bibliotecas de lectores


También hay otras bibliotecas que proporcionan formas de leer y decodificar el formato MP3 o
Otros formatos.

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.it­ebooks.info
Machine Translated by Google

Hacer que las cosas se muevan y suenen

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.

Te recomiendo que lo pruebes. Hay muchos ejemplos en el sitio web de Sparkfun.

Resumen
Aprendimos cómo hacer que las cosas se muevan aquí con Arduino. En particular, aprendimos sobre:

• Mover objetos sólidos con motores.

• Mover el aire con generadores de sonido.

Por supuesto, lamentablemente no puedo describir más sobre cómo hacer que las cosas se muevan.

Si necesita ayuda con el sonido, contácteme en book@cprogrammingforarduino.


com. También estaré encantado de ayudarte con las entradas de sonido, por ejemplo.

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 Wi­Fi. Por último,
diseñaremos una pequeña biblioteca juntos y revisaremos algunos buenos consejos y trucos para mejorar
nuestro código C.

[ 360 ]

www.it­ebooks.info
Machine Translated by Google

Algunas técnicas avanzadas


En este capítulo, aprenderemos diferentes técnicas que se pueden utilizar de forma conjunta o
independiente. Cada técnica desarrollada aquí es una nueva herramienta para sus proyectos
actuales o futuros. Vamos a utilizar EEPROM para proporcionar a las placas Arduino un pequeño sistema
de memoria que se pueda leer y escribir.

También vamos a probar las comunicaciones entre las propias placas Arduino, utilizar módulos GPS,
hacer autónomas nuestras placas, y más.

Almacenamiento de datos con EEPROM


Hasta ahora, hemos aprendido a utilizar las placas Arduino como dispositivos totalmente dependientes
de la electricidad, es decir, necesitan corriente para ejecutar las tareas compiladas en nuestro firmware.

Como hemos observado, cuando los apagamos, se pierden todas las variables y datos vivos.
Afortunadamente, el firmware no lo es.

Tres reservas nativas de memoria en el


Placas Arduino
Las placas Arduino basadas en el chipset ATmega168 poseen tres grupos de memoria diferentes:

• Memoria flash
• Memoria RAM

• Memoria EEPROM

La memoria flash también se denomina espacio de programa. Es el lugar donde se almacena


nuestro firmware.

www.it­ebooks.info
Machine Translated by Google

Algunas técnicas avanzadas

SRAM significa memoria de acceso aleatorio estático y es el lugar donde el firmware en


ejecución almacena, lee y manipula variables.

EEPROM significa memoria de sólo lectura programable y borrable eléctricamente .


Es el lugar donde nosotros, los programadores, podemos almacenar cosas para propósitos a largo plazo.
Este es el lugar donde se encuentra nuestro firmware, y nada en la EEPROM se borra si se apaga la placa.

ATmega168 tiene:

• 16000 bytes de Flash (2000 bytes se utilizan para el gestor de arranque)


• 1024 bytes de SRAM
• 512 bytes de EEPROM

Aquí no discutiremos el hecho de que tenemos que cuidar la memoria mientras


programamos; lo haremos en el último capítulo de este libro, el Capítulo 13, Mejorando su
programación en C y creando bibliotecas.

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.

Escritura y lectura con la biblioteca central EEPROM


Básicamente, este ejemplo no requiere ningún cableado. Vamos a utilizar la EEPROM interna
de 512 bytes. Aquí hay un código que lee todos los bytes de la EEPROM y los imprime en el
monitor serial de la computadora:

#include <EEPROM.h>

// comienza a leer desde el primer byte (dirección 0) de la EEPROM


int dirección = 0;
valor de byte;

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.it­ebooks.info
Machine Translated by Google

Capítulo 10.

Serial.print(dirección);
Serie.print("\t");
Serial.print(valor, DEC);
Serie.println();

// avanzar a la siguiente dirección de la EEPROM


dirección = dirección + 1;

// solo hay 512 bytes de EEPROM, de 0 a 511, así que si estamos


// en la dirección 512, volver a la dirección 0
si (dirección == 512)
dirección = 0;

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.

Pasamos a la siguiente dirección, comprobamos si la dirección es igual a 512, si es así reiniciamos el


contador de direcciones a 0 y así sucesivamente.

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.it­ebooks.info
Machine Translated by Google

Algunas técnicas avanzadas

Cableado de EEPROM externa


Existen muchos componentes EEPROM baratos disponibles en los mercados de productos
electrónicos. Vamos a utilizar el clásico 24LC256, un EEPROM que implementa I2C para
operaciones de lectura/escritura y que ofrece 256 kilobits (32 kilobytes) de espacio de memoria.

Puedes encontrarlo en Sparkfun: https://www.sparkfun.com/products/525. Así es como podemos conectar


su primo mayor 24LC1025 (1024k bytes) usando I2C:

Una EEPROM 24LC256 conectada al Arduino a través de comunicación I2C

[ 364 ]

www.it­ebooks.info
Machine Translated by Google

Capítulo 10.

El diagrama correspondiente es el que se muestra a continuación:

3V3 5V Venir
Fuerza
D13

Primera vez D12

ARÉF D11
Modulación por ancho de pulso (PWM)

Yo ref. Arduino D10


Modulación por ancho de pulso (PWM)

D9
Modulación por ancho de pulso (PWM)

CAROLINA DEL NORTE

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

Adventista del Séptimo Día

Tierra

Una EEPROM 24LC256 conectada al Arduino a través de comunicación I2C

Describamos la EEPROM.

A0, A1 y A2 son entradas de dirección del chip. +V y 0V son 5V y tierra. WP es el pin de


protección contra escritura. Si está conectado a tierra, podemos escribir en la EEPROM. Si está
conectado a 5V, no podemos.

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:

• El Arduino UNO antes de R3 y los pines I2C de Ethernet son A4 (SDA) y


A5 (SCL)
• Mega2560, pines 20 (SDA) y 21 (SCL) •
Leonardo, pin 2 (SDA) y pin 3 (SCL) • Due Pins,
pines 20 (SDA) y 21 (SCL) y también otro SDA1 y SCL1

[ 365 ]

www.it­ebooks.info
Machine Translated by Google

Algunas técnicas avanzadas

Lectura y escritura en la EEPROM


La biblioteca subyacente que podemos utilizar para fines I2C es Wire. Puedes encontrarla
directamente en el núcleo de Arduino. Esta biblioteca se encarga de los elementos básicos, pero
tenemos que analizarla más de cerca.

La biblioteca Wire se encarga de muchas cosas por nosotros. Veamos el código en la carpeta
Chapter10/readWriteI2C:

#include <Cable.h>

void eepromWrite(byte dirección, byte source_addr, byte datos) {


Wire.beginTransmission(dirección);
Wire.write(dirección_de_origen);
Wire.write(datos);
Wire.endTransmission();
}

byte eepromRead(int dirección, int dirección_origen) {


Wire.beginTransmission(dirección);
Wire.write(dirección_origen);
Wire.endTransmission();

Wire.requestFrom(dirección, 1);
si(Cable.disponible())
devuelve Wire.read();
demás
devuelve 0xFF;
}

configuración vacía() {
Cable.begin();
Serial.begin(9600);

para (int i = 0; i < 10; i++) {


eepromWrite(B01010000, i, 'a'+i); retraso(100);

Serial.println("¡Bytes escritos en EEPROM externa!");


}

bucle vacío() { para(int


i = 0; i < 10; i++) { byte val =
eepromRead(B01010000, i);

[ 366 ]

www.it­ebooks.info
Machine Translated by Google

Capítulo 10.

Serie.print(i);
Serie.print("\t");
Serie.print(val);
Serie.print("\n");
retraso(1000);
}
}

Incluimos primero la biblioteca Wire y luego definimos dos funciones:

• 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.

En la función loop() , leemos la EEPROM. Es bastante similar a la biblioteca EEPROM.

Obviamente, todavía no hemos hablado de direcciones. Aquí hay un formato de mensaje I2C:

Bit de lectura/escritura

Código de control Bits de selección de chip

S 1 0 1 0 A2 A1 A0 R/W ACK

Dirección de esclavo

Bit de inicio Bit de reconocimiento

Un mensaje I2C

[ 367 ]

www.it­ebooks.info
Machine Translated by Google

Algunas técnicas avanzadas

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.

Uso de módulos GPS


GPS significa Sistema de Posicionamiento Global. Este sistema se basa en constelaciones de
satélites.

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.

No entraremos en detalles sobre este proceso; nos centraremos en el análisis de los


datos que llegan desde los módulos GPS. Puedes obtener más información en
Wikipedia: http://en.wikipedia.org/wiki/Global_Positioning_System.

Cableado del módulo receptor GPS Parallax


El receptor GPS Parallax se basa en la especificación PMB­248 y proporciona una forma muy sencilla de
agregar detección de posición al Arduino con su pequeño tamaño y bajo costo.

[ 368 ]

www.it­ebooks.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)

El receptor GPS Parallax: tamaño reducido y precisión

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).

NMEA0183 es una especificación combinada de hardware y lógica para la comunicación entre


dispositivos electrónicos marinos, como sonares, anemómetros y muchos otros, incluido el GPS.
Puede encontrar una excelente descripción de este protocolo aquí: http://aprs.
http://www.gids.nl/nmea/.

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:

• $GPGGA: Datos de corrección del sistema de posicionamiento global

• $GPGSV: Satélites GPS a la vista


• $GPGSA: GPS DOP y satélites activos

• $GPRMC: Datos de tránsito/GPS específicos mínimos recomendados

[ 369 ]

www.it­ebooks.info
Machine Translated by Google

Algunas técnicas avanzadas

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

El cableado es bastante sencillo.

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.it­ebooks.info
Machine Translated by Google

Capítulo 10.

Análisis de datos de ubicación GPS


Antes de construir cualquier firmware que pueda utilizar datos GPS, debemos saber un poco más sobre lo que el
dispositivo puede transmitir.

Podemos leer la hoja de datos del dispositivo GPS en: http://www.rcc.ryerson.ca/medi a/


2008HCLParallaxGPSReceiverModuledatasheet.pdf.

A continuación se muestra un ejemplo de datos que se pueden transmitir:

$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.

Aquí está el significado de cada campo:

1. Hora UTC de la corrección

2. Estado de los datos (A significa posición válida y V significa advertencia)


3. Latitud de la fijación

4. Latitud norte o sur

5. Longitud del punto de referencia

6. Longitud este u oeste 7. Velocidad

sobre el suelo (en nudos)

8. Trayectoria corregida en grados 9. Fecha


UTC de corrección

10. Variación magnética en grados 11. Variación

magnética Este u Oeste 12. Suma de comprobación

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:

int rxPin = 0; int // PIN DE RECIBIR

byteGPS = ­1; char línea[300] // Byte leído actual


= ""; char comandoGPR[7] = // Buffer
"$GPRMC"; // Cadena relacionada con los mensajes

int contador=0; int


corrección=0;
int contadorDeLínea=0; int
índice[13];

[ 371 ]

www.it­ebooks.info
Machine Translated by Google

Algunas técnicas avanzadas

configuración vacía() {

pinMode(rxPin, ENTRADA);
Serial.begin(4800);

// Limpiar el buffer para


(int i=0;i<300;i++){
línea[i]=' ';
}
}

bucle vacío() {

byteGPS = Serial.read(); //Leer un byte desde el puerto serial

// Probar si el puerto está vacío if (byteGPS


== ­1) { delay(100);

else { // si no está vacío

line[lineCounter] = byteGPS; // coloca los datos leídos en el buffer lineCounter++;

Serial.print(byteGPS); // imprime los datos leídos en el monitor serial

// Probamos si la transmisión ha finalizado // si ha finalizado


comenzamos a analizar ! if (byteGPS==13){

contador=0;corrección=0;

// Probar si el comando recibido comienza con $GPR


// Si es así, aumenta el contador de corrección para (int i=1;i<7;i++){ if
(line[i]==commandGPR[i­1]){ correctness+

}
}

if(correctness==6){ // Estamos
seguros de que el comando está bien aquí.

//
para (int i=0;i<300;i++){

[ 372 ]

www.it­ebooks.info
Machine Translated by Google

Capítulo 10.

// almacena la posición de los separadores "," si (line[i]==','){

í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++;

}
}

// Escribe datos en el monitor serial de la computadora Serial.println(""); Serial.println("");


Serial.println("­­­­­­­­­­­­­­­"); for (int
i=0;i<12;i++){ switch(i){ case 0 :
Serial.print("Hora en UTC (HhMmSs): "); break;

caso 1 :
Serial.print("Estado (A=OK,V=KO): "); break; caso 2 :

Serial.print("Latitud: "); break; caso 3 : Serial.print("Dirección


(N/S): ");
break;

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 :

Serial.print("Encabezado en grados: "); break; case 8 :

Serial.print("Fecha UTC (DdMmAa): "); break;

caso 9 :
Serial.print("Grados magnéticos: "); break;

[ 373 ]

www.it­ebooks.info
Machine Translated by Google

Algunas técnicas avanzadas

caso 10 :

Serial.print("(E/W): "); break;

caso 11 :
Serial.print("Modo: "); break; caso 12 :

Serial.print("Suma de comprobación: "); break;

} para (int j=índice[i];j<(índice[i+1]­1);j++){ Serial.print(línea[j+1]);

}
serie.println("");
}
Serie.println("­­­­­­­­­­­­­­­");
}

// Restablecer el buffer
lineCounter=0; for (int
i=0;i<300;i++){ line[i]=' ';

}
}
}
}

Vamos a explicar un poco el código. Primero, defino varias variables:

• rxPin es la entrada digital donde está conectado el dispositivo


GPS • byteGPS es el último byte leído del GPS mediante comunicación serial • line
es una matriz de búfer •
commandGPR es una cadena relacionada con los mensajes que
queremos analizar • counter es el índice de la
matriz de índice • correctness almacena la validez del
mensaje • lineCounter es un contador que mantiene un registro de la posición del
búfer de los datos • index almacena la posición de cada uno de los separadores en la cadena de datos GPS (",")

[ 374 ]

www.it­ebooks.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.

Reiniciamos el contador y las variables de corrección y comprobamos si los primeros 6 caracteres en


El buffer es igual a $GPRMC. Para cada coincidencia, incrementamos la variable de corrección .

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.it­ebooks.info
Machine Translated by Google

Algunas técnicas avanzadas

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]

Analizar progresivamente cada parte del mensaje según cada separador

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.it­ebooks.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.

Arduino, batería y autonomía


Las placas Arduino pueden suministrar energía de dos maneras:

• Un cable USB desde una computadora

• Una fuente de alimentación externa

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.

Veamos algunos casos de uso real.

Casos clásicos de alimentación por USB


¿Por qué y cuándo deberíamos utilizar una fuente de alimentación USB?

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.

Esta es la razón principal para utilizar una fuente de alimentación 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.it­ebooks.info
Machine Translated by Google

Algunas técnicas avanzadas

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.

Suministro de energía externa


Existen dos formas diferentes de suministrar energía a un sistema basado en Arduino. Podemos decir que las dos
fuentes de alimentación principales son:

• 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.it­ebooks.info
Machine Translated by Google

Capítulo 10.

Comprobemos el cableado básico con una batería de 9 V:

Una batería de 9 V conectada a una placa Arduino UNO R3

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:

Una batería clásica de tipo botón

[ 379 ]

www.it­ebooks.info
Machine Translated by Google

Algunas técnicas avanzadas

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:

Arduino Pro Mono

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.

Adaptador de corriente para fuente de alimentación Arduino


Para proyectos que requieren más potencia, tenemos que utilizar una fuente de alimentación externa. La
configuración de Arduino es la misma que con las baterías. El adaptador Arduino que se vende en el mercado
debe cumplir algunos requisitos:

• Adaptador de CC (¡Aquí no hay adaptador de CA!)

• Voltaje de salida entre 9V y 12V DC

• Capaz de generar una corriente mínima de 250 mA, pero con un objetivo de 500 mA como mínimo o
Preferiblemente 1A

• Debe tener un enchufe de alimentación de 2,1 mm con centro positivo

[ 380 ]

www.it­ebooks.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:

El símbolo que muestra el enchufe positivo central

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.

Cómo calcular el consumo actual


Para calcular la corriente en su circuito, debe utilizar la ley de Ohm como se describe en el primer capítulo de
este libro.

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/YSL­R596CR3G4B5C­C10.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.

Seguramente ya habrás comprendido la estrategia que ya utilizamos en el ciclo de alimentación, encendiendo


cada LED uno tras otro en rápida sucesión. Esto permite reducir el consumo de energía y también permite que
algunos proyectos utilicen muchos LED sin necesidad de un adaptador de alimentación externo.

[ 381 ]

www.it­ebooks.info
Machine Translated by Google

Algunas técnicas avanzadas

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.

Te sugeriría que hagas algunos cálculos para asegurarte de:

• No anule la capacidad de Arduino por pines

• 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.

Dibujo sobre gLCD


Dibujar siempre es divertido. Dibujar y manipular pantallas LCD en lugar de matrices de LED
también es muy interesante, porque tenemos dispositivos con puntos de alta densidad que podemos
encender y apagar fácilmente.

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 glcd­arduino. Esta biblioteca tiene licencia GNU Lesser GPL.

Vamos a descargarlo aquí: http://code.google.com/p/glcd­arduino/downloads/


Lista. Descargue la versión más reciente.

Descomprímelo, colócalo en el lugar donde están todas tus librerías y reinicia o inicia tu IDE de
Arduino.

Ahora debería ver muchos ejemplos relacionados con la biblioteca gLCD.

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.it­ebooks.info
Machine Translated by Google

Capítulo 10.

Cableado del dispositivo


Vamos a comprobar el cableado de un Panel B tipo gLCD basado en KS0108:

Un montón de cables que conectan el gLCD a Arduino y el potenciómetro para ajustar el contraste del LCD.

El esquema eléctrico correspondiente es el siguiente:

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)

Yo ref. Arduino D10


Modulación por ancho de pulso (PWM)
14 DB7

D9 13 DB6
Modulación por ancho de pulso (PWM)

CAROLINA DEL NORTE

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

Panel B gLCD basado en KS0108 conectado a un Arduino Uno R3

[ 383 ]

www.it­ebooks.info
Machine Translated by Google

Algunas técnicas avanzadas

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 :

La documentación de gLCD­Arduino que muestra el sistema de coordenadas de la pantalla

[ 384 ]

www.it­ebooks.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.

Algunas familias de métodos útiles


Sugeriría ordenar los métodos de aprendizaje en tres partes:

• Métodos GLCD globales

• Métodos de dibujo
• Métodos de texto

Métodos GLCD globales


La primera es la función init() . Esta inicializa la biblioteca y debe llamarse antes que cualquier
otro método gLCD.

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.

El conjunto de constantes es el siguiente:

• GLCD.Width es el ancho de la pantalla en píxeles


• GLCD.Height es la altura de la pantalla en píxeles
• GLCD.Right es la última columna de píxeles a la derecha (igual a GLCD.Width – 1)
• GLCD.Bottom es la última fila de píxeles en la parte inferior (es igual a GLCD.Altura – 1)
• GLCD.CenterX y GLCD.CenterY son las coordenadas del píxel en
El medio

[ 385 ]

www.it­ebooks.info
Machine Translated by Google

Algunas técnicas avanzadas

Básicamente, puedes dibujar moviendo el cursor gráfico y dibujando formas primitivas:

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

También se pueden dibujar otras formas más complejas:

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).

DibujarRectangular() Dibuja un bonito rectángulo con esquinas redondeadas.


DrawCircle() y FillCircle() Dibuja un círculo a partir de coordenadas y un radio, y un
círculo relleno con píxeles negros (o blancos).
Dibujar mapa de bits() Dibuja un mapa de bits completo en una posición
determinada de la pantalla. Utiliza un puntero a ese
mapa de bits en la memoria.

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.

Establecer color de fuente () Elige el color.

Establecer modo de texto () Elige una dirección de desplazamiento.


CursorA() Mueve el cursor a una columna y fila específicas. El cálculo de la columna
utiliza el ancho del carácter más ancho.

CursorToXY() Mueve el cursor a una coordenada de píxel particular.

[ 386 ]

www.it­ebooks.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.

Uso de VGA con Gameduino Shield


Gameduino es una Arduino Shield. Es la primera que utilizamos en este libro.
Básicamente, un shield es una PCB (placa de circuito impreso) que se puede conectar a otra PCB,
en este caso nuestro Arduino.

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.

Veamos cómo funciona:

El controlador Gameduino Arduino Shield

[ 387 ]

www.it­ebooks.info
Machine Translated by Google

Algunas técnicas avanzadas

Las placas Arduino Shield se pueden conectar directamente a las placas Arduino. Consulta la siguiente
captura de pantalla:

El Gameduino conectado a la placa Arduino

A continuación se muestran algunas características de Gameduino:

• La salida de vídeo es de 400 x 300 píxeles en 512 colores.

• Todos los colores se procesan internamente con una precisión de 15 bits.

• Compatible con cualquier monitor VGA estándar (800 x 600 a 72 Hz)

• Gráficos de fondo (caracteres de 512 x 512 píxeles, 256 caracteres)

• Gráficos en primer plano (habilidades de sprite 16 x 16, transparencia, rotación/volteo y


detección de colisión de sprites)

• Salida de audio como estéreo; sintetizador de frecuencia de 12 bits

• 64 voces independientes de 10 a 8000 Hz

• Canal de reproducción de muestra

El concepto subyacente es conectarlo al Arduino y controlarlo usando nuestro firmware Arduino


con la biblioteca encargándose de toda la comunicación SPI entre Arduino y Gameduino.

[ 388 ]

www.it­ebooks.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/.

Puedes encontrar la biblioteca aquí: http://excamera.com/files/gameduino/synth/


bocetos/Gameduino.zip.

También puedes consultar y utilizar el póster de referencia rápida aquí: http://excamera.com/


archivos/gameduino/synth/doc/gen/poster.pdf.

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.

En el próximo capítulo, hablaremos sobre conceptos de redes. La creación y el uso de redes


son formas habituales de comunicación en la actualidad. Describiremos el uso de redes
cableadas e inalámbricas con nuestros proyectos de Arduino en el próximo capítulo.

[ 389 ]

www.it­ebooks.info
Machine Translated by Google

www.it­ebooks.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 Wi­Fi 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.

También presentaremos el protocolo de intercambio OSC, ampliamente utilizado en todo lo relacionado


con el diseño de interacción, la música y el multimedia.

Una visión general de las redes


Una red es un sistema de elementos conectados entre sí. Hay muchas redes a nuestro alrededor,
como sistemas de autopistas, redes eléctricas y redes de datos. Las redes de datos nos rodean.
Están relacionadas con redes de servicios de video, redes telefónicas y de telecomunicaciones
globales, redes de computadoras, etc. Nos centraremos en este tipo de redes hablando sobre cómo
podemos compartir datos a través de diferentes tipos de medios, como cables que transportan pulsos
eléctricos u ondas electromagnéticas que facilitan la comunicación inalámbrica.

www.it­ebooks.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.

Descripción general del modelo OSI


El modelo de interconexión de sistemas abiertos ( modelo OSI) fue iniciado en 1977 por la Organización
Internacional de Normalización con el fin de definir prescripciones y requisitos en torno a las funciones de los
sistemas de comunicación en términos de capas abstractas.

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:

Posición Capa Unidad de datos Características

Solicitud Proceso de red a aplicación

Representación de datos, cifrado/descifrado, máquina


Anfitrión Presentación Datos
conversión de datos dependientes/independientes
Comunicación entre hosts y manejo de sesiones entre
Sesión
aplicaciones

Transporte Segmentos Conexiones de extremo a extremo, confiabilidad y control de flujo

Red Paquete/datagrama Determinación de ruta y direccionamiento lógico


Red
Enlace de datos Marco Direccionamiento físico

Físico Poco Medios, señales y transmisiones binarias

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.it­ebooks.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

Protocolos que ayudan a las capas de los hosts a comunicarse entre sí

Encapsulación y desencapsulación de datos


Si la aplicación de un host necesita enviar datos a otra aplicación de otro host, los datos efectivos,
también llamados payload, se pasan directamente a la capa inferior. Para que la aplicación pueda
recuperar sus datos, se añaden un encabezado y un pie de página a estos datos según el protocolo
utilizado en cada capa. Esto se denomina encapsulamiento y se produce hasta la capa inferior, que
es la física.
En este punto, se modula un flujo de bits en el medio para el receptor.

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.it­ebooks.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

datos Transporte Transporte desencapsulación de datos

encapsulamiento
Red Red

Enlace de datos Enlace de datos

Enlace físico
Físico Físico

ANFITRIÓN 1 ANFITRIÓN 2

Encapsulación y desencapsulación a lo largo de toda la pila de capas

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

encapsulamiento de datos desencapsulación de datos

N­1 N­1

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.

Ahora vamos a ilustrar cada capa y protocolo con ejemplos.

Los roles de cada capa


Vamos a describir el propósito y las funciones de cada capa aquí.

Capa física La capa física


define las especificaciones eléctricas y físicas necesarias para la comunicación.

[ 394 ]

www.it­ebooks.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:

• Inicialización y finalización de una conexión a un medio de comunicación.

• Participación en procesos de control de recursos compartidos •


Conversión entre los datos comunicados y las señales eléctricas
que los llevan

Podemos citar algunos estándares conocidos que se encuentran en esta capa física:

• ADSL y ISDN (servicios de red y proveedores telefónicos) • Bluetooth

• IEEE 1394 (FireWire) • USB

• IrDA (transferencia de datos a través de enlaces


infrarrojos) • SONET, SDH (redes de fibra óptica de área amplia operadas por proveedores)

Capa de enlace de datos

Esta capa está formada por dos subcapas:

• Control de enlace lógico (LLC) •


Control de acceso al medio (MAC)

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

Podemos citar algunos estándares conocidos de esta capa de enlace de datos:

• Ethernet
• Wi­Fi
• APP
• I2C

[ 395 ]

www.it­ebooks.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

• Informes de errores de entrega

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:

• ARP (resolución y traducción de direcciones MAC físicas en direcciones de red)

• BOOTP (que proporciona una forma para que el host arranque a través de la red)

• BGP, OSPF, RIP y otros protocolos de enrutamiento

• IPv4 e IPv6 (Protocolo de Internet)

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:

• Control de flujo para asegurar la confiabilidad del enlace utilizado

• Segmentación/desegregación de unidades de datos


• Control de errores

[ 396 ]

www.it­ebooks.info
Machine Translated by Google

Capítulo 11

Generalmente ordenamos los protocolos en dos categorías:

• 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.

Podemos citar los dos estándares conocidos de la suite IP en esta capa:

• Protocolo de transferencia de datos (TPC)

• 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.

Encontramos allí muchas aplicaciones cliente/servidor:

• FTP para transferencias de archivos básicas y ligeras

• POP3, IMAP y SMTP para servicios de correo

• SSH para comunicación segura mediante shell remoto

• HTTP para navegar y descargar en servidores web (y actualmente


mucho más)

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.it­ebooks.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.

Algunos aspectos de las direcciones IP y los puertos


Una de las pilas de protocolos que solemos utilizar a diario es la de TCP/IP. TCP es el protocolo de transporte de
capa 4 e IP la red de capa 3.

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.it­ebooks.info
Machine Translated by Google

Capítulo 11

La máscara de subred de mi computadora es 255.255.255.0. Esta información y mi dirección IP definen


que mi red doméstica comienza en 192.168.1.0 (que es la dirección de red base) y termina en
192.168.1.255 (que es la dirección de transmisión).
No puedo usar estas direcciones para mi dispositivo, sino solo las de 192.168.1.1 a 192.168.1.254.

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.

El puerto UDP 53 se utiliza para todo lo relacionado con DNS.

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/nombres­de­servicio­numeros­de­puerto/nombres­de­servicio­numeros­de­puerto.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.

Conexión de Arduino a Ethernet por cable


Ethernet es la red de área local más utilizada hoy en día.

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.it­ebooks.info
Machine Translated by Google

Redes

Puede encontrar la página de referencia aquí: http://arduino.cc/en/Main/


Placa ArduinoEthernet.

Placa Ethernet Arduino con conector Ethernet

Vamos a utilizar el Arduino Ethernet Shield y un cable 100BASE­T 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.

El Shield Ethernet de Arduino

Si buscas el módulo Ethernet Arduino, debes saber que se venden con o sin el módulo PoE.

[ 400 ]

www.it­ebooks.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:

• Un módulo en el dispositivo que debe ser suministrado

• Un equipo de red capaz de proporcionar soporte PoE

En nuestro caso, no utilizaremos PoE.

Cómo hacer que Processing y Arduino se comuniquen a través


de Ethernet
Diseñemos un sistema básico que muestre cómo configurar una comunicación a través de Ethernet
entre la placa Arduino y un applet de procesamiento.

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í.

El interruptor y la resistencia pull­down conectados al Arduino Ethernet Shield

[ 401 ]

www.it­ebooks.info
Machine Translated by Google

Redes
El diagrama del circuito correspondiente es el siguiente:

(3V3) (5V) (Ganar)

Fuerza
(primera vez) CCC

(REF) MISO

Arduino
Modulación por ancho de pulso (PWM)

DINERO

Ethernet Espartano
Modulación por ancho de pulso (PWM)

Blindaje 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

Modulación por ancho de pulso (PWM)

(A0) (D5)

(A1) Espartano

Modulación por ancho de pulso (PWM)

(A2) (D3)

(A3) (D2)
Tejas
(A4) (D1)
Recepción

(A5) (D0)

(tierra)

El interruptor y la resistencia pull­down conectados al Arduino Ethernet Shield

Implementación de la codificación de conectividad de red en Arduino Como hemos


descrito, si queremos

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.it­ebooks.info
Machine Translated by Google

Capítulo 11

Para este código necesitas:

#include <SPI.h> #include


<Ethernet.h>
#include <EthernetUdp.h>

Este es un ejemplo del código Arduino, seguido de una explicación.

Puede encontrar el código completo de Arduino en Capítulo 11/WiredEthernet.

#include <SPI.h> #include


<Ethernet.h> #include
<EthernetUdp.h>

// Interruptor y cosas LED const int


switchPin = 2; const int ledPin = 13; int // pin de conmutación //
switchState = 0; pin LED incorporado // variable
de almacenamiento para conmutación actual
estado
int lastSwitchState = BAJO; largo
lastDebounceTime = 0; largo debounceDelay
= 50;

// Cosas relacionadas con la red

// una dirección MAC, una dirección IP y un puerto para el Arduino byte mac[] = { 0xDE, 0xAD, 0xBE,
0xEF, 0xFE, 0xED };

Dirección IP ipArduino(192, 168, 1, 123); int sin signo ArduinoPort


= 9999;

// una dirección IP y un puerto UDP para la computadora // modifíquelos según su


configuración
Dirección IP ipComputer(192, 168, 1, 222); int sin signo
ComputerPort = 10000;

// Buffer de envío/recepción char


packetBuffer[UDP_TX_PACKET_MAX_SIZE]; //buffer para paquetes entrantes

// Cree una instancia de EthernetUDP para enviar/recibir paquetes a través de UDP


EthernetUDP UDP;

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

// inicia Ethernet y UDP:

[ 403 ]

www.it­ebooks.info
Machine Translated by Google

Redes

Ethernet.begin(mac,ipArduino);
Udp.begin(PuertoArduino);
}

bucle vacío(){

// si se ha recibido un paquete, lea un paquete en packetBufffer if (Udp.parsePacket())


Udp.read(packetBuffer,UDP_TX_PACKET_MAX_
TAMAÑO);
si (packetBuffer == "Claro") digitalWrite(ledPin, ALTO); de lo contrario si (packetBuffer ==
"Oscuro") digitalWrite(ledPin, BAJO);

// lee el estado del pin digital int readInput =


digitalRead(switchPin); if (readInput != lastSwitchState) {

lastDebounceTime = milisegundos();
}

si ( (millis() ­ lastDebounceTime) > debounceDelay ) {

switchState = leerInput;
}

lastSwitchState = leerEntrada; si (switchState


== ALTO) {

// Si se presiona el conmutador, se envía un paquete a Processing Udp.beginPacket(ipComputer,


ComputerPort); Udp.write('Pushed'); Udp.endPacket();

} 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.it­ebooks.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.

En la primera parte, comprobamos si Arduino ha recibido un paquete. Si es así, lo comprobamos llamando


a la función parsePacket() de la biblioteca Ethernet y comprobando si ésta devuelve un tamaño de
paquete distinto de cero. Leemos los datos y los almacenamos en el
variable packetBuffer .

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.

Ahora revisemos la parte de Procesamiento/Computadora.

[ 405 ]

www.it­ebooks.info
Machine Translated by Google

Redes

Codificación de una aplicación de procesamiento que se comunica a


través de Ethernet
Revisemos el código en el Capítulo 11/Procesamiento Ethernet cableado.

Necesitamos la biblioteca hipermedia. La podemos encontrar en http://ubaa.net/shared/


processing/udp.

importar hypermedia.net.*;

UDP udp; // define el objeto UDP


Cadena mensajeActual;

Cadena ip int = "192.168.1.123"; // la dirección IP de Arduino // el puerto UDP de Arduino =


puerto 9999;

void setup() { tamaño(700,


700); noStroke(); relleno(0);

udp = new UDP( this, 10000 ); // crear socket UDP // esperar mensaje entrante
udp.listen( true );
}

void dibujar() {

elipse(ancho/2, alto/2, 230, 230);


}

void recibir(byte[] datos) {

// si el mensaje pudiera ser "Pushed" o "Released" if ( data.length == 6 || data.length


== 8 ) {

para (int i=0; i < data.length; i++) {

mensajeActual += datos[i];
}

// si el mensaje realmente fue enviado // entonces responda


enviando "Light" if (currentMessage == "Pushed") {

udp.send("Luz", ip, puerto ); fill(255);

} de lo contrario si (mensajeActual == "Publicado") {

[ 406 ]

www.it­ebooks.info
Machine Translated by Google

Capítulo 11

udp.send("Oscuro", ip, puerto );


rellenar(0);
}
}
}

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.

En la función draw() , dibujamos un círculo. La función Receive() es una devolución de llamada


que utiliza el código cuando llegan paquetes. Probamos la longitud de los paquetes en bytes porque
queremos reaccionar solo a dos mensajes diferentes aquí (Pushed o Released), por lo que
verificamos si la longitud es de 6 u 8 bytes. Todos los demás paquetes no se procesarán.
Podríamos implementar un mejor mecanismo de verificación, pero este funciona bien.

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.

Luego, lo comparamos con Pushed y Released y actuamos en consecuencia enviando de vuelta el


mensaje Light al Arduino y llenando nuestro círculo dibujado con color blanco, o enviando de vuelta el
mensaje Dark al Arduino y llenando nuestro círculo dibujado con color negro.

Acabamos de diseñar nuestro primer protocolo de comunicación básico utilizando Ethernet y UDP.

Algunas palabras sobre TCP


En mi propio diseño, suelo utilizar UDP para la comunicación entre sistemas. Es mucho más ligero
que TCP y es más que suficiente para nuestros propósitos.

En algunos casos, necesitarás el control de flujo proporcionado por TCP. La biblioteca


Ethernet que acabamos de utilizar también ofrece funciones TCP. Puedes encontrar la página de
referencia en http://arduino.cc/en/Reference/Ethernet.

[ 407 ]

www.it­ebooks.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.

Aprenderemos cómo conectar nuestro Arduino a algún servidor en vivo en Internet en el


Fin de este capítulo.

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.

La placa Arduino BT implementa esta tecnología de forma nativa. Ahora se suministra


con ATmega328 y un módulo Bluetooth Bluegiga WT11. La página de referencia es http://
www.arduino.cc/en/Main/ArduinoBoardBluetooth.

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.it­ebooks.info
Machine Translated by Google

Capítulo 11

Cableado del módulo Bluetooth


Compruebe las siguientes cifras:

Módulo Bluetooth RN41 conectado al Arduino a través de un enlace serial

El diagrama del circuito correspondiente es el siguiente:

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 (RN­41)
PIO4 ESPIMOSI
Modulación por ancho de pulso (PWM)

CAROLINA DEL NORTE D9


PIO5 DISCURSO
D8
PIO6 SPICSB­ES
D7
PIO7 ESPIGA
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

Modulación por ancho de pulso (PWM)

A1 D3

A2 D2
Tejas
A3 D1

A4 D0 Recepción

A5 LCC

Adventista del Séptimo Día

Tierra

Módulo RN41 de Roving Networks conectado a la placa Arduino

[ 409 ]

www.it­ebooks.info
Machine Translated by Google

Redes

Hay un módulo Bluetooth RN41 de Roving Networks conectado a la placa Arduino.

Puedes encontrarlo en https://www.sparkfun.com/products/10559.

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.

Codificación del firmware y del subprograma


Processing
El firmware es el siguiente. Puedes encontrarlo en el Capítulo 11/Bluetooth.

// 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

Serie.begin(9600); // iniciar comunicación serial a 9600bps


}

bucle vacío() {

si (Serial.available() > 0) {

entranteByte = Serial.read();

si (incomingByte == 1) digitalWrite(ledPin, HIGH); de lo contrario si


(incomingByte == 0) digitalWrite(ledPin, LOW);
}
}

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.

El código de procesamiento es el siguiente:

importación processing.serial.*; Puerto


serie;

int color de fondo, color de fondo;

configuración vacía() {

[ 410 ]

www.it­ebooks.info
Machine Translated by Google

Capítulo 11

tamaño(700, 700);
fondo(0); trazo(255);
color_fondo = 0;
color_fondo = 255;

println(Serial.list()); puerto = new


Serial(this, Serial.list()[2], 9600);

} 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 = 255; fgcolor


= 0; puerto.write('1');

}
}

vacío ratón liberado() {

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);

La función draw() solo configura:


• Color de fondo según la variable bgcolor • Color del
trazo según la variable fgcolor
• Color de relleno según la variable fgcolor

[ 411 ]

www.it­ebooks.info
Machine Translated by Google

Redes

Luego dibujamos un cuadrado.

Las funciones mousePressed() y mouseReleased() son dos devoluciones de llamadas de Processing


respectivamente que se llaman cuando ocurre un evento del mouse, cuando presiona un botón del mouse
y lo suelta.

En cuanto se pulsa el ratón, comprobamos dónde se encontraba el cursor al pulsarlo. En mi caso,


definí el área dentro del cuadrado.

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.

Escribimos el valor 1 en el módulo Bluetooth.

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.

Acabamos de comprobar un buen ejemplo de un módulo externo que proporciona la función de


comunicación inalámbrica Bluetooth al Arduino.

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.

Mejoremos nuestra comunicación de datos por aire utilizando Ethernet Wi­Fi.

Jugando con wifi


Anteriormente aprendimos a usar la biblioteca Ethernet. Luego, probamos Bluetooth para comunicaciones
de red de corto alcance. Ahora, probemos Wi­Fi para comunicaciones de rango medio sin ningún cable.

¿Qué es Wi­Fi?
Wi­Fi 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 Wi­Fi pueden comunicarse usando sus pilas de IP sin
necesidad de cables. Wi­Fi utiliza varios modos de red.

[ 412 ]

www.it­ebooks.info
Machine Translated by Google

Capítulo 11

Modo de infraestructura En ese modo,

los hosts Wi­Fi pueden comunicarse entre sí a través de un punto de acceso.

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 Wi­Fi 1

Acceso Anfitrión wifi 3


Punto

Anfitrión wifi 2

Hosts intercambiando datos a través de un punto de acceso en modo infraestructura

Modo ad hoc En este

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 Wi­Fi 1

Anfitrión wifi 2

Dos hosts conectados directamente en modo ad hoc

[ 413 ]

www.it­ebooks.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.

El shield wifi de Arduino


Esta placa añade capacidades de red inalámbrica a la placa Arduino. La placa oficial
también contiene una ranura para tarjeta SD que también ofrece funciones de
almacenamiento. Ofrece:

• Conexión a través de redes 802.11b/g


• Cifrado mediante cifrado personal WEP o WPA2.
• Conexión FTDI para depuración en serie del propio shield
• Mini­USB para actualizar el firmware del escudo Wi­Fi.

El Shield Wi­Fi de Arduino

Se basa en el sistema LAN inalámbrico 802.11b/g HDG104 incluido. Un Atmega 32 UC3


adecuado proporciona la pila IP de la red.

[ 414 ]

www.it­ebooks.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.

Intentemos conectar nuestro Arduino a nuestra red WiFi.

Conexión Wi­Fi básica sin cifrado


Aquí no tenemos que dibujar ningún esquema. Básicamente, conectamos la placa al Arduino y
cargamos nuestro código en ella. Vamos a probar una conexión básica sin cifrar nada, al principio.

El punto de aceptación debe proporcionar un servidor DHCP; este último entregará una dirección IP a
nuestro sistema basado en Arduino.

Verifiquemos el ejemplo ConnectNoEncryption proporcionado con la biblioteca WiFi .

#include <WiFi.h>

char ssid[] = "suRed"; int estado = // el nombre de tu red


WL_IDLE_STATUS; // el estado de la radio Wifi

configuración vacía() {
//Inicialice el serial y espere a que se abra el puerto:
Serie.begin(9600);

// comprobar la presencia del escudo:


si (WiFi.estado() == WL_NO_SHIELD) {
Serial.println("El escudo WiFi no está presente"); // no continúe:

mientras(verdadero)

retraso(30) ;
}

//Intentar conectarse a la red Wifi:


mientras ( estado != WL_CONNECTED) {
Serial.print("Intentando conectarse al SSID abierto: ");
Serie.println(ssid);
estado = WiFi.begin(ssid);

//espera 10 segundos para la conexión:

[ 415 ]

www.it­ebooks.info
Machine Translated by Google

Redes

retraso(10000);
}

// ahora estás conectado, así que imprime los datos: Serial.print("Estás


conectado a la red"); printCurrentNet(); printWifiData();

bucle vacío() {
// comprobar la conexión de red una vez cada 10 segundos: delay(10000);
printCurrentNet();

void printWifiData() { // imprime la


dirección IP de tu escudo WiFi: IPAddress ip = WiFi.localIP();
Serial.print("Dirección IP: "); Serial.println(ip);
Serial.println(ip);

// imprime tu dirección MAC: byte mac[6];

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);

// imprime tu máscara de subred:


IPAddress subnet = WiFi.subnetMask(); Serial.print("NetMask:
"); Serial.println(subnet);

// Imprime tu dirección de puerta de enlace:

[ 416 ]

www.it­ebooks.info
Machine Translated by Google

Capítulo 11

Dirección IP puerta de enlace = WiFi.gatewayIP();


Serial.print("Puerta de enlace: ");
Serial.println(puerta de enlace);
}

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);

// imprime la intensidad de la señal recibida: long rssi =


WiFi.RSSI(); Serial.print("intensidad
de la señal (RSSI):"); Serial.println(rssi);

// imprimir el tipo de cifrado: byte encrypted =


WiFi.encryptionType(); Serial.print("Tipo de cifrado:");
Serial.println(encryption,HEX);

Primero incluimos la librería WiFi . Luego, configuramos el nombre de nuestra red, el SSID.
Tenga cuidado de cambiarlo a su propio SSID.

En la función setup() instanciamos la conexión serial . Luego, verificamos la presencia


del shield llamando a la función WiFi.status().

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.it­ebooks.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 Wi­Fi sin seguridad puede acarrear problemas. De hecho, es muy fácil capturar paquetes de una red
Wi­Fi sin protección.

Utilicemos la biblioteca WiFi con más seguridad.

Conexión wifi de Arduino mediante WEP o WPA2


Si abre ambos códigos ConnectWithWEP y ConnectWithWPA, hay pequeñas diferencias con el ejemplo
anterior.

Uso de WEP con la biblioteca Wi­Fi


Si utilizamos un WEP de 40 bits, necesitaremos una clave que contenga 10 caracteres que deben
ser hexadecimales. Si utilizamos un WEP de 128 bits, necesitaremos una clave que contenga 26
caracteres, también hexadecimales. Esta clave debe estar especificada dentro del código.

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.

Uso de WPA2 con la biblioteca Wi­Fi


Siguiendo el mismo esquema, aquí sólo necesitamos una contraseña. Luego, llamamos a
WiFi.begin() con 2 argumentos: el SSID y la contraseña.

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.it­ebooks.info
Machine Translated by Google

Capítulo 11

Arduino tiene un servidor web (ligero)


Aquí utilizamos el código WifiWebServer proporcionado con la biblioteca.

En este ejemplo, Arduino actúa como un servidor web después de haber sido conectado a una WEP.
o red Wi­Fi WPA.

#include <WiFi.h>

char ssid[] = "yourNetwork"; char pass[] = // su SSID de red (nombre)


"secretPassword"; // su contraseña de red
= 0; (necesario solo para // su número de índice de clave de red int keyIndex
WEP)

int estado = WL_IDLE_STATUS;

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
}

// comprobar la presencia del escudo:


si (WiFi.estado() == WL_NO_SHIELD) {
Serial.println("El escudo WiFi no está presente"); // no continúe:

mientras(verdadero);
}

//Intentar conectarse a la red Wifi:


mientras ( estado != WL_CONNECTED) {
Serial.print("Intentando conectarse a SSID: ");
Serie.println(ssid);
// Conéctese a la red WPA/WPA2. Cambie esta línea si usa una red abierta o
Red WEP:
estado = WiFi.begin(ssid, pass);

//espera 10 segundos para la conexión:


retraso(10000);

} servidor.begin();
// Ahora estás conectado, así que imprime el estado:
imprimirEstadoWifi();
}

[ 419 ]

www.it­ebooks.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 http­equiv=\"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.it­ebooks.info
Machine Translated by Google

Capítulo 11

// obtuviste un carácter en la línea actual currentLineIsBlank = false;

}
}

} // 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());

// imprime la dirección IP de tu escudo WiFi: IPAddress ip


= WiFi.localIP(); Serial.print("Dirección IP: ");
Serial.println(ip);

// imprime la intensidad de la señal recibida: long rssi =


WiFi.RSSI(); Serial.print("intensidad
de la señal (RSSI):"); Serial.print(rssi); Serial.println(" dBm");

Expliquemos los conceptos subyacentes a estas afirmaciones.

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.

La declaración server(80) de WiFiServer crea una instancia de un servidor en un puerto específico.


Aquí, el puerto TCP elegido es 80, el puerto TCP del servidor HTTP estándar.

En la función setup() conectamos automáticamente el Arduino a la red wifi y luego iniciamos el


servidor. Básicamente, abre un socket en el puerto TCP 80 y comienza a escuchar en este puerto.

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.it­ebooks.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.

Tuitear pulsando un interruptor


Al conectar Arduino a redes, obviamente pensamos en Internet. Podríamos intentar crear un pequeño sistema
que pueda enviar mensajes a través de Internet. Elegí utilizar el servicio de microblogging Twitter porque
ofrece una API de comunicación muy útil.

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.

Una descripción general de las API


API significa Interfaz de Programación de Aplicaciones. Básicamente, define formas de intercambiar
datos con el sistema en cuestión. Podemos definir API en nuestros sistemas para que se comuniquen
con otros.

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.it­ebooks.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.

Podemos crear una aplicación yendo a https://dev.twitter.com/apps/new.

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.

Uso de la biblioteca de Twitter con soporte OAuth


Markku Rossi creó una biblioteca muy potente y confiable que incorpora el soporte OAuth y está
diseñada para enviar tweets directamente desde Arduino. El sitio web oficial de la biblioteca es http://
www.markkurossi.com/ArduinoTwitter.

Esta librería debe utilizarse con una placa con más memoria de la habitual. Arduino MEGA la ejecuta
perfectamente.

OAuth es un protocolo abierto que permite la autorización segura de forma sencilla y


estándar desde aplicaciones web, móviles y de escritorio. Se define en http://oauth.net.

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.

Obteniendo credenciales de Twitter


La biblioteca de Markku implementa la firma de solicitudes OAuth, pero no implementa el
flujo de recuperación del token de acceso OAuth. Podemos recuperar nuestro token utilizando esta
guía en el sitio web de Twitter donde creamos nuestra aplicación: https://dev.twitter.com/docs/auth/
tokens­devtwittercom.

Debes tener a mano el token de acceso y el secreto del token de acceso, ya que los incluiremos en nuestro
firmware.

Codificación de un firmware que se conecta a Twitter


La biblioteca de Markku es fácil de usar. Aquí se muestra un código que permite conectar Arduino a la
red Ethernet para poder enviar mensajes directamente.

[ 423 ]

www.it­ebooks.info
Machine Translated by Google

Redes

Puedes encontrarlo en Chapter11/tweetingButton/.

#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;

// Configuración de red local


uint8_t mac[6] = 0xc4, 0x2c, {
0x03, 0x0a, 0x3b, 0xb5}; // UTILICE SU DIRECCIÓN MAC
Dirección IP ip(192, 168, 1, 43); // UTILICE IP EN SU RED
Dirección IP de puerta de enlace (192, 168, 1, 1); // UTILICE LA IP DE SU PUERTA DE ENLACE
DIRECCIÓN

Dirección IP subred(255, 255, 255, 0); // UTILICE SU MÁSCARA DE SUBRED

// Dirección IP de Twitter
Dirección IP twitter_ip(199, 59, 149, 232);
uint16_t puerto_twitter = 80;

unsigned long last_tweet = 0;


#define TWEET_DELTA (60L * 60L)

// Almacenar las credenciales


const static char clave_consumidor[] PROGMEM = "xxxxxxxxxxxxx";
const static char secreto_consumidor[] PROGMEM
= "aaaaaaaaaaaaaaa";

#DEFINE ALREADY_TOKENS 0 ; // Cámbialo a 1 cuando coloques tus tokens

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");

// el pin del interruptor está configurado como entrada


pinMode(switchPin, ENTRADA);

[ 424 ]

www.it­ebooks.info
Machine Translated by Google

Capítulo 11

// iniciar la conexión de red Ethernet.begin(mac, ip,


dns, gateway, subnet);

// define el punto de entrada de Twitter


twitter.set_twitter_endpoint(PSTR("api.twitter.com"), PSTR("/1/status/update.json"),
twitter_ip, twitter_port, false);
twitter.set_client_id(consumer_key, consumer_secret);

// Almacenar o leer credenciales en la parte EEPROM de la placa


#si YA HAY TOKENS
/* Leer la identificación de la cuenta OAuth desde la EEPROM. */ twitter.set_account_id(256,
384); #else /* Establecer la identificación de la cuenta
OAuth
desde la memoria del programa. */ twitter.set_account_id(PSTR("*** establecer token de acceso a la
cuenta aquí ***"),

PSTR("*** establezca el secreto del token de cuenta aquí ***"));


#finsi

retraso(500);
}

void loop() { if
(twitter.is_ready()) // si la conexión de Twitter está bien {

unsigned long ahora = twitter.get_time(); si (último_tuit == 0)


último_tuit = ahora ­ TWEET_DELTA + 15L;

// lee el estado del pin digital int readInput =


digitalRead(switchPin); if (readInput != lastSwitchState) {

lastDebounceTime = milisegundos();
}

si ( (millis() ­ lastDebounceTime) > debounceDelay ) {

switchState = leerInput;
}

lastSwitchState = readInput; if (switchState


== HIGH) // si presiona el botón {

if (now > last_tweet + TWEET_DELTA) // si no tuiteaste durante un tiempo


mientras
{

carácter msg[32];

[ 425 ]

www.it­ebooks.info
Machine Translated by Google

Redes

sprintf(msg, "Twittear desde #arduino presionando un botón es genial, gracias a


@julienbayle");

// retroalimentación al monitor serial


Serial.print("Publicando en Twitter: "); Serial.println(msg);

last_tweet = ahora;

si (twitter.post_status(msg))
Serial.println("Estado actualizado");
demás
Serial.println("La actualización falló");

} else Serial.println("¡Espera un poco antes de volver a enviarlo!");


}

} delay(5000); // esperando un poco, por si acaso


}

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:

• Pulsador con sistema antirrebote • Conexión Ethernet


con Arduino Ethernet Shield

• Ejemplo de biblioteca de Twitter

Primero incluimos muchos encabezados de biblioteca:

• SPI y Ethernet para conexión de red

• Sha1 para encriptación de credenciales •

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

• La propia biblioteca de Twitter

Luego incluimos la variable relacionada con el botón en sí y el sistema antirrebote.

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.it­ebooks.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.

TOKEN_IN_MEMORY se define anteriormente como 0 o 1. Dependiendo de su valor, la


compilación se produce de una manera u otra.

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.

Entonces, la función loop() es bastante simple considerando lo que aprendimos antes.

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.

Si presionamos el botón, probamos si lo hicimos en menos de TWEET_DELTA


cantidad de tiempo. Si es el caso, estamos seguros con respecto a las reglas de la API de Twitter y
Podemos twittear.

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.it­ebooks.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, Wi­Fi, 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.

En el próximo capítulo, describiremos y profundizaremos en el framework Max 6. Se trata de


una herramienta de programación muy potente que puede generar y analizar datos, y
explicaremos cómo podemos utilizarla con Arduino.

[ 428 ]

www.it­ebooks.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.

Comunicarse fácilmente con Max 6 – el


objeto [serial]
Como ya comentamos en el Capítulo 6, Sensing the World – Feeling with Analog Inputs, la forma más
sencilla de intercambiar datos entre tu ordenador con un parche Max 6 y tu placa Arduino es a través del
puerto serie. El conector USB de nuestras placas Arduino incluye el circuito integrado FTDI EEPROM
FT­232 que convierte el estándar serie RS­232 a USB.

www.it­ebooks.info
Machine Translated by Google

Jugando con Max 6 Framework

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.

Puede encontrarlo en la carpeta Capítulo 12 ; el parche se llama serialObject.maxpat.

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.it­ebooks.info
Machine Translated by Google

Capítulo 12

Seleccionar el puerto serie correcto


En el capítulo 6, Sense the World – Feeling with Analog Inputs, utilizamos el mensaje (print)
enviado a [serial] para enumerar todos los puertos seriales disponibles en la computadora.
Luego, verificamos la ventana Max. Esa no fue la solución más inteligente.
Aquí vamos a diseñar uno mejor.

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.

[prepend] agrega un mensaje delante del mensaje de entrada entrante.

[ 431 ]

www.it­ebooks.info
Machine Translated by Google

Jugando con Max 6 Framework

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.

Al golpear el objeto [serial] , aparecen los valores contenidos en su búfer.

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.

Analizar y seleccionar datos provenientes de


Arduino
Primero, quiero presentarles un firmware auxiliar inspirado en la página Arduino2Max del sitio web de
Arduino, pero actualizado y optimizado un poco por mí. Proporciona una manera de leer todas las
entradas de su Arduino, empaquetar todos los datos leídos y enviarlos a nuestro parche Max 6 a través del
objeto [serial] .

[ 432 ]

www.it­ebooks.info
Machine Translated by Google

Capítulo 12

El firmware readAll El código


siguiente es el firmware. Puedes encontrarlo en el Capítulo 12/ReadAll:
int valor = 0;

configuración vacía()
{
Serial.begin(9600);
pinMode(13,ENTRADA);
}

bucle vacío() {

// Verificar el buffer serial en busca de caracteres entrantes si


(Serial.available() > 0){

// Si se recibe una 'r' entonces lea todos los pines si (Serial.read() == 'r') {

// Leer y enviar valores de los pines analógicos 0­5 para (int


pin= 0; pin<=5; pin++){ val = analogRead(pin);
sendValue (val);

// Leer y enviar valores de los pines digitales 2­13 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

}
}

void sendValue (int val){ Serial.print(val);


Serial.write(32); // agrega un
carácter de espacio después de cada valor enviado
}

Para empezar, comenzamos la comunicación serial a 9600 baudios en el bloque setup() .

[ 433 ]

www.it­ebooks.info
Machine Translated by Google

Jugando con Max 6 Framework

Como es habitual en el manejo de la comunicación en serie, primero comprobamos si hay algo en el


búfer en serie de Arduino utilizando la función Serial.available() . Si hay algo disponible, comprobamos
si es el carácter r. Por supuesto, podemos utilizar cualquier otro carácter. r aquí significa lectura, lo cual
es básico. Si se recibe una r , se activa la lectura de los puertos analógicos y digitales. Cada valor (la
variable val ) se pasa a la función sendValue(); esto básicamente imprime el valor en el puerto serie y
añade un carácter de espacio para formatear un poco las cosas y facilitar el análisis por parte de Max 6.
Podríamos adaptar fácilmente este código para leer solo algunas entradas y no todas. También podríamos
eliminar la función sendValue() y encontrar otra forma de empaquetar los datos.

Al final, enviamos un retorno de carro al puerto serie utilizando Serial.println().


Esto crea un separador entre cada paquete de datos que se envía.

Ahora, mejoremos nuestro parche Max 6 para manejar este paquete de datos que se reciben desde
Arduino.

El parche ReadAll Max 6


La siguiente captura de pantalla es el parche ReadAll Max que proporciona una forma de
comunicarnos con nuestro Arduino:

Puedes encontrar este parche en la carpeta Chapter12 . Se llama ReadAll.maxpat.

[ 434 ]

www.it­ebooks.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.

Solicitando datos de Arduino


Primero, veremos un objeto [tbb] . También es un disparador que ordena los bangs
proporcionados por el objeto [metro] . Cada bang recibido dispara otro bang a otro [trigger].
objeto, luego otro al objeto [serial] mismo.

El objeto [t 13 r] puede parecer complicado. Simplemente activa un carácter r y luego


el entero 13. El carácter r se envía a [spell] que lo convierte a código ASCII y luego envía el
resultado a [serial]. 13 es el código ASCII para un retorno de carro.

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.

Analizando los datos recibidos


Debajo del objeto [serial] , podemos ver una nueva estructura que comienza con el objeto
[sel 10 13] . Esta es una abreviatura del objeto [select] . Este objeto selecciona un mensaje
entrante y lanza un mensaje de advertencia a la salida específica si el mensaje es igual al
argumento correspondiente al lugar específico de esa salida. Básicamente, aquí seleccionamos
10 o 13. La última salida muestra el mensaje entrante si este no es igual a ningún
argumento.

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.it­ebooks.info
Machine Translated by Google

Jugando con Max 6 Framework

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.

El objeto [fromsymbol] convierte un símbolo en una lista de mensajes.

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.it­ebooks.info
Machine Translated by Google

Capítulo 12

Distribuir los datos recibidos y otros trucos


Vamos a presentar aquí algunos otros trucos para mejorar nuestro estilo de parcheo.

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.

Estas tres estructuras son equivalentes.

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.

Esta es una buena manera de distribuir datos.

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.it­ebooks.info
Machine Translated by Google

Jugando con Max 6 Framework

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.

Un parcheador contenido dentro de otro también se denomina subparcheador.

Veamos cómo funciona con el parche llamado ReadAllCutest.maxpat.

[ 438 ]

www.it­ebooks.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.it­ebooks.info
Machine Translated by Google

Jugando con Max 6 Framework

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.

La posición de estas entradas y salidas en el subpatcher es importante. De hecho, si mueves el


objeto 1 a la derecha del objeto 2 , ¡los números se intercambian! Y las diferentes entradas en
el parche superior también se intercambian. Debes tener cuidado con eso. Pero, nuevamente,
puedes organizarlas exactamente como quieras y necesites.

Mira la siguiente captura de pantalla:

Y ahora, comprueba el parche raíz que contiene este subparche. Invierte automáticamente las
entradas, manteniendo la relevancia de todo.

[ 440 ]

www.it­ebooks.info
Machine Translated by Google

Capítulo 12

Ahora echemos un vistazo a los otros subparcheadores:

El subparcheador [p portHandler]

El subparcheador [p dataHandler]

El subpatchador [p dataDispatcher]

[ 441 ]

www.it­ebooks.info
Machine Translated by Google

Jugando con Max 6 Framework

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.

Esta función se llama encapsular y es parte del menú Editar de Max 6.

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.

Encapsular y desencapsular funciones

También puedes desencapsular un subpacher. Para ello, se seguiría el proceso


inverso de quitar el subpacher y sacar toda la estructura que estaba dentro
directamente al exterior.

La subdivisión de parches ayuda a mantener las cosas bien organizadas y legibles.

[ 442 ]

www.it­ebooks.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.

Esto puede ser realmente difícil.

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.

Un parche utilizado de esta manera se llama abstracción.

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.

El concepto de abstracción en Max 6 es muy poderoso porque proporciona reutilización.

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.

Es realmente fácil de mantener durante todos los meses o años de desarrollo.

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.

Continuemos ahora describiendo algunos buenos ejemplos con Arduino.

[ 443 ]

www.it­ebooks.info
Machine Translated by Google

Jugando con Max 6 Framework

Creación de un medidor de nivel de sonido con LED


Este pequeño proyecto es un ejemplo típico de una colaboración de hardware y software Max
6/Arduino.

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.

La siguiente figura muestra el circuito:

Nuestra serie doble de ocho LED

[ 444 ]

www.it­ebooks.info
Machine Translated by Google

Capítulo 12

Arduino1

3V3 5V Venir
Fuerza
D13

Primera vez D12

ARÉF D11
Modulación por ancho de pulso (PWM)

Yo ref. Arduino D10


Modulación por ancho de pulso (PWM)

LED09 R1
D9
Modulación por ancho de pulso (PWM)

CAROLINA DEL NORTE

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

8 9 Adventista del Séptimo Día

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'

Nuestra serie doble de ocho LED

La idea básica es:

• Utilice cada serie de ocho LED para cada canal de sonido (izquierdo y derecho) • Muestre

el nivel de sonido a lo largo de la serie de LED

Para cada canal, cuanto mayor sea el número de LED encendidos, mayor será el nivel de sonido.

Veamos ahora cómo podemos gestionar esto en Max 6 primero.

[ 445 ]

www.it­ebooks.info
Machine Translated by Google

Jugando con Max 6 Framework

El parche Max 6 para calcular los niveles de sonido


Eche un vistazo a la siguiente figura que muestra el parche SoundLevelMeters :

Generación de sonidos y medición de niveles de sonido

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.it­ebooks.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.

También utilicé el objeto [meter~] para mostrar el nivel de cada canal.

Por último, agregué un objeto [flonum] para mostrar el valor actual del nivel cada vez.

Estos son los números que vamos a enviar a Arduino.

Agreguemos los bloques de construcción de comunicación serial que ya describimos.

Envío de datos a Arduino

Tenemos nuestra configuración de comunicación serial lista.

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.it­ebooks.info
Machine Translated by Google

Jugando con Max 6 Framework

De esta forma, tenemos listas de mensajes que se envían desde la computadora a Arduino tan pronto
como cambian los valores de nivel.

El firmware para leer bytes


Veamos cómo manejar esto en Arduino:

#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

int SR_Number = 2; // número de registros de desplazamiento en la cadena

// instanciar y habilitar la biblioteca shiftOutX con nuestros parámetros de circuito

shiftOutX regGroupOne(LATCH_595, DATOS_595, RELOJ_595, MSBFIRST, SR_;


Número);

// variables aleatorias de la máquina de ranura


int contador = 0;
byte LeftChannel = B00000000 ; // almacena la información de los LED del canal izquierdo
byte RightChannel = B00000000 ; // almacena la información de los LED del canal derecho

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

datos = ( CanalIzquierdo << 8 ) | RightChannel; // agregando los 2


leer bytes
shiftOut_16(DATA_595, CLOCK_595, MSBFIRST, data); // empujando el
datos completos a SR

// haz una breve pausa antes de cambiar el estado de los LED


retraso(2);
}
}

[ 448 ]

www.it­ebooks.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.

Estamos haciendo eso con Serial.parseInt() en la prueba Serial.available() .

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.

Tomemos otro ejemplo de juego con archivos de sonido y un sensor de distancia.

Efecto de cambio de tono controlado manualmente


El cambio de tono es un efecto muy conocido en todos los campos relacionados con el procesamiento
de sonido. Cambia el tono de un sonido entrante. Aquí vamos a implementar un cambiador de tono
muy económico con Max 6, pero nos centraremos en cómo controlar este efecto de sonido.
Lo controlaremos moviendo nuestra mano sobre un sensor de distancia.

Vamos a utilizar el mismo circuito que en el Capítulo 6, Sentir el mundo: sensaciones con entradas
analógicas.

El circuito con el sensor y el firmware.


El siguiente circuito muestra la placa Arduino conectada a un sensor:

El sensor de distancia Sharp conectado a Arduino

[ 449 ]

www.it­ebooks.info
Machine Translated by Google

Jugando con Max 6 Framework

El firmware también es casi el mismo. Eliminé la parte sobre el cálculo de la distancia


porque, en realidad, no nos importa la distancia en sí.

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.

El código siguiente es el firmware. Puedes encontrarlo en el Capítulo 12/PitchShift


carpeta:

int sensorPin = 0; está // número de pin donde se encuentra el SHARP GP2Y0A02YK


conectado
int sensorValue = 0; // almacenando el valor medido de 0 a
1023

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.

El parche para alterar el sonido y analizarlo


Mensajes de Arduino
No puedo describir el pitch shifter en su totalidad. Por cierto, puedes abrir el subpatch relacionado para
ver cómo se ha diseñado. Todo está abierto.

[ 450 ]

www.it­ebooks.info
Machine Translated by Google

Capítulo 12

El cambiador de tono controlado por tu mano sobre el sensor de distancia

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.it­ebooks.info
Machine Translated by Google

Jugando con Max 6 Framework

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.it­ebooks.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.it­ebooks.info
Machine Translated by Google

Mejorando su programación en C y creando bibliotecas

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:

La biblioteca EEPROM en nuestro ordenador (un sistema OS X)

Tenemos los siguientes archivos:

• EEPROM.h, que contiene los encabezados de la biblioteca

• EEPROM.cpp, que contiene el código en sí

• 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.

Ingresemos código en estos archivos.

[ 454 ]

www.it­ebooks.info
Machine Translated by Google

Capítulo 13

El archivo de encabezado
Abramos EEPROM.h:

EEPROM.h mostrado en Xcode IDE

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.it­ebooks.info
Machine Translated by Google

Mejorando su programación en C y creando bibliotecas

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)

• void escritura (int, uint8_t)

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.it­ebooks.info
Machine Translated by Google

Capítulo 13

El archivo fuente Abramos


EEPROM.cpp:

El archivo fuente de la biblioteca EEPROM se muestra en el IDE de Xcode

[ 457 ]

www.it­ebooks.info
Machine Translated by Google

Mejorando su programación en C y creando bibliotecas

El archivo comienza con la inclusión de algunos encabezados. avr/eeprom.h hace referencia a la


biblioteca EEPROM del procesador de tipo AVR. En este ejemplo de biblioteca, simplemente tenemos
una biblioteca que hace referencia a nuestro estilo de programación Arduino y crea una mejor interfaz
para él que el código AVR original puro. Por eso elegí este ejemplo de biblioteca. Es el ejemplo más
breve pero el más explícito, y nos enseña mucho.

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?

Creando tu propia biblioteca de matrices de LED


Vamos a crear una biblioteca muy pequeña y probarla con un circuito básico que incluye seis LED que
no están multiplexados.

Cableado de seis LED a la placa


Aquí está el circuito. Básicamente, contiene seis LED conectados a Arduino:

Seis LED conectados a la placa

[ 458 ]

www.it­ebooks.info
Machine Translated by Google

Capítulo 13

El diagrama del circuito se muestra de la siguiente manera:

3V3 5V Venir
Fuerza
D13

Primera vez D12

ARÉF D11
Modulación por ancho de pulso (PWM)

Yo ref. Arduino D10


Modulación por ancho de pulso (PWM)

D9
Modulación por ancho de pulso (PWM)

CAROLINA DEL NORTE

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

Adventista del Séptimo Día

Tierra

Otro diagrama de los seis LED conectados directamente a Arduino

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.

Creando algunos patrones de iluminación agradables


Aquí se muestra el código para encender los LED según algunos patrones, todos codificados. Se hace una pausa entre
cada visualización de patrón:

configuración vacía() {

para (int i = 2; i <= 7; i++) {

pinMode(i, SALIDA);
}
}

bucle vacío(){

// enciende todo progresivamente

[ 459 ]

www.it­ebooks.info
Machine Translated by Google

Mejorando su programación en C y creando bibliotecas

para (int i = 2; i <= 7; i++) {

digitalWrite(i, ALTO); retraso(100);

retraso(3000);

// apaga todo progresivamente for (int i = 7 ; i >=2 ; i­­) {

digitalWrite(i, BAJO); retraso(100);

retraso(3000);

// enciende los LED pares para (int


i = 2; i <= 7; i++) {

si ( i % 2 == 0 ) digitalWrite(i, ALTO); de lo contrario digitalWrite(i,


BAJO);
}

retraso(3000);

// enciende los LED impares para


(int i = 2; i <= 7; i++) {

si ( i % 2 != 0 ) digitalWrite(i, ALTO); de lo contrario digitalWrite(i,


BAJO);
}

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.it­ebooks.info
Machine Translated by Google

Capítulo 13

Diseño de una pequeña biblioteca de patrones LED


En primer lugar, podemos diseñar el prototipo de nuestra función en un encabezado. Llamaremos a la
biblioteca LEDpatterns.

Cómo escribir el encabezado LEDpatterns.h Así es como podría ser un


posible encabezado:

/*
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();

vacío switchOdd(); privado:


int _firstPin;
int _ledsNumber;


#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

cableados de forma contigua.

[ 461 ]

www.it­ebooks.info
Machine Translated by Google

Mejorando su programación en C y creando bibliotecas

Escribiendo el código fuente de LEDpatterns.cpp Aquí


está el código fuente de la biblioteca C++:
/*
LEDpatterns.cpp ­ Biblioteca para crear lindos patrones de LED.
Creado por Julien Bayle, 10 de febrero de 2013. */

#include "Arduino.h"
#include "patronesLED.h"

PatronesLED::PatronesLED(int primerPin, int ledsNumber) {

para (int i = primerPin; i < numeroDeLed + primerPin; i++) {

pinMode(i, SALIDA);
}

_ledsNumber = ledsNumber; _firstPin =


primerPin;
}

vacío LEDpatterns::switchOnAll() {

para (int i = _firstPin; i < _ledsNumber + _firstPin; i++) {

digitalWrite(i, ALTO); retraso(100);

}
}

vacío LEDpatterns::switchOffAll() {

para (int i = _numeroLed + _primerPin ­1 ; i >= _primerPin ; i­­) {

digitalWrite(i, BAJO); retraso(100);

}
}

vacío LEDpatterns::switchEven() {

para (int i = _firstPin; i < _ledsNumber + _firstPin; i++) {

si ( i % 2 == 0 ) digitalWrite(i, ALTO); de lo contrario digitalWrite(i,


BAJO);
}
}

vacío LEDpatterns::switchOdd()

[ 462 ]

www.it­ebooks.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.

Cómo escribir el archivo keyword.txt


Cuando observamos nuestro código fuente, resulta muy útil que las cosas destaquen y no se mezclen
con el fondo. Para colorear correctamente las diferentes palabras clave relacionadas con nuestra nueva
biblioteca creada, tenemos que usar el archivo keyword.txt . Veamos este archivo:

#######################################
# Mapa de colores de sintaxis para Messenger
#######################################

#######################################
#Tipos de datos (PALABRA CLAVE1)
#######################################

Patrones de LED PALABRA CLAVE1

#######################################
# Métodos y funciones (PALABRA CLAVE2)
#######################################
Encender todo PALABRA CLAVE2

apagartodo PALABRA CLAVE2

cambiar incluso PALABRA CLAVE2

switchOdd PALABRA CLAVE2

#######################################

[ 463 ]

www.it­ebooks.info
Machine Translated by Google

Mejorando su programación en C y creando bibliotecas

# Instancias (PALABRA CLAVE2)


#######################################

#######################################
# Constantes (LITERAL1)
#######################################

En el código anterior podemos ver lo siguiente:

• Todo lo que siga a KEYWORD1 se coloreará en naranja y generalmente es para


clases
• Todo lo que siga a KEYWORD2 se coloreará en marrón y es para
funciones
• Todo lo que siga a LITERAL1 se coloreará en azul y es para constantes.

Es muy útil utilizarlos para colorear el código y hacerlo más legible.

Uso de la biblioteca LEDpatterns


La biblioteca está en la carpeta LEDpatterns en el Capítulo 13 y tienes que ponerla en la
carpeta correcta con las otras bibliotecas, lo cual hemos hecho. Tenemos que reiniciar
el IDE de Arduino para que la biblioteca esté disponible. Después de haber hecho eso,
deberías poder comprobar si está en el menú Sketch | Import Library. LEDpatterns ahora
está presente en la lista:

La biblioteca es una contribución porque no es parte del núcleo de Arduino.

[ 464 ]

www.it­ebooks.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 :

#include <LEDpatterns.h> Patrones


LED ledpattern(2,6);

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:

• El primer pin del primer LED • El


número total de LED

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.it­ebooks.info
Machine Translated by Google

Mejorando su programación en C y creando bibliotecas

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 flash (espacio de programa), donde se almacena el firmware

• Memoria de acceso aleatorio estático (SRAM), donde el boceto crea y manipula variables en
tiempo de ejecución

• EEPROM es un espacio de memoria para almacenar información a largo plazo.

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:

• ATMega328 (UNO) tiene:

° Flash 32k bytes (0,5k bytes utilizados por el gestor de arranque)

° SRAM 2k bytes

° EEPROM 1k bytes

• ATMega2560 (MEGA) tiene:

° Flash 256k bytes (8k bytes utilizados por el gestor de arranque)

° SRAM 8k bytes

° EEPROM 4k bytes

Un ejemplo clásico es citar una declaración básica de una cadena:

char text[] = "Me encanta Arduino porque es genial.";

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.it­ebooks.info
Machine Translated by Google

Capítulo 13

• Puede utilizar la EEPROM nativa de su placa Arduino, lo que


Requiere la creación de dos pequeños programas: el primero para almacenar esa información en la
EEPROM y el segundo para utilizarla. Lo hicimos utilizando la biblioteca PCM en el Capítulo 9, Hacer que
las cosas se muevan y crear sonidos.

Dominando el cambio de bits


Hay dos operadores de desplazamiento de bits en C++:


<< 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.

Multiplicar/dividir por múltiplos de 2


Multipliquemos una variable usando desplazamiento de bits.
int a = 4;
int b = a << 3;

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.

Empaquetar múltiples elementos de datos en bytes


En lugar de utilizar una tabla grande y bidimensional para almacenar, por ejemplo, un mapa de bits mostrado
como sigue:

const prog_uint8_t BitMap[5][7] = { // almacenar en


la memoria del programa para ahorrar RAM {1,1,0,0,0,1,1},

[ 467 ]

www.it­ebooks.info
Machine Translated by Google

Mejorando su programación en C y creando bibliotecas

{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} };

Podemos utilizar el siguiente código:

const prog_uint8_t BitMap[5] = { // almacenar en la


memoria del programa para ahorrar RAM
B1100011,
B0010100,
B0001000,
B0010100,
B1100011 };

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?

Activación y desactivación de bits individuales en un registro


de control y puerto
Lo siguiente es una consecuencia directa del consejo anterior. Si queremos configurar los pines 8 a 13
como salida, lo podemos hacer de la siguiente manera:

vacío configuración() {
int pin;

para (pin=8; pin <= 13; ++pin) { pinMode (pin, BAJO);

}
}

Pero esto sería mejor:

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.it­ebooks.info
Machine Translated by Google

Capítulo 13

Reprogramación de la placa Arduino


Arduino utiliza de forma nativa el famoso gestor de arranque. Esto proporciona una forma agradable
de cargar nuestro firmware mediante el puerto serie virtual del USB. Pero puede que nos interese
seguir adelante sin ningún gestor de arranque. ¿Cómo y por qué? En primer lugar, eso ahorraría
algo de memoria Flash. También proporciona una forma de evitar el pequeño retraso cuando
encendemos o reiniciamos nuestra placa antes de que se active y comience a funcionar.
Requiere un programador externo.

Puedo citar el AVR­ISP, el STK500 o incluso un programador paralelo (un programador


paralelo se describe en http://arduino.cc/en/Hacking/
ParallelProgrammer). Puede encontrar un AVR­ISP en Sparkfun Electronics.

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.

El programador Pocket AVR de Sparkfun Electronics

[ 469 ]

www.it­ebooks.info
Machine Translated by Google

Mejorando su programación en C y creando bibliotecas

Este programador se puede conectar mediante conectores 2 x 5 al puerto ICSP de la placa


Arduino.

El conector ICSP de Arduino

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.it­ebooks.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.

¡Cuídate y continúa explorando!

[ 471 ]

www.it­ebooks.info
Machine Translated by Google

www.it­ebooks.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 291­295 analógico 138
75HC595 dominio analógico 326
conectando a Arduino 266­268 entradas
conectando a LEDs 266­268 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 266­268 acerca
de 7­9 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 16­18
funciones matemáticas 105
movimiento del aire 323
Conector MIDI, cableado a 352­354

www.it­ebooks.info
Machine Translated by Google

Implementación de conectividad de red, codificación Arduino UNO R3 400


402­405 Arquitectura argumentos 100, 101
de software 13, 14 Sonido, producción operadores aritméticos
329 Giro, en voltímetro de acerca de
bajo voltaje 184, 185 Motor paso a paso unipolar, cableado 76 tipos de caracteres
a 318­320 76 tipos numéricos 77
URL 8 ARP396
usado para controlar el servidor web Arduino Cálculo de
311 419, 421 con C 39 operaciones de índice de
con C++ 39 matriz 57 , reemplazando con 119
ASCII210
Protocolo de comunicación entre Conversiones ASCII 212­214
Arduino y Processing , configuración del archivo Símbolos ASCII 212­214
Arduino.app 155 454 Placas operador de asignación 76
Arduino comunicación asincrónica 241
casos de alimentación USB 377, 378 diferencias ATmega168 362
10 alimentación ATmega328 408
externa, suministro 378 grupos de ATMega328 (UNO) 466
memoria 361 alimentación, ATMega2560 (MEGA) 466
suministro con baterías 378­380 programación 469, ATMEL13
470 Procesador Atmel AVR 9 archivos
Código Arduino 168, 169 de audio
Controladores Arduino reproducción, con la biblioteca PCM 355
Diecimilla , instalación para 20 función audioHook() 338, 342 avr­g++ 105
Arduino Duemilanove
controladores, instalacion para 20
Shield Ethernet Arduino 400 B
Firmware Arduino 163­165
Arduino IDE Bangs 195
Circuito básico 150
lanzamiento 30­34
Cables 151
utilizado, para crear prototipos de funciones 100
Arduino LilyPad 10 Pasos básicos de desarrollo

Arduino Mega 10 Verificación 44­46


LED básicos 254
Mensajes de Arduino en
Max 6 206­209 Conexión Wi­Fi básica

Arduino Nano sobre Sin cifrado 415­417 Baudios 47


10 Velocidad
en baudios 47
controladores, instalación para 20
Biblioteca nativa de Arduino Comportamiento Encapsulación 40
Beneficios, funciones 103­105
descubriendo 40, 41, 42
funciones 40 BGP 396

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 bit­banging 329, 332 profundidad
Controladores Arduino de bits 328

Uno R3 , instalación para 19 operaciones de bits 111

[ 474 ]

www.it­ebooks.info
Machine Translated by Google

bitRead(number,n) función 237 bits bytes


de elementos de datos múltiples, empaquetados en 467
desactivando 468 variable bytesCount 161
activando 468
dominio del do
desplazamiento de
do
bits 467 usado, para multiplicar variables 467
Acerca de
operación de desplazamiento
de bits 111 operadores de 38 ventajas 38
C++ 38
desplazamiento de bits 467 operadores bit a bit
Y 112 cálculo

NO 113 sustitución, con operaciones de índice de matriz 119


O 112 cálculo optimización acercándose
Abstracción 110 capacitancia 22
de caja negra XOR 113 230 capacitor 22
Comunicación
casos
serial Blink250ms , agregando a la función blink()
49­52 133 modificación del buscando, para la estructura condicional 88, 89
retardo de parpadeo, Multiplexor analógico CD4051B 230
Circuito integrado CD4051B
para LED con potenciómetro 182, 183
cableado 231
ParpadeoM 247 Centro de nueva música y audio

Bluegiga WT11 408 Tecnologías (CNMAT) 344 unidad


bluetooth 395 central de procesamiento (CPU) 8 char 56
acerca del
características, comunicación serial asíncrona 241
firmware 408, codificación 410­412
subprograma de procesamiento, codificación 410­412 sistema de bus 242
Cableado del módulo codificación de datos

Bluetooth 409, placa 243 modo dúplex 241


410 sistema de

LED, cableado a 458, 459 emparejamiento 242


cuerpo, función 101­103 sincrónico 241 LCD de
caracteres 300 tipos de
proyecto bonome 13
booleano 56 caracteres 76 función

Comparaciones de charAt() acerca de 62


sintaxis 62
expresiones de operadores
booleanos , combinación circuito
con 83 bootloader 13
Placas de Placa Arduino, conectada al sensor
pruebas BOOTP 396 24 449, 450 en el mundo
real 151, 152 configuración
Modo puente 414 bus
47 buses 333 diagrama de
24 sistema circuito para múltiples

de bus 242 pulsación interruptores 166, 167


de botón circuitos 23
Clases 39
150 byte 57
Función ClearScreen() 385

[ 475 ]

www.it­ebooks.info
Machine Translated by Google

CLI (interfaz de línea de comandos) 15 código Ciclismo


y POV 289
condiciones, añadir en 86 código Ciclismo '74 187
licencia problema 104 puerto de
comunicación 399 protocolo de D
comunicación acerca de 155, 392
definir, entre conexión en cadena 272

Arduino y Processing 155 diseño Matriz de transistores Darlington 286 análisis


de
156 requisitos 156
expresiones datos 432­ 436

de comparación solicitud, desde Arduino 435 selección

acerca de 82 combinar, con 432


operadores almacenamiento, EEPROM utilizada 361
Detección de portadora de datos
booleanos 83 operadores de comparación combinar,
con operadores de negación 245 codificación de datos

84, 85 incrementos complejos 93 concatenación 64 243 capa de enlace


de datos
función concat() acerca de 64
sintaxis 64 notaciones acerca de 395 funciones 395

condensadas 77, 78 Control de enlace lógico (LLC) 395


condensador. Control de acceso al medio (MAC) 395
estándares 395
Ver
hoja de datos
condensador estructura condicional
casos, buscar 88, 89 condiciones lectura 215­217 tipo
añadir, en código 86 de datos
acerca de
56 matriz
57 booleano

calificador constante 75 56 byte


57 char
construcción 61
56 doble 57
constructores 39
flotante 57
detección de valores
entero 57
continuos 180
acoplamiento control/retroalimentación 260, 261 cuerda
truco inalámbrico 437, 438 larga 57 57
coseno 108 Cadena 57
void 56
acoplamiento firmware 263, 264
palabra 57
Programa C 99
obtención de Conector DB25 245, 246 concepto
antirrebote 173­176 depuración 36
credenciales, de Twitter 423
compilación cruzada 46 desencapsulación
diafonía 241 393 número decimal
consumo
actual 21 cálculo de consumo número binario, conversión a 111 operador
de decremento 78 decrementos
actual 381, 382
93
Función CursorTo() 386
Función CursorToXY() 386

[ 476 ]

www.it­ebooks.info
Machine Translated by Google

grado Función DrawRoundRect() 386 Función


DrawVLine() 386 controladores
aproximadamente 107 versus radianes 106, 107 instalación
concepto de retardo 124­126 19 instalación,
función delay() 124­183 función para Arduino Diecimilla 20 instalación, para
delayMicroseconds() 124 demultiplexación 227 Arduino Duemilanove 20 instalación, para Arduino
generador de bits aleatorios Nano 20 instalación, para Arduino Uno R3
deterministas (DRBG) 271 digital 19 Modelo de secuencia de unidad 321
138 bits digitales que se Paquete dual en línea. Ver modo
reproducen, dúplex DIP acerca de 241 dúplex
como sonidos completo 241
328 semidúplex
colisiones digitales 119 241 simplex 241
dominio digital 326 pin
digital 153 selección
233­237 función
digitalRead() 183 convertidor digital Y
a analógico (DAC) 328 diodo 23 corriente continua
(CC) 21 EEPROM

concepto de retorno directo acerca de 43, 362, 466

116, 117 medición de distancias 214, 215 lectura a 366­368 usado,


lectura, en para almacenamiento de datos
Max 6 220­222 sensores 361 escritura a 366­368
de distancia 215 doble 57 Biblioteca central de EEPROM
estructura de bucle do… acerca de
while 96 454 lectura con 362, 363
función DrawBitmap() 386 función escritura con 362, 363
DrawCircle() 386 función draw() 148, Archivo EEPROM.cpp
acerca de
161, 407 función DrawHLine() 386
dibujo en gLCDs 382 métodos de dibujo 454 apertura 457, 458
EEPROM FT­232 429
acerca de 385 DrawBitmap() 386
Archivo EEPROM.h
DrawCircle()
acerca de
386 DrawHLine()
386 DrawLine() 386 454 apertura 455, 456
DrawRect() Función eeprom_read_byte() 458 Función
386 DrawRoundRect() eepromRead() 367 Función
386 DrawVLine() 386 eeprom_write_byte() 458 Función eepromWrite()
Función FillCircle() 386 367
Función FillRect() Programable y borrable eléctricamente
386 Función GotoXY() Memoria de sólo lectura. Véase EEPROM
386 Función DrawLine() 386 electricidad 20
programación de sistemas integrados 35
encapsulación 393, 438, 442 función
endsWith() acerca de 63
sintaxis 63

[ 477 ]

www.it­ebooks.info
Machine Translated by Google

envolventes Trabajando 223


sobre 344 Biblioteca FlexiTimer2 121
generando 344­346 flotante 57
implementando 346­351 FOLED 254
utilizadas, para controlar sonidos 343 para estructura de bucle 91, 92
Ethernet Transformada de Fourier 324
sobre 43, 395, 399 multiplexación por división de frecuencia 228
Applet de procesamiento que se comunica, modulación de frecuencia, onda sinusoidal 338
codificando en 406, 407 Fritzing
utilizado, para establecer la comunicación entre alrededor de 23­26
Placa Arduino y subprograma de URL 27
procesamiento Circuito integrado FTDI

401 conversión de tipo explícita 80, 82 usado, para convertir RS­232 a USB 250 modo full­
funciones exponenciales 110 duplex 242 función acerca de
cableado EEPROM externo 364, 365 bibliotecas 99 beneficios
externas 103­105
MsTimer2 44 cuerpo 101­103
TLC5940 44 encabezado 100,
Instalación 101 nombre 100, 101
de la biblioteca declaraciones
externa Tone 44 131, 132 101­103
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

fillColor 161 función fill() 161


Gameduino
Función FillRect() 386 sobre 387
Firmado 43 características 388
código de Escudo de Gameduino
firmware 154, 155 VGA, uso con objetos de puerta
codificación, para conexión de Twitter 423­427 387, 388 206
diseño 154 diseño, Génesis 196­198
para manejo de registros de desplazamiento 268 para Git
lectura de bytes 448, 449 URL 145
pseudocódigo 154 Ejemplo de demostración de GLCD 384,
motor paso a paso, control 320­323 385
actualización, para manejo de entrada 340­343 gLCD que se basa
usado, para accionar servos 316, 317 en 382 cableado 383, 384
vibraciones, generación 308, 309 Flash Métodos GLCD globales sobre
466 memoria 385
flash 361 OLED flexible. Borrar pantalla() 385
Véase FOLED flexión 222 sensores init() 385
flexibles acerca Leer datos () 385
de 222 propósito Establecer modo de visualización () 385
223 Escritura de datos () 385

[ 478 ]

www.it­ebooks.info
Machine Translated by Google

Sistema de posicionamiento global. Véase el Esquema pequeño (SO) 230


patrón de programación del registro de desplazamiento identificador 58
global IEEE 1394 (firewire) 395 if y
GPS 270, 271 GNU LGPL 2.1 + else estructura condicional 86 if…else
biblioteca 121 Función GotoXY() estructura
386 GPS encadenamiento, a otra if…else
Acerca de estructura 87, 88
368 usando 368 con comparaciones combinadas expresiones 88
Análisis de datos de imbricadas
ubicación GPS 371­377 utilizando, bucles for 93, 94
GPU 197 conversión de tipo implícita 80, 81
Marco de programación protección de inclusión
gráfica LCD 300 189 software de programación 456 operador de incremento
gráfica 78 índices
Compositor de cuarzo 189 utilizando, dentro de String
Reactor 189 61 función indexOf()
Sintetizador 190 acerca de 62,
Fábrica 189 66 sintaxis
vvvv 190 62 bucles infinitos 97
Interfaz gráfica de usuario (GUI) 189 Unidad modo de infraestructura 413

de procesamiento gráfico. Véase GPU función initCosineLUT() 119 función


init() 385 variable init
yo 161 manejo de entrada

modo semidúplex 242 firmware, manejo de entradas 340­343 8,


Función HandleControlChange() 350 139 instalación,
Función HandleNoteOff() 350 controladores Arduino 19 instalación,
Función HandleNoteOn() 350 hardware biblioteca externa 131, 132 instalación, Max 6 198
utilizado, instancia 39 int 57 entero a
para controlar software 203 programación ASCII. Véase
de hardware 35 creación de itoa
prototipos de hardware 11, 12 circuito integrado (IC) acerca de
Circuito de pantalla LCD compatible con 7, 230 suministro 232 entorno
HD44780 301, 302 de desarrollo
archivo de
integrado (IDE) 10
encabezado 100 encabezado,
Intel 4004 8 Intel Corporation 8
función 100,
interacción 253 concepto de
101 encabezados 45 archivo de encabezados 455, 456 controlador de
Ejemplo de LED Hola 256, 257 interrupciones 128 Rutina
Hertz 325 de servicio de
Dispositivo de
interrupciones (ISR) 75 funciones
interfaz humana (HID) HTTP 188 188 trigonométricas inversas 109 dirección IP 398 , 128
IPv4 396 IPv6 396 IrDA 395
I
I2C 246, 247, 395
Paquetes de circuitos integrados

inmersión 230

[ 479 ]

www.it­ebooks.info
Machine Translated by Google

ISDN 395 Biblioteca LEDpatterns que


ahogó 436 utiliza 464, 465 LED

Yo
75HC595, conectando a 266­268 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

función lastIndexOf() acerca de bucles acerca de 91 romper 96


62, 63 sintaxis diseño, para tareas repetitivas 91 bucle do…
63 pestillo while
267 LCD 96 bucle for
299 Bit 91 imbricado,
menos significativo. Ver LSB Biblioteca usando 93, 94 bucle while 95 Oscilador de
de matrices de LED baja frecuencia (LFO)

creación 458 336 voltímetro

LED, cableado a la placa 458, 459 patrones de bajo voltaje Arduino,


de luz, creación 459, 460 matrices de LED convirtiéndose en
construcción 184, 185 LSB 271

284, 285 circuito 290,


291 matriz de LED
acerca de 287
concepto de
METRO

arquitectura 288, 289 biblioteca de


patrones de LED diseño
función map() 341 bus
461 código fuente maestro 242
de LEDpatterns.cpp escritura
funciones matemáticas, Arduino acerca de
462, 463 encabezado 105 funciones
de LEDpatterns.h escritura 461
exponenciales 110 funciones
trigonométricas C 106

[ 480 ]

www.it­ebooks.info
Machine Translated by Google

Archivo math.h 105, 109 MIDI 188


Máx. acerca de 262­344
Acerca de 190, 198 implementando 346­351
Características URL 343
192 Historia 187, 188 utilizada para controlar los sonidos 343
Con parche 191, 192 Caja MIDI 8
Máximo 4 188 Conector MIDI
Máximo 5 188 cableado, a Arduino 352­354
Máximo 6 Librería MIDI para
aproximadamente 37, 198 Arduino 344
Arduino, conexión a 203, 204 Función MIDI a frecuencia 341
Arduino mensajes 206­209 millis() 121­123
comunicarse con 429 sistema de Módulo 77 de
depuración 206 distancia, MISO 247
lectura 220­222 mejoras 188 momentáneos 150
instalación 198 sistema LED monocromáticos 255
de sondeo 432 Monómero 256, 261
[serial] objeto 430 puerto Interfaz Monome 261
serie, selección 431, Enrutador serial Monome 262
432 sistema de seguimiento 206 Antepasado de la telegrafía en código Morse
alrededor del año 244

Máximo 6 11, 186 I2C 246, 247


Máximo 6 RS­232 244
niveles de sonido de parche, calculando 446, 447 SPI247, 248
Procesamiento de señal máximo. Ver USB 248
ventana MSP Max 192 MOSI 247 Bit
memorias 7 más significativo. Ver MSB Motorola 247
ahorro de Función
memoria , consejos mousePressed() 412 Función
466 memoria, placas Arduino mouseReleased() 412 Mozzi
Memoria EEPROM 362

memoria flash 361 Documentación 333 Motor


Gestión de de sonido, mejora 332, 333
memoria SRAM 362 466 Instalación de la
microcontrolador 7 biblioteca Mozzi 333, 334
microcontrolador, partes MSB271
entradas 8 MSP
memorias 7 alrededor de 188,
salidas 8 198 para sonido 193, 194
periféricos 7 MsTimer2 44
procesador 7 botones múltiples que
micrófonos 325, 326 juegan con 165
microprocesadores 8 empaquetamiento de
función micros() 123 elementos de datos múltiples
Microsoft DirectX HLSL en bytes 467 LED monocromáticos múltiples 258, 259
URL 197

[ 481 ]

www.it­ebooks.info
Machine Translated by Google

Interfaces seriales múltiples acerca OLED 254


de 244 Opcode Systems 187
Antepasado de la telegrafía en código Morse 244 openFrameworks 11 OpenGL
Múltiples servos con 195 OpenGL
fuente de alimentación externa 314, 315 GLSL URL 197 Open
Multiplexación 226, 227, 265 Sound
Técnicas de multiplexación acerca Control. Véase el modelo de interconexión
de 227
de sistemas abiertos OSC. Véase
Multiplexación por división de frecuencia 228 Modelo OSI
Multiplexación por división espacial 228 operadores
Multiplexación por división de tiempo 229, 230 acerca de
Interfaz digital para instrumentos musicales Véase MIDI 76 aritmética 76
notaciones condensadas 77, 78
objeto myServo 314 decremento 78
incremento 78
norte
precedencia 77, 78 LED
orgánico. Ver operador OR OLED
nombre, función 100, 101
112 OSC 188, 262,
operadores de negación 344 oscilador 336
combinando, con operadores de Biblioteca OSC
comparación 84, 85
para Arduino
red 391
344 modelo OSI
conectividad de red implementación codificación,
en Arduino 402­ 405 capa de red acerca de
acerca de 396
392 capa de aplicación/host 397
funciones
capa de enlace de datos
396 estándares
395 capas
396
394 capa de red 396
Función NMEA0183
capa física 394 capa de
369 noTone() 332
transporte 396
Operador NOT 113 OSPF 396
Transistor NPN 310
salidas 8, 139
NTP (Protocolo de tiempo de red) 397 tipos
numéricos 77 PAG

Nvidia Cg
URL 197 variable 405 del paquete buffer
Frecuencia de Nyquist 326 PAN 408
paradigma 37
EL Módulo receptor GPS Parallax
cableado 368­370
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
Objetivo­C 38 Parche del
Propiedades de la programación orientada a
objetos (POO) 39 analizador 46 sobre 189, 199­201
Ohmios 22
Mensajes de Arduino, análisis 450, 452
Ley de Ohm 181

[ 482 ]

www.it­ebooks.info
Machine Translated by Google

sonido, alterar 450, 451 sonidos, utilizado, para modificar el retardo de


reproducir dentro de 201, 202 modo de parpadeo del LED
edición de parche 439 estilo 182, 183 potValue variable 183
de parcheo trucos de mejora abstracciones 443 power 21
truco inalámbrico 437, adaptador de
438 encapsulación 438, 442 corriente para Arduino suministro 380,
reutilización 443 subparcheo 381 Alimentación a través de Ethernet.
438­442 modo de Véase Fundamentos
bloqueo de parche 439 de la fuente de alimentación
carga útil 211, 212 PoE 27, 28 Unidad de fuente de
alimentación
PCM305 (PSU) 27 PPP 395
Biblioteca PCM precedencia
sobre 355 77, 78 cálculo de
utilizada, para reproducir archivos de audio precisión 186
355 cableado Preprocesador 46 placa de circuito impreso
del lector PCM 358, (PCB) 231 objetos de
359 PDU impresión 206
394 sistema de Proce55ing
emparejamiento 140 Procesamiento
242 período 325 acerca de 11, 135, 140 y
periféricos Arduino 149, 150
7 Perl 38 Redes de área personal. Véase PAN ejemplo 145­148 Alternativas
PHP 38 IDE 145 instalación
capa física sobre 141 lanzamiento 141, 142
394 funciones URL 140
395 estándares URL para descargar 141
395 PIC 8 sensor Applet de procesamiento que comunica la
codificación, en Ethernet 406, 407
piezoeléctrico 306 función Código de
pinMode 468 identificación del procesamiento
número de pin sobre 157 código, escritura
232 tuberías 20 157, 158 función draw()
cambio de 161 pseudocódigo, esbozo 157
tono 449 procesamiento devolución de llamada serialEvent() 162,
de píxeles 195 función Plug 163 función setup() 161
and Play 248 PoE 401 definiciones de variables 160
Código de procesamiento 170­173
punteros 120 Procesador IDE de procesamiento
concepto de sondeo 127 142­145 7
ejemplo de biblioteca de sondeo 130 PROGMEM palabra clave 466
sistema de sondeo 432 programa
LED policromáticos 255 acerca de 35,
potenciómetro 46 diseño 36
sobre 22, 181 escritura 36
sumando, en circuito generador de sonido 339 flujo del programa 124
propósito 181 programador 14

[ 483 ]

www.it­ebooks.info
Machine Translated by Google

programación 35 modo extensor de rango 414


biblioteca de programación 39, 40, 453, 454 firmware readAll 433, 434 ReadAll
paradigmas de programación Max 6 parche acerca de 434,
acerca de 435 datos,
37 funcional 37 solicitando de Arduino 435 datos recibidos,
imperativo 37 distribuyendo 437 datos recibidos,
programación lógica 37 analizando 435, 436 trucos, para mejorar
orientada a objetos 37 el estilo de parcheo 437 ReadAll.maxpat parche 434
estilo de programación 37 función ReadData() 385 bibliotecas
tiempo de propagación 241 de lectura 359 Memoria de solo
Unidad de datos de protocolo. Véase lectura (ROM) 7 Reaktor
PDU Controlador Protodeck 8 acerca de 189
ciclo de creación de prototipos
12 pseudocódigo
acerca de URL 189

36 ejemplo 36 función recibir() 407 Rojo,


concepto de pull­down 153 verde, azul. Ver RGB tareas repetitivas
concepto de pull­up 153 bucles, diseño para
Modulación por ancho de pulso. Véase PWM 91 función reemplazar() acerca
Datos puros 11 de 67 sintaxis 67 cálculos
PWM de resistencia
acerca de 230, 296 224, 225
utilizado, para simular salidas analógicas 295 pin resistencias 22 resultados 100 RGB 279
digital con capacidad PWM 307 LED RGB

componente controlador PWM 298, 299 acerca de 282


iluminación

Q 281 tipos 280


uso 279
Calificadores Indicador de
sobre 73
anillo 245
const 75
RIP 396
estática 74
volátil 75
Compositor de cuarzo concepto de enrollado/enrollado 58
alrededor de 189 enrutadores 396
URL 189
Redes móviles RN41 410
RS­232 244
R Conversión de RS­232 a USB
IC FTDI usado 250
radián

S
aproximadamente 106 versus grado 106, 107
Memoria de acceso aleatorio (RAM) 7 Función Número de serie 247

random() 342 mensajes Concepto de alcance SCL (Serial Clock Line)


aleatorios 246, 365 72, 73, 101
mostrando 302, 303 tonos Día 43
aleatorios
SDA (Línea de datos en serie) 246, 365
reproduciendo 331, 332

[ 484 ]

www.it­ebooks.info
Machine Translated by Google

SDH395 paquetes de tres pines 311


SDK (kits de desarrollo de software) 190 cableado 312, 313
Búsqueda Función SetDisplayMode() 385
SDU 394 Función SetFontColor() 386
utilizando dentro de la cadena 61 Función SetTextMode() 386 función
Función SelectFont() 386 Función setup() 125, 148, 161, 183 proceso shader 197
sendValue() 434 detecta 136 shaders 197

sensores Sensor Sharp


acerca de 135, 226 conectado a placa Arduino 217­219

capacidades 136 Biblioteca ShiftOutX


jugando con 214 tipos acerca de 272, 274
136, 137 separador usando 276
usado, para registros de
dividir cadena 66 Serial.available() desplazamiento

función 434 Serial.begin() función 53 acerca de 267 vinculando 273


serialBytesArray 160 comunicación Biblioteca SimpleTimer 121 modo
serial 47 acerca de 239, 240 simplex 241 seno 108
agregando, a Blink250ms 49­52
características 241 onda sinusoidal

serialEvent() devolución de llamada modulación de frecuencia 338 usando


162, 163 monitor serial 335, 336 método
usando 46, 47 monitoreo serial 48, 35 sizeof() 356 bus esclavo 242
objeto serial 204, control deslizante

205 220

serialObject.maxpat parche 430 Software de

Interfaz periférica serial. Ver control

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

Serial.read() función 370 sonido

Serial.write() función 370 Unidad de sobre 323

datos de servicio. Consulte el identificador control, envolventes utilizadas 343 control,


de conjunto de servicios (SSID) de MIDI utilizado 343 bits digitales,
SDU 413 Servo 43 Biblioteca de reproducción como 328 digitalización
servos utilizada para controlar servos 326­328 reproducción,
313, 314 servomotor 311 dentro del parche 201, 202 producción,
Arduino utilizado 329 representaciones
324, 325 bits de sonido
reproducción

329 cableado
servomotores del circuito de

control 311 control, sonido 330


biblioteca Servo utilizada 313, 314 control, con Arduino motor de sonido
311 conducción, con firmware 316, 317 mejorando, con Mozzi 332, 333 circuito
propósito 311 generador de sonido
Potenciómetro, sumando 339

[ 485 ]

www.it­ebooks.info
Machine Translated by Google

circuito de sonómetro Función substring() sobre


444, 445 creación, la sintaxis
con LEDs 444 65 66
Niveles de sonido del parche 446 de SVN
SoundLevelMeters URL 145
cálculo, se utilizaron 6 parches como máximo 446, cambiar
447 código alrededor de
fuente mantenimiento 150 tipos
36 archivo fuente 457, 150 cambiar…caso…romper condicional
458 multiplexación por división espacial 228 estructura 89, 90
Sparkfun técnicas de optimización
sobre 307 de etiquetas de casos de conmutación 114,
URL 364 115 variable switchID 160
hablantes 325, 326 variable switchState 160
SPI247, 248 comunicación sincrónica 241
SRAM 362, 466 SynthMaker
Artículo 247 alrededor de 190
función startPlayback() 356 función URL 190
startsWith() acerca de 63
sintaxis 63 yo
declaración,
función 101­103 calificador estático tangente 107
74 Memoria de acceso Expansiones de la serie de Taylor 119, 120
TCP 397, 407
aleatorio estático. Véase SRAM std::complex 105 motores
Puerto TCP 80 399
paso a paso acerca de
terminales 24
318 control 318­322
cadena operador ternario 91
pruebas 36
acerca de 57 división,
métodos de texto
acerca de 386
separador
CursorTo()386
usado 66 Cadena acerca de 57, 60
índices, CursorToXY() 386
usando 61 SeleccionarFuente() 386
Establecer color de fuente () 386
búsqueda, usando 61
Establecer modo de texto () 386
definición de cadena
El Instituto Europeo de Investigación y
en construcción 61 Coordinación acústica/musical
(IRCAM) 187
cadenas
termómetros 136, 137 objeto
concatenando 64
theSerialPort 160 hilo 129 tiempo
extrayendo 65 +
121
operador, usando en 64
multiplexación
reemplazando
67 subred 398 por división de tiempo 229, 230

subparcheadores 441 Biblioteca TimerOne 333


TLC5940 44
creando 442
función toCharArray() 68 alternar
subparcheo 438­442
objetos 206

[ 486 ]

www.it­ebooks.info
Machine Translated by Google

alterna 150 a la diseño de sistemas 249


función LowerCase() 68 Cable USB 27, 249
Tono 44 Conectores USB 249
función tone() 329, 332 cadena Fábrica
de herramientas alrededor de 189

15 función toUpperCase() 68 trazas URL 189


48
transistor En
acerca de 23, 285, 309
base 310 valores

colector 310 que distinguen 180


emisor 310 variable
sobre 56, 101
funcionamiento
310 capa de declarar 58
transporte definir 59, 60
acerca de 396 multiplicar, desplazamiento de bits usado
funciones 396 467 probar 68, 71
definiciones de variables 160
estándares 397 funciones trigonométricas
C 106 ejemplo de triángulo trigonométrico 107, 108 control de versiones 145
VESA DDC247
funciones de trigonometría 109
Uso de
función trim() 68
truncamiento 80 VGA , con motor de vibración Gameduino Shield
Twitter 387, 388

sobre 422 cableado 307, 308

credenciales, robadas de 423 Tecnología de Virtual Studio. Véase VST


API de Twitter 423 programación visual 37 lenguajes
Conexión de Twitter de programación visual 189 void acerca de 56
Firmware, codificación para 423­427
usando 117
Biblioteca de Twitter
usando, con soporte OAuth 423 calificador
Interfaz de dos cables (TWI) 247 selección volátil 75 voltaje 21 Voltios
de 22 VST 190
tipo 79 tipos de
manipulaciones 79
vvvv

EN alrededor de 11, 190


URL 190
UDP 397, 407
Puerto UDP 53 399 EN
Matriz de transistores Darlington ULN200x 320 Cableado
agua 20
de motor paso a paso
Tabla de ondas
unipolar a Arduino 318­320 Bus serie
universal. Véase la función USB WAV2C 356 336, 337
servidor web 419, 421
updateAudio() 351 Método
Usando
updateControl() 338, 342 USB
WEP , con la biblioteca Wi­Fi 418
alrededor de 239, 248 mientras que la estructura del bucle 95

[ 487 ]

www.it­ebooks.info
Machine Translated by Google

Wi­Fi 395
acerca de
412 modo ad hoc 413
modo puente 414 modo
infraestructura 413 modo extensor
de rango 414 WiFi.begin() 418
biblioteca Wi­Fi acerca
de 415 WEP,
usando con
418 WPA2, usando con 418
Wi­Fi 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

Wi­Fi 418
Función WriteData() 385

incógnita

Operador XOR 113

[ 488 ]

www.it­ebooks.info
Machine Translated by Google

Gracias por comprar


Programación en C para Arduino

Acerca de Packt Publishing


Packt, que se pronuncia 'packed', publicó su primer libro "Mastering phpMyAdmin for Effective MySQL
Management" en abril de 2004 y posteriormente continuó especializándose en la publicación de libros altamente
enfocados en tecnologías y soluciones específicas.

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.

Acerca de Packt Open Source


En 2010, Packt lanzó dos nuevas marcas, Packt Open Source y Packt Enterprise, para continuar con su enfoque
en la especialización. Este libro es parte de la marca Packt Open Source, que alberga libros publicados sobre
software creado con licencias de código abierto y ofrece información a cualquier persona, desde desarrolladores
avanzados hasta diseñadores web en ciernes. La marca Open Source también administra el Plan de regalías
de código abierto de Packt, por el cual Packt otorga regalías a cada proyecto de código abierto sobre cuyo
software se vende un libro.

Escribiendo para Packt


Aceptamos todas las consultas de personas interesadas en escribir. Las propuestas de libros deben
enviarse a [email protected]. Si su idea de libro aún está en una etapa inicial y le gustaría discutirla antes
de escribir una propuesta formal, contáctenos; uno de nuestros editores comisionados se pondrá en contacto
con usted.

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.it­ebooks.info
Machine Translated by Google

Centro multimedia Raspberry Pi


Libro de bolsillo: 978­1­782163­02­2 Tapa blanda: 108 páginas

Transforma tu Raspberry en un completo centro multimedia en


24 horas

1. Descubra cómo puede transmitir videos, música y


Fotos directamente a tu TV

2. Reproduce contenido existente desde tu computadora o


unidad USB

3. Mira y graba televisión vía satélite, cable o terrestre.

4. Crea tu propia biblioteca que se actualiza automáticamente


Incluye información detallada y material de portada.

Automatización del hogar con Raspberry Pi y


Arduino
ISBN: 978­1­849695­86­2 Tapa blanda: 380 páginas

¡Automatiza tu hogar con un conjunto de emocionantes


proyectos para Raspberry Pi!

1. Aprenda a adaptar dinámicamente su entorno vital con


ejemplos detallados paso a paso

2. Descubre cómo puedes aprovechar la potencia


combinada de Raspberry Pi y Arduino para tus
propios proyectos

3. Revoluciona la forma en que interactúas con tu hogar a


diario

Por favor, consulte www.PacktPub.com para obtener información sobre nuestros títulos.

www.it­ebooks.info
Machine Translated by Google

Redes Raspberry Pi
Libro de cocina
ISBN: 978­1­849694­60­5 Tapa blanda: 204 páginas

¡Una colección épica de recetas prácticas y atractivas para


Raspberry Pi!

1. Aprenda a instalar, administrar y mantener su Raspberry Pi

2. Crea un servidor de archivos en red para compartir


documentos, música y vídeos.

3. Aloje un portal web, una wiki de colaboración o incluso su propio


punto de acceso inalámbrico

4. Conéctese a su escritorio de forma remota, con el


mínimo esfuerzo

Procesamiento 2: Creativo
Libro de recetas de programación
ISBN: 978­1­849517­94­2 Tapa blanda: 436 páginas

Más de 90 recetas altamente efectivas para dar rienda


suelta a tu creatividad con arte interactivo, gráficos, visión
artificial, 3D y más.

1. Explora el lenguaje Processing con una amplia gama de recetas


prácticas para el arte computacional y los gráficos.

2. Amplia cobertura de temas que incluyen arte interactivo, visión


artificial, visualización, dibujo en 3D y mucho más con
Processing

3. Cree instalaciones de arte interactivas y aprenda a exportar sus


obras de arte para imprimirlas, visualizarlas en pantalla,
Internet y dispositivos móviles.

Por favor, consulte www.PacktPub.com para obtener información sobre nuestros títulos.

www.it­ebooks.info

También podría gustarte