Вывод Изображения С Камеры Ov7670 На Vga-Монитор С Помощью Fpga



Предисловие Прочитав множество увлекательных статей об интересных разработках для ПЛИС, таких как Тетрис , радиопередатчик И другой , я тоже загорелась идеей сделать что-нибудь для души.

Для этого я купил камеру.

OV7670 и совет по развитию ДЕ-1 от Terasic с чипом Cyclone II от Altera. Я поставил следующую задачу: вывести изображение с камеры на VGA-монитор.

Чтобы оправдать использование FPGA, я собираюсь сделать это на максимальной скорости камеры.

Должен отметить, что легче разобраться в этой работе помогут знания в области электроники: знание интерфейсов VGA и I2C, понимание работы памяти SDRAM и т.д.



Введение

Данная статья не исследование, это скорее отчет о проделанной работе, в котором я постарался показать основную идею и наиболее интересные и сложные на мой взгляд места.

По сложности этот проект близок к «мигни светодиодом», но имеет огромный потенциал для расширения.

В проекте сознательно не используются готовые IP-ядра и стандартные интерфейсы, поскольку изначально проект планировался как рукописный.

Это также поможет вам немного выиграть с точки зрения ресурсов и производительности.

Надеюсь, эта статья будет интересна читателям, а желание увидеть себя на экране через «самодельную камеру» побудит их к изучению ПЛИС.

Отказ от ответственности В некоторых местах проекта архитектура и синтаксис кода могут быть неоптимальными.

Это связано с тем, что над проектом я работал в свободное время, и иногда между подходами были перерывы в несколько месяцев: старые мысли забывались, но появлялись новые.

Например, центральный автомат был сильно упрощен: от исходного монстра осталось только название «глобальный».

Перед публикацией я провел рефакторинг кода, но если будут обнаружены какие-то недостатки, просьба указать на них в комментариях.



Проблемы и решения

Чтобы понять, что нас ждет, давайте взглянем на «железо» и оценим, с какими проблемами мы столкнемся.

Камера OV7670. Камера способна формировать изображения разрешением 640x480 пикселей с частотой 30 кадров в секунду в формате RGB565. Для работы камеры необходимо обеспечить ее тактовую частоту 24 МГц.

Камера передает данные пользователю по 8-битной шине, а также стробам синхронизации VSYNC и HSYNC. Временные диаграммы работы камеры представлены на рисунке 1.

Вывод изображения с камеры OV7670 на VGA-монитор с помощью FPGA

Рисунок 1 Информация о цвете передается за 2 такта, побайтно.

Упаковка данных в байты показана на рисунке 2.

Вывод изображения с камеры OV7670 на VGA-монитор с помощью FPGA

Рис.

2 VGA-монитор.

VGA — аналоговый сигнал, поэтому послать на его вход цифровые данные не получится.

Но на борту DE-1 есть 4-битные ЦАП, и мы используем их для преобразования цифрового сигнала в аналоговый.

VGA с разрешением 640х480 имеет частоту обновления 60 кадров в секунду.

Необходимо задать данные на ЦАП с частотой 25,175 МГц, а также сформировать стробы синхронизации VSYNC и HSYNC. Тайминги для VGA можно посмотреть Здесь .

Становится понятно, что частота приема данных с камеры и частота вывода данных на монитор различны, что исключает возможность прямого подключения.

Выходом из этой ситуации является использование кадровый буфер .

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

Для хранения одного кадра требуется 640*480*16 = 4,915*10^6 бит, что намного больше, чем встроенной памяти, имеющейся на борту Cyclone II. Поэтому мы будем использовать для хранения кадров SDRAM-память , расположенный отдельной микросхемой на плате DE-1. Это позволит нам организовать кадровый буфер для решения технической задачи и даст возможность попрактиковаться в написании контроллера SDRAM. Следующая задача вытекает из решения предыдущей.

При использовании памяти SDRAM в нашем проекте необходимо учитывать два важных момента: во-первых, память работает на высокой для нашей конструкции частоте 120 МГц, и мы сталкиваемся с новой проблемой — переносом данных из тактовой области камеры в SDRAM. часовой домен; во-вторых, для достижения максимальной производительности следует писать в SDRAM целыми транзакциями, которые называются пакетными.

Лучшим способом решения этих проблем является FIFO, организованный во встроенной памяти FPGA. Основная идея такова: камера заполняет FIFO на низкой частоте, после чего контроллер SDRAM считывает данные на высокой частоте и сразу записывает их в память одной транзакцией.

Вывод данных на монитор организован по такому же принципу.

Данные из SDRAM записываются в FIFO, а затем извлекаются на частоте 25 МГц для подачи на ЦАП.

После того как FIFO опустеет, операция повторяется.

Самая маленькая проблема в том, что настройки камеры «из коробки» нас не устраивают, и нам необходимо их изменить.

Самый важный момент — камера выводит данные в формате YUV422, а вам нужно поменять его на RGB444. Чтобы получить доступ к внутренним регистрам OV7670, вам потребуется описать модуль передатчика I2C. Теперь мы можем сказать, какие модули нам придется реализовать и какие задачи они будут решать.

  • cam_wrp – модуль получает данные от камеры и записывает их во входной FIFO;
  • hvsync – модуль формирует стробы для VGA, принимает данные из SDRAM, записывает их во входной FIFO и через строб отправляет в ЦАП;
  • sdram_cntr – контроллер SDRAM;
  • FSM_global – автоматическое управление;
  • camera_configure – модуль настройки и управления камерой.

На рисунке 3 представлена функциональная схема конструкции.



Вывод изображения с камеры OV7670 на VGA-монитор с помощью FPGA

Рис.

3 Рассмотрим подробнее каждый из модулей.



модуль cam_wrp

Один из самых простых модулей.

Его задача, в момент активности строба hsync камеры, — последовательно получить два байта, сформировать их в одно двухбайтовое слово и записать его в FIFO. По сигналу контроллера SDRAM передать ему все содержимое FIFO. Чтобы «упаковать» 2 последовательных байта в одно слово, мы используем сигнал wr_fifo, который инвертируем по частям (делим частоту на 2).

Когда этот сигнал имеет логическую 1, мы записываем данные в младший байт, когда логический 0 — в старший байт. Мы также используем wr_fifo в качестве сигнала записи в FIFO. Помимо шины данных, из FIFO выводится шина, на которой задается количество записываемых в нее данных.

Эта шина подключена к управляющей машине.

На рисунке 4 показана временная диаграмма «упаковки» байтов в двухбайтовые слова.



Вывод изображения с камеры OV7670 на VGA-монитор с помощью FPGA

Рис.

4

Модуль FSM_global

У модуля очень претенциозное название; по сути, это простая машина, имеющая всего 4 состояния, но выполняющая очень важную функцию.

Контролируя сигнал готовности sd_ready SDRAM контроллера, заполненность входного и выходного FIFO, машина выдает SDRAM-команды контроллеру для забора данных со входного или записи в выходной FIFO. Чтение и запись происходят незадолго до того, как FIFO полностью заполнится или опустеет. Необходимо правильно выбрать уровень заполнения FIFO, чтобы операции с FIFO на высокой частоте не заканчивались раньше, чем на низкой частоте – это гарантированно приведет к ошибкам.

В части, посвященной контроллеру SDRAM, я приведу рисунок, иллюстрирующий эту особенность.



Модуль SDRAM_contr

Контроллеров SDRAM уже написано немало, мне не хотелось снова изобретать велосипед, поэтому я решил изобретать велосипед на гусеницах.

А именно, контроллер SDRAM, адаптированный под этот конкретный проект. Это упростит управление и немного ускорит работу.

Граф перехода машины для полноценного контроллера SDRAM представлен на рисунке 5.

Вывод изображения с камеры OV7670 на VGA-монитор с помощью FPGA

Рис.

5 Давайте подумаем, что мы можем из него исключить.

Во-первых, мы не будем обновлять данные.

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

Данные не успеют испортиться.

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

В-третьих, не нужно думать об адресе, мы просто будем его инкрементировать после каждого пакета и сбрасывать в ноль в конце каждого кадра.

Получившийся граф переходов показан на рисунке 6.

Вывод изображения с камеры OV7670 на VGA-монитор с помощью FPGA

Рис.

6 Контроллер запускается в состоянии ожидания.

Перед началом нормальной работы необходимо инициализировать микросхему памяти (состояние машины s0_MRS), после чего устанавливается флаг mode_flag, контроллер переходит в состояние ожидания, и мы можем записывать и читать данные.

Для этого от модуля fsm_global поступает команда на начало чтения или записи, мы открываем нужную колонку в выбранном банке (состояние s0_ACT), после чего должно произойти чтение или запись (состояния s0_WRIT, s0_READ).

К сожалению, одним пакетом нам не обойтись, глубина столбца в нашей микросхеме памяти составляет всего 256 16-битных слов, а нам нужно записать вектор длиной 640. Придется писать в 3 пакета.

, два по 256 и один по 128. Видно, что половина третьей Строка остаётся пустой, то есть ресурсы мы используем нерационально, но так как их недостатка у нас нет, я решил не усложнять машину и прийти смириться с этим.

Что касается адресов, то они имеют отдельные регистры для чтения и записи, которые инкрементируются перед каждым перебором.

Таким образом, чтобы записать вектор длиной 640, мы проходим по 640*4=1440 адресам.

Строб вертикальной синхронизации камеры или адреса VGA сбрасываются на ноль для записи и чтения соответственно.

Мы используем двойную буферизацию: пишем в один буфер из другого и читаем.

Для упрощения я поместил один буфер в банк 0, а второй в банк 1 микросхемы SDRAM. Банки чтения и записи меняются местами после окончания приема кадра с камеры.

На рис.

7 показаны временные диаграммы записи одного вектора.

Видно, что запись разделена на 3 части: после каждой части адрес инкрементируется, вся передача происходит под стробом cur_wr. Для чтения схема аналогична.



Вывод изображения с камеры OV7670 на VGA-монитор с помощью FPGA

Рис.

7 На рисунке 8 показано, как данные с камеры записываются в SDRAM в сравнении со временем, необходимым для заполнения FIFO. Обратите внимание, что мы начинаем запись в SDRAM, не дожидаясь полного заполнения FIFO.

Вывод изображения с камеры OV7670 на VGA-монитор с помощью FPGA

Рис.

8

модуль hvsync

Это один из двух модулей в этом проекте, написанных не мной.

Я уже однажды реализовал подобный модуль; Мне не было интересно повторяться, поэтому я воспользовался отличным модулем, написанным авторами сайта.

marsohod.org .

В этом модуле нет ничего лишнего, он параметризуется и легко настраивается под любое разрешение экрана.

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

От FIFO идет шина, по которой задается объем записываемых в него данных; эта шина подключена к управляющей машине по аналогии со входом FIFO. Выход FIFO подключен к проводам, идущим к ЦАП.



модуль camera_configure

Изначально, вольничая с домашним проектом и не внимательно читая документацию, я хотел запустить камеру с настройками «по умолчанию», но оказалось, что без настроек OV7670 передает информацию в формате не RGB565, а в YUV422. Переписывать ничего не хотелось и я решил, что нужно все сделать с умом и нормально инициализировать камеру.

Так как камера управляется по I2C, пришла в голову идея использовать NIOS. Запустить NIOS с коркой I2C с опенкором с полпинка не удалось, но случайно наткнулся на Verilog модуль инициализации и конкретно для OV7670. Он настолько легко интегрировался в код, что мне не пришлось практически ничего менять, я изменил только одну строчку: вместо RGB565 я активировал режим RGB444, так как на плате установлены 4-битные ЦАП.

На рисунке 9 представлена временная диаграмма программного сброса камеры записью числа 0x80 по адресу 0x12.

Вывод изображения с камеры OV7670 на VGA-монитор с помощью FPGA

Рис.

9

Демонстрация результата

После того, как все модули написаны, соединяем их в топ-модуль, собираем в Quartus и можем протестировать.

Видео демонстрирует результат. Время для съемки выбрал не очень удачное – закат и очень яркое солнце – на слишком яркие солнечные блики камера реагирует неадекватно.

Видно, что движущиеся объекты отображаются корректно, дерганий и шлейфов нет. Именно этого я и добился с помощью ПЛИС, которая позволяет с небольшими затратами обрабатывать все 30 (а возможности камеры больше) кадров в секунду.

Если говорить о четкости изображения, то могу сказать, что текст с листа А4 читается без каких-либо затруднений; к сожалению, фотографии с монитора получаются хуже, чем в реальности.

На рисунке 10 показан фрагмент листа А4 с документацией к камере.



Вывод изображения с камеры OV7670 на VGA-монитор с помощью FPGA

" Представленные видео и фото демонстрируют некоторые недостатки: первый с резкостью, второй с цветом.

Проблему с резкостью на видео я связываю с несовершенной фокусировкой.

Фокусировка на фотоаппарате регулируется механически путем вкручивания или выкручивания объектива, расположенного на резьбе.

Резьба пластиковая и имеет довольно большой люфт; даже небольшое встряхивание может ухудшить резкость.

Проблема с излишней зелено-желтизной белого листа, как мне кажется, связана с проблемой баланса белого: съемка производилась в помещении с освещением, далеким от естественного.

Также на цветовую ситуацию могут влиять настройки камеры.

Я с ним практически не экспериментировал, использовал как магическое число.



Заключение

Поставленная задача — вывод изображения с камеры OV7670 на VGA-монитор в реальном времени — решена.

Если сравнить результат, полученный в этом проекте, с результатом, полученным другими разработчиками, использующими микроконтроллеры или Arduino, то можно увидеть, что они уступают в скорости отображения движущихся объектов.

По трудоемкости данный проект не превосходит аналогичные, выполненные с использованием микроконтроллера.

Человек с базовыми знаниями в области проектирования FPGA может реализовать это за несколько дней.

Проект имеет большой потенциал для расширения; есть возможность фильтровать полученное изображение, распознавать объекты и т.д. Конструкция на микросхеме Cyclone II занимает следующие ресурсы: LE - 745 (4%), бит памяти - 32768 (14%), PLL - 1 (25%).

), Embedded Multiplier — 0 (0%), — таким образом, у разработчиков еще достаточно ресурсов для реализации ваших идей.



Послесловие

Что дальше? В будущем планирую расширить проект, добавив обработку изображений в реальном времени с помощью матричные фильтры .

Я выражаю свою благодарность ишевчук за консультацию по содержанию и оформлению статьи и моей девушке за проверку орфографии.

Плохие дубли Когда я включил его в первый раз, на экране монитора появились загадочные узоры.

Я долго думал, что может быть так.

В результате оказалось, что камера не в фокусе.

После того, как я покрутил линзу на объективе, все стало на свои места.



Вывод изображения с камеры OV7670 на VGA-монитор с помощью FPGA

" alt="изображение"/> При втором включении камера инициализировалась неправильно, в результате чего получилось неожиданное селфи.



Вывод изображения с камеры OV7670 на VGA-монитор с помощью FPGA

" Вы можете скачать исходный архив здесь (Я.

Диск) .

Теги: #FPGA #vga #OV7670 #verilog #FPGA

Вместе с данным постом часто просматривают:

Автор Статьи


Зарегистрирован: 2019-12-10 15:07:06
Баллов опыта: 0
Всего постов на сайте: 0
Всего комментарий на сайте: 0
Dima Manisha

Dima Manisha

Эксперт Wmlog. Профессиональный веб-мастер, SEO-специалист, дизайнер, маркетолог и интернет-предприниматель.