4 апреля 2016 в 08:36

Реверс-инжиниринг лазерного датчика расстояния

image
Однажды ко мне попал нерабочий лазерный датчик расстояния Keyence LK-G407. Мало того, что он был нерабочий, так его еще и нельзя было использовать без специального управляющего блока. Но ведь у датчика такие интересные характеристики: измерение расстояния с точностью до единиц микрон, и скорость работы — 50 килоизмерений/с. Так что, чтобы запустить его, придется заметно поковыряться в самом датчике, заодно и ценный опыт получить.

Что же находится внутри датчика?


Оптическая часть датчика показана на фотографии ниже:

Слева на фотографии — лазерный модуль, за ним — светочувтвительная линейка, справа — объектив и зеркало.
Из конструкции становится понятно, что этот датчик можно отнести к классу лазерных дальномеров с триангуляционным методом измерения расстояния. Принцип работы таких дальномеров хорошо описан здесь. В принципе, он довольно прост — при изменении расстояния до объекта, на который светит лазер, меняется угол между объективом дальномера и пятном лазера. Если в фокальной плоскости объектива установить светочувствительную линейку или матрицу, то можно определить этот угол по положению максимума выходного сигнала. Зная угол и расстояние между лазером и объективом, можно определить расстояние до объекта.
Достоинствами такого метода является очень большая точность на небольших расстояниях — при определенных условиях она может быть лучше 0.1 мкм!
Так же не проблема измерять расстояние с большой скоростью — нужно только использовать высокоскоростную светочувствительную линейку.
Схемотехника такого дальномера тоже достаточная простая — за счет того, что в устройстве нет больших частот, а первичное усиление сигнала идет в самой линейке.
Но есть и недостаток — точность метода резко падает при увеличении расстояния.
В этом датчике использован длиннофокусный объектив (фокусное расстояние около 150 мм), поэтому, для уменьшения габаритов датчика в его состав входит зеркало.

А теперь стоит перейти к электронике датчика.
Вот как выглядит вторая часть датчика:

И сама плата:

И с другой стороны:

Печатная плата вроде бы четырехслойная — большая часть сигнальных проводников находятся на внешних слоях, силовые линии — на внутренних.
Как я уже упоминал, управляющего блока к датчику не было, а без него он не начинал работать. Понятно, что схем на датчик тоже не было, не была даже известна распиновка кабеля и напряжение питания датчика. Вывод — нужно делать реверс-инжиниринг схемы.
В результате получилась вот такая схема:

Конечно, я не стал рисовать всю схему датчика, и разобрался только в той части, что связана с FPGA. Номера элементов на схеме не соответствуют номерам на плате.
Таким образом, структурная схема датчика:
image
Из нее понятно, что работой всего датчика управляют две микросхемы — FPGA Xilinx Spartan-3A и некая заказная микросхема. Однако, мне очень повезло — из схемы видно, что заказная микросхема связана только с FPGA. Таким образом, FPGA сама способна управлять всеми сигналами в датчике.

Ключевой элемент всей конструкции — светочувствительная линейка. Эта линейка — явно заказная. Под микроскопом на одном из ее краев видна надпись:
25-512
LI004-02
Я предположил, что 512 — число пикселей линейки, а 25 — ширина пикселя в микронах. Как выяснилось позже, я оказался прав.
Сзади к линейке припаяна небольшая плата:

На ней расположен операционный усилитель, увеличивающий сигнал с линейки в 2 раза и несколько резисторов и конденсаторов. Эта плата подключается к разъему P1. Как видно из схемы, к линейке идут всего 3 сигнальных линии. Одна из них — явно аналоговый сигнал с ее выхода (он передается по отдельному коаксиальному проводу). Оставшиеся две линии — цифровые, и используются для управления линейкой. При анализе схемы мне опять повезло — при подаче напряжения на схему на одной из этих линий (4) появляется частота 10 МГц. Сразу стало понятно, что эта линия отвечает за тактирование линейки. Очевидно, что все управление линейкой идет по оставшейся линии (3). Я подключил линейку к микроконтроллеру STM32F4, и начал подавать на линии (3) и (4) различные сигналы. Как оказалось, работает линейка довольно просто — пока на линии (3) присутствует высокий уровень, идет экспозиция — линейка принимает свет. После установки на линии (3) низкого уровня нужно подать на линейку 14 тактовых импульсов, после чего на последующие 512 тактовых импульсов она будет выдавать аналоговый сигнал. Линейка работает от напряжения 5В, а FPGA — от 3.3В, и поэтому для согласования уровней используется микросхема DD2.

Аналоговый сигнал с линейки передается через ФНЧ на повторитель, собранный на микросхеме DA1. Далее сигнал подается на PGA — усилитель с программируемым усилением AD8369. Максимальное усиление этой микросхемы — 40 дБ, и его можно регулировать программно, устанавливая нужной код на ее входах BIT0-3. Эта микросхема предназначена для усиления дифференциального сигнала, и выход у нее тоже дифференциальный, так что далее оба ее выхода заведены на операционный усилитель DA4, усиливающий сигнал в 2 раза, и формирующий одиночный сигнал.
Далее аналоговый сигнал подается на вход 10-битного АЦП AD9200. Эта микросхема уже была знакома мне по SDR приемнику. В данном случае она подключена так, что диапазон оцифровываемых ею напряжений — (0,5-2,5) В. Оцифрованный сигнал с выхода АЦП передается на FPGA.
Стоит обратить внимание на вход CLAMP этого АЦП. Этот вход также управляется FPGA. Он предназначен для приведения постоянной составляющей входного сигнала к определенному уровню.
Вот схема входного каскада АЦП из даташита:

При подаче высокого уровня на вход CLAMP на выходе усилителя и на AIN появляется напряжение, равное напряжению на входе «CLAMP IN».
В таком случае конденсатор CIN будет заряжаться до тех пор, пока напряжение на нем не станет равным (Uвх — Uclamp_in). После этого на входе CLAMP устанавливают низкий уровень, и усилитель перестает как-либо влиять на работу АЦП. В данном датчике вход «CLAMP IN» подключен к нижнему опорному напряжению АЦП +0,5В. Таким образом, если на выходе DA4 будет присутствовать некая постоянная составляющая, то за счет использования функции CLAMP можно устранить ее влияние на результат работы АЦП.
После того, как были написаны первые тестовые конфигурации для FPGA, оказалось, что управлять сигналом CLAMP действительно нужно, иначе сигнал с АЦП имеет очень большую постоянную составляющую. В своей реализации я просто подавал на него 1 в то время, пока не идет захват данных при помощи АЦП.

Из схемы видно, что в ней используется большое число питающих напряжений. Я не стал рисовать схемы различных источников питания, входящих в датчик и различные сглаживающие конденсаторы. Как оказалось, выводы питания (они выведены на отдельный разъем с 2 выводами) соединяются с DC-DC преобразователем TPS62050. Максимальное напряжение для него — 10В, от 6В электроника еще не запускалась, так что я решил, что рабочее напряжение датчика — 8В.

Лазерный диод, использованный в этом модуле, управляется электроникой, установленной на отдельной платке:

Схему этой платы я рисовать не стал. К главной плате она подключается через разъем P3. Как видно, управление лазером идет по двум линиям. Одна из них (3) подключена к FPGA через инвертор, и отвечает за включение лазера — он включается низким уровнем на выходе FPGA. Другая линия (4) нужна для регулирования мощности лазера. Это аналоговая линия, и для изменения напряжения на ней с состав схемы входит ЦАП, собранный на микросхемах DA5-7 (я так и не понял, почему разработчики нагородили такую запутанную схему, а не взяли готовую микросхему ЦАП).

Как известно, большинство FPGA не содержат энергонезависимой памяти, соответственно, конфигурация FPGA должна храниться во внешней микросхеме. В данном случае это DD3 XCF01 — специализированная микросхема Flash-памяти. При включении FPGA автоматически считывает конфигурацию из нее в свою память. Сама FPGA и XCF01 соединены в JTAG-цепь, которая подключена к разъему P2. В результате через этот разъем можно внутрисхемно программировать XCF01, конфигурировать FPGA и вести отладку.

Таким образом я разобрался в принципе работы электроники датчика, и у меня появилась часть его схемы. Теперь можно приступать к экспериментам, т.е. программированию ПЛИС. Стоит заметить, что до этого я не имел дела с ПЛИС производства Xilinx. Нужного программатора у меня тоже не было, так что пришлось сделать его самому, путем объединения нескольких OpenSource проектов.
Программатор нормально заработал, и мне удалось запустить на ПЛИС простые проекты — простое переключение выводов ПЛИС. Однако в дальнейшем мне нужна была связь с компьютером. С интерфейсом LVDS связываться я не захотел (у порта, на который заведены линии LVDS напряжение питания 2.5В), так что я просто перерезал две дорожки, соединяющие ПЛИС и ASIC. На плате был разъем, судя по всему предназначенный для настройки или тестирования ASIC, его я использовать не мог, поэтому также перерезал две дорожки, идущие к нему, и соединил выводы разъема с выводами ПЛИС. Теперь к этому разъему можно подключать переходник USB-UART.
Вид платы после доработки:


После этого я написал простую программу для проверки работы UART. Она заработала — компьютер правильно принимал одиночные байты, передаваемые по UART c ПЛИС. Следующий этап — передача данных с светочувствительной линейки на компьютер. Я использовал такую структурную схему программы FPGA:

Вид схемы в ISE:

Top-level проекта нарисован в схемном редакторе, а все входящие в него модули написаны на Veriolg. Принцип работы проекта достаточно прост — данные с линейки, оцифрованные АЦП, захватываются ПЛИС и сохраняются в ОЗУ. После того, как все 512 элементов сигнала захвачены, они передаются по UART на компьютер. После того, как все данные переданы, цикл повторяется. Модуль «sensor_reader» в данном проекте управляет линейкой, лазером и сигналом CLAMP. Управление реализовано простейшим образом — всеми сигналами управляет счетчик тактовых импульсов. Модуль «tx_controller» включает в себя модуль передатчика UART. Он предназначен для передачи данных, которые модуль получает из внешней памяти.
В процессе работы уровень полезного сигнала на линейке может сильно меняться — из-за изменения расстояния до объекта и изменения его коэффициента отражения. При слишком маленьком сигнале измерения становятся невозможными, а при слишком большом сильно падает точность измерения. Из-за этого усиление аналогового сигнала нужно регулировать. Изначально проект в проект входил модуль UART-приемника, который позволял вручную изменять усиление, позже я его убрал и сделал автоматическую регулировку усиления — AGC.
Она включает в себя модуль поиска максимума сигнала («max_finder») и сам модуль AGC («agc_module»). Этот модуль тоже достаточно простой — если уровень сигнала меньше 170, то усиление увеличивается, если больше 250 — уменьшается.
Все модули, линейка и АЦП тактируются от частоты 10 МГц. Время экспозиции я сделал равным 5 мкс. Таким образом, весь процесс экспозиции и захват сигнала в ПЛИС занимают (5+51) мкс. Время передачи данных намного больше — при тактовой частоте 500000 бит/сек передача 512 байт занимает 10 мс, что дает 100 измерений в секунду.

Для просмотра переданных данных в реальном времени была написана простая программа на C#:

При перемещении объекта вдоль лазерного луча положение максимума пика изменяется. Простое вычисление положения максимума дает низкую точность измерения, поскольку линейка содержит всего 512 пикселей. Поэтому для более точного измерения положения максимума сигнала приходится использовать алгоритмы поиска центра тяжести, которые позволяют определить координаты максимума сигнала с субпиксельной точностью.
Я использовал такую формулу для поиска центра тяжести пика:

где n — общее число пикселей, Int[i] — интенсивность i пикселя.
Для того, чтобы различный шум, присутствующий в сигнале, не ухудшал точность работы, полезно обрабатывать только выборки, превышающие определенный порог и находящиеся близко к максимуму пика. Особенно это важно в том случае, когда усиления не хватает, и полезный сигнал не превышает половины шкалы АЦП. Более того, с ростом усиления увеличивается уровень шумов, что ухудшает ситуацию. В вышеупомянутой программе это учтено.
На картинке выше MAX POS — вычисленное по этой формуле значение, MAX POS F — среднее значение последних 50 измерений.
Как я уже говорил, получившаяся частота измерений — 100 Гц, и она ограничена скоростью передачи данных по UART. Однако не обязательно обрабатывать сигнал на компьютере, это можно сделать и на ПЛИС, за счет чего можно многократно повысить скорость измерений.

В результате была разработана программа для ПЛИС с такой структурной схемой:

Вид схемы в ISE:

Как видно, часть модулей взяты из предыдущего проекта.
В данном случае вычислением положения центра тяжести (центроида) сигнала занимается модуль «centroid_finder». Для того, чтобы ограничить область анализа данных, в модуль передается грубое значение положение максимума и его амплитуда.
Так как эти величины можно вычислить, только проанализировав весь сигнал (то есть они появляются с задержкой в 512 тактовых импульсов), то получается, что оцифрованные данные нужно подавать на вход «centroid_finder» с этой же задержкой. Для того, чтобы задержать данные на 512 тактов, используется буфер FIFO. Для первоначального заполнения FIFO используется модуль «fifo_logic» — он запрещает чтение из FIFO, если он не заполнен.
Модуль «tx_controller_3bytes» последовательно передает 3 байта, первый из них — нулевой, оставшиеся два содержат вычисленное положение центра тяжести. На скорости 50000 bit/s передача 3 байт занимает 60 мкс -практически столько же, как и захват сигнала. Нулевой байт используется для синхронизации данных — после него всегда идет старший байт.
Передача данных по UART и захват данных запускаются одновременно сигналом «start_capture». Этот сигнал формируется, если одновременно закончилась предыдущая передача и вычислено новое положение центра тяжести. В результате время измерения расстояния и передачи данных оказывается близким к 60 мкс, что дает скорость измерения координат — 16,6 KSPS. Это меньше, чем заявлено у производителя датчика. Там указывается минимальное время измерения — 20 мкс (это соответствует 50 KSPS), хотя непонятно как получено это время, ведь даже при максимальной скорости работы AD9200 — 20 MSPS время захвата сигнала с 512 пикселей будет — 25,6 мкс. А это ведь еще без учета времени экспозиции.

Как я уже говорил ранее, этот датчик не работал. Насколько мне известно, проблема была в том, что он был установлен на сильно вибрирующей промышленной установке, и из-за вибрации лазер датчика вышел из строя (датчик перестал реагировать на темные поверхности).
К сожалению, на родном диоде маркировки не было. Я пробовал заменить лазерный диод в лазерном модуле на купленный 5 мВт лазерный диод, но через некоторое время его интенсивность упала. Скорее всего, электроника лазерного модуля была рассчитана на более мощный диод (хоть и работающий в импульсном режиме, за счет чего средний уровень излучения получается достаточно низким).
Для того, чтобы хоть как-то запустить датчик, я сделал свой драйвер лазерного диода, работающий в режиме постоянного излучения:
image
Родной лазерный диод датчика был завальцован в металлический корпус лазерного модуля, так что новый лазерный диод пришлось просто приклеить к модулю. При этом, габаритные размеры использованного диода несколько отличались от размеров родного диода, из за чего мне так и не удалось качественно сфокусировать лазерный модуль.
Так выглядит собранный датчик:

Для того, чтобы при помощи датчика можно было измерять расстояние, нужно произвести его калибровку, т.е. определить закон, связывающий результат, возвращаемый датчиком, и реальное расстояние. Сам процесс калибровки представляет собой серию измерений, в результате которых формируется набор расстояний от датчика до некоторого объекта, и соответствующих им результатов.
Расстояние между датчиком и объектом нужно измерять очень точно. Для проведения калибровки я сделал стенд, включающий в себя линейный энкодер и сам лазерный датчик:


Расстояние измеряется до пластинки, закрепленной на торце энкодера.
После того, как все данные собраны, можно провести регрессионный анализ в Mathcad.
В результате у меня получилось такое выражение:
value_mm = 70.0 / Tan(-0.000277757*max_pos + 0.28355) — 366.23554
Очевидно, что значения констант в выражении от положения деталей датчика. Малейший сдвиг деталей приведет к тому, что вычисленное значение расстояния будет неверным. Поэтому все детали должны быть очень прочно закреплены.

На видео ниже показано, как можно обрабатывать данные с датчика:

В первой части видео показано, как выглядит сигнал со светочувствительной линейки. Хорошо видно, что на если объект темный, то амплитуда не изменяется (за счет работы АРУ), но уровень шумов сильно возрастает.
Во второй части видео программа принимает от датчика положение центра тяжести, и пересчитывает его в расстояние. Также в программу передается значение расстояния до объекта, полученное от энкодера. Под расстоянием энкодера выводится разность между этими расстояниями. Можно видеть, что в при движении разность становится больше 1мм (это связано с задержками при передаче расстояний и их отображении), но по время остановок при любом расстоянии разность не превышает 0.03 мм.

Для того, чтобы полученные с датчика данные было проще анализировать, я написал программу, сохраняющую данные, принятые от датчика в формат wav. Такие файлы можно открывать в звуковых редакторах, и применять к ним различные фильтры.
Вот например, как выглядит сигнал с датчика, который был направлен на стенку трансформаторного блока питания:

Видно, как при включении блок питания начал вибрировать.
Я пробовал направлять датчик на диффузор динамика, на котором воспроизводится музыка — и после обработки в звуковом редакторе ее действительно было слышно.

Таим образом, мне удалось дать нерабочему датчику новую жизнь (он может понадобится мне в будущих проектах), и заодно получить опыт работы с ПЛИС Xilinx.

Проекты для FPGA
@iliasam
карма
140,0
рейтинг 89,6
Программист микроконтроллеров
Похожие публикации
Самое читаемое Разработка

Комментарии (22)

  • +6
    Получился лазерный микрофон как в джеймсобондах всяких ) круто
  • 0
    Кстати, в роботах пылесосах Neato лазерный дальномер работает по такому же принципу. Только он там еще и вращается, измеряя вокруг себя расстояния на 360гр.
    Насчет такой потрясающей точности, что видно вибрацию трансформатора. Мне кажется, тут дело в эффекте лазерных спеклов. Даже малейшее движение изменяет интерференционную картину лазерного пятна. Это и детектируется дальномером. Но такие измерения имеют шумовую природу, т.е. по ним нельзя сказать, на сколько микрон сдвинулся объект в абсолютных расстояниях, но если преобразовать их в звук, то получим колебания объекта.
    • 0
      Вы описываете Лидар.
      • 0
        Вы не правы. Я описываю триангуляционный лазерный дальномер. Лидар измеряет время движения света.
    • 0
      Кстати, в роботах пылесосах Neato лазерный дальномер работает по такому же принципу. Только он там еще и вращается, измеряя вокруг себя расстояния на 360гр.

      Я даже делал аналогичный дальномер.
      Я все же думаю, что датчик измеряет расстояние, используя законы геометрической оптики, т.е. он не использует спеклы.
      • 0
        Он и не "использует" спеклы, они возникают из-за самой природы источника света и здорово, кстати, в подобных датчиках мешают. Вплоть до необходимости введения в оптический путь специальной вибрирующей пластинки которая подавляет интерференционную картину (точнее "размазывает" ее, смешивая много разных картин)
        • +1
          Я имел в виду, что конкретно этот датчик, скорее всего, все же "честно" использует законы геометрической оптики при измерении вибрации, и не реагирует на спеклы (просто чувствительности линейки не хватает, чтобы их замечать).
          Но с тем, что они могут мешать, я полностью согласен, и идея с вибрирующей пластинкой действительно интересная.
          • 0
            Датчик реагирует на максимум светового пятна, используя субпиксельную точность. Спеклы смещают максимум пятна туда-сюда. Немного, но это позволяет увидеть те самые микронные перемещения.
            Просто измерьте амплитуду вибраций трансформатора, которую выдает вам датчик и сравните её с реальным смещением. Уверен, она будет намного больше реальной. Это также можно проверить, направив луч на торец микрометра.
            Также можно соорудить вместо лазера светодиодный прожектор, сфокусировав его свет в точку, размером с луч лазера. Спеклов не будет. И той самой гигантской точности тоже не будет, хотя в целом триангуляционный принцип остался тем же.
  • +1
    очень интересная статья. по поводу импульсного режима — имхо он там сделан для синхронного детектирования, что очень сильно повышает соотношение сигнал/шум. сам не использовал, но если верно понимаю — считываете линейку с выключенным лазером, потом со включенным. из второго результата вычитаете первый, получаете чистый сигнал.
    • 0
      Изначально я тоже думал, что в родная прошивка так и делает, но как я уже заметил в статье, скорость АЦП, допускаемая по даташиту, не позволяет реализовать скорость измерения 50 KSPS, которые заявляет производитель.
      А в случае использования синхронного детектирования нужно либо в 2 раза увеличивать тактовую частоту линейки и АЦП, или уменьшать число измерений в секунду, так что в родной прошивке при указанной скорости реализовать синхронное детектирование проблематично (на более низких скоростях измерения — реально).
      Так что импульсный режим там скорее всего — просто для увеличения скорости измерений (увеличивая мощность лазера, можно уменьшить время экспозиции).
  • 0
    Каков теоретический/практический предел максимального расстояния, которое можно измерить этим датчиком? Как я понимаю, все зависит от используемой оптики и согласования оптики с лазерным диодом?
    Можно ли использовать этот девайс, чтобы почувствовать себя героем шпионского фильма, или отражающей способности оконного стекла недостаточно, чтобы воспринять его колебания и преобразовать их в звук? ;)
    • 0
      Действительно, все характеристики таких дальномеров зависят от базового расстояния (расстояния между объективом и лазером), фокусного расстояния объектива, и параметров светочувствительной линейки.
      Но я сильно сомневаюсь, что триангуляционный дальномер в таком виде можно использовать для "снятия" звука с окон. Там либо используется интерференционные методы (с сопутствующими ими сложностями) либо тот же триангуляционный принцип, но базовое расстояние делается очень большим (десятки метров, то есть лазер и приемник света разносятся по разным квартирам).
      • 0
        Ну да, пожалуй интерференционный метод лучше подойдет для "снятия" звука с окон — типа интерферометра Майкельсона. Точность измерения перемещений (но не абсолютного расстояния) — доли длины волны, столько даже не нужно.
        До Луны расстояние, кажется, тоже измеряли лазером, но уже импульсным методом.
  • 0
    Спасибо за статью! Кстати, микросхема ПЛИС называется Spartan, поправьте пожалуйста.
    • 0
      Спасибо, поправил опечатку.
  • 0
    Крутое исследование, но статья не набрала и 50 плюсов и просмотров маловато. Что то здесь не так.
    • 0
      Еще не вечер — вчера только вышла. Но работа колоссальная и автор профи. Такой дальномер с нуля разработать было бы пожалуй проще.
      • +2
        Такой дальномер с нуля разработать было бы пожалуй проще.

        Я уверен, что в реальности логика работы дальномера значительно сложнее, чем то, что я описал в статье. Разработчики не зря использовали ASIC, в ней, скорее всего, находится некий процессор, обрабатывающий данные с линейки. Алгоритмы поиска центра тяжести там посложнее, чем у меня в статье — в каталоге этих дальномеров явно упоминались различные программные методы подавления переотражений, работы со стеклянными пластинками, и прочее. Перевод в расстояние там, скорее всего, так же производится внутри ASIC. И ASIC также одновременно управляет мощностью лазера, временем импульса, и коэффициентом усиления.
        Да и до заявленных производителем характеристик мне дойти не так и не удалось.
  • 0
    Я так и не понял какое разрешение получилось? 10мкм?
    • 0
      Если судить по энкодеру, то абсолютная погрешность вышла 0.03мм, но я не очень то уверен в самом энкодере. Калибровка тоже была проведена довольно грубо, так что ошибка могла возникать на этапе вычисления расстояния. Разрешение самого датчика получилось выше, около +-0.01мм (на видео видно, что последний знак расстояния «дрожит»).
      Между прочим, производитель заявляет для датчика точность 2 мкм, но в сноске мелким шрифтом пишет — при усреднении по 4096 точкам.
      • 0
        А динамический диапазон?
        • 0
          Тут я могу только приблизительно сказать. Усиление AD8369 меняется на 45 дБ, если сигнал на АЦП будет меньше 1/3 шкалы, то точность сильно падает, так что 45+20log(3) = 54 дБ.

Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.