segunda-feira, 2 de setembro de 2019

Virtual Realidade usando Arduino e Processing

Este é um projeto muito interessante no qual vamos aprender como implementar a realidade virtual usando o Arduino e o Processamento. Para a maioria de nós, o filme Homem de Ferro de Jon Favreau sempre foi uma inspiração para construir coisas novas que tornarão nossa vida mais fácil e divertida. Eu pessoalmente admirei os técnicos mostrados no filme e sempre quis criar algo semelhante a isso. Portanto, neste projeto, tentei imitar as coisas de realidade virtual que acontecem no filme, como se pudéssemos simplesmente acenar com a mão na frente do computador e mover o ponteiro para o local desejado e executar algumas tarefas.
Aqui vou mostrar como você pode basta acenar com a mão na frente da webcam e desenhar algo no seu computador. Também mostrarei como você pode alternar as luzes movendo sua mão virtualmente e fazendo cliques com os dedos no ar.

Conceito:

Para que isso aconteça, precisamos aproveitar o poder do  Arduino e Processamento   combinados. A maioria estaria familiarizada com o  Arduino, mas o processamento pode ser novo para você. Processing é um aplicativo como o Arduino e também é de código aberto e gratuito para download. Usando o Processing, você pode criar aplicativos simples do sistema, aplicativos Android e muito mais. Ele também tem a capacidade de realizar processamento de imagem e reconhecimento de voz. É como o Arduino e é muito fácil de aprender, mas não se preocupe se você é completamente novo no processamento porque o   Eu escrevi este tutorial bastante simples, para que qualquer pessoa interessada possa fazer isso funcionar rapidamente.
Neste tutorial, estamos usando o Processing para criar um aplicativo de sistema simples que nos fornece uma interface do usuário e rastreia a posição da nossa mão usando o processamento de imagens. Agora, temos que clicar com o botão esquerdo e clicar com o botão direito. Para isso, usei dois sensores de salão (um no meu dedo indicador e outro no dedo médio) que serão lidos pelo Arduino Nano. O Arduino também transmite o status do clique ao computador sem fio via Bluetooth.
Pode parecer complicado, mas confie em mim; não é tão difícil quanto parece. Então, vamos dar uma olhada nos materiais necessários para que este projeto esteja em funcionamento.


Materiais requisitados:

  1. Arduino Nano
  2. Sensor Hall (A3144) – 2Nos
  3. Um pequeno pedaço de ímã
  4. Módulo Bluetooth (HC-05 / HC-06)
  5. Bateria 9V
  6. Placa de ponto dos fios de conexão.
  7. Um par de luvas
  8. Arduino IDE (Software)
  9. Processing IDE(Software)
  10. Um computador com webcam e Bluetooth (você também pode usar Bluetooth ou webcam externa para o seu computador)

Esquemas e Hardware:

A parte de hardware deste projeto é muito simples e fácil de construir. O esquema completo é mostrado abaixo.
Circuit Diagram for Virtual Reality Project using Arduino
O Arduino, os resistores e os pinos berg stick são soldados em uma placa de pontos, como mostrado abaixo.
arduino nano
O sensor da sala e o módulo Bluetooth são soldados a um fio conector, como mostrado abaixo. 
hall sensor and bluetooth module
Quando essas duas seções estiverem prontas, poderão ser montadas em luvas para facilitar o uso. Eu usei luvas de plástico descartáveis ​​que podem ser adquiridas em qualquer posto médico perto de você. Você deve garantir que o ímã apareça no dedo polegar e o sensor hall 1 e sensor hall 2 estejam presentes antes do indicador e do dedo médio, respectivamente. Eu usei fitas de pato para prender os componentes no lugar. Depois que os componentes são montados, ele deve se parecer com isso.
Virtual Reality Gloves with Bluetooth and Hall Sensor
Agora vamos abrir o IDE do Arduino e começar a programar.

Programa para Arduino:

O objetivo deste código do Arduino é ler o status do sensor do hall e transmiti-lo usando o módulo Bluetooth. Ele também deve receber dados do Bluetooth e alternar o LED integrado com base no valor recebido. O programa completo é fornecido no final deste tutorial; Eu também expliquei algumas linhas abaixo.
if (Phs1!=HallState_1 || Phs2!=HallState_2) //Verifique se novas teclas estão pressionadas
 {
if (HallState_1==LOW && HallState_2==LOW)
Aisha.write(1);
if (HallState_1==HIGH && HallState_2==LOW)
Aisha.write(2);
if (HallState_1==LOW && HallState_2==HIGH)
Aisha.write(3);
if (HallState_1==HIGH && HallState_2==HIGH)
Aisha.write(4);
 }
Conforme mostrado nas linhas acima, com base no status do sensor de hall, o Bluetooth gravará um valor específico. Por exemplo, se o sensor hall 1 estiver alto e o sensor hall 2 baixo, transmitiremos o vale "2" através do módulo Bluetooth. Certifique-se de escrever os valores no módulo BT e não imprimi-los. Porque será fácil ler o único no lado Processamento apenas se eles forem escritos. Além disso, o valor será enviado apenas se não for o mesmo que o valor anterior.
if (BluetoothData=='y')
digitalWrite(ledpin,HIGH);
if (BluetoothData=='n')
digitalWrite(ledpin,LOW);
Essas linhas são usadas para alternar o LED integrado que está conectado ao Pino 13, com base no valor recebido pelo módulo BT. Por exemplo, se o módulo receber um "y" então o LED acende e, se receber um "n ’ n ’ então é desligado.

Programa para processamento:

O objetivo do programa Processing é criar um aplicativo de sistema que possa atuar como uma interface do usuário (interface do usuário) e também executar o processamento de imagens para rastrear um objeto específico. Nesse caso, rastreamos o objeto azul que colamos nas luvas acima. O programa basicamente possui quatro telas.
  1. Tela de calibração
  2. Tela principal
  3. Tela de pintura
  4. Tela de alternância de LED
Podemos navegar de uma tela para outra simplesmente agitando as mãos e arrastando as telas no ar. Também podemos clicar nos locais desejados para alternar o LED ou até desenhar algo na tela.
Você pode copiar e colar o programa completo de Processing (fornecido no final) e modificá-lo com base em sua criatividade ou simplicidade. baixe os arquivos EXE aqui, e siga as etapas a seguir para iniciar o aplicativo.
  1. Instale o JAVA no seu computador se você não o instalou antes
  2. Instale o You Cam perfeito no seu computador
  3. Ligue o seu Arduino e emparelhe o seu computador com o módulo Bluetooth
  4. Inicie o arquivo do aplicativo
Se tudo der certo, você poderá notar que o LED do módulo Bluetooth está estável e a luz da webcam acende. Se você tiver algum problema, entre em contato através da seção de comentários e eu vou ajudá-lo.
Se você deseja modificar o código e criar mais recursos para isso, pode usar os seguintes insights do programa
O IDE do Processing pode ser baixado em aqui. Se você quiser aprender mais sobre o Processing e criar projetos mais interessantes, visite os tutoriais aqui.  
O Processing tem a capacidade de ler dados seriais; neste programa, os dados seriais são provenientes da porta COM Bluetooth. Você deve selecionar a qual porta COM o seu Bluetooth está conectado usando esta linha abaixo
port = new Serial(this,Serial.list()[1],9600);
Aqui eu selecionei meu 1st Porta COM, que é COM5 no meu caso (veja a imagem abaixo) e mencionei que o módulo Bluetooth roda em 9600 baudrate.
VR
Como dito anteriormente, o processamento também tem a capacidade de processar imagens, neste tutorial as imagens são enviadas dentro do esboço usando uma webcam. Em cada imagem, rastreamos um objeto em particular. Para saber mais sobre isso, visite aqui tutorial.
Eu tentei o meu melhor para explicar o programa (fornecido no final) através das linhas de comentário. Você pode baixar os arquivos aqui.
Se você quiser saber mais sobre o esboço, entre em contato através da seção de comentários e eu o ajudarei.

Trabalhando:

Quando o hardware e o software estiverem prontos, use as luvas e prepare-se para alguma ação. Agora, simplesmente ligue o Arduino e, em seguida, inicie o aplicativo. O led no módulo Bluetooth deve ficar estável. Agora, isso significa que seu aplicativo System estabeleceu um link Bluetooth com seu Arduino.
Você verá a seguinte tela onde você deve selecionar o objeto a ser rastreado. Esse rastreamento pode ser feito simplesmente clicando no objeto. Nesse caso, o objeto é o disco azul. Agora você pode mover seu objeto e observe que o ponteiro segue seu objeto. Use um objeto de cor exclusivo e uma sala iluminada para obter melhores resultados.
Virtual Reality using processing
Agora toque seu dedo polegar com o dedo indicador e você verá a mensagem "Key 1 Pressed". e quando você pressionar o polegar com o dedo médio, deverá ver "Key 2 Pressed" isso indica que tudo funciona bem e a calibração terminou. Agora clique no botão Concluído.
Virtual Reality using arduino nano
Virtual Reality using processing image
Depois que o botão Concluído for pressionado, você será direcionado para a tela principal, onde poderá pintar no ar ou alternar o LED na placa Arduino, como mostra o vídeo abaixo. 
Código: 
#include <SoftwareSerial.h>//importar a biblioteca serial
SoftwareSerial Aisha(11, 12); //TX, RX
int ledpin=13; //led no D13 mostrará piscar on / off
int hall_1=9;
int hall_2=10;
int BluetoothData; //os dados fornecidos pelo Computador
int HallState_1,HallState_2;
int change;
int Phs1,Phs2;

 void setup()
 {
   Aisha.begin(9600); //O módulo Bluetooth funciona a 9600 baudrate
   pinMode(ledpin,OUTPUT); //pino de led como saída
   pinMode(hall_1,INPUT); //sensor hall 1 como entrada
   pinMode(hall_2,INPUT); //hall sensor 2 também é entrada
 }

 void loop()
 {
   if (Aisha.available()) //se os dados são enviados do laptop
   BluetoothData=Aisha.read(); //leia e guarde-o no BluetoothData
 Phs1=HallState_1;
 Phs2=HallState_2;
 HallState_1 = digitalRead(hall_1);
 HallState_2 = digitalRead(hall_2);


 if (Phs1!=HallState_1 || Phs2!=HallState_2) //Verifique se novas teclas estão pressionadas
 {
if (HallState_1==LOW && HallState_2==LOW)
Aisha.write(1);
if (HallState_1==HIGH && HallState_2==LOW)
Aisha.write(2);
if (HallState_1==LOW && HallState_2==HIGH)
Aisha.write(3);
if (HallState_1==HIGH && HallState_2==HIGH)
Aisha.write(4);
 }
if (BluetoothData=='y')
digitalWrite(ledpin,HIGH);
if (BluetoothData=='n')
digitalWrite(ledpin,LOW);

  }
//----------- O código do Arduino termina---------------//




//------------Processing código começa-----------//
import processing.video.*;  //Importe o Librarey para usar o vídeo
import processing.serial.*; //Importe o Librarey para usar a porta serial (Bluetooth)
//**Declarações variáveis ​​globais**//
Serial port; //port é uma variável de objeto para comunicação serial
int data;
boolean calibration= false;
int mirror =0;
int mirrorn =-1;
PImage Done,Aisha,Paint,LED_Toggle,LED_on,LED_off;
boolean key1,key2,key3,movePaint,PaintScreen,PaintScreenClear,moveLED,LEDscreen;
float Paintx,Painty,avgX,avgY,LEDx,LEDy;
int count;
PImage img = createImage(380, 290, RGB);
int Px,Py;
Capture video;  //crie um objeto chamado video
color trackColor;  //variável para armazenar a cor que vamos rastrear
float threshold = 50  ; //pode ser variado pelo usuário
//_____Fim da declaração da variável______//
//*Função para carregar todas as imagens da pasta de dados do sketch*//
void loadImages()
{
  Done = loadImage("Done.png");
  Aisha = loadImage ("Aisha.png");
  Paint = loadImage("Paint.png");
  LED_Toggle = loadImage("LED_Toggle.png");
  LED_on = loadImage("LED_on.png");
  LED_off = loadImage ("LED_off.png");
}
//_____Fim da declaração da variável______//
//**Executa apenas os**//
void setup() {
  size(800, 600);
  loadImages();
  String[] cameras = Capture.list();
  printArray(cameras);
  video = new Capture(this, cameras[34]);
  video.start();
  key1=key2=key3=false;
  Paintx=width/10;
  Painty=height/8.5;
  LEDx=width/1.1;
  LEDy=height/8.5;
  movePaint=PaintScreen=PaintScreenClear=moveLED=LEDscreen=false;
  port = new Serial(this,Serial.list()[1],9600);
  println(Serial.list());
}
//**Fim do Setup**//
//**Disparado para atualizar cada quadro do vídeo**//
void captureEvent(Capture video)  //quando uma nova imagem aparece
 { video.read(); } //como um vídeo
//*Função para apontar qual cor rastrear*//
void Calibrate()
{
   image(video,0,0);
   imageMode(CORNERS);
   image(Done,width/1.2,height/1.1,width,height); //posição do botão Concluído
   if (mouseX>width/1.2 && mouseY>height/1.1) //Se o mouse estiver dentro do botão Concluído
   {
   calibration=true;
   cursor(HAND);
   mirrorn=1;
   mirror=width;
   }
fill(#1B96E0);
textSize(20);
if (key1==true) //se o sensor hall 1 estiver ativo no Arduino
text("Key-1 Pressed",width/12,height/1.05); //Texto e sua posição
if (key2==true) //if hall sensor 2 is active on Arduino
text("Key-2 Pressed",width/12,height/1.05); //Texto e sua posição
}
//_____Fim da calibração______//
//*Função para representar a tela principal*//
void UI()
{
    imageMode(CORNERS);
    image(Aisha,0,0,width,height);
    imageMode(CENTER);
   
    if ((avgX<(width/10+((width/4)/2)) && avgY<(height/8.5+((height/4)/2)) && key1==true) || (movePaint==true&&key1==true)) //se clicou dentro da imagem
    {
    movePaint=true;
    image (Paint, avgX,avgY,width/4, height/4); //Arraste a imagem
    }
    else if (movePaint==false)
    image (Paint, Paintx,Painty,width/4, height/4); //coloque a imagem na esquina
    else
      PaintScreen=true;
     
       if ((avgX>(width/1.1-((width/4)/2)) && avgY<(height/8.5+((height/4)/2)) && key1==true) || (moveLED==true&&key1==true)) //se clicou dentro da imagem
    {
    moveLED=true;
    image (LED_Toggle, avgX,avgY,width/4, height/4); //Arraste a imagem
    }
    else if (moveLED==false)
    image (LED_Toggle, LEDx,LEDy,width/4, height/4); //coloque a imagem na esquina
    else
      LEDscreen=true;
}
//_____Fim da função da tela principal______//
//*Função para representar a tela de pintura*//
void Paintfun()
{
    imageMode(CENTER);
    background(#0B196A);
    image (Paint, width/2,height/2,width/1.5, height);
 
img.loadPixels();
for (int IX = 210, Px=0; IX<=590; IX++, Px++)
{
for (int IY = 85, Py=0; IY<=375; IY++, Py++)
  {
  if ((dist(avgX,avgY,IX,IY)<4)  && key1==true)
  img.pixels[(Px+(Py*img.width))] = color(255);  //cor do plano de fundo da pintura atualizada
  if (key2==true)
  PaintScreen = false;
  }
}
img.updatePixels();
image(img, width/2, height/2.6);
}
//_____Fim da função principal da tela de pintura______//
//*Função para exibir a tela LED de alternância*//
void LEDfun()
{
  imageMode(CENTER);
  background(255);
  image(LED_on,(width/2 - width/4), height/3,width/4, height/5);
  image(LED_off,(width/2 + width/4), height/3,width/4, height/5);
   textSize(50);
  textAlign(CENTER);
  if (key1==true && avgX<300 && avgY>150 && avgX>95 && avgY<260)
  { fill(#751EE8);
  text("LED turned on",width/2,height/1.5);
  port.write(121);
  }
  if (key1==true && avgX<700 && avgY>150 && avgX>500 && avgY<260)
  { fill(#FC0808);
  text("LED turned   off",width/2,height/1.5);
  port.write(110);
  }
}
//_____Fim da função principal da tela de LED_____//
//*Função para saber qual tecla é pressionada*//
void key_select() {
 
  switch(data){
  case 1:
     key1=true; key2=true;
     break;
   
  case 2:
     key1=false; key2=true;
     break;
   
  case 3:
     key1=true; key2=false;
     break;
   
  case 4:
     key1=false; key2=false;
     break;
}
}
//_____Fim da função______//

void draw() {
  if (port.available()>0) //se houver um valor BT recebido
  {
    data=port.read(); //leia o valor recebido BT e salve nos dados
    println(key1,key2,data); //imprimir para depuração
    key_select(); //alternar as teclas 1 e 2 da variável
  }
 
  video.loadPixels();
  if (calibration==false) //nenhuma calibração feita
  Calibrate(); //Calibrar tela
  if (calibration==true && (PaintScreen==false || LEDscreen==false) )
  UI(); //Tela principal
  if (PaintScreen==true && calibration ==true)
  Paintfun(); //Tela de pintura
  if (LEDscreen==true && calibration ==true)
  LEDfun(); //Tela de LED
 
 if (key2==true)
  movePaint=PaintScreen=PaintScreenClear=moveLED=LEDscreen=false; //voltar para a tela principal
avgX = avgY = count = 0;
  // Comece o loop para percorrer todos os pixels
  for (int x = 0; x < video.width; x++ ) {
    for (int y = 0; y < video.height; y++ ) {
      int loc = x + y * video.width;
      // Qual é a cor atual
      color currentColor = video.pixels[loc];
      float r1 = red(currentColor);
      float g1 = green(currentColor);
      float b1 = blue(currentColor);
      float r2 = red(trackColor);
      float g2 = green(trackColor);
      float b2 = blue(trackColor);
      float d = distSq(r1, g1, b1, r2, g2, b2); 
      if (d < threshold*threshold) {
        stroke(255);
        strokeWeight(1);
       // point((mirror-x)*mirrorn, y);
        avgX += x;
        avgY += y;
        count++;
      }
    }
  }
  if (count > 0) {
    avgX = avgX / count;
    avgY = avgY / count;
    // Desenhe um círculo no pixel rastreado
    fill(#21FADB);
    avgX = (mirror-avgX)*mirrorn;
    ellipse(avgX, avgY, 15, 15);
  }
}
float distSq(float x1, float y1, float z1, float x2, float y2, float z2) {
  float d = (x2-x1)*(x2-x1) + (y2-y1)*(y2-y1) +(z2-z1)*(z2-z1);
  return d;
}

void mousePressed() {
  if(calibration==false)
  {
  int loc = mouseX + mouseY*video.width;
  trackColor = video.pixels[loc]; //carregar a cor a ser rastreada
   }
}

Nenhum comentário:

Postar um comentário

Peço que use somente caixa baixa, não todo escrito em letra grande.