Você está na página 1de 70

INSTITUTO FEDERAL DE EDUCAÇÃO, CIÊNCIA E TECNOLOGIA FLUMINENSE IFFluminense PROGRAMA DE GRADUAÇÃO EM ENGENHARIA DE CONTROLE E AUTOMAÇÃO BACHARELADO EM ENGENHARIA DE CONTROLE E AUTOMAÇÃO

Caio Jorge Haddad de Paula

PROJETO E CONSTRUÇÃO DE UM ROBÔ AUTÔNOMO COM VISÃO COMPUTACIONAL

CAMPOS DOS GOYTACAZES, RJ Dezembro de 2015

INSTITUTO FEDERAL DE EDUCAÇÃO, CIÊNCIA E TECNOLOGIA FLUMINENSE IFFluminense COORDENAÇÃO DE GRADUAÇÃO EM ENGENHARIA DE CONTROLE E AUTOMAÇÃO BACHARELADO EM ENGENHARIA DE CONTROLE E AUTOMAÇÃO

Caio Jorge Haddad de Paula

PROJETO E CONSTRUÇÃO DE UM ROBÔ AUTÔNOMO COM VISÃO COMPUTACIONAL

Trabalho de Conclusão de Curso apresentado à coordenação do curso de Engenharia de Controle e Automação, do Instituto Federal de Educação, Ciência e Tecnologia Fluminense, para obtenção do grau de BACHAREL EM ENGENHARIA DE CONTROLE E AUTOMAÇÃO

Orientador: Prof. MSc. Edson Simões dos Santos.

CAMPOS DOS GOYTACAZES, RJ Dezembro de 2015

CAIO JORGE HADDAD DE PAULA

PROJETO E CONSTRUÇÃO DE UM ROBÔ AUTÔNOMO COM VISÃO COMPUTACIONAL

Trabalho de Conclusão de Curso apresentado à Coordenação de Engenharia de Controle e Automação, do Instituto Federal de Educação, Ciência e Tecnologia Fluminense Campos dos Goytacazes/RJ, para obtenção do grau de BACHAREL EM ENGENHARIA DE CONTROLE E AUTOMAÇÃO

Aprovada em 23 de dezembro de 2015.

Orientador: Prof. MSc. Edson Simões dos Santos.

BANCA EXAMINADORA

Professor Edson Simões dos Santos, M.Sc.- Orientador Instituto Federal Fluminense

Professor Fábio Junio dos Santos Coelho Instituto Federal Fluminense

Professor Marcos Moulin Valencia Instituto Federal Fluminense

CAMPOS DOS GOYTACAZES / RJ DEZEMBRO 2015

AGRADECIMENTOS

Agradeço a Deus pela sua infinita misericórdia.

Ao meu orientador, professor Edson Simões dos Santos, pela compreensão e dedicação que foram fundamentais na concretização deste trabalho.

Aos meus queridos e amados pais e irmã, Jorge Afonso de Paula, Faride Rena Haddad de Paula e Sara Ester Haddad de Paula, pela paciência e dedicação.

A minha querida namorada, Giullia Junqueira Pessanha pelo carinho e apoio incondicional.

A minha querida tia Denise Rena Haddad que contribuiu com orientação e recursos para a conclusão deste projeto.

Ao Instituto Federal de Educação, Ciência e Tecnologia Fluminense pela disponibilização de seus laboratórios sem os quais o projeto não poderia ter se concretizado.

A vitória cabe ao que mais persevera.”

Napoleão Bonaparte

RESUMO

O objetivo deste projeto é construir um robô com visão computacional via

processamento de imagens, em que uma plataforma microcontrolada recebe um algoritmo de controle para que o objetivo de colocar a bola dentro do gol seja alcançado. Esta plataforma recebe parâmetros referentes as posições dos objetos dentro do espaço

delimitado como o campo. Tal sistema deverá ser utilizado para fins educacionais dentro

do Instituto Federal Fluminense. O funcionamento do sistema se dá através de uma

câmera ajustada para capturar imagens do campo em que os robôs se encontram envia as imagens capturadas para um computador, em que através do software Matlab® as imagens são processadas, de forma que se identifique marcadores nessas imagens. O

marcador da plataforma robótica é um triângulo isósceles vermelho, em que através da

cor pode se identificar o objeto, e através do formato pode se identificar a direção e o

sentido da plataforma. O marcador da bola é uma circunferência verde, e o marcador do

gol é um retângulo azul. Após analisar a imagem, o software calcula a distância e o

ângulo do robô até a posição ideal, onde a bola deverá sofrer o impacto para que se acerte o gol. Após ter estes parâmetros, um sistema microcontrolado é responsável por enviar estes parâmetros à plataforma robótica via rádio frequência.

PALAVRAS-CHAVE:

Computacional.

Robô

Autônomo.

Processamento

de

Imagem.

Visão

ABSTRACT

The objective of this project is to build a system using image processing, where a robotic microcontrolled platform should make the decision-making so that the goal of putting the ball into the goal is reached. This platform receives parameters for the positions of objects within the limited space as the field. Such a system should be used for educational purposes within the Federal Fluminense Institute. The system operation takes place as follows: A camera is set to capture images of the field where robots are, sends the captured images to a computer, where software Matlab through the images are processed, so that these markers identify images. The marker of the robotic platform is a red isosceles triangle, where through color can identify the object, and through the format can identify the direction and the direction of the platform. The ball marker is a green circle, and the goal of the marker is a blue rectangle. After analyzing the image, the software will calculate the distance and the angle of the robot to the ideal position where the ball should be impacted so that they hit the goal. After these parameters, one microcontroller system will be responsible for sending these parameters robotics platform via radio frequency.

KEYWORDS:

Autonomous

Robot.

Image

Processing.

Computer

Vision.

LISTA DE FIGURAS E TABELAS

Figura 1: TRANSMISSOR DE RF

18

Figura 2: RECEPTOR DE RF

19

Figura 3: SERVOMOTOR PARALLAX

21

Figura 4: GRÁFICO PWM

22

Figura 5: ROBÔ MONTADO

26

Figura

6: BOLA E GOL

27

Figura 7: IMAGEM CAPTURADA COM RETAS TRAÇADAS PELO MATLAB

30

Figura 8: IMAGEM CAPTURADA PELO MATLAB EM DETALHES

31

Figura 9: ROBÔ E A INDICAÇÃO DO ÂNGULO

32

Quadro 1: MATRIZ DOS VALORES MÍNIMOS

33

Quadro 2: MATRIZ DOS VALORES MÁXIMOS

33

Figura 10: TRIÂNGULO DE EXTREMIDADES 1, 2 E 3

34

Quadro 3: RELAÇÃO ENTRE VARREDURAS E LOCALIZAÇÃO DE PIXELS

35

Figura 11(a): ILUSTRAÇÃO DE BOLA EM FORMATO DE PIXELS

36

Figura 11(b): ILUSTRAÇÃO DA PRIMEIRA VARREDURA

36

Figura

12: SEQÜÊNCIA DE VARREDURAS EFETUADAS

37

Figura

13: VARREDURA EM UM TRIÂNGULO

37

Figura 14: GRÁFICO

41

Figura 15: IMAGENS EXTRAÍDAS DA FILMAGEM DO TESTE

42

LISTA DE SIGLAS

RF

Rádio Frequência

PID

Proporcional Integrativo e Derivativo

PD

Proporcional e Derivativo

PI

Proporcional e Integrativo

TX

Transmissor

RX

Receptor

GND

Ground (Terra)

PWM

Pulse Width Modulation

Vcc

Volts em Corrente Contínua

SUMÁRIO

1

INTRODUÇÃO

11

1.1

OBJETIVO

12

1.1.1 Objetivo Geral

12

1.1.2 Objetivos Específicos

12

1.2 JUSTIFICATIVA

13

1.3 ORGANIZAÇÃO DOS CAPÍTULOS

13

2

REVISÃO DE LITERATURA

15

2.1 PROCESSAMENTO DE IMAGENS

15

2.2 - ARDUINO

16

2.3 Transmissor e Receptor RF

17

2.4 Servomotor

20

2.5 PWM - Modulação por largura de pulso

22

2.6 Comunicação Serial

23

3

DESENVOLVIMENTO DO PROJETO

24

3.1 DESING DE HARDWARE E ESTRUTURAS

24

3.2 PROGRAMAÇÃO DOS MÓDULOS

27

3.2.1 Programação do Módulo de Transmissão

27

3.2.2 Programação do Módulo de Recepção

28

 

3.3

PROGRAMAÇÃO DO MATLAB

29

3.3.1

Funções

32

3.3.1.1 Calibra_Cores.m

32

3.3.1.2 captura.m

33

3.3.1.3 varredura.m

34

3.3.1.4 verifica.m

38

3.3.1.5 corrigir.m

38

3.3.1.6 pos_carro.m

38

3.3.1.8

pos_otima.m

39

3.3.1.9

frente_do.m

39

3.3.1.10 encontre_reta.m

39

4 RESULTADOS

40

5 CONSIDERAÇÕES FINAIS

43

5.1 CONCLUSÃO

43

5.2 SUGESTÕES PARA TRABALHOS FUTUROS

43

6

REFERÊNCIAS BIBLIOGRÁFICAS

45

APÊNDICE A - HARDWARE E MICROCONTROLADORES

46

APÊNDICE B - CÓDIGO IMPLEMENTADO NO MATLAB

53

11

1 INTRODUÇÃO

A robótica autônoma é uma área de pesquisas que vem se desenvolvendo bastante nos últimos anos. Os robôs tem auxiliado o homem em diversas tarefas, tais como a exploração espacial e o auxílio a pessoas com deficiências físicas. Diversos algoritmos vem sendo desenvolvidos para controlar esses robôs, muitos deles se utilizam de informações coletadas “a priori” para planejar, antes da execução, todos os movimentos do início ao fim da tarefa. Outros algoritmos utilizam dados coletados do ambiente, em tempo real, através de sensores, para decidir qual será o próximo movimento (comportamento reativo) (HEINEN, 1999; OSÓRIO,

1999).

Para obter resultados de forma abrangente em tempo real ao implementar sensores em um robô autônomo podemos fazer uso da ferramenta de visão computacional. A visão computacional vem sendo utilizada cada vez mais devido a sua imensa flexibilidade de aplicações. É possível através dela, identificar formas, cores e tonalidades, e trabalhar com os dados obtidos de forma que o robô consiga identificar sozinho no ambiente os objetos necessários para a sua interação, dando a ele um comportamento reativo. Este trabalho consiste em projetar e implementar uma plataforma utilizando de ferramentas de visão computacional que em conjunto com uma base robótica microcontrolada faz com que um jogo que simula uma partida de futebol seja implementado. O jogo de futebol robótico proposto por este trabalho tem um objetivo diferente do convencional: além de fazer com que a bola alcance a área delimitada que representa o gol, é necessário desenvolver um algoritmo de controle de trajetória eficiente, dadas as limitações físicas do projeto. O sistema a ser desenvolvido terá o objetivo de atuar junto às plataformas robóticas já existentes no Laboratório de Automação Inteligente do Instituto Federal Fluminense; tais plataformas são microcontroladas. O sistema desenvolvido deve localizar estas plataformas robóticas em um espaço físico delimitado, calcular parâmetros de posição e ângulo em relação a posição em que se encontram, e transmitir estes parâmetros ao microprocessador da própria plataforma, possibilitando que cada estudante desenvolva seu próprio algoritmo e insira dentro

12

das plataformas robóticas a fim de tornar os movimentos da plataforma robótica mais eficientes para um determinado objetivo, como por exemplo, ao executar movimentos buscando atingir a bola em direção ao gol. Após a implantação do algoritmo de processamento de imagem, transmissão e recepção de dados via RF, a plataforma robótica servirá de ferramenta para os estudantes de engenharia no aprendizado e prática de controle, possibilitando que cada estudante possa compreender e aprimorar seus conhecimentos em controle e automação. O algoritmo de processamento de imagem possui o objetivo de implementar a estrutura de visão computacional ao sistema. Através da visão computacional será possível obter informações de imagens, e através destes dados extraídos da imagem será possível fazer com que o robô autônomo determine o erro existente entre sua posição atual e a posição ideal, e a correção necessária para que este erro seja nulo ou próximo de zero. Robôs autônomos geralmente são utilizados para realizar determinada tarefa em um ambiente em que não existe estrutura dedicada ao funcionamento do robô e não existe auxílio humano. Especificamente neste projeto, o robô autônomo deve realizar a tarefa de empurrar a bola em direção ao gol, completando o objetivo determinado. Para isso, a única interface sensorial que este robô dispõe para identificar o mundo exterior são os parâmetros adquiridos através da visão computacional. Dentre os possíveis conhecimentos que os estudantes poderão explorar ao trabalhar com este sistema, encontram-se áreas como algoritmos, linguagem de programação, técnicas de programação, microcontroladores, robótica, controle, entre outros.

1.1 OBJETIVO

1.1.1 Objetivo Geral

Projetar e construir uma plataforma robótica dinâmica de modo a receber sinais contendo parâmetros via radio frequência e conforme a variação destes parâmetros aplicar uma ação de controle de modo que a plataforma robótica se desloque em uma trajetória permitindo que a bola seja atingida e role em direção ao

13

marcador que simboliza o gol.

1.1.2 Objetivos Específicos

Montar uma plataforma robótica física, incluindo estrutura física, hardware e lógica implementada no microcontrolador. Prover a captura de imagens em bancada projetada, que permita a visualização de todo a área de atuação do projeto em tempo real. Promover programação adequada a inserção de parâmetros de ajustes característicos do ambiente de modo que seja simples executar o sistema em diversas condições de iluminação. Analisar o comportamento do sistema em relação às estratégias aplicadas. Verificar se o controle aplicado consegue atender aos requisitos estipulados no projeto.

1.2 JUSTIFICATIVA

Através desta plataforma será possível desenvolver um ambiente de aprendizagem baseado em dispositivos robóticos, permitindo a prática de atividades pedagógicas, visto que o cenário universitário atual exige a presença de recursos tecnológicos didáticos para que se torne encorajador o aprendizado relacionado às ferramentas e tecnologias disponíveis no mercado.

1.3 ORGANIZAÇÃO DOS CAPÍTULOS

Capítulo 1: Introdução: Neste capítulo é apresentada uma contextualização dos temas abordados na visão computacional. Expõem-se os objetivos, justificativas e a forma como o tema é organizado e abordado nos capítulos.

Capítulo 2: Revisão da Literatura. Neste capítulo faz-se uma breve introdução sobre os elementos utilizados no projeto, tais como transmissor e receptor de RF, PWM, Microcontroladores e Comunicação serial, seu surgimento e

14

sua evolução, áreas de atuação e definição do conceito IA para que o leitor se sinta

familiarizado com o tema.

Capítulo 3: Desenvolvimento. Neste capítulo é apresentado e detalhado o

desenvolvimento do projeto. Cada parte do processo de elaboração é aqui descrito,

tais como materiais utilizados na prototipagem, projeto de hardware e programação.

Capítulo 4: Resultados. Neste capítulo são apresentados através de gráficos,

tabelas e quadros, os resultados obtidos após a implementação do sistema.

Capítulo 5: Considerações finais. Este capítulo apresenta a conclusão e

sugestões para trabalhos futuros.

Conclusão. Neste utiliza-se os resultados apresentados para fazer uma

análise e responder se os objetivos estipulados na apresentação deste trabalho

foram alcançados e o quanto se alcançou.

Sugestões para trabalhos futuros. Neste capítulo são apresentadas

algumas sugestões pra trabalhos futuros, de modo a aproveitar os dados gerados e

a metodologia aplicada no desenvolvimento deste trabalho.

Capítulo 6: Referências Bibliográficas. Lista os trabalhos que serviram

como base para o desenvolvimento desta pesquisa.

Apêndice A: Hardware e Microcontroladores. Apresenta os códigos implementados na programação dos microcontroladores e os desenhos esquemáticos contendo as ligações.

Apêndice B: Código implementado no Matlab. Apresenta os códigos implementados na programação do Matlab.

15

2 REVISÃO DE LITERATURA

Este capítulo contém a revisão de literatura relacionada aos dispositivos e ferramentas utilizados no desenvolvimento do projeto.

2.1 PROCESSAMENTO DE IMAGENS

Atualmente o desenvolvimento de sistemas de informação multimídia, tais como bibliotecas virtuais e catálogos eletrônicos, trouxeram a necessidade de gerenciamento de grandes bancos de dados de imagens. Para que este gerenciamento seja eficaz é necessário o desenvolvimento de metodologias que incorporem técnicas eficientes de acesso para o arquivamento e recuperação da informação. Além disso, a necessidade da utilização de métodos baseados em descrição textual tem introduzido o desenvolvimento de mecanismos para consulta de bases de dados através de imagens-exemplo ou pela especificação da imagem desejada, em termos de cores dominantes, textura e formato dos objetos (RUDECK, 2001; COELHO, 2001; CANCIGLIERI JR, 2001). Uma imagem é formada por diversos pixels. Um pixel é o menor ponto que compõe uma imagem, e através da manipulação seletiva dos pixels de uma imagem, feita através de softwares específicos, é possível efetuar o processamento de imagem utilizando-se técnicas para que se alcance o objetivo determinado. Diversas técnicas de reconhecimento de imagens têm sido apresentadas na literatura e geralmente são validadas através de protótipo de aplicações, pois em um ambiente industrial, raramente obtém-se as condições ideais de iluminação, contraste, posicionamento correto da peça, e do ângulo de obtenção da imagem, além de outros fatores externos que dificultam a interpretação de uma cena (RUDECK, 2001; COELHO, 2001; CANCIGLIERI JR, 2001 apud WEEKS, 1996; RUSS, 1995; YANG &YAN, 2000; CHENG, 2000). Utilizando um modelo de textura compatível com a textura utilizada no objeto o qual se deseja identificar na imagem é possível através de uma simples varredura de pixels efetuada em uma imagem filtrada, identificar a localização do objeto na imagem. Rudeck (2001), Coelho (2001) e Canciglieri Jr (2001) propõem um algoritmo genérico para processamento de imagens com o objetivo de reconhecer padrões. Este algoritmo foi testado com sucesso no reconhecimento de padrões de

16

diferentes tipos de parafusos. O algoritmo aplicado por Rudeck (2001), Coelho (2001) e Canciglieri Jr (2001) é descrito da seguinte forma:

Aquisição Pré-processamento Segmentação Identificação do Objeto Reconhecimento de Padrões

Durante a aquisição da imagem é pertinente destacar que elementos presentes no ambiente, tais como iluminação e posicionamento, e elementos como hardware e software utilizados são de fundamental importância, sendo necessário prestar devida atenção no que diz respeito a fatores externos. O pré-processamento ocorre ao transmitir os dados de imagem para o computador. Nele são feitos ajustes de cor, brilho, contraste e nitidez. Durante a segmentação a imagem é compactada, de forma que o número de informações nela contida seja apenas o necessário para que o objetivo seja cumprido. Isto torna o processamento mais rápido e evita que informações desnecessárias para a realização da tarefa sejam enviadas junto com a imagem capturada para a etapa de identificação do objeto. Na etapa de identificação do objeto, o software irá efetuar comparações das imagens adquiridas com modelos pré-programados e a partir de características do objeto, como seu formato e tamanho, irão determinar dentro daquela imagem, onde está localizado o objeto. Durante o reconhecimento de padrões é feita a comparação do objeto identificado na imagem, com padrões pré-programados via software, e a partir daí poderá ser feita a classificação do objeto.

2.2 ARDUINO

O conceito Arduino surgiu na Itália, em 2005, com objetivo de criar um dispositivo de controle para protótipos construídos de forma menos dispendiosa do que outras soluções disponíveis. O quite de desenvolvimento Arduino é dito uma plataforma de computação física, em que sistemas digitais, ligados a sensores e a atuadores, são capazes de medir variáveis no ambiente físico, realizar cálculos numéricos e tomar decisões lógicas no ambiente computacional e gerar novas variáveis no ambiente físico. A parte central do kit é um microcontrolador, o qual pode ser entendido como a evolução de um microprocessador, na qual ele é

17

ampliado com sistemas de temporização, de aquisição e de comunicação (Da FONSECA, 2011; DE LA VEGA, 2011). Existe um portifólio diversificado com informações disponíveis sobre a capacidade do hardware do Arduino, a linguagem de programação para a sua IDE específica, e fóruns de discussão com experiências de outros desenvolvedores disponível em: www.arduino.cc. Segundo Da Fonseca e De La Veja (2011), um grande diferencial deste kit é a utilização da licença open-source, em que uma comunidade de usuários constantemente explora o sistema com o objetivo de desenvolver e aperfeiçoar projetos que são divulgados livremente.

2.3 TRANSMISSOR E RECEPTOR RF

Existem diversos formas de se efetuar uma comunicação sem fio utilizando Arduino. Uma delas consiste na utilização de módulos de transmissão e recepção de frequências de rádio. Um dos módulos disponíveis no mercado utilizado para prototipagem é o módulo RF 433, cuja montagem é simples e a aplicação é elementar.

O rádio é um recurso tecnológico de telecomunicações utilizado para permitir a

transmissão e recepção de dados pela transcepção de informações previamente codificadas em um sinal eletromagnético. São necessários três elementos para que haja a comunicação: o transmissor, o meio de transmissão e o receptor (PEREIRA,

2014).

Segundo Pereira (2014), existe mais de um modo de transmissão utilizado na comunicação via radiofrequência. O modo simplex é utilizado quando a comunicação é unidirecional no meio da transmissão. Já o modo de transmissão semi duplex, também conhecido como half duplex, é utilizado quando a transmissão é bidirecional, porém os transmissores compartilham o mesmo meio, não podendo transmitir simultaneamente. O modo duplex é aquele em que a comunicação é bidirecional e simultânea.

A modulação de sinal pode ser também de dois tipos, designados como AM e

FM. Na modulação por amplitude, conhecida como AM, o comprimento da onda é da

ordem de metros. Então, são usadas as camadas atmosféricas para a propagação

18

por reflexão. Por outro lado, na modulação por frequência, FM, o comprimento de onda é bem inferior, da ordem de centímetros, o que a torna muito penetrante apesar de pouco refletida (PEREIRA, 2014, apud, VIEIRA, 2011).

Transmissor:

O módulo transmissor possui 3 pinos, sendo 2 utilizados para a alimentação e 1 pino dedicado a receber os dados que serão transmitidos via RF. Para transmitir os dados basta enviá-los utilizando a funcionalidade da comunicação serial do Arduino. Também possui um orifício no circuito no qual poderá ser soldada uma antena para ampliar o alcance do sinal. Na Figura 1 é apresentado um modelo de transmissor de RF e suas características.

Figura 1: Transmissor de RF

de RF e suas características. Figura 1: Transmissor de RF Fonte: www.blog.filipeflop.com (2015). O transmissor

Fonte: www.blog.filipeflop.com (2015).

O transmissor MX-FS-03V, identificado na Figura 1, opera na faixa de frequência de 433,92MHz e pode ser alimentado com tensão entre 3,5Vcc e 12Vcc. Especificações técnicas:

Frequência: 433,92 MHz;

Modelo: MX-FS-03V;

Distância de transmissão: 20m a 200m (depende da tensão);

19

Tensão: 3,5 V ~ 12V;

Dimensões: 19 mm x 19 mm;

Tipo de modulação: AM;

Potência de transmissão: 10mW;

Antena: 25 cm;

Velocidade de transmissão: 4 Kb/s

Receptor:

O módulo receptor possui 4 terminais, sendo 2 utilizados exclusivamente para

a alimentação e 2 utilizados para a transmissão de dados, não havendo diferença

entre estes. É possível utilizar apenas um terminal dos dois destinados a transmissão de dados, deixando o outro terminal livre. O módulo receptor também possui um orifício no circuito no qual poderá ser soldada uma antena para ampliar a qualidade de recepção do sinal. A Figura 2 apresenta um modelo de receptor de RF

e suas características.

Figura 2: Receptor de RF

de RF e suas características. Figura 2: Receptor de RF Fonte: www.blog.filipeflop.com (2015). No receptor de

Fonte: www.blog.filipeflop.com (2015).

No receptor de RF identificado na Figura 2 podemos notar a presença de dois pinos dedicados a transmissão de dados. Este receptor opera na faixa de frequência de 433,92 MHz e deve ser alimentado com 5 Vcc. Especificações técnicas:

20

Frequência:433,92MHz;

Modelo:MX-05V;

Tensão: 5VCC;

Corrente: 4 mA;

Sensibilidade: 105db;

Antena: 35 cm;

Dimensões: 30 mm x 17 mm x 7 mm.

2.4 SERVOMOTOR

Servomotor é uma máquina que recebe um sinal de controle, verifica a posição original, e depois atua no sistema em busca da posição desejada. É um motor que não gira indefinidamente, pode fazer a rotação de apenas 180 graus, mas são extremamente precisos. Ele é constituído por três partes principais: Sistema atuador, sensor e circuito de controle. O primeiro é um motor, geralmente de corrente contínua, e um conjunto de engrenagens que forma uma caixa de redução com uma relação longa, pra aumentar o torque. O sensor é normalmente um potenciômetro acoplado ao eixo do servo, e através da sua resistência, é possível determinar a sua posição. E o circuito de controle é um circuito composto de componentes eletrônicos discretos ou circuitos integrados que tem a capacidade de receber o sinal do sensor e o sinal de controle e posicionar o motor no eixo da direção desejada (ARAÚJO, 2011; PESSOA, 2011; TURCHENSKI, 2011). É possível modificar um servomotor para que o mesmo possua sua rotação contínua, sem que fique limitada aos 180 graus. No interior do servomotor existe um potenciômetro acoplado a uma engrenagem, utilizado para garantir a posição do eixo. Tanto o potenciômetro quanto a engrenagem possuem travas mecânicas que limitam a rotação. Ao retirar estas travas, o motor terá liberdade para girar continuamente. É necessário também modificar o circuito de controle, que é responsável pelo monitoramento do potenciômetro e acionamento do motor visando obter uma posição pré-determinada. Existem servo motores modificados disponíveis no mercado que controlam a velocidade do servo ao invés da posição. O servomotor da marca Parallax na Figura 3 é um exemplo de servomotor modificado de fábrica.

21

Figura 3: Servomotor Parallax

21 Figura 3: Servomotor Parallax Fonte: www.parallax.com (2015) O controle dos servomotores é feito através de

Fonte: www.parallax.com (2015)

O controle dos servomotores é feito através de PWM, assunto que será tratado posteriormente. Porém, o Arduino possui uma biblioteca específica para controle de servomotores. Essa biblioteca se chama Servo.h e possui funções específicas para controle de posição do eixo do servomotor, em que a angulação desejada é inserida, e a saída da função envia um sinal de controle para o motor de forma que a posição desejada seja alcançada. No caso do controle de servomotores modificados, os ângulos inseridos farão com que a velocidade do motor seja modificada. Cada ângulo possui velocidade e sentido de rotação específica, e são obtidos experimentalmente para cada servomotor. Por exemplo, ao passar 93º como argumento para a função, um servomotor modificado ficaria parado. Ao elevar essa angulação para 95º esse motor iria girar em sentido horário bem devagar. Ao reduzir essa angulação para 70º, o motor giraria em sentido anti-horário com velocidade elevada, possivelmente atingiria a sua velocidade máxima.

22

2.5 PWM - MODULAÇÃO POR LARGURA DE PULSO

PWM (Modulação por Largura de Pulso) é um método de emularmos um comportamento analógico a partir de uma porta digital. Para isto utilizamos um chaveamento sobre a porta, ativando-a e desativando-a em um período de tempo. Geramos deste modo, uma onda retangular, em que o tempo do sinal em tensão alta é denominado largura de pulso. Ao variarmos a relação entre o tempo da chave ligada e o período de oscilação total, variamos também a tensão média que a carga recebe, ou seja, efetuamos uma modulação da largura do pulso. Na Figura 4, podemos visualizar os pulsos gerados, utilizando a função analogWrite da biblioteca padrão do Arduino, que fornece uma resolução de 8 bits para o controle da tensão de saída (ARAÚJO, 2011; PESSOA, 2011; TURCHENSKI, 2011).

Figura 4: Gráfico PWM.

PESSOA, 2011; TURCHENSKI, 2011). Figura 4: Gráfico PWM. Fonte: (ARAÚJO, 2011; PESSOA, 2011; TURCHENSKI, 2011). 2.6

Fonte: (ARAÚJO, 2011; PESSOA, 2011; TURCHENSKI, 2011).

2.6 COMUNICAÇÃO SERIAL

Por definição, comunicação serial é o processo de enviar dados bit a bit, seqüencialmente, através de um canal de comunicação. A comunicação serial do Arduino tem o objetivo de comunicar o Arduino com um computador ou outros

23

dispositivos. A biblioteca SoftwareSerial possui funções que podem ser utilizadas em conjunto com os módulos de transmissão e recepção de RF para realizar a transmissão de dados sem fio. Essas duas funcionalidades trabalham juntas harmonicamente e não geram conflitos entre si.

24

3 DESENVOLVIMENTO DO PROJETO

Neste capítulo será feita a descrição detalhada dos elementos que constituem o sistema proposto e desenvolvido neste trabalho. É abordado o desenvolvimento de toda a parte física do projeto, incluindo hardware e embarcados, e também é abordada toda a parte de programação do projeto.

3.1 DESING DE HARDWARE E ESTRUTURAS

O hardware foi projetado com base na plataforma arduino, utilizando matriz de contatos e fios conectores para realizar as conexões. Existem dois Arduinos no sistema. Um deles é responsável por receber os parâmetros que são enviados pelo Matlab através da porta serial do computador e enviar estes parâmetros através de radio frequência. Para isso, a placa se conecta ao computador através da porta USB, que serve de ponte para a comunicação serial e alimentção da placa, esta possui um módulo transmissor de rádio frequência de 433Mhz conectado a placa Arduino através do pino 12. O esquemático desta ligação se encontra no Apêndice A - Hardware e Microcontroladores. A parte de hardware projetada para receber os dados foi concebida de modo a funcionar sendo alimentada através de uma bateria de 9V. Este módulo fica localizado acoplado a plataforma robótica, em que tem a função de receber os parâmetros transmitidos via rádio frequência, e de acordo com o tipo de controle implementado, enviar o sinal de correção para os servo-motores. Portanto este Arduino está conectado a dois servo-motores através dos pinos 9 (servo-motor esquerdo) e 10 (servo-motor direito) que movimentam a plataforma, um módulo receptor de rádio frequência de 433MHz através do pino 11, e um led através do pino 12, utilizado para indicar o momento em que a posição ideal para o chute é alcançada de acordo com o algoritmo do exemplo implementado. O esquemático desta ligação se encontra no Apêndice A - Hardware e Microcontroladores. Além destes sistemas, uma Webcam Logitec é utilizada para capturar imagens da área de testes e enviar estes dados para o Matlab. Os marcadores utilizados para identificar o gol, a bola e a plataforma robótica foram escolhidos arbitrariamente entre as cores vermelho, verde e azul, por serem as matrizes de cores que o Matlab utiliza - Matriz RGB. O gol recebeu a cor azul e foi pintado em uma folha de papel

25

utilizando tinta relevo. Após feita a pintura, a peça foi recortada e inserida na área de testes. A bola foi projetada em isopor por ser um material leve e de baixo atrito. Outros materiais emborrachados e metálicos foram utilizados, porém o isopor se tornou o material mais apropriado, de acordo com testes práticos realizados. A bola de isopor foi tingida com tinta para tecido cor verde brilhante. O marcador utilizado para sinalizar a plataforma robótica é no formato de uma estrela de 3 pontas, tomando-se como base para a criação dessa estrela um triângulo isósceles. Este formato é ideal para indicar o sentido no qual se encontra a plataforma robótica, uma vez que os pontos mais próximos indicam a parte de trás da plataforma, e o ponto mais distante indica a frente. O marcador foi confeccionado em papel e isopor. O desenho foi feito utilizando tinta para tecido vermelha, a figura foi fixada em um pedaço retangular de isopor e posicionado em cima de 4 palitos que foram fixados em 4 pontos da plataforma robótica, a fim de esconder as partes coloridas para não serem detectadas na captura de imagem, destacando-se assim apenas o marcador. A plataforma robótica utilizada para a base do carro foi gentilmente cedida pelo Laboratório de Automação Inteligente do Instituto Federal Fluminense, e consiste em uma plataforma fixa de metal contendo dois servomotores independentes conectados a rodas através de um eixo, e uma base esférica para apoio. Um cano de PVC foi cortado e fixado a frente da plataforma e tem o objetivo de empurrar a bola. Os servomotores são modificados de fábrica, de modo a fornecer rotação contínua e forte tração, além de facilitar o controle da velocidade. A Figura 5 mostra o robô montado.

26

Figura 5: Robô montado

26 Figura 5: Robô montado Fonte: Autor. 1- PVC utilizado para tocar a bola. 2- Figura

Fonte: Autor.

1-

PVC utilizado para tocar a bola.

2-

Figura utilizada para identificar o robô e sua posição.

3-

Acrílico utilizado para sustentar os elementos eletrônicos do robô.

4-

Plataforma robótica de metal.

5-

Roda com elástico acoplada a servomotor.

A

base robótica (4) possui um cano de PVC cortado (1) a fim de direcionar a bola

tangencialmente a circunferência do cano. O teto com o marcador vermelho (2) é feito de isopor e fixado com palitos de madeira nas extremidades da estrutura de acrílico (3) que também abriga os elementos do circuito. As rodas de plástico (5) foram adaptadas com elásticos de borracha a fim de melhorar o atrito e evitar derrapagens.

27

A Figura 6 mostra a bola na cor verde e o gol na cor azul utilizados neste

experimento.

Figura 6: Bola e gol

cor azul utilizados neste experimento. Figura 6: Bola e gol Fonte: Autor. 3.2 PROGRAMAÇÃO DOS MÓDULOS

Fonte: Autor.

3.2 PROGRAMAÇÃO DOS MÓDULOS

Neste

item

é

descrita

a

estrutura

utilizada

na

programação

dos

microcontroladores utilizados nos módulos de transmissão e recepção do sistema.

3.2.1 Programação do Módulo de Transmissão

O módulo de transmissão foi programado de modo a transmitir a informação

recebida via comunicação serial da mesma forma como foi recebida. Caso nenhuma

informação for recebida, nenhum dado será transmitido, caracterizando assim uma

comunicação assíncrona.

Este programa foi concebido com a finalidade de servir como exemplo

funcional, e se restringe a transmissão de 8 bytes por vez. Ao receber dados através

da comunicação serial, a taxa de transmissão (baud rate) deverá ser ajustada para

28

9600 bits por segundo. Para fins de desenvolvimento, o programa exibe no monitor serial, caso esteja disponível, a mensagem que foi recebida via comunicação serial. Após receber a informação via comunicação serial, o programa transmite essa informação através do módulo de transmissão de radio frequência conectado ao Arduino. Além disso, toda vez que uma informação é enviada, um led conectado internamente ao pino 13 do Arduino indica a transmissão de dados. A biblioteca

está disponível em:

utilizada

http://www.airspayce.com/mikem/arduino/RadioHead/ (2015) O programa utilizado como exemplo pode ser encontrado no Apêndice A - Hardware e Microcontroladores.

é

a

"RadioHead"

e

3.2.2 Programação do Módulo de Recepção

O módulo de recepção foi programado de modo a receber a informação transmitida pelo módulo de transmissão e disponibilizar o dado para efetuar o controle de velocidade dos motores de acordo com o parâmetro recebido pelo controlador. Um controlador proporcional foi implementado, de forma que quanto maior fosse a diferença entre o ângulo ideal e o ângulo real, maior seria a velocidade dos motores. Tal correção seria aplicada durante um determinado período fixo de tempo, pois tal artifício foi utilizado como forma de contornar um conflito entre bibliotecas do Arduino e o retardo de transporte gerado pelo atraso do computador no tratamento de imagens ao realizar os cálculos e enviar os parâmetros. Sendo assim, os motores só serão configurados pela biblioteca a partir do momento que o ângulo é recebido. Após a configuração, os motores são acionados por um determinado período de tempo fixo, e então são excluídos da memória do programa, precisando de nova configuração quando outro ângulo for recebido. A biblioteca RadioHead também foi utilizada neste programa como forma de substituir a biblioteca VirtualWire que gerava conflitos constantes com a biblioteca Servo. A biblioteca PID não foi utilizada, sendo efetuado o controle através das próprias linhas de comando do programa. Para fins de programação, o programa exibe no monitor serial, caso esteja conectado, o valor recebido via rádio frequência. Para utilizar a biblioteca RadioHead é necessário alterar uma linha em seu código de

29

forma que o timer1 do microcontrolador seja substituído pelo timer2, pois o timer1 é utilizado pela biblioteca Servo.h que controla os motores. No arquivo RH_ASK.cpp, acrescentar a linha "#define RH_ASK_ARDUINO_USE_TIMER2". Este programa também foi desenvolvido como exemplo e está disponibilizado no Apêndice A - Hardware e Microcontroladores.

3.3 PLATAFORMA DE TRATAMENTO DE IMAGEM

O software Matlab® R2011A foi escolhido para efetuar o processamento dos dados capturados através da câmera, retirar destes dados os devidos parâmetros, e enviar estes através da porta de comunicação serial. Basicamente o programa realiza um ciclo que será repetido quantas vezes o usuário determinar. Porém antes de realizar o ciclo de captura, processamento e envio de dados, é necessário efetuar a calibração das cores através de modelos fotografados anteriormente. Isto se faz necessário pois as condições de luminosidade do ambiente podem variar de acordo com o horário do dia, local e condições climáticas no momento em que o programa está sendo executado. Também é necessário abrir um canal de comunicação com a câmera de vídeo e um canal de comunicação serial. Sendo assim, podemos determinar o escopo do programa como sendo:

-Calibração das cores -Abertura de conexão com a câmera de vídeo -Abertura de conexão com a porta serial -Ciclo de captura, processamento e envio de dados -Fechamento da conexão com a porta serial -Fechamento da conexão com a câmera de vídeo É muito importante que as conexões sejam finalizadas, pois conexões em aberto podem resultar em erros nos próximos ciclos de execução. Por exemplo, caso aconteça algum erro de captura de imagem, processamento ou envio de dados durante a realização do ciclo, o Matlab irá interromper a execução do programa sem fechar as portas de conexão (serial e vídeo). Ao tentar executar novamente o programa um erro de comunicação serial será mostrado na tela, tornando-se necessário fechar o Matlab e abrir novamente o trabalho salvo para continuar executando o programa.

30

O ciclo de captura executa diversas funções com o objetivo de encontrar o erro a cada nova captura. O erro, no caso deste estudo, consiste na diferença entre o ângulo da posição ideal e o ângulo de encontro entre as retas; a que define a posição real do carro e a reta ideal que passa sobre o gol, sobre a bola e sobre a posição ideal. A Figura 7 mostra a imagem capturada com as retas calculadas e traçadas pelo Matlab.

Figura 7: Imagem capturada com retas traçadas pelo Matlab.

as retas calculadas e traçadas pelo Matlab. Figura 7: Imagem capturada com retas traçadas pelo Matlab.

Fonte: Autor.

31

A Figura 8 aponta a localização exata na imagem de cada item presente.

Figura 8: Imagem capturada pelo Matlab em detalhes.

Figura 8: Imagem capturada pelo Matlab em detalhes. Fonte: Autor. 1- Asterisco azul utilizado para marcar

Fonte: Autor.

1- Asterisco azul utilizado para marcar a base do robô, calculada pelo Matlab.

2- Reta traçada entre a base e a frente do robô, com o objetivo de indicar a direção do robô

3- Asterisco verde utilizado para indicar a frente do robô.

4- Reta traçada entre a frente do robô e a posição ideal para acertar a bola. 5- Asterisco verde utilizado para indicar a posição ideal, no qual o robô acerta a bola em direção ao gol.

6- Asterisco verde indicando o centro da bola.

7- Reta entre a bola e o centro do gol, utilizada para encontrar a posição ideal.

32

A Figura 9 mostra o ângulo entre a direção do robô e a reta ideal.

Figura 9: Robô e a indicação do ângulo

e a reta ideal. Figura 9: Robô e a indicação do ângulo Fonte: Autor. 1- Ângulo

Fonte: Autor.

1- Ângulo formado entre a reta que indica a direção do robô e a reta ideal que passa pela posição ideal e pela frente do robô.

3.3.1 Funções

Esta seção descreve detalhadamente cada função que foi criada para a utilização no código implementado no Matlab.

3.3.1.1 Calibra_Cores.m

Esta função efetua a leitura de 3 recortes de imagens com exemplos de cores

e em seguida determina as intensidades de cores que estão compreendidas dentro

daquele espectro para a identificação dos marcadores. Ao exibir uma imagem colorida, existem intensidades diferentes de cores diferentes que são característicos da imagem. Ao efetuar a mistura dessas cores em intensidades diferentes, é possível gerar novas cores. A função Calibra_Cores se encarrega de efetuar a busca dos valores de intensidade mínimos e máximos para as cores vermelho, verde e azul, para identificar o carro, a bola e o gol na imagem. Sendo assim, esta função gera duas matrizes, uma matriz com os valores

33

mínimos de intensidade e outra com os valores máximos de intensidade, em que as linhas representam as cores vermelho, verde e azul e as colunas são referentes ao carro, bola e gol. Estes valores serão utilizados posteriormente ao efetuar a varredura, em busca dos marcadores da imagem. Por exemplo: Suponhamos hipotéticamete que uma imagem do marcador do robô seja capturada e sua cor no ponto mais claro é formada por 10% de azul, 80% de vermelho e 0% de verde, e por 20% de azul, 85% de vermelho e 5% de verde no ponto mais escuro. Sendo assim, a matriz dos valores mínimos é indicada pelo Quadro 1:

Quadro 1: Matriz dos valores mínimos

 

ROBÔ

BOLA

GOL

VERMELHO

80%

indiferente

indiferente

VERDE

0%

Indiferente

Indiferente

AZUL

10%

indiferente

Indiferente

Fonte: Autor.

E a matriz dos valores máximos é indicado pelo Quadro 2:

Quadro 2: Matriz dos valores máximos

 

ROBÔ

BOLA

GOL

VERMELHO

85%

indiferente

indiferente

VERDE

5%

Indiferente

Indiferente

AZUL

20%

indiferente

Indiferente

Fonte: Autor.

Obviamente neste exemplo não estamos considerando valores de intensidade de cores para a bola e para o gol, portanto neste exemplo hipotético estes valores são indiferentes.

3.3.1.2 captura.m

A função captura.m é utilizada para efetuar a captura da imagem e efetuar uma varredura de forma que o retorno desta função sejam 3 matrizes representando 3 imagens diferentes, já filtradas em preto e branco: A matriz contendo apenas o marcador do carro (Img_Red), a matriz contendo apenas o marcador da bola (Img_Green), e a matriz contendo apenas o marcador do gol (Img_Blue).

34

Os parâmetros recebidos por esta função são as matrizes de padrões máximo e mínimo definidas na função Calibra_Cores, pois além de efetuar a captura, esta função já faz uma varredura na imagem a fim de filtrar os objetos. Esta filtragem é feita pixel a pixel, comparando se o valor do pixel da imagem está compreendido entre os valores máximos e mínimos de cores calibrados anteriormente. Caso essa afirmação seja verdadeira, este pixel é copiado para uma outra imagem. Caso contrário, um pixel preto é utilizado para substituir aquele pixel cuja cor não se enquadra nos limites calibrados.

3.3.1.3 varredura.m

Realiza 8 varreduras em todos os sentidos e direções possíveis na imagem, após reconhecer o objeto e transformar a imagem em preto e branco de forma a sempre identificar o primeiro pixel branco. Esta função foi concebida para encontrar os 3 pontos que caracterizam as extremidades do triângulo marcador do carro. Esta função retorna 8 pontos, e no geral, estes 8 pontos possuem 3 valores distintos que se repetem. A Figura 10 mostra um triângulo.

Figura 10: Triângulo de extremidades 1, 2 e 3.

triângulo. Figura 10: Triângulo de extremidades 1, 2 e 3. Fonte: Autor Sabendo-se que podem ser

Fonte: Autor

Sabendo-se que podem ser efetuadas 8 tipos distintos de varreduras, o Quadro 3 indica em qual das extremidades do triângulo estará o primeiro pixel a ser encontrado.

35

Quadro 3: Relação entre varreduras e localização de pixels (Ref. Figura 10)

Direção da Varredura

Primeiro pixel encontrado

Direita para Esquerda Cima para Baixo

1

Direita para Esquerda Baixo para Cima

3

Esquerda para Direita Cima para Baixo

1

Esquerda para Direita Baixo para Cima

2

Cima para Baixo Direita para Esquerda

3

Baixo para Cima Direita para Esquerda

3

Cima para Baixo Esquerda para Direita

1

Baixo para Cima Esquerda para Direita

2

Fonte: Autor

Como podemos observar apenas 3 valores referentes ao primeiro pixel encontrado de cada vértice serão encontrados, e deverão se repetir entre os 8 valores coletados através da varredura. Se a varredura coletar mais de 3 valores distintos pode significar erro na aquisição de imagens ou na maioria dos casos dois pixels muito próximos. Para os casos em que pixels muito próximos, relativos ao mesmo ponto, são detectados, existe a função corrigir.m que pode ser utilizada para converter a posição de dois pixels diferentes e próximos, dentro de um raio específico, em uma posição única. Para ilustrar melhor, tomaremos como exemplo a Figura 11(a):

36

Figura 11(a): Ilustração de bola em formato de pixels

36 Figura 11(a): Ilustração de bola em formato de pixels Fonte: Autor. A figura 11(b) representa

Fonte: Autor.

A figura 11(b) representa uma circunferência ampliada, ao ponto que consegue-se observar cada pixel que forma esta imagem. Ao efetuar a primeira varredura (da esquerda para a direita, de cima para baixo) o primeiro pixel a ser encontrado e o pixel da linha 3 coluna 4, conforme ilustra a figura 11(b):

Figura 11(b): Ilustração da primeira varredura.

11(b): Figura 11(b): Ilustração da primeira varredura. Fonte: Autor. Seguindo este mesmo raciocínio, a figura 12

Fonte: Autor.

Seguindo este mesmo raciocínio, a figura 12 mostra a seqüência completa das varreduras efetuadas:

37

Figura 12: Seqüência de varreduras efetuadas.

37 Figura 12: Seqüência de varreduras efetuadas. Fonte: Autor. No caso da Figura 12, oito varreduras
37 Figura 12: Seqüência de varreduras efetuadas. Fonte: Autor. No caso da Figura 12, oito varreduras
37 Figura 12: Seqüência de varreduras efetuadas. Fonte: Autor. No caso da Figura 12, oito varreduras
37 Figura 12: Seqüência de varreduras efetuadas. Fonte: Autor. No caso da Figura 12, oito varreduras
37 Figura 12: Seqüência de varreduras efetuadas. Fonte: Autor. No caso da Figura 12, oito varreduras
37 Figura 12: Seqüência de varreduras efetuadas. Fonte: Autor. No caso da Figura 12, oito varreduras
37 Figura 12: Seqüência de varreduras efetuadas. Fonte: Autor. No caso da Figura 12, oito varreduras
37 Figura 12: Seqüência de varreduras efetuadas. Fonte: Autor. No caso da Figura 12, oito varreduras

Fonte: Autor.

No caso da Figura 12, oito varreduras encontraram 8 pixels diferentes por se tratar de uma circunferência. Ao efetuar as 8 varreduras em triângulos, é possível que mais de 3 pixels sejam identificados como pontos, caso estejam muito próximos, como podemos ver na Figura 13. Neste caso, dois pixels muito próximos representam um único ponto.

Figura 13: Pixels encontrados ao efetuar varredura em um triângulo

próximos representam um único ponto. Figura 13: Pixels encontrados ao efetuar varredura em um triângulo Fonte:

Fonte: Autor

38

3.3.1.4 verifica.m

A função verifica.m é utilizada para verificar se a função varredura.m identificou os 3 pontos distintos referentes ao triângulo marcador do carrinho. Caso a função identifique mais ou menos de 3 pontos distintos, a mesma retorna o valor 1

(erro=1). Caso a função identifique os 3 pontos distintos sem erro, o valor de retorno

é 0 (erro=0).

3.3.1.5 corrigir.m

Caso sejam capturados mais ou menos de 3 pontos ao tentar identificar o marcador do carro, a função corrigir.m poderá ser utilizada para aproximar os parâmetros. A função recebe um vetor contendo 8 pontos, e um raio de ação (em pixels) como parâmetros. Caso pontos muito próximos sejam capturados, é possível determinar um raio para que todos os pontos encontrados dentro deste raio sejam substituídos pelo valor médio entre eles. O valor para o raio de ação ideal encontrado experimentalmente no sistema implementado pelo autor foi de 10 pixels.

3.3.1.6 pos_carro.m

Esta função tem o objetivo de substituir o vetor com 8 pontos responsável por identificar o carro, que foi obtido através da varredura da imagem em todas as direções, por uma matriz 3x2 que contém apenas os pontos necessários, no qual cada linha representa um ponto diferente e cada coluna representa um eixo no plano (x e y). Em outras palavras, quando o vetor de 8 pontos é formado, ele recebe pontos repetidos. Quando a matriz 3x2 é criada pela função pos_carro, esses pontos repetidos são eliminados, restando somente os 3 pontos essenciais para a identificação da posição do carro na imagem.

3.3.1.7 pos_centro.m

Esta função realiza a varredura em uma imagem preto e branco. Ao identificar

o objeto, a função calcula o centro a partir dos 8 pontos encontrados após efetuar a

39

varredura da imagem.

3.3.1.8 pos_otima.m

Esta função encontra a equação da reta que passa através do gol e da bola. Após encontrar a equação, a função calcula a posição ideal para o carro empurrar a bola em trajetória retilínea até o gol, de forma que a posição ideal é um prolongamento desta reta, acrescido dos parâmetros raio da bola e raio do pára- choque do carrinho. Para nível de desenvolvimento, esta função pode também exibir

a reta ótima sobre a imagem capturada.

3.3.1.9 frente_do.m

Esta função compara os três pontos adquiridos através do marcador do carro,

e identifica qual deles representa a frente do carro, através da comparação entre as

distâncias entre os pontos. Visto que o marcador é um triângulo isósceles, o ponto mais distante dos outros dois representa a frente do carro.

3.3.1.10 encontre_reta.m

Esta função recebe dois pontos como parâmetros e retorna a equação da reta entre esses pontos. É utilizada por exemplo para encontrar a reta ideal, que passa pelo ponto que representa a frente do carro e a posição ideal, ou mesmo a reta que determina a direção do carro

40

4 RESULTADOS

Alguns problemas ocorreram no desenvolvimento deste projeto. O conflito de bibliotecas devido a utilização do mesmo timer do microcontrolador merece destaque. Este problema foi contornado substituindo-se a biblioteca virtualwire.h pela biblioteca radiohead.h. Ambas são utilizadas para facilitar a programação do microcontrolador junto a módulos de comunicação via rádio frequência, porém a biblioteca virtualwire.h conflitava com a biblioteca servo.h pois ambas utilizam o timer1 para efetuar a temporização. Esta biblioteca foi substituída pela biblioteca radiohead.h que possui uma linha de comando interna que pode alterar o seu funcionamento, de modo que o timer1 seja substituído pelo timer2. Embora este problema tenha sido contornado, ele ainda existe de forma que no instante em que os servomotores estão trabalhando, não é possível utilizar a recepção de dados via RF. O atraso gerado pelo processamento de imagem lento, fez com que os parâmetros fossem enviados em intervalos de tempo longos, o que permitiu definir um tempo exato para que o motor permanecesse ligado e depois fosse desligado para receber os dados. Porém, caso códigos de processamento de dados mais eficientes sejam implementados, esta solução não será funcional. Sugere-se que não se utilize a biblioteca servo.h para controlar os servomotores, e seja implementado o comando através do envio de sinal PWM manualmente. Os servomotores possuem um bom resultado quando submetidos ao controle proporcional. Porém sua velocidade é muito limitada. É possível substituir os servomotores por motores de corrente contínua, uma vez que a bola utilizada no jogo é constituída de isopor, e não necessita de muita força para ser deslocada. A utilização de motores de corrente contínua tornaria o sistema mais dinâmico. O algoritmo de controle PID foi implementado no módulo de recepção de parâmetros, porém os ganhos integral e derivativo foram ajustados para zero. Isto se fez necessário pois o retardo de transporte devido ao longo intervalo de tempo entre a aquisição de parâmetros impediu a implementação de um controlador PID. Este algoritmo de controle foi implementado sem a utilização de bibliotecas especializadas. O controle consiste em corrigir o ângulo de forma proporcional ao erro, sendo assim, quanto mais próximo o ângulo do carro estiver da direção ideal, mais devagar ocorrerá o giro dos motores. Dada a precisão pouco acurada na aquisição de parâmetros, não há garantia do erro assumir o valor zero, mas um valor

41

próximo de zero. Esta faixa é definida como parâmetro no controlador, estando ajustada para ±1°. O gráfico abaixo mostra a variação de ângulo entre a direção da plataforma robótica e a bola. O último ponto é o momento no qual considera-se o ângulo ideal por ser muito próximo do desejado, 0°. A seqüência de imagens foi retirada das filmagens do teste, e ilustram perfeitamente os resultados finais do projeto, apresentados na Figura 15 e o gráfico apresentado na Figura 14 mostra a retroação do erro ao longo do tempo.

Figura 14: Gráfico ângulo X tempo

na Figura 14 mostra a retroação do erro ao longo do tempo. Figura 14: Gráfico ângulo

Fonte: Autor.

42

Figura 15: Imagens extraidas da filmagem do teste

Figura 15 (a)

15: Imagens extraidas da filmagem do teste Figura 15 (a) Figura 15 (b) Figura 15 (c)

Figura 15 (b)

extraidas da filmagem do teste Figura 15 (a) Figura 15 (b) Figura 15 (c) Figura 15

Figura 15 (c)

filmagem do teste Figura 15 (a) Figura 15 (b) Figura 15 (c) Figura 15 (d) Figura

Figura 15 (d)

Figura 15 (a) Figura 15 (b) Figura 15 (c) Figura 15 (d) Figura 15 (e) Figura

Figura 15 (e)

(a) Figura 15 (b) Figura 15 (c) Figura 15 (d) Figura 15 (e) Figura 15 (f)

Figura 15 (f)

(b) Figura 15 (c) Figura 15 (d) Figura 15 (e) Figura 15 (f) Figura 15 (g)

Figura 15 (g)

(c) Figura 15 (d) Figura 15 (e) Figura 15 (f) Figura 15 (g) Fonte: Autor. A

Fonte: Autor.

A Figura 15 (a) representa o primeiro ponto do gráfico, a Figura 15 (b) representa o segundo ponto, e assim sucessivamente. Quando determinada angulação bem próxima a ideal é atingida, como na Figura 15 (e), o algoritmo interno do robô faz com que um led localizado na parte inferior do robô comece a piscar - Figura 15 (f) - indicando a posição ideal para atingir a bola no melhor ângulo - Figura 15 (g).

43

5 CONSIDERAÇÕES FINAIS

Neste capítulo são apresentadas as conclusões dos resultados obtidos e sugestões para trabalhos futuros.

5.1 CONCLUSÃO

A realização do projeto pode ser considerada um sucesso, em virtude dos desafios encontrados no decorrer do desenvolvimento. Com o sistema desenvolvido é possível identificar marcadores em objetos utilizando visão computacional, enviar dados via rádio frequência de um computador para um sistema microcontrolado e aplicar uma estratégia de controle, conforme o sistema proposto inicialmente. Embora tenha atendido ao propósito inicial, o desenvolvimento do projeto encontrou dois pontos a serem considerados. O primeiro deles é o tempo necessário para processar todas as informações referentes aos parâmetros. Uma vez que cálculos complexos são realizados e varreduras de imagem são feitas, a capacidade de processamento necessária para que o sistema possua uma resposta rápida aumenta. Com isso foi possível enviar parâmetros a cada intervalo de 1 segundo a 1 segundo e meio. Outro fator a ser considerado é o conflito de bibliotecas, que impediu a utilização do controle dos servomotores e o recebimento de parâmetros via RF ao mesmo tempo. Estes dois itens em conjunto tornaram difícil de se utilizar um controlador PID, sendo utilizado apenas um controlador proporcional para a demonstração do sistema.

5.2 SUGESTÕES PARA TRABALHOS FUTUROS

Algumas considerações devem ser feitas para futuros projetos a serem desenvolvidos com base neste sistema. Primeiramente é necessário diminuir o tempo de processamento da imagem e da aquisição e cálculo de parâmetros. Isto pode ser feito com o aperfeiçoamento das funções descritas neste trabalho e a utilização de um hardware com maior capacidade de processamento. Estas ações

44

tornariam o sistema mais rápido e dinâmico, evitando problemas com retardo de transporte. Recomenda-se a substituição dos servomotores por motores de corrente contínua. Embora os servomotores sejam mais simples de se controlar, não possuem velocidade o suficiente para fazer a bola se mover rapidamente. Neste tipo de sistema a força contida em um servomotor não é necessária para deslocar a bola com uma velocidade apropriada. Controlar a velocidade dos motores utilizando diretamente o PWM, ao invés de utilizar uma biblioteca específica. Isso poderá evitar futuros conflitos de bibliotecas. Utilizar os registradores do microcontrolador para efetuar operações de forma mais rápida. Desenvolver um software específico que permita a calibração e utilização do sistema de forma simples e intuitiva.

45

6 REFERÊNCIAS BIBLIOGRÁFICAS.

ARAÚJO, Fabiano Guilherme Prado; PESSOA, Igor Rodrigues; TURCHENSKI, Rafael Góes. Desenvolvimento de um Robô Perseguidor de Objetos. 2011.

DA FONSECA, Erika GP; DE LA VEGA, Alexandre S. Tutorial sobre Introdução a Projetos Utilizando o kit de Desenvolvimento Arduino. 2011.

HEINEN, Farlei J.; OSÓRIO, Fernando Santos. Salão de Iniciação Científica. Livro de resumos. Porto Alegre : UFRGS/PROPESQ, 1999, Disponível em:

http://hdl.handle.net/10183/100179. Acesso em: 19/01/2016.

MIRANDA, Alan Tavares; DE ALBUQUERQUE, Márcio Portes; DE ALBUQUERQUE, Marcelo Portes. Introdução ao MatLab. Centro Brasileiro de Pesquisas Físicas, CBPFNT-002/2007, 2007.

PEREIRA, Eduardo Henrique Hortencio. Soluções inteligentes e de baixo custo para a automação residencial utilizando smartphones. 2014

RUDEK, Marcelo; COELHO, Leandro dos Santos; CANCIGLIERI JR, Osíris. Visão computacional aplicada a sistemas produtivos: fundamentos e estudo de caso. XXI Encontro Nacional de Engenharia de Produção-2001, Salvador, 2001.

46

APÊNDICE A HARDWARE E MICROCONTROLADORES

Código implementado no módulo transmissor de RF:

// ask_transmitter.pde // -*- mode: C++ -*- // Simple example of how to use RadioHead to transmit messages // with a simple ASK transmitter in a very simple way. // Implements a simplex (one-way) transmitter with an TX-C1 module

#include <RH_ASK.h> #include <SPI.h> // Not actually used but needed to compile

RH_ASK driver;

void setup()

{

Serial.begin(9600);

if (!driver.init()) Serial.println("init failed");

// Debugging only

pinMode(13,OUTPUT);

}

void loop()

{

if (Serial.available())

{

 

char recebido[8]=""; Serial.readBytes(recebido, 8); Serial.println(recebido); driver.send((uint8_t *)recebido, strlen(recebido)); driver.waitPacketSent();

digitalWrite(13,1);

delay(200);

digitalWrite(13,0);

}

//char recebido[8]={'1', '2', '3', '4', '5', '6', '7', '8'};

}

47

Código implementado no módulo receptor de RF:

#include <RH_ASK.h> #include <SPI.h> // Not actualy used but needed to compile #include <Servo.h>

float cp, cd,kp,kd, ki,e,e0,t,t0,vp,sp,dir,k1,k2; float bias=0.0; float pid,ci; float angulo; char texto[8]; int i;

RH_ASK pacote;

Servo Motor_e; //Motor esquerdo Servo Motor_d; //Motor direito

int pos; long oldPosition = -999;

//Caso d: Giro para a direita

//Caso e: Giro para a esquerda //Caso f: Anda para frente //Caso r: Anda de ré //Caso p: Fica parado void movimento(char lado)

{

switch (lado)

{

case 'd':

Motor_d.write(92);

position in variable 'pos'

Motor_e.write(94);

delay(20);

to reach the position break;

case 'e':

Motor_e.write(94);

position in variable 'pos'

Motor_d.write(92);

delay(20);

to reach the position break;

case 'f':

Motor_e.write(180);

position in variable 'pos'

Motor_d.write(0);

delay(20);

to reach the position break;

case 'r':

// in steps of 1 degree // tell servo to go to

// waits 15ms for the servo

// tell servo to go to

// waits 15ms for the servo

// tell servo to go to

// waits 15ms for the servo

48

Motor_e.write(0);

position in variable 'pos'

Motor_d.write(180);

delay(20);

to reach the position break;

case 'p':

Motor_e.write(93);

position in variable 'pos'

Motor_d.write(93);

delay(20);

to reach the position break;

}

}

//

tell

servo

to

go

to

// waits 15ms for the servo

// tell servo to go to

// waits 15ms for the servo

void chute_a_gol(Servo* MdServo, Servo* MeServo)

{

 

MeServo->detach(); MdServo->detach();

digitalWrite(13,HIGH);

delay(1000);

for(int j=0;j<=20;j++)

{

digitalWrite(12,HIGH);

delay(100);

digitalWrite(12,LOW);

delay(100);

}

for(int j=0;j<=50;j++)

{

digitalWrite(12,HIGH);

digitalWrite(13,LOW);

delay(50);

digitalWrite(12,LOW);

digitalWrite(13,HIGH);

delay(50);

}

digitalWrite(12,HIGH);

digitalWrite(13,LOW);

delay(3000);

MeServo->attach(9);

MdServo->attach(10);

delay(100);

MdServo->write(0);

MeServo->write(180);

delay(2000);

digitalWrite(12,LOW);

}

void controle(Servo* MdServo, Servo* MeServo, double angulo)

{

49

float newPosition = angulo; if (newPosition != oldPosition) { oldPosition = newPosition; //Serial.println(newPosition);

}

vp=newPosition; //sp= map(analogRead(A9), 0, 1023, 0, 5000);

sp=0;

kp=0.05;

ki=0.0;

kd=0.0;

//vp= map(analogRead(A0), 0, 1023, 0, 255); e=sp-vp;

cp=kp*e;

//ci=ki*((e+e0)/2)*((t-t0)/1000)+ci;

//cd=kd*(e-e0)/((t-t0)/1000);

if(ci>6) ci=6; if(ci<-6) ci=-6; if (cd>4) cd=4; if (cd<-4) cd=-4; pid=cp+ci+cd+bias;

if (pid>4) pid=4; if (pid<-4) pid=-4; if (pid>-1 && pid<0) pid=-1; if (pid<1 && pid>0) pid=1;

if (e<3 && e>-3 && e0<3 && e0>-3)

{

chute_a_gol(MdServo,MeServo);

}

else

{

MdServo->write(93+pid);

MeServo->write(93+pid);

}

e0=e;

t0=t;

t=millis();

Serial.print("\t SP = "); Serial.print(sp); Serial.print("\t VP = "); Serial.print(vp); Serial.print("\t PID = "); Serial.println(pid); Serial.print("\t k1 = ");

Serial.println(k1);

Serial.print("\t k2 = ");

Serial.println(k2);

Serial.print("\t angulo = "); Serial.println(angulo);

delay(1);

//parseInt()

50

}

void setup()

{

Serial.begin(9600); // Debugging only Serial.println("setup"); if (!pacote.init()) Serial.println("init failed");

pinMode(12,OUTPUT);

pinMode(13,OUTPUT);

}

ci=0;

bias=0;

e=0;

e0=e;

t=millis();

t0=t;

uint8_t buf[RH_ASK_MAX_MESSAGE_LEN]; uint8_t buflen = sizeof(buf);

void loop()

{

if (pacote.recv(buf, &buflen)) // Non-blocking

{

for (i = 0; i < buflen; i++)

{

texto[i]=buf[i]; Serial.print(texto[i]); Serial.print(" ");

}//for

Serial.println(""); angulo=atof(texto); Serial.print("Angulo: "); Serial.print(angulo); Serial.println(""); Motor_e.attach(9); //Motor esquerdo Motor_d.attach(10); //Motor direito controle(&Motor_d, &Motor_e, angulo);

delay(500);

Motor_e.detach();

Motor_d.detach();

}//loop

}

51

51

52

52

53

APÊNDICE B CÓDIGO IMPLEMENTADO DO MATLAB

Funções:

video.m

vid = videoinput('winvideo',1);% abre a conexção com a camera de video %preview(vid) % abre uma janela com a camera A = getsnapshot(vid); % obtem um quadro do video (figura RGB) delete(vid) imshow(A)

verifica.m

%vet_pos=[pos1 pos2 pos3 pos4 pos5 pos6 pos7 pos8]; %Vetor de posições [vert hor] %vet_pos_V=[pos1(1) pos2(1) pos3(1) pos4(1) pos5(1) pos6(1) pos7(1) pos8(1)]; %Vetor de posições verticais %vet_pos_H=[pos1(2) pos2(2) pos3(2) pos4(2) pos5(2) pos6(2) pos7(2) pos8(2)]; %Vetor de posições horizontais

function [erro1] = verifica(vet_pos)

vet_pos_V=[vet_pos(1,1) vet_pos(2,1) vet_pos(3,1) vet_pos(4,1) vet_pos(5,1) vet_pos(6,1) vet_pos(7,1) vet_pos(8,1)]; vet_pos_H=[vet_pos(1,2) vet_pos(2,2) vet_pos(3,2) vet_pos(4,2) vet_pos(5,2) vet_pos(6,2) vet_pos(7,2) vet_pos(8,2)]; %Ordenando os vetores

for k=1:1:7 for i=1:1:7 if vet_pos_V(i) > vet_pos_V(i+1); aux=vet_pos_V(i);

vet_pos_V(i)=vet_pos_V(i+1);

vet_pos_V(i+1)=aux;

end

end

end

for k=1:1:7 for i=1:1:7 if vet_pos_H(i) > vet_pos_H(i+1); aux=vet_pos_H(i);

vet_pos_H(i)=vet_pos_H(i+1);

vet_pos_H(i+1)=aux;

end

end

end

%Verificando valores iguais

total_de_pontos_V=1;

total_de_pontos_H=1;

for k=1:1:7 if vet_pos_V(k+1) ~= vet_pos_V(k)

total_de_pontos_V=total_de_pontos_V+1;

end

54

end

for k=1:1:7 if vet_pos_H(k+1) ~= vet_pos_H(k)

total_de_pontos_H=total_de_pontos_H+1;

end

end

%caso o número de parâmetros recolhidos do triângulo seja maior que 3, %um sinal de erro é gerado

if total_de_pontos_V >3 || total_de_pontos_H >3; erro1=1; %erro de aquisição de parâmetros

else

erro1=0;

end

varredura_intensiva.m

%Efetua a varredura procurando pixels brancos na imagem, pixels brancos %possuem valor 1, enquanto pixels pretos possuem valor 0.

%Esta função recebe como parâmetro a imagem e retorna uma matriz com as %primeiras posições encontradas de acordo com a orientação da varredura

%Cada posição encontrada é apagada em um "raio" de pixels ao redor do ponto %encontrado. Esta função deve ser utilizada tendo como marcador 3 pontos %vermelhos.

function [vet_pos] = varredura_intensiva(Im, raio)

tam=size(Im); %Im(1) == Altruta Im(2) == Largura

%Varredura 1 for V=1:1:tam(1, 1)

%Vertical

for H=1:1:tam(1, 2) %Horizontal if (Im(V,H)== 1)

%pos1 é o primeiro ponto branco encontrado.

pos1=[V,H];

Im(V,H)=0;

%Apaga o ponto na Imagem

for(cont1=(V-floor(raio/2)):1:floor((raio/2)))

for(cont2=floor((H-raio/2)):1:floor((raio/2)))

end

end

end

end

figure (9)

imshow(Im)

break

end

%Varredura 2 for V=1:1:tam(1, 1)

Im(cont1,cont2)=0;

%Vertical

for H=1:1:tam(1, 2) %Horizontal if (Im(V,H)== 1)

55

%pos2 é o segundo ponto branco encontrado.

pos2=[V,H];

%Apaga o ponto na Imagem

for(cont1=(V-floor(raio/2)):1:floor((raio/2)))

for(cont2=floor((H-raio/2)):1:floor((raio/2)))

end

end

end

end

break

end

%Varredura 3 for V=1:1:tam(1, 1)

Im(cont1,cont2)=0;

%Vertical

for H=1:1:tam(1, 2) %Horizontal

if (Im(V,H)== 1)

%pos3 é o terceiro ponto branco encontrado.

pos3=[V,H];

%Apaga o ponto na Imagem

for(cont1=(V-floor(raio/2)):1:floor((raio/2)))

for(cont2=floor((H-raio/2)):1:floor((raio/2)))

end

end

end

end

break

end

Im(cont1,cont2)=0;

vet_pos=[pos1; pos2; pos3]

figure(9);

imshow(Im);

end

varredura.m

%Efetua a varredura procurando pixels brancos na imagem, pixels brancos %possuem valor 1, enquanto pixels pretos possuem valor 0.

%Esta função recebe como parâmetro a imagem e retorna uma matriz com as %primeiras posições encontradas de acordo com a orientação da varredura

function [vet_pos] = varredura(Im)

tam=size(Im); %Im(1) == Altruta Im(2) == Largura

%Varredura da esquerda para a direita de cima para baixo

for V=1:1:tam(1, 1)

%Vertical

for H=1:1:tam(1, 2) %Horizontal if (Im(V,H)== 1)

pos1=[V,H];

56

break

end

end if (Im(V,H)== 1) break; end

%Mensagem caso não seja detectada a imagem:

if V==tam(1, 1) && H==tam(1, 2); vet_pos=[0 0 0 0 0 0 0 0]; pos1=[0 0]; pos2=[0 0]; pos3=[0 0]; pos4=[0 0]; pos5=[0 0]; pos6=[0 0]; pos7=[0 0]; pos8=[0 0]; disp('****Imagem não detectada. Erro detectado durante a varredura.****') break;

end

end

%pos1 é o primeiro ponto branco encontrado.

%Varredura da direita para a esquerda de cima para baixo

for V=1:1:tam(1, 1)

%Vertical

for H=tam(1, 2):-1:1 %Horizontal

if (Im(V,H)== 1)

pos2=[V,H];

break

end

end if (Im(V,H)== 1) break; end

end

%Varredura da esquerda para a direita de baixo para cima

for V=tam(1, 1):-1:1

%Vertical

for H=1:1:tam(1, 2) %Horizontal

if (Im(V,H)== 1)

pos3=[V,H];

break

end

end if (Im(V,H)== 1) break; end

end

%Varredura da direita para a esquerda de baixo para cima

for V=tam(1, 1):-1:1

%Vertical

for H=tam(1, 2):-1:1 %Horizontal if (Im(V,H)== 1)

pos4=[V,H];

break

end

end if (Im(V,H)== 1) break; end

end

57

%-------------------------------------------------------------------

%Varredura de cima para baixo da esquerda para a direita

for H=1:1:tam(1, 2)

%Horizontal

for V=1:1:tam(1, 1) %Vertical if (Im(V,H)== 1)

pos5=[V,H];

break

end

end if (Im(V,H)== 1) break; end

end

%Varredura de cima para baixo da direita para a esquerda

for H=1:1:tam(1, 2)

%Horizontal

for V=tam(1, 1):-1:1 %Vertical

if (Im(V,H)== 1)

pos6=[V,H];

break

end

end if (Im(V,H)== 1) break; end

end

%Varredura de baixo para cima da esquerda para a direita

for H=tam(1, 2):-1:1

%Horizontal

for V=1:1:tam(1, 1) %Vertical if (Im(V,H)== 1)

pos7=[V,H];

break

end

end if (Im(V,H)== 1) break; end

end

%Varredura de baixo para cima da direita para a esquerda

for H=tam(1, 2):-1:1

%Horizontal

for V=tam(1, 1):-1:1 %Vertical if (Im(V,H)== 1)

pos8=[V,H];

break

end

end if (Im(V,H)== 1) break; end

end

vet_pos=[pos1; pos2; pos3; pos4; pos5; pos6; pos7; pos8]; end

pos_otima.m

%Esta função retorna a posição ótima do carrinho para que a bola seja %atingida e acerte o gol, em coordenadas retangulares com o gol como o %centro do plano.

58

%A posição ideal deverá ser a extenção da reta que passa pelo centro do gol %e pelo centro da bola. O ponto ideal é esta reta acrescida dos valores do %raio da bola e do raio do para-choque do carrinho.

function [posicao_otima]=pos_otima(gol, bola, raio_carrinho, raio_bola)

%Função da reta que passa através do gol e da bola:

eq_reta=encontre_reta(gol,bola);

%Encontrando o coeficiente angular e o ângulo da equação da reta:

syms x;

coef_angular=subs(eq_reta,x,1)-subs(eq_reta,x,0);

theta=atan(coef_angular);

%Encontra a posição x ideal:

if gol(1)>bola(1);

x_ideal=bola(1)-(raio_carrinho*cos(theta)+raio_bola*cos(theta));

else

x_ideal=bola(1)+(raio_carrinho*cos(theta)+raio_bola*cos(theta));

end

%Encontra a posição y ideal:

y_ideal=subs(eq_reta,x,x_ideal);

%Retorna as coordenadas ideais:

posicao_otima=[x_ideal y_ideal];

%plota a reta ótima hold on;

plot(gol(1),subs(eq_reta,x,gol(1)),'*',bola(1),subs(eq_reta,x,bola(1)),'*')

%marca no desenho o centro da bola e do gol com asteriscos plot([gol(1) bola(1)], [subs(eq_reta,x,gol(1)),subs(eq_reta,x,bola(1))]) %plota a linha: plot(valores_das_abscissas, valores_das_ordenadas)

end

pos_centro.m

%Esta função recebe a imagem após a aplicação dos filtros %e retorna a posição do centro.

function [pos] = pos_centro(Im) vet_pos=varredura(Im);

vet_pos_V=vet_pos(1,1)+vet_pos(2,1)+vet_pos(3,1)+vet_pos(4,1)+vet_pos(5,1)+

vet_pos(6,1)+vet_pos(7,1)+vet_pos(8,1);

vet_pos_H=vet_pos(1,2)+vet_pos(2,2)+vet_pos(3,2)+vet_pos(4,2)+vet_pos(5,2)+

vet_pos(6,2)+vet_pos(7,2)+vet_pos(8,2);

pos_V=vet_pos_V/8;

pos_H=vet_pos_H/8;

pos=[pos_H pos_V]; end

59

pos_carro.m

%Esta função retorna a posição do carrinho com base nos 3 parâmetros de %posição encontrados desde que não haja erro de aquisição de parâmetros.

function [posicao]=pos_carro(pos)

posicao(1,1)=pos(1,1);

posicao(1,2)=pos(1,2);

for k=2:1:8 if pos(k,1) ~= posicao(1,1) || pos(k,2) ~= posicao(1,2);

posicao(2,1)=pos(k,1);

posicao(2,2)=pos(k,2);

break

end

end

for k=3:1:8 if (pos(k,1) ~= posicao(1,1) || pos(k,2) ~= posicao(1,2)) && (pos(k,1) ~= posicao(2,1) || pos(k,2) ~= posicao(2,2))

posicao(3,1)=pos(k,1);

posicao(3,2)=pos(k,2);

break

end

end

param_carro.m

%Esta função pega 3 parâmetros de posição (triangulo marcador) do carro, e %1 parametro de posição da bola e retorna a distância do carro até a bola e %a angulação do carro em relação a bola.

function [parametros]=param_carro(p_carro, p_bola)

%Encontrando o ponto mais afastado da base do marcador (triângulo isósceles

L1=sqrt((p_carro(1,1)-p_carro(2,1))^2 + (p_carro(1,2)-p_carro(2,2))^2); L2=sqrt((p_carro(1,1)-p_carro(3,1))^2 + (p_carro(1,2)-p_carro(3,2))^2); L3=sqrt((p_carro(2,1)-p_carro(3,1))^2 + (p_carro(2,2)-p_carro(3,2))^2);

%compara os lados do triângulo, encontra o menor, e atribui ao centro do %carrinho o valor do ponto oposto ao menor lado.

if L1<L2 && L1<L3

centro(1,1)=p_carro(3,1);

centro(1,2)=p_carro(3,2);

end

if L2<L1 && L2<L3

centro(1,1)=p_carro(2,1);

centro(1,2)=p_carro(2,2);

end

if L3<L1 && L3<L2

centro(1,1)=p_carro(1,1);

centro(1,2)=p_carro(1,2);

end

60

%Calcula a distância entre o centro e a bola

dist=sqrt((centro(1,1)-p_bola(1,1))^2 + (centro(1,2)-p_bola(1,2))^2);

%Calcula o ângulo entre o carro e a bola

%Encontra o ponto médio entre os dois pontos mais próximos (base do %triângulo isósceles (Xm)

if L1<L2 && L1<L3

Xm(1,1)=(p_carro(1,1)+p_carro(2,1))/2;

Xm(1,2)=(p_carro(1,2)+p_carro(2,2))/2;

end

if L2<L1 && L2<L3

Xm(1,1)=(p_carro(1,1)+p_carro(3,1))/2;

Xm(1,2)=(p_carro(1,2)+p_carro(3,2))/2;

end

if L3<L1 && L3<L2

Xm(1,1)=(p_carro(2,1)+p_carro(3,1))/2;

Xm(1,2)=(p_carro(2,2)+p_carro(3,2))/2;

end

%Encontra os vetores da origem até a bola e da origem até o ponto Xm

vet_bola(1,1)=p_bola(1,1)-Xm(1,1);

vet_bola(1,2)=p_bola(1,2)-Xm(1,2);

vet_carro(1,1)=centro(1,1)-Xm(1,1);

vet_carro(1,2)=centro(1,2)-Xm(1,2);

%Encontra o valor do ângulo entre os dois vetores

num=(vet_bola(1,1)*vet_carro(1,1))+vet_bola(1,2)*vet_carro(1,2);

mod_bola=sqrt((vet_bola(1,1)^2)+(vet_bola(1,2)^2));

mod_carro=sqrt((vet_carro(1,1)^2)+(vet_carro(1,2)^2));

den=mod_bola*mod_carro;

cos_theta=num/den;

ang=acos(cos_theta);

parametros=[dist, ang];

mod_e_ang.m

%Esta função retorna o valor do módulo e do ângulo entre 2 pontos

function [parametros]=mod_e_ang(p1, p2)

%Calcula o módulo mod= sqrt((p2(1)-p1(1))^2+(p2(2)-p1(2))^2);

%Calcula o ângulo

61

cos_alpha=(p2(1)-p1(1))/mod;

ang=acos(cos_theta);

%Calcula o coeficiente angular

coef_a=(p2(2)-p1(2))/p2(1)-p1(1);

%Calcula o coeficiente linear coef_l=(p1(2)-coef_a*p1(1)); %b=y-a*x

%Retorno parametros=[mod ang coef_a coef_l];

end

Loop.m

%Tudo Calibra_Cores; %gera matrizes com os máximos e os mínimos de cada cor vid = videoinput('winvideo',1);% abre a conexção com a câmera de video s1 = serial('COM3'); %conexão serial

fopen(s1);

i=0;

while i<30

i=i+1; %parada após realizar 10 ciclos

[CARRO BOLA GOL]=captura(vid, mat_max, mat_min);

%imagem_id %Função utilizada para testes. Efetua a identificação da imagem.

oito_pontos=varredura(CARRO); if(verifica(oito_pontos))

oito_pontos=corrigir(oito_pontos,10);

end

%"carro" é uma matriz 3x2 que contém os 3 pontos do triângulo marcador do carro carro=pos_carro(oito_pontos);

%"bola" é o ponto do centro da bola bola=pos_centro(BOLA); bola=floor(bola); %corta a parte quebrada

%"gol" é o ponto do centro do gol gol=pos_centro(GOL); gol=floor(gol); %corta a parte quebrada

%Encontra a posição que o carrinho tem que ter para acertar a bola em um %ponto que faça com que o trajeto da bola seja o gol.

pos_ideal=pos_otima(gol,bola,30,35);

pos_ideal=floor(pos_ideal); %corta a parte quebrada

%Encontra a reta ideal que passa pela frente do carrinho e pela posição %ideal frente_do_carro=frente_do(carro);

62

reta_ideal=encontre_reta(frente_do_carro,pos_ideal);

%encontra a reta que dá a direção do carro, passando pela frente e pela %base base_do_carro=base_do(carro); reta_carro=encontre_reta(base_do_carro,frente_do_carro);

%Ponto de encontro entre a reta ideal e a reta direção do carro syms x; encontro_retas=[solve(reta_carro-reta_ideal) subs(reta_ideal,x,solve(reta_carro-reta_ideal))];

encontro_retas=sym2poly(encontro_retas);

%Encontrando o angulo ideal em 3 passos:

%1- Transladando a origem do eixo para a base do carrinho

pos_ideal1=[pos_ideal(1)-base_do_carro(1) pos_ideal(2)-

base_do_carro(2)];

encontro_retas1=[encontro_retas(1)-base_do_carro(1)

encontro_retas(2)-base_do_carro(2)];

%2- Encontra os ângulos entre a origem e posição ideal e origem e

encontro

%de retas angulo_pos_ideal=atan2(pos_ideal1(2), pos_ideal1(1));

angulo_encontro_retas=atan2(encontro_retas1(2),

encontro_retas1(1));

%3- A subtração desses ângulos será o angulo necessário para o

carrinho

%corrigir a posição. erro=angulo_encontro_retas-angulo_pos_ideal;

%convertendo o erro de radianos para graus

erro=erro*180/pi;

%Ajustando o sinal do ângulo %O gol deverá estar localizado na parte inferior da imagem para funcionar.

%if frente_do_carro(2)>bola(2);

%

erro=erro*(-1);

%end

%if gol(1)<bola(1);

%

erro=180-erro;

%end

%if erro>=180;

%

erro=-(360-erro);

%end

disp(erro);

%Envia dados via comunicação serial para o arduino

fprintf(s1,'%.2f',erro);

%Plota no desenho hold on syms x;

63

plot(frente_do_carro(1),subs(reta_ideal,x,frente_do_carro(1)),'*',pos_ideal

(1),subs(reta_ideal,x,pos_ideal(1)),'*')

plot([frente_do_carro(1) pos_ideal(1)],

[subs(reta_ideal,x,frente_do_carro(1)),subs(reta_ideal,x,pos_ideal(1))])

hold on;

plot(base_do_carro(1),subs(reta_carro,x,base_do_carro(1)),'*',frente_do_car

ro(1),subs(reta_ideal,x,frente_do_carro(1)),'*')

plot([base_do_carro(1) frente_do_carro(1)],

[subs(reta_carro,x,base_do_carro(1)),subs(reta_carro,x,frente_do_carro(1))]

)

end

fclose(s1);

delete(s1);

delete(vid); %fecha a conexão com o canal de vídeo.

imagem_id.m

%Filtra a imagem, subtrai as cores, e indica a imagem filtrada %em preto e branco, evidenciando o objeto.

%vid = videoinput('winvideo',1);% abre a conexção com a camera de video %A = getsnapshot(vid); % obtem um quadro do video (figura RGB) %delete(vid)

[A, MAP1] = imread('teste3.png');

figure(1)

imshow(A)

R

= A(:, :, 1); % Matriz de tons vermelhos

G

= A(:, :, 2); % Matriz de tons verdes

B

= A(:, :, 3); % Matriz de tons azuis

R1=R-G-B;

G1=G-R-B;

B1=B-R-G;

%figure(2)

%imshow(R1)

CARRO = im2bw(R1, 0.1);%(imagem preto e branco 0 0u 1 mariz nxm)

%figure(3)

%imshow(I1)

%figure(4)

%imshow(G1)

BOLA = im2bw(G1, 0.1);%(imagem preto e branco 0 0u 1 mariz nxm)

%figure(5)

%imshow(I2)

%figure(6)

%imshow(B1)

GOL = im2bw(B1, 0.1);%(imagem preto e branco 0 0u 1 mariz nxm)

%figure(7)

%imshow(I3)

IT=CARRO+BOLA+GOL;

figure(8)

imshow(IT)

64

frente_do.m

%Esta função recebe os 3 pontos do marcador do carro (triângulo isósceles) %e retorna o ponto que marca a frente do carro (ponto oposto ao menor lado %do triângulo isósceles).

function [frente]=frente_do(p_carro)

%Encontrando o ponto mais afastado da base do marcador (triângulo isósceles L1=sqrt((p_carro(2,1)-p_carro(3,1))^2 + (p_carro(2,2)-p_carro(3,2))^2); %módulo do lado oposto ao ponto p1 L2=sqrt((p_carro(1,1)-p_carro(3,1))^2 + (p_carro(1,2)-p_carro(3,2))^2); %módulo do lado oposto ao ponto p2 L3=sqrt((p_carro(1,1)-p_carro(2,1))^2 + (p_carro(1,2)-p_carro(2,2))^2); %módulo do lado oposto ao ponto p3

%compara os lados do triângulo, encontra o menor, e atribui ao centro do %carrinho o valor do ponto oposto ao menor lado.

if L1<L2 && L1<L3

centro(1,1)=p_carro(1,1);

centro(1,2)=p_carro(1,2);

end

if L2<L1 && L2<L3

centro(1,1)=p_carro(2,1);

centro(1,2)=p_carro(2,2);

end

if L3<L1 && L3<L2

centro(1,1)=p_carro(3,1);

centro(1,2)=p_carro(3,2);

end frente=[centro(1,2) centro(1,1)]; end

envia.m

%Esta função envia dados para o arduino.

function envia(mod, ang)

s1 = serial('COM1');

fopen(s1);

fprint(s1,'%s',mod);

fprint(s1,'%s',ang);

end

encontre_reta.m

%Encontra a equação da reta que passa por 2 pontos

function [eq]=encontre_reta(p1, p2)

65

syms x; syms y; A=[x y 1; p1(1) p1(2) 1; p2(1) p2(2) 1]; eq=det(A);

symvar(y);

eq=solve(eq,y);

end

%Declara y como variável principal %Isola y da equação.

encontre_angulo.m

%Encontra o ângulo entre 2 retas. As variáveis deverão conter as funções de %x "f(x)"

function [alpha]=encontre_angulo(reta_1, reta_2)

%m1 e m2 são coeficientes angulares das retas 1 e 2. syms x;

m1=subs(reta_1,x,1)-subs(reta_1,x,0);

m2=subs(reta_2,x,1)-subs(reta_2,x,0);

alpha=atan(abs((m1-m2)/(1+m1*m2)));

end

corrigir.m

%Esta função corrige caso diferentes mas muito próximos estejam %representando o mesmo ponto no vetor. Recebe um vetor com 8 pontos e um %raio de ação como argumentos. Caso dois pontos sejam encontrados no mesmo %raio, eles serão substituidos pelo ponto médio.

function [corrigido] = corrigir(pontos, raio)

%Ordenando os vetores tendo como critério o primeiro número da linha

for k=1:1:7 for i=1:1:7 if pontos(i,1) > pontos(i+1,1); aux=[pontos(i,1) pontos(i,2)];

pontos(i,1)=pontos(i+1,1);

pontos(i,2)=pontos(i+1,2);

pontos(i+1,1)=aux(1);

pontos(i+1,2)=aux(2);

end

end

end

for k=1:1:7 for i=1:1:7

%Verifica se os pontos estão dentro do raio de busca. Caso

estejam,

%os dois pontos são substituidos pelo valor medio e o valor do %contador é incrementado.

p1=[pontos(i,1); pontos(i,2)];

66

p2=[pontos(i+1,1); pontos(i+1,2)]; mod= sqrt((p2(1)-p1(1))^2+(p2(2)-p1(2))^2); mod=floor(mod);

if

mod <= raio;

pontos(i+1,1)=pontos(i,1);

pontos(i+1,2)=pontos(i,2);

i=i+1;

end

end

end

total_de_pontos=1;

pontos=round(pontos); %Arredonda para número inteiro mais próximo. for i=1:1:7 %Verifica se existem apenas 3 pontos no vetor com oito. if pontos (i,1) ~= pontos(i+1,1) || pontos (i,2) ~= pontos(i+1,2);

total_de_pontos=total_de_pontos+1;

end

end

if total_de_pontos > 3; disp('****Erro na correção dos parâmetros. Verificar o "raio" na função "corrigir"****') end

corrigido=pontos;

captura.m

%Esta função faz a leitura da câmera de vídeo e retorna as imagens em preto %e branco após aplicação de filtro de cores RGB. vid é a variável "canal" %de vídeo, que deverá ser passada como parâmetro para a função.

function [Img_Red Img_Green Img_Blue] = captura(vid, mat_max, mat_min)

A = getsnapshot(vid);

figure(1)

imshow(A)

%Mascara(:,:,1) representa a imagem do carro %Mascara(:,:,2) representa a imagem da bola %Mascara(:,:,3) representa a imagem do gol

Mascara=A(:,:,:)*0;

k=size(A); x=1; %Limite superior de tolerância y=1; %Limite inferior de tolerância

for i=1:1:3 for L=1:1:k(1,1)

67

for C=1:1:k(1,2)

if A(L,C,1)<mat_max(1,i)*x; if A(L,C,1)>mat_min(1,i)*y; if A(L,C,2)<mat_max(2,i)*x; if A(L,C,2)>mat_min(2,i)*y; if A(L,C,3)<mat_max(3,i)*x; if A(L,C,3)>mat_min(3,i)*y;

end

end

end

Mascara(L,C,i)=A(L,C,i);

end

end

end

end

end

end

Img_Red

= im2bw(Mascara(:,:,1), 0.1);

Img_Green = im2bw(Mascara(:,:,2), 0.1);

Img_Blue = im2bw(Mascara(:,:,3), 0.1); end

Calibra_Cores.m

[Modelo_Bola, MAP1] = imread('bola.png'); [Modelo_Carro, MAP2] = imread('carro.png'); [Modelo_Gol, MAP3] = imread('gol.png');

%Pegando os limites de intensidade dos modelos e organiza os dados em uma %matriz de máximos e outra matriz de mínimos.

%

%

mat_max

|

mat_min

 

%

carro bola

x

x

x

gol

|

carro

bola gol

%

r

x

x

|

r

x

x

x

%

g

x

x

|

g

x

x

x

%

b

x

x

|

b

x

x

x

for i=1:1:3

mat_max(i,1)=max(max(Modelo_Carro(:,:,i)));

mat_min(i,1)=min(min(Modelo_Carro(:,:,i)));

mat_max(i,2)=max(max(Modelo_Bola(:,:,i)));

mat_min(i,2)=min(min(Modelo_Bola(:,:,i)));

mat_max(i,3)=max(max(Modelo_Gol(:,:,i)));

mat_min(i,3)=min(min(Modelo_Gol(:,:,i)));

end

68

base_do.m

%Esta função recebe os 3 pontos do marcador do carro (triângulo isósceles) %e retorna o ponto que marca a base do carro. O ponto médio entre os dois pontos %opostos a frente do carro.

function [base]=base_do(p_carro)

%Encontrando o ponto mais afastado da base do marcador (triângulo isósceles L1=sqrt((p_carro(2,1)-p_carro(3,1))^2 + (p_carro(2,2)-p_carro(3,2))^2); %módulo do lado oposto ao ponto p1 L2=sqrt((p_carro(1,1)-p_carro(3,1))^2 + (p_carro(1,2)-p_carro(3,2))^2); %módulo do lado oposto ao ponto p2 L3=sqrt((p_carro(1,1)-p_carro(2,1))^2 + (p_carro(1,2)-p_carro(2,2))^2); %módulo do lado oposto ao ponto p3

%compara os lados do triângulo, encontra o menor, e atribui a base do %carrinho o valor médio dos pontos opóstos a frente do carro.

if L1<L2 && L1<L3 base=[(p_carro(2,2)+p_carro(3,2))/2 (p_carro(2,1)+p_carro(3,1))/2];

end

if L2<L1 && L2<L3 base=[(p_carro(1,2)+p_carro(3,2))/2 (p_carro(1,1)+p_carro(3,1))/2];

end

if L3<L1 && L3<L2 base=[(p_carro(1,2)+p_carro(2,2))/2 (p_carro(1,1)+p_carro(2,1))/2];

end

end

acha_erro.m

%Esta função retorna o ângulo entre as retas formadas pela posição real do %carrinho e a posição ideal do carrinho.

function [erro]=acha_erro(reta_ideal, reta_real)

R1 = mod_e_ang(gol, bola); %retorna [modulo angulo coeficiente_angular coeficiente_linear]

R2=3;

R3=5;

%Sendo assim, a distância do gol até a posição ideal será:

R_ideal=R1(1)+R2+R3;

%Posição ideal:

y_ideal=bola(2)-cos(atan(coef_a))*R2+R3;

x_ideal=(y_ideal-coef_l)/coef_a;

posicao_otima=[x_ideal y_ideal];

end