Páginas

martes, 22 de mayo de 2012

[Emb Comp Class] ARDUINO: Proyecto Final

Control de la Instalación Eléctrica y Medidor del Consumo Eléctrico

Material


General
  • Arduino UNO con su cable USB
  • Protoboard
  • Cables Jumper para las conexiones
  • Cable de cobre delgado para realizar las conexiones en la protoboard

Para el control de la instalación eléctrica
  • 5 Resistencias 330 Ohms
  • 4 push buttons
  • 2 leds blancos de alta luminosidad
  • 2 Relevadores compatibles con Arduino [instrucciones de armado: AQUI]
  • Contacto Duplex con tierra física, cubierta y caja protectora
  • Extensión eléctrica o cable de cobre
  • Lamparita de noche o cualquier otro dispositivo electrico para probar.

Para el sistema de medición (REFERENCIA How to build an Arduino Energy Monitor)
  • Arduino Ethernet Shield
  • Para la medición del voltaje
    • Transformador de corriente alterna 120V - 9V (o un adaptador de corriente AC-AC con salida de 9V)
    • 1 resistencia de 100 KOhms
    • 2 resistencias de 10 KOhms
    • 1 capacitor de 10 uF
  • Para la medición de la corriente
    • Sensor CT SCT-013-000
    • Burden Resistor (resistencia de 33 Ohms)
    • 2 resistencias de 10 KOhms
    • 1 capacitor de 10 uF
    • 1 jack 3.5mm hembra

Advertencias y consideraciones previas

  • Se trabajara con corriente alterna, se recomienda utilizar no conectar ningun componente a la misma hasta terminar el armado
  • Es importante tener un multimetro a la mano, nos ayudara a realizar correctamente nuestras conexiones y verificar que funcionen correctamente antes de conectarlas a la corriente alterna.

Armado para la el control de la instalación eléctrica


Vamos primero con lo mas simple, armemos el contacto duplex de tal forma que simulemos la instalación eléctrica de la casa, es algo complejo explicarlo, pero es algo básico y super fácil que todos podemos hacer, así que mejor les dejo un esquema:

Y estas son las fotos de como yo arme mi contacto duplex



Por si no recuerdan como conectar correctamente los relevadores, aqui les dejo las entradas y salidas correspondientes.

Para las entradas del relevador (son 3 inputs)


  • Arduino 5V: Es la salida regulada (5V) que nos proporciona nuestro Arduino
  • Arduino Digital Out: Esta conectada al pin desde el cual enviaremos la señal
  • Arduino GND: Es la tierra (GND) que proporciona nuestro Arduino


Para las entradas del relevador de corriente alterna:



  • AC/DC Input: Es el cable ya sea de corriente alterna o directa de donde entra el voltaje
  • Sin usar: Por seguridad para cuando usemos corriente alterna, se deja sin usar para separar la corriente y evitar un arco y provocar algun corto circuito
  • AC/DC Output: Es el cable por el que continuara circulando la corriente una vez que el relevador cierre el circuito

Después hay que conectar nuestros relevadores al arduino, para ello prepare el siguiente esquema en Fritzing:



Armado para la el control de la iluminación


Ahora continuamos con el control de la iluminación, para ello utilizaremos 2 entradas, una para aumentar la luminosidad de los leds y otra para bajarla; además de una salida regulada. Esquema en fritzing:



La idea es combinar ambos sistemas, para tener todo en uno solo, así se ven ambos sistemas conectados:


Armado para la el sistema de medición


Primero preparamos las conexiones en nuestro protoboard siguiendo el esquema que les adjunto:

Tomado de OpenEnergyMonitor URL=http://openenergymonitor.org/emon/buildingblocks/how-to-build-an-arduino-energy-monitor


Tomado de OpenEnergyMonitor URL=http://openenergymonitor.org/emon/buildingblocks/measuring-voltage-with-an-acac-power-adapter


Conectaremos la entrada de nuestro transformador a la corriente alterna y la salida (9V-300mA) a la protoboard,



Tomado de OpenEnergyMonitor URL=http://openenergymonitor.org/emon/buildingblocks/ct-sensors-interface


Para conectar el CT a la protoboard utilizaremos un jack 3.5mm hembra, conectaremos solamente el positivo (cabeza o tap) y la tierra (brazo o sleeve).



Con esto vamos a construir un monitor de energía electrica simple que se puede utilizar para medir la cantidad de energía eléctrica que utiliza en una casa. Se mide la tensión con el transformador 120V-9V y la corriente con el sensor CT.

El monitor de energía se puede calcular la potencia real, potencia aparente, factor de potencia, voltaje rms, corriente eficaz. Todos los cálculos se hacen en el Arduino.

Los datos son enviados al servidor por medio de un shield Arduino Ethernet y son recogidos para su posterior procesamiento.

OpenEnergyMonitor es el proyecto en el que base, valga la redundancia, mi proyecto. OpenEnergyMonitor se compone de diversos módulos, en este caso el hardware EmonTX, para el Arduino la librería que realiza los cálculos EmonLib, y un servidor que se encarga de graficar los datos de salida del Arduino EmonCMS

Toda la teoría la podemos encontrar en esta página: http://openenergymonitor.org/emon/buildingblocks.
En ella se explican de forma bastante detallada los conceptos necesarios para comprender el funcionamiento del monitor de energía.

Este es todo el circuito, los 3 modulos montados en la protoboard



Código

#include "EmonLib.h"
#include <SPI.h>
#include <Ethernet.h>
byte mac[] = { MYMAC };
byte myIP[] = { 192, 168, 0, 2 };
byte gateway[] = { 192, 168, 0, 1 };
byte subnet[] = { 255, 255, 255, 0 };
byte serverIP[] = { 192, 168, 0, 1 };
String serverIPS = "192.168.0.1";
EthernetClient client;
long lastConnectionTime = 0;
boolean lastConnected = false;
const int postingInterval = 1000;
EnergyMonitor emon1;
String emoncmsApikey = MYAPIKEY;
int leds = 9;
int buttonUp = 2;
int buttonDown = 3;
int buttonUpEstado = 0;
int buttonDownEstado = 0;
int intensidad = 0;
int intensidadMax = 100;
int relays[] = {7, 8};
int mainRelayButton = 5;
int relayButton = 6;
int mainRelayVal = 0;
int relayVal = 0;
int mainRelayEstado = 0;
int relayEstado = 0;
int relaySignal = HIGH;
void aumentaIntensidad() {
if(intensidad < intensidadMax) {
intensidad += 10;
analogWrite(leds, intensidad);
}
}
void bajaIntensidad() {
if(intensidad > 0) {
intensidad -= 10;
analogWrite(leds, intensidad);
}
}
void checkLED() {
buttonUpEstado = digitalRead(buttonUp);
buttonDownEstado = digitalRead(buttonDown);
if ((buttonUpEstado == HIGH) && (buttonDownEstado == HIGH)) {
Serial.print('No valido! \n\n');
}
else {
if(buttonUpEstado == HIGH) {
aumentaIntensidad();
delay(100);
}
else if(buttonDownEstado == HIGH) {
bajaIntensidad();
delay(100);
}
}
}
void mainRelayControl() {
if(mainRelayEstado == 0) {
mainRelayEstado = relaySignal;
}
else {
mainRelayEstado = 0;
}
digitalWrite(relays[0], mainRelayEstado);
}
void relayControl() {
if(relayEstado == 0) {
relayEstado = relaySignal;
}
else {
relayEstado = 0;
}
digitalWrite(relays[1], relayEstado);
}
void checkRelay() {
mainRelayVal = digitalRead(mainRelayButton);
relayVal = digitalRead(relayButton);
if ((mainRelayVal == HIGH) && (relayVal == HIGH)) {
Serial.print('No valido! \n\n');
}
else {
if(mainRelayVal == HIGH) {
mainRelayControl();
delay(200);
}
else if(relayVal == HIGH) {
relayControl();
delay(200);
}
}
}
void calcCurrent() {
double Irms = emon1.calcIrms(2000);
Serial.print(Irms*120.0);
Serial.print(" ");
Serial.println(Irms);
}
String energyMonitor() {
String data = NULL;
static char charBuf[15];
emon1.calcVI(20,2000);
//emon1.serialprint();
data = "RealPower:";
data += dtostrf(emon1.realPower, 0, 2, charBuf);
data += ",ApparentPower:";
data += dtostrf(emon1.apparentPower, 0, 2, charBuf);
data += ",Vrms:";
data += dtostrf(emon1.Vrms, 0, 2, charBuf);
data += ",Irms:";
data += dtostrf(emon1.Irms, 0, 2, charBuf);
data += ",PowerFactor:";
data += dtostrf(emon1.powerFactor, 0, 2, charBuf);
Serial.print(data);
Serial.println();
return data;
}
void webClient() {
if (client.available()) {
char c = client.read();
Serial.print(c);
}
if (!client.connected() && lastConnected) {
Serial.println();
Serial.println(">> Desconectando...");
client.stop();
}
if(!client.connected() && (millis() - lastConnectionTime > postingInterval)) {
if (client.connect(serverIP, 80)) {
String data = energyMonitor();
Serial.println(">> Conectando...");
String request = "GET /emoncms3/api/post.json?apikey=";
request += emoncmsApikey;
request += "&json={";
request += data;
request += "} HTTP/1.0";
Serial.println(">> Enviando datos...");
Serial.println(request);
client.println(request);
client.println();
request = "Host: ";
request += serverIPS;
Serial.println(request);
client.println(request);
client.println();
lastConnectionTime = millis();
}
else {
Serial.println("[X] Fallo la conexion");
}
}
lastConnected = client.connected();
}
void setup() {
Serial.begin(9600);
Ethernet.begin(mac, myIP, gateway, subnet);
Serial.print("[!] IP > ");
Serial.println(Ethernet.localIP());
delay(1000);
pinMode(leds, OUTPUT);
pinMode(buttonUp, INPUT);
pinMode(buttonDown, INPUT);
pinMode(relays[0], OUTPUT);
pinMode(relays[1], OUTPUT);
pinMode(mainRelayButton, INPUT);
pinMode(relayButton, INPUT);
analogWrite(leds, intensidad);
emon1.voltage(2, 110.0, 1.7);
emon1.current(1, 111.1);
}
void loop(){
checkLED();
checkRelay();
webClient();
}

Video





Referencias

martes, 8 de mayo de 2012

[MDE Lab] ANDROID: Tabs

Para una primera parte del proyecto decidí hacer una barra de Tabs para elegir entre los 2 posibles módulos que el usuario tiene al momento de ejecutar mi aplicación, entonces, después de mucho intentar ahora les mostraré como realizar esta tarea.

1. Creamos un proyecto en Eclipse


Abrimos Eclipse y creamos un nuevo proyecto Android:


Despues introducimos el nombre de nuestro proyecto y damos siguiente, este se llamara TabTuto, damos click en next.


A continuacion elegimos la API de Android con la cual trabajaremos, en mi caso elijo la API 2.3.3 que es compatible con mi celular, damos clic en next.


Por ultimo agregamos la informacion de nuestra aplicacion


2. Creamos las Tabs


Cada tab necesita su clase independiente, entonces necesitamos crear archivos .java diferentes para cada tab y necesitamos crear tantos archivos como tabs queremos tener.
Entonces, para crear las tabs, tenemos que crear nuevas clases:


Y le ponemos un nombre, en este caso las pondré numeradas, es decir Tab1, Tab2, ..., TabN


Y este es el código que debemos colocar a cada clase que hemos creado para cada Tab, cuidando por supuesto cambiar el nombre para las clases de las Tabs. Cada tab es una actividad, es decir, una ventanita individual en el teléfono. Como es una prueba lo único que agregaremos a la ventana sera un TextView.

package com.jceceniceros.tabTuto;
import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
public class Tab1 extends Activity{
@Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
TextView textview = new TextView(this);
textview.setText("TAB 1 :)");
setContentView(textview);
}
}
view raw tab.java hosted with ❤ by GitHub


Lo siguiente es agregar las actividades de cada Tab al archivo AndroidManifest.xml, como son 3 Tabs entonces agregamos 3 actividades.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.jceceniceros.tabTuto"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk android:minSdkVersion="10" />
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name" >
<activity
android:name=".TabTutoActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".Tab1"
android:label="@string/app_name">
</activity>
<activity
android:name=".Tab2"
android:label="@string/app_name">
</activity>
<activity
android:name=".Tab3"
android:label="@string/app_name">
</activity>
</application>
</manifest>


3. Creamos el contenedor de las Tabs


En el archivo principal del código, vamos a teclear el siguiente código, con el agregaremos las Tabs al contenedor de la ventana principal.

package com.jceceniceros.tabTuto;
import android.app.TabActivity;
import android.content.Intent;
import android.content.res.Resources;
import android.os.Bundle;
import android.widget.TabHost;
public class TabTutoActivity extends TabActivity{
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Resources res = getResources();
TabHost tabHost = getTabHost();
TabHost.TabSpec spec;
Intent intent;
//Agregamos cada Tab, lo mismo para cada una.
intent = new Intent().setClass(this, Tab1.class);
spec = tabHost.newTabSpec("tab1").setIndicator("Tab1",
res.getDrawable(R.drawable.home)).setContent(intent);
tabHost.addTab(spec);
intent = new Intent().setClass(this, Tab2.class);
spec = tabHost.newTabSpec("tab2").setIndicator("Tab2",
res.getDrawable(R.drawable.chart)).setContent(intent);
tabHost.addTab(spec);
intent = new Intent().setClass(this, Tab1.class);
spec = tabHost.newTabSpec("tab3").setIndicator("Tab3",
res.getDrawable(R.drawable.ic_launcher)).setContent(intent);
tabHost.addTab(spec);
tabHost.setCurrentTab(1);
}
}


Y por ultimo, pero no menos importante, debemos configurar el main.xml para que se muestren las tabs correctamente en nuestra ventana principal. Convertimos la ventana en un TabHost y le agregamos un LinearLayout vertical para acomodar nuestras tabs con el mismo tamaño y hacia la derecha. Agregamos el Widget de las tabs y cada tab contiene un FrameLayout para mostrar su contenido.

<?xml version="1.0" encoding="utf-8"?>
<TabHost xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@android:id/tabhost"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="5dp">
<TabWidget
android:id="@android:id/tabs"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<FrameLayout
android:id="@android:id/tabcontent"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="5dp" />
</LinearLayout>
</TabHost>
view raw main.xml hosted with ❤ by GitHub


4. Prueba

Solo nos queda probar nuestro codigo, en las barras de herramientas damos clic en el boton Run As... y en la ventana emergente seleccionamos la opcion Android Application, con ello se abrira nuestro emulador de Android.



Y este debe ser nuestro resultado final.



Espero les haya servido el minitutorial, saludos :)

Referencias

Android Developer: TabWidget

[Emb Comb Lab] ARDUINO: Trabajando con relevadores

Material

  • Relevador RAS-0510
  • Diodo 1N4007
  • Transistor 2N2222A
  • Resistencia 10KOhms
  • Terminales para circuito con 3 entradas
  • Placa fenólica pequeña para realizar las conexiones (opcional)
  • Cable de cobre calibre 14 (opcional)

Advertencias y consideraciones previas

  • El relevador que vamos a utilizar es capaz de trabajar con corrientes y voltajes altos, es muy util para controlar la instalación eléctrica, que es lo que queremos hacer. También puede trabajar con corrientes directas, útil para controlar circuitos en proyectos pequeños
  • El cable de cobre es opcional también, yo lo usaré porque trabajare con corriente alterna.
  • La placa fenólica es opcional, pueden hacer su propia placa impresa.
  • Se puede utilizar una protoboard en caso de querer utilizar el relevador para corriente directa.
  • No es recomendable utilizar una protoboard si se quiere utilizar el relevador para corrientes alternas.


Armado

Para armar el relevador, vamos a seguir el siguiente esquemático:



El relevador tiene 5 patitas, con el podemos controlar 2 estados diferentes para un circuito en lugar de solo prenderlo y apagarlo. Podemos medir la continuidad de las patitas utilizando un multímetro.



La posición natural del relevador es tener el circuito cerrado conectando la patita 4 y 3, es decir, que si giramos el relevador con las patitas arriba y después ubicamos 3 de las patitas en la parte inferior y 2 en la superior podremos ver que la patita 3 corresponde a la que queda en la parte superior derecha.

Esta sera nuestra posición de apagado.

La posición de encendido sera cuando el circuito este cerrado con las patitas 4 y 5, que si giramos el relevador igual que antes la patita 5 sera la que se encuentra en la parte superior izquierda.

Esta posición sera para cerrar el circuito que queremos controlar.

Las terminales para circuito son opcionales, a mi se me hace una forma bastante cómoda para cablear, en mi caso, las terminales las conecte asi:

Para las entradas del relevador (3)


  • Arduino 5V: Es la salida regulada (5V) que nos proporciona nuestro Arduino
  • Arduino Digital Out: Esta conectada al pin desde el cual enviaremos la señal
  • Arduino GND: Es la tierra (GND) que proporciona nuestro Arduino


Para las salidas del relevador (2)



  • AC/DC Input: Es el cable ya sea de corriente alterna o directa de donde entra el voltaje
  • Sin usar: Por seguridad para cuando usemos corriente alterna, se deja sin usar para separar la corriente y evitar un arco y provocar algun corto circuito
  • AC/DC Output: Es el cable por el que continuara circulando la corriente una vez que el relevador cierre el circuito


Este es el circuito ya armado.



Pruebas con Arduino


Para las pruebas hice un sketch bastante simple que solo envía una señal desde el PIN 13, cierra el circuito del relay, espera 3 segundos, abre el circuito, espera 3 segundos.
int myPin = 13; // Declaramos la salida del led
//al pin 13
void setup() {
pinMode(myPin, OUTPUT); // Declaramos que el pin sera salida
}
void loop() { // Inicio del ciclo del codigo
digitalWrite(myPin, HIGH); // Que se cierre el circuito
delay(2000); // Esperamos 3 segundos
digitalWrite(myPin, LOW); // Que se abra el circuito
delay(2000); // Esperamos 3 segundos
}
view raw relay.cpp hosted with ❤ by GitHub

Video





Espero que les haya sido util la entrada, el Relay Shield compatible con Arduino de Sparkfun cuesta aproximadamente $8 USD + envió, nuestro Relay también es 100% compatible y la inversión fue de aproximadamente $50 pesos MXN, la mitad :)

Referencias

jueves, 3 de mayo de 2012

[Emb Comb Lab] Juego con Stars Wars The Force Trainer

Para la competencia del iPad tuvimos que desarrollar un juego utilizando este dispositivo. Para ello habia que hackear el MindReader y despues interfacear el mismo al Arduino.

Este es el tutorial hecho por el compañero Saul para lograr dicho objetivo:

LINK: Como hacer un hack a un dispositivo EEG con Arduino

Preparación


Primero que nada hay que instalar la IDE de Arduino, aqui un minitutorial hecho por mi

LINK: Programando con Arduino

Después hay que instalar la librería Brain, los pasos son sencillos:
  • 1. Descargar la libreria de aquí: Arduino Brain Library
  • 2. Descomprimimos y la agregamos a la carpeta libraries en la carpeta de Arduino, en mi caso el path es:


    Y ya dentro:


Esto nos permitirá exportar la libreria y utilizar el ejemplo BrainSerialOut que viene en la IDE de Arduino, lo encontramos así:


Así se ve el sketch, si se fijan en la función loop comente la línea Serial.println(brain.readErrors()); , esto es para que no nos regrese ninguna otra información que no sean los datos que nos interesan del MindReader.


Ahora simplemente lo compilamos y lo subimos a nuestro Arduino conectado al MindReader, con el botón UPLOAD

Yo usé Python para el juego, entonces, para escuchar los datos enviados por Arduino debemos instalar pySerial, los pasos son ultra sencillos:

El juego


El juego lo llame Magic Warriors!.


El objetivo del juego es sencillo, se trata de algo parecido a hacer Genkidamas. Según tu nivel de concentración es la cantidad de energía que se agrega a la Genkidama, asi pues, de todos los datos que me da el MindReader solo me quedo con dos que son atención y meditación; dichos valores se suman y se saca un promedio, el promedio es la energía que se agrega cada segundo a la Genkidama. Básicamente son sumas, del valor anterior mas el nuevo valor durante un tiempo determinado que son 5 segundos.

Por el lado de la CPU, es una simple sumatoria que se realiza mediante números random, que, según la dificultad, son obtenidos dentro de determinado rango. Entre mayor es el nivel el rango es más ajustad y se mueve hacia valores más altos.

El ganador se selecciona comparando quién acumulo la mayor cantidad de energía, una comparación entre tu sumatoria final y la del CPU.


Código relevante



El juego fue desarrollado utilizando pygame, la temática es simple, y como ven el cálculo que realiza es super sencillo, entonces, veamos algunas partes relevantes del código desarrollado.

Escuchando al Arduino

class ArduinoEEG:
#===========================================================
# El constructor de la clase, toma el puerto donde esta
# conectado el Arduino.
# USB es el puerto serial, es dinamico, por alguna razón
# cambia, hay que estarlo verificando en laa IDE de
# Arduino.
# CONNECTION almacena el estado de la conexion.
# EEG_VALUE es un diccionario que almacenara los datos
# enviados por Arduino.
#===========================================================
def __init__(self, port):
self.port = port
self.usb = '/dev/ttyACM0'
self.connection = ''
self.eeg_value = dict()
#================ def connect(self) ========================
# Este metodo comienza la conexion al Arduino.
# El intento de conexion esta dentro de un bloque try... except
# para mostrar el mensaje correspondiente.
# 'Ready' en caso de exito, 'Error' en caso de fracasar.
# Ademas, regresa un 0 en caso de exito y un 1 en caso de fracasar
#===========================================================
def connect(self):
print '>> Attempting to connect to Arduino EEG'
try:
self.connection = serial.Serial(self.usb, self.port)
print '>> ARDUINO EEG CONNECTION => Ready'
return 0
#self.connection.baudrate = 19200
except:
print '>> ARDUINO EEG CONNECTION => Error'
return 1
#================== def read(self) =========================
# Este metodo lee la cadena de datos enviada desde Arduino.
# Se crea una cadena vacia 'temp'
# Si hay conexion, leemos el dato y lo separamos (recordemos
# que es una cadena con formato CSV)
# A veces no recibimos una cadena completa, mientras su
# longitud sea muy pequeña, seguimos leyendo hasta obtener
# una completa.
# Imprimimos temo, que en este punto debido a la funcion
# 'split' ya es una lista de elementos. Regresamos la lista.
#===========================================================
def read(self):
print '>> Reading values from Arduino EEG...'
temp = ''
if(self.connection != ''):
temp = self.connection.readline()
temp = temp.split(',')
while(len(temp) < 10):
temp = self.connection.readline()
temp = temp.split(',')
print temp
return temp
else:
return 0
#=================== def get(self) =========================
# Este metodo obtiene los datos de la cadena de datos leida
# desde Arduino.
# Los valores sera una lista de elementos, retornada por el
# metodo 'read()'.
# Creamos 2 elementos en el diccionario self.eeg_value
# correspondientes a la atencion y meditacion, que son los
# primeros 2 elementos de la lista, los demas no nos importan
# para efectos del juego.
# que es una cadena con formato CSV)
# Imprimimos el diccionario para verificar y regresamos
# ambos valores.
#===========================================================
def get(self):
print '>> Getting values from Arduino EEG'
values = self.read()
self.eeg_value['attention'] = int(values[1])
self.eeg_value['meditation'] = int(values[2])
print self.eeg_value
return [self.eeg_value['meditation'], self.eeg_value['meditation']]
#================ def randValues(self) =====================
# Este metodo es usado para efectos de testing, emula el
# metodo de leer-obtener valores de Arduino.
# Se crea una lista de elementos temporal.
# Creamos 2 elementos en el diccionario self.eeg_value
# Generamos los 10 valores que comunmente el Arduino nos
# retornaria y los agregamos a la lista.
# Creamos 2 elementos en el diccionario self.eeg_value
# correspondientes a la atencion y meditacion, que son los
# primeros 2 elementos de la lista.
# Imprimimos el diccionario para verificar y regresamos
# ambos valores.
#===========================================================
def randValues(self):
print '>> Generating Random Values...'
temp = list()
for i in range(10):
temp.append(random.randint(0,100))
self.eeg_value['attention'] = temp[1]
self.eeg_value['meditation'] = temp[2]
print self.eeg_value
return [temp[2], temp[1]]
view raw arduinoClass.py hosted with ❤ by GitHub


Jugador y Enemigo

class Player:
#==================================================
# El constructor.
# Recibe el objeto Arduino, el cual ya debio haber
# sido construido y debe tener una conexion
# establecida.
# MAGIC es el nivel de magia inicial, es cero.
#==================================================
def __init__(self, arduino):
print '>> Creating new Player'
self.magic = 0
self.arduino = arduino
#============= def recharge(self) =================
# Funcion que recarga la energia del jugador.
# Con la funcion 'get' del objeto Arduino obtenemos
# los datos.
# La magia es igual a la sumatoria de la magia
# anterior mas el promedio de los valores obtenidos
# desde el Arduino [ (atencion+meditacion)/2 ]
# Imprimimos la magia como informacion.
#==================================================
def recharge(self):
print 'Player is recharging magic'
magicUp = self.arduino.get()
self.magic = self.magic + (sum(magicUp)/2)
print 'Player\' magic => ' + str(self.magic)
#=========== def randRecharge(self) ===============
# Funcion que recarga la energia del jugador con
# valores random.
# Generamos un numero random.
# La magia es igual a la sumatoria de la magia
# anterior mas el valor random
# Imprimimos la magia como informacion.
#==================================================
def randRecharge(self):
print 'Player is recharging power'
magicUp = random.randint(0, 100)
self.magic = self.magic + magicUp
print 'Player\' magic => ' + str(self.magic)
class Enemy:
#==================================================
# El constructor.
# Recibe el nivel del CPU
# MAGIC es el nivel de magia inicial, es cero.
# Se definen los limites dentro de los cuales seran
# calculados los valores de magia.
#==================================================
def __init__(self, level):
print '>> Creating new Enemy'
self.magic = 0
self.level = level
defineLimits(self)
#============= def defineLimits(self) =============
# Define los limites dentro de los cuales seran
# calculados los valores de magia.
#==================================================
def defineLimits(self):
if(self.level == 1):
self.limitA = 10
self.limitB = 60
if(self.level == 2):
self.limitA = 20
self.limitB = 70
if(self.level == 3):
self.limitA = 30
self.limitB = 80
if(self.level == 4):
self.limitA = 40
self.limitB = 90
if(self.level == 5):
self.limitA = 50
self.limitB = 100
#============= def recharge(self) =================
# Funcion que recarga la energia del enemigo con
# valores random.
# Generamos un numero random dentro de los limites
# establecidos.
# La magia es igual a la sumatoria de la magia
# anterior mas el valor random
# Imprimimos la magia como informacion.
#==================================================
def recharge(self):
print 'Enemy is recharging magic'
magicUp = random.randint(self.limitA, self.limitB)
self.magic = self.magic + magicUp
print 'Enemy\' magic => ' + str(self.magic)
view raw player_enemy.py hosted with ❤ by GitHub


La Batalla!!

class Battle:
#=============================================
# El constructor
#=============================================
def __init__(self):
pass
#=========== def build(self, level) ===========
# Recibe el nivel del enemigo.
# Prepara un objeto Arduino.
# Verifica si hay conexion.
# Establece un nivel de batalla.
# Si hay conexion, entonces creamos al jugador
# y al enemigo.
# Si no hay conexion, regresamos un cero para
# avisar.
#=============================================
def build(self, level):
arduino = ArduinoEEG(9600)
isConnected = arduino.connect()
self.level = level
if(isConnected == 0):
self.player = Player(arduino)
self.enemy = Enemy(self.level)
else:
self.level = 0
#============= def start(self) ==============
# Solo imprime mensajes de aviso y la magia
# inicial de los participantes.
# La batalla comienza al presionar la tecla
# 'F'.
#============================================
def start(self):
print '>> Starting battle...'
print '\nLEVEL => ' + str(self.level)
print 'Focus your magic ...'
print 'And press F when you are focused'
print '\nPlayer Magic = ' + str(self.player.magic)
print 'Enemy Magic = ' + str(self.enemy.magic)
#============= def fight(self) ==============
# Se encarga de llamar a los metodos de
# de recarga de energia de cada uno de los
# participantes, durante 5 segundos.
# Compara para seleccionar el ganador.
#============================================
def fight(self):
for i in range(10):
self.player.recharge()
#self.player.randRecharge()
self.enemy.recharge()
time.sleep(0.5)
winner = self.compare()
#============ def compare(self) =============
# Compara la magia final de los participantes
# para seleccionar el ganador.
# Imprime el ganador en pantalla.
#============================================
def compare(self):
if(self.player.magic >= self.enemy.magic):
print 'Player wins :)'
return 1
else:
print 'Player loses :('
return 0
view raw battle.py hosted with ❤ by GitHub


Lo demas ya son funciones propias de python para interconectar clases, enviar variables y bueno, los métodos obligados de PyGame para la asignación de teclas y demás. Por ultimo, les dejo las librerías que utilice por si a alguien le interesa.

import time, csv, sys, random, threading
import serial
import pygame
from pygame.locals import *
view raw libraries.py hosted with ❤ by GitHub


Espero que les guste, lo que falta es obviamente lo gráfico en en 6 horas fue imposible de terminar, adicional quise agregar algo de interactividad con OpenCV, NADA DE TECLAS!!, quería hacer que el juego se controlara con movimientos en la webcam, hacer un movimiento con el brazo para avanzar entre pantallas y levantar los brazos como si realmente estuvieras haciendo la Genkidama para recargar energía, pero bueno, eso era mas complejo, y ademas quería imprimir los valores del EEG en todo momento pero igual, por falta de tiempo no pude instalar las dependencias y demás.

Sin embargo, me divertí mucho haciéndolo y deseo terminarlo un día de estos, comprar mi EEG y todo el rollo porque realmente estuvo genial.

Bueno, esa fue mi idea en la competencia, espero les haya gustado :)