You are on page 1of 24

J. Chamorro, J. Leiva, B.

Rubio

Display con Matriz LED

Informe Proyecto de Introducción a la Ingeniería Eléctrica y Electrónica

Escuela de Ingeniería Eléctrica


Proyecto de Escritura en una Matriz LED 8x8 Usando
Programación en Arduino

Javier Chamorro Valdés


Joshua Leiva Muñoz
Byron Rubio Ferrada

Proyecto de programación para el ramo de Introducción a la Ingeniería Eléctrica y


Electrónica

Sr. Sebastian Carlos Fingerhuth Massmann


Profesor Guía

Sr. Daniel Alejandro Contreras Veliz


Ayudante

Valparaíso, 09 de Junio del 2017


Resumen
Es obligatorio escribir un resumen en español y en inglés. En la medida de lo posible debe completar
esta página, sin sobrepasarse a la siguiente. Se sugiere dejar el resumen para el final, ya que sabrá con
certeza que es lo que incluye el informe. Luego de su resumen debe escribir palabras claves, como por
ejemplo los tópicos más importantes relevantes al documento.

Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Ut purus elit, vestibulum ut, placerat ac,
adipiscing vitae, felis. Curabitur dictum gravida mauris. Nam arcu libero, nonummy eget, consectetuer
id, vulputate a, magna. Donec vehicula augue eu neque. Pellentesque habitant morbi tristique senectus
et netus et malesuada fames ac turpis egestas. Mauris ut leo. Cras viverra metus rhoncus sem. Nulla et
lectus vestibulum urna fringilla ultrices. Phasellus eu tellus sit amet tortor gravida placerat. Integer
sapien est, iaculis in, pretium quis, viverra ac, nunc. Praesent eget sem vel leo ultrices bibendum.
Aenean faucibus. Morbi dolor nulla, malesuada eu, pulvinar at, mollis ac, nulla. Curabitur auctor semper
nulla. Donec varius orci eget risus. Duis nibh mi, congue eu, accumsan eleifend, sagittis quis, diam. Duis
eget orci sit amet orci dignissim rutrum.

Nam dui ligula, fringilla a, euismod sodales, sollicitudin vel, wisi. Morbi auctor lorem non justo. Nam
lacus libero, pretium at, lobortis vitae, ultricies et, tellus. Donec aliquet, tortor sed accumsan bibendum,
erat ligula aliquet magna, vitae ornare odio metus a mi. Morbi ac orci et nisl hendrerit mollis.
Suspendisse ut massa. Cras nec ante. Pellentesque a nulla. Cum sociis natoque penatibus et magnis dis
parturient montes, nascetur ridiculus mus. Aliquam tincidunt urna. Nulla ullamcorper vestibulum
turpis. Pellentesque cursus luctus mauris.

Nam dui ligula, fringilla a, euismod sodales, sollicitudin vel, wisi. Morbi auctor lorem non justo. Nam
lacus libero, pretium at, lobortis vitae, ultricies et, tellus. Donec aliquet, tortor sed accumsan bibendum,
erat ligula aliquet magna, vitae ornare odio metus a mi. Morbi ac orci et nisl hendrerit mollis.
Suspendisse ut massa. Cras nec ante. Pellentesque a nulla. Donec aliquet, tortor sed accumsan
bibendum, erat ligula aliquet magna, vitae ornare odio metus a mi. Morbi ac orci et nisl hendrerit
Pellentesque cursus luctus mauris.

Palabras claves: protocolo, Arduino, código, programación.


Abstract
It’s mandatory to write an abstract in Spanish and English. You should complete this page as far as
possible, without exceed to the next one. It’s suggested to leave the summary to the end, because you
will know for sure what the report includes. You must type some keywords, such as relevant topics
involved in the document.

Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Ut purus elit, vestibulum ut, placerat ac,
adipiscing vitae, felis. Curabitur dictum gravida mauris. Nam arcu libero, nonummy eget, consectetuer
id, vulputate a, magna. Donec vehicula augue eu neque. Pellentesque habitant morbi tristique senectus
et netus et malesuada fames ac turpis egestas. Mauris ut leo. Cras viverra metus rhoncus sem. Nulla et
lectus vestibulum urna fringilla ultrices. Phasellus eu tellus sit amet tortor gravida placerat. Integer
sapien est, iaculis in, pretium quis, viverra ac, nunc. Praesent eget sem vel leo ultrices bibendum.
Aenean faucibus. Morbi dolor nulla, malesuada eu, pulvinar at, mollis ac, nulla. Curabitur auctor semper
nulla. Donec varius orci eget risus. Duis nibh mi, congue eu, accumsan eleifend, sagittis quis, diam. Duis
eget orci sit amet orci dignissim rutrum.

Nam dui ligula, fringilla a, euismod sodales, sollicitudin vel, wisi. Morbi auctor lorem non justo. Nam
lacus libero, pretium at, lobortis vitae, ultricies et, tellus. Donec aliquet, tortor sed accumsan bibendum,
erat ligula aliquet magna, vitae ornare odio metus a mi. Morbi ac orci et nisl hendrerit mollis.
Suspendisse ut massa. Cras nec ante. Pellentesque a nulla. Cum sociis natoque penatibus et magnis dis
parturient montes, nascetur ridiculus mus. Aliquam tincidunt urna. Nulla ullamcorper vestibulum
turpis. Pellentesque cursus luctus mauris.

Nam dui ligula, fringilla a, euismod sodales, sollicitudin vel, wisi. Morbi auctor lorem non justo. Nam
lacus libero, pretium at, lobortis vitae, ultricies et, tellus. Donec aliquet, tortor sed accumsan bibendum,
erat ligula aliquet magna, vitae ornare odio metus a mi. Morbi ac orci et nisl hendrerit mollis.
Suspendisse ut massa. Cras nec ante. Pellentesque a nulla. Cum sociis natoque penatibus et magnis dis
parturient montes, nascetur ridiculus mus. Aliquam tincidunt urna. Cum sociis natoque urna. Is
parturient montes, nascetur ridiculus mus. Aliquam tincidunt urna. Nulla ullamcorper vestibulum
turpis. Pellentesque cursus luctus mauris.

Key words: protocol, Arduino, code, programming


Índice general
Introducción .............................................................................................................................................. 1
Objetivos generales ................................................................................................................................................................... 1

1 Antecedentes Generales y Propuesta ........................................................................................... 2

2 Solución ................................................................................................................................................... 4

Discusión y conclusiones ................................................................................................................... 13

Bibliografía .............................................................................................................................................. 14

A Un apéndice ................................................................................... Error! Bookmark not defined.


Introducción
En el contexto de los grandes avances en las tecnologías de la información y comunicaciones se hace
cada vez más relevante para los profesionales universitarios, especialmente ingenieros, el ambientarse
y capacitarse en el uso de algoritmos y lenguajes de programación que les permitan comprender los
trabajos y ensayos realizados por sus colegas, a la vez que les ayudan en la modelación y simulación de
los diversos variables que se encuentran presentes en los ámbitos que estudian o investigan. No basta
con ser capaz de utilizar alguno u otro software relativo a su especialización, se requiere tener
conocimientos de programación.

El perfil del Ingeniero Civil en Electricidad o Electrónica de la Pontificia Universidad Católica de


Valparaíso indica que el profesional “utiliza diversas tecnologías de la información, que apoyen su
desempeño profesional, de manera fluida y eficaz” [1]. Es a partir de esta idea que se busca tomar una
primera aproximación a los lenguajes de programación, de una manera simple y didáctica, para
ambientar a los estudiantes de la Escuela de Ingeniería Eléctrica.

Debido a que este informe se realiza durante la primera asignatura de la carrera, que tiene un carácter
introductorio al mundo de la ingeniería, es que no se profundiza en los distintos aspectos más técnicos
del informe. El objetivo es una introducción a lo que es la programación con código, no se espera
obtener un amplio dominio del lenguaje de programación, ya que eso está muy por sobre el alcance de
este proyecto.

El presente informe trata acerca del uso del microcontrolador conocido como ARDUINO y de la
implementación de un código que permita representar imágenes y figuras fácilmente reconocibles en
una matriz LED de 8x8 luces.

Objetivos generales
 Obtener una primera aproximación a lo que son los lenguajes de programación.
 Desarrollar e implementar un código en el entorno de programación ARDUINO.
 Redactar en conformidad un informe que ocupe la plantilla de informes EIE.

1
1 Antecedentes Generales y Propuesta

1.1 ARDUINO UNO


El Arduino es una plataforma de Hardware de código abierto, que está basada en una placa de circuito
interno que contiene un micro-controlador, contiene varias entradas y salidas, analógicas y digitales,
en un entorno de trabajo basado en el lenguaje de programación Procesing. Su propósito es facilitar la
parte electrónica en el desarrollo de diferentes proyectos, así como el lenguaje de programación es
sencillo y fácil de aprender. El sistema trabajo por medio de la recepción de datos a través de sus pines,
los cuales pueden ser conectados a una gran cantidad de sensores y sistemas externos, pudiendo
manejar luces, motores u otros actuadores.

1.2 Circuito Integrado MAX7219:


El MAX7219 es un chip capaz de controlar hasta 8 dígitos de 7 segmentos o 64 diodos LED
independientes. El chip incorpora un decoder BCD code-B, realiza multiplexado, y tiene una memoria
RAM interna de 8x8 para almacenar el valor de cada dígito. Solamente se necesita de una resistencia
externa para hacerlo funcionar. Se maneja tan sólo con 3 patillas y es compatible con SPI™, QSPI™, y
MICROWIRE™.

El MAX7219 es ideal para controlar fácilmente una gran cantidad de diodos LED o dígitos de 7
segmentos. También podemos controlar una matriz de LED de 8x8 con un sólo chip.

1.3 Pong
El juego Pong es un juego de deportes en dos dimensiones que simula una mesa. El jugador controla
una paleta moviéndola verticalmente y puede competir tanto contra la maquina u otro jugador humano.
Los jugadores usan las paletas para pegarle a una pelota de un lado hacia el otro. El juego consiste en
que el jugador con más puntos consigue llevarse la victoria. Estos puntos se consiguen cuando el
jugador adversario falla intentando devolver la pelota.

2
Error! Use the Home tab to apply Título 1 to the text that you want to appear here. Error! Use the
Home tab to apply Título 1 to the text that you want to appear here.
Arduino Uno:

Arduino Uno es una placa electrónica basada en el microcontrolador ATmega328. Cuenta con 14
entradas/salidas digitales, de las cuales 6 se pueden utilizar como salidas PWM (Modulación por ancho
de pulsos) y otras 6 son entradas analógicas. Además, incluye un resonador cerámico de 16 MHz, un
conector USB, un conector de alimentación, una cabecera ICSP y un botón de reseteado. La placa incluye
todo lo necesario para que el microcontrolador haga su trabajo, basta conectarla a un ordenador con
un cable USB o a la corriente eléctrica a través de un transformador.

Potenciometro:

Un potenciómetro es un resistor eléctrico con un valor de resistencia variable y generalmente ajustable


manualmente. Los pontenciómetros utilizan tres terminales y se suelen utilizar en circuitos de poca
corriente, para circuitos de mayor corriente se utilizan los reostatos. En muchos dispositivos eléctricos
los potenciómetros son los que establecen el nivel de salida. En este caso se utilizará un potenciómetro
de 10.000Ω (o bien, 10kΩ).

3
2 Solución
En el presente segmento se procederá a explicar el código utilizado en el proyecto para la
implementación del conocido juego Pong. No sea realiza una explicación exhaustiva de cada línea de
código ni de cada comando utilizado, ya que eso estaría por sobre el alcance del presente proyecto, pero
sí se realiza una explicación del algoritmo de trabajo y de las distintas variables utilizadas.

Las primeras líneas de código hasta la línea 71 se utilizan principalmente para definir diferentes
parámetros y variables globales utilizados en el proyecto, los cuales se detallan a continuación

 POTPIN: entrada de tensión al ARDUINO desde el potenciómetro, se asigna al pin “A5”.


 PADSIZE: define el largo de la “paleta” del Pong, se define con un largo de 3.
 BALL_DELAY: tiempo que demora la pelota en desplazarse de una posición a otra contigua, se
define a 0,2 segundos.
 GAME_DELAY: tiempo que demora el juego en actualizarse, en volver a leer sus entradas y
desarrollar sus funciones, se define a 0,01 segundos.
 BOUNCE_VERTICAL: define un valor para cuando se cumple la condición de rebote en el borde
superior del display, se le asigna el valor 1.
 BOUNCE_HORIZONTAL: similar al parámetro anterior para la condición de rebote en los
bordes laterales del display, se le asigna el valor -1.
 NEW_GAME_ANIMATION_SPEED: tiempo que demora el juego en comenzar una nueva partida
después de terminar una, se define en 0,05 segundos.
 HIT_NONE: condición cuando la pelota llega a la parte inferior del display sin tocar a la paleta,
se le asigna el valor 0
 HIT_CENTER: condición cuando la pelota llega a la parte inferior del display tocando a la paleta
en la sección central, se le asigna el valor 1.
 HIT_LEFT: condición cuando la pelota llega a la parte inferior del display tocando a la paleta
en la sección izquierda, se le asigna el valor 2.
 HIT_RIGHT: condición cuando la pelota llega a la parte inferior del display tocando a la paleta
en la sección derecha, se le asigna el valor 3.
 byte sad: imagen que se presenta al comenzar una partida. Se define como 8 números binarios
de 8 bits que indican con un 1 las luces de la matriz que deben estar encendidas y con un 0 las
luces que deben estar apagadas.
 byte smile: imagen que se presenta al perder una partida. Se define de la misma manera que el
anterior.

4
Error! Use the Home tab to apply Título 1 to the text that you want to appear here.

 byte direction: número de 8 bits que representa la dirección que puede tomar la pelota. Puede
tomar cualquier valor entre 0 y 7. El 0 corresponde al norte y el resto de los valores toman la
dirección que corresponde según el sentido horario.
 Int xball: posición actual de la pelota en el eje x.
 Int yball: posición actual de la pelota en el eje y.
 Int yball_prev: posición de la pelota en el eje y durante el estado anterior.
 Byte xpad: número de 8 bits que se ocupa para definir la posición en el eje x de la “paleta” en
el juego. Corresponde a la totalidad de la paleta.
 ball_timer: variable utilizada para asignar el delay al comenzar una nueva partida.

En funciones posteriores se definen otras variables de tipo local que no es necesario definirlas de
manera global.

Los comandos debug y serial.print no son necesarios para el algoritmo de trabajo, pero son necesarios
para verificar el buen funcionamiento del código. [2]

Las líneas 79 a 94 que se muestran a continuación definen la función newGame que fija el protocolo
que se sigue cada vez que el programa llama a esta función. Lo que hace es primero definir la posición
inicial de la pelota junto con su dirección, que puede tomar en este caso valores 3, 4 o 5, que
corresponden a las direcciones sureste, sur y suroeste, respectivamente. Luego prende sucesivamente
todas las luces de la matriz, presenta la figura de byte smile por 1,5 segundos y finalmente apaga todas
las luces.

Listado 2-1 Código de Función newGame

79 void newGame() {
80 lc.clearDisplay(0);
81 // posición inicial
82 xball = random(1, 7);
83 yball = 1;
84 direction = random(3, 6); // Movimiento al sur
85 for(int r = 0; r < 8; r++){
86 for(int c = 0; c < 8; c++){
87 lc.setLed(0, r, c, HIGH);
88 delay(NEW_GAME_ANIMATION_SPEED);
89 }
90 }
91 setSprite(smile);
92 delay(1500);
93 lc.clearDisplay(0);
94 }

La función “setPad” le asigna un valor a la variable xpad de acuerdo a la posición del potenciómetro.
Gracias a la línea de código 97 es que el programa sabe en qué posición colocar la paleta.

Listado 2-2 Código de función setPad

96 void setPad() {
97 xpad = map(analogRead(POTPIN), 0, 1020, 8 - PADSIZE, 0);
98 }

5
Error! Use the Home tab to apply Título 1 to the text that you want to appear here.

Entre las líneas 114 y 137 se definen tres nuevas variables que se ocupan para analizar el estado actual
de la pelota para saber cómo responder. La variable checkBounce se ocupa para ver cuándo la pelota
llega a los bordes del display. Mientras la pelota no llegue a los bordes, la variable tendrá valor 0, pero
si la pelota llega a algún borde la variable tomará el mismo valor que la variable auxiliar bounce. La
variable getHit se ocupa para ver si la pelota toca a la paleta al llegar a la parte inferior del display y
toma diferentes valores dependiendo de en qué sección la pelota toca a la paleta o si no la toca. La
variable checkLoose toma el valor 1 cuando la pelota llega a la parte inferior del display y la variable
getHit tiene el valor de HIT_NONE.

Listado 2-3 Código de Definición de Variables Locales

114 int checkBounce() {


115 if(!xball || !yball || xball == 7 || yball == 6){
116 int bounce = (yball == 0 || yball == 6) ? BOUNCE_HORIZONTAL : BOUNCE_VERTICAL;
117 #ifdef DEBUG
118 debug(bounce == BOUNCE_HORIZONTAL ? "HORIZONTAL" : "VERTICAL");
119 #endif
120 return bounce;
121 }
122 return 0;
123 }
124
125 int getHit() {
126 if(yball != 6 || xball < xpad || xball > xpad + PADSIZE){
127 return HIT_NONE;
128 }
129 if(xball == xpad + PADSIZE / 2){
130 return HIT_CENTER;
131 }
132 return xball < xpad + PADSIZE / 2 ? HIT_LEFT : HIT_RIGHT;
133 }
134
135 bool checkLoose() {
136 return yball == 6 && getHit() == HIT_NONE;
137 }

Las líneas de código entre la 139 y la 241 definen el movimiento de la pelota mientras está en juego a
través de la función moveBall. Cuando la pelota choca con algún borde o con la paleta cambia su
dirección dependiendo de la dirección desde la que golpea y el lugar en el que golpea. Si todo funciona
bien y la partida no ha terminado, los valores de posición de la pelota en el eje x y en el eje y aumentan
o disminuyen en 1 durante cada iteración del programa.

Listado 2-4 Código de Función moveBall

139 void moveBall() {


140 debug("MOVE");
141 int bounce = checkBounce();
142 if(bounce) {
143 switch(direction){
144 case 0:
145 direction = 4;
146 break;
147 case 1:
148 direction = (bounce == BOUNCE_VERTICAL) ? 7 : 3;
149 break;
150 case 2:
151 direction = 6;

6
Error! Use the Home tab to apply Título 1 to the text that you want to appear here.

152 break;
153 case 6:
154 direction = 2;
155 break;
156 case 7:
157 direction = (bounce == BOUNCE_VERTICAL) ? 1 : 5;
158 break;
159 case 5:
160 direction = (bounce == BOUNCE_VERTICAL) ? 3 : 7;
161 break;
162 case 3:
163 direction = (bounce == BOUNCE_VERTICAL) ? 5 : 1;
164 break;
165 case 4:
166 direction = 0;
167 break;
168 }
169 debug("->");
170 }
171
172 // Verificar golpe: direccion modificada es izquierda o derecha
173 switch(getHit()){
174 case HIT_LEFT:
175 if(direction == 0){
176 direction = 7;
177 } else if (direction == 1){
178 direction = 0;
179 }
180 break;
181 case HIT_RIGHT:
182 if(direction == 0){
183 direction = 1;
184 } else if(direction == 7){
185 direction = 0;
186 }
187 break;
188 }
189
190 // Verificar direcciones ortogonales y bordes
191 if((direction == 0 && xball == 0) || (direction == 4 && xball == 7)){
192 direction++;
193 }
194 if(direction == 0 && xball == 7){
195 direction = 7;
196 }
197 if(direction == 4 && xball == 0){
198 direction = 3;
199 }
200 if(direction == 2 && yball == 0){
201 direction = 3;
202 }
203 if(direction == 2 && yball == 6){
204 direction = 1;
205 }
206 if(direction == 6 && yball == 0){
207 direction = 5;
208 }
209 if(direction == 6 && yball == 6){
210 direction = 7;
211 }
212
213 // Caso de las esquinas
214 if(xball == 0 && yball == 0){
215 direction = 3;
216 }

7
Error! Use the Home tab to apply Título 1 to the text that you want to appear here.

217 if(xball == 0 && yball == 6){


218 direction = 1;
219 }
220 if(xball == 7 && yball == 6){
221 direction = 7;
222 }
223 if(xball == 7 && yball == 0){
224 direction = 5;
225 }
226
227 yball_prev = yball;
228 if(2 < direction && direction < 6) {
229 yball++;
230 } else if(direction != 6 && direction != 2) {
231 yball--;
232 }
233 if(0 < direction && direction < 4) {
234 xball++;
235 } else if(direction != 0 && direction != 4) {
236 xball--;
237 }
238 xball = max(0, min(7, xball));
239 yball = max(0, min(6, yball));
240 debug("AFTER MOVE");
241 }

La función gameOver cuando es llamada produce la imagen del byte sad en el display por 1,5 segundos
y luego apaga todas las luces. La función gameDraw traspasa la información de posición de la pelota al
display. Cada vez que la pelota cambia de posición prende la luz que corresponde a la nueva posición y
borra (apaga) la última posición que tomó la pelota.

Listado 2-5 Código de Funciones gameOver y gameDraw

243 void gameOver() {


244 setSprite(sad);
245 delay(1500);
246 lc.clearDisplay(0);
247 }
248
249 void drawGame() {
250 if(yball_prev != yball){
251 lc.setRow(0, yball_prev, 0);
252 }
253 lc.setRow(0, yball, byte(1 << (xball)));
254 byte padmap = byte(0xFF >> (8 - PADSIZE) << xpad) ;
255 #ifdef DEBUG
256 //Serial.println(padmap, BIN);
257 #endif
258 lc.setRow(0, 7, padmap);
259 }

La función setup debe realizarse cada vez que se prenda el dispositivo, ya que el modo normal del
MAX7219 cada vez que se prende es el de ahorro de energía. Esta función activa al MAX7219, define la
intensidad de brillo del display y llama a la función newGame para comenzar una partida.

Listado 2-6 Código de Función setup

261 void setup() {

8
Error! Use the Home tab to apply Título 1 to the text that you want to appear here.

262 // El MAX72XX está en modo de ahorro de energia cuando se prende,


263 // se necesita realizar un llamado de activación
264 pinMode(POTPIN, INPUT);
265
266 lc.shutdown(0,false);
267 // Fijar el brillo a un valor medio
268 lc.setIntensity(0, 8);
269 // y limpiar el display
270 lc.clearDisplay(0);
271 randomSeed(analogRead(0));
272 #ifdef DEBUG
273 Serial.begin(9600);
274 Serial.println("Pong");
275 #endif
276 newGame();
277 ball_timer = timer.every(BALL_DELAY, moveBall);
278 }

La función loop es la que mantiene el programa actualizándose constantemente, llamando a las


funciones setPad y drawGame durante cada iteración que la partida se mantiene activa. Esta función
también verifica durante cada iteración el valor de la variable checkLoose. Cuando esa variable toma el
valor 1, llama a la función gameOver para terminar la partida actual y luego llama a la función newGame
para comenzar una nueva partida.

Listado 2-7 Código de función loop

281 void loop() {


282 timer.update();
283 // Panel de movimiento
284 setPad();
285 #ifdef DEBUG
286 Serial.println(xpad);
287 #endif
288 // Actualizar pantalla
289 drawGame();
290 if(checkLoose()) {
291 debug("LOOSE");
292 gameOver();
293 newGame();
294 }
295 delay(GAME_DELAY);
296 }

9
3 Desarrollo
En la presente sección se procederá a indicar los distintos elementos físicos utilizados y a explicar el
esquema de conexión, como para que puedan fácilmente reproducirse los resultados del proyecto.

Los primeros pasos a seguir son conseguir los elementos necesarios y realizar el esquema de conexión
para la implementación del proyecto, como se muestra en la Figura 1. [3]

Figura 1 Esquema de Conexión

Los elementos utilizados en el desarrollo del proyecto son los siguientes:

10
Error! Use the Home tab to apply Título 1 to the text that you want to appear here.

 ARDUINO UNO.
 Matriz LED 8x8.
 C.I. MAX7219.
 Potenciómetro de 10 [kΩ].
 Piezo Buzzer.
 Protoboard.
 Cambles de conexión.

El C.I. se utiliza principalmente porque el ARDUINO no tiene suficientes salidas como para activar
individualmente cada LED de la matriz. El MAX7219 permite usar solo una salida del ARDUINO para
enviar las señal de encendido y apagado a toda la matriz LED.

Para esta aplicación se puede eliminar el Piezo Buzzer, puesto que no hace nada, pero puede ocuparse
para añadir algunos sonidos que inmerjan al jugador

Los terminales del potenciómetro se conectan a la salida de 5 [V] del ARDUINO, al terminal de GROUND
y a la entrada A5

11
4 Resultados

12
Discusión y conclusiones
Las conclusiones finales del trabajo no se consideran como capítulos del texto, sin embargo ellas son
obligatorias para la estructura general del informe de proyecto e independientes de aquellas que
puedan existir en cada capítulo.

En ella, se deben indicar las conclusiones finales obtenidas, su proyección futura, usos, modificaciones,
limitaciones, etc. No debe incluir datos nuevos. Recuerde que las explicaciones de cada tema las dio a
conocer en cada uno de los capítulos anteriormente descritos.

Para el trabajo de un año (Proyecto I y II para ingenieros, seminario y proyecto para civiles), se espera
que su discusión y conclusiones tenga más o menos la misma extensión que la introducción, es decir
entre tres y cinco páginas.

13
Bibliografía

[1] E. d. I. Eléctrica, «Perfil de Egreso Carrera Ingeniería Civil Eléctrica,» Valparaíso, 2013.

[2] «ARDUINO AG,» 2017. [En línea]. Available: http://playground.arduino.com.

[3] schwiftyarduino, «schwiftyarduino,» 16 Julio 2016. [En línea]. Available:


schwiftyarduino.wordpress.com.

[4] A. Passoti, «Arduino Pong with 8x8 LED matrix and MAX7219,» itOPEN, 09 Marzo 2012. [En línea].
Available: https://www.itopen.it/.

14
A Código de Juego Pong en ARDUINO [4]
Listado A-1 Código Completo Juego Pong en ARDUINO

1 /**
2 * Jugar pong en una matriz 8x8
3 *
4 * 0 1 2 3 4 5 6 7
5 * 0
6 * 1
7 * 2 7 0 1
8 * 3 6 X 2 (direcciones)
9 * 4 5 4 3
10 * 5
11 * 6
12 * 7 [pad]
13 *
14 *
15 *
16 *
17 */
18
19
20 #include "LedControl.h"
21 #include "Timer.h"
22
23
24 #define POTPIN A5 // Potenciometro
25 #define PADSIZE 3
26 #define BALL_DELAY 200
27 #define GAME_DELAY 10
28 #define BOUNCE_VERTICAL 1
29 #define BOUNCE_HORIZONTAL -1
30 #define NEW_GAME_ANIMATION_SPEED 50
31 #define HIT_NONE 0
32 #define HIT_CENTER 1
33 #define HIT_LEFT 2
34 #define HIT_RIGHT 3
35
36
37 //#define DEBUG 1
38
39 byte sad[] = {
40 B00000000,
41 B01000100,
42 B00010000,
43 B00010000,
44 B00000000,
45 B00111000,
46 B01000100,

15
Error! Use the Home tab to apply Título 6 to the text that you want to appear here. Error! Use the
Home tab to apply Título 6 to the text that you
want to appear here.
47 B00000000
48 };
49
50 byte smile[] = {
51 B00000000,
52 B01000100,
53 B00010000,
54 B00010000,
55 B00010000,
56 B01000100,
57 B00111000,
58 B00000000
59 };
60
61
62 Timer timer;
63
64 LedControl lc = LedControl(4,3,2,1);
65
66 byte direction; // Rosa de los vientos, 0 es el norte
67 int xball;
68 int yball;
69 int yball_prev;
70 byte xpad;
71 int ball_timer;
72
73 void setSprite(byte *sprite){
74 for(int r = 0; r < 8; r++){
75 lc.setRow(0, r, sprite[r]);
76 }
77 }
78
79 void newGame() {
80 lc.clearDisplay(0);
81 // posición inicial
82 xball = random(1, 7);
83 yball = 1;
84 direction = random(3, 6); // Movimiento al sur
85 for(int r = 0; r < 8; r++){
86 for(int c = 0; c < 8; c++){
87 lc.setLed(0, r, c, HIGH);
88 delay(NEW_GAME_ANIMATION_SPEED);
89 }
90 }
91 setSprite(smile);
92 delay(1500);
93 lc.clearDisplay(0);
94 }
95
96 void setPad() {
97 xpad = map(analogRead(POTPIN), 0, 1020, 8 - PADSIZE, 0);
98 }
99
100 void debug(const char* desc){
101 #ifdef DEBUG
102 Serial.print(desc);
103 Serial.print(" XY: ");
104 Serial.print(xball);
105 Serial.print(", ");
106 Serial.print(yball);
107 Serial.print(" XPAD: ");
108 Serial.print(xpad);
109 Serial.print(" DIR: ");
110 Serial.println(direction);

16
Error! Use the Home tab to apply Título 6 to the text that you want to appear here. Error! Use the
Home tab to apply Título 6 to the text that you
want to appear here.
111 #endif
112 }
113
114 int checkBounce() {
115 if(!xball || !yball || xball == 7 || yball == 6){
116 int bounce = (yball == 0 || yball == 6) ? BOUNCE_HORIZONTAL : BOUNCE_VERTICAL;
117 #ifdef DEBUG
118 debug(bounce == BOUNCE_HORIZONTAL ? "HORIZONTAL" : "VERTICAL");
119 #endif
120 return bounce;
121 }
122 return 0;
123 }
124
125 int getHit() {
126 if(yball != 6 || xball < xpad || xball > xpad + PADSIZE){
127 return HIT_NONE;
128 }
129 if(xball == xpad + PADSIZE / 2){
130 return HIT_CENTER;
131 }
132 return xball < xpad + PADSIZE / 2 ? HIT_LEFT : HIT_RIGHT;
133 }
134
135 bool checkLoose() {
136 return yball == 6 && getHit() == HIT_NONE;
137 }
138
139 void moveBall() {
140 debug("MOVE");
141 int bounce = checkBounce();
142 if(bounce) {
143 switch(direction){
144 case 0:
145 direction = 4;
146 break;
147 case 1:
148 direction = (bounce == BOUNCE_VERTICAL) ? 7 : 3;
149 break;
150 case 2:
151 direction = 6;
152 break;
153 case 6:
154 direction = 2;
155 break;
156 case 7:
157 direction = (bounce == BOUNCE_VERTICAL) ? 1 : 5;
158 break;
159 case 5:
160 direction = (bounce == BOUNCE_VERTICAL) ? 3 : 7;
161 break;
162 case 3:
163 direction = (bounce == BOUNCE_VERTICAL) ? 5 : 1;
164 break;
165 case 4:
166 direction = 0;
167 break;
168 }
169 debug("->");
170 }
171
172 // Verificar golpe: direccion modificada es izquierda o derecha
173 switch(getHit()){
174 case HIT_LEFT:

17
Error! Use the Home tab to apply Título 6 to the text that you want to appear here. Error! Use the
Home tab to apply Título 6 to the text that you
want to appear here.
175 if(direction == 0){
176 direction = 7;
177 } else if (direction == 1){
178 direction = 0;
179 }
180 break;
181 case HIT_RIGHT:
182 if(direction == 0){
183 direction = 1;
184 } else if(direction == 7){
185 direction = 0;
186 }
187 break;
188 }
189
190 // Verificar direcciones ortogonales y bordes
191 if((direction == 0 && xball == 0) || (direction == 4 && xball == 7)){
192 direction++;
193 }
194 if(direction == 0 && xball == 7){
195 direction = 7;
196 }
197 if(direction == 4 && xball == 0){
198 direction = 3;
199 }
200 if(direction == 2 && yball == 0){
201 direction = 3;
202 }
203 if(direction == 2 && yball == 6){
204 direction = 1;
205 }
206 if(direction == 6 && yball == 0){
207 direction = 5;
208 }
209 if(direction == 6 && yball == 6){
210 direction = 7;
211 }
212
213 // Caso de las esquinas
214 if(xball == 0 && yball == 0){
215 direction = 3;
216 }
217 if(xball == 0 && yball == 6){
218 direction = 1;
219 }
220 if(xball == 7 && yball == 6){
221 direction = 7;
222 }
223 if(xball == 7 && yball == 0){
224 direction = 5;
225 }
226
227 yball_prev = yball;
228 if(2 < direction && direction < 6) {
229 yball++;
230 } else if(direction != 6 && direction != 2) {
231 yball--;
232 }
233 if(0 < direction && direction < 4) {
234 xball++;
235 } else if(direction != 0 && direction != 4) {
236 xball--;
237 }
238 xball = max(0, min(7, xball));

18
Error! Use the Home tab to apply Título 6 to the text that you want to appear here. Error! Use the
Home tab to apply Título 6 to the text that you
want to appear here.
239 yball = max(0, min(6, yball));
240 debug("AFTER MOVE");
241 }
242
243 void gameOver() {
244 setSprite(sad);
245 delay(1500);
246 lc.clearDisplay(0);
247 }
248
249 void drawGame() {
250 if(yball_prev != yball){
251 lc.setRow(0, yball_prev, 0);
252 }
253 lc.setRow(0, yball, byte(1 << (xball)));
254 byte padmap = byte(0xFF >> (8 - PADSIZE) << xpad) ;
255 #ifdef DEBUG
256 //Serial.println(padmap, BIN);
257 #endif
258 lc.setRow(0, 7, padmap);
259 }
260
261 void setup() {
262 // El MAX72XX está en modo de ahorro de energia cuando se prende,
263 // se necesita realizar un llamado de activación
264 pinMode(POTPIN, INPUT);
265
266 lc.shutdown(0,false);
267 // Fijar el brillo a un valor medio
268 lc.setIntensity(0, 8);
269 // y limpiar el display
270 lc.clearDisplay(0);
271 randomSeed(analogRead(0));
272 #ifdef DEBUG
273 Serial.begin(9600);
274 Serial.println("Pong");
275 #endif
276 newGame();
277 ball_timer = timer.every(BALL_DELAY, moveBall);
278 }
279
280
281 void loop() {
282 timer.update();
283 // Panel de movimiento
284 setPad();
285 #ifdef DEBUG
286 Serial.println(xpad);
287 #endif
288 // Actualizar pantalla
289 drawGame();
290 if(checkLoose()) {
291 debug("LOOSE");
292 gameOver();
293 newGame();
294 }
295 delay(GAME_DELAY);
296 }

19

You might also like