Ov7670 300kp vga модуль камеры для arduino подключение

Обновлено: 01.07.2024

Данная статья не является исследованием, это, скорее, отчет о проделанной работе, в котором я постарался показать основную идею и наиболее интересные и сложные на мой взгляд места. По сложности этот проект следует за «поморгать светодиодом», но имеет огромный потенциал к расширению. В проекте намеренно не используются готовые IP-ядра и стандартные интерфейсы, так как проект изначально планировался как рукописный. Также это поможет немного выиграть по ресурсам и быстродействию. Надеюсь, эта статья будет интересна читателям, а желание увидеть себя на экране через «самодельную камеру» сподвигнет к изучению FPGA.

В некоторых местах проекта архитектура и синтаксис кода могут быть не оптимальны. Это связанно с тем, что реализацией проекта я занимался в свободное время, и между подходами иногда были перерывы в несколько месяцев: старые мысли забывались, но появлялись новые. Так, например, сильно был упрощен центральный автомат: от первоначального монстра осталось лишь название «global». Перед публикацией я провел рефакторинг кода, но если будут обнаружены недостатки, прошу указать на них в комментариях.

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

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



Рис.1

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



Рис.2

VGA монитор. VGA это аналоговый сигнал, поэтому подавать цифровые данные на его вход не получится. Но на борту DE-1 имеются 4-х разрядные ЦАП, их мы и задействуем для преобразования цифрового сигнала в аналоговый. VGA с разрешением 640х480 имеет частоту обновления 60 кадров в секунду. Необходимо выставлять данные на ЦАП с частотой 25.175 МГц, а также формировать стробы синхронизации VSYNC и HSYNC. Тайминги для VGA можно посмотреть здесь.

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

Следующая проблема вытекает из решения предыдущей. При использовании памяти SDRAM в нашем проекте необходимо учитывать два важных момента: во-первых, работает память на высокой для нашего дизайна частоте 120 МГц и перед нами появляется новая проблема — передача данных из клокового домена камеры в клоковый домен SDRAM; во-вторых, для достижения максимального быстродействия писать в SDRAM следует целыми транзакциями, которые называются burst. Для решения этих проблем наилучшим способом подходит FIFO, организованное в on-chip памяти 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

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

Модуль cam_wrp

Один из самых простых модулей. Его задача в момент действия строба hsync камеры принимать последовательно по два байта, формировать из них одно двухбайтовое слово и записывать его в FIFO. По сигналу от SDRAM контроллера передать ему все содержимое FIFO.

Для «упаковки» 2-х последовательных байт в одно слово используем сигнал wr_fifo, который инвертируем по клоку (делим частоту на 2). Когда этот сигнал в логической 1, записываем данные в младший байт, когда в логическом 0 — в старший. Также используем wr_fifo, как сигнал записи в FIFO. Кроме шины данных из FIFO выведена шина, на которую выставляется число записанных в него данных. Эта шина подключена к автомату управления. На рисунке 4 представлена временная диаграмма «упаковки» байт в двухбайтовые слова.



Рис.4

Модуль FSM_global

Модуль имеет весьма пафосное название, на деле это несложный автомат всего на 4 состояния, но выполняет он очень важную функцию. Отслеживая сигнал готовности sd_ready SDRAM контроллера, наполненность входного и выходного FIFO, автомат выдает в команды SDRAM контроллеру забрать данные из входного или записать в выходное FIFO. Чтение и запись происходят несколько раньше, чем FIFO полностью заполнится или опустошится. Необходима правильно выбрать уровень заполненности FIFO, чтобы операции с FIFO на высокой частоте не закончились раньше, чем на низкой, — это гарантированно приведет к ошибкам. В части, посвященной SDRAM контроллеру, я приведу рисунок, иллюстрирующий эту особенность.

Модуль SDRAM_contr

Контроллеров SDRAM написано уже много, изобретать велосипед в очередной раз не хотелось, поэтому я решил изобрести велосипед на гусеничном ходу. А именно, SDRAM контроллер, заточенный под этот конкретный проект. Это упростит управление и чуть-чуть ускорит работу. Граф переходов автомата для полноценного SDRAM контроллера представлен на рисунке 5.



Рис.5

Подумаем, что мы сможем из него исключить.

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

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

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



Рис.6

Стартует контроллер в состоянии idle. Перед началом нормальной работы необходимо провести инициализацию микросхемы памяти (состояние автомата s0_MRS), после чего выставляется флаг mode_flag, контроллер переходит в состояние ожидания, и мы можем записывать и считывать данные. Для этого из модуля fsm_global поступает команда начала чтения или записи, открываем необходимый столбец в выбранном банке (состояние s0_ACT), и далее должно происходить чтение или запись (состояния s0_WRIT, s0_READ). К сожалению, обойтись одним burst не выйдет, глубина столбца в нашем чипе памяти всего 256 16-ти битных слов, а нам необходимо записывать вектор длиной 640. Придется писать за 3 burst, два по 256 и одни на 128. Видно, что половина третьей строки остается пустой, то есть мы нерационально используем ресурсы, но так как недостатка в них у нас нет, я решил не усложнять автомат и смириться с этим.

Что касается адресов, для них выделены разные регистры для чтения и записи, которые инкрементируются перед каждым bust. Таким образом, для записи вектора длиной 640 мы проходим 640*4=1440 адресов. Стробом вертикальной синхронизации камеры или VGA адреса обнуляются для записи и чтения соответственно.

Мы используем двойную буферизацию: в один буфер пишем из другого читаем. Для упрощения один буфер я разместил в банке 0, а второй в банке 1 чипа SDRAM. Банки для чтения и записи меняются местами после окончания приема кадра с камеры. На рисунке 7 представлены временные диаграммы записи одного вектора. Видно, что запись разбита на 3 части: после каждой адрес инкрементируется, вся передача происходит под стробом cur_wr. Для чтения диаграмма аналогична.



Рис.7

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



Рис.8

Модуль hvsync

Модуль camera_configure

Изначально позволив себе вольность домашнего проекта и невнимательно прочитав документацию, я хотел запустить камеру с настройками «по умолчанию», но оказалось, что без настройки OV7670 передает информацию в формате не RGB565, а в YUV422. Переписывать ничего не хотелось, и я решил, что надо делать все по уму и нормально проинициализировать камеру. Так как камера управляется по I2C, в голову пришла идея использовать NIOS. NIOS с коркой I2C с opencore завести с полпинка не удалось, но я случайно наткнулся на Verilogовский модуль инициализации именно для OV7670. Он так легко встроился в код, что не пришлось практически ничего менять, изменил только одну строку: вместо RGB565 активировал режим RGB444, так-как на плате стоят именно 4 разрядные ЦАП. На рисунке 9 представлена временная диаграмма программного сброса камеры записью числа 0х80 по адресу 0х12.



Рис.9

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

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

Мной было выбрано не очень удачное время для съемки — закат и очень яркое солнце, — камера неадекватно реагирует на слишком яркие солнечные блики. Видно, что движущиеся объекты отображаются корректно, дерганий и шлейфов нет. Именно этого я и добивался, используя FPGA, которая позволяет обрабатывать все 30 (а возможности камеры больше) fps малой кровью. Если говорить о четкости изображения, то могу сказать, что текст с листа А4 читается без сложностей, к сожалению, фото с монитора получаются хуже, чем в реальности. На рисунке 10 показан фрагмент листа А4 с документацией на камеру.


"

На представленных видео и фото видны некоторые недостатки: первый с резкостью и второй с цветом.
Проблему с резкостью на видео я связываю с неидеально выставленным фокусом. Фокус настраивается на камере механически, вкручиванием или выкручиванием находящейся на резьбе линзы. Резьба пластиковая и имеет довольно большой люфт, даже от небольшой тряски резкость может ухудшаться.

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

Заключение

Поставленная задача — вывод изображения с камеры OV7670 на VGA монитор в реальном времени, — решена. Если сравнить результат, полученный в данном проекте с результатом, полученным другими разработчиками, использующими микроконтроллеры или Arduino, видно, что они уступают в скорости отображения движущихся объектов. По трудоёмкости данный проект не превосходит аналогичные, выполненные с использованием микроконтроллера. Человек, обладающий начальными знаниями в разработке дизайна FPGA, может реализовать его за несколько дней. Проект имеет большой потенциал к расширению, возможна фильтрация полученного изображения, распознавание предметов и прочее. Дизайн на чипе Cyclone II занимает следующие ресурсы: LE – 745(4%), memory bits – 32768 (14%), PLL – 1 (25%), Embedded Multiplier — 0(0%), — таким образом, разработчикам остается еще достаточно ресурсов для реализации своих идей.

Послесловие

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

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

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


" alt=«image»/>

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


"

Шаг 1. О проекте

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

Шаг 2. Модуль камеры OV7670

Этот модуль позволяет захватывать изображения в формате VGA (640x480). Он может выполнять некоторую начальную обработку и передавать изображения на микроконтроллеры, такие как Arduino, через интерфейс SCCB.

Модуль камеры OV7670.

Модуль камеры OV7670.

Камера позволяет формировать изображения в других форматах, таких как CIF (352x240) например. Ручная регулировка до 40x30 также возможна. Максимальная скорость передачи изображения (VGA) может достигать 30 кадров в секунду. Камера также выполняет предварительную обработку изображений, например контроль экспозиции, усиление, баланс белого и многое другое. Также поддерживаются различные варианты кодирования изображений (YUV, различные типы RGB). Передача данных осуществляется по протоколу SCCB.

OV7670 характеристики

  • Разрешение VGA (640 x 480)
  • QVGA (320 х 240)
  • CIF (352 х 240)
  • QCIF (176 × 144);
  • Скорость передачи до 30 кадров в секунду,
  • несколько способов кодирования изображения RAW RGB, RGB 565/555, YUV / YCbCr 4: 2: 2.

Шаг 3. Комплектующие


Нам понадобится очень небольшой набор комплектующих (на фото выше слева направо):

Для понимания работы TFT-дисплея обязательно посмотрите Гид по работе с TFT-дисплеями.

Шаг 4. Схема соединения

Продолжаем со сборки всех компонентов, как показано на схеме ниже.



Соединения между OV7670 и Arduino Nano:

OV7670 Arduino Nano
VSYNC PIN2
XCLCK PIN3(должен быть сдвинут по уровню от 5 В => 3,3 В)
PCLCK PIN12
SIOD A4 (I2C data)
SIOC A5 (I2C clock)
DO D3 A0.. A3 (pixel data bits 0..3)
D4 D7 PIN4..PIN7 (pixel data bits 4..7)
3.3V 3.3V
RESET 3.3V
GND GND
PWDN GND

Соединения между TFT-дисплеем и Arduino Nano:

TFT Display Arduino Nano
DC PIN 8 (5V => 3.3V)
CS PIN 9 (5V => 3.3V)
RESET PIN 10 (5V => 3.3V)
SPI data PIN 11 (5V => 3.3V)
SPI clock PIN 13 (5V => 3.3V)
VCC 5V/3.3V (в зависимости от положения перемычки на плате TFT)
BL 3.3V
GND GND

Шаг 5. Компиляция в Arduino IDE

  • Скопируйте "src/lib/LiveOV7670Library" и "src/lib/Adafruit_GFX_Library" в папку Arduino "libraries" (если у вас уже есть "Adafruit_GFX_Library", то вам не нужно её копировать).
  • Откройте "src/LiveOV7670/LiveOV7670.ino" в Arduino IDE.
  • Select Tools -> Board -> Arduino Uno/Nano.

Шаг 6. Настройка программы

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


Сначала идем на Github.



После загрузки разархивируйте файлы в нужную папку.


Откройте разархивированную папку и перейдите в каталог: LiveOV7670-master\src\lib. Скопируйте две папки в вашу библиотеку (Library) Arduino.


Перейдите в LiveOV7670-master\src\LiveOV7670. Откройте файл с именем setup.h.

При изменении значения примера 1 на пример 3, как показано на скриншоте ниже, камера будет транслировать изображение непосредственно на компьютер.

Когда установлен Пример 1, камера передает изображение непосредственно на ЖК-дисплей, который подключен через интерфейс SPI с использованием библиотеки LiveOV7670Library.


Установите Пример 1 для live-потока TFT.


Далее откройте файл LiveOV7670.ino.


В нижней правой части экрана выберите плату Arduino и порт (Port).


Загрузите код сверху без каких-либо изменений.


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



Шаг 7. Заключение



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

4 комментария

In file included from C:\Users\����\Documents\Arduino\libraries\Adafruit_GFX_Library\Adafruit_SPITFT.cpp:36:0:

using Adafruit_GFX::drawRGBBitmap; // Check base class first

Ошибка компиляции для платы Arduino Nano.

У меня все заработало (поправила контакты, перезагрузила скетч). Жаль, что вы так необщительны, но все равно спасибо. А сделайте еще на какой-нибудь урок на другой TFT экран. Я хочу большой экран, ну хотя бы 6-7 дюймов.

Здравствуйте, а можете поделиться проектом, хотел подробно узнать, спасибо

В данной статье мы рассматриваем подключение камеры OV7670 к Arduino. Этот модуль выбран не случайно - он является самым доступным устройством на рынке (среди аналогов) с неплохими функциональными характеристиками (скорость передачи до 30 fps, несколько способов кодировки изображений и др.).

Если вы хотите попробовать настроить web-камеру для видеонаблюдения или пробуете себя в конструировании игрушек со встроенной видеокамерой (роботов, радиоуправляемых машинок) – вам точно пригодится наша небольшая инструкция по этой теме.

  • Arduino Uno;
  • макетная плата;
  • камера OV7670 (с разрешением 0,3 МП.);
  • соединительные провода.


В комментариях с радостью отвечу на ваши вопросы.


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


В новом информационном обзоре рассматриваем GSM модуль SIM800L к Arduino. Почему выбрано именно это устройство? Во-первых, оно достаточно известно и популярно.

Модуль энкодер KY-040 является электромеханическим устройством, а точнее - датчиком угла поворота и вращения оси различных девайсов. Непосредственно сам прибор.


В данной статье рассмотрим подключение Arduino Ethernet shield к Ардуино. Этот шилд создан для обмена информацией между локальной сетью и контроллером, а.


В этой статье мы рассмотрим подключение ADS1115 к Ардуино. Речь идет о 16-битном аналого-цифровом преобразователе, оснащенном 4 входами непосредственно для.

OV7670


И здесь, как черт из табакерки, на арену выпрыгивают китайские производители контроллеров. Сначала появляется ESP8266, который был нами протестирован, но честно говоря, поговорка о том, что чего из него ни делай, а получается погодная станция, родилась не на пустом месте. Попытки установить ESP8266 на мобильного робота и одновременно обеспечить адекватную работу обвески из датчиков у нас не получилось. Но, тем не менее, эти контроллеры пользуются определенным успехом, по крайней мере, их покупают.
Начав разработку, дети Поднебесной уже остановиться не могут, и следом выпускают новую версию контроллера ESP32, который не только получил адекватный запас GPIO, но и дополнительно получил второе ядро, и дополнительно (к поддержке WiFi протокола, который уже был на ESP8266) поддержку протокола Bluetooth.
Частота 160МГц, два 32-ных ядра, WiFI, BT, не оставили нас равнодушными, тем более идея сборки мобильного робота с камерой, которая передает изображение по WiFi витает уже давно.
Анализ документации по камере показал, что подключить ее к ESP32 вполне по силам. А позднее был найден пример подобного подключения на github:

Исходная схема OV7670 + дисплей

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

OV7670 + ESP32 NO FIFO


Помимо камеры в примере к ESP32 подключен TFT дисплей.
Я не нашел поблизости дисплея и подключил только камеру. Более того использовался контроллер Lolin32 Lite, который не имеет разведенного вывода GPIO 21 и моя схема немного изменилась.


С 5й ноги камеры контакт соединен с 23 GPIO платы на основе ESP32. В программе убрано всё, что касается работы с дисплеем и изменен указанный выше GPIO.
Программный код будет по второй схеме прикреплен к данной статье.
Сначала из куска шлейфа IDE был создан шлейф для камеры, но потом для простоты (скорости) все было сделано на макетной плате.


На стандартную макетную плату Lolin32 Lite становится так, что остаются с боков по одному контактному месту для соединений, а вот плата ESP-WROOM32 шире, и с одной стороны все контактные посадочные места оказываются под платой.

LOLIN32 LITE

OV7670 + LOLIN32 LITE


Вот такой пучёк проводов получился.


Установив прошивку и открыв Serial port на скорости 115200, можно убедиться, что плата завелась, а заодно узнать полученный ею адрес от вашей WiFi сети. И не забудьте в программе прописать ваше имя WiFi сети и пароль сети.
Чтобы получить информацию из Serial port следует: открыть Serial port, затем нажать на ESP32 кнопку Reset (Boot). После этого ESP32 перезагрузится и напечатает в порт информацию по подключению.

Теперь во внутренней сети потребуется компьютер или смартфон.
На нем в адресной строке браузера следует указать ip-адрес нашего устройства (здесь это 192.168.1.136). Все! Смотрим на картинки с камеры.

Картинка с камеры 1

картинка с камеры в браузере 2

Картинка с камеры в браузере 3

Честно говоря, качество полученной картинки не выдерживает никакой критики. Под большим вопросом и скорость передачи, отрисовка рисунка 320х240 шла довольно медленно и с задержкой в пару секунд. В итоге мы имеем загруженный под завязку ESP32 и 1-3 мутных кадра в секунду.
Выводы: камера OV7670 работает, но образец без буфера FiFo показывает на выходе изображение низкого качества, причины тому могут быть две – 1) большое время экспонирования полного кадра, что приводит к смазыванию картинки, 2)объектив без автофокуса с ручной фокусировкой, что затрудняет использование данной камеры в динамике (на мобильном роботе).
Использование камеры с внутренним буфером FiFo может немного улучшить ситуацию, но кардинально ничего не изменится.
Дальнейшие испытания пойдут в область использования готовых изделий, таких как смартфон в качестве камеры робота (или подобное устройство с возможностью отдельной от контроллера робота трансляции видео в сеть).

Читайте также: