Ha uma semana finalmente comprei uma câmera IP wireless, coisa que eu estava querendo a muito tempo. É um lançamento recente da marca Feasso, modelo F-IPCAM01, brinquedinho bem legal, ela tem pan-tilt, consegue girar 270 graus na horizontal, quase 90 na vertical e vem com um programa de controle que pra falar a verdade nem tive a curiosidade de instalar pra ver como é.
E aí tive boas e más surpresas. Minha intenção era tentar instalar a câmera no meu robozinho e tentar algo com navegação por imagens, mas assim que vi a fonte dela já percebi que não ia dar. A fonte fornece 2 amperes pra câmera, alimentar isso com baterias é complicado, a não ser que eu faça outro robô bem mais parrudo que o atual. Com o que eu tenho não tem jeito mesmo.
A outra decepção, mas que eu já meio que esperava, é que em lugar nenhum, nem no manual, nem no CD ou no site tem qualquer referência aos comandos que a câmera aceita, cheguei até a mandar um email pro representante da Feasso no Brasil, e adivinha... nenhuma resposta. As vezes eu acho que alguns fabricantes de hardware têm titica de galinha na cabeça, fazem um equipamento cheio dos recursos e não dizem como usar esses recursos em aplicações, será que não passa pela cabeça deles que se os programadores conseguirem desenvolver aplicações para o equipamento deles isso incentivaria a venda desses produtos? Ou eles têm tão pouca imaginação que pensam que o programa que vem junto com a câmera atende todas as aplicações possíveis para o equipamento?
Mas felizmente a câmera tem dentro dela algumas páginas web que permitem controlar boa parte dos recursos e com a ajuda do Google Chrome não foi difícil interceptar toda a comunicação entre a página e a câmera, no fim acabei descobrindo quase todos os comandos da câmera. Que felicidade... Imediatamente fiz uma aplicaçãozinha em delphi pra testar o controle da câmera e consegui que ela fizesse todo tipo de movimento.
E aí a outra decepção, pra isso ser útil em um robô, não adianta apenas poder mover a câmera, é preciso poder também quantificar esse movimento e isso a câmera não faz. Não tem como você dizer pra ela girar tantos graus e a câmera também não diz quantos graus ela girou. Na verdade, não tem nenhuma precisão nos movimentos dela, mas afinal de contas é uma câmera de segurança, não foi feita pra robôs.
Ela tem três tipos básicos de movimento: patrulha, linear e por passo, e cada um desses tipos tem opções em todas as direções. Na patrulha ela fica repetindo o mesmo movimento esquerda-direita, pra cima pra baixo sem parar. No movimento linear, você manda ela ir pra alguma direção e ela vai, até chegar no fim de curso e para. No movimento por passo, ela vai pra alguma direção em passos, cada comando faz ela mover um pouco naquela direção. Até que seria útil se os passos fossem sempre iguais movendo sempre o mesmo angulo, mas não é assim, é uma coisa meio aleatória quantos graus cada passo gira a câmera.
Mas também tive boas surpresas com a câmera. Ela tem uma saída de 5 volts que serve pra ativar algum alarme caso a câmera detecte movimento e é possível enviar comandos pra ativar ou desativar essa saída. É claro que não tenho nenhuma intenção de usar alarmes com a câmera, mas uma saída de 5 volts que pode ser ligada e desligada via programa é extremamente útil e me animou a implementar uma idéia que eu já tinha a algum tempo: de instalar um laser na câmera pra medir distâncias. E olha só... Funcionou... e com um laser comprado em camelô por 6 reais... No próximo post falo sobre esse projeto. Abaixo uma foto de como ficou.
quarta-feira, 29 de fevereiro de 2012
sexta-feira, 24 de fevereiro de 2012
Download do tutorial de robô usando sucata
Acabo de colocar a versão PDF do tutorial para download no meu SkyDrive, então quem estiver interessado pode baixar ou visualizar o tutorial completo clicando aqui. É um projeto aberto. Sugestões, críticas e principalmente colaborações para incrementar o tutorial serão bem vindas. Pretendo fazer revisão periódicas do tutorial acrescentando mais informações, circuitos, técnicas, etc. Mas sempre dentro da proposta de usar de preferência material extraído de sucata e/ou de baixo custo e indicar técnicas caseiras e baratas para resolver problemas comuns no estudo da robótica.
sábado, 18 de fevereiro de 2012
PIC ou Arduíno?
Desde que iniciei o projeto do robozinho controlado por porta paralela, já venho imaginando que a próxima versão vai usar um microcontrolador. E de lá pra cá estou tentando resolver em qual microcontrolador vale a pena investir. Percebi que a disputa hoje está entre PIC e Arduíno, não tenho visto muita gente falando do 8051, então imagino que atualmente ele não faça muito sucesso entre os entusiastas da robótica. Deve ter alguma boa razão pra isso. Vi muitos sites comparando o PIC com o ATmega usado no Arduíno, mas senti que dificilmente vou conseguir uma opinião isenta, os dois lados têm defensores ardorosos e com argumentos bem convincentes.
Sem dúvida o PIC 18F2550 e seu irmão mais cheio de pernas o 18F4550, são mais rápidos e tem mais memória do que o ATmega168 e o ATmega368 que são os mais comuns nas placas Arduíno. Mas o Arduíno com certeza tem mais documentação disponível e acessível para os pobres mortais que querem iniciar na programação de microcontroladores. Também pesa o fato de ter compiladores freeware de melhor qualidade (penso eu) e uma grande biblioteca de funções disponível para programação, visto que é uma plataforma aberta.
Mas ser uma plataforma aberta não significa que é barato desenvolver dispositivos com o ATmega. A placa do padrão Arduíno realmente facilita muito o desenvolvimento de protótipos, mas parece que para por aí. Tem centenas de shields no mercado para encaixar no Arduíno e geralmente a documentação se limita a dizer qual pino encaixa aonde, mas e daí? Da maneira que eu vejo, isso serve pra testar o circuito, ver se tudo vai dar certo e se for o caso fazer as correções necessárias. Mas finalizados os testes, quero poder montar o dispositivo final da maneira mais compacta e econômica possível. Não quero gastar uma placa Arduíno e vários shields para cada dispositivo que eu for montar, isso não faz muito sentido. Afinal uma placa padrão Arduíno custa entre R$ 120,00 e R$ 250,00 conforme o tipo e os shields, bom, tem de todos os preços, mas nunca são baratos. Um microcontrolador, que no final é o que importa, não chega a R$ 20,00 e os sensores usados nos shields também são muito mais em conta quando comprados separadamente fora dos shields. Nas minhas navegações não tenho visto muitos circuitos usando o ATmega fora da placa Arduíno. Já para o PIC, uma rápida prece ao Santo Google retorna dúzias de circuitos usando o microcontrolador e sensores variados sem placas pré-montadas (e caras).
Então até o momento, estou inclinado a investir no PIC.
Sem dúvida o PIC 18F2550 e seu irmão mais cheio de pernas o 18F4550, são mais rápidos e tem mais memória do que o ATmega168 e o ATmega368 que são os mais comuns nas placas Arduíno. Mas o Arduíno com certeza tem mais documentação disponível e acessível para os pobres mortais que querem iniciar na programação de microcontroladores. Também pesa o fato de ter compiladores freeware de melhor qualidade (penso eu) e uma grande biblioteca de funções disponível para programação, visto que é uma plataforma aberta.
Mas ser uma plataforma aberta não significa que é barato desenvolver dispositivos com o ATmega. A placa do padrão Arduíno realmente facilita muito o desenvolvimento de protótipos, mas parece que para por aí. Tem centenas de shields no mercado para encaixar no Arduíno e geralmente a documentação se limita a dizer qual pino encaixa aonde, mas e daí? Da maneira que eu vejo, isso serve pra testar o circuito, ver se tudo vai dar certo e se for o caso fazer as correções necessárias. Mas finalizados os testes, quero poder montar o dispositivo final da maneira mais compacta e econômica possível. Não quero gastar uma placa Arduíno e vários shields para cada dispositivo que eu for montar, isso não faz muito sentido. Afinal uma placa padrão Arduíno custa entre R$ 120,00 e R$ 250,00 conforme o tipo e os shields, bom, tem de todos os preços, mas nunca são baratos. Um microcontrolador, que no final é o que importa, não chega a R$ 20,00 e os sensores usados nos shields também são muito mais em conta quando comprados separadamente fora dos shields. Nas minhas navegações não tenho visto muitos circuitos usando o ATmega fora da placa Arduíno. Já para o PIC, uma rápida prece ao Santo Google retorna dúzias de circuitos usando o microcontrolador e sensores variados sem placas pré-montadas (e caras).
Então até o momento, estou inclinado a investir no PIC.
sexta-feira, 17 de fevereiro de 2012
Apêndice - Duplicando polias e engrenagens
A boa notícia é que é possível duplicar uma engrenagem com materiais de baixo custo e sem envolver equipamentos caros. Em resumo, a duplicação de uma engrenagem envolve fazer um molde com a engrenagem disponível e depois preencher o molde com resina. Eventualmente pode ser necessário modificar o tamanho do furo central. Nesta seção abordaremos as técnicas para duplicar engrenagens e polias.
O silicone líquido
Em primeiro lugar é preciso conseguir um material para fazer o molde. Para isso a melhor opção é o silicone líquido. Este tipo de silicone é vendido com um endurecedor que deve ser misturado ao silicone nas proporções indicadas. Depois de algum tempo o silicone endurece e se transforma em uma borracha flexível. O silicone pode ser encontrado em casas que vendem materiais para artesanato e/ou pintura artística, também não é difícil de encontrar para venda on-line pela internet. Neste caso, faça buscas por “borracha de silicone” ou “silicone líquido”. A cor do silicone indica a sua dureza (ou flexibilidade) depois de curado. Os mais indicados para moldar engrenagens são o branco e o azul. Existem também silicones capazes de suportar alguns metais derretidos (silicone vermelho ou marrom), mas são bem mais caros. O silicone azul utilizado neste projeto pode ser encontrado por um preço que varia de R$ 22,00 a R$ 30,00 o litro (preços de 2011). Um litro é suficiente para fazer vários moldes, considerando que cada molde usa cerca de 100 ml de silicone. A figura 34 mostra o silicone utilizado neste projeto.
Figura 34: Silicone líquido azul e endurecedor |
O molde
Para fazer o molde, consiga um recipiente de plástico não muito fino. Um plástico muito fino pode deformar e atrapalhar a modelagem. Também é importante que tenha o fundo plano. Recipientes de plástico com tamanhos e espessuras variadas podem ser encontrados facilmente em lojas de materiais para festas.
Para conseguir engrenagens de boa qualidade, também vai ser necessário dispor de uma superfície bem nivelada. Uma boa dica é fazer uma mesa niveladora. É bem simples e evita vários problemas depois. Pode ser feita com um pedaço de madeira lisa e quatro parafusos com suas respectivas porcas. Faça furos nos cantos da madeira no diâmetro dos parafusos e fixe as porcas alinhadas com os furos. Assim os parafusos podem ser rosqueados para cima e para baixo até que a madeira fique bem nivelada. A figura 35 mostra a mesa niveladora feita para este projeto.
Figura 35: Mesa niveladora |
Use uma fita adesiva dupla face para fixar a engrenagem no fundo do recipiente plástico (figura 36). Fitas bem finas dão um resultado melhor, existe uma fita dupla face de borracha que é usada para fixar quadros na parede, essa não é indicada porque é muito grossa e cria sulcos no molde que acabam atrapalhando a modelagem. O outro tipo de fita é uma fita adesiva comum com adesivo dos dois lados, pode ser facilmente encontrada em papelarias e é bem mais barata.
Figura 36: Recipiente para o molde com a engrenagem fixada no fundo |
Dica: Se o silicone ficou algum tempo armazenado, o que com certeza é o caso quando você acaba de comprar um pote, ele tende a se depositar no fundo do pote. Antes de usar, é uma boa idéia misturar misturar bem o silicone com um pedaço de madeira para deixa-lo mais homogêneo, inclusive raspando bem o fundo do pote, você vai perceber que o silicone no fundo do pote é muito mais denso que o que está na superfície.Depois de fixar a engrenagem no fundo do recipiente, coloque-o em uma superfície nivelada ou na mesa niveladora e faça a mistura do silicone com o endurecedor. Para o silicone usado neste projeto, a medida que deu melhores resultados foi duas tampinhas de endurecedor para 100 ml de silicone. É preciso cuidado para não produzir muitas bolhas no silicone enquanto estiver misturando, fazendo movimentos lentos e suaves. Também é importante misturar bem o silicone com o endurecedor, raspando as laterais e o fundo do copinho para misturar o silicone que fica aderido às paredes do recipiente. Depois de misturado, algumas pancadinhas no fundo do copinho ajudam a fazer subir as bolhas que estiverem no silicone. Essa operação não deve demorar mais do que dois minutos, depois de misturado com o endurecedor, o silicone começa a endurecer rápido e é importante que ele seja despejado no molde enquanto ainda está bem líquido para que forme uma superfície nivelada na parte de cima.
Dica: Depois de despejar o silicone no copinho medida e antes de misturar o endurecedor (perceberam que eu negritei, inclinei e sublinhei a palavra antes né?), deixar o copinho descansar por alguns minutos vai fazer com que boa parte das bolhas que estiverem la dentro subam e estourem na superfície.
Despeje o silicone no recipiente de plástico e espere cerca de 3 horas para retirar o molde do recipiente e a engrenagem do molde (Figura 37). A cura completa só acontece depois de 24 horas. É aconselhável esperar a cura completa antes de usar a resina no molde ou ela pode aderir ao silicone, outra opção é usar algum desmoldante. Um desmoldante é uma substancia, geralmente em spray, que é colocada no molde para que a resina não grude nele. Existe um óleo de silicone em spray que é próprio para isso e é facilmente encontrado em lojas de ferramentas.
Importante: Não use recipientes de vidro para fazer o molde. O silicone adere ao vidro.
Figura 37: Silicone no recipiente esperando a secagem |
Depois de seco, o silicone forma uma borda ligeiramente levantada devido à tensão superficial que existe enquanto está líquido. Essa borda deve ser retirada para garantir que o molde fique bem nivelado quando for colocada a resina. Com uma tesoura, corte as bordas conforme mostrado na figura 38.
Figura 38: Bordas sendo cortadas para garantir bom nivelamento do molde |
Figura 39: O molde depois de pronto |
A resina
Durante o desenvolvimento deste projeto foram testados vários tipos de resina. A mais fácil de conseguir é a resina de poliéster pré-acelerada. Essa resina é utilizada para fazer peças de fibra de vidro, então pode ser encontrada em qualquer loja de tintas e é bem barata. Mas infelizmente não serve para fazer engrenagens. Depois que seca apresenta uma retração bem significativa o que acaba alterando o diâmetro da peça. Além disso, a resistência mecânica dela é baixa, uma engrenagem feita com essa resina nem pôde ser testada porque caiu no chão e quebrou.
Também foi feito um teste com acrílico em pó auto-polimerizante, material utilizado pelos dentistas para fazer próteses. Este material é um pouco mais caro e mais difícil de encontrar já que só é encontrado em casas especializadas em materiais para dentistas. Tem uma excelente resistência mecânica e não tem o problema da retração como a resina de poliéster. O problema do acrílico em pó é que depois misturado com o líquido ele se transforma em uma pasta bastante densa e é difícil colocar a pasta no molde de borracha, preenchendo todos os detalhes sem deformar o molde que é bem flexível. Também é possível colocar diretamente o pó no molde e depois gotejar o líquido sobre ele. O problema dessa técnica é garantir que o líquido se espalhe por todo o pó de maneira homogênea. Se uma parte do pó não receber o líquido, não vai endurecer e a engrenagem será inutilizada.
Os melhores resultados foram obtidos com a resina epóxi. Não é uma resina cara (por volta de R$ 40,00 o litro – valores de 2011), tem uma ótima resistência mecânica, não apresenta retração depois de seca e a mistura da resina com o endurecedor forma um líquido com uma viscosidade satisfatória para ser despejado no molde preenchendo todos os detalhes. O único problema é que é difícil encontrar estabelecimentos que vendam essa resina. Como não foi encontrada nos estabelecimentos da cidade, a opção foi comprar pela internet. Existem vários tipos de resina epóxi, o ideal é que seja um tipo com baixa viscosidade.
É preciso muito cuidado ao manipular a resina epóxi. Use jornais velhos para evitar que respingos possam atingir a superfície de trabalho e palitos de sorvete e copinhos descartáveis para fazer a mistura, esta resina depois de seca é extremamente dura e os respingos não saem facilmente.
Uma superfície nivelada também é importante no momento de preencher o molde com a resina, então antes de fazer a mistura coloque o molde na mesa niveladora. A resina epóxi é razoavelmente lenta para secar, demora pelo menos 5 horas para que possa ser retirada do molde, mas só atinge o máximo da sua resistência mecânica depois de 24 horas.
Câmara de secagem
A temperatura e umidade do ar influenciam bastante no processo de cura da resina. O ideal é um ambiente seco e ligeiramente aquecido, isso acelera a secagem e melhora a resistência da engrenagem. Não é difícil fazer uma câmara de secagem para a resina, é basicamente uma caixa de madeira com uma lâmpada incandescente de 40W dentro dela. Na falta de uma caixa de madeira apropriada, uma câmara de secagem usando uma prateleira de armário foi improvisada para este projeto, conforme mostrado na Figura 40.
Resista à tentação de colocar o dedo na resina para verificar se está seca, antes de secar a resina fica em um estado gelatinoso e a pressão do dedo pode deformar a engrenagem. Use as sobras da mistura para deixar uma porção à parte como controle.
Figura 40: Câmara de secagem improvisada em um armário |
O furo central
Se for possível encontrar uma engrenagem que tenha o diâmetro, o tamanho e numero de dentes correto para seu projeto e, além disso, tenha também o furo central na medida correta para o eixo onde a engrenagem será fixada, parabéns, considere-se com sorte. Mas eventualmente acontece de a engrenagem não ter um furo central na medida correta. Se for um furo pequeno e você precisa de um furo maior, talvez seja possível aumentar o furo com uma broca apropriada. Mas se o furo não for tão pequeno assim e você precisar aumentar o tamanho dele, vai acabar descobrindo que é muito difícil aumentar seu diâmetro mantendo o furo exatamente centralizado na engrenagem. E uma engrenagem com o furo fora de centro, mesmo que ligeiramente, fica inutilizada. Uma situação parecida ocorre quando a engrenagem tem um furo maior do que o necessário, nesse caso não há como diminuir o diâmetro dele. A solução, tanto para um caso quanto para o outro, é eliminar o furo e fazer outro.
Para eliminar o furo é bastante simples, basta cortar o pino central do molde e moldar a engrenagem sem o furo, como mostrado na Figura 41. Já para fazer o novo furo é bastante mais complicado, especialmente porque o furo precisa estar muito bem centralizado na engrenagem.
Figura 41: (a) Molde com o pino central retirado (b) A engrenagem depois de pronta |
Esquadro de centrar
O problema de fazer o novo furo é como determinar a posição exata do centro da engrenagem. Existe um tipo de esquadro que é próprio para marcar o centro de uma peça circular, o esquadro de centrar, mas é muito difícil de ser encontrado e costuma ter um preço proibitivo. Felizmente, não é difícil fazer um esquadro de centrar caseiro com um custo muito baixo.
Só é necessário dispor de um esquadro de desenho triangular comum, do tipo com ângulos de 45º e 90º. O primeiro passo é cortar o lado do esquadro que tem os ângulos de 45º (hipotenusa). Em seguida a parte cortada deve ser posicionada e colada de modo que um dos ângulos de 45º divida o ângulo de 90º na metade, conforme mostrado na figura 42.
Figura 42: (a) Esquadro de desenho cortado (b) Depois de posicionado e colado |
Figura 43: (a) Engrenagem posicionada no esquadro (b) Depois de riscada |
Links úteis
Aqui alguns links muito bons pra quem quiser se aprofundar mais:
Resina
1) Um breve mas bem completo resumo sobre tipos de resina e suas aplicações e características. Também tem um FAQ com informações bem importantes pra quem quiser fazer peças mais bem acabadas:
http://www.fazfacil.com.br/reforma-construcao/resinas-poliester-epoxi/
Silicone
1) Informações acessíveis e úteis sobre tipos de silicone e suas aplicações:
http://www.fazfacil.com.br/materiais/silicone.html
Índice
2) Visão geral do projeto3) Fonte de alimentação para testes de bancada
4) A porta paralela
5) Motores de passo
6) Montagem dos circuitos
7) Montagem do robô
8) Alimentação
9) Software de navegação
10) Conclusão
Apêndice - Duplicando polias e engrenagens
10) Conclusão
Este trabalho mostra que é possível construir dispositivos robóticos com materiais extraídos de sucata e/ou de baixo custo. Apesar do dispositivo descrito aqui ser bastante simples, nada impede de usar os mesmo conceitos e materiais para criar dispositivos mais sofisticados. O pequeno robô desenvolvido tem os elementos básicos para o estudo da robótica. Envolveu programação, comunicação do computador com um dispositivo externo, eletrônica e a montagem física do hardware.
O foco no estudo dos motores de passo tem a intenção de divulgar
e desmistificar o uso destes motores, provendo o conhecimento básico para que
sejam utilizados em outros projetos. É um recurso importantíssimo para o
desenvolvimento de dispositivos robóticos e são muito facilmente obtidos em
impressoras sucateadas.
É fato que o robô descrito neste trabalho nada faz além de
se mover, mas espera-se que seja considerado pelos estudantes como um ponto de
partida para projetos mais elaborados. Por exemplo, poderiam ser instalados
sensores que retornem sinais para o computador, a comunicação com o computador
poderia ser feita por alguma tecnologia sem fio e utilizando outras portas como
a porta COM ou a porta USB, o programa poderia ser melhorado para permitir o
armazenamento de rotas pré-programadas, entre muitos outros aprimoramentos que
podem ser implementados a partir deste projeto.
E finalmente gostaria de deixar registrado que é
extremamente recompensador ver o resultado de um trabalho ganhar vida e se
mover fisicamente pelo mundo real. Ao ver o pequeno robô ganhando a capacidade
de movimento é difícil não ter o impulso de fornecer a ele mais habilidades e
recursos através de dispositivos, sensores e de uma programação mais elaborada.
Às vezes tenho a impressão que encontrar utilidades práticas e acadêmicas para
robôs é só um pretexto, e que no fundo o que os pesquisadores e desenvolvedores
realmente querem é ver suas criações evoluindo, crescendo e se tornando cada
vez mais independentes.
Prof. Ms. Francesco Artur Perrotti
3) Fonte de alimentação para testes de bancada
4) A porta paralela
5) Motores de passo
6) Montagem dos circuitos
7) Montagem do robô
8) Alimentação
9) Software de navegação
10) Conclusão
Apêndice - Duplicando polias e engrenagens
Índice
2) Visão geral do projeto3) Fonte de alimentação para testes de bancada
4) A porta paralela
5) Motores de passo
6) Montagem dos circuitos
7) Montagem do robô
8) Alimentação
9) Software de navegação
10) Conclusão
Apêndice - Duplicando polias e engrenagens
9) Software de navegação
Tão importante quanto os circuitos e a montagem, é o software que irá controlar os movimentos do robô. A unit ParBib descrita no capítulo 4, foi criada apenas para enviar sinais à porta paralela, mas para que esses sinais se transformem em movimento no robô, eles precisam ser gerados com coerência e sincronia, sendo essa a função do software de navegação.
Para gerar os sinais de navegação foi desenvolvida uma classe que fornece os recursos básicos de movimentação do robô. A classe TRobotMove declarada dentro da unit RobotMove, permite selecionar entre 9 tipos de movimento, alterar a velocidade e ligar/desligar o modo de alto torque.
Métodos públicos da classe TRobotMove
Abaixo segue a declaração da parte pública da classe e uma breve explicação sobre o uso de cada método. O tópico seguinte contém a listagem completa da classe.
type
TRobotMove = class
public
constructor Create(AOwner: TComponent;
LPTPort: TLPT;
BaseTm: cardinal);
destructor Destroy; override;
procedure Ahead;
procedure Back;
procedure Stop;
procedure Right;
procedure Left;
procedure VeryRight;
procedure VeryLeft;
procedure SpinRight;
procedure SpinLeft;
property PulseTime: cardinal;
property HiTorq: boolean;
end;
constructor
Create(AOwner: TComponent; LPTPort: TLPT;
BaseTm: cardinal);
Construtor da classe. Usa os seguintes parâmetros:
AOwner: Pode ser qualquer componente
descendente de TComponent. Normalmente é o próprio form principal da aplicação.
Este parâmetro é necessário porque a classe usa internamente um timer para
gerar os pulsos e a construção do timer exige um Owner.
LPTPort:
Porta paralela que será usada. Em geral é a LPT1.
BaseTM: Tempo base para o timer em milissegundos. Esse
é o tempo que será usado entre cada pulso enviado para os motores. Quanto menor
o tempo, mais rápido o robô vai se mover. Existe um valor mínimo para esse
tempo que depende do tipo do motor de passo e do peso do robô. Caso sejam
usados valores abaixo do mínimo, os motores começam a perder passo ou podem nem
se mover.
destructor Destroy;
Destrutor da classe.
procedure Ahead;
Move para frente em linha reta.
procedure Back;
Move para trás em linha reta.
procedure Stop;
Para o movimento, mas as bobinas continuam ativadas. Isso
cria um efeito de “freio de mão” no robô.
procedure Right;
Curva leve à direita. A roda da direita passa a rodar com a
metade da velocidade da roda da esquerda.
procedure Left;
Curva leve à esquerda. Aqui é a roda da esquerda que tem sua
velocidade reduzida pela metade.
procedure VeryRight;
Curva fechada à direita. A roda da direita fica travada na
mesma posição e a roda da esquerda continua no movimento normal. O efeito disso
é que o robô começa a circular em torno da roda da direita.
procedure VeryLeft;
Curva fechada à esquerda. Idem acima.
procedure SpinRight;
Giro à direita. A roda da direita tem o movimento invertido e
passa a rodar para trás, enquanto a roda da esquerda se move para frente. O
efeito é que o robô começa a girar no sentido horário sem sair do lugar.
procedure SpinLeft;
Giro à esquerda. A roda da esquerda inverte o movimento e o
robô gira no sentido anti-horário.
property PulseTime: cardinal;
Permite ler e alterar o tempo (em milissegundos) entre cada
pulso durante o movimento.
property HiTorq: boolean;
Liga/desliga o modo de alto torque.
Listagem da classe TRobotMove
unit RobotMove;
interface
uses
SysUtils, Classes, DateUtils, Forms, ExtCtrls,
ParBib;
type
TRobotMove = class
private
lport: TLPT;
tm: TTimer;
FHiTorq:
boolean; // Ativa/desativa alto
torque
dvLeft, dvRight, // divisor de frequencia
psLeft, psRight: byte; // pulsos
fwLeft, fwRight: boolean; // direção
onLeft, onRight: boolean; // anda / para
baseCount: integer; // contador base
FBaseTime: cardinal;
procedure OnTimer(Sender: TObject);
public
constructor Create(AOwner: TComponent;
LPTPort: TLPT;
BaseTm: cardinal);
destructor Destroy; override;
procedure Ahead;
procedure Back;
procedure Stop;
procedure Right;
procedure Left;
procedure VeryLeft;
procedure VeryRight;
procedure SpinLeft;
procedure SpinRight;
property PulseTime: cardinal read FBaseTime
write FBaseTime;
property HiTorq: boolean read FHiTorq write
FHiTorq;
end;
implementation
{
TRobotMove }
constructor
TRobotMove.Create(AOwner: TComponent; LPTPort: TLPT;
BaseTm:
cardinal);
begin
inherited Create;
lport:= LPTPort;
SetLPT(lport);
tm:= TTimer.Create(AOwner);
tm.Enabled:= false;
FBaseTime := BaseTm;
tm.Interval:= FBaseTime;
tm.OnTimer:= OnTimer;
dvLeft:= 1;
dvRight:= 1;
psLeft:= 1;
psRight:= 1;
fwLeft:= true;
fwRight:= true;
baseCount := 1;
onLeft:= false;
onRight:= false;
tm.Enabled:= true;
FHiTorq := false;
end;
procedure
TRobotMove.OnTimer(Sender: TObject);
var pr,
pl: byte;
begin
if (baseCount mod dvRight = 0) and onRight
then
begin
if fwRight then
begin
if psRight = 8
then psRight := 1
else psRight := psRight shl 1;
end
else begin
if psRight = 1
then psRight := 8
else psRight := psRight shr 1;
end;
end;
if (baseCount mod dvLeft = 0) and onLeft then
begin
if fwLeft then
begin
if psLeft = 1
then psLeft := 8
else psLeft := psLeft shr 1;
end
else begin
if psLeft = 8
then psLeft := 1
else psLeft := psLeft shl 1;
end;
end;
if FHiTorq then
begin
pr := psRight or (psRight shl 1);
if pr >= 16 then pr := psRight + 1;
pl := psLeft or (psLeft shl 1);
if pl >= 16 then pl := psLeft + 1;
SetDataByte((pl shl 4) or pr);
end
else SetDataByte((psLeft shl 4) or psRight);
Inc(baseCount);
baseCount := baseCount mod 100000;
tm.Interval:= FBaseTime;
end;
procedure
TRobotMove.Ahead;
begin
onLeft:= true;
onRight:= true;
fwLeft:= true;
fwRight:= true;
dvLeft:= 1;
dvRight:= 1;
end;
procedure
TRobotMove.Back;
begin
onLeft:= true;
onRight:= true;
fwLeft:= false;
fwRight:= false;
dvLeft:= 1;
dvRight:= 1;
end;
procedure
TRobotMove.Stop;
begin
onLeft:= false;
onRight:= false;
end;
procedure
TRobotMove.Right;
begin
onLeft:= true;
onRight:= true;
fwLeft:= true;
fwRight:= true;
dvLeft:= 1;
dvRight:= 2;
end;
procedure
TRobotMove.Left;
begin
onLeft:= true;
onRight:= true;
fwLeft:= true;
fwRight:= true;
dvLeft:= 2;
dvRight:= 1;
end;
procedure
TRobotMove.VeryRight;
begin
onLeft:= true;
onRight:= false;
fwLeft:= true;
fwRight:= true;
dvLeft:= 1;
dvRight:= 1;
end;
procedure
TRobotMove.VeryLeft;
begin
onLeft:= false;
onRight:= true;
fwLeft:= true;
fwRight:= true;
dvLeft:= 1;
dvRight:= 1;
end;
procedure
TRobotMove.SpinRight;
begin
onLeft:= true;
onRight:= true;
fwLeft:= true;
fwRight:= false;
dvLeft:= 1;
dvRight:= 1;
end;
procedure
TRobotMove.SpinLeft;
begin
onLeft:= true;
onRight:= true;
fwLeft:= false;
fwRight:= true;
dvLeft:= 1;
dvRight:= 1;
end;
destructor
TRobotMove.Destroy;
var tmp:
TDateTime;
begin
tm.OnTimer:= nil;
tm.Enabled:= false;
tmp := IncMilliSecond(Now, tm.Interval+2);
while tmp > Now do
Application.ProcessMessages;
tm.Free;
SetDataByte(0);
end;
end.
Programa de navegação e controle do robô
O programa listado a seguir usa a classe TRobotMove para
controlar o robô e fornece uma interface para o usuário. Basicamente o programa
associa um botão na tela de interface a cada método fornecido pela classe. As
funções de movimento também podem ser ativadas pelo teclado numérico. O tempo
mostrado no canto inferior direito do form é o intervalo de tempo entre cada
pulso enviado aos motores. Diminuir o tempo aumenta a velocidade do robô, mas
existe um limite que varia de acordo com os motores utilizados e o peso do
robô. Se usado um intervalo abaixo desse limite, os motores começam a perder
passos ou simplesmente param. A figura
33 mostra o form da aplicação.
As imagens que ilustram os botões foram omitidas da listagem
para que a mesma não fique excessivamente longa. Como se trata de um form, foi
incluído o arquivo dfm e o arquivo pas, além do arquivo de projeto.
Figura 33: Tela do programa de navegação |
Arquivo de projeto RoboNav.dpr
program RoboNav;
uses
Forms,
Unit1 in 'Unit1.pas' {Form1},
RobotMove in 'RobotMove.pas',
ParBib in 'ParBib.pas';
{$R
*.res}
begin
Application.Initialize;
Application.CreateForm(TForm1, Form1);
Application.Run;
end.
Definição do form de interface, arquivo Unit1.dfm
object
Form1: TForm1
Left =
269
Top = 108
Width = 528
Height = 291
Caption = 'Robô Nav'
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'MS Sans Serif'
Font.Style = [fsBold]
OldCreateOrder = False
OnCreate = FormCreate
OnKeyPress = FormKeyPress
PixelsPerInch = 96
TextHeight = 13
object Label1: TLabel
Left = 16
Top = 11
Width = 64
Height = 13
Caption = 'Portas LPT'
end
object btOn: TButton
Left = 13
Top = 60
Width = 112
Height = 57
Caption = 'Ativar'
TabOrder = 0
OnClick = btOnClick
OnKeyPress = FormKeyPress
end
object btOff: TButton
Left = 13
Top = 124
Width = 112
Height = 57
Caption = 'Desligar'
Enabled = False
TabOrder = 1
OnClick = btOffClick
OnKeyPress = FormKeyPress
end
object cbxPortas: TComboBox
Left = 16
Top = 32
Width = 107
Height = 21
ItemHeight = 13
ItemIndex = 0
TabOrder = 2
Text = 'LPT1'
OnKeyPress = FormKeyPress
Items.Strings = (
'LPT1'
'LPT2')
end
object pnMov: TPanel
Left = 138
Top = 32
Width = 367
Height = 222
BevelOuter = bvNone
Enabled = False
TabOrder = 3
object Label2: TLabel
Left = 264
Top = 136
Width = 66
Height = 13
Caption = 'Tempo (ms)'
end
object btLeft: TBitBtn
Left = 7
Top = 6
Width = 68
Height = 66
TabOrder = 0
OnClick = btLeftClick
OnKeyPress = FormKeyPress
end
object btAhead: TBitBtn
Left = 79
Top = 6
Width = 68
Height = 66
TabOrder = 1
OnClick = btAheadClick
OnKeyPress = FormKeyPress
end
object btRight: TBitBtn
Left = 151
Top = 6
Width = 68
Height = 66
TabOrder = 2
OnClick = btRightClick
OnKeyPress = FormKeyPress
end
object btVRight: TBitBtn
Left = 151
Top = 77
Width = 68
Height = 66
TabOrder = 3
OnClick = btVRightClick
OnKeyPress = FormKeyPress
end
object btStop: TBitBtn
Left = 79
Top = 77
Width = 68
Height = 66
TabOrder = 4
OnClick = btStopClick
OnKeyPress = FormKeyPress
end
object btVLeft: TBitBtn
Left = 7
Top = 77
Width = 68
Height = 66
TabOrder = 5
OnClick = btVLeftClick
OnKeyPress = FormKeyPress
end
object btSLeft: TBitBtn
Left = 7
Top = 148
Width = 68
Height = 66
TabOrder = 6
OnClick = btSLeftClick
OnKeyPress = FormKeyPress
end
object btBack: TBitBtn
Left = 79
Top = 148
Width = 68
Height = 66
TabOrder = 7
OnClick = btBackClick
OnKeyPress = FormKeyPress
end
object btSRight: TBitBtn
Left = 151
Top = 148
Width = 68
Height = 66
TabOrder = 8
OnClick = btSRightClick
OnKeyPress = FormKeyPress
end
object btTurbo: TBitBtn
Left = 249
Top = 6
Width = 113
Height = 105
Caption = 'Turbo'
TabOrder = 9
OnClick = btTurboClick
Layout = blGlyphTop
end
object seTime: TSpinEdit
Left = 262
Top = 152
Width = 97
Height = 22
Enabled = False
MaxValue = 100
MinValue = 10
TabOrder = 10
Value = 35
OnChange = seTimeChange
end
end
end
Listagem do arquivo Unit1.pas
unit Unit1;
interface
uses
Forms, StdCtrls, Spin, Buttons, Controls,
ExtCtrls, Classes,
ParBib, RobotMove;
type
TForm1 = class(TForm)
btOn: TButton;
btOff: TButton;
Label1: TLabel;
cbxPortas: TComboBox;
pnMov: TPanel;
btLeft: TBitBtn;
btAhead: TBitBtn;
btRight: TBitBtn;
btVRight: TBitBtn;
btStop: TBitBtn;
btVLeft: TBitBtn;
btSLeft: TBitBtn;
btBack: TBitBtn;
btSRight: TBitBtn;
btTurbo: TBitBtn;
Label2: TLabel;
seTime: TSpinEdit;
procedure btOnClick(Sender: TObject);
procedure btOffClick(Sender: TObject);
procedure btTurboClick(Sender: TObject);
procedure FormKeyPress(Sender: TObject; var
Key: Char);
procedure FormCreate(Sender: TObject);
procedure btLeftClick(Sender: TObject);
procedure btVLeftClick(Sender: TObject);
procedure btSLeftClick(Sender: TObject);
procedure btAheadClick(Sender: TObject);
procedure btStopClick(Sender: TObject);
procedure btBackClick(Sender: TObject);
procedure btRightClick(Sender: TObject);
procedure btVRightClick(Sender: TObject);
procedure btSRightClick(Sender: TObject);
procedure seTimeChange(Sender: TObject);
private
function LPTSelected: TLPT;
public
rob: TRobotMove;
end;
var
Form1: TForm1;
implementation
{$R
*.dfm}
{ TForm1
}
function
TForm1.LPTSelected: TLPT;
begin
case cbxPortas.ItemIndex of
0: result := pLPT1;
else result := pLPT2;
end;
end;
procedure
TForm1.btOnClick(Sender: TObject);
begin
rob:= TRobotMove.Create(self, LPTSelected,
seTime.Value);
btOff.Enabled:= true;
btOn.Enabled:= false;
pnMov.Enabled:= true;
end;
procedure
TForm1.btOffClick(Sender: TObject);
begin
rob.Stop;
rob.Free;
btOn.Enabled:= true;
btOff.Enabled:= false;
pnMov.Enabled:= false;
end;
procedure
TForm1.btTurboClick(Sender: TObject);
begin
rob.HiTorq := not rob.HiTorq;
if rob.HiTorq
then btTurbo.Caption := 'Turbo on'
else btTurbo.Caption := 'Turbo off'
end;
procedure
TForm1.FormKeyPress(Sender: TObject; var Key: Char);
begin
case Key of
'8': begin
rob.Ahead;
btAhead.SetFocus;
end;
'2': begin
rob.Back;
btBack.SetFocus;
end;
'5': begin
rob.Stop;
btStop.SetFocus;
end;
'7': begin
rob.Left;
btLeft.SetFocus;
end;
'9': begin
rob.Right;
btRight.SetFocus;
end;
'4': begin
rob.VeryLeft;
btVLeft.SetFocus;
end;
'6': begin
rob.VeryRight;
btVRight.SetFocus;
end;
'1': begin
rob.SpinLeft;
btSLeft.SetFocus;
end;
'3': begin
rob.SpinRight;
btSRight.SetFocus;
end;
end;
end;
procedure
TForm1.FormCreate(Sender: TObject);
begin
seTime.Enabled:= true;
end;
procedure
TForm1.btLeftClick(Sender: TObject);
begin
Rob.Left;
end;
procedure
TForm1.btVLeftClick(Sender: TObject);
begin
rob.VeryLeft;
end;
procedure
TForm1.btSLeftClick(Sender: TObject);
begin
rob.SpinLeft;
end;
procedure
TForm1.btAheadClick(Sender: TObject);
begin
rob.Ahead;
end;
procedure
TForm1.btStopClick(Sender: TObject);
begin
rob.Stop;
end;
procedure
TForm1.btBackClick(Sender: TObject);
begin
rob.Back;
end;
procedure
TForm1.btRightClick(Sender: TObject);
begin
rob.Right;
end;
procedure
TForm1.btVRightClick(Sender: TObject);
begin
rob.VeryRight;
end;
procedure
TForm1.btSRightClick(Sender: TObject);
begin
rob.SpinRight;
end;
procedure
TForm1.seTimeChange(Sender: TObject);
begin
rob.PulseTime:= seTime.Value;
end;
Índice
2) Visão geral do projeto3) Fonte de alimentação para testes de bancada
4) A porta paralela
5) Motores de passo
6) Montagem dos circuitos
7) Montagem do robô
8) Alimentação
9) Software de navegação
10) Conclusão
Apêndice - Duplicando polias e engrenagens
Assinar:
Postagens (Atom)