Un LIDAR es un dispositivo que permite determinar la distancia desde un emisor láser a un objeto o superficie utilizando un haz láser pulsado. La distancia al objeto se determina midiendo el tiempo de retraso entre la emisión del pulso y su detección a través de la señal reflejada. Esto permite generar modelos bi o tridimensionales del entorno.
Este proyecto es un LIDAR bidimensional, es decir, mapea la dirección y la distancia de los objetos circundantes en un solo plano y que es útil para por ejemplo el control autónomo de robot.
El rayo laser ha de girar 360 grados de forma continua para ese mapeo del entorno, lo cual conlleva el problema de los cable que unen al sensor LASER (que está girando) con el resto de circuito de control.
Esto puede resolverse de dos forma. -Mantener estático el sensor LASER con el resto de circuitos y enviar el rayo a través de un espejo superior e inclinado 45 grados y que es el que realmente gira. -Usar un dispositivo llamado SLIP RING. Consta de una parte fija con cables a circuitos de control y otra superior con los mismos cables y que pueden girar sin enredarse.
Uso el segundo método, pero como habitualmente eso implica dos estructuras (motor y circuitos) y requiere una impresora 3D que no tengo por falta de espacio. Así, en vez de usar un sistema adyacente he probado uno sobrepuesto. Motor abajo pasando su eje a través del SLIP RING.
El sensor VL53L1X integra un laser infrarrojo de 940nm que mide el tiempo de reflexión independientemente de las caracteristicas fisicas de los materiales reflejados (color, forma, textura y reflexibilidad). Sí es cierto que funciona mejor con luz ambiente baja o en oscuridad. La distancia mínima que mide es de 4cm y máxima de 400cm y resolución de 1mm. Tiene tres modos: Long(400mm en oscuridad), Medium(300mm en oscuridad) y Short(130mm, el más inmune a interferencias de luz ambiente).
El elemento clave del montaje es el SLIP RING.
Por un lado tiene cuatro cables (pueden ser más) que están fijos y que van al Arduino Nano (foto de mas a la izquierda)
En el otro lado los cable pueden girar y van al sensor laser.
Dos cables de alimentación y otros dos para el I2C
El Arduino podemos alimentarlo por Vin con los 9v que van al motor. El sensor y el Hall toman los 5v del Nano. El motor 28BYJ-48 es unipolar de cinco hilos y que junto a su controladora es muy común y barato. Esta muy desmultiplicado (4096 pasos) lo que le dan gran precisión de giro pero con poco torque, por ello lo alimento a 9-10v aunque es de 5v. Para cortos periodos no hay problema..
El sensor Hall por medio de un imán puesto en la rueda de giro superior y a través del pin 2 hace que el programa en Processing borre los datos tras cada giro completo.
Los componentes. Arduino Nano, motor 28BY-48 con su controladora, módulo Hall, SIP RING y sensor laser VL53L1X.
Rueda superior rescatada de no se donde. El eje que la une al motor es un tornillo de métrica M4.
Y sí, la tabla es secuestrada de la cocina.
//PoorManLIDARunipolar.ino //www.jopapa.me 2024
#include <Wire.h> #include <VL53L1X.h>
VL53L1X sensor;
const int Hall = 2; // Definimos los pines donde tenemos conectadas las bobinas #define IN1 8 #define IN2 9 #define IN3 10 #define IN4 11
int pasos=0; int sHall; float angulo=0; int distancia; int flag=0;
void setup(){ Serial.begin(9600); delay(10); Wire.begin(); Wire.setClock(400000); // use 400 kHz I2C sensor.setTimeout(500); if (!sensor.init()){ Serial.println("Failed to detect and initialize sensor!"); while (1);}
sensor.setDistanceMode(VL53L1X::Medium); //Long(400mm), Short(130mm), Medium sensor.setMeasurementTimingBudget(40000); sensor.startContinuous(50); // Todos los pines motor en modo salida pinMode(IN1, OUTPUT); pinMode(IN2, OUTPUT); pinMode(IN3, OUTPUT); pinMode(IN4, OUTPUT);
pinMode(Hall, INPUT); }
void loop(){ flag++; //Solo mitad de medidas de distancia para acelerar el motor if (flag==2){ distancia=sensor.read(); flag=0;}
//distancia = sensor.readRangeSingleMillimeters(); for (int i = 0; i < 4; i++){ digitalWrite(IN1, paso[i][0]); digitalWrite(IN2, paso[i][1]); digitalWrite(IN3, paso[i][2]); digitalWrite(IN4, paso[i][3]); delay(2); }
sHall=digitalRead(Hall); if (sHall != 0){ //detecta el paso por el imán Serial.print(angulo); Serial.print(","); Serial.print(distancia/5); Serial.println(","); angulo = angulo+0.757; } else{ angulo=0; }
}
Los datos se capturan con el programa en Arduino y se visualizan por cable USB en el ordenador con un Sketch en lenguaje Processing
//PoorManLIDARunipolar.pde //www.jopapa.me 2024
import processing.serial.*;
Serial myPort; // Objeto para el puerto serial
void setup() { size(600, 600); background(136, 203, 255); // Cambia el nombre del puerto serial según tu configuración myPort = new Serial(this, "COM5", 9600); }
void draw() { while (myPort.available() > 0) { String data = myPort.readStringUntil('\n'); if (data != null) { // Divide los datos en ángulo y distancia String[] values = split(data, ','); if (values.length > 2) { float angle = float(values[0]); //Limpia pantalla if(angle==0) background(136, 203, 255); float distance = float(values[1]); // Llama a la función para graficar en el círculo plotOnCircle(angle, distance); } } } }
void plotOnCircle(float angle, float distance) { stroke (0); //Color del punto (negro) strokeWeight (2); //Tamaño del punto // Convierte ángulo a radianes float radians = radians(angle);
// Calcula coordenadas x, y en el círculo float x = width / 2 + cos(radians) * distance; float y = height / 2 + sin(radians) * distance;
// Dibuja un punto en las coordenadas calculadas point(x, y); }