segunda-feira, 30 de junho de 2014

Game "genius" na placa Intel® Galileo

Este post apresenta o roteiro para fazer o jogo de memória conhecido como "Genius" utilizando a placa de desenvolvimento Galileo da Intel®.

Materiais Necessários:


  • 1x Placa de desenvolvimento Intel® Galileo
  • 1x Protoboard
  • 4x Resistores de 10kohm
  • 4x Resistores de 220ohm
  • 4x Leds (cores diferentes)
  • 4x Botões
  • Fios
Este projeto foi adaptado deste site para não tocar o som durante o jogo.


Alguns componentes utilizados

Faça a montagem do circuito seguindo a imagem abaixo ainda com a placa sem alimentação e ainda não ligada ao computador.

Ligação da placa Galileo ao circuito de leds e botões

Uma observação especial que deve ser feita a respeito deste circuito é que é importante que cada botão possua um resistor de pull-up para garantir uma tensão bem definida sobre eles.

Com a ligação acima feita, ligue a placa Intel® Galileo na energia primeiro e em seguida ligue ao computador, verificando pela IDE que a placa foi identificada pelo computador.

#include <EEPROM.h>

/*Simon Says game. 
 
 Feito originalmente por Robert Spann

 */
int starttune[] = {
  262, 349, 262, 349, 262, 349, 262, 349, 392, 349, 330, 349, 392};
int duration2[] = {
  100, 200, 100, 200, 100, 400, 100, 100, 100, 100, 200, 100, 500};
int note[] = {
  262, 262, 392, 523, 392, 523};
int duration[] = {
  100, 100, 100, 300, 100, 300};
boolean button[] = {
  2, 3, 4, 5}; //Os 4 botoes de entrada
boolean ledpin[] = {
  8, 9, 10, 11};  // pinos LED 
int turn = 0;  // contador de turno
int buttonstate = 0;  // checa o estado do botao 
int randomArray[100]; //Armazena até 100 inputs
int inputArray[100]; 


void setup()
{   
  Serial.begin(9600);
  Serial.print("High Score: ");
  Serial.println(EEPROM.read(0));
  for(int x=0; x<4; x++)  // pinos LED sao outputs
  {
    pinMode(ledpin[x], OUTPUT);
  }

    
  for(int x=0; x<4; x++)
  {
    pinMode(button[x], INPUT);  // pinos de botao sao inputs
   }

  randomSeed(analogRead(0)); //Tentativa de melhorar a aleatoriedade
  startup();
  delay(1000);
}

void loop()
{  
  for (int y=0; y<=99; y++)
  {
    // Funcao que gera a sequencia a ser repetida plo jogador
    digitalWrite(ledpin[0], HIGH);
    digitalWrite(ledpin[1], HIGH);
    digitalWrite(ledpin[2], HIGH);
    digitalWrite(ledpin[3], HIGH);

    
    digitalWrite(ledpin[0], LOW);
    digitalWrite(ledpin[1], LOW);
    digitalWrite(ledpin[2], LOW);
    digitalWrite(ledpin[3], LOW);
    delay(1000);
    
    for (int y=turn; y <= turn; y++)
    { //Limitada pela variavel de turno
      randomArray[y] = random(1, 5); //Atribuindo um numero randomico (1-4) a randomArray[y], sendo y o contador de turno
      
      for (int x=0; x <= turn; x++)
      {
        
        for(int y=0; y<4; y++)
        {
            

          if (randomArray[x] == 1 && ledpin[y] == 8)
          {  //if statements to display the stored values in the array
            digitalWrite(ledpin[y], HIGH);
            
            delay(400);
            digitalWrite(ledpin[y], LOW);
            delay(100);
          }

          if (randomArray[x] == 2 && ledpin[y] == 9)
          {
            digitalWrite(ledpin[y], HIGH);
            
            delay(400);
            digitalWrite(ledpin[y], LOW);
            delay(100);
          }

          if (randomArray[x] == 3 && ledpin[y] == 10)
          {
            digitalWrite(ledpin[y], HIGH);
            
            delay(400);
            digitalWrite(ledpin[y], LOW);
            delay(100);
          }

          if (randomArray[x] == 4 && ledpin[y] == 11)
          {
            digitalWrite(ledpin[y], HIGH);
            
            delay(400);
            digitalWrite(ledpin[y], LOW);
            delay(100);
          }
        }
      }
    }
    input();
  }
}



void input() { 
  //Funcao de captura de input e comparacao com o array gerado

  for (int x=0; x <= turn;)
  { // Controlado pelo contador de turno

    for(int y=0; y<4; y++)
    {
      
      buttonstate = digitalRead(button[y]);

      if (buttonstate == LOW && button[y] == 2)
      { // checando botao apertado
        digitalWrite(ledpin[0], HIGH);
        
        
        delay(200);
        digitalWrite(ledpin[0], LOW);
        inputArray[x] = 1;
        delay(250);
        if (inputArray[x] != randomArray[x]) { //Checa o valor do input do jogador e compara
          fail();                              //com o valor da mesma posicao no vetor gerado.
        }                                      // a rotina fail e chamada se os valores nao forem iguais
        x++;
      }
      if (buttonstate == LOW && button[y] == 3)
      {
        digitalWrite(ledpin[1], HIGH);
        
        delay(200);
        digitalWrite(ledpin[1], LOW);
        inputArray[x] = 2;
        delay(250);
        if (inputArray[x] != randomArray[x]) {
          fail();
        }
        x++;
      }

      if (buttonstate == LOW && button[y] == 4)
      {
        digitalWrite(ledpin[2], HIGH);
        
        delay(200);
        digitalWrite(ledpin[2], LOW);
        inputArray[x] = 3;
        delay(250);
        if (inputArray[x] != randomArray[x]) {
          fail();
        }
        x++;
      }

      if (buttonstate == LOW && button[y] == 5)
      {
        digitalWrite(ledpin[3], HIGH);
        
        delay(200);
        digitalWrite(ledpin[3], LOW);
        inputArray[x] = 4;
        delay(250);
        if (inputArray[x] != randomArray[x])
        {
          fail();
        }
        x++;
      }
    }
  }
  delay(500);
  turn++; // Incrementa o contador de turno
}

void fail() { 
  // Funcao usada se o jogador errar a jogada
  

  for (int y=0; y<=2; y++)
  { //Luzes piscam quando o o jogador falha

    digitalWrite(ledpin[0], HIGH);
    digitalWrite(ledpin[1], HIGH);
    digitalWrite(ledpin[2], HIGH);
    digitalWrite(ledpin[3], HIGH);
    
    delay(200);
    digitalWrite(ledpin[0], LOW);
    digitalWrite(ledpin[1], LOW);
    digitalWrite(ledpin[2], LOW);
    digitalWrite(ledpin[3], LOW);
    
    delay(200);
  }
  delay(500);
  if(EEPROM.read(0) < (turn+1)){
    digitalWrite(ledpin[0], HIGH);
    digitalWrite(ledpin[1], HIGH);
    
    delay(200);
    digitalWrite(ledpin[2], HIGH);
    digitalWrite(ledpin[3], HIGH);
    digitalWrite(ledpin[0], LOW);
    digitalWrite(ledpin[1], LOW);
    
    delay(500);
    digitalWrite(ledpin[2], LOW);
    digitalWrite(ledpin[3], LOW);
    EEPROM.write(0,turn+1);
  }
  Serial.print("\nScore: ");
  Serial.println(turn+1);
  Serial.print("High Score: ");
  Serial.println(EEPROM.read(0));
  turn = -1; // Reseta o valor do turno para reiniciar o jogo sem precisar apertar o botao reset
  startup();
}

void startup(){
  for (int thisNote = 0; thisNote < 13; thisNote ++) {
    
    if (thisNote==0 || thisNote==2 || thisNote==4 || thisNote== 6)
    {
      digitalWrite(ledpin[0], HIGH);
    }
    if (thisNote==1 || thisNote==3 || thisNote==5 || thisNote== 7 || thisNote==9 || thisNote==11)
    {
      digitalWrite(ledpin[1], HIGH);
    }
    if (thisNote==8 || thisNote==12)
    {
      digitalWrite(ledpin[2], HIGH);
    } 
    if (thisNote==10)
    {  
      digitalWrite(ledpin[3], HIGH);
    }
    delay(duration2[thisNote]);
    
    digitalWrite(ledpin[0], LOW);
    digitalWrite(ledpin[1], LOW);
    digitalWrite(ledpin[2], LOW);
    digitalWrite(ledpin[3], LOW);
    delay(25);
  }
}

Observe que o código acima utiliza a memória EEPROM para armazenar as posições geradas randomicamente pela Galileo e, em cada turno elas são comparadas com a entrada do jogador.

Cole este código na IDE e faça o upload na placa Galileo e comece a jogar!




quinta-feira, 26 de junho de 2014

Código Morse na placa Intel® Galileo via porta serial

Este será um teste simples da porta serial da Galileo com o envio de caracteres que serão transformados em código morse e apresentados na placa Galileo pelo led.

O código abaixo foi baseado neste código fonte, com algumas modificações:
//Define the LED Pin
#define PIN_OUT        13
//Define unit length in ms
#define UNIT_LENGTH    250

String incomingWord = "";
int menu = 0;    
char message[25];

//Build a struct with the morse code mapping
static const struct {const char letter, *code;} MorseMap[] =
{
 { 'A', ".-" },
 { 'B', "-..." },
 { 'C', "-.-." },
 { 'D', "-.." },
 { 'E', "." },
 { 'F', "..-." },
 { 'G', "--." },
 { 'H', "...." },
 { 'I', ".." },
 { 'J', ".---" },
 { 'K', ".-.-" },
 { 'L', ".-.." },
 { 'M', "--" },
 { 'N', "-." },
 { 'O', "---" },
 { 'P', ".--." },
 { 'Q', "--.-" },
 { 'R', ".-." },
 { 'S', "..." },
 { 'T', "-" },
 { 'U', "..-" },
 { 'V', "...-" },
 { 'W', ".--" },
 { 'X', "-..-" },
 { 'Y', "-.--" },
 { 'Z', "--.." },
 { ' ', "     " }, //Gap between word, seven units 
  
 { '1', ".----" },
 { '2', "..---" },
 { '3', "...--" },
 { '4', "....-" },
 { '5', "....." },
 { '6', "-...." },
 { '7', "--..." },
 { '8', "---.." },
 { '9', "----." },
 { '0', "-----" },
  
 { '.', "·–·–·–" },
 { ',', "--..--" },
 { '?', "..--.." },
 { '!', "-.-.--" },
 { ':', "---..." },
 { ';', "-.-.-." },
 { '(', "-.--." },
 { ')', "-.--.-" },
 { '"', ".-..-." },
 { '@', ".--.-." },
 { '&', ".-..." },
};

void setup()
{
  pinMode( PIN_OUT, OUTPUT );
  digitalWrite( PIN_OUT, LOW );
  Serial.begin(9600);
    
}

void loop(){
  
  if (Serial.available() && menu == 0) {
    
    Serial.println("-- Decodificador de string para codigo Morse -- ");
    Serial.println("Pronto para enviar uma mensagem.");
    menu = 1;
  
  }
  
  if (Serial.available() && menu == 1) {
    incomingWord = Serial.readStringUntil('\n');
  
    
    Serial.println("Eu recebi: ");
    Serial.println(incomingWord);
    
    incomingWord.toCharArray(message,incomingWord.length());
  
    String morseWord = encode( message );
    
    for(int i=0; i<=morseWord.length(); i++){
      switch( morseWord[i] ){
        case '.': //dit
          digitalWrite( PIN_OUT, HIGH );
          delay( UNIT_LENGTH );
          digitalWrite( PIN_OUT, LOW );
          delay( UNIT_LENGTH );
            
          break;
   
        case '-': //dah
          digitalWrite( PIN_OUT, HIGH );
          delay( UNIT_LENGTH*3 );
          digitalWrite( PIN_OUT, LOW );
          delay( UNIT_LENGTH );
            
          break;
   
        case ' ': //gap
          delay( UNIT_LENGTH );
      }
    }
  }
}
String encode(const char *string)
{
  size_t i, j;
  String morseWord = "";
  
  for( i = 0; string[i]; ++i )
  {
    for( j = 0; j < sizeof MorseMap / sizeof *MorseMap; ++j )
    {
      if( toupper(string[i]) == MorseMap[j].letter )
      {
        morseWord += MorseMap[j].code;
        break;
      }
    }
    morseWord += " "; //Add tailing space to seperate the chars
  }
 
  return morseWord;  
}
 
String decode2(String morse)
{
  String msg = "";
  
  int lastPos = 0;
  int pos = morse.indexOf(' ');
  while( lastPos <= morse.lastIndexOf(' ') )
  {    
    for( int i = 0; i < sizeof MorseMap / sizeof *MorseMap; ++i )
    {
      if( morse.substring(lastPos, pos) == MorseMap[i].code )
      {
        msg += MorseMap[i].letter;
      }
    }
 
    lastPos = pos+1;
    pos = morse.indexOf(' ', lastPos);
    
    // Handle white-spaces between words (7 spaces)
    while( morse[lastPos] == ' ' && morse[pos+1] == ' ' )
    {
      pos ++;
    }
  }
 
  return msg;
}

O código acima fica em loop esperando até que uma mensagem seja enviada pela porta serial, quando esta mensagem é recebida o programa decodifica cada letra com seu respectivo significado em morse ( a funcção estática no inicio do programa possui todas as relações letra - sinal) em "ponto" e "traço".

Faça upload deste código para a placa Galileo e abra o terminal serial em Tools...Serial Monitor para enviar as mensagens via porta serial.

Acesso ao terminal serial
Terminal serial acima da IDE arduino
Faça os testes enviando uma palavra de cada vez e verifique o led da placa acender em código morse.