Introducción
En la primera parte de esta serie conectamos el sensor ToF a una D1 Mini NodeMCU ESP8266 y construimos una advertencia acústica de distancia. En esta publicación quisiera utilizar un ESP32 NodeMCU así como un Arduino Nano. Quiero descubrir qué funcionalidad está aun disponible y si podemos usar los pines GPIO1 y XSHUT. Así que comencemos!
Hardware
Número | Componente | Nota |
---|---|---|
1 | VL53L0X Sensor Board pasado de moda de break | |
1 | ESP8266 Node la mini MCU D1 | |
1 | ESP32 NodeMCU módulos o ESP32 Dev Kit | |
1 | Arduino Nano | |
1 | Piezo Buzzer pasivo KY-006 la alarma el módulo para Arduino | |
Cable de relación | ||
Ordenador con Arduino IDE y relación de Internet |
Conexión de Pines
Primero, conectamos el sensor a una mini D1 Mini NodeMCU ESP8266 como en la Parte 1 según el siguiente diagrama de conexión:
Pines de VL53L0X | Pines de D1 Mini GPIO |
---|---|
VIN | 3.3VOLTMETER |
GND | GND |
SCL | SCL (D1 / GPIO5) |
SDA | SDA (D2 / GPIO4) |
GPIO1 | - |
XSHUT | - |
Buzzer KY-006 | D1 la mini GPIO |
- (Menos) | GND |
S (la señal) | D7 (GPIO 13) |
Liberamos los pines GPIO1 y XSHUT.
Para recordar: Para los Pines-IqC SDA y SCL se recomienda revisar la descripción general del Pinout. En el ESP8266, estos Pines GPIO4 y GPIO5 están etiquetados como D2 y D1 en la placa. Sin embargo, esto es diferente de un microcontrolador a otro microcontrolador. El pin número 13 tiene que ser utilizado en el Arduino IDE. Este Pin está etiquetado con D7.
En la primera parte tenemos las siguientes ampliaciones y cambios al código de ejemplo vl53l0x realizado:
#define BUZZER 13 #define FREQ 800 #define DURATION 300
Una variable para la medición de tiempo:
unsigned long zeitAlt = 0;
En setup () inicia el pin Buzzer como salida:
pinMode(BUZZER, OUTPUT);
Cuestión de la medición de tiempo en el loop ():
if (measure.RangeStatus != 4) { // phase failures have incorrect data
Serial.print("Distance (mm): "); Serial.println(measure.RangeMilliMeter);
} else {
Serial.println(" out of range ");
}
Añade Buzzer:
if (measure.RangeStatus != 4) { // phase failures have incorrect data
Serial.print("Distance (mm): ");
Serial.println(measure.RangeMilliMeter);
if (millis() - zeitAlt >= measure.RangeMilliMeter * 3) {
zeitAlt = millis();
tone(BUZZER, FREQ, DURATION);
}
} else {
Serial.println(" out of range ");
}
Si descargamos el programa en el microcontrolador, tenemos el estado de la última vez y ahora podemos continuar.
Código fuente completo: ToFBuzzerESP8266_Adafruit.ino
ESP32
Ahora cambiamos al módulo ESP32 NodeMCU. Por esto conectamos el sensor y Buzzer según el siguiente diagrama de conexión:
VL53L0X Pins | ESP32 |
---|---|
VIN | 3.3Voltmeter o el 5Voltmeter |
GND | GND |
SCL | GPIO22 |
SDA | GPIO21 |
GPIO1 | - |
XSHUT | - |
Buzzer KY-006 | ESP32 |
- (Menos) | GND |
S (la señal) | GPIO13 |
Según en el diseño de la placa de desarrollo, la disposición de los pines puede variar.
En el Arduino IDE cambiamos la placa a ESP32 utilizando herramientas y cargando el mismo programa en el microcontrolador. Recibimos un aviso de error que la función tonnes () no es reconocida. Ésto no está implementado en el ESP32 Core. Hay algunos derivados en la librería administración. Encontré Github la librería Tone32. Esta funciona de forma similar a la función Arduino Tone. Hay sólo otro parámetro con el nombre "Channel", que nosotros establecemos a 0. Puede descargar el código fuente como ZIP. A continuación selecciona el Arduino IDE en el menú el Sketch >Include Library > .Add ZIP library.
En el código fuente de nuestro programa añadimos las siguientes líneas:
#include <Tone32.h>
#define BUZZER_CHANNEL 0
Luego cambiamos la línea:
tone(BUZZER, FREQ, DURATION);
en
tone(BUZZER, FREQ, DURATION, BUZZER_CHANNEL);
Esto debería permitir cargar y hacer que todo funcione como con el D1 Mini. Sin embargo, me ha llamado la atención que la salida de sonido causa retrasos en el tiempo. Dado que no conozco la librería, no puedo explicar exactamente de momento el motivo de esto. Aparentemente, la salida de sonido no funciona sin bloquear. Esto tendrá que ver con los temporizadores utilizados y el PWM generado. También hay una librería llamada ESP32Servo, que se puede encontrar en la administración. También existe la función Tonnes () implementada. Sin embargo, presenta el mismo comportamiento. En caso de que usted quisiera probarlo, instale esta librería y cambie de la siguiente manera el código fuente:
#include <ESP32Servo.h>
En Setup ():
ESP32PWM::allocateTimer(0); ESP32PWM::allocateTimer(1); ESP32PWM::allocateTimer(2); ESP32PWM::allocateTimer(3);
y en ella loop ():
tone(BUZZER, FREQ, DURATION);
Así lo he tomado del ejemplo conentregado. Sin embargo, pienso que esta biblioteca es un poco de peso, dado que ella ofrece también la otra funcionalidad.
Hay la posibilidad de programar la producción de sonido händisch con PWM. No quisiera llegar más lejos a ello, dado que se trata en esta contribución sobre todo del ToF sensor.
Código fuente completo: ToFBuzzerESP32_Adafruit.ino
Arduino NANO
Para una advertencia acústica de distancia, WLAN no es a toda costa necesario (sin embargo, es una de las causas más importantes para usar ESP). Es por esto que, quisiera reconstruir el circuito con el Arduino NANO.
Pines de VL53L0X | Arduino NANO |
---|---|
VIN | 5Voltmeter o el 3.3Voltmeter |
GND | GND |
SCL | A5 |
SDA | A4 |
GPIO1 | - |
XSHUT | - |
Buzzer KY-006 | Arduino NANO |
- (Menos) | GND |
S (la señal) | D13 |
Para los Pines SDA y SCL tenemos que revisar de nuevo la descripción general del Pinout. En Arduino Nano (y también en UNO) son los Pines A4 y A5. Dado que utilizamos de nuevo el Pin 13 para el Buzzer, que también controla el LED interno del Nano, tenemos una señal óptica para el acústico al mismo tiempo.
Ahora abrimos el programa que habíamos cargado al comienzo en el D1 Mini. También podríamos reutilizar ese. En el Arduino IDE en el menú Tools cambiamos la placa de nuevo y seleccionamos el Arduino Nano. Eventualmente puede ser necesario convertir al antiguo gestor de arranque en "processor". En mi caso, se debe realizar esto. Si aparece un aviso de error cuando está cargando, intente esta opción.
Si ejecutamos el programa, la alarma de distancia vuelve a funcionar como en el D1 Mini. El sonido suena un poco diferente. Esto se debe a la frecuencia de ritmo menor. Se puede percatar que no hay ningún retraso en la producción de sonido. Esto se debe por la función tonnes () de la librería Arduino Core, que podemos utilizar de nuevo con el Nano.
Ahora hemos probado el sensor en todos los tres microcontroladores. La librería Adafruit puede ser utilizada, según la aplicación, con uno de los dispositivos. Si usted quiere transmitir los datos a una red, el Arduino Nano no entra en consideración por ahora. Si el retraso en la producción de sonido es obstructivo, no tome en cuenta el ESP32.
Aquí puede probar la librería Pololu independientemente con los otros dos microcontroladores. Utilice el código fuente en la Parte 1.
Código fuente completo: ToFBuzzerESP8266_Adafruit.ino
Precisión vs Velocidad vs Rango
En la descripción del sensor ToF (revise la Parte 1) está explicado que puede cambiar los perfiles de clasificación. Los modos disponibles son “High Accuracy” (Alta precisión), “High speed” (Alta velocidad), “Long range” (Largo rango) y “Default” (Predeterminado). Para convertirlo, he tenido que investigar más en el código fuente de la librería Adafruit, ya que no se proporciona ningún ejemplo.
En este caso, los modos se definen como un nuevo tipo de datos. Estos se denominan:
- VL53L0XGUADAÑADEFAULT
- VL53L0XGUADAÑALONG_RANGE
- VL53L0XGUADAÑAHIGH_SPEED
- VL53L0XGUADAÑAHIGH_ACCURACY
En la Adafruit_VL53L0X hay una función denominada configSensor (), a la cual se pasa al modo deseado. Escribimos en la función setup () después de iniciar el sensor, la línea siguiente:
lox.configSensor(Adafruit_VL53L0X::VL53L0X_SENSE_HIGH_ACCURACY);
Con esto se establece el sensor en el modo "High Precision". Si deja esta línea, VL53L0X utilizará automáticamente SENSEDEFAULT. Reemplace VL53L0XSENSEHIGHACCURACY por VL53L0XSENSELONGRANGE, puede ver obstáculos hasta 2 m de distancia. Esto reduce la exactitud. Detrás de este modo hay una instrucción de switch-case en la librería que establece los valores para el presupuesto de tiempo, el período de pulso y la tasa de la señal.
Código fuente completo: ToFBuzzerESP8266AdafruitTeil2.ino
Para realizar el mismo cambio con la librería Pololu, abrimos el ejemplo de sketch "Single". La posibilidad de cambiar el modo está implementada allí. Sólo debemos comentar en una de las líneas (escojo aquí el modo “Long Range”):
#define LONG_RANGE
//#define HIGH_SPEED
//#define HIGH_ACCURACY
Para que podamos incorporar esto en nuestra advertencia acústica de distancia, agregamos en el ejemplo, el código fuente correspondiente del ejemplo Continuous de la Parte 1 que habíamos cambiado.
Constantes:
#define BUZZER 13
#define FREQ 800
#define DURATION 300
Variable para la medición de tiempo:
unsigned long zeitAlt = 0;
En Setup () estas líneas incorporan o adaptan:
Serial.begin(115200);
pinMode(BUZZER, OUTPUT);
...
Serial.println(F("Failed to detect and initialize sensor!"));
...
En ella loop () la medición de tiempo incorporan:
void loop()
{
if (sensor.timeoutOccurred()) { Serial.print(" TIMEOUT"); }
if (sensor.readRangeSingleMillimeters() < 4000) {
Serial.println(sensor.readRangeSingleMillimeters());
if (millis() - zeitAlt >= sensor.readRangeSingleMillimeters() * 3) {
zeitAlt = millis();
tone(BUZZER, FREQ, DURATION);
}
}
else {
Serial.println(" out of range ");
}
}
Volveré a utilizar ESP8266 D1 Mini y subiré el programa allí. Ahora también podemos ver obstáculos con esta librería con una distancia de hasta 2 m.
Código fuente completo: ToFBuzzerESP8266PololuSingle_LongRange.ino
XSHUT Pin y varios sensores
El Pin XSHUT está allí para traer el sensor en un modo hardware standby. Por ejemplo, así puede encender y apagar los sensores individuales. Por ejemplo, así ellos no se molestan mutuamente (según el fabricante, sin embargo, ningunas molestias se presentarán, mientras los sensores no estén dirigidos directamente uno sobre el otro). Para la colaboración de los sensores hay diferentes posibilidades. La lectura de los valores medidos es sincronizada o asíncrona. También se puede utilizar el GPIO1. Así, cada sensor se lee sólo si también puede proporcionar valores útiles.
Cuando utilice múltiples sensores, es importante establecer la dirección IqC. Ejemplos de esto se presenta en la librería Adafruit. En el ejemplo de sketch "vl53l0x_dual" presenta como utilizar al mismo tiempo dos sensores. Dado que cada sensor tiene la misma dirección por defecto (0x29), las direcciones tienen que ser reasignadas de nuevo. Desafortunadamente, éstas no se conservan permanentemente, por lo que tienen que ser establecidas de nuevo cada vez que se reinicia el microcontrolador. Los sensores deben ser encendidos uno tras otro usando XSHUT y luego se deben asignar las direcciones respectivas. Adafruit presenta una breve instrucción.
Se necesitan pines digitales adicionales en el microcontrolador para los pines XSHUT de los sensores.
En este punto pondré un sensor a dormir en XSHUT. Ampliamos nuestro circuito en el D1 Mini conectando desde el pin XSHUT al Pin D6 (GPIO12).
Ahora, en el código del programa para nuestra advertencia acústica de distancia, completamos la asignación de pines y el despertar. Utilizo aquí la librería Adafruit:
Una constante para Pinnummer:
#define XSHUT 12
Variable para mediciones de tiempo y estado de XSHUT-Pins:
unsigned long sleepTime = 2000;
unsigned long sleepTimeAlt = 0;
bool XSHUT_STATE = HIGH;
Pin en Setup () cuando la salida inicializan y en HIGH apostar:
pinMode(XSHUT, OUTPUT);
pinMode(XSHUT, OUTPUT);
digitalWrite(XSHUT, XSHUT_STATE);
Si el sensor es desconectado por XSHUT en el principio, no será reconocido más en la inicialización subsecuente. Si no damos al pin un estado claro, esto puede ser a que él se encuentra todavía en el estado LOW, lo que significa que el sensor no es reconocido.
En el principio loop () la función incorporamos líneas siguientes:
if (millis() - sleepTimeAlt >= sleepTime) {
sleepTimeAlt = millis();
XSHUT_STATE = !XSHUT_STATE;
digitalWrite(XSHUT, XSHUT_STATE);
if (XSHUT_STATE == HIGH) {
Serial.println("Sensor On");
if (!lox.begin()) {
Serial.println(F("Failed to boot VL53L0X"));
while(1);
}
}
else {
Serial.println("Sensor in Standby");
}
}
Cuando el tiempo se acaba, el estado se conecta al pin digital para el XSHUT. Cuando el sensor se despierta, es necesario utilizar lox. () para ser reiniciado. Si cargamos el programa en el D1 Mini, la medición de la distancia debe encenderse y apagarse en el intervalo especificado. La desventaja en este caso es que el sensor sigue entregando el último valor medido después de ser puesto en espera. Para hacer esto un poco más limpio y medir realmente sólo cuando XSHUT está en HIGH, ajustamos el código fuente de nuevo y establecemos la medición del sensor en una instrucción if:
if (XSHUT_STATE) {
Serial.print("Reading a measurement... ");
lox.rangingTest(&measure, false); // pass in 'true' to get debug data printout!
if (measure.RangeStatus != 4) { // phase failures have incorrect data
Serial.print("Distance (mm): ");
Serial.println(measure.RangeMilliMeter);
if (millis() - zeitAlt >= measure.RangeMilliMeter * 2) {
zeitAlt = millis();
tone(BUZZER, FREQ, DURATION);
}
} else {
Serial.println(" out of range ");
}
}
Gracias a la extensión, el sensor es sólo utilizado si el estado del pin XSHUT está en HIGH. Descargue el programa en el microcontrolador y pruébelo.
Ahora hemos conectado y desconectado el sensor en función del tiempo. Si usamos el sensor de distancia en un vehículo, podríamos conectar el pin XSHUT a través de un circuito electrónico, por ejemplo, con la marcha atrás. La mayoría de las veces hay una conexión que asegura que la luz de retroceso se encienda. Esto permitiría utilizar el dispositivo de advertencia acústico sólo si se conduce hacia atrás.
Si construye un robot, puede equiparlo con varios de estos sensores y dependiendo de los requerimientos, sólo conecta un sensor que señala en una dirección determinada.
Código fuente completo: ToFBuzzerESP8266AdafruitTeil2_XSHUT.ino
Si quiere utilizar la librería Pololu en lugar de la librería Adafruit, el programa tiene aspecto muy similar. Habíamos desarrollado nuestra advertencia acústica de distancia del ejemplo "single". Lo completamos con las mismas variables y ajustes. La única diferencia son los nombres de las llamadas a las funciones. Para despertar el sensor, a continuación, se llevará a cabo lox. () la función sensor.init (), al igual que en la función setup().
Código fuente completo: ToFBuzzerESP8266PololuSingleLongRangeXSHUT.ino
GPIO1 e Interrupts
Por último, quisiera mencionar el pin GPIO1 en el sensor ToF. Este pin digital está conectado cuando un obstáculo se encuentra dentro de una distancia establecida al sensor. Así es la teoría. Desafortunadamente, esto no está documentado bien, aunque esto haya sido implementado por STM en el API. Para el Arduino IDE esto no ha sido implementado en detalle. Primero, queremos ampliar el circuito y conectar el pin:
GPIO1 del sensor ToF conectamos con D5 (en Arduino IDE pin 14). Desde este punto he investigado por mucho tiempo como se puede utilizar el GPIO1 en conjunto con una interrupción. Kris Winer ha usado la librería Pololu y en Github ha escrito un programa Arduino para el ESP32. He modificado algo para que funcione con ESP8266:
LED-Pin de modo cambiado de 5 a 2:
int myLed = 2;
La I²C inicialización sin parámetro:
Wire.begin ();
La variable en Interrupt el servicio la práctica tiene que estar declarada volatile:
volatile bool newData = false;
Interrupt el servicio la práctica tiene que ser cargado en ESP8266 en IRAM. Por ello completamos lo siguiendo:
ICACHE_RAM_ATTR void myinthandler()
{
newData = true; // set the new data ready flag to true on interrupt
}
Si cargamos el programa al D1 Mini, la medición de distancia debería ser visible en el monitor en serie. Si removemos el pin D5, la medición será interrumpida. Así se demuestra que el interruptor funciona. Desafortunadamente, no se ha implementado ninguna forma de introducir los valores de umbral a partir de los cuales debe activarse la interrupción. Esto significa que los datos de medición se detectan siempre y, por lo tanto, la interrupción se activa siempre. En realidad, esto funciona tan bien como el ejemplo "Continuous" sin la funcionalidad de interrupción. Así que esto no es realmente útil.
Código fuente completo: ToFESP8266Interrupt_Pololu.ino
Con la librería Adafruit (stand version 1.1.0) un ejemplo se denomina como vl53l0xmultiextended en el cual un modo asincrónico utilizando el GPIO1 está implementado. La función se denomina timedasyncread_gpio (). De ello se puede derivar un programa similar al anterior con la librería Pololu. La funcionalidad es la misma. Desafortunadamente, tampoco hay la posibilidad de introducir los valores de umbral.
En Github si esto da también una versión vieja de la Adafruit biblioteca, Interrupt ejemplo contiene. El ejemplo llama las funciones que no están disponibles en la versión actual. Por eso he instalado esta versión antigua y luego he cargado el ejemplo en D1 Mini. Muchas advertencias se presentan durante la compilación, lo cual no es una buena señal. El propio programa tampoco se ejecuta en el microcontrolador. Es posible eventualmente reescribir la versión actual de la librería y transferir las funciones existentes que están disponibles en la versión vieja. Eso ya no es trivial. Por eso termino mis pruebas aquí.
Conclusión
He realizado muchas investigaciones y pruebas. Adafruit y Pololu ofrecen librerías para utilizar el sensor basado en el API de STMicroelectronics en el Arduino IDE. Interrupciones en un Arduino no son normalmente necesarias. Sin embargo, dado que ESPs soporta Deep Sleep, una interrupción que pueda despertar al microcontrolador del Deep Sleep sería útil.
Utilizando los diferentes microcontroladores con ambas librerías en esta forma ha funcionado. También pudimos establecer los modos para los perfiles de clasificación.
Debido a las mutuas posibles interferencias de los sensores de distancia acústicos, el Sensor Tiempo de Vuelo VL53L0X es una alternativa muy buena para la detección de obstáculos de nuestros coches robot.
Andreas Wolter
para AZ-Delivery Blog
5 comentarios
Klaus
Hallo Walter, ich habe eine Softwarelösung zur Glättung der Messwerte eingebaut.
In meinem Projekt verwende ich 2 VL53L0X, wozu softwaremäßg die Bus-Adressen geändert werden müssen. Bisher habe ich diese Möglichkeit nur in der Bibliothek von adafruit gefunden. Diese ist aber sehr speicherintensiv, sodaß eine weitere Programmierung in dem Sketch kaum möglich ist. Gibt es eine andere, nicht so speicherintensive Bibliothek, die das Ändern der Bus-Adresse unterstützt?
Gruß Klaus
Andreas Wolter
um die Werte zu stabilisieren, müsste man entweder einen fertigen Filter einsetzen, oder selbst einen Basteln. Man könnte dafür mehrere Datensätze speichern und den Mittelwert bilden. Beides kostet dann allerdings etwas Zeit.
Bender Klaus
Hallo, ich setze den VL53L0X mit dem arduino uno ein. Verwende die Bibliothek von adafruit. Kann man den VL53L0X zu einstellen, dass er bei gleichem Abstand den gleichen Wert ermittelt. Zurzeit variieren die Werte in Bereich von bis zu 5mm. Der Abstand zwischen Sensor und Objekt beträgt ca. 5 – 10 cm.
Wäre schön, wenn Sie mir helfen könnten.
Herzlichen DAnk
Bender
Matthias
Hallo Andreas, ich habe mit den aufgeführten Qellcodes D1 mini / EPS8622 und den aktuell von Az gelieferten VL53L0X Probleme. (6 Stück)
Die Adressen (0×29) werden nicht erkannt und dementsprechend eine Fehlermeldung: “Failed to detect and initialize sensor!” aus gegeben. Ist dieses durch eine Änderung des Quellcodes behebbar?
Ältere Sensoren haben dieses Problem nicht. Verwendet wird die Schaltung im Modelleisenbahnbereich, wobei ab einer bestimmten Entfernung ein ja /nein Aussage benötigt wird.
Mfg
Walter
Hallo Andreas,
vielen Dank für deinen Bericht und deine Mühe.
Konstet Du ermitteln welchen Öffnungswinkel der Sensor besitzt?
Also z.b. bei einer Entfernung von 100 cm muss die Refektionsfläche (bei 90 grad) im minimum …? mm² betragen und was ist wenn sich der Winkel ändert?