Participantes: Bruno Raniery e Émerson Bezerra.
Sob orientação de: Prof. Clemilson Santos e Prof. Melo Júnior
Uma das formas de interação sem fio que temos contato a um bom tempo e que a utilizamos com muita frequência é o uso de ondas de rádio, onde possuímos um emissor e um receptor. No caso das ondas de rádio, elas podem variar de 3 KHz à 200 GHz no que diz respeito a ciclos por segundo.
Uma das aplicabilidades mais comuns para as ondas de rádio e que está bem próximo do nosso cotidiano é o uso nos carrinhos de controle remoto os quais encapsulam componentes e microcontroladores capazes de controlar o envio e a recepção das ondas, em uma frequência conhecida, para que seja possível controlar o carrinho a distância.
A proposta a seguir visa controlar um carro de controle remoto de maneira automática através de um software de processamento de imagens. O experimento se propõe a tornar o carro “inteligente” sem que tenha uma intervenção em seu hardware.
1. Materiais Utilizados
1 carro de controle remoto 7 funções atuando na frequência de 40 GHz
1 Controle do carro de controle remoto com o microcontrolador TXM TX-2B ZYTAAAD
1 Arduino Uno
6 fios (macho)
1 Webcam
2. Montagem dos materiais
Para este trabalho será preciso trabalhar apenas no controle do carrinho e para isso é necessário abrir o controle removendo os parafusos com uma chave estrela. Tendo acesso a placa do controle é possível acessar o microcontrolador e seus pinos.
Seguindo o esquema do microcontrolador TXM TX-2B ZYTAAAD é possível identificar quais os pinos são os responsáveis por fazer o carrinho ir para frente, trás, direita e esquerda, além de identificar os pinos referentes ao Vcc e ao terra (Gnd).
Tendo identificado os pinos, para acessá-los é preciso usar os fios e soldar os fios em cada um destes pinos e conecta-los nos pinos do Arduino Uno.
No caso deste projeto conectamos os fios no Arduino da seguinte forma:
fio laranja – porta digital 13
fio azul – porta digital 12
fio verde – porta digital 11
fio amarelo – porta digital 10
fio vermelho – 5V
fio preto – GND
Em relação ao ambiente, este projeto precisa de um certo espaço aberto, com um terreno sem obstáculos e com aderência para o carrinho não derrapar.
A webcam precisa estar localizada a uma altura de aproximadamente 5 metros em relação ao chão e apontada para baixo, além de ser conectada via USB em um computador/notebook.
Este posicionamento da webcam se deve pelo motivo de que a webcam deve conseguir visualizar o carrinho mesmo nos casos em que ele precise fazer uma curva completa.
3. Código utilizado no Arduino
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | //Variável que armazena os valores enviados pelo Processing unsigned int readChar = 0; void setup() { //Inicialização da Serial Serial.begin(9600); } void loop() { if (Serial.available() > 0) { //Armazena valor recebido na Serial readChar = Serial.read(); Serial.println(readChar); //Bloco que recebe valor 1 e manda sinal LOW para o carro ir para frente if(readChar == 1) { limpa(); pinMode(13, OUTPUT); digitalWrite(13, LOW); } //Bloco que recebe valor 2 e manda sinal LOW para o carro ir para trás if(readChar == 2) { limpa(); pinMode(12, OUTPUT); digitalWrite(12, LOW); } //Bloco que recebe valor 3 e manda sinal LOW para o carro ir para direita if(readChar == 3) { limpa(); pinMode(10, OUTPUT); digitalWrite(10, LOW); pinMode(13, OUTPUT); digitalWrite(13, LOW); } //Bloco que recebe valor 4 e manda sinal LOW para o carro ir para esquerda if(readChar == 4) { limpa(); pinMode(11, OUTPUT); digitalWrite(11, LOW); pinMode(13, OUTPUT); digitalWrite(13, LOW); } //Bloco que recebe valor 0 deixa os pinos "flutuando" para o carro parar if(readChar == 0) { limpa(); } } } void limpa() { pinMode(13, INPUT); pinMode(12, INPUT); pinMode(10, INPUT); pinMode(11, INPUT); } |
4. Código utilizado no Processing
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 | import processing.video.*; import processing.serial.*; PImage source; PImage destination; PImage prevFrame; Capture cam; Serial port; //parametrizavéis int limiar_angulo_inicial = 15; int limiar_angulo = limiar_angulo_inicial; float limiar_media = 150; int limiar_carro = 35; int index_porta = 0; boolean clicou = false; boolean desenha = false; int par = 0; int mensagem = -1; int x1 = 0; int y1 = 0; int mediaPY, mediaPX; int quantidade, somax, mediax, somay, mediay; void setup() { size(640, 240); cam = new Capture(this, 320, 240, 30); cam.start(); destination = createImage(320, 240, RGB); prevFrame = createImage(320,240,RGB); // Select port println(Serial.list()); port = new Serial(this, Serial.list()[index_porta], 9600); } void draw() { if(cam.available()) { prevFrame.copy(cam,0,0,320,240,0,0,320,240); // antes de ler, salvar o frame anterior para fazer a comparação prevFrame.updatePixels(); cam.read();//recebe novo frame } destination.loadPixels(); prevFrame.loadPixels(); quantidade=0; somax=0; somay=0; //calcula a diferença de frames pixel a pixel e calcula a média deles for (int x = 0; x < cam.width; x++ ) { for (int y = 0; y < cam.height; y++ ) { int loc = x + y*cam.width; color current = cam.pixels[loc]; // Step 2, what is the current color color previous = prevFrame.pixels[loc]; // Step 3, what is the previous color // Step 4, compare colors (previous vs. current) float r1 = red(current); float g1 = green(current); float b1 = blue(current); float r2 = red(previous); float g2 = green(previous); float b2 = blue(previous); float diff = dist(r1,g1,b1,r2,g2,b2); destination.pixels[loc] = color(diff); if(diff>limiar_media){ quantidade++; somax = somax + x; somay = somay + y; } } } if(quantidade!=0){ mediaPX = mediax; mediaPY = mediay; //calcula angulo entre o previous x,y e o current x,y translate(mediaPX,mediaPY); mediax = somax / quantidade; mediay = somay / quantidade; float a = atan2(mediay, mediax); a = degrees(a); println("ponto 1:"+a); stroke(255, 0, 0); strokeWeight(2); translate(-mediaPX,-mediaPY); //calcula o angulo entre o current x,y e o x,y do destino translate(mediax,mediay); float distC, distP; distC = dist(x1, y1, mediax, mediay); distP = dist(x1, y1, mediaPX, mediaPY); float b = atan2(y1, x1); b = degrees(b); println("ponto 2:"+b); //mudar limiar com a distância do destino if(distP<=200) limiar_angulo = 4*limiar_angulo_inicial; if(distP<=100) limiar_angulo = 3*limiar_angulo_inicial; if(distP<=50) limiar_angulo = 2*limiar_angulo_inicial; if(distP<=25) limiar_angulo = limiar_angulo_inicial; if(a<=b+limiar_angulo && a>=b-limiar_angulo){ if(distC<=distP) { println("siga em frente"); mensagem = 1; } if(distC>distP) { println("rode mais"); mensagem = 3; delay(100); } } else{ if(a<b){ println("rode esq"); mensagem = 4; } if(a<=b){ println("rode dir"); mensagem = 3; } } if(mediax< x1+limiar_carro && mediax>x1-limiar_carro && mediay<y1+limiar_carro && mediay>y1-limiar_carro){ println("parou!!!!"); mensagem = 0; } //enviar mensagem port.write(mensagem); translate(-mediax,-mediay); //desenhar o current x,y e o previous x,y if(par%2 == 0){ //rect(0,0,320,240); image(cam,0,0); } //evitar estouro if(par == 1000){ par = 0; } par++; //desenha as linhas e os marcadores do caminho line(mediax, mediay, x1, y1); line(mediaPX, mediaPY, mediax, mediay); //line(mediax, mediay, ladoX, ladoY); ellipse(mediax, mediay, 1, 1); if(desenha) ellipse(x1, y1, 5, 5); } if(clicou) { desenha =true; ellipse(mouseX, mouseY, 5, 5); println("x:"+mouseX+" y:"+mouseY); clicou = false; } destination.updatePixels(); image(destination,320,0); } void mouseClicked() { x1 = mouseX; y1= mouseY; clicou = true; port.write(1); delay(500); port.write(0); } void keyPressed() { if (key == CODED) { if (keyCode == UP) { port.write(0); } } } |
5. Conclusão
Nosso projeto atingiu o objetivo de demostrar o controle do carrinho através do processamento de imagens em conjunto com o arduino. Ainda necessita de algumas melhorias, como fazer curvas para os dois lados, em casos de incapacidade de movimento utilizar-se da ré e diminuir o tempo de procura do ponto quando ele não estiver no lado “dominante”.











