Está en la página 1de 28

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

Loremipsum dolor sit amet, consectetueradipiscingelit. Utpuruselit, vestibulumut,


placerat ac, adipiscing vitae, felis. Curabiturdictumgravidamauris. Namarcu libero,
nonummyeget, consectetuer id, vulputate a, magna. Donec vehicula augueeuneque.
Pellentesquehabitantmorbitristiquesenectus et netus et
malesuadafamesacturpisegestas. Mauris ut leo. Crasviverrametusrhoncussem. Nulla
et lectusvestibulum urna fringilla ultrices. Phaselluseutellussitamet tortor
gravidaplacerat. Integersapienest, iaculis in, pretiumquis, viverraac, nunc.
Praesentegetsemvel leo ultrices bibendum. Aeneanfaucibus. Morbi dolor nulla,
malesuadaeu, pulvinar at, mollisac, nulla. Curabiturauctorsempernulla.
Donecvariusorciegetrisus. Duisnibhmi, congueeu, accumsaneleifend, sagittisquis,
diam. Duisegetorci sit ametorcidignissimrutrum.

Nam dui ligula, fringilla a, euismodsodales, sollicitudinvel, wisi. Morbiauctorlorem non


justo. Nam lacus libero, pretium at, lobortis vitae, ultricieset, tellus. Donecaliquet,
tortorsedaccumsanbibendum, erat ligula aliquet magna, vitae ornareodiometus a mi.
Morbi ac orcietnislhendreritmollis. Suspendisseutmassa. Crasnec ante. Pellentesque a
nulla. Cum sociisnatoquepenatibusetmagnis dis parturient montes, nasceturridiculus
mus. Aliquamtincidunturna. Nullaullamcorpervestibulumturpis.
Pellentesquecursusluctusmauris.

Nam dui ligula, fringilla a, euismodsodales, sollicitudinvel, wisi. Morbiauctorlorem non


justo. Nam lacus libero, pretium at, lobortis vitae, ultricieset, tellus. Donecaliquet,
tortorsedaccumsanbibendum, erat ligula aliquet magna, vitae ornareodiometus a mi.
Morbi ac orcietnislhendreritmollis. Suspendisseutmassa. Crasnec ante. Pellentesque a
nulla. Donecaliquet, tortorsedaccumsanbibendum, erat ligula aliquet magna, vitae
ornareodiometus a mi. MorbiacorcietnislhendreritPellentesquecursusluctusmauris.
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.

Loremipsum dolor sit amet, consectetueradipiscingelit. Utpuruselit, vestibulumut,


placerat ac, adipiscing vitae, felis. Curabiturdictumgravidamauris. Namarcu libero,
nonummyeget, consectetuer id, vulputate a, magna. Donec vehicula augueeuneque.
Pellentesquehabitantmorbitristiquesenectus et netus et
malesuadafamesacturpisegestas. Mauris ut leo. Crasviverrametusrhoncussem. Nulla
et lectusvestibulum urna fringilla ultrices. Phaselluseutellussitamet tortor
gravidaplacerat. Integersapienest, iaculis in, pretiumquis, viverraac, nunc.
Praesentegetsemvel leo ultrices bibendum. Aeneanfaucibus. Morbi dolor nulla,
malesuadaeu, pulvinar at, mollisac, nulla. Curabiturauctorsempernulla.
Donecvariusorciegetrisus. Duisnibhmi, congueeu, accumsaneleifend, sagittisquis,
diam. Duisegetorci sit ametorcidignissimrutrum.

Nam dui ligula, fringilla a, euismodsodales, sollicitudinvel, wisi. Morbiauctorlorem non


justo. Nam lacus libero, pretium at, lobortis vitae, ultricieset, tellus. Donecaliquet,
tortorsedaccumsanbibendum, erat ligula aliquet magna, vitae ornareodiometus a mi.
Morbi ac orcietnislhendreritmollis. Suspendisseutmassa. Crasnec ante. Pellentesque a
nulla. Cum sociisnatoquepenatibusetmagnis dis parturient montes, nasceturridiculus
mus. Aliquamtincidunturna. Nullaullamcorpervestibulumturpis.
Pellentesquecursusluctusmauris.

Nam dui ligula, fringilla a, euismodsodales, sollicitudinvel, wisi. Morbiauctorlorem non


justo. Nam lacus libero, pretium at, lobortis vitae, ultricieset, tellus. Donecaliquet,
tortorsedaccumsanbibendum, erat ligula aliquet magna, vitae ornareodiometus a mi.
Morbi ac orcietnislhendreritmollis. Suspendisseutmassa. Crasnec ante. Pellentesque a
nulla. Cum sociisnatoquepenatibusetmagnis dis parturient montes, nasceturridiculus
mus. Aliquamtincidunturna. Cum sociisnatoqueurna. Is parturient montes,
nasceturridiculus mus. Aliquamtincidunturna.Nullaullamcorpervestibulumturpis.
Pellentesquecursusluctusmauris.
Key words: protocol, Arduino, code, programming
Índice general
Introducción............................................................................................1
Objetivos generales................................................................................................... 2

1 Antecedentes Generales y Propuesta..................................................3

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

Discusión y conclusiones......................................................................10

Bibliografía............................................................................................11

A Un apéndice.......................................................................................13
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”
[CITATION Esc13 \l 13322 ]. 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
Introducción

2
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

3
1Antecedentes Generales y Propuesta

consigue llevarse la victoria. Estos puntos se consiguen cuando el jugador adversario


falla intentando devolver la pelota.

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

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

5
Solución

 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.
 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.
 Intxball: posición actual de la pelota en el eje x.
 Intyball: posición actual de la pelota en el eje y.
 Intyball_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.printno son necesarios para el algoritmo de trabajo,


pero son necesarios para verificar el buen funcionamiento del código.[ CITATION
ARD17 \l 13322 ]

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 }

6
Solución

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 }

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 return0;
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.

7
Solución

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 case0:
145 direction =4;
146 break;
147 case1:
148 direction =(bounce == BOUNCE_VERTICAL)?7:3;
149 break;
150 case2:
151 direction =6;
152 break;
153 case6:
154 direction =2;
155 break;
156 case7:
157 direction =(bounce == BOUNCE_VERTICAL)?1:5;
158 break;
159 case5:
160 direction =(bounce == BOUNCE_VERTICAL)?3:7;
161 break;
162 case3:
163 direction =(bounce == BOUNCE_VERTICAL)?5:1;
164 break;
165 case4:
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 }elseif(direction ==1){
178 direction =0;
179 }
180 break;
181 case HIT_RIGHT:
182 if(direction ==0){
183 direction =1;
184 }elseif(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;

8
Solución

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 }elseif(direction !=6&& direction !=2){
231 yball--;
232 }
233 if(0< direction && direction <4){
234 xball++;
235 }elseif(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);

9
Solución

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


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 }

10
Solución

11
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
esquemade conexión para la implementación del proyecto, como se muestra en la
Figura 1.[ CITATION sch16 \l 13322 ]

Figura 1 Esquema de Conexión

12
Solución

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

 ARDUINO UNO.
 Matriz LED 8x8.
 C.I. MAX7219.
 Potenciómetro de 10[kΩ].
 PiezoBuzzer.
 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 PiezoBuzzer, puesto que no hace nada, pero
puede ocuparse para añadir algunos sonidos queinmerjan 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

13
4 Resultados

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

Parael 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 cincopáginas.

15
Solución

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

16
Solución

A Código de Juego Pong en


ARDUINO[ CITATION Pas12 \l
13322 ]
Listado - Código Completo Juego Pong en ARDUINOA

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[]={

17
Solución

40 B00000000,
41 B01000100,
42 B00010000,
43 B00010000,
44 B00000000,
45 B00111000,
46 B01000100,
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(constchar* desc){
101 #ifdef DEBUG
102 Serial.print(desc);
103 Serial.print(" XY: ");
104 Serial.print(xball);

18
Solución

105 Serial.print(", ");


106 Serial.print(yball);
107 Serial.print(" XPAD: ");
108 Serial.print(xpad);
109 Serial.print(" DIR: ");
110 Serial.println(direction);
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 return0;
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 case0:
145 direction =4;
146 break;
147 case1:
148 direction =(bounce == BOUNCE_VERTICAL)?7:3;
149 break;
150 case2:
151 direction =6;
152 break;
153 case6:
154 direction =2;
155 break;
156 case7:
157 direction =(bounce == BOUNCE_VERTICAL)?1:5;
158 break;
159 case5:
160 direction =(bounce == BOUNCE_VERTICAL)?3:7;
161 break;
162 case3:
163 direction =(bounce == BOUNCE_VERTICAL)?5:1;
164 break;
165 case4:
166 direction =0;
167 break;
168 }
169 debug("->");

19
Solución

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 }elseif(direction ==1){
178 direction =0;
179 }
180 break;
181 case HIT_RIGHT:
182 if(direction ==0){
183 direction =1;
184 }elseif(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 }elseif(direction !=6&& direction !=2){
231 yball--;
232 }
233 if(0< direction && direction <4){
234 xball++;

20
Solución

235 }elseif(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 }
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 }

21

También podría gustarte