Sensores de distância são úteis em diversas aplicações. E um bom sensor disponível é o VL53L0X, que é um sensor de distância a laser. Portanto, vamos aprender a utilizá-lo com o Arduino em diferentes configurações.
Informações básicas
O que é
O VL53L0X é um sensor que é capaz de medir distância por meio de um laser infravermelho. É possível encontrar informações dizendo que ele identifica gestos, mas isto é feito por meio da medição da distância.
Enfim… Este sensor é encontrado para comprar já montado em uma plaquinha, como mostra na imagem abaixo (o post será focado nela):
Uma informação interessante a ser dita é sobre o possível risco que este produto apresenta, que é o de causar dano aos olhos. Teoricamente, olhar o sensor diretamente seria o equivalente a olhar o laser destas canetas laser. E, dependendo da potência do laser, você pode ficar até cego com pouco tempo de exposição.
Entretanto, o sensor VL53L0X não oferece este risco e está de acordo com uma norma que trata disto (IEC 60825-1:2014). De qualquer forma, ainda assim não é uma boa prática olhá-lo diretamente, pois evita qualquer desgaste por menor que seja.
E esta informação eu tirei do datasheet do sensor, o qual possui informações mais completas caso você queira aprender mais.
Características
- Distância de medição máxima: cerca de 2 metros.
- A resolução dele está na casa dos milímetros.
- A acurácia do sensor depende de alguns fatores diferentes, mas ela pode ser +-3% ou +-5%.
- Leia a respeito na página 28 do datasheet.
- Mede distâncias até mesmo se a superfície do objeto estiver inclinada em relação ao sensor.
- Ao contrário do sensor de distância ultrassônico.
- Apresenta pequenas diferenças de distância dependendo da cor do objeto (devido ao índice de reflexão).
- Interface I2C com endereço programável.
Modos de operação e perfis de medição
O sensor é capaz de operar em 3 modos distintos:
- Single ranging
A medição é feita uma única vez quando solicitada e após isto o sensor fica em standby.
- Continuous ranging
A medição é feita de forma contínua: assim que uma termina, outra já começa na sequência com o menor atraso possível.
- Timed ranging
Mesma coisa do modo anterior. A diferença é que entre uma medição e outra, pode ser definido um atraso (delay).
Perfis de medição
Existem 4 perfis de medição disponíveis:
- Default mode
Perfil padrão que apresenta um tempo de resposta de 30ms e permite medir até 120cm.
- High speed
Perfil que apresenta um tempo de resposta de 20ms.
- High accuracy
É o perfil que apresenta um tempo de resposta de 200ms, mas uma acurácia de +-3%.
- Long range
Perfil que permite medir até 200cm, mas com uma acurácia de +-5%.
O modo de longo alcance é recomendado apenas em ambientes sem interferência externa de luz infravermelha. Pois, se ele for utilizado em ambientes com interferência, a medição será um pouco instável e imprecisa (veremos isto mais a frente).
E o perfil “Long range” pode ser combinado com o “High speed” ou o “High accuracy”. O mesmo vale para o perfil “Default mode”.
Pinos
O sensor VL53L0XV2 (plaquinha da imagem anterior) apresenta 6 pinos, que são:
- Vcc – Alimentação positiva: Alimentado com 5V.
- Gnd – Alimentação negativa.
- SCL: Clock da comunicação I2C.
- SDA: Dados da comunicação I2C.
- GPIO1: Pino de interrupção que é ativado quando uma medição é completada.
- Pode ser utilizado para alertar o microcontrolador quando a medição for completada (interrupção).
- XSHUT: Pino para “desligar” o sensor.
- A máxima tensão que pode ser aplicada neste pino é 3.6V, então cuidado na hora de ligar no Arduino.
VL53L0X com o Arduino
O sensor se comunica via I2C e necessita de uma série de configurações em seus registradores para funcionar corretamente. E, para facilitar a vida, vou utilizar uma biblioteca que já lida com isto tudo.
Na hora de falar dos resultados do sensor, vou misturar um pouco o conceito de estabilidade das medições com o conceito de acurácia (proximidade entre o valor real e o medido). Mas é para ilustrar o comportamento do sensor.
Biblioteca
A biblioteca que vou utilizar pode ser encontrada na própria IDE do Arduino:
- Acesse o menu: Sketch -> Incluir biblioteca -> Gerenciar bibliotecas
Feito isto, instale a seguinte biblioteca:
Circuito
Anteriormente, comentei sobre os pinos do VL53L0X, mas agora vamos ver como ele se liga ao Arduino.
Não tem muito mistério: Basta alimentar o sensor (pinos Vcc e GND com 5v e GND respectivamente). Além disto, é só conectar o pino SCL na porta analógica A5 do Arduino e o SDA na porta analógica A4. Se você estiver utilizando outro Arduino, é só verificar quais são os pinos correspondentes da comunicação I2C (SDA e SCL).
Os demais pinos (GPIO1 e XSHUT) não são necessários para o funcionamento básico do sistema. O GPIO1 é para lidar com interrupção, e não pretendo mostrar isto neste post. E o XSHUT serve para “desligar” o sensor, e isto será necessário mais a frente.
Medição simples
Para mostrar como lidar com o sensor, pretendo mostrar apenas o modo Single ranging (medição única).
Os exemplos que vem junto à biblioteca do sensor são extremamente úteis e já servem para te dar um norte sobre como fazer o sensor funcionar. De qualquer forma, pretendo mostrar os principais aspectos da biblioteca.
O código abaixo mostra o mínimo que você precisa fazer para ler distância com o sensor no perfil “Default”. O monitor serial está sendo utilizado apenas para exibir as leituras do sensor. Leia os comentários para entender o funcionamento.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | #include <Wire.h> #include <VL53L0X.h> // Cria uma instancia do sensor VL53L0X sensor; void setup() { // Inicializa a comunicação serial Serial.begin(9600); // Inicializa a comunicação I2C Wire.begin(); // Inicializa o sensor sensor.init(); // Define um timeout de 500mS para a leitura do sensor // Em caso de erro, este será o tempo máximo de espera da resposta do sensor sensor.setTimeout(500); } void loop() { // Faz a medição da distância e retorna um valor em milímetros int dist = sensor.readRangeSingleMillimeters(); // Imprime no monitor serial Serial.println(dist); } |
Medição de longas distâncias
O código anterior só permite medir distâncias máximas de 100cm (próximo disto). E, para conseguir medir até pouco mais de 2m, você tem que habilitar o perfil de longo alcance.
Isto é feito adicionando os seguintes comandos após a inicialização (dentro do void setup, após definir o timeout):
1 2 3 | sensor.setSignalRateLimit(0.1); sensor.setVcselPulsePeriod(VL53L0X::VcselPeriodPreRange, 18); sensor.setVcselPulsePeriod(VL53L0X::VcselPeriodFinalRange, 14); |
De acordo com meus testes, a distância máxima foi de 2200mm (2,2 metros). E, nesta distância, o sensor fica oscilando a medição em +-90mm. Ou seja, não tem uma boa acurácia.
Medição de exatidão
Para melhorar a exatidão da medição, é possível habilitar o perfil de alta acurácia. Isto é feito aumentando o tempo no qual o sensor faz a medição. E o comando para fazer esta alteração é o seguinte:
O comando deve ser adicionado dentro do void setup, após definir o timeout.
1 | sensor.setMeasurementTimingBudget(200000); |
Utilizando a medição de alta acurácia e o perfil de longo alcance, a oscilação caiu de +-90mm para +-20mm. Apesar desta melhora, o intervalo entre as medições ficou maior.
Por outro lado, no modo Default, a medição oscila +-20mm. E, quando aplico o perfil de alta acurácia, ela passa a oscilar +-6mm. Ou seja, o resultado é realmente melhor.
Medição rápida
Para acelerar o tempo da medição, é possível habilitar o perfil de alta velocidade. Isto é feito diminuindo o tempo no qual o sensor faz a medição. E o comando para fazer esta alteração é o seguinte:
O comando deve ser adicionado dentro do void setup, após definir o timeout.
1 | sensor.setMeasurementTimingBudget(20000); |
As medições ficam mais rápidas, como era de se esperar. Mas, a acurácia cai e as medições passaram a oscilar +-120mm.
Interferência da luz do sol no VL53L0X
Este sensor sofre interferência da luz solar e isto pode atrapalhar as medições de distância. Entretanto, o VL53L0X apresenta um comportamento muito superior (em termos de funcionamento) a um sensor de obstáculo infravermelho quando exposto à luz solar.
Para demonstrar a interferência, fiz um teste medindo a distância no perfil de longo alcance com a janela fechada e com a janela aberta. Em nenhum momento do teste, houve incidência direta da luz solar no sensor. Para isto, fiz um outro teste, onde pude verificar que o sensor apresenta uma alta instabilidade quando exposta ao sol diretamente.
O teste consistiu em colocar o sensor próximo à janela apontado para o teto, onde ele iria medir distâncias em torno de 2 metros. Esta região perto da janela não estava recebendo luz direta do sol.
Sem filtrar as medições
Apliquei o código que está mostrado abaixo, que apenas faz as medições da distância no perfil de longo alcance sem filtrar os dados.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | #include <Wire.h> #include <VL53L0X.h> VL53L0X sensor; void setup() { Serial.begin(9600); Wire.begin(); sensor.init(); sensor.setTimeout(500); // Perfil de longo alcance sensor.setSignalRateLimit(0.1); sensor.setVcselPulsePeriod(VL53L0X::VcselPeriodPreRange, 18); sensor.setVcselPulsePeriod(VL53L0X::VcselPeriodFinalRange, 14); } void loop() { int dist = sensor.readRangeSingleMillimeters(); Serial.println(dist); } |
Resultado sem filtrar as medições
O valor de distância de ~8000mm é obtido quando o sensor chega no tempo limite de espera da medição. Portanto, é quando ele não é capaz de informar a distância (como se não existissem objetos na frente dele).
É perceptível que, mesmo com incidência solar indireta, o sensor sofre grande influência. Mesmo com a janela fechada, houve alguns picos em que o sensor não foi capaz de obter uma medição. O mesmo procedimento feito durante a noite não apresenta o mesmo comportamento, pois não há mais interferência significativa.
Quando a janela foi aberta, praticamente não da para saber qual é a distância certa, pois o sensor fica constantemente perdendo a medição (quando ele mede ~8000mm).
Filtrado as medições
Para resolver o problema anterior, podemos aplicar um método simples para filtrar as medições. O método consiste apenas em ignorar o valor de ~8000mm quando ele for retornado pelo sensor. Desta forma, o programa irá considerar o último valor válido lido e irá “descartar” o valor de ~8000mm.
Este procedimento foi feito na função “filtrar_sinal” do código abaixo. Além do que comentei acima, adicionei um “timeout” de 1 segundo: se o sensor retornar apenas ~8000mm durante 1 segundo, então ele para de descartar este valor. Leia os comentários do código para entender.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | #include <Wire.h> #include <VL53L0X.h> VL53L0X sensor; // Variaveis para armazenar a distancia atual e o ultimo valor lido int dist = 0, dist_old = 0; // Variavel para armazenar o tempo na parte do timeout unsigned long timeout = 0; void setup() { Serial.begin(9600); Wire.begin(); sensor.init(); sensor.setTimeout(500); // Perfil de longo alcance sensor.setSignalRateLimit(0.1); sensor.setVcselPulsePeriod(VL53L0X::VcselPeriodPreRange, 18); sensor.setVcselPulsePeriod(VL53L0X::VcselPeriodFinalRange, 14); } void loop() { dist = sensor.readRangeSingleMillimeters(); filtrar_sinal(); // Filtra o valor de distancia Serial.println(dist); } // Função para filtrar o valor medido void filtrar_sinal() { // Se a distância medida for maior que 8000 e ainda não tiver passado 1 segundo de timeout if (dist > 8000 && ((millis() - timeout) < 1000)) { // Descarta a medição feita e iguala ela à anterior dist = dist_old; } else // Caso contrário (medição < 8000 ou passou do timeout) { // Não descarta a medição atual e atualiza a medição antiga para a atual dist_old = dist; timeout = millis(); // Reseta o valor da variável do timeout } } |
Resultado filtrando as medições
Em ambos os casos, com este simples procedimento de filtragem, as medições ficaram livre das oscilações de antes. Portanto, é uma coisa boa de ser feita, a não ser que você vá utilizar o sensor em um ambiente escuro livre da interferência solar.
Ligando dois ou mais sensores
Conforme foi dito no início do post, o endereço I2C do VL53L0X é programável. Desta forma, é possível utilizar diversos sensores ao mesmo tempo no mesmo barramento. E, pretendo mostrar como fazer isto com 2 sensores.
Circuito
A ideia do circuito é interligar os pinos SDA e SCL dos dois sensores, além de alimentar os sensores da mesma forma. E, também será necessário utilizar os pinos XSHUT dos sensores. Este último pode ser conectado em qualquer pino digital do Arduino (cada um em uma entrada digital separada).
Conforme dito anteriormente, a máxima tensão em cima do pino XSHUT deve ser 3.6V e o pino digital do Arduino funciona em 5V. Portanto, não podemos utilizar este pino como saída e aplicar um nível alto. Para isto, teríamos que utilizar um divisor de tensão, mas existe uma solução mais fácil que será explicada no próximo tópico.
Cheguei a utilizar o pino XSHUT com 5V várias vezes e meus sensores não queimaram, mas não é bom arriscar.
Como alterar o endereço I2C do sensor
Os sensores por padrão inicializam com o mesmo endereço I2C e é preciso alterá-los. Para isto, você mantém o pino XSHUT do sensor que você irá alterar em nível alto e desliga todos os outros colocando o pino XSHUT em nível baixo.
Como o Arduino não pode colocar o pino XSHUT em nível alto devido à tensão máxima, é necessário seguir outro caminho: definir o pino como entrada. Ao fazer isto, o pull-up interno do sensor automaticamente faz o pino XSHUT ficar em nível alto (~3,2V).
Com isto, resta apenas utilizar o comando abaixo para alterar o endereço (o valor está em hexadecimal, mas pode ser um número decimal mesmo):
1 2 | sensor.setAddress(0x32); // Basta alterar o valor de 0x32 para o endereço desejado (0-127 decimal) |
Após aplicar o comando acima, o endereço do sensor já fica alterado. Depois, é só religar os outros sensores e repetir o procedimento caso seja necessário reconfigurar outro sensor.
Código completo
Leia os comentários para entender.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | #include <Wire.h> #include <VL53L0X.h> // Instancia dois sensores VL53L0X sensor, sensor2; #define SHUT_1 7 #define SHUT_2 6 void setup() { Serial.begin(9600); Wire.begin(); // Define o sensor 2 como entrada para fazer o pino SHUT_2 ficar em nível alto pinMode(SHUT_1, OUTPUT); pinMode(SHUT_2, INPUT); // "Desliga" o sensor 1 digitalWrite(SHUT_1, LOW); delay(2); // Altera o endereço do sensor 2 sensor2.setAddress(0x32); // Religa o sensor 1 definindo ele como entrada pinMode(SHUT_1, INPUT); // É possível alterar o endereço do sensor 1 apenas com o código abaixo // Como o sensor 2 já está com endereço diferente, não é necessário desligá-lo, // pois ele não interferirá na comunicação //sensor.setAdress(0x31); // Inicializa sensores sensor.init(); sensor2.init(); sensor.setTimeout(500); sensor2.setTimeout(500); } void loop() { // Mede a distância dos dois sensores int dist1 = sensor.readRangeSingleMillimeters(); int dist2 = sensor2.readRangeSingleMillimeters(); Serial.print(dist1); Serial.print(" - "); Serial.println(dist2); } |
Código de dois sensores com filtro
O código abaixo é complementar ao anterior, pois adiciona uma função para filtrar as medições dos dois sensores. E o método de filtragem é de acordo com o que foi mostrado no tópico sobre a interferência da luz do sol.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 | #include <Wire.h> #include <VL53L0X.h> VL53L0X sensor, sensor2; // Define os pinos XSHUT #define SHUT_1 7 #define SHUT_2 6 int dist1_atual, dist1_old=0; int dist2_atual, dist2_old=0; unsigned long timeout1=0, timeout2=0; void setup() { Serial.begin(9600); Wire.begin(); // Define o sensor 2 como entrada para fazer o pino SHUT_2 ficar em nível alto pinMode(SHUT_1, OUTPUT); pinMode(SHUT_2, INPUT); // "Desliga" o sensor 1 digitalWrite(SHUT_1, LOW); delay(2); // Altera o endereço do sensor 2 sensor2.setAddress(0x32); // Religa o sensor 1 definindo ele como entrada pinMode(SHUT_1, INPUT); // Inicializa sensores sensor.init(); sensor2.init(); sensor.setTimeout(500); sensor2.setTimeout(500); // Longo alcance sensor.setSignalRateLimit(0.1); sensor.setVcselPulsePeriod(VL53L0X::VcselPeriodPreRange, 18); sensor.setVcselPulsePeriod(VL53L0X::VcselPeriodFinalRange, 14); sensor2.setSignalRateLimit(0.1); sensor2.setVcselPulsePeriod(VL53L0X::VcselPeriodPreRange, 18); sensor2.setVcselPulsePeriod(VL53L0X::VcselPeriodFinalRange, 14); // Alta velocidade sensor.setMeasurementTimingBudget(20000); sensor2.setMeasurementTimingBudget(20000); } void loop() { dist1_atual = sensor.readRangeSingleMillimeters(); dist2_atual = sensor2.readRangeSingleMillimeters(); filtrar_sinais(); Serial.print(dist1_atual); Serial.print(" - "); Serial.println(dist2_atual); } void filtrar_sinais(void) { if((dist1_atual > 8000) && ((millis()-timeout1) < 1000)) { dist1_atual = dist1_old; } else { dist1_old = dist1_atual; timeout1 = millis(); } if((dist2_atual > 8000) && ((millis()-timeout2) < 1000)) { dist2_atual = dist2_old; } else { dist2_old = dist2_atual; timeout2 = millis(); } } |
Excelentes explicações e código também muito bem comentado.
Parabéns!!
Grato.
Sds.,
José Alfredo.
Muito obrigado pelo comentário, José! Fico feliz que o conteúdo tenha te auxiliado.
Abraço,
Fábio
MUITO OBRIGADO, nossa… eu estava exatamente atrás de um post assim
Explicação muito boa, Parabéns!
Muitíssimo obrigado pelo comentário, Alexandre!! Espero que o site também possa te ajudar em outros assuntos.
Ola boa tarde!!
poderia me ajudar tentei usar quatro sensores mas nao deu certo!!
Bom dia, Francisco. Posso sim, mas, pra isso, preciso ver o código e o circuito pra entender o problema. Se puder, me envie uma mensagem por e-mail: mundoprojetado@gmail.com
Olá Fábio, boa tarde. Estou ajudando o Josiran. Nós conseguimos fazer algumas combinações de 3 dos 4 funcionar, mas outras combinações não e os 4 nunca funcionou. O código é exatamente o seu, só acrescentando mais dois e o circuito também.
Boa noite, Arthur! Entendido. Bem, eu não cheguei a testar com 4 sensores pra verificar se tem algo a mais que precisa ser feito, mas acredito que não. De toda forma, fica difícil te ajudar sem analisar o código ou o circuito. Até porque, dentro do código, erros podem passar despercebidos e, no circuito, pode haver mau contato ou coisas assim. Enfim, se desejar, pode me mandar o código por e-mail: mundoprojetado@gmail.com
Parabéns pela riqueza de detalhes.
Você é fera!!!
Que bom que gostou do post. Muito obrigado pelo comentário!
Cara !!!! Um dos posts mais detalhados que já vi.
Meus parabéns pelo capricho.
Caramba, é muito bom ler isso, Eduardo! Muito obrigado pelo comentário!
boa tarde
eu gostaria de usar um sensor deste mas eu preciso de distancia no minimo 20 mtrs sera que vai funcionar nao precisa ser preciso so mesmo avisar se algum objeto passou na frente
Bom dia, Antonio. Infelizmente o VL53L0X só mede até 2 metros. Não sei te indicar um sensor específico que seja capaz de detectar 20 metros, mas já vi um sensor ultrassônico sendo usado para isto. Talvez existam sensores infravermelhos com essa capacidade, mas, particularmente, não conheço.
me pode explicar como posso fazer o programa para 4 sensores?
Olá, Pedro. Para ligar 4 sensores você deve seguir a mesma lógica que foi feita com 2 sensores: os pinos SCL e SDA devem ser todos interligados e os pinos XSHUT devem ser ligados em pinos digitais diferentes. E na programação é preciso desligar 3 sensores (pino XSHUT) e mudar o endereço de 1, depois ligar mais um sensor e mudar o endereço e assim em diante. Se ainda tiver confuso, me mande mensagem por e-mail que te mostro um exemplo de código (mundoprojetado@gmail.com).
Não sou de comentar em sites, mas essa explicação da teoria do sensor ficou muito bom.
Parabéns Fábio Guimarães pelo trabalho!!!!
Olá, Walter. Muitíssimo obrigado! Espero que goste dos demais conteúdos do site.
Boa tarde, grato pelos ensinamentos .Uma pergunta,? Sabe me dizer qual é a distância que um sensor deve ficar do outro para não haver interferências entre eles?
Olá, Marcio. Ótima pergunta. Já cheguei a fazer testes com as placas (PCBs) de dois módulos estando uma do lado da outra e não observei interferência entre eles. Mas não sei te dizer qual é a distância mínima para não haver problemas.
Parabéns pela matéria. Excelente explicação detalhando muitas coisas que eu tinha dúvidas.
Foi a melhor matéria sobre estes sensores que achei, mesmo procurando em inglês.
Gostaria de uma idéia se alguém tiver.
Estou trabalhando com um esp32 , tenho dois motores controlados com a aplicação do PID e uso d biblioteca para encoders. Regulam a velocidade perfeitamente.
Tenho 8 sensores VL530X por I2C. Funcionam perfeitamente no loop ou em uma tasks no core 1 apenas. No core 2 não funciona, mas tudo bem.
Quando ligo os motores com o VL530X dentro de uma tasks, o VL530X da erro de leitura.
Se mudo o programa e uso o VL530X no loop, ele funciona mas os motores não conseguem ser controlado por PID para manter um rpm. Dá a impressão que o VL530X está atrasando a leitura dos encoders.
Teria algum jeito de pular a leitura se ela não tivesse completa pra não prejudicar o controle de rotação???
Mais uma vez parabéns…..
Ola, muito obrigado pelas explicações, o post ficou ótimo. Gostaria apenas de tirar uma dúvida sobre os endereços dos sensores. Uma vez atribuído um endereço, ele permanecerá para sempre ou vou ter que fazer o procedimento do xshut todas as vezes que ligar o arduíno.
Mais uma vez parabéns pela explicação e muito obrigado.
Olá, Jonathas. Eu que agradeço pelo comentário! Infelizmente o endereço não permanece e você precisa ficar mudando toda vez.
Parabéns pela matéria. Excelente explicação detalhando muitas coisas que eu tinha dúvidas.
Foi a melhor matéria sobre estes sensores que achei, mesmo procurando em inglês.
Gostaria de uma idéia se alguém tiver.
Estou trabalhando com um esp32 , tenho dois motores controlados com a aplicação do PID e uso d biblioteca para encoders. Regulam a velocidade perfeitamente.
Tenho 8 sensores VL530X por I2C. Funcionam perfeitamente no loop ou em uma tasks no core 1 apenas. No core 2 não funciona, mas tudo bem.
Quando ligo os motores com o VL530X dentro de uma tasks, o VL530X da erro de leitura.
Se mudo o programa e uso o VL530X no loop, ele funciona mas os motores não conseguem ser controlado por PID para manter um rpm. Dá a impressão que o VL530X está atrasando a leitura dos encoders.
Teria algum jeito de pular a leitura se ela não tivesse completa pra não prejudicar o controle de rotação???
Mais uma vez parabéns…
Show de bola, Alexandre. Valeu demais!
Boa pergunta viu. Já tentei encarar a biblioteca do VL53L0x, mas é bem assustadora hehe. Pelo que me lembro, a ST (fabricante do sensor) não fornece publicamente um datasheet dos registradores do sensor, então é bem difícil descobrir como controlar ele por conta própria pra criar esse tipo de ajuste. Se o problema for o atraso da leitura dos encoders, o ideal seria atrelar a leitura deles por interrupção para evitar que qualquer trecho do código cause interferência. Mas não sei te ajudar neste ponto, pois ainda preciso aprender a mexer com o esp32. Outra coisa que você pode tentar é ligar o perfil de medição high speed dos sensores e intercalar a leitura deles. Tipo: lê 1 sensor a cada segundo. E uma solução de último caso seria colocar um Arduino pro mini (ou outro) só para ler os sensores e comunicar com o esp32 via barramento serial. Enfim, espero ter ajudado!
Obrigado Fábio pela resposta.
Já estou utilizando os encoders com interrupção e estas interrupções que danificam a leitura do VL53L0x quando dentro de uma task.
Quando o VL53L0x está no loop ele atrasa a leitura do encoder fazendo com que o rpm oscile.
È isto mesmo que pensei , utilizar outra placa dedicada para o VL53L0x assim não tenho estas variações.
Aprendi pouco do esp32, mas gostei muito.
Parabéns mais uma vez!
Muito obrigado.
Obrigado Fábio pela resposta.
Já estou utilizando os encoders com interrupção e estas interrupções que danificam a leitura do VL53L0x quando dentro de uma task.
Quando o VL53L0x está no loop ele atrasa a leitura do encoder fazendo com que o rpm oscile.
È isto mesmo que pensei , utilizar outra placa dedicada para o VL53L0x assim não tenho estas variações.
Aprendi pouco do esp32, mas gostei muito.
Valeu!
Muito obrigado.
Por nada, Alexandre! Entendi, bem complicado esse problema então. Talvez a placa dedicada seja a solução mais acertada mesmo.
Pois é, o esp32 parece ser muito bom. Vou arrumar um tempo pra ver uns tutoriais.
Abraço!
Amigo, excelente seu post. Você não poderia me dar a dica de como ligar 3 sensores. Não estou conseguindo endereçar os 3. Obrigado!
Olá, Marcelo. Obrigado! Teoricamente, pra ligar os 3 juntos, você desliga 2 e endereça o que ficou ligado, religa 1 e endereça novamente e por fim religa o último. A lógica inicial do código seria mais ou menos assim:
// Configura SHUT_3 como entrada para ligar o sensor 3
pinMode(SHUT_1, OUTPUT);
pinMode(SHUT_2, OUTPUT);
pinMode(SHUT_3, INPUT);
// Desliga sensores 1 e 2
digitalWrite(SHUT_1, LOW);
digitalWrite(SHUT_2, LOW);
// Muda endereço do sensor 3
sensor3.setAddress(0x32);
// Religa sensor 2
pinMode(SHUT_2, INPUT);
// Muda endereço do sensor 2
sensor2.setAddress(0x33);
// Religa sensor 1
pinMode(SHUT_2, INPUT);
// Muda endereço do sensor 1
sensor1.setAddress(0x34);
…
Se não der certo, verifique também as ligações. Qualquer coisa, me mande o código e a ligação que você está usando por e-mail (mundoprojetado@gmail.com), que tento verificar o problema.
Prezado Fábio,
parabéns pela iniciativa de compartilhar o seu conhecimento. Em especial é muito valiosa a informação de como fazer para atribuir endereços I2C para vários módulos VL53L0X sem a necessidade de utilizar conversores de nível (level converters) ou divisores de tensão resistivos e mais fantástico ainda mostrar um exemplo de filtragem por software.
Se possível, pretendo contribuir com os teus ensinamentos alertando para alguns fatos depois de ler atentamente as informações na página, efetuar alguns experimentos e medições:
Para “desligar” os sensores configuram-se os pinos escolhidos para comandar os sinais XSHUT como “OUTPUT”, o que garante nível baixo nestes sinas e desabilitando os sensores, tal como explicado. Para “ligar”, ou sela garantir nível alto basta tão somente configurá-los como “INPUT” e então atribuir os endereços, procedimento que pode ser efetuado sequencialmente uma vez que os sensores com novos endereços irão ignorar a operação.
Quanto à tensão aplicada nos pinos XSHUT dos VL53L0X com os pinos do Arduino configurados como INPUT, medi 3,2V ao invés de 2,8V. Apesar da tensão ser mais alta, o sensor não é danificado. Não arrisquei colocar 5V diretamente apesar de ter lido em outras páginas que o sensor aguenta essa tensão. Seja como for, não é bom arriscar.
E por último, no diagrama de conexões de como ligar dois VL53L0X no Arduino UNO, o pino D7 está no XSHUT do primeiro sensor e o pino D6 no XSHUT do segundo sensor, ao contrário do que está definido nos programas-exemplo.
Abraços,
João Roberto Gabbardo
Olá, João. Muitíssimo obrigado pelos elogios e pela excelente contribuição. Fiz as correções no post conforme você pontuou!
Grande abraço!
Olá, porque tudo o que consigo é:
“Adafruit VL53L0X test
17:53:29.641 -> ⸮[⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮”
Obrigado desde já.
Olá, Reinaldo. Me parece que você está usando a biblioteca da Adafruit. Teste o sensor com a biblioteca que indiquei no post para ver se assim o sensor funciona normalmente.
GOSTEI MUITO DO MATERIAL.
EU GOSTARIA DE FAZER UMA PERGUNTA.
EU PRECISO QUE O SENSOR ENCONTRE UMA MÉDIA DAS MEDIDAS ENCONTRADAS E ME DE UM VALOR FIXO, SEM VARIAR.
PARA QUE MESMO ENTRE EM UMA FORMULA INSERIDA NA PROGRAMAÇÃO, FIZ ALGUNS TENTATIVAS MAS NÃO DEU CERTO.
ALGUMA DICA PARA SOLUÇÃO DESSE PROBLEMA?
Que ótimo, André! Mesmo que o objeto na frente do sensor esteja totalmente imóvel, a medida de distância irá variar um pouco, por conta da imprecisão e ruído da medição. Com certeza a média ajuda a amenizar essa variação, talvez você precisa aumentar a quantidade de amostras da média pra melhorar o resultado que você está obtendo. Quanto maior a quantidade, mais estável será a medida. Outra coisa que você pode fazer é arredondar o valor medido.
OI
Tudo bem?
Não entendi o que é esse 8000
if((dist1_atual > 8000) && ((millis()-timeout1) < 1000))
{
dist1_atual = dist1_old;
}
Olá, Jorge. Tudo bem e com você?
Acontece que a biblioteca retorna o valor de 8000 quando a distância lida é maior do que o valor máximo (2 metros). Para este caso, eu forcei o código a utilizar a última leitura, ao invés de usar o valor de 8000 (que é um valor inválido).
Oi amigo
Tudo bem?
Mano teria como você explicar como seria utilizando 3x sensores VL53L0X
Olá. Tudo certo, e com você?
Dá uma olhada na explicação que dei pro Marcelo aqui nos comentários, pois ele teve a mesma dúvida que você.
Oi eu fiz o código com 3x sensores e gostaria que desse uma olhada por onde posso mandar
Me mande por email: mundoprojetado@gmail.com
Estou fazendo uma torneira automática, mas o local recebe luz solar indireta. Com o sensor de ultrassom funciona normalmente, mas com o infravermelho fica uma droga, pois luz indireta o aciona sozinho. Será que se usasse esse a laser também sofreria com luz solar indireta?
Olá, Nelson. Só testando mesmo pra ter certeza. Mas te digo que esse sensor (VL53L0X) sofre bem menos interferência do aqueles sensores simples que utilizam um LED infravermelho diretamente. Te digo isso, pois já tentei criar um sistema utilizando esses 2 tipos de sensores e o sensor infravermelho simples não funcionou nada bem, enquanto o VL53L0X funcionou sem problemas para distâncias pequenas (menor que 1,5m).
Oi, Fábio, parabéns pelo post! Rico em detalhes, bem escrito e bastante didático. Aproveitando a oportunidade, gostaria de tirar uma dúvida.. Esse sensor seria capaz de detectar um objeto que passa por ele numa velocidade de 11 a 12 m/s? Sei que o intuito dele não é detectar a presença do objeto, mas sim aferir a distância para o objeto, porém, para a minha finalidade, o importante é detectar, mesmo que a distância aferida não seja tão precisa.
Olá, Lucas. Brigadão!
Excelente pergunta. Não tenho total certeza se daria certo ou não, mas acredito que não. O sensor no modo de alta velocidade (high speed) tem um tempo de resposta de 30ms e um objeto à uma velocidade de 12m/s percorre 36 cm nesse tempo (30ms). Ou seja, o objeto pode passar na frente do sensor sem que ele perceba, pois durante o tempo de leitura (30ms), o objeto pode deslocar até 36 cm e o sensor não tem um cone de leitura tão amplo assim. Portanto, recomendo olhar outro sensor ou então fazer um teste prático pra ter certeza.