Sensor de distância Hcsr04

###### **In english: Hcsr04**

Este é um dos mais comuns dispositivos no mundo do arduino. É barato, fácil de encontrar e de usar, mas pode ser um tanto frustrante se acreditar piamente na propaganda dos vendedores. Diz a lenda que ele mede distancias de até 4 metros. Talvez até meça, mas dentro de condições tão ideais que ainda não vi acontecer no mundo real. Na prática o que podemos esperar são medidas de até 2 a 2,5 metros e com muita sorte 3 metros, o que aliás não é pouca coisa, já torna o sensor bem útil para um robô de pequeno porte como o deste projeto. Outra lenda é que a abertura do feixe de ultrassom é de 15 graus, não conte com isso, na prática a abertura é bem maior. Significa que objetos bastante à esquerda ou à direita do sensor acabam refletindo a rajada de ultrassom. Também não dá pra confiar muito na precisão de 0,3 cm propagada pelos fabricantes, mas tem uma precisão que chega perto de 1 cm, portanto não compensa usar *float's* para ler a distância medida, a precisão não vai ter nenhum aumento significativo, mas com certeza o tamanho do código gerado vai. Um outro detalhe é que tem diferenças bem significativas no desempenho de cada unidade. Não funcionam todos exatamente do mesmo jeito, então é sempre bom ter mais de um e testar todos eles. Mas apesar de tudo isso, é uma boa aquisição para instalar em um robô e pelo seu preço, proporciona um excelente custo-benefício.

### Funcionamento

Este sensor tem 4 pinos, sendo dois para a alimentação (*VCC* e *GND*) e dois para a operação (*Trigger* e *Echo*). Deve ser alimentado com 5 volts. Talvez funcione com 3.3 volts, mas nesse caso acho que seu alcance diminui bastante. Sua operação é relativamente simples, o pino *Trigger* deve ser colocado em nível alto por 10 microssegundos e depois em nível baixo novamente por 2 microssegundos. Após isso o sensor solta uma rajada de ultrassom e coloca o pino *Echo* em nível alto. Quando o eco da rajada retorna o pino *Echo* é colocado em nível baixo novamente. O que o programa tem que fazer é medir o tempo que o pino *Echo* fica em nível alto e a partir dessa medida calcular a distancia do obstáculo que refletiu a rajada de ultrassom. É um sistema simples, mas na prática várias coisas podem dar errado.

### Problemas comuns

Se o obstáculo estiver muito distante, o eco não vai ter força suficiente para sensibilizar o sensor, para esse caso o programa deve prever um *timeout* a fim de evitar que o programa fique esperando por muito tempo. Considerando que na teoria o alcance máximo é de 4 metros, um *timeout* de 23500 microssegundos é um valor até generoso. Mas obstáculos fora de alcance não chegam a ser um problema para um robô. O problema maior é quando o obstáculo está próximo e mesmo assim o eco não retorna. Pode acontecer se a superfície do obstáculo for bem lisa e estiver em um angulo bem aberto em relação ao sensor (figura 3). Nesse caso a rajada é refletida para longe e não retorna. Isso engana o robô fazendo-o acreditar que tem terreno livre pela frente quando na verdade está bem próximo de um obstáculo. Outro problema parecido é o de reflexões múltiplas, que ocorre por exemplo em cantos de paredes. A rajada é refletida por uma parede, atinge a outra parede e depois retorna para o sensor. Nesse caso a distância medida será muito maior do que a distância real. Todos esses problemas podem ser contornados se for não for colocada uma confiança excessiva nas medidas feitas pelo sensor. Por exemplo, fazendo várias medidas de cada vez ou confirmando as medidas realizadas antes de tomar alguma decisão baseado nelas.

### Operação com um pino

Um outro problema, que tecnicamente não é um problema, mas na prática acaba sendo, é o fato do sensor precisar de dois pinos para ser operado. Se o seu robô usa apenas um sensor, isso pode não ser realmente um problema, mas um dos robôs deste projeto já conta com 10 sensores *HC-SR04* e talvez venha a ter mais alguns em um futuro próximo. Então faz muita diferença o uso de um ou dois pinos por sensor, já que a quantidade de pinos disponíveis no arduino é bem limitada, mesmo utilizando um Mega como é o caso. Felizmente existe uma maneira de utilizar o mesmo pino tanto para o *Trigger* quanto para o *Echo*, só que exige a instalação de um resistor de *pulldown* e uma pequena alteração no programa.

### Resistores de pulldown e pullup

Uma característica importante sobre pinos de entrada de microcontroladores é que eles ficam em flutuação quando não há nenhum sinal chegando até eles. Significa que se o pino está desconectado ou se o dispositivo conectado a ele não está enviando sinal nenhum, uma leitura desse pino poderá retornar um valor aleatório (alto ou baixo) que não tem nenhum significado. Para evitar essa flutuação nos pinos de entrada é comum o uso de resistores de *pulldown* ou de *pullup*. São resistores que conectam o pino ao terra (no caso de *pulldown*) ou ao nível alto do sistema (no caso de *pullup*). Como são resistores de um valor relativamente alto, qualquer sinal que chegue ao pino irá se sobrepor ao sinal gerado pelo resistor, mas é o suficiente para eliminar a flutuação no pino quando não tem nenhum sinal chegando. Um resistor *pulldown* que conecta o pino ao terra, fará com que o pino fique sempre em nível baixo até que um sinal de nível alto chegue ao pino. No caso de resistores de *pullup* é a lógica inversa, o pino fica em nível alto, até que chegue um sinal de nível baixo. O arduino tem resistores de *pullup* internos em seus pinos, eles são ativados usando a opção *INPUT\_PULLUP* na função *pinMode()*.

### Classes de suporte

Para dar suporte ao uso de sensores compatíveis com o HC-SR04 foram desenvolvidas algumas classes disponíveis na biblioteca pBot. A classe **Hcsr04** dá o suporte básico para o sensor. Faz a leitura e retorna a medida na unidade escolhida (centímetros ou polegadas). Também prevê a possibilidade de usar o mesmo pino para as funções de trigger e echo.
Um nível acima está a classe  **HcsrAuto** que acrescenta o recurso de temporização, o que permite leituras automáticas em intervalos regulares. Também introduz o uso de eventos que podem ser capturados por outras classes. Finalmente a classe **HcsrArray** permite monitorar um array de sensores com qualquer quantidade (razoável) de unidades.