Skip to content

Encoder

iliasam edited this page Aug 2, 2024 · 14 revisions

Encoder consists of two main parts: encoder disc and optical sensor

Encoder disc

I have taken this disc from old ball mouse.
Encoder photo
This disc have 65 slits, one of them is closed (but it is counted too: 64 opened + 1 closed) - it is zero angle reference mark.
See this drawing:
image

Number of slits is defined in "config.h" file: "ENCODER_HOLES_CNT".
Diameter of the disc is 15.5 mm.

Optical sensor

I have taken mine sensor from old printer so I can't give exact name of it. It is conventional opto-interrupter, with one LED and one NPN photo-transistor.
Closed opto-interrupter (no current through opto-transistor) is need to produce high level at the sensor output.
Notice that if you are using disc with a small diameter, you need to use sensor with small diameter of the optical beam - usually such sensors have smaller packages.
It is recommended to make sensor fixing adjustable - to change position of the light beam in relation to disc.

Sensor is connected to the PCB using 3 wires: +3.3V (ENC PWR), GND, Signal (connect it to P6 pad).
See "PCB_3D_view_up.png": https://github.com/iliasam/OpenTOFLidar/blob/develop/PCB/PCB_project_v4/PCB_3D_view_up.png
You can use R34 as a pulp-up for opto-interrupter photo-transistor.

This is how signal from the sensor should look at the oscilloscope when motor is running:
Signal from oscilloscope
Zero mark "pulse" is shown at the center of this image.

Signal from the sensor goes to comparator integrated to the MCU. Comparator reference voltage is 1.2V. See: "encoder_processing.c" and "config.h":
#define ENCODER_COMP_NEG_SRC COMP_InvertingInput_1_2VREFINT

Simulating encoder with Arduino

If you are having problems with your encoder, you can try to simulate it with Arduino compatible board. Use this sketch:

#include <Arduino.h>

#define SEC_TO_US               1000000

//Rotations per second
#define SIM_ENC_SPEED           15

// Number of slits in encoder, including manually closed zero slit
#define ENC_TOTAL_PAIRS         65

//Open-closed pair duration (~1000 for 65 pairs and 15PRS)
#define ENC_PAIR_DURATION_US    (SEC_TO_US / SIM_ENC_SPEED / ENC_TOTAL_PAIRS)

//MCU pin
#define SIM_PIN                 23


void encoder_closed() 
{
  //Closed slit -> no light -> no current -> pull-up to 1
  digitalWrite(SIM_PIN, 1);
}

void encoder_opened() 
{
  digitalWrite(SIM_PIN, 0);
}

void encoder_simulate_pair() 
{
  encoder_opened();
  delayMicroseconds(ENC_PAIR_DURATION_US / 2);
  encoder_closed();
  delayMicroseconds(ENC_PAIR_DURATION_US / 2);
}

//Simulate manually closed zero pair
void encoder_simulate_closed() 
{
  //encoder_opened(); //This slit is manally closed
  encoder_closed();
  delayMicroseconds(ENC_PAIR_DURATION_US / 2);
  encoder_closed();
  delayMicroseconds(ENC_PAIR_DURATION_US / 2);
}


void setup() 
{
  pinMode(SIM_PIN, OUTPUT);
}

void loop() 
{
  encoder_simulate_closed();//zero
  for (int i = 0; i < (ENC_TOTAL_PAIRS - 1); i++)
  {
    encoder_simulate_pair();
  }
}

You need to set number of slits (holes) of your encoder - ENC_TOTAL_PAIRS .
You need to set suitable GPIO pin - SIM_PIN .
You can use any Arduino compatible board - I tested this sketch at ESP32 board with Arduino FW.
Just disconnect motor and encoder from your LIDAR board and connect GND and SIM_PIN of the Arduino to the LIDAR encoder input P6. This input not 5V tolerant. Use variable potentiometer to make 3.3V output if our Arduino has 5V GPIO!

Add patch to you "scanning_fw" Firmware
In file "dist_measurement.c" in function dist_measurement_recalculate_ref_distance()
add line corr_ref_dist_bins = 50.0f; before the last
dist_meas_zero_offset_bin = corr_ref_dist_bins - true_dist_bin; line.
This is needed to disable Reference Plate distance corrections. You will not get accurate distance measurements in a such way, but you can test that FW is detecting encoder pulses and laser is controlled OK.

Resulting image: image Diameter of the circle is depending on distance to the object.