Poor man LIDAR motor unipolar

          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

// Secuencia de pasos (par máximo)
int paso [4][4] ={
  {1, 0, 0, 0},
  {0, 1, 0, 0},
  {0, 0, 1, 0},
  {0, 0, 0, 1}
};

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);
}

Menu