Leitor de Gabarito com Arduino

Espaço para os membros do fórum postarem seus projetos e compartilharem suas experiências.

Leitor de Gabarito com Arduino

Mensagempor marcos635 » Sex Dez 12, 2014 7:14 pm

Estou com a ideia de fazer um leitor de gabaritos com arduino mas estou na duvida de como fazer para reconhecer os pontos pretos no papel, alguém poderia me dar umas dicas de qual componente utilizar?
Imagem
marcos635
 
Mensagens: 2
Registrado em: Sex Dez 12, 2014 7:05 pm

Re: Leitor de Gabarito com Arduino

Mensagempor marcos635 » Sex Dez 12, 2014 7:21 pm

Pelo que andei pesquisando poderia usar o Sensor Optico Reflexivo Tcrt5000.
tcrt5000-1-detail.jpg
tcrt
tcrt5000-1-detail.jpg (10.17 KiB) Exibido 1319 vezes


Como também poderia usar o Sensor Fotoresistor LDR.
LDR-light-dependent-resistor.jpg
ldr
LDR-light-dependent-resistor.jpg (15.92 KiB) Exibido 1319 vezes
marcos635
 
Mensagens: 2
Registrado em: Sex Dez 12, 2014 7:05 pm

Re: Leitor de Gabarito com Arduino

Mensagempor renato.aloi » Sex Dez 12, 2014 9:24 pm

Boa noite! Estou desenvolvendo o código.

Vou publicar aqui o esboço:

Código: Selecionar todos

#define NEURONIOS_HIDDEN   2
#define NEURONIOS_ENTRADA  5
#define NEURONIOS_SAIDA    3

float pesosSaida[NEURONIOS_SAIDA][NEURONIOS_HIDDEN];
float pesosEntrada[NEURONIOS_HIDDEN][NEURONIOS_ENTRADA];
float biasHidden[NEURONIOS_HIDDEN];
float biasSaida[NEURONIOS_SAIDA];

float entradas[NEURONIOS_ENTRADA];

unsigned long contaTreinamento = 0;
boolean fimTreinamento = true;

void setup()
{
  Serial.begin(9600);
  delay(100);
 
  Serial.println("Serial OK!");
 
  // Carregando bias e pesos iniciais
  for (unsigned i = 0; i < NEURONIOS_HIDDEN; i++)
  {
    for (unsigned j = 0; j < NEURONIOS_SAIDA; j++)
    {
      pesosSaida[j][i] = rand() % 2 + .5;
    }
    for (unsigned j = 0; j < NEURONIOS_ENTRADA; j++)
    {
      pesosEntrada[i][j] = rand() % 2 + .5;
    }
    biasHidden[i] = rand() % 2;
  }
  // Carregando bias de saida
  for (unsigned i = 0; i < NEURONIOS_SAIDA; i++)
  {
    biasSaida[i] = rand() % 2 + .5;
  }
}

boolean iniciarTreinamento = false;
boolean executarTreinamento = false;
boolean executarRede = false;
int r;

void loop()
{
 
  if (!iniciarTreinamento && !executarTreinamento && !executarRede)
  {
    Serial.println(F("Envie letra 'i' pela serial para iniciar treinamento!"));
    Serial.println(F("Envie letra 'e' pela serial executar rede treinada!"));
    Serial.println(F("Envie letra 's' pela serial parar treinamento!"));
    delay(100);
  }
 
  r = Serial.read();
  iniciarTreinamento = (r == 'i');
  executarRede = (r == 'e');
  fimTreinamento = (r == 's');
 
  if (iniciarTreinamento)
  {
    contaTreinamento = 0;
    fimTreinamento = false;
    executarTreinamento = true;
  }
 
  if (fimTreinamento)
  {
    // Registrando tudo e fechando a conta
  }
 
  if (executarTreinamento && !fimTreinamento)
  {
     
      // Pegando valores dos sensores
      Serial.print(F("Posicione os sensores na linha desejada e digite 'p' quando pronto para executar treinamento "));
      Serial.print(contaTreinamento+1, DEC);
      Serial.print(" de ");
      Serial.print(EPOCAS_TREINAMENTO, DEC);
      Serial.print(": ");
      valor
     
      // Precisamos dizer qual a resposta certa para rede calcular propagacao de erro
      Serial.print(F("Digite valor da resposta (A, B, C, D ou E):"));
      respostaTreinamento = pegarValorSaidaDaSerial();
     
      fimTreinamento = (contaTreinamento >= EPOCAS_TREINAMENTO);
      contaTreinamento++;
    }
   
   
    if (executarRede)
    {
      // Executar rede depois de treinada
    }
  }
}



Vou atualizando conforme eu for desenvolvendo a ideia.

Abraços,
Renato
renato.aloi
Site Admin
 
Mensagens: 1337
Registrado em: Seg Ago 20, 2012 11:44 pm

Re: Leitor de Gabarito com Arduino

Mensagempor renato.aloi » Sex Dez 12, 2014 9:39 pm

Atualização feita no Face:

O processo de treinamento é meio chatinho de montar, mas é assim, vc posiciona o sensor em uma linha. Vc diz para a rede qual é a resposta da linha que o sensor está em cima. Por exemplo, vc diz q a resposta é B. o sensor vai ter 5 entradas e uma delas vai estar diferente das outras, pois vai estar "enxergando" a bolinha. A Rede Neural vai responder (sei lá) que a resposta é D, mas está errado, ela ajusta os pesos e tenta melhorar na proxima linha, assim por diante. Depois de uns 20 treinamentos (pq o problema é espacialmente simples de resolver), a rede vai acertar sozinha o resultado. É bem legar de ver funcionando! Vou postar isso no forum tbém.
renato.aloi
Site Admin
 
Mensagens: 1337
Registrado em: Seg Ago 20, 2012 11:44 pm

Re: Leitor de Gabarito com Arduino

Mensagempor renato.aloi » Sex Dez 12, 2014 10:02 pm

Atualizando código:

Código: Selecionar todos

#define NEURONIOS_HIDDEN     2
#define NEURONIOS_ENTRADA    5
#define NEURONIOS_SAIDA      3
#define ETA                  0.15
#define ALPHA                0.35
#define MIN_ERRO_GLOBAL      0.01
#define EXEMPLOS_TREINAMENTO 20
#define EPOCAS_TREINAMENTO   10

float pesosSaida[NEURONIOS_SAIDA][NEURONIOS_HIDDEN];
float pesosEntrada[NEURONIOS_HIDDEN][NEURONIOS_ENTRADA];
float biasEntrada[NEURONIOS_HIDDEN];
float biasSaida[NEURONIOS_SAIDA];

float funcaoAtivacaoEntrada[NEURONIOS_HIDDEN];
float funcaoTransferenciaEntrada[NEURONIOS_HIDDEN];
float funcaoAtivacaoSaida[NEURONIOS_SAIDA];
float funcaoTransferenciaSaida[NEURONIOS_SAIDA];
float gradienteSaida[NEURONIOS_SAIDA];
float gradienteEntrada[NEURONIOS_HIDDEN];
float deltaSaida[NEURONIOS_SAIDA];
float deltaEntrada[NEURONIOS_HIDDEN];

float entradas[NEURONIOS_ENTRADA];
float saidas[NEURONIOS_SAIDA];
float erros[NEURONIOS_SAIDA];

unsigned long contaTreinamento = 0;
boolean fimTreinamento = true;
char comando;

boolean iniciarTreinamento = false;
boolean executarTreinamento = false;
boolean executarRede = false;
int r;

float erroGlobal = 0;
float erroLocal = 0;


void setup()
{
  Serial.begin(9600);
  delay(100);
 
  Serial.println("Serial OK!");
 
  // Carregando bias e pesos iniciais
  for (unsigned i = 0; i < NEURONIOS_HIDDEN; i++)
  {
    for (unsigned j = 0; j < NEURONIOS_SAIDA; j++)
    {
      pesosSaida[j][i] = rand() % 2 + .5;
    }
    for (unsigned j = 0; j < NEURONIOS_ENTRADA; j++)
    {
      pesosEntrada[i][j] = rand() % 2 + .5;
    }
    biasEntrada[i] = rand() % 2;
  }
  // Carregando bias de saida
  for (unsigned i = 0; i < NEURONIOS_SAIDA; i++)
  {
    biasSaida[i] = rand() % 2 + .5;
  }
}


void loop()
{
 
  if (!iniciarTreinamento && !executarTreinamento && !executarRede)
  {
    Serial.println(F("Envie letra 'i' pela serial para iniciar treinamento!"));
    Serial.println(F("Envie letra 'e' pela serial executar rede treinada!"));
    Serial.println(F("Envie letra 's' pela serial parar treinamento!"));
    delay(100);
    aguardarComandoSerial();
  }
 
  //r = Serial.read();
  iniciarTreinamento = (comando == 'i');
  executarRede = (comando == 'e');
  fimTreinamento = (comando == 's');
 
  if (iniciarTreinamento)
  {
    contaTreinamento = 0;
    fimTreinamento = false;
    iniciarTreinamento = false;
    executarTreinamento = true;
   
  }
 
  if (fimTreinamento)
  {
    // Registrando tudo e fechando a conta
  }
 
  if (executarTreinamento && !fimTreinamento)
  {
      // Pegando valores dos sensores
      Serial.print(F("Posicione os sensores na linha desejada e digite 'p' quando pronto para executar treinamento "));
      Serial.print(contaTreinamento+1, DEC);
      Serial.println(" ('q' para sair): ");
      aguardarComandoSerial();
     
      if (comando == 'p')
      {
        leituraValorSensores();
       
        // Precisamos dizer qual a resposta certa para rede calcular propagacao de erro
        Serial.print(F("Digite valor da resposta (A, B, C, D ou E) ('q' para sair):"));
        aguardarComandoSerial();
       
        if (comando == 'A' || comando == 'B' || comando == 'C' || comando == 'D' || comando == 'E')
        {
          leituraResposta();
         
          apresentarExemploDeTreinamento();
         
          propagarSinaisNaRede();
         
          apresentarRespostaDoExemplo();
         
          calcularErrosDaRede();
       
         
          Serial.print(F("Erro Medio Global: "));
          Serial.println(erroGlobal);
         
          // Nesse ponto perguntar ao usuario se deseja atualizar sinapses
          // Importante decidir quando parar
         
          retropropagarErrosNaRede();
       
          fimTreinamento = ((contaTreinamento >= EPOCAS_TREINAMENTO) || erroGlobal < MIN_ERRO_GLOBAL);
          contaTreinamento++;
         
        } else if (comando == 'q') fimTreinamento = true;
      }
      else if (comando == 'q') fimTreinamento = true;
  }
   
   
  if (executarRede)
  {
    // Executar rede depois de treinada
  }

}

void leituraValorSensores()
{
  for (unsigned i = 0; i < NEURONIOS_ENTRADA; i++)
  {
    entradas[i] = analogRead(i);
  }
}

void leituraResposta()
{
  switch(comando)
  {
    case 'A':
      saidas[0] = 0;
      saidas[1] = 0;
      saidas[2] = 1;
      break;
    case 'B':
      saidas[0] = 0;
      saidas[1] = 1;
      saidas[2] = 0;
      break;
    case 'C':
      saidas[0] = 0;
      saidas[1] = 1;
      saidas[2] = 1;
      break;
    case 'D':
      saidas[0] = 1;
      saidas[1] = 0;
      saidas[2] = 0;
      break;
    case 'E':
      saidas[0] = 1;
      saidas[1] = 0;
      saidas[2] = 1;
      break;
    default: // erro
      saidas[0] = 1;
      saidas[1] = 1;
      saidas[2] = 1;
      break;
  }
}

void aguardarComandoSerial()
{
  int c = Serial.read();
  while (c != 'p' && c != 'q' && c != 'A' && c != 'B' && c != 'C' && c != 'D' && c != 'E' && c != 'i' && c != 'e' && c != 's')
  { 
    c = Serial.read();
    delay(10);
  }
  comando = (char)c;
}

void apresentarExemploDeTreinamento()
{
  Serial.println();
  Serial.print(F("Dados do treinamento "));
  Serial.print(contaTreinamento+1, DEC);
  Serial.println(": ");
 
  Serial.print(F("Entradas: "));
  for (unsigned i = 0; i < NEURONIOS_ENTRADA; i++)
  {
    Serial.print(entradas[i], DEC);
    if (i < NEURONIOS_ENTRADA - 1) Serial.print(", ");
  }
  Serial.println();
  Serial.print(F("Saidas ("));
  Serial.print(comando);
  Serial.print(F("): "));
  for (unsigned i = 0; i < NEURONIOS_SAIDA; i++)
  {
    Serial.print(saidas[i], DEC);
    if (i < NEURONIOS_SAIDA - 1) Serial.print(", ");
  }
  Serial.println();
 
}

void apresentarRespostaDoExemplo()
{
  Serial.println();
  Serial.print(F("Resposta da Rede: "));
  for (unsigned i = 0; i < NEURONIOS_SAIDA; i++)
  {
    Serial.print(funcaoTransferenciaSaida[i], DEC);
    if (i < NEURONIOS_SAIDA - 1) Serial.print(", ");
  }
  Serial.println();
 
}

// RNA

void propagarSinaisNaRede()
{
  for (unsigned i = 0; i < NEURONIOS_HIDDEN; i++)
  {
    funcaoAtivacaoEntrada[i] = 0;
    for (unsigned j = 0; j < NEURONIOS_ENTRADA; j++)
    {
      funcaoAtivacaoEntrada[i] += pesosEntrada[i][j] * entradas[j];
    }
    funcaoAtivacaoEntrada[i] += biasEntrada[i];
   
    funcaoTransferenciaEntrada[i] = 1 / (1 + exp(-funcaoAtivacaoEntrada[i]));
  }
 
  for (unsigned i = 0; i < NEURONIOS_SAIDA; i++)
  {
    funcaoAtivacaoSaida[i] = 0;
    for (unsigned j = 0; j < NEURONIOS_HIDDEN; j++)
    {
      funcaoAtivacaoSaida[i] += pesosSaida[i][j] * funcaoTransferenciaEntrada[j];
    }
    funcaoAtivacaoSaida[i] += biasSaida[i];
   
    funcaoTransferenciaSaida[i] = 1 / (1 + exp(-funcaoAtivacaoSaida[i]));
  }
}

void calcularErrosDaRede()
{
  // Calculando erros
  erroLocal = 0;
  for (unsigned i = 0; i < NEURONIOS_SAIDA; i++)
  {
    erros[i] = saidas[i] - funcaoTransferenciaSaida[i];
    erroLocal += (erros[i]*erros[i])/2;
  }
 
  erroGlobal = ((erroGlobal * contaTreinamento) + erroLocal) / (contaTreinamento + 1);
}

void retropropagarErrosNaRede()
{
  for (unsigned i = 0; i < NEURONIOS_SAIDA; i++)
  {
    gradienteSaida[i] = exp(-funcaoAtivacaoSaida[i]) / ((1 + exp(-funcaoAtivacaoSaida[i])) * (1 + exp(-funcaoAtivacaoSaida[i])));
    deltaSaida[i] = -erros[i] * gradienteSaida[i];
  }
 
  for (unsigned i = 0; i < NEURONIOS_HIDDEN; i++)
  {
    gradienteEntrada[i] = exp(-funcaoAtivacaoEntrada[i]) / ((1 + exp(-funcaoAtivacaoEntrada[i])) * (1 + exp(-funcaoAtivacaoEntrada[i])));
    deltaEntrada[i] = 0;
    for (unsigned j = 0; j < NEURONIOS_SAIDA; j++)
    {
      deltaEntrada[i] += (gradienteEntrada[i] * deltaSaida[j] * pesosSaida[j][i]);
    }
  }
 
  // Ajustando pesos
  for (unsigned i = 0; i < NEURONIOS_SAIDA; i++)
  {
    for (unsigned j = 0; j < NEURONIOS_HIDDEN; j++)
    {
      pesosSaida[i][j] -= (ETA * deltaSaida[i] * funcaoAtivacaoEntrada[j]) - ALPHA;
      biasSaida[i] -= (ETA * deltaSaida[i] * funcaoAtivacaoEntrada[j]) - ALPHA;
    }
  }
 
  for (unsigned i = 0; i < NEURONIOS_HIDDEN; i++)
  {
    for (unsigned j = 0; j < NEURONIOS_ENTRADA; j++)
    {
      pesosEntrada[i][j] -= (ETA * deltaEntrada[i] * entradas[j]) - ALPHA;
      biasEntrada[i] -= (ETA * deltaEntrada[i] * entradas[j]) - ALPHA;
    }
  }
}
Editado pela última vez por renato.aloi em Dom Dez 14, 2014 2:14 am, em um total de 5 vezes.
Razão: atualizando codigo 1, 2, 3, 4
renato.aloi
Site Admin
 
Mensagens: 1337
Registrado em: Seg Ago 20, 2012 11:44 pm

Re: Leitor de Gabarito com Arduino

Mensagempor renato.aloi » Dom Dez 14, 2014 6:56 pm

Postando fotos do tablet
FB_IMG_1418532923540.jpg
Tela do monitor da serial
FB_IMG_1418532923540.jpg (741.18 KiB) Exibido 1210 vezes


FB_IMG_1418531709119.jpg
Sensor em funcionamento
FB_IMG_1418531709119.jpg (529.97 KiB) Exibido 1210 vezes


20141214_020427.jpg
Montagem do sensor
20141214_020427.jpg (608.24 KiB) Exibido 1210 vezes
renato.aloi
Site Admin
 
Mensagens: 1337
Registrado em: Seg Ago 20, 2012 11:44 pm

Re: Leitor de Gabarito com Arduino

Mensagempor renato.aloi » Dom Dez 14, 2014 6:59 pm

Telas da Rede NEural funcionando

arduinoNeural2.png
Rede Neural começando treinamento. Ainda faltam alguns ajustes, a taxa de aprendizado está muito lenta...
arduinoNeural2.png (72.64 KiB) Exibido 1209 vezes


arduinoNeural1.png
Primeiro teste
arduinoNeural1.png (24.13 KiB) Exibido 1209 vezes
renato.aloi
Site Admin
 
Mensagens: 1337
Registrado em: Seg Ago 20, 2012 11:44 pm


Voltar para Projetos dos Membros

Quem está online

Usuários navegando neste fórum: Nenhum usuário registrado e 1 visitante

cron