Você está na página 1de 71

Apostila

Exemplos de Códigos
Fonte em MikroC

Autor: Wagner Rambo


Área: Programação
Nível: Principiante / Intermediário

www.wrkits.com.br

Copyright WR Kits 2011 (todos os direitos reservados): Proibida


reprodução total ou parcial sem prévia autorização por escrito do autor.
Copyright protegido pela Lei de Direitos Autorais LEI N° 9.610, de 19 de
Fevereiro de 1998.
Exemplos de Códigos Fonte em MikroC

1 – Introdução

Como já foi abordado em outras apostilas do disco de drivers do kit


Paradoxus 9 da W.R. Kits, cada um poderá utilizar a linguagem de
programação que bem entender para efetuar os testes e programações do
microcontrolador. Sendo o circuito extremamente versátil, o mesmo admite os
mais diversos tipos de linguagem de programação. Visando uma rápida
evolução do usuário neste departamento, optamos pela utilização de uma
linguagem que não é tão complexa, mas em contra partida não é das mais
fáceis: a linguagem C. E particularmente, a linguagem C para o software
MikroC Pro for PIC, por ser um compilador bem interativo e de fácil
compreensão até certo ponto. Esta apostila trará diversos exemplos de códigos
fonte, demonstrando vários recursos que o circuito Paradoxus 9 apresenta,
ampliando as ideias do leitor. É sempre aconselhável, que os códigos fonte
sejam totalmente digitados por você, letra por letra, para que consiga aprender
mais rapidamente a criar seus próprios programas. Vale ressaltar que
disponibilizamos todos os arquivos .hex para gravação direta no PIC, dos
respectivos códigos fonte aqui mostrados e estão na pasta “Arquivos .hex”
deste disco de drivers. Alguns programas criados, poderão ser executados
apenas com os recursos e dispositivos contidos no próprio circuito Paradoxus 9
(on board). Já outros, necessitarão de montagem específica em matriz de
contatos (protoboard), conexão dos componentes nas entradas/saídas
programáveis previstas para o circuito, ou mesmo confecção de um circuito
impresso, pelos mais experientes (off board). Na apostila “Exemplos de
Circuitos Para Teste dos Códigos Fonte”, você encontrará todos os diagramas
esquemáticos destes circuitos, bem como sua disposição na protoboard.

2 – Exemplos

A seguir, você encontrará diversos exemplos de códigos fonte, para


utilizar no MikroC, com respectivas explicações. Os códigos fonte podem ser
modificados da forma que o usuário desejar. Digite letra por letra, para ir se
acostumando com a linguagem. Para saber como criar um novo projeto em
MikroC e como compilá-lo, leia o arquivo “MikroC Pro for PIC Tutorial”, contido
no disco dos drivers. Tendo-se entendido o tutorial sobre MikroC, agora você
poderá dar início à digitação dos exemplos que aqui seguem. Para um
aproveitamente ainda maior dos códigos fonte, você também deverá ter
entendido o tutorial “Programação - Tutorial de Noções Básicas”, presente no
mesmo disco dos drivers.
 Exemplo 1: Fazendo o LED1 piscar uma vez a cada segundo

Como já comentamos no tutorial “Programação - Tutorial de Noções


Básicas”, conseguindo manipular um led, o usuário poderá controlar os mais
diversos dispositivos, com as devidas modificações. Por este motivo, os
primeiros exemplos serão justamente o controle de led’s. Alguns utilizarão
apenas os led’s programáveis da Paradoxus 9, outros utilizarão led’s externos,
devidamente montados em protoboard.
Este simples programa consiste em fazer com que o LED1 da placa,
pisque indefinidamente a cada um segundo. Abaixo, podemos visualizar o
código fonte, que torna isto possível:

Código fonte para o Exemplo 1

Explicação: Os textos em verde são os comentários realizados dentro do


programa para auxiliar na compreensão, isso significa que o programa não irá
rodar estes textos. Efetuar comentários sobre os comandos utilizados e
descrever o programa é totalmente aconselhável, para que no futuro, o usuário
entenda o que foi feito, e qual a finalidade do código fonte. Para inserir um
comentário no seu programa, basta digitar a barra normal duas vezes “//”, e
após realizar a escrita. Tudo que estiver depois das duas barras será entendido
como um comentário, e tudo que estiver antes na mesma linha, será entendido
como comandos a serem executados. O programa inicia com a função “void
main()”, esta é a primeira instrução que o PIC irá executar, quando for
inicializado. Como o “void main()” é executado apenas uma vez, é necessário
inserir um laço infinito, no que se deseja executar indefinidamente. O comando
“trisa = 0;” configura todo port A como saída. Lembre-se: 0 (Output) é saída; e
1 (Input) é entrada. Abaixo do comando tris, podemos visualizar a seguinte
linha: “porta = 0” e ela define que os pinos do port A iniciarão em low (nível
baixo). Logo depois, você encontra o laço infinito “while(1)”. Tudo que estiver
dentro deste comando, será executado indefinidamente pelo microcontrolador.
Após “porta.ra3 = 1;” , seta o pino RA3 (onde o LED1 está) para nível alto,
acendendo o led. Depois, “delay_ms(1000);”, dá o tempo que ele permanecerá
aceso, ou seja, por 1000 milisegundos (1 segundo). Finalmente, “porta.ra3 =
0;”, seta o pino RA3 para o nível baixo e apaga o led, com delay de 1 segundo
novamente. Logo depois disso o ciclo se repete a partir do laço infinito
“while(1)” e teremos o efeito de pisca led. Para melhor visualização da
instrução delay, altere os valores de 1000 milisegundos, para 500 (meio
segundo), para 2000 (dois segundos), para 10000 (dez segundos), ou
quaisquer outros valores desejados. Isto é interessante para que você assimile
bem o funcionamento do comando delay, muito empregado em códigos fonte
diversos.
 Exemplo 2: LED1 e LED2 piscando alternadamente

O próximo código fonte faz os led’s programáveis da Paradoxus 9


piscarem alternadamente a cada meio segundo. Preste bastante atenção neste
programa, pois fazendo pequenas modificações nele você poderá criar os mais
diversificados efeitos de leds. Abaixo, o código fonte do exemplo 2:

Código fonte para o Exemplo 2

Explicação: Agora foi utilizada uma outra técnica para setar em high os pinos
desejados - os números binários. Quando trabalhamos com números binários,
todos os bits do respectivo port são acionados simultaneamente. Para
determinar que utilizaremos binários, escrevemos 0 (zero) seguido de “bê”
minúsculo (b). Em seguida, escrevem-se 8 caracteres, que devem ser somente
zero (0) ou um (1). Zero indica que aquele pino estará, naquele momento, em
low; e um, por sua vez, indica que o pino estará em high. Por exemplo, se
escrevermos “porta = 0b00000001;”, estamos dizendo que somente o pino RA0
estará em high (a contagem é feita de trás pra frente). Isso significa que o
último caractere é o pino RA0, o penúltimo é o RA1, o antepenúltimo é o RA2 e
assim por diante, até chegar no primeiro que é o RA7. No caso deste
programa, escrevemos “porta = 0b00001000;”, ou seja, estamos setando o
RA3 em nível high, acendendo assim o LED1. Depois de um delay de meio
segundo, o código apresenta “porta = 0b00000100;”, informando que apenas o
RA2 será nível high, seguido de um novo delay de meio segundo. Somando
isso ao laço infinito “while(1)”, teremos o efeito de leds piscando
alternadamente. Para criar outros efeitos, basta alterar o tempo de delay, a
ordem de acionamento dos pinos dos led’s programáveis e diversas outras
alterações. É importante que o usuário experiente diversas alterações nos
códigos fonte aqui descritos, para ir incrementando e aprendendo os mesmos
de maneira intuitiva.
 Exemplo 3: Multi efeito com os led’s programáveis

O programa a seguir é um aperfeiçoamento do já utilizado no Exemplo 2,


que faz apenas os led’s programáveis da Paradoxus 9 piscarem
alternadamente. Se você testou outros tempos de delay, e outras sequências
de acionamento, já deve ter percebido que os mais diversos efeitos podem ser
criados. Este código fonte faz o LED1 e o LED2 piscarem em diferentes tempos
e sequencias, revelando efeitos interessantes.

Código fonte para o Exemplo 3


Explicação: A única diferença para o programa do Exemplo 2, é que foram
digitadas mais linhas dentro do laço while. Observe que os tempos de delay
foram os mais diversos e que em algumas situações ambos os led’s
encontram-se em nível high, justamente para criar um efeito bem diferenciado.
Experimente os mais diferentes tipos de delay e configurações de acionamento
para os led’s programáveis da placa, e adicione mais linhas de comando se
quiser obter efeitos ainda mais diversificados, é um ótimo exercício para você ir
aprendendo programação.
 Exemplo 4: Controlando led’s com botões (1)

Até aqui só havíamos utilizado os pinos do PIC como saída. Agora


iremos aprender como utilizá-los também como entrada, aproveitando os
próprios botões (S1 e S2) e led’s (LED1 e LED2) programáveis do circuito
Paradoxus 9. O domínio do uso dos pinos do microcontrolador também como
entrada é de extrema importância, afinal é desta forma que posteriormente os
sensores dos robôs irão operar. Abrindo um breve parênteses: os sensores
detectarão as condições do meio ao qual o robô se encontra, e são estas
condições que vão estimular os sensores (que podem ser os mais variados
possíveis), enviando nível alto ou baixo para entrada do microcontrolador.
Atribuindo um laço de condição ao programa, temos a possibilidade de tornar a
unidade robótica autônoma. Um exemplo de sensores bem simples que podem
ser implementados são bumpers de colisão, que consistem em chaves do tipo
microswitch instaladas na parte frontal do chassi, que informam ao circuito o
fato do robô ter tocado algum obstáculo.
Este primeiro exemplo de controle de botões faz com que S1, quando
pressionado, acenda o LED1 e S2, quando pressionado, acenda LED2. Após
pressionarmos ambos os botões, os led’s ficarão acesos, até que o PIC seja
resetado. Pressionando o botão RESET, da placa, os led’s se apagam, e os
botões S1 e S2 poderão ser pressionados novamente.

Código fonte para o Exemplo 4


Explicação: Este programa contém alguns detalhes diferentes se comparado
aos exemplos já demonstrados. Iniciamos o programa com o comando “cmcon
= 7;”, que tem a função de desativar os comparadores analógicos/digitais
presentes no port A do microcontrolador. Sem este comando, o programa não
funcionaria. Logo após, configuramos pino por pino a ser utilizado com
“trisa.raN = Input ou Output;”, onde N é o número do respectivo pino (RA0,
RA3, etc) e Input ou Output são configurações de entrada ou saída,
respectivamente. É lógico que habilitamos os pinos RA1 e RA0 como entradas,
pois são neles que os botões da Paradoxus 9 estão conectados. RA3 e RA2
foram novamente definidos como saídas. Depois ainda configuramos os pinos
dos led’s para iniciarem em nível lógico baixo. Então, aplicamos o laço infinito
while, seguido de dois laços de condição. Um laço de condição é o que utiliza o
comando “if”. Para “if(porta.ra1 == 0)”, lê-se “Se o pino RA1 do
microcontrolador estiver em nível baixo…”. Depois aplica-se entre chaves a
condição “então”, desta maneira: {porta.ra3 = 1;}, e lê-se “…então o pino RA3
passará para nível lógico um. Da mesma forma, o outro laço if irá atuar, só que
para o botão S2 e o LED2: “Se o pino RA0 do PIC estiver em nível baixo, então
o pino RA2 apresentará nível alto”. Repare que o “igual real” é representado
por dois sinais de igual (==), no laço if. Já quando queremos definir níveis
lógicos ou atribuir valores à variáveis, utilizamos apenas um sinal de igual (=).
Outro detalhe a ser explicado neste código fonte é o fato dos comandos if, para
o caso de se usar os botões programáveis S1 e S2, sempre serem iguais a
zero (0). Esta fato é devido os botões estarem ligados ao circuito, através de
resistores de Pull-Up. Estes resistores de Pull-Up tem a função de manter estas
entradas sempre em nível high, exceto quando os botões são pressionados
mandando 0 diretamente para as entradas. Se não utilizássemos estes
resistores, a entrada estaria flutuante, podendo apresentar tanto nível alto
quanto baixo, prejudicando a operação dos botões. Você poderá ver mais
detalhes sobre isso, visualizando os diagramas esquemáticos no arquivo
“Exemplos de Circuitos Para Teste dos Códigos Fonte”.
 Exemplo 5: Controlando led’s com botões (2)

Mais um exemplo de controle de botões on board, que consiste no


controle do LED1 e LED2, com os botões S1 e S2. Porém, agora inserimos um
novo comando em relação ao exemplo anterior. Ao invés dos led’s
permanecerem acesos e só se apagarem com um reset no microcontrolador,
eles apenas acenderão enquanto os botões forem mantidos pressionados. O
que torna isto possível é o comando “else”.

Código fonte para o Exemplo 5

Explicação: A única diferença em relação ao programa do Exemplo 4, é a


inserção do comando “else”, que significa “senão”. Analisando o primeiro laço
“if”, podemos dizer que o mesmo nos diz o seguinte: “Se o pino RA1 do
microcontrolador estiver em nível baixo (botão S1 pressionado), o pino RA3
apresentará nível alto; senão, o pino RA3 estará em low (ou seja, o pino RA1
estará em high – o botão não estará pressionado). A mesma análise vale para
o segundo laço “if”. Para tornar este programa ainda mais interessante você
poderá, por exemplo, adicionar uma linha de delay em cada laço if,
determinando o tempo que em os led’s permanecerão acesos depois que os
botões forem pressionados. Por exemplo, para “delay_ms(1000);”, os led’s
ficam acesos um segundo após o pressionar do respectivo botão, e depois
tornam a apagar. Veja na imagem abaixo:

Melhorando o código fonte do Exemplo 5 com delays: Delay de 1 segundo


inserido no primeiro laço if. O mesmo delay pode ser colocado no
segundo laço if.

Este simples programa, contendo delays específicos poderá ser utilizado


como temporizadores, por exemplo, para jogos ou até mesmo aplicações mais
específicas, acionando relés para ligar ou desligar cargas maiores. Você
poderá estipular um tempo de um minuto, ou quanto desejar, para jogos. O
jogador pressiona o botão e o led permanece aceso por um tempo determinado
pelo delay, no qual o adversário terá de realizar uma tarefa. Poderá inserir um
relé, mas aí utilizando o port B da placa, e controlar o ligar e desligar de
aparelhos de TV, rádio, ou outros. Enfim, as aplicações para temporizadores
(timers) são as mais diversas possíveis.
 Exemplo 6: Controlando led’s com botões (3)

Desta vez iremos controlar os led’s programáveis da Paradoxus 9 da


seguinte forma: Pressionando S1 o LED1 acenderá e permanecerá aceso, até
que, ao pressionarmos novamente S1, o LED1 se apagada; e assim
sucessivamente. Se pressionarmos e deixarmos o led aceso, assim ficará até
que o botão seja novamente pressionado. A mesma coisa irá acontecer com
S2 e LED2. O diferencial deste código fonte é que para conseguirmos este
efeito, teremos que declarar variáveis, procedimento muito útil, que nos fornece
alguns “atalhos” para códigos mais complexos.
Código fonte para o Exemplo 6

Explicação: O programa tem início com a declaração de duas variáveis:


“paradoxus” e “wrkits”. Qualquer palavra pode ser empregada para declaração
de variáveis, desde que não contenha caracteres da língua portuguesa
(acentuação, cedilha, etc) e não seja uma palavra reservada da linguagem C
(comandos em geral). Um dos comandos que pode ser utilizado para declarar
uma variável é o char (caractere). Para “char paradoxus = 0;”, dizemos que
paradoxus é uma variável do tipo caractere e a mesma iniciará em nível 0. O
mesmo vale para a segunda variável por nós declarada “wrkits”. Em seguida
desabilitamos os comparadores A/D do PIC (cmcon = 7) e configuramos
nossas entradas e saídas, respeitando os pinos específicos em que os botões
e led’s estão conectados. Novamente utilizamos um laço infinito while, seguido
desta vez de quatro laços de condição if. O laço “if(porta.ra1 == 0 &&
paradoxus == 0)”, lê-se “se o pino RA1 e a variável paradoxus estiverem em
nível 0…”. Note que na linguagem C, a palavra “e” se escreve com dois “e’s”
padrão comercial (&&). E após, temos “porta.ra3 = ~porta.ra3;”, que significa
que o pino RA3 irá inverter seu estado lógico (se estiver em low passará para
high, e vice-versa). O til (~) é o caractére que realiza a inversão. Logo abaixo
há um breve delay de 20 milisegundos para correção de repiques (deboucing,
ruídos, pulsos indesejáveis) que o botão poderia apresentar (por ser um
componente eletromecânico, apresenta níveis de ruído quando pressionado
podendo ocasionar erros na quantidade de pulsos lógicos). Finalmente
dizemos que se a condição if1A for verdadeira, a variável paradoxus
apresentará nível low (paradoxus = 0;), e é este fato que manterá o LED1
aceso. O laço de condição if1B tem a utilidade de inverter novamente o estado
lógico do pino onde está LED1, fazendo com que ele se apague novamente e
assim permaneça até um novo pressionar de S1, onde o ciclo se repetirá. A
mesma análise supracitada, vale para os dois laços if seguintes (if2A e if2B),
porém agora para os pinos RA0 e RA2, e para a variável wrkits. Este programa
pode ser utilizado para ligar e desligar cargas maiores, apenas com o
pressionar de um botão, bastando utilizar o mesmo código para 2 pinos
quaisquer do port B, e conectar um relé através de um transistor drive, por
exemplo (veja mais detalhadamente em “Exemplos de Circuitos Para Teste dos
Códigos Fonte”).
 Exemplo 7: Controlando led’s com botões (4)

Este é o último exemplo de controle de led’s com botões on board. É


claro que há a possibilidade de criação de infinitos programas utilizando
apenas os dispositivos programáveis contidos na própria placa Paradoxus 9,
mas aí deixaremos a imaginação do leitor trabalhar um pouquinho. O Exemplo
7 é bastante útil, pois com ele temos a base para utilizar dois programas
diferentes para o mesmo robô, sem a necessidade de regravar o PIC para
alternar entre um algoritmo e outro. Graças aos dois botões programáveis do
circuito (S1 e S2), isto será possível. Neste caso, controlaremos apenas os
led’s, mas aí basta adaptar o código, aos dispositivos utilizados externamente
ao circuito. Basicamente é isto que o código fará: Pressionando S1, os led’s da
placa piscarão alternadamente, ora um ora outro. Pressionando-se RESET eles
param e aí poderemos pressionar S2. Ao pressionarmos S2, ambos os led’s
piscarão juntos, à razão de meio segundo. Novamente, para pararmos o
programa, a tecla RESET deverá ser apertada. Logo, basta escolher entre um
programa ou outro, sempre pressionando RESET e aí pressionando a tecla do
respectivo programa que se deseje rodar. Em uma unidade robótica podemos,
por exemplo, fazer com que o robô desvie obstáculos de acordo com a leitura
dos sensores pressionando-se S1, e pressionando-se S2, fazer com que o robô
apenas realize uma sequência de passos, tais como andar pra frente por 2
segundos e fazer curva à direita, ou qualquer outra sequência de passos
previamente programada. Teremos assim a possibilidade de se “programar” ou
escolher o programa que o robô efetuará manualmente, sem a necessidade de
se utilizar um computador para regravar o PIC. Outra aplicação para este
programa seria em competições, alterando a velocidade do robô para
determinadas tarefas sugeridas pelo concurso, dentre muitas outras. A
novidade neste código fonte é o uso do laço for, que consiste em um loop
infinito dentro do laço de condição if.
Código fonte para o Exemplo 7

Explicação: Dentro do laço infinito while(1) temos dois laços de condição if,
cada um contendo um laço com loop infinito for(;;) em seu interior. O primeiro
laço de condição, diz que se RA1 passar para nível low, então o
microcontrolador executará o laço for1, repetindo-o constantemente até que o
RESET seja pressionado. O segundo laço de condição define que se RA0
passar para nível low, o laço for2 entrará em operação constante até o resetar
do PIC. Tanto faz qual será o programa ou ordem selecionados pelo usuário,
basta resetar o circuito e escolher qualquer um dos dois “programas”
pressionando S1 ou S2. Adiante, traremos outras explicações sobre o comando
for, muito útil para programação em C.
 Exemplo 8: Sequencial de led’s

Sequenciais de led’s são efeitos bastante populares em se tratando de


programação de microcontroladores. Neste Exemplo 8, o primeiro off board,
apresentamos duas maneiras de se programar a Paradoxus 9, para efetuar
uma sequencial de led’s empregando todos os pinos do port B. Na apostila
“Exemplos de Circuitos Para Teste dos Códigos Fonte”, você encontrará a lista
de componentes para que possa testar esta sequencial, o diagrama
esquemático, o desenho físico do circuito em protoboard e sua explicação de
funcionamento.
O primeiro código fonte apresentado, faz uso de uma variável que
assumirá todo port B e também utiliza do comando shift left, que serve para
deslocar os bits do port B para esquerda, gerando nossa sequencial.

Exemplo 8: Código Fonte A

Explicação: A função main inicia com a declaração de uma variável “w” e com
a informação de que a mesma inicia em nível high. Em seguida, com o
comando “trisb = 0;”, configuramos todo port B do PIC como saída e definimos
que estes pinos iniciarão em nível low (“portb = 0;”). O loop infinito é aplicado
com o auxílio do laço “for(;;)”. A variável “w”, assumirá então todo o port B com
o comando “portb = w;” e um delay de 300 milisegundos determina o tempo de
nossa sequencial. Finalmente, entramos com um shift left (“w=w<<1”), que faz
os bits do port B se deslocarem para esquerda, um após o outro. O laço de
condição “if(w==0)w=1;” determina que ao chegar ao último bit, ele retornará
para o primeiro. Se não utilizássemos este último laço, a sequencial iria “correr”
apenas uma vez. Observe no programa: se tivermos apenas um comando
dentro do laço if, as chaves “{ }”poderão ser suprimidas.
O efeito produzido pelo segundo código fonte do Exemplo 8 é
exatamente o mesmo do que o apresentado pelo primeiro algoritmo. A
diferença está na apresentação do programa, e dos comandos utilizados. Ao
invés de utilizarmos o shift left para deslocarmos os bits um a um, agora nós
faremos os bits se deslocarem manualmente. Esta forma de apresentação de
código, é bem útil para o leitor visualizar perfeitamente como se dá o
deslocamento de bits pelo port B. Com simples alterações de bits, fica bem
simples de se criar diversas sequenciais a partir deste segundo exemplo.

Exemplo 8: Código Fonte B

Explicação: Este segundo código, apesar de mais extenso, poderá ser mais
facilmente assimilado pelos iniciantes, já que podemos ver claramente o
deslocamente de bits que produz a sequencial de led’s. Após configurarmos o
port B como saída e para iniciar em low, utilizamos um laço infinito while, que
garante que a sequencial prosseguirá sem interrupções. Então, com a lógica
binária, setamos os pinos com nível 1, na sequência que desejarmos,
intercalados por delays de 300 milisegundos. Observe o número 1 que se
desloca em cada comando “portb = 0b00000001;”. Cada número 1,
corresponde ao respectivo led que estará aceso naquele momento. Então, para
produzir novas sequencias, basta alternar o número 1 à vontade. Você poderá
por exemplo, fazer com que mais led’s estejam acesos ao mesmo tempo,
bastando trocar os zeros (led’s apagados), por uns (led’s acesos), conforme
aprendemos na introdução à lógica digital e também os tempos de delay.

Abrindo um breve parênteses, em linguagem C a forma geral do laço for


é a seguinte:

for (inicialização; condição; incremento)


{
comandos;
}

Na inicialização, atribui-se um valor a uma variável de controle para


determinarmos o início do laço de repetição. A condição determina quando o
laço de repetição termina após testarmos a variável contra algum valor. O
incremento determina como a variável mudará a cada repetição do laço. As
três instruções citadas devem ser separadas por ponto-e-vírgula “;”. A variável
de controle pode ser declarada do tipo inteiro, com o comando int.

Abaixo um breve exemplo de um trecho de código que traz uma


sequencial de dois led’s, ligados em RB0 e RB1, que se repetirá 20 vezes, com
delay de 1:

int i=0; //declaração de variável do tipo inteiro, chamada “i”, valendo 0

for ( i = 0; i < 20 ; i = i +1)


{
portb = 0b00000001;
delay_ms(1000);
portb = 0b00000010;
delay_ms(1000);
}

Obviamente, o código não está completo, mas já dá ao usuário uma boa


noção de como utilizar o laço de repetição for para fazer seqüenciais diversas
na Paradoxus 9. A variável i, a cada repetição da seqüencial, passará a valer
mais um. Quando i chegar a 19, o laço termina e o programa segue adiante,
nos comandos que estiverem depois da chave de fechamento do laço. Para
mais repetições da mesma sequencial, basta alterar o valor de 20 para o
número desejado de repetições. Faça os testes para estudar a lógica do laço
for.
Outra característica do laço for, é que o mesmo não necessita de
parâmetros para funcionar. Por isso, quando escrevemos no programa “for( ; ;)”
e deixamos os parâmetros vazios, o compilador entende como loop infinito.
 Exemplo 9: Simples Semáforo

Outro exemplo bem simples porém eficaz para aplicações práticas,


desta vez para os entusiastas de modelismo, ou mesmo os curiosos. Um
simples semáforo pode ser facilmente programado com a Paradoxus 9, da WR
Kits. Utilizando apenas 6 pinos do port B da placa, o leitor poderá programar
um semáforo para um cruzamento de duas ruas, o que é muito útil para dar
mais realismo em maquetes ou em pistas de ferromodelismo. Outro circuito off
board, cujo diagrama esquemático é apresentado no arquivo “Exemplos de
Circuitos Para Teste dos Códigos Fonte”, contido no disco de drivers. Nosso
exemplo utiliza led’s verdes, amarelos e vermelhos representando o semáforo,
mas o leitor mais experiente em eletrônica, poderá até adaptá-lo para utilização
com cargas maiores tais como lâmpadas, empregando etapas de potência com
TRIAC’s, por exemplo.

Exemplo 9: Código Fonte

Explicação: Novamente foi utilizada a praticidade da lógica binária para


programar os pinos de saída do port B concomitantemente. O port B foi
configurado como saída e para iniciar em nível zero. Dentro do laço infinito está
o programa de nosso semáforo. O pino RB2 está em sinal verde para a
primeira via (led verde) e o pino RB3 está em sinal vermelho (led vermelho)
para a segunda via. Após um delay de 14 segundos, o sinal verde muda para
amarelo (led amarelo), pois o pino RB1 está em nível um, mas o RB3
permanece em high, apresentando sinal vermelho por mais 1 segundo.
Somados os dois primeiros delay’s, temos então 15 segundos de tempo entre a
mudança de sinal de uma via para a outra. Agora quem estará em high é o
RB0 (sinal vermelho da primeira via) e o RB5 (sinal verde da segunda via),
permanecendo assim por 14 segundos, até que o RB4 indicará amarelo para a
segunda via e o RB0 continuará indicando vermelho para a primeira.
Passando-se 1 segundo, o laço while fará a sinaleira voltar à posição inicial,
com sinal verde para a primeira via e sinal vermelho para a segunda e o ciclo
se repetirá, por tempo indeterminado.
 Exemplo 10: Driver Básico Para Motor DC

O código fonte deste exemplo não apresenta novidade nenhuma, muito


menos dificuldades. Pode até parecer um programa extremamente ingênuo,
comparado aos demais já apresentados nesta apostila. Mas o que vale aqui é
aprendermos a controlar um pequeno motor de corrente contínua, amplamente
empregado em robôs móveis de pequeno e médio porte. Para tanto, será
necessário um circuito off board, conhecido como driver ou etapa de potência.
O diagrama e a explicação teórica do circuito estão no arquivo “Exemplos de
Circuitos Para Teste dos Códigos Fonte”. Como já foi visto em outros tutoriais,
as saídas do microcontrolador não fornecem corrente suficiente para controlar
determinados dispositivos. Os motores dc, mesmo os de baixa corrente,
enquadram-se neste grupo necessitando, portanto, de um “arranjo” conhecido
como driver. O driver utilizado foi o transistor npn de uso geral BC547,
facilmente encontrado em lojas de eletrônica. Como foi visto no tópico
“Introdução à Lógica Digital”, contido no arquivo “Programação - Tutorial de
Noções Básicas”, um transistor npn passará a conduzir corrente quando em
sua base for aplicado nível lógico 1. O programa abaixo simplesmente alterna o
pino RB0 do PIC, de nível 0 para 1 aplicando esta informação na base do
BC547 a cada segundo, controlando assim, um pequeno motor dc. Isto
significa que o motor aguarda um segundo, gira durante um segundo e pára
novamente, por tempo indeterminado.

Exemplo 10: Código Fonte

Explicação: Como já foi citado acima, não há nenhuma novidade neste


programa. Na função main, configura-se apenas o pino RB0 como saída e para
iniciar em nível low. Depois executa-se um laço infinito while, onde define-se
que o pino RB0 ficará em low, depois passará para high, com delay de 1
segundo. Altere o tempo de delay para observar o comportamento do motor,
verificando o funcionamento do driver. O foco principal deste exemplo é que o
usuário comece a controlar motores a fim de criar programas mais complexos
para controlar robôs no futuro. Note também que para controlar o girar e o
parar de um único motor em um único sentido de rotação, necessitamos de
apenas uma saída da placa Paradoxus 9. Significa que com ela é possível se
controlar até 9 motores desta forma separadamente.
 Exemplo 11: Robô Programável Para Iniciantes

Apenas com a Paradoxus 9 e mais alguns poucos componentes ligados


off board, já é possível de se criar um simples robô móvel programável. O
Exemplo 11, trata-se exatamente disto. Utilizando apenas dois pinos do port B,
dois transistores pnp de uso geral e outros componentes comuns, temos um
robô completo. É claro que o mesmo apresenta certas limitações, já que nesta
configuração não será possível o controle dos motores em ambos os sentidos,
e o robô não apresenta sensores. O que pode ser feito é que o robô ande em
linha reta para frente e realize curvas, simplesmente alterando os tempos de
delay e o nível lógico das duas saídas utilizadas.

Código Fonte para o Exemplo 11

Explicação: Outro código fonte bem simples, se comparado aos anteriores já


vistos nesta apostila. Configuramos o portb como saída e para iniciar em nível
1. No laço infinito, modificamos o nível lógico dos pinos RB0 e RB1, pois cada
um deles está conectado a um driver, e cada driver controla um motor. Isto
torna possível os seguintes controles para este simples robô: andar em linha
reta para frente, parar, fazer curvas à direita e fazer curvas à esquerda.
Modifique a vontade os tempos de delay e também a sequência de
acionamento dos pinos, programando este robô da sua maneira. Como
estamos utilizando transistores pnp, os motores estarão girando quando o
respectivo pino de controle receber nível low. Outra ideia interessante seria a
adição de led’s nos outros pinos, criando efeitos visuais programáveis para
robô.
 Exemplo 12: Robô Elementar Que Detecta Obstáculos

A característica de intereção com o meio a qual se encontra é de grande


valia para robôs móveis. Neste exemplo apresentamos um robô elementar
capaz de detectar obstáculos que surjam em seu caminho como objetos, por
exemplo. Este fato dá ao robô funções autônomas. Para que possa “enxergar”
ou “sentir” um obstáculo em sua frente, o robô necessita do uso de sensores.
Para falar de sensores seria necessário um único tutorial e, por este motivo,
não entraremos nos pormenores sobre sensores na robótica. Os sensores
consistem tipicamente em dispositivos que detectam mudanças de estado tais
como iluminação, calor, pressão, colisão, e vários outros. O dispositivo sensor
detecta a mudança nestes estados e às converte em pulsos elétricos. Temos,
portanto, com as devidas adequações, formas de aplicar pulsos ora no nível
high ora no nível low, na entrada do microcontrolador. O robô do exemplo,
como o próprio nome sugere, faz uso do tipo de sensor mais elementar: os
bumpers de colisão. Um bumper de colisão nada mais é do que uma chave de
contato simples que, quando pressionada, modifica o nível lógico da porta a
qual estará conectada. É o que fazem os botões programáveis on board S1 e
S2 da Paradoxus 9. Neste simples exemplo, temos dois sensores de colisão,
utilizando de chaves microswitch, que mudam o nível lógico de dois pinos do
portb da Paradoxus 9. O algoritmo utilizado terá certa semelhança com os dos
exemplos de controle de led’s com botões, no início deste tutorial.
Empregaremos dois laços de condição if, um para cada bumper. O diagrama
eletrônico do Robô Elementar está contido na apostila que traz exemplos de
circuitos para estes códigos fonte.
Código Fonte para o Exemplo 12

Explicação: Na função main, determinamos que os comparadores


analógico/digitais não estarão ativados, com o comando “cmcon = 7;”. Após,
utilizando a lógica binária, configuramos os pinos RB2 e RB3 como entrada
digital, e todos os demais pinos do port B como saída, empregando o comando
“trisb”. Novamente com a lógica binária, fazemos com que RB0 e RB1 iniciem
em high, isto faz com que os motores permaneçam girando e o robô se
deslocará para frente. Aí entram dois laços de condição if, dentro do laço while,
que determinam que, se os bumpers de colisão forem acionados, o respectivo
motor para de girar, do contrário (comando else), eles continuam girando. Este
fato torna possível ao robô “sentir” um obstáculo, contornando-o. Para obter
ainda mais detalhes, veja o diagrama esquemático deste circuito com outras
dicas na apostila que traz exemplos de circuitos para uso dos códigos fonte.
 Exemplo 13: Contagem de 0 a 9 com Display de 7 Segmentos

Os displays são dispositivos amplamente utilizados nos equipamentos,


desde industriais até domésticos. Na indústria, fornecem dados como
temperatura, pressão, contagem de peças, medições, dentre muitos outros. Em
nossa casa, estão presentes em aparelhos de som, micro-ondas, celulares e os
mais diversos que o leitor já está identificando. Na robótica, começam a ser
cada vez mais difundidos, para informar a posição de robôs manipuladores,
para incrementar o aspecto visual da unidade, para identificar o que o robô está
“vendo”, e mais uma infinidade de coisas. Sendo a Paradoxus 9, da WR Kits,
uma placa micro controlada extremamente versátil, não poderíamos deixar de
enfatizar o controle de displays, aqui nesta apostila de exemplos.
O Exemplo 13, traz o controle de um display muito simples, porém
bastante útil: o display de 7 segmentos, catodo comum. O mesmo, nada mais é
do que o conjunto de 7 led’s, dispostos geometricamente, afim de formar os
dígitos necessários para composição de caracteres, no caso, tipicamente
numéricos. O que temos aqui é uma contagem de 0 a 9, empregando um
destes displays, ou seja, um timer progressivo com indicação visual numérica.

Código Fonte para o Exemplo 13

Explicação: Como pode ser observado, o código fonte acima não é muito
extenso, porém nele são empregados novos conceitos. Três variáveis do tipo
char são declaradas inicialmente, enviando zero para cnt. Criamos agora uma
variável do tipo vetor, com o nome “segmento”, e a ela são enviados os
valores, desta vez em hexadecimal, dos números pertinentes aos bits que irão
formar os caracteres de 0 a 9 no display de 7 segmentos. Repare que para
declararmos um vetor em C, utilizamos os comandos de declaração de variável
(char, int, etc), damos um nome ao vetor seguindo as mesmas normas de
nomeação de variáveis e no final abrimos e fechamos colchetes “[ ]”. A forma
genérica de declaração de um vetor em C é esta:

int nome_do_vetor [tamanho];

Observe que o espaço entre colchetes é destinado à colocarmos o


tamanho do vetor. Para um vetor de 10 posições por exemplo, poderíamos
declarar:

int nome_do_vetor [10];

Entretanto, se não soubermos ao certo o tamanho que nosso vetor irá


apresentar, podemos simplesmente abrir e fechar colchetes, não informando
nenhum número. Mesmo conhecendo o tamanho do vetor, também podemos
omitir o número na declaração, que foi o caso de nosso exemplo.

Voltando ao código do exemplo, como já foi dito, um display de 7


segmentos consiste em 7 led’s, um para cada segmento. Estes led’s ficam
geometricamente instalados formando assim os caracteres numéricos. Para
acender estes led’s separadamente, temos que enviar nível lógico alto para as
saídas onde os mesmos estarão conectados. Desta vez não utilizamos lógica
binária para informar os bits que serão levados a high, mas sim, lógica
hexadecimal. Para inserir valores em hexadecimal na linguagem C, basta
digitarmos “0x...” e o número equivalente hexadecimal desejado. Lembrando
que para binários, digitávamos “0b...” e em seguida os 8 bits da saída do portB
que queríamos que estivessem em high ou em low. Podemos trabalhar com
lógica decimal também, substituindo os valores em hexa pelo número decimal
equivalente, obtendo assim, a saída em binário desejada. Dica: a calculadora
do Windows, faz a conversão de valores hexadecimal para binário, decimal ou
octal. Para facilitar o entendimento, fornecemos a tabela 1 abaixo, com o
número hexadecimal, o número binário, o número decimal e o número que o
display exibirá quando utilizarmos cada exemplo. Vale frisar que não podemos,
por exemplo, escrever o número 5 no código, e esperar que o display exiba o
caractere “5”, pois as 8 saídas do portB não enviarão nível high nos segmentos
corretos. É claro que em alguns casos, os valores podem coincidir. Compare a
tabela 1 abaixo, e faça os testes, substituindo os valores em hexa, por lógica
binária e depois por valores em decimal, verificando o número exibido no
display.
Tabela 1: Valores em hexadecimal, binário e decimal para formação dos
dígitos no display de 7 segmentos

Em seguida, utiliza-se a instrução for como laço infinito. Dentro deste


laço, o valor de cnt, dentro do vetor segmento, é enviado como ponteiro para a
variável pattern. A variável cnt é utilizada como um ponteiro que diz a posição
da matriz segmento que ele quer retornar para pattern. Para saber mais
detalhes sobre o conceito de ponteiros, pesquise sobre “ponteiros em
linguagem C”. Após, basta enviar pattern para todo portB, seguido de um
incremento em cnt, com a instrução “cnt++;”. O laço de condição if serve para
informar que quando cnt chegar na décima posição, ele retornará para a
primeira. O comando de delay define o tempo da mudança de um número para
outro. Este código fonte ilustra a operação com display de catodo comum.
Caso o usuário deseje, poderá utilizar um display de anodo comum sem
problemas. Para isto, basta inverter os bits enviados para portB, com o
comando “pattern=~pattern”, que, como já vimos, informa que “a variável
pattern é igual ao seu inverso”.
 Exemplo 14: Cronômetro regressivo de 10 segundos com Display de 7
Segmentos

Dando sequência nos projetos com display, iremos agora ilustrar uma
contagem regressiva de 10 segundos com display de 7 segmentos de catodo
comum. Trabalharemos desta vez com lógica binária, pois a principal diferença
deste exemplo para o anterior é no hardware. Como o usuário deve ter
percebido, o uso de um display de 7 segmentos ligado diretamente nas saídas
do microcontrolador, acaba ocupando 7 pinos do portB, impossibilitando
portanto a implementação de outros componentes ou periféricos para o mesmo
PIC. Graças ao uso de outro circuito integrado de tecnologia CMOS, podemos
poupar 3 das 7 saídas normalmente utilizadas para o uso de displays. O
circuito integrado em questão é o decodificador 4511, que converte os 4 bits de
entrada binária, para o número decimal já relativo aos segmentos do display
(veja mais detalhes no tutorial “Exemplos de Circuitos Para Teste dos Códigos
Fonte”). Certamente o usuário já está imaginando o quão mais versátil se
tornará o uso de displays com o auxílio desde chip decodificador. Podemos
também, controlar até dois displays de 7 segmentos independentemente,
utilizando os 8 pinos do portB, bastando para isso utilizar dois CI’s 4511. Com
isso, é possível de se fazer uma contagem de 00 a 99, por exemplo. É claro
que para esta função, também existe a técnica conhecida como multiplexação
de displays, mas isto é outra história. A principal utilidade do Exemplo 14 é o
uso de um único display, ocupando apenas 4 saídas da Paradoxus 9, deixando
as outras 5 livres para implementação de outros componentes ou sistemas
sensores, etc.
Exemplo 14 e respectivo código fonte

Explicação: O código fonte do Exemplo 14 confirma que de fato a novidade


aqui é principalmente no hardware. Inicialmente determinamos que todo portB
será saída e que o mesmo iniciará em nível lógico baixo. Após, o comando
while(1) é utilizado como laço infinito, logo, apenas para uma breve revisão,
tudo que estiver neste comando será executado por tempo indeterminado, só
sendo interrompido quando o botão RESET é pressionado ou então quando a
Paradoxus 9 for desligada. Utilizando a lógica binária, mandamos os números
de 9 até 0 nos pinos RB0 a RB3, onde o CI 4511 está conectado. A diferença
aqui é que os bits em binário de fato correspondem aos números 9 até 0, nesta
ordem, provando que a “conversão” para o mostrador de led’s é realmente feita
pelo chip decodificador. Na tabela 2, apresentamos os números de 9 a 0 (em
ordem decrescente, pois trata-se de um cronômetro regressivo) em binário,
decimal, e o número exibido pelo display.
Tabela 2: Binário para Decimal

Observando a tabela 2, a conclusão que se tira é que, se enviarmos os


valores decimais para o portB, intercalados também com delay de 1 segundo, o
PIC se encarregaria de convertê-los para saída binária e, o decodificador por
sua vez, convertê-los novamente para decimal! Faça o teste, substituindo a
lógica binária do código fonte por lógica decimal “portb = 9; , portb = 8; , etc”.
 Exemplo 15: Exibição de Mensagem em Display LCD

Os displays LCD são extremamente úteis para aplicações em robótica e


automação. Nestes sistemas podem ser empregados displays LCD
alfanuméricos e até mesmo displays gráficos. Na indústria, tem a função de
exibir contagem de peças, dados como pressão ou temperatura (assim como
os displays comuns de 7 segmentos), porém apresentam a grande vantagem
de poder inserir textos, proporcionando uma melhor interação homem -
máquina. São cada vez mais introduzidos em projetos de robôs móveis, como
mostrador de status (nível de carga da bateria, detecção de obstáculos, etc) ou
muitas vezes como mero incremento visual. Podemos instalá-los em robôs
autônomos, fazendo com que informem a situação a qual o robô se encontra,
por exemplo, “Robô Pronto, Robô Detectou Obstáculo, Trajeto Desconhecido,
N Obstáculos Encontrados” dentre infinitas possibilidades.
O Exemplo 15, consiste basicamente na configuração de um display
LCD de 16x2 (16 colunas por 2 linhas) e culminando na exibição de uma
mensagem de texto qualquer. Este exemplo é o mais básico para utilização de
displays LCD e sem dúvida será de grande utilidade para o projetista. A
Paradoxus 9 proporciona o controle de displays LCD de interface paralela,
tipicamente.
Código Fonte para o Exemplo 15

Explicação: Diferentemente do exemplo anterior, neste código fonte surgem


algumas novidades. A primeira delas consiste no aproveitamento da região de
comentários para organizar melhor o código. Observe que separamos o código
em quatro regiões: Configuração do Módulo LCD, Configuração dos PORTS,
Início do LCD e Laço Infinito. Esta sistemática pode ser aplicada em qualquer
código fonte, principalmente em códigos mais complexos, justamente para
facilitar a posterior atualização dos mesmos. Novamente fazendo uma revisão,
lembre-se, para inserir comentários basta digitar barra comum duas vezes “//”
e, tudo que for comentário, não será compilado, isto é, tem apenas a função de
organizar ou mostrar informações adicionais sobre o código. Na região de
Configuração do Módulo LCD, introduzimos um novo comando chamado sbit,
que serve essencialmente para definir a comunicação entre os pinos do
microcontrolador e os pinos do display LCD. A sintaxe é realizada da seguinte
forma: “sbit LCD_RS at RB0_bit;”, onde RB0 é o pino do microcontrolador que
será conectado ao pino RS do display LCD, e assim por diante, até que todos
os pinos do LCD estejam configurados. O usuário poderá configurar a saída de
bits da forma que lhe convir, já que não importa a ordem. A atual organização
foi selecionada apenas para simplificar ao máximo o entendimento. Veja que o
pino D4 do LCD está no RB4 do PIC, o D5 está no RB5, e assim
sucessivamente, mas isto é meramente para facilitar a sintaxe, cabendo ao
usuário escolher a configuração melhor para o seu projeto. As três regiões
seguintes estão contidas na função void main(). Na configuração dos ports não
há novidades no código, apenas é designado que todo portB será saída
utilizando lógica binária e a instrução “tris”. O comando em lógica hexadecimal
“CMCON = 0xff”, não é obrigatório neste programa, pois não utilizamos
entradas no portA do PIC. Mas já foi inserido para o caso de o projetista
resolver utilizá-las. Este comando desabilita os comparadores A/D do
microcontrolador. Ele já havia sido utilizado, porém com lógica decimal, nos
primeiros exemplos de controle com botões deste tutorial. Logo abaixo
encontra-se a região nomeada de Início do LCD, onde são determinados os
comandos iniciais do display. “Lcd_Init();” serve apenas para inicializar o
mostrador, “LCD_Cmd(_LCD_CLEAR);” limpa a tela e
“LCD_Cmd(_LCD_CURSOR_OFF);” apaga o cursor do display. O cursor é
como a barrinha de prompt que fica piscando quando estamos digitando algum
texto. Se quisermos que o mesmo esteja visível, basta substituir pela instrução
“LCD_Cmd(_LCD_CURSOR_ON);”. A região de Laço Infinito é o trecho de
código que será executado indeterminadamente até que o PIC receba pulso de
reset ou a alimentação seja cortada. Como o display do exemplo apresenta
duas linhas, foram introduzidas mensagens em ambas. Para fazer o LCD exibir
uma mensagem utilize o comando “lcd_Out(1,1,”Digite um texto”);”, onde o
primeiro número dentro do parênteses refere-se à linha (ou seja, primeira linha)
e o segundo número refere-se à coluna (ou seja, primeira coluna) na qual o
texto terá início. Ainda dentro do parênteses, entre aspas, digite a mensagem
desejada para ser exibida no display. Se o seu texto tiver mais de 16
caracteres, os excedentes não serão mostrados, por exemplo, se a mensagem
for “Digite aqui a sua mensagem”, só irá aparecer no display “Digite aqui a su”.
No outro comando lcd_Out foi selecionada a segunda linha do display e
primeira coluna. Faça diversos testes alterando as mensagens e as respectivas
posições de linha e coluna, para entender o funcionando do modo de exibição.

Inserindo mensagens com mais de 16 caracteres

Ainda tratando do Exemplo 15, há um artifício onde um texto com mais


de 16 caracteres pode ser exibido no display: o texto animado. Para isso, basta
incrementarmos a região de Laço Infinito do mesmo código fonte.
Exemplo 15B: Exibição de texto animado

Primeiramente foi inserido o texto “Paradoxus 9”, na primeira linha e


primeira coluna. Como esta será uma mensagem estática, ficará apenas dentro
do laço while(1). Em seguida, um loop infinito foi implementado com o
comando for(;;). Dentro desse laço for, a mensagem animada foi introduzida
com delays de 600 milisegundos na segunda linha e primeira coluna do display.
Observe que a frase utilizada foi “WR Kits Robotica Sem Obstaculos” que
contém 31 caracteres, quase o dobro do máximo permitido para o LCD mas,
com o implemento dos delays e da “animação”, ela pôde ser exibida, criando
um efeito visualmente bem interessante. Vale ressaltar que o display LCD não
aceita caracteres da língua portuguesa tais como acentos, cedilha e outros.
 Exemplo 16: Display LCD interativo

As aplicações para displays do tipo LCD (liquid crystal display) são


inúmeras. Uma delas - largamente utilizada em equipamentos industriais,
domésticos e robôs – é o display LCD interativo, onde o usuário visualiza a
operação realizada no display ou, melhor ainda, o display LCD informa ao
usuário o procedimento por ele efetuado. Esta característica é de grande valia
no quesito interação homem – máquina. O programa do Exemplo 16 fará com
que o display informe qual LED está ligado na Paradoxus 9 (LED1 ou LED2) e
também qual botão deverá ser pressionado para acender o respectivo LED (S1
ou S2). Este código fonte pode ser adaptado pelo projetista para funcionar
como mostrador de status de um robô móvel ou equipamento, por exemplo. O
programa funciona da seguinte maneira: ao energizar a Paradoxus 9, o display
exibirá na primeira linha a mensagem de instrução “Press Sn p/ LEDn”, tal
mensagem foi escolhida pelo simples fato de caber na primeira linha. Qualquer
texto com até 16 caracteres pode ser utilizado. Matematicamente, a
representação de diversos números é dada por “n”. Logo, a mensagem da
primeira linha do display será interpretada como “Pressione o botão S1 para
ligar o LED1 ou pressione o botão S2 para ligar o LED2 e assim
sucessivamente”. É claro que a Paradoxus 9 apresenta apenas dois botões e
dois led’s. Mas este texto de instrução já está prevendo a adição de mais
botões de comando e mais led’s, se forem necessários para o projeto. Num
primeiro instante, a segunda linha do display não apresentará nada. Se S1 for
pressionado, o LED1 irá acender e surgirá na segunda linha do LCD a frase
“LED1 ligado.”. Pressionando-se o botão S2, o display mudará a frase da
segunda linha para “LED2 ligado.”, e de fato, o LED2 da placa acenderá e o
LED1 irá se apagar. Voltando a pressionar S1, LED2 apaga, LED1 acende e o
LCD volta a exibir “LED1 ligado.” na segunda linha, e assim por diante. Para
apagarmos a frase da segundo linha basta pressionarmos o botão RESET, e o
ciclo recomeça. Como pode ser observado, este código fonte é de grande valia
e permite infinitas modificações. Após a análise e explicação do código do
Exemplo 16, outras dicas serão abordadas.
Exemplo 16 e respectivo Código Fonte

Explicação: No programa do Exemplo 16 surgem novidades de linguagem C.


Assim como no exemplo anterior, todo o código foi dividido em regiões, dessa
vez em oito: Define Entradas, Define Saídas, Módulo LCD, Variáveis
Declaradas, Configuração dos Ports, Início do LCD, Iniciando os Bits e Laço
Infinito. As regiões “Define de Entradas” e “Define de Saídas” contém o
comando “#define”, que é um tipo de diretiva para a linguagem C. Toda diretiva
inicia com um sustenido “#” seguida pelo comando específico. Para ter mais
informações sobre esta categoria e conhecer outras diretivas, pesquise sobre
“Diretivas em Linguagem C”. A diretiva “#define” foi inserida justamente para
definir nomes aos pinos utilizados no projeto. Por exemplo, a linha “#define S2
porta.f0” designa que o pino RA0 do microcontrolador se chamará S2. O
mesmo vale para as outras linhas de #define: RA1 se chamará de S1, RA3 se
chamará de led1 e RA2 se chamará de led2. Após isso, toda vez que
escrevermos S2 no código, o compilador entenderá que trata-se do pino RA0.
A mesma analogia é feita para as demais diretivas de #define. Tais pinos foram
definidos porque os dispositivos on board da Paradoxus 9 de fato estão
conectados a eles, através do circuito. A vantagem de se utilizar a diretiva
#define se dá, principalmente ao caso de que, se houver necessidade de
mudar o pino do PIC a ser utilizado, só é necessário fazer a alteração na
diretiva, o restante todo do código fonte já conterá o nome originalmente
designado.
Na região “Módulo LCD”, configuramos a comunicação entre os pinos do
display e as saídas da Paradoxus 9. No Exemplo 15 há mais informações
sobre essa região. Não é obrigatório, mas uma variável foi declarada na região
“Variáveis Declaradas”, apenas para ilustrar outra forma de se utilizar variáveis
e também de se trabalhar com os textos no LCD. A variável é do tipo char e foi
chamada de *mensagem, sendo a ela atribuído o texto “Press Sn p/ LEDn”,
exatamente a mensagem da primeira linha do display. Reparem que na frente
do nome é acrescentado um asterisco “*”. Este asterisco designa que a variável
será uma “string”, isto é, conterá um texto e não um numeral. Toda variável que
receberá uma string (texto), deverá apresentar o asterisco no início da
declaração. Para utilizá-la depois no programa o asterisco é omitido. Na região
“Início do LCD”, são inseridos comandos de inicialização do mesmo,
exatamente como no Exemplo 15. Após, configuramos o estado inicial dos bits
que serão manipulados, na região “Iniciando os Bits”. Observe que os led’s
iniciarão em nível low (apagados) e os botões iniciarão em nível high. Os
botões são configuramos para iniciar em high porque a Paradoxus 9 apresenta
resistores de pull up nestas entradas, garantindo o nível lógico “1”. Do contrário
as entradas estariam flutuantes e a atuação de S1 e S2 poderia apresentar
erros (veja mais informações no arquivo “Programação - Tutorial de Noções
Básicas”).
Finalmente, na região “Laço Infinito”, a operação cíclica do
microcontrolador é definida. Já dentro do laço while(1), a instrução
“lcd_Out(1,1, mensagem);” informa que a variável mensagem será enviada
para linha 1 e coluna 1 do display LCD. No caso, a mensagem será “Press Sn
p/ LEDn”. O primeiro laço de condição if diz que se S1 for igual a zero (botão
S1 pressionado uma vez na Paradoxus 9), então ocorrerão os seguintes
eventos:

- LED1 acende  led1 = 1;


- LED2 apaga  led2 = 0;
- Limpa o display  lcd_cmd(_lcd_clear);
- Exibe na segunda linha e primeira coluna a mensagem “LED1 ligado.” 
lcd_out(2,1, “LED1 ligado);
- Faz delay de 70 milisegundos para correção de debouncing  delay_ms(70);

Da mesma forma, no segundo laço if, caso S2 for pressionado uma vez
na Paradoxus 9, ocorrerão os eventos abaixo:

- LED1 apaga  led1 = 0;


- LED2 acende  led2 = 1;
- Limpa o display  lcd_cmd(_lcd_clear);
- Exibe na segunda linha e primeira coluna a mensagem “LED1 ligado.” 
lcd_out(2,1, “LED2 ligado);
- Faz delay de 70 milisegundos para correção de debouncing  delay_ms(70);

Repare que no código fonte os eventos realizados, caso a condição seja


verdadeira sempre ficam entre chaves “{ }” e separados por ponto e vírgula “;”.
Modifique este programa para adquirir ainda mais experiência na programação
de displays LCD. A mensagem da primeira linha pode ser modifica para um
texto animado como, por exemplo, “Pressione S1 ou S2”, “Pressione os botoes
para acender os LED’s”, etc. Ao invés de utilizar os led’s, o projetista poderá
optar pelo controle de relés com cargas específicas, então o display exibe o
nome da carga e informa se ela está ligada ou desligada. Para aplicação em
robôs móveis que requerem mais pinos de controle, o usuário poderá intercalar
mais um microcontrolador PIC16F628A próprio para o controle do display e já
previamente gravado, fazendo com que sobrem mais entradas/saídas na
Paradoxus 9. Dessa maneira, apenas dois pinos de controle já são suficientes
para emular o display (restando 7 para todos os periféricos do robô).
3 – Robot Paradoxus 9

Os próximos exemplos tratarão da programação do Robot Paradoxus 9,


para os usuários que adquiriram o kit completo. É claro que, quem não adquiriu
o kit completo, poderá aproveitar os próximos exemplos em qualquer unidade
robótica autônoma, projetando seus próprios robôs desde a mecânica (Robô de
Esteiras, por exemplo), até os dispositivos eletrônicos que faltam (sensores,
drivers, módulos extra, etc). Vale salientar que o kit Paradoxus 9, contendo
apenas a placa de execução e o gravador já é um excelente ponto de partida,
já que o cérebro do robô estará pronto para o uso. O kit de robótica Robot
Paradoxus 9 da W.R. Kits contém a placa de execução Paradoxus 9, o
Gravador de PIC ICSP, uma placa driver para dois motores DC, uma placa de
sensores duplos do tipo infra vermelho com filtro de frequência; além de rodas,
pneus, engrenagens, eixos, chassi, parafusos e porcas, cabos e conectores,
chave liga/desliga e suporte de pilhas. Os itens que foram citados consistem no
mínimo possível para se ter um robô móvel autônomo interagindo com o meio.
A placa driver para dois motores DC é baseada no CI L293D, circuito integrado
dedicado contendo duas pontes H e diodos de proteção. Ele contém quatro
entradas (duas para cada motor), que dependendo dos bits aplicados, os
motores responderão girando num sentido ou no outro ou permanecendo
parados. Os sensores do Robot Paradoxus 9 são do tipo infravermelho duplos,
para um melhor “mapeamento” do ambiente. O mesmo apresenta filtro de
frequência, o que evita disparos erráticos por parte do sensor. O circuito
integrado que torna isto possível é o microcontrolador PIC12F675, previamente
gravado. O projetista não precisará gravar este microcontrolador pois o mesmo
já vem contendo o programa de sensoriamento. A placa de sensores apresenta
duas saídas, que serão aplicadas aos pinos da Paradoxus 9. Estas saídas são
mantidas em nível high, até que o sensor detecte um obstáculo à frente,
fazendo com que a respectiva saída vá para nível baixo. Veja mais detalhes
sobre os shields nos arquivos “Exemplos de Circuitos Para Teste dos Códigos
Fonte” e “Robot Paradoxus 9: Manual de Montagem”.
 Exemplo 17: Robot Paradoxus 9 (1)

Função: Seguir um trajeto previamente programado.

Neste primeiro exemplo para o Robot Paradoxus 9, os movimentos da


unidade serão previamente programados pelo usuário, para aprendermos
como controlar os motores independentes do robô móvel com o driver L293D.
Logo, os sensores não serão utilizados. A ideia é fazer com que o robô ande
para frente por um tempo (a), depois vire para a direita (b), ande mais um
pouco para frente na nova direção (c), depois vire para esquerda (d), pare por
uns segundos (e), ande um pouco para trás (f) e recomece o ciclo. Observe
que os passos citados são totalmente randômicos apenas para testar
movimentos possíveis para o robô autônomo e marcamos os mesmos de “a”
até “f”, para facilitar a sequência de execução. O projetista tem toda liberdade
para programar quaisquer passos. Para executar a sequência acima, devemos
mandar os níveis lógicos corretos para as 4 entradas do driver. Na tabela 3,
apresentamos a tabela verdade para as 4 entradas (IN1 a IN4). Veja
atentamente, que para a tabela ser verdadeira, IN1 deverá estar conectado no
pino RB3 da Paradoxus 9, IN2 no pino RB2, IN3 no pino RB1 e IN4 no pino
RB0. Esta configuração foi escolhida porque os bits são enviados sempre de
trás pra frente no código fonte. Mesmo utilizando lógica decimal ou
hexadecimal, os bits serão lidos nessa sequência.

Tabela 3: Tabela verdade do Shield Driver L293D

Observando a tabela 3, a conclusão que se tira é que sempre que


mandarmos nível high somente para as entradas pares (IN2 e IN4), os motores
irão girar no sentido horário. Por outro lado, sempre que enviarmos high para
as entradas ímpares (IN1 e IN3), os motores irão girar no sentido anti-horário.
Finalmente, se mandarmos o mesmo nível lógico para o mesmo par de
entradas, o respectivo motor estará parado. A tabela 3 não é só válida para o
Exemplo 17, mas para todos os exemplos do Robot Paradoxus 9. De acordo
com a construção do Robot Paradoxus 9, onde o Motor 1 é o motor esquerdo
(controlado pelas entradas IN1 e IN2) e o Motor 2 é o motor direito (controlado
pelas entradas IN3 e IN4), extrapolamos a tabela 3 combinando os bits nas 4
entradas do driver, obtendo assim, a ação executada pela unidade robótica
móvel. A tabela 4 exibida abaixo foi o resultado disso, pois nela podemos ver
todas as combinações possíveis de níveis lógicos aplicados às entradas e o
respectivo comportamento do robô, o que facilita muito sua posterior
programação. Como são ao todo quatro entradas a serem programadas,
teremos 16 combinações possíveis para os bits aplicados, 2 que é a base
(binário), elevado a quatro ( ).

Tabela 4: Ações do Robot Paradoxus 9 de acordo com os bits das


entradas do driver L293D

A tabela 4 é uma ferramenta de extrema utilidade, pois com ela


podemos controlar todos os movimentos do robô que desejarmos. Ela contém
a coluna “Ação”, que descreve a resposta dada pela unidade robótica de
acordo com os bits enviados às entradas do driver; a coluna “Entradas / Bits”,
que exibe as 16 combinações possíveis e a coluna “Aplicação no PortB”, que
informa os valores (binário, decimal ou hexadecimal) a serem enviados na
saída do portb para obter-se determinada ação por parte do robô. É importante
frisar que esta última coluna terá acréscimos quando um sensor ou outro
dispositivo forem utilizados. Por exemplo, se quisermos ler a resposta dos
sensores infra vermelho do robô, além dos quatro bits iniciais, teremos que
enviar o nível high aos pinos RB4 e RB5 (portb = 0b00110000;), mas este caso
ficará mais claro no próximo exemplo, onde os sensores são empregados. As
linhas em vermelho da tabela 4 (primeira coluna), são as situações nas quais o
robô ficará parado. As linhas em verde na mesma coluna, são as situações
mais comumente utilizadas: “Gira Para Esquerda” significa que o robô irá virar
para esquerda, girando em torno do próprio eixo, com cada par de rodas se
movendo em sentidos opostos; “Anda Para Trás” fará o robô andar para trás
em linha reta e “Anda Para Frente”, como o nome sugere, fará o robô andar
para frente também em linha reta e “Gira Para Direita” fará o robô virar para
direita também girando em torno do próprio eixo. Com apenas estes quatro
movimentos citados acima já é possível controlar o Robot Paradoxus 9 em
todas as direções. As linhas em amarelo na coluna “Ação” servem para refinar
os movimentos da unidade, mas são menos usuais. Sempre que uma delas for
executada, significa que o robô estará utilizando apenas um motor, o que em
determinadas situações poderá não ser eficiente o bastante. É claro que
sempre haverá casos em que será necessário o uso das mesmas. O comando
“Curva Para Frente à Esquerda” fará a unidade realizar uma curva à esquerda,
com as rodas direitas se movendo para frente; o comando “Curva Para Trás à
Direita” fará o robô efetuar uma curva à direita, com as rodas esquerdas se
movendo para trás; e assim por diante. Note que algumas ações se repetem
mesmo quando bits diferentes são aplicados nas quatro entradas. Isso se dá
pelo fato dos motores pararem tanto pela aplicação de nível alto quanto pela
aplicação de nível baixo (mesmo nível lógico nas duas entradas – IN1 e IN2 ou
IN3 e IN4).
Agora que temos a tabela que rege as ações do Robot Paradoxus 9,
ficou fácil de criar um código fonte que execute a sequência de 6 etapas (“a”
até “f”), criada acima. A tabela 4 poderá ser consultada pelo projetista sempre
que desejar sequências diferentes de controle do robô.

Código Fonte para o Exemplo 17


Explicação: A única novidade no código fonte do Exemplo 17 é a instrução
“goto” (ou seja, “vai para”). Este comando pode ser também empregado como
laço infinito, o que foi o caso deste programa. A palavra criada “Inicio:” seguida
de dois pontos ( : ) designa o ponto inicial do programa nesse caso. Com o
comando “goto Inicio”, dizemos ao compilador que o mesmo deverá ir para o
ponto “Inicio”. Como o ponto “Inicio” localiza-se antes do comando “goto”,
temos um laço que se repetirá indefinidamente. A instrução goto também pode
ser utilizada para mandar o compilador pular linhas de código, para isso, a
palavra criada deverá estar abaixo da instrução. Esta palavra pode ser
qualquer uma, desde que não seja uma palavra reservada da linguagem C e
que não contenha caracteres da língua portuguesa (acentos, cedilha, etc). O
resto do programa, nada mais é do que a já conhecida configuração dos pinos
do PIC, e a sequência seguida utilizando-se lógica binária, respeitando a tabela
4, para que o robô ande no trajeto desejado. Altere a vontade o código acima,
trocando os tempos de delay, ou mesmo a sequência de passos que o Robot
Paradoxus 9 deverá executar. É importante que o usuário aprenda a controlar
bem o meio de locomoção do robô, no caso as rodas, para direcioná-lo
corretamente fazendo-o cumprir as tarefas necessárias.
 Exemplo 18: Robot Paradoxus 9 (2)

Função: Desviar de obstáculos.

O que caracteriza um robô como autônomo é sua capacidade de


interação com o meio a qual se encontra, sem a necessidade de controle
remoto, exercendo funções previamente programadas ou não. O intuito
principal do kit é permitir que o usuário possa montar um robô autônomo
completo, totalmente programável, para executar as mais diversificadas
funções. O desvio de obstáculos é uma das funções primordiais para um robô
autônomo. E esta é a ideia do Exemplo 18, mostrar ao leitor um modo de tornar
o Robot Paradoxus 9 autônomo, sendo capaz de desviar de obstáculos
diversos ou objetos que possam atrapalhar o seu caminho. O nosso hardware,
que terá explicações mais detalhadas na apostila de exemplos de circuitos,
apresenta um par de sensores infra vermelhos, localizados em sua região
frontal e apontando cada um para um lado a 45°. Isso permite ao robô
“enxergar” tanto obstáculos frontais, quanto obstáculos diagonais. Com isso, há
uma infinidade de modos possíveis para fazê-lo desviar de obstáculos. Cada
sensor, quando percebe um obstáculo, aplica nível lógico baixo na respectiva
entrada da Paradoxus 9. As entradas deverão ser mantidas em nível alto,
sempre que o robô não estive detectando obstáculo algum. A própria placa de
sensores já apresenta os resistores de pull-up, que garantem o nível high para
as duas entradas utilizadas, no caso, RB4 e RB5.
Queremos não só apenas que o Robot Paradoxus 9 desvie de
obstáculos e objetos, mas faço-o de maneira inteligente, afinal de contas o
hardware permite isto. Tudo que precisamos é saber trabalhar bem o software,
desenvolvendo o algoritmo mais lógico possível. O código fonte deste exemplo
funcionará da seguinte forma: ao ligarmos a alimentação, a unidade robótica
seguirá em frente, andando não muito rápido, isso será possível com a
aplicação de um controle PWM (pulse width modulation), ou modulação por
largura de pulsos. Caso o sensor da direita (que está conectado à RB4) detecte
um obstáculo, o robô irá parar por 1 segundo, andar para trás por 0,3 segundos
e girar para esquerda por 0,5 segundos (isto é, no sentido contrário do
obstáculo), seguindo novamente em frente. Se o sensor da esquerda (ligado à
RB5) encontrar um obstáculo, o robô se comportará da mesma forma, porém
fará o desvio para direita (sentido oposto ao obstáculo). O delay de 0,5
segundos para os desvios foi escolhido pois é o tempo aproximado que o robô
leva para girar 90°. Note que se o projetista trabalhar com uma estrutura
mecânica diferente do Robot Paradoxus 9, os tempos de delay certamente
deverão mudar, para o mesmo efeito de controle. Os led’s programáveis da
placa Paradoxus 9 também serão aproveitados para criar um efeito visual para
o robô. O LED1 acenderá quando o sensor direito detectar obstáculo e o LED2
quando o esquerdo detectar obstáculo.
A modulação por largura de pulsos (PWM) foi utilizada para que o robô
pudesse fazer a leitura mais precisa do ambiente através dos sensores, pois se
o mesmo andasse de forma muito acelerada poderia esbarrar em algum objeto
ou obstáculo (móveis, paredes, etc) antes mesmos dos sensores o detectarem.
O comando for foi utilizado como loop infinito, fazendo com que os motores
sejam acionados a cada 25 milisegundos. Para isto, basta seguir a tabela 4,
ora mandando a configuração de bits que faz o robô andar para frente, ora
fazendo ambos os motores parar. O tempo de delay terá 0,025 segundos
(25ms), este tempo é tão rápido que as paradas dos motores são serão
percebidas, dando a impressão que de fato o robô estará andando mais
devagar e sem perda de torque, o que é muito importante. A onda quadrada
abaixo sintetiza o controle que estamos descrevendo.

Forma de onda do controle PWM utilizado (Exemplo 18).

Fluxograma: Um fluxograma é uma espécie de diagrama em blocos que


apresenta a sequência lógica que diz respeito ao código fonte. Em geral, antes
da criação de um código fonte, traça-se o fluxograma, para facilitar o seu
entendimento como um todo. Em robótica isto é uma prática muito comum. A
forma geral de se escrever (ou desenhar) o fluxograma, consiste em utilizar
retângulos onde os comandos fixos são executados e losangos quando
surgirem conflitos. Cada conflito e comando são separados por setas e quando
duas convergem para um mesmo local, utiliza-se um círculo para esta
representação. Os laços de condição if representam um conflito, assim como
outras instruções reservadas da linguagem C. Expõe-se este conflito em forma
de pergunta e traça-se duas retas, uma para cada resposta. Cada seta aponta
para um próximo retângulo de comando fixo que o robô executará. Geralmente
estes comandos fixos irão convergir para o ponto inicial do programa, onde o
laço infinito reinicia. Fluxogramas também podem ser traçados após a escrita
do código fonte, para que outros usuários entendam melhor ainda o programa
em questão. Um bom exercício para treinar a construção de fluxogramas é
pegar os primeiros exemplos desta apostila e desenhar os diagramas
sequenciais lógicos. A imagem abaixo traz o fluxograma do Exemplo 18, para
ilustrar como tudo funciona e concomitantemente ajuda o leitor a entender o
comportamento do robô, por assim dizer.
Fluxograma relativo ao Exemplo 18.

O código fonte pertinente ao Exemplo 18 é apresentado abaixo e


permite as mais diversas modificações por parte do leitor.
Código fonte do Exemplo 18

Explicação: O programa do Exemplo 18 está todo comentado para facilitar


ainda mais a compreensão. O código inicia já na função main com a
configuração dos port’s utilizando-se lógica binária. O portB é configurado
como entrada em RB4 e RB5, pois ali estão conectadas as saídas do sensor
infravermelho do robô. O portA é inicializado em low em todos os pinos, exceto
RA0 e RA1, pois os botões programáveis são sempre ativos em low e o portB é
todo inicializado em zero. Já dentro do laço infinito while(1), foi utilizado um
loop infinito através da instrução for(;;) e é nele que inserimos os comandos
para um efeito PWM. Repare que no código inteiro, os pinos de entrada RB4 e
RB5 são sempre mantidos em nível alto, para garantir que o microcontrolador
não apresentará erros fazendo o robô detectar “obstáculos fantasmas”. Mesmo
apresentando resistores de pull-up no próprio shield sensor, é aconselhável
utilizar este procedimento. Em suma, o portB neste código dentro do laço
infinito apresentará sempre este aspecto “portb = 0b0011XXXX”, sendo que os
bits iniciais “XXXX” (pinos RB0 a RB3), serão determinados de acordo com o
desejo do usuário já que estes são responsáveis justamente pela locomoção
do robô, sendo compatíveis com a Tabela 4.
Após o artifício de PWM, ainda dentro do laço for, dois laços de
condição if são introduzidos. O primeiro laço, diz que se o pino RB4 for igual a
zero (sensor direito detectando obstáculo ou objeto), o robô não seguirá mais
em frente, mas executará a sequência de comandos que encontra-se entre as
chaves “{ }” do laço if1. Primeiro o robô para e acende o LED1 por um
segundo. Em seguida anda para trás por 0,3 segundos e apaga o LED1.
Finalmente, gira para esquerda (direção oposta ao obstáculo) por 0,5 segundos
(o que dá aproximadamente 90° de giro) e volta a seguir em frente até que um
novo obstáculo ou objeto seja encontrado. No laço de condição if2, a unidade
irá executar a série de comandos quando RB5 for igual a zero (sensor
esquerdo detectando obstáculo). A sequência é semelhante à do laço if1, a
diferença é que quando o robô parar o LED2 irá acender; e a unidade irá girar
para a direita (sentido oposto ao obstáculo) antes de seguir em frente. Este
código do Exemplo 18 é bastante útil como ferramenta básica para o projetista
aprender a programar o robô com todos os seus dispositivos. As sequências
dos laços de condição podem e devem ser alteradas pelo usuário para
verificações práticas de funcionamento. O leitor também poderá aproveitar os
pinos programáveis que estão sobrando na Paradoxus 9 para inserir mais
dispositivos como outros led’s, buzzers, sensores, etc.
 Exemplo 19: Robot Paradoxus 9 (3)

Função 1: Lutar sumô de robôs.


Função 2: Encontrar e empurrar objetos.

Existem diversas competições de robótica, destinadas à criação e


desenvolvimento de unidades autônomas capazes de executar tarefas
determinadas que satisfaçam as regras do evento em questão, com melhor
índice de aproveitamento possível. Os robôs móveis em particular, são
empregados em modalidades já muito conhecidas como Seguidor de Linha,
Futebol de Robôs, Robôs de Combate, Robôs Rastreadores (para achar a
saída de labirintos) e uma das favoritas entre os entusiastas de robótica: O
Sumô de Robôs. O Sumô de Robôs é uma competição, onde dois adversários
(robôs móveis autônomos) se enfrentam em uma arena (geralmente branca
ladeada por linha preta). A batalha em questão consiste em determinar qual
robô é capaz de detectar o adversário e empurrá-lo para fora da arena. O
primeiro que o fizer, é declarado vencedor da luta. Até aí pode parecer algo
bastante elementar. Entretanto, é necessário o projeto de um robô que, além
de ser capaz de encontrar um adversário, não caia acidentalmente para fora da
arena e, principalmente, tenha mais força que o oponente, para assim empurrá-
lo para fora da área de luta. Algoritmos destinados ao contorno de situações
que venham a surgir - como o robô adversário ter mais força ou a arena
apresentar obstáculos ou formas irregulares – certamente devem ser criados
para o melhor desempenho possível. Cada competição arbitra suas regras e
estas podem conter condições que limitam o projeto do robô em questão, como
tamanho, peso, motores utilizados, chassi, bateria, dentre outros, mas isso é
outra história. O kit Robot Paradoxus 9 da WR Kits, viabiliza o implemento de
um robô para lutar sumô, já que acompanha sensores de detecção de
obstáculos (no caso, o adversário) e a possibilidade de incrementar a unidade
com sensores extra (para detecção das linhas da arena, evitando que o robô
saia fora dela acidentalmente).
O código fonte proposto pelo Exemplo 19, diz respeito a um algoritmo
que servirá de base para o projetista desenvolver o seu robô lutador de sumô,
pois trata-se de um programa extremamente simplificado para esta tarefa, o
que certamente limitaria muito o robô para uso em competições. Cabe ao
usuário, portanto, aperfeiçoar o código aqui exposto, integrando mais sensores
e outras sub-rotinas ao Robot Paradoxus 9 lutador de sumô. Naturalmente
algumas dicas serão abordadas, como auxílio ao projeto. O comportamento do
robô será basicamente este: Ligando a alimentação, o LED indicador de
energia irá acender na Paradoxus 9 e o robô estará parado. Ao pressionar-se o
botão programável S1, o robô aguardará 1 segundo e iniciará a se movimentar,
girando sempre 360° ao redor do próprio eixo. Quando o sensor esquerdo ou o
sensor direito detectarem um obstáculo (ou adversário), o robô liga os led’s
programáveis da Paradoxus 9 e ataca por um determinado tempo, avançando
em frente na direção do adversário, assim empurrando-o. Com este simples
programa já é possível fazer o robô “lutar” sumô, mas lógico terá as limitações
mencionadas anteriormente. Como pode ser observado no título deste
exemplo, o Robot Paradoxus 9 apresentará duas funções: a primeira é de lutar
sumô, que é o foco deste exemplo e a segunda, é a de encontrar e empurrar
objetos. A função 2 consiste em deixar o robô operando fora da arena e colocar
um objeto qualquer (uma lata de refrigerante, por exemplo) que seja detectado
por seus sensores, e observar a capacidade do robô em empurrar o objeto em
questão. A função 2 pode ser usada para testes, o que é útil para aperfeiçoar o
código fonte do robô, antes de coloca-lo em uma arena.

Código fonte do Exemplo 19


Explicação: A inicialização dos port’s consiste em configurar como entrada os
pinos dos botões programáveis (RA0 e RA1) e os pinos que fazem a leitura dos
sensores infravermelhos (RB4 e RB5). Os comparadores AD são desabilitados
com o comando “cmcon = 7;”, caso o projetista deseje utilizar os botões
programáveis da placa para implementar novas sub-rotinas ao robô. O laço
infinito “while” inicia com a sub-rotina do laço de condição if principal. Este laço
faz com que o robô apenas comece a andar, quando o botão S1 for
pressionado na placa. O delay de 1 segundo faz o robô aguardar este tempo
após o botão ser pressionado, antes de começar a andar. Logo após, o código
entra no programa batizado de “sumo” e um laço de loop infinito for é
implementado, já prevendo um controle de velocidade por PWM, caso o leitor
julgue necessário (veja mais sobre PWM no Exemplo anterior). Durante a
execução deste laço, o robô estará andando em círculos à esquerda
procurando o adversário (ou algum objeto), conforme Tabela 4, pela instrução
“portb = 0b00110101;”. Em seguida, temos o laço if destinado à avaliação dos
sensores. As barras verticais “| |” utilizadas no meio dos parênteses do laço,
referem-se ao operador lógico “ou” da linguagem C. Se o sensor direito (RB4)
ou o sensor esquerdo (RB5) detectarem obstáculo, então o Robot Paradoxus 9
avança em frente, por 2 segundos (500ms + 1500ms) , ligando os led’s
programáveis da placa (apenas para efeito visual). Ou seja, tanto faz qual
sensor “enxergar” o adversário, o robô executará a mesma forma de ataque.
Por fim, o código encontra a instrução “goto sumo”, que faz o programa rodar
novamente a partir da linha “sumo:”.
Como foi mencionado no início deste exemplo, o código fonte criado
para o mesmo é o mais simples possível e dificilmente será eficiente em
competições de sumo. Porém, já serve como o “alicerce” de um programa para
uso em competições. A primeira sugestão seria o uso de laços if separados,
um para cada sensor, fazendo com que o robô apresente ataque diferente,
conforme o sensor que detectar o adversário. A segunda sugestão, consiste no
acréscimo de outros dois sensores ao robô, um instalado na frente e outro na
traseira mirados para baixo, destinados à detecção da linha final da arena.
Quando o robô “enxergar” a linha com o sensor frontal ele faz um desvio para
trás, quando “enxergar” com o sensor traseiro, realiza desvio para frente,
evitando que o adversário o derrube tão facilmente para fora da arena. A lógica
adotada para que o robô detecte a linha pode ser a mesma de um robô
seguidor de linha, só que utilizando um par emissor/receptor de infravermelho
voltado para baixo na frente e outra atrás. Como não há reflexão de feixe
infravermelho no preto, o robô detecta a linha (veja na imagem abaixo).

Reflexão de infravermelho.

A terceira sugestão é fazer com que o robô procure o adversário de


forma diferente, do que andando em torno do próprio eixo.
 Exemplo 20: Robot Paradoxus 9 (4)

Função: Desviar e contar obstáculos, “falar” qual a direção do obstáculo


encontrado e “falar” quando detectar o quinto obstáculo.

A função descrita para este exemplo pode parecer um tanto utópica à


primeira vista. Mas de fato, é exatamente o que o Robot Paradoxus 9 fará.
Conforme já foi comentado, não apenas neste, mas em outros arquivos
contidos na documentação Paradoxus 9, robôs autônomos permitem não
apenas a instalação de dispositivos sensores ou drivers para motor (que são os
shields inclusos no kit Robot Paradoxus 9), mas permitem também a utilização
de módulos especiais que apresentam circuitos integrados dedicados à
determinadas funções menos triviais. Um servo motor, por exemplo, consiste
em um módulo especial, pois além de conter um motor dc com caixa de
redução, apresenta um circuito driver de posicionamento, para o controle
preciso do ângulo do eixo. Entretanto, o módulo empregado neste exemplo é
ainda menos trivial. Consiste em um módulo de voz muito versátil, dedicado à
gravação e reprodução de até 8 mensagens distintas, podendo estas serem
acessadas pelo nosso microcontrolador, através das saídas da Paradoxus 9.
Este módulo de voz (que não está incluso no presente kit) é o ISD1932, que
pode ser adquirido em sites especializados em eletrônicos para robótica, por
exemplo. Devido às dezenas de possibilidades apresentadas pelo ISD1932, a
WR Kits inclusive desenvolveu um tutorial específico, ensinando o projetista
como trabalhar com o mesmo, operando no Direct Mode, que é a forma de
operação que nos interessa para utilização em robótica. Lá no tutorial, você
aprenderá como gravar e reproduzir as mensagens, e conta com um circuito
exclusivo para operar o ISD1932. Na apostila de exemplos de circuitos você
também encontrará mais detalhes sobre o hardware do Exemplo 20.
O código utilizado para este exemplo consiste em uma evolução do
empregado no Exemplo 18, destinado ao desvio de obstáculos. A principal
diferença é que aqui, quando alimentamos a unidade, o robô nada fará até que
S1 da Paradoxus 9 seja pressionado. Ao pressionarmos S1, o robô fará uma
varredura em seu hardware e notificará o usuário de que está pronto para
começar, já “pronunciando” sua primeira frase que é “Sistemas OK, Robot
Paradoxus 9 iniciando.”, previamente gravada no ISD1932. Após, o robô inicia
seu trajeto seguindo em frente, com implemento PWM. Quando o sensor
esquerdo detectar um obstáculo, a unidade para e emite a frase “Obstáculo
detectado à esquerda, desviando.”. Quando o sensor direito detectar um
obstáculo, a unidade para e emite a frase “Obstáculo detectado à direita,
desviando.”. Concomitante a isso, o robô vai somando os obstáculos
encontrados em seu caminho. Ao chegar no quinto (5º) obstáculo detectado, o
robô para de seguir em frente e emite sua quarta e última frase “Robô detectou
5 obstáculos, reiniciando contagem.”, faz um desvio diferente e o ciclo se
reinicia. Este exemplo mostra claramente que é possível de se incrementar
módulos especiais ao robô, tornando-o ainda mais realístico. Note que
utilizamos apenas 4 dos 8 pinos destinados ao armazenamento de mensagens
de áudio no ISD1932. Para fazer o robô “falar” estas mensagens, é necessário
enviar nível baixo no pino referente à mensagem que se deseja reproduzir no
módulo de voz. O próprio circuito integrado do módulo de voz, já conta com
resistores de pull-up internos nos pinos de mensagem, garantindo o nível alto
quando as mensagens não forem reproduzidas, porém, sempre é bom
garantirmos este nível também via código fonte. A seguir apresentamos em 3
partes o código fonte do Exemplo 20, seguido de sua explicação linha por linha,
logo abaixo.
Código Fonte Pertinente ao Exemplo 20.

Explicação: O código inicia-se com a determinação de alguns dispositivos


através da diretiva #define. É aconselhável o uso desta diretiva sempre que
possível para tornar o código fonte mais simples de se trabalhar e ler. Ao pino
RA1, demos o nome de S1 (pois de fato, o botão programável S1 está neste
pino) e aos pinos RB4 e RB5 demos o nome de SR (sensor direito) e SL
(sensor esquerdo), respectivamente, pelo mesmo motivo. Em seguida, são
declaradas três variáveis globais, sendo duas delas, auxiliares (i e j) e a
terceira a variável que armazena a quantidade de obstáculos detectados pelo
robô, batizada de “contagem”. As três variáveis são do tipo inteiro e já foram
inicializadas valendo zero “0”. Já na função main(), como de costume, as I/O’s
do microcontrolador são definidas através da instrução TRIS. Os comparadores
A/D são desativados com “cmcon = 7;”. O portA tem seus pinos RA0 e RA1
(dos botões) iniciados em “1”, garantindo este nível lógico nestas entradas. O
portB, por sua vez, tem os bits destinados ao controle dos motores (RB0 a
RB3) iniciados em zero lógico “0” e os demais bits (RB4 a RB7) iniciados em
nível high “1”. Como as saídas dos sensores infravermelhos são ligadas aos
pinos RB4 e RB5, e os mesmos são acionados quando é aplicado nível baixo,
os dois pinos de mensagem M3 e M4 do ISD1932, que contém
respectivamente as frases “Obstáculo detectado à direita, desviando.” e
“Obstáculo detectado à esquerda, desviando.”, também estão conectados em
RB4 e RB5, fazendo com que na verdade as saídas do infrared sensor que
ativem estas duas frases. Com isso, os pinos RB6 e RB7 sobram na Paradoxus
9, para o uso das outras duas frases emitidas pelo robô. Para uma quinta frase,
o projetista ainda poderá empregar o pino RA4 da Paradoxus 9.
Após o comando while(1), que determina o laço infinito, temos o
comando if principal, que contém todas as demais instruções do código fonte
entre suas chaves “{ }”. Por este motivo, como inicializamos o portB em zero
para os pinos que comandam o driver dos motores, o robô permanecerá
parado, até que S1 seja pressionado na Paradoxus 9. Em suma, temos uma
condição inicial para o robô começar a funcionar. Ao pressionarmos S1, o
Robot Paradoxus 9 aguardará mais 4,2 segundos antes de começar a se
locomover para frente. Este é o tempo aproximado da primeira frase que o robô
emitirá que é “Sistemas OK, Robot Paradoxus 9 iniciando!”, o que dará a
impressão de que o robô realizou uma varredura em seus sistemas de
hardware e software antes de iniciar suas funções. Depois disso o robô inicia
andando em frente em PWM de 25 milisegundos, contido no loop for( ; ; ).
Na segunda parte do código do Exemplo 20, encontra-se o laço if que
testa o sensor direito do robô. O comando “if (SR == 0 & contagem < 5)” diz
que, se o sensor direito receber nível low (sensor detectando obstáculo) e a
variável contagem for menor que 5, então o robô executará os comandos entre
as chaves “{ }” deste laço de condição. Observe que para colocar mais
condições dentro de uma instrução if, temos que utilizar o ê comercial “&” entre
as condições desejadas. Então o programa testa estas duas condições, sendo
ambas verdadeiras, os comandos entre as chaves do if serão executados. O
primeiro comando entre estas chaves é o de incrementar a variável contagem,
com a instrução “contagem ++;”. Isso significa que contagem, que inicialmente
valia zero, agora valerá 0 + 1, ou seja, será igual a 1. Isto garante que, a cada
obstáculo detectado o robô somará 1 e armazenará na variável contagem, isto
permite à unidade “saber” quantos obstáculos já detectou. Na próxima vez que
o robô detectar um obstáculo, a instrução “contagem ++;” será lida novamente,
porém contagem que valia 1 devido ao incremento anterior, agora valerá 2, e
assim por diante. Temos assim, um robô que “soma”.
Neste código fonte surge como novidade, o uso do comando while de
forma diferente. Após o incremento na variável contagem, ainda dentro do laço
de condição, aparece a instrução “while( i < 21 )”. A tradução do inglês para a
palavra while é “enquanto”. Lê-se, portanto, a instrução utilizada desta forma:
“enquanto i for menor que 21”, ou seja, tudo que estiver entre as chaves desta
instrução, será executado em loop enquanto a variável auxiliar i valer menos
que 21. Temos uma repetição de comandos temporária e não infinita. Isto
permite realizarmos comandos sucessivos sem a repetição exaustiva de linhas.
Utilizamos este comando para fazer os LED’s programáveis da Paradoxus 9
“correrem” em forma sequencial enquanto a frase de “Obstáculo detectado à
direita…” for emitida pelo robô, criando um efeito visual para o áudio emitido.
Dentro do while( i < 21 ) temos o incremento na variável i com o comando “i
++;” e mais 3 etapas separadas por delays de 64 milisegundos. Em cada etapa,
o portB estará igual, mantendo o robô parado. Porém, no portA, os LED’s
programáveis serão configurados para acenderem em sequencia. Como são 3
etapas de 64 milisegundos, temos o incremento em i a cada 192 milisegundos
(64 x 3). Como configuramos para estas etapas se repetirem enquanto i for
menor que 21, teremos a repetição sucessiva das mesmas por 20 vezes, o que
dá um tempo total de 3840 milisegundos (192 x 20). Resumindo, durante o
tempo de 3,84 segundos o robô pára e emite a frase “Obstáculo detectado à
direita, desviando.”, ao mesmo tempo que, os LED’s programáveis fazem uma
sequencial rápida para simular o efeito visual do áudio emitido. Não sendo mais
verdadeira a expressão “i < 21”, a código segue adiante, primeiro zerando
novamente a variável auxiliar i (i = 0;), depois efetuando o desvio do obstáculo
como em outros códigos descritos nesta apostila. Primeiro anda um tempo para
trás e depois vira para esquerda, no sentido oposto do obstáculo e finalmente
torna a seguir em frente.
A análise do código é idêntica para o segundo laço if, que testa o sensor
esquerdo SL e a variável contagem. A diferença está apenas na frase que o
robô “fala”, na variável auxiliar utilizada, e no desvio do obstáculo, que agora
será virando para direita. Vale ressaltar que a variável contagem será
incrementada a cada obstáculo, independente se for o sensor direito ou o
esquerdo que o detectou.
Finalmente temos o teste final, que consiste em verificar se a variável
contagem é igual a 5. Se contagem for igual a 5 ( if(contagem == 5) ), então a
variável é novamente zerada (“contagem = 0;”), o robô pára, os LED’s piscam
juntos por 4,5 segundos (750ms x 6), ao mesmo tempo que o Robot Paradoxus
9 “fala” a frase "Robot detectou 5 obstáculos...Reiniciando contagem." Após
este tempo, o robô anda para trás e faz um desvio maior para direita (direção
adotada, poderia ser para esquerda também). Após este laço ser executado,
teremos todas as variáveis zeradas novamente e o ciclo recomeça, com o robô
movendo-se à frente, detectando obstáculos, contando e “falando” as frases
previamente gravadas no módulo de voz. O usuário poderá implementar
também um laço while de repetição finita neste laço if. Para isto, basta
declarar outra variável auxiliar (k, por exemplo).
Para ver detalhes do hardware deste robô “falante”, consulte o Exemplo
20 na apostila de circuitos e leia o tutorial ISD1932, contido no disco de drivers
do kit. Experimento outros modos de programação, alterando tempos de delay,
comandos entre outros. É importante que o leitor entenda bem o código fonte
aqui proposto, para passar à leitura do último exemplo desta apostila (Exemplo
21).
 Exemplo 21: Robot Paradoxus 9 (5)

Função: Detectar e memorizar obstáculos

O quinto e último exemplo pertinente à programação do Robot


Paradoxus 9 WR Kits, traz uma característica nobre para robôs, amplamente
difundida em clássicos de ficção científica: a memória. De fato, este exemplo
traz um robô capaz de memorizar “vícios” em obstáculos contornando
situações indesejáveis. Esta característica torna a unidade dotada de ainda
mais inteligência, fazendo com que o robô muito dificilmente fique trancado em
algum obstáculo. Quem já experimentou o código fonte do Exemplo 18, cuja
função é fazer o robô desviar de obstáculos, deve ter percebido que para
determinados obstáculos o mesmo código não é tão eficiente quanto deveria.
Ao deparar-se com um canto, por exemplo, com obstáculos em ângulo de 90°,
a unidade pode tender a não sair mais dali, detectando obstáculo ora com
sensor esquerdo, ora com direito. Isso caracteriza um vício de obstáculos que
no caso se dá devido ao fato dos sensores do shield estarem posicionados um
em oposição ao outro a 45° (temos assim um ângulo de reflexão de 90°). O
desenho abaixo ilustra nossa explicação, para que o projetista compreenda
melhor o problema aqui descrito.

Vício de Obstáculo.

Outro detalhe bastante típico em robôs que desviam de obstáculo se dá


pelos mesmos se locomoverem em círculos, após um determinado tempo, caso
encontrem-se dentro de “redomas” ou labirintos com áreas amplas; padrões
comumente difundidos em competições de robôs móveis autônomos. Temos,
portanto, outra espécie de vício de obstáculos, onde a unidade passa a se
mover em círculos, chegando sempre ao ponto de partida, em suma, não indo
a lugar nenhum. A seguir ilustramos esta situação visando entendimento claro
por parte do leitor.
Vício de obstáculo “andando em círculos”.

O Exemplo 21 visa contornar estes dois tipos de vício em obstáculo, que


surgem em robôs móveis autônomos. Quem compreendeu bem o algoritmo
aplicado no Exemplo 20 já terá uma boa base para compreensão do presente
código fonte. Se ainda não ficou muito clara a compreensão daquele exemplo,
sugerimos sua releitura até que o usuário tenha total entendimento do mesmo,
para após passar a analisar o código do Exemplo 21. No exemplo anterior, fora
o “dom da fala” aplicado ao Robot Paradoxus 9, também utilizamos uma lógica
para a soma de obstáculos por ele detectados. Para a memorização de vícios
em obstáculo, iremos utilizar uma lógica parecida, porém agora o robô irá
somar as coincidências detectadas em sua trajetória, para então tomar as
decisões cabíveis à situação.
A lógica funciona da seguinte maneira: o robô inicia movendo-se em
linha reta até encontrar um obstáculo. Encontrando um obstáculo à direita, o
robô armazena este dado em uma variável auxiliar, desvia e segue adiante. Se
o próximo obstáculo detectado pelo robô for também à direita, novamente ele
cumpre a tarefa de armazenar o dado e desviar. Até aí ele se comporta
semelhante ao Exemplo 18. Porém, na terceira incidência seguida de detecção
de obstáculo à direita, o robô pára e realiza um desvio maior de trajetória. Este
fato impede que a unidade ande em círculos à esquerda, pois detectando 3
obstáculos seguidos com o sensor direito, o robô percebe que está tendendo
para o movimento circular à esquerda e toma a providência buscando uma rota
alternativa. Mas vale salientar que isto só ocorre quando 3 obstáculos seguidos
forem encontrados com o sensor direito. Se o robô detectar 2 obstáculos com o
sensor direito, e o terceiro for detectado pelo sensor esquerdo, a unidade
apaga os dados armazenados pelo sensor direito e continuo o ciclo.
A análise supracitada é exatamente igual para o sensor esquerdo.
Quando o robô detectar 3 obstáculos seguidos com este sensor, realiza o
desvio maior, evitando que o mesmo comece a andar em círculos à direita.
Novamente, se a unidade detectar 2 obstáculos com o sensor esquerdo, só
que o terceiro for detectado com o sensor direito, os dados são apagados e o
ciclo recomeça. Este artifício de armazenamento de dados coincidentes em
cada sensor permite ao Robot Paradoxus 9 contornar o problema de andar em
círculos.
Para fazer com que o robô saia de cantos com obstáculos a 90°, é
necessário armazenar um terceiro dado, que diz respeito à coincidência dos
sensores detectarem muito repetidamente obstáculo, ora à direita ora à
esquerda. Esta informação é aproveitada pelo robô, que percebe que está em
um canto ao alternar a detecção muitas vezes entre um sensor e outro. Na
incidência de 4 obstáculos seguidos, alternando entre um sensor e outro, o
robô para e realiza um desvio maior, “fugindo” assim do canto sem saída.
Para tornar mais clara a explicação do texto, exibimos um simples
diagrama logo abaixo, que mostra a resposta do robô à incidência dos 3
primeiros obstáculos detectados por cada sensor.

Diagrama: Resposta do robô à detecção do número de obstáculos por


sensor.

Observando-se o diagrama acima fica mais fácil de entender o que o


robô faz ao encontrar determinado número de obstáculos. Na linha de cima,
temos os 3 primeiros obstáculos que o sensor direito detecta (1º, 2º e 3º). Após
detectar o terceiro obstáculo seguido a unidade executa um desvio maior, nos
demais casos, executa desvio normal. O mesmo vale para o sensor esquerdo,
analisado na linha de baixo. Temos também a análise de coincidência que diz
que quando houver 4 obstáculos detectados alternadamente pelos sensores,
haverá um desvio ainda maior, pois significa que o robô estará deparando-se
com um canto. Para tornar ainda mais interessante o programa aqui descrito,
empregamos um módulo buzzer, que realiza o efeito sonoro do robô durante a
memorização de obstáculos. Este módulo buzzer é largamente aplicado à
robôs móveis autônomos e o próprio projetista poderá construí-lo com poucos
componentes, fáceis de encontrar no mercado e baratos (www.wrkits.com.br).
Na apostila de exemplos de circuitos fornecemos a lista de material e o
diagrama esquemático do módulo buzzer, para os leitores que desejarem
construí-lo, bem como suas ligações à Paradoxus 9. Este módulo por nós
proposto, faz o buzzer emitir som contínuo quando aplicarmos nível lógico alto
na saída a qual o mesmo estiver conectado. A ideia é que o mesmo notifique o
usuário dos obstáculos registrados e armazenados pelo robô, no decorrer de
seu percurso. No primeiro obstáculo detectado é emitido um breve “bip”. Na
coincidência de um segundo obstáculo detectado pelo mesmo sensor, são
emitidos dois “bips”. Finalmente havendo a incidência de um terceiro obstáculo
detectado pelo mesmo sensor, o robô emitirá um “bip” mais longo e contínuo
antes de efetuar o desvio maior. Também emitirá um “bip” longo e contínuo na
incidência de 4 detecções alternadas entre um sensor e outro. No entanto, o
uso do módulo não é obrigatório, sua omissão apenas restringirá os efeitos
sonoros do robô, nada mais.
Outra novidade que empregamos neste código é o uso da diretiva
#define de maneira a simplificar comandos extensos do código e também o uso
de lógica decimal para configurar o portB e portA. O uso de lógica decimal
torna o código menor e mais objetivo, por exemplo, ao invés de enviarmos para
portB o valor em binário “portb = 0b00111001;”, que faz o robô se mover para
frete e deixa as entradas dos sensores em nível high, escrevemos o número
decimal relativo a estes 8 bits (00111001) que é 57. Logo, o comando
apresenta-se da seguinte forma “portb = 57;”, que significa absolutamente a
mesma coisa. Como já citamos nesta apostila, a própria calculadora do
Windows converte números binários para decimais, isto é útil para os que
tiverem dificuldades em interpretar o código ou fazer alterações no mesmo. Na
explicação linha por linha do código em questão, daremos mais dicas a
respeito de lógica decimal.
Dada a complexidade do código aqui proposto, elaboramos o fluxograma
do mesmo, para auxiliar ainda mais a sua compreensão. Procure entender bem
o fluxograma antes de partir para leitura do código fonte. À primeira vista pode
parecer um tanto confuso, mas seguindo as setas e lendo cuidadosamente os
comandos fixos e os conflitos, você entenderá a lógica perfeitamente. O
fluxograma é apresentado a seguir.
Fluxograma do código fonte do Exemplo 21.

O código fonte do Exemplo 21 é apresentado logo abaixo em 3 partes. O


mesmo está totalmente comentado, linha por linha, para que o usuário localize
facilmente conectando-o com o texto de explicação. As mais diversas
alterações podem ser feitas pelo projetista/programador.
Código Fonte do Exemplo 21.

Explicação: Conforme citamos anteriormente a diretiva #define foi explorada


neste código, de maneira a obter uma visualização mais amigável do mesmo.
Primeiramente, alteramos o nome do comando “delay_ms”, exaustivamente
utilizado em todos os códigos para “tempo”. Significa que toda vez que for
necessário um comando de delay no decorrer do código, bastará escrevê-lo da
seguinte forma “tempo(valor em milisegundos);”. Para ilustrar, se quisermos um
delay de 1 segundo, escreveremos “tempo(1000);”. Isto já torna o código mais
simples. Como “porta” e “portb” também são instruções muito usadas do
código, às definimos agora como “A” e “B” maiúsculos, respectivamente. Então
no programa, se aparecer escrito “A=0;” e “B=0;” é o mesmo que dizer
“porta=0;” e “portb=0;”. Tudo que estiver entre os símbolos “/* */” (barra,
asterisco e asterisco, barra), e após “//” (barra, barra – mesma linha), será visto
como mero comentário, não sendo compilado junto com o código.
Já dentro da função main(), temos a linha /*VARIÁVEIS LOCAIS*/ onde
são declaradas as 3 variáveis responsáveis pelo armazenamento dos dados
obtidos pelo robô, ao detectar coincidências de obstáculos. As 3 foram
batizadas de store1, store2 e store3, são do tipo inteiro e já foram inicializadas
em um “1”. Repare que o comando utilizado para declaração desta vez foi
“unsigned int”. O comando “unsigned” (sem sinal) significa que trabalharemos
com variáveis positivas apenas. É aconselhável o uso deste comando, quando
tivermos certeza de que as variáveis apresentarão apenas valores positivos,
pois isto dá mais velocidade ao hardware, que ignora totalmente os números
abaixo de zero. O comando “int” logo após “unsigned” nos diz que
trabalharemos com variáveis do tipo inteiro.
Em /*INICIALIZAÇÃO DOS PORTS*/ configuramos os pinos RA0 e RA1
no portA (botões programáveis da Paradoxus 9) e os pinos RB4 e RB5 no
portB (sensores) como entradas e logo após inicializamos os pinos
programáveis com os comandos “A = 3;” e “B = 0;”. Isto é o mesmo que dizer,
respectivamente, “porta = 0b00000011;” (3 em binário, inicializando em high os
pinos dos botões programáveis) e “portb = 0b00000000;” (0 em binário,
inicializando todo portB em low). Como citado, utilizaremos lógica decimal no
decorrer de todo o código. Para converter decimal para binário, enxergando
assim a programação bit a bit, basta utilizar a calculadora do Windows ou
qualquer calculadora científica. A tabela 5 apresenta os valores decimais
utilizados neste código e os respectivos equivalentes binários.

Tabela 5: Decimais utilizados no Exemplo 21 e Equivalente Binário


Decimal Utilizado Equivalente Binário
0 0b00000000
3 0b00000011
4 0b00000100
8 0b00001000
48 0b00110000
53 0b00110101
54 0b00110110
57 0b00111001
58 0b00111010
63 0b00111111
112 0b01110000

Tabela 5

Iniciamos o /*LAÇO INFINITO*/ while(1) com um loop for( ; ; ) destinado


ao implemento PWM do robô. Logo após, iniciam-se os testes necessários nos
sensores de acordo com as detecções realizadas pela unidade. O primeiro laço
de condição, batizado de /* if1a */, diz que se o sensor direito detectar um
obstáculo e a variável store1 for igual a um, o robô armazena o valor 2 na
variável store3 (store3 ++ = 1 + 1 = 2), pára e emite um “bip” por meio segundo
e acende LED1, permanece parado por mais meio segundo sem emitir “bip”,
anda para trás por 0,3 segundos, vira para esquerda por meio segundo e
apagada LED1, volta a mover-se para frente em PWM, armazena o valor 2 em
store1 e limpa store2 (store2 = 1). Sempre que citarmos “armazena tal número
em tal variável” significa nesse caso que o robô incrementou o valor atual da
variável (nome_da_variável ++;). Quando for mencionado que a unidade limpa
determinada variável, significa que a mesma retorna ao valor que foi
inicializada (como todas foram inicializadas valendo 1, voltarão a valer 1).
Observe o sistema um tanto diferente apresentado neste código. Aproveitamos
a mesma linha para colocar mais de um comando, tornando-o menos comprido
e mais legível. Podemos então, analisar o código por colunas dentro dos laços
de condição: na coluna da esquerda, temos os valores carregados no portB, na
coluna do meio os valores carregados no portA e na terceira coluna os valores
de delay_ms, agora chamado de “tempo”. Este fato mostra que o que separa
um comando do outro em linguagem C é o ponto-e-vírgula ( ; ) e não a tecla de
nova linha do PC (enter).

Valores no portB Valores no portA Valores de delay_ms


B = 48; A = 8; Tempo(500);
Exemplos de comandos do código fonte 21

O laço de condição /* if2a */ só será executado se o sensor direito


detectar um obstáculo e a variável store1 for igual a 2. Note que, para este laço
ser executado, o laço anterior (/* if1a */) deverá já ter sido executado
obrigatoriamente, pois apenas nele há o incremento em store1 que permite que
esta variável tenha o valor 2, para condição de /* if2a */ ser verdadeira. Este
padrão se manifesta por todo o código, permitindo assim que o robô realmente
armazene dados em sua memória. Os comandos efetuados neste laço são
semelhantes ao do primeiro, porém agora não há o incremento em store3, o
robô emitirá não apenas um, mas dois “bips” breves e o laço encerra
armazenando o valor 3 em store1 e limpando a variável store3. O que o leitor
deve ter percebido já, que a variável store3 é a responsável por armazenar os
dados que detectam a coincidência de obstáculos a 90° (cantos) e que as
variáveis store1 e store2 são as responsáveis por evitar que o robô tenda a
andar em círculos (uma para círculos à direita, outra para círculos à esquerda).
Em /* if3a */ temos o terceiro teste de coincidência por parte da unidade,
para verificar se o robô não encontra-se andando em círculos. Para os
comandos do mesmo serem executados, o sensor direito deverá detectar um
obstáculo e store1 deverá ser igual a 3. Obrigatoriamente o programa deverá
ter executado os dois primeiros laços if em sequência para este terceiro ser
executado, pois só assim store1 terá o valor 3 tornando verdadeira a condição
de /* if3a */. Neste laço o robô pára e emite um “bip” contínuo por 0,8 segundos
acendendo o LED1, anda para trás por 0,6 segundos acendendo LED2 e
apagando LED1, gira para esquerda por 0,8 segundos realizando um desvio
maior (mais tempo de giro), volta a seguir em frente e limpa as três variáveis,
limpando todos os dados obtidos até o momento e retomando o teste de
sensores do começo (acompanhe no fluxograma).
A análise do /* if4a */ deve ser feita com atenção por parte do leitor.
Temos o comando inicial escrito da seguinte forma: if(B.rb5 == 0 & store3 > 3).
Até aí, entendemos que os comandos deste laço serão executados, apenas se
o sensor esquerdo detectar obstáculo e a variável store3 tiver armazenado um
valor maior que 3. A sequência de comandos de /* if4a */ é exatamente igual à
sequência de /* if3a */. Mas então, como o robô executa um desvio ainda
maior, como sugerido no fluxograma, se o tempo de desvio é o mesmo do laço
/* if3a */? Para executar estes comandos, o robô deverá ter incrementado
store3 no mínimo 3 vezes. Isto só ocorrerá se a unidade detectar um obstáculo
ora com sensor direito ora com sensor esquerdo, indicando o fato de que a
mesma encontra-se em um canto (repare que store3 sempre é limpa dos if’s2
em diante). A variável store3 só será incrementada dentro dos laços if1 (a e b),
sendo assim, os comandos desses laços também serão executados. Significa
que, para o robô realizar o desvio maior proposto no laço /* if4a */, terá
obrigatoriamente já realizado um desvio normal, a partir de um dos laços if1 (a
ou b) e, por esta razão, teremos o desvio ainda maior, que soma o desvio
normal com o desvio maior empregado neste laço, viabilizando ao robô o
escape de um canto contendo obstáculos a 90°. Ao final deste laço, os dados
coletados pelo robô em seu percurso serão limpos e o ciclo se reinicia.
Os laços de condição seguintes (if1b, if2b, if3b e if4b) tem a análise
exatamente igual aos primeiros laços explicados acima, devido ao controle
bilateral (um sensor de cada lado) adotado para o Robot Paradoxus 9. O único
detalhe que ainda é importante ressaltar é que nos laços if4 (a e b) fazemos o
teste do sensor oposto ao da sequência de laços corrente. Esta lógica foi
adotada para que o robô se comporte de forma igual independente de qual
sensor detectou o obstáculo a 90° primeiro. Pelo mesmo motivo, uma das
condições é que store3 seja maior que 3 e não simplesmente igual a 4.
Embora o uso de laços de condição if em demasia (bem como
encadeamentos do tipo if else if) não seja a solução mais elegante na maioria
dos casos para programação em linguagem C, adotamos esse sistema para o
Exemplo 21 julgando ser o modo mais dinâmico de fazer com que o usuário
entenda um código fonte de tal magnitude. O projetista/programador que tiver
mais experiência, poderá adotar outras alternativas, como comandos switch e
switch aninhado, ou mesmo o uso de vetores para a programação do Robot
Paradoxus 9 WR Kits.
4 – Conclusão

Após a leitura da apostila Exemplos de Códigos Fonte em MikroC,


conclui-se que a programação da placa kit de desenvolvimento Paradoxus 9 da
WR Kits não é uma tarefa complicada, cabendo ao usuário o seu entendimento
como um todo para poder desenvolver seus próprios códigos fonte. Todos os
algoritmos aqui propostos permitem as mais distintas modificações por parte do
leitor, que já poderá fazê-lo como forma de exercício, aperfeiçoando seus
conhecimentos em programação. É totalmente aconselhável que o leitor efetue
a digitação palavra por palavra, de cada código fonte, adquirindo assim mais
experiência na criação de programas e aprendendo ainda mais sobre a
linguagem adotada. De qualquer forma, para os que preferirem copiar os
códigos inteiros a fim de testá-los ou apenas fazer modificações nos mesmos,
fornecemos no disco de drivers o arquivo “Exemplos MikroC (Ctrl+c – Ctrl+v)”,
que contém os 21 códigos aqui descritos em formato de texto, bastando copiá-
los para o compilador MikroC. A linguagem C aproxima muito o usuário do
código de máquina, não tanto quanto Assembly (que também pode ser utilizado
na programação da Paradoxus 9), mas não chega a ser uma linguagem de alto
nível como Pascal, Python e Basic, por exemplo.

Você também pode gostar