TGA130V10 - модуль с установленной камерой OmniVision OV9650
можно приобрести в Терраэлектронике (на данный момент цена около 950 руб.)
Камера от знаменитого производителя, столь сложная для любительского монтажа (BGA-исполнение), смонтирована на плате с разъемом 2.00mm header, на борту установлен 2.5V LDO regulator, необходимый для аналогового питания, и к ней требуется подвести питание для процессорного ядра (1.8V) и питание ввода/вывода (2.5-3.3V).
Введение
Предлагаю вашему вниманию уникальный опус, в котором я поделюсь бесценным опытом работы с камерой, на даташите которой производитель отлично отдохнул. Я нигде в инете не нашел руковдоства к действию даже на английском языке, максимум конкретные вопросы на форумах. Единственный источник полной информации - тех. поддержка OmniVision
Даташит не только неполноценный, это еще цветочки, в нем полно грубейших ошибок, природа которых заключается в небрежной копипасте. Много информации можно почерпнуть из даташитов на близжайшие модели камер и обнаружить, например, что такой же регистр выполняет совершенно другие функции.
Я подключил камеру к отладочной плате Olimex LPC-H2103 с установленным на ней МК NXP LPC2103. Это 32-битный МК архитектуры ARM7, работающий на частоте 60МГц. Моей целью стояло получение изображения разрешением QQCIF (88x72) в формате RGB555. МК имеет очень мало памяти, поэтому я получаю в память строку из кадра, передаю ее на комп по UART, затем из следующего кадра получаю следующую строку и т.д. Разумеется, сцена перед камерой должна быть статичной
В статье я обязуюсь предоставлять исключительно достоверную информацию, иначе бы она не имела смысла, и несу ответственность за любую опечатку головой (ну... орфографические опечатки допускаются ). Обобщение фактов на другие модели камер оставляю вам. Если я в чем-то хоть чуть-чуть сомневаюсь, я это указываю.
Итак, дальнейшая информация получена мною в результате мучений и разнообразных экспериментальных иссследований в течение недели, проводившихся преимущественно методом тыка (о, хвала даташитописателям ! я могу часами их материть...).
Краткое описание
Прежде всего внимательно изучаем подробнейший документ на камеру (уникальная вещь !) и даташит Doc 02, а лучше новую версию 1.91
Камера может тактироваться ШИМ-сигналом частотой от 10 до 48 МГц. Изображение выдается на 8-битную шину согласно стандартным сигналам горизонтальной (HREF, HSYNC) и вертикальной (VSYNC) синхронизации и стробирующему пиксельному сигналу PCLK, частота которого может быть настроена делителем в регистре CLKRC(0x11). Сразу после включения камера начинает выдавать картинку в формате YUV (CCIR601, 8-bit Cb Y Cr Y), наиболее хорошо форматы описаны в даташите на OV6620 , в котором нас интересует Table 4 и Figure 3 (нижний тайминг). Все настройки камеры доступны посредством записи/чтения 170 8-битных регистров (не обольщайтесь) через интерфейс SCCB, который, смею вас заверить, полностью совместим с I2C. Ввведение OmniVision'ом якобы собственного стандарта всего лишь трюк для избежания лицензионных требований от компании изобретателя I2C - компании Philips, не более. Настройки/регистры наиболее полно описаны в даташите на OV9660 .
Схемотехника
Распиновка выводов с камеры на 0.5mm pitch connector ("гибкая лента") приведена в Doc 04, а схема самой платы, соединяющей камеру с интерфейсным разъемом в Doc 03. И, разумеется, тут тоже ошибки. На самом деле, все нормально, пины Y7-0 подключены к выводам камеры D9-2 соответственно. Заметьте, что D1-0 не выведены вообще.
Схема моей платы выполнена в Eagle PCB 5.6.0, я вырезал все лишнее (подключения сервоприводов и т.п.), вот сами файлы , а у кого нет игла, скриншоты:
а вот как оно в железе выглядит:
После того как я угробил пару камер, я стал очень бережно относиться к ним, поэтому не удивляйтесь "забронированной" камере
Черным проводом я отдельно провел XVCLK, ...<бредятина>... - позже я выяснил, что это полный бред и совершенно нет необходимости
Сама камера практически впритык к разъему подключена. Возможно все это покажется вам параноидальным, но я столкнулся с наводками/помехами. Изначально то я, конечно, 30см шлейфом соединил (я ведь камеру на схват робота устанавливаю, а плата в основании находится), но при этом камера заводилась на раз через раз и только с плясками с бубном.
Сверху подключен JTAG-адаптер Signalyzer DT-USB-SLITE, с помощью которого я прошиваю МК и провожу отладку в чипе
Регистр IN74AC374N (аналог КР1554ИР23) защелкивает данные по стробу PCLK и хранит их до следующего строба, иначе МК может и не успеть прочитать их, ведь фиг знает, сколько они удерживаются после строба.
Пины камеры RESET и PWDN внутренне подтянуты до нуля, поэтому в принципе нет необходимости подключать их, т.к. в камере заложена возможность программного сброса и ухода в спящий режим (!не проверено!)
Программная часть (software)
Самая интересная и кульминационная часть, не так ли
Полностью рабочий пример на C, составленный в виде проекта C++ Project на Eclipse IDE для GNU GCC и Yagarto GNU Toolchain (GNU ARM Eclipse Plug-in для Eclipse), и файл Launch-конфигурации (который можно импортирвоать в проект) для отладки в OpenOCD (Zylin Embedded CDT plugin). В проекте присутствуют сгенерированные автоматически эклипсом make-файлы, поэтому в принципе можно вручную собрать Программа выводит в UART картинку в разрешении QQCIF попиксельно (3 байта, GRB). Полученные данные можно вставить в bmp-файл и узреть BMP-файл содержит заголовок, опционально таблицу цветов (у нас нет) и собственно сами данные. Строки идут снизу вверх, данные начинаются со смещения 0x36, причем цветовые составляющие пикселя идут в порядке GRB, а не RGB. Создаем в виндовом пейнте пустую картинку с разрешением 88x72 и сохраняем в формате "24-разрядный рисунок bmp". Потом WinHEX'ом вставляем по смещению 0x36 raw-данные, полученные по уарту (это смещение хорошо видно, начиная с него идут FF FF FF ... (белые пиксели), вот поверх них и записываем), сохраняем, и вуаля, получаем перевернутую картинку
После подачи на камеру тактового сигнала она начинает выдавать изображение, но не совсем сразу. В любом случае крайне рекомендуется делать сброс. Устанавливаем RESET в 1, ждем хотя бы 5мс, включаем ШИМ-сигнал, ждем 5мс, устанавливаем RESET в 0, ждем хотя бы 1000мс (можно и меньше, но если включены всякие авто-штучки типа AWB, ABLC, AGC, AEC, то требуется еще время, чтобы картинка подстроилась под освещение, цвета и т.п.), после чего можно принимать изображения.
Подробно I2C-взаимодействие с ней раписано в этом даташите . Slave ID камеры 0x60 (при записи 0x60, при чтении 0x61), subaddress - адрес регистра, data - значение регистра.
По регистрам разбросаны самые различные настройки, которыми овладеть полностью может только мегаспец в области видео (если вы думаете, что вам не придется в них разбираться исходя из того, что вы всего лишь хотите получить хоть какое-то изображение, а всякие настройки по умолчанию заданы самым оптимальным образом и нет необходимости их трогать, то спешу вас разочаровать ). Значения разрядностью более 8 бит разбросаны по разным регистрам. LSB (less significant bit) - младший значащий бит, MSB (most significant bit) - старший значащий бит. Опции могут быть взаимосвязаны, например, в одном регистре надо установить бит, включающий функцию, а в другом, а возможно и третьем, задать необходимые значения.
Ну а теперь крайне ценные руководства и факты...
- Первым делом выясните, с каким чипом и его версией вы работаете. Да, да, мне попался чип с более новой версией. Для этого прочтите регистры PID(0x0A) и VER(0x0B) (не из даташита, а из самой камеры). На сайте TechToys находится даташит версии 1.3, где PID=0x96, VID=0x50, я же обнаружил, что у меня VID=0x52. Я просто загуглил "omnivision pid 96 vid 52" и нашел даташит версии 1.91. Сравнил оба даташита, в новом исправили как мелкие косяки, так и удалили некоторые настройки регистров и добавили новые. Вообще, с каждой версией даташита (а может и чипа тоже), раскрываются регистры, ранее считавшиеся зарезервированными (RSVD), просто даташитописателям лень все документировать сразу.
- В начале камера выдает всякое барахло. Запишите в регистр OFON(0x39) значение 0x43 (и никакое другое!), если хотите увидеть осмысленное изображение Смысл этого регистра в разных даташитах разный и ни разу не отражает его истинное предназначение. Условно назовем его регистром, включающим камеру
- Сигнал VSYNC ведет себя странным образом (!есть сомнение!). Я как то хотел подсчитать, сколько строк выдается в кадре, и пришел к такому выводу, что в течение кадра VSYNC выдает положительные импульсы, возможно из-за наводок. Причем, это не мешает приему изображения, если синхронизироваться этим сигналом, а во время приема кадра (т.е. пока VSYNC=0), не обращать на него внимания. Видимо вблизи начала кадра этот сигнал ведет себя корректно (ведь href и, возможно, pclk отсутствуют, что и навело меня на мысль о наводках)
- Настройка частоты PCLK. Регистр CLKRC(0x11). BIT[6] и вправду устанавливает частоту PCLK равной входной тактовой частоте XVCLK, значения остальных битов более не виляют на частоту (!не проверял последнюю часть утверждения!). BIT[5:0] - делитель, позволяет уменьшить частоту PCLK до 32 раз меньшей входной, значение расчитывается согласно тут же приведенной в описании формуле. BIT[7] - если 0, то PCLK еще в 2 раза уменьшается, если 1, то нет.
- Получить изображение в формате RGB555 мне не удалось. Я установил BIT[2] в COM7(0x12) и BIT[5:4] в 11 в COM15(0x40). Я плюнул на него, ведь фиг знает, регистры то напутаны могут быть, и лишь одному Онотоле известно, куда что записать, чтобы камера выдавала данные в RGB555. Пока что я смирился с этим фактом и декодировал YUV (CCIR601, 8-bit Cb Y Cr Y, тобишь 4 байта на пиксель), которым она выдает по умолчанию. Это был триумф, когда я впервые получил осмысленную картинку. Обычно я в таких случаях подпрыгиваю до потолка, ударяюсь башкой и мне ее сносит, я долго бегаю по квартире, вопя "оно заработало !!! фак мой моск !!!", но бессоные ночи меня вымотали, и тем более я опаздывал в бассейн. Я просто вздохнул с облегчением
- Выбор разрешения. Это самое веселое Регистр COM7(0x12) содержит биты, устанавливающие нужное разрешение. Кажется, что все очень просто, устанавливаем нужный бит и камера начинает выдавать изображение с соответсвующим количеством строк и пикселей и соответствующими таймингами. Но не тут то было... Во-первых, биты напутаны и не соответствуют заявленным разрешениям и даже вообще банальной логике. Я установил бит QCIF, но камера при этом стала выдавать QQCIF, причем изображение полосистое и растянутое (количество строк в 2 раза больше, как в QCIF), происхождение полос очень похоже на режим прогрессивного скана. Я решил воспользоватсья предлагаемым (а точнее даже требуемым) для QQCIF пропуском строк в регистре COM1(0x04), установив BIT[3:2] в 01 (строки пропускаются в буквальном смысле, т.е. href=0 на пропускаемой строке, кстати, это может оказаться весьма нелишним временем, если вы обрабатываете изображение в реальном времени). Вуяля, изображение стало пропорциональным, но полосы остались. Я тогда выбрал разрешение CIF и получил картинку в 2/3 раза меньшую (!не помню точно, помню лишь, что тоже ерунда была!), и тогда я наконец попробовал QVGA, которое мне выдало изящную картинку - без полос и с насыщенной гаммой цветов. Нетрудно сообразить, что разрешение и картинку определяют несколько различных регистров в совокупности, и тупо сидеть перебирать значения 170 регистров просто нереально, и я забил. Мне как раз нужно было QQCIF и я его получил
- Магические установки от Девида Блейна. По умолчанию камера выдает жутко дерьмовое изображение (хотя бы уже полосы, перечисленные выше в формате QCIF или, вернее, QQCIF). TechToys предлагает Breakout board compatible with 3.5" TFT color LCD module for life video, в котором установлена наша плата с камерой. Там я скачал Example code for Microchip PIC18xxx & CMOS camera (ver. 19012009). Из camera/ov9650.c, camHwInit я извлек эти священные установки регистров, покрытые мраком неизвестности. Это настолько таинственные настройки, что даже в комментариях к ним написаны недоумевания. Видимо автор вошел в транс, когда писал их, но выйдя из него, он не смог объяснить, что он произвел на свет. Благодаря им, дерьмовое изображение стало шикарным - полосы исчезли, цвета насытились, яркость увеличилась, единственный минус - на неосвещенных участках шум из розовых, красных и синих пикселей, а идеальная картинка только при отличном освещении. Итак, там устанавливаются практически все регистры камеры: различные авто-штучки, настройки экспозиции, gain-control, фильтры, шумоподавление, гамма-коррекция, коэффициенты матриц и прочее, причем половина из них устанавливается в значения по умолчанию, что далеко не самое странное, так помимо прочего записываются еще и зарезервированные регистры. Я закомментировал зарезервированные регистры, наивно полагая, что ничего не изменится, но не тут то было Я сделал лишь немного изменений, касающихся моих собственных предустановок, все остальное я пробовал ковырять, но мне не удалось постичь их магию, и я оставил как есть.
- Непредсказуемое влияние одних установок на другие.
Пример 1. Магические установки привели к тому, что изображение сдвинулось вправо, в начало добавиллись две полосы, первая белая, вторая - утемненное изображение края, и, соответственно, две послыедние полосы уехали за край Я стал искать, какая из установок приводит к такому, я надеялся, что где-то нечаянно лишний бит устанавливается или значение какого нить зарезервированного регистра, и я просто удалю эту установку, но не тут то было ... К данному смещению приводит включение функции "White-pixel erase" в регистре COM22(0x8C). Если не включать, смещение исчезает, но картинка с шумами. Вот такой вот подлый шантаж
Пример 2. Вертикальный переворот изображения (VFlip enable в регистре MVFP(0x1E)) приводит к тому, что появляются жуткие артефакты в верхних (или нижних, смотря каких понятий придерживаться) строках. Переворот мне понадобился, потому что по умолчанию камера выдает перевернутое изображение. Что ж, ладно, фиг с ним. Буду работать с перевернутым. - В виду выше сказанного, поинтересовался я, а какие действительно значения по умолчанию содержатся в регистрах после старта работы камеры ? Все 170 голубчиков вывел в уарт и сравнил. Выяснилось, что регистры 0x20-0x23 содержат отличные от умолчания значения. Вот так вот
- При JTAG-отладке, т.е. когда вы прямо в чипе будете по шагам выполнять программу и устанавливать различные брейкпойнты, будьте крайне осторожны. Думаю, достаточно очевидно, что при пошаговом выполнении замораживвается толкьо выполнение инструкций, но периферия работает в реальном времени, т.е. таймеры не замораживаются, передача по уарту не приостанавливается, поэтому не получится пошагово вмешаться в процесс синхронного приема данных с камеры и получить валидное изображение. НО! Более того. Даже если вы свободно "проскочите" синхронный код (например, дотопаете шагами до него, потом поставите брейкпойнт на его последнюю строку, и нажмете Resume, код свободно выполнится, а потом встанет на брейпоинте), то в этом случае он будет выполняться медленнее, потому как отладчик сканирует код и ждет срабатывания брейкпоинта (спецы, возможно, меня подправят, я не сильно разбираюсь в этом, а всего лишь суть объясняю).
- gcc даже при отключенной оптимизации (-O0) как помешанный параоник оптимизирует код, поэтому будьте очень осторожны, когда на глаз прикидываете, сколько ассемблерных команд будет занимать та или иная строка сишного кода, в случае, если пишете синхронный код. Когда я читаю ассмеблерный листинг, у меня волосы дыбом встают, какой дикий код генерирует gcc
Вроде бы я все перечислил, позже еще чего-нить вспомню и включу в этот список
Оценка качества
Изображение, запечатленное цифровиком Canon PowerShot A95 (5.0 MegaPixels):
Изображение, запечатленное камерой OV9650 в разрешении QQCIF c магическими установками Девида Блейна, на объектив наклеена пленка (которую по идее надо снять) + стоит "стеклышко" от двд-бокса, поверх которого слой прозрачного скотча (возможно, без них качество лучше, но я предпочитаю безопасность): (пришлось конвертнуть в png, т.к. bmp запрещено настройками форума, но ни качество, ни цвета не пострадали)
Заключение
Если вы внимательно все прочитали, то скорее всего у вас отпало желание работать с камерами
Я писал это руководство, стремясь отдать дань общественности, другим авторам и всем тем, кто помогает друг другу и делится опытом. Надеюсь, что эта информация поможет вам резко сократить особо изощренный сексуальный акт, предшествующий успеху. Обращайтесь с вопросами, если таковые имеются, но советую поторопиться, потому как меня могут забрать в армию, откуда мне будет крайне затруднительно отвечать
Буду рад принять любые замечания, исправления и дополнения, которые буду по мере сил добавлять сюда (если, конечено, ограничения форума позволяют неограниченно редактировать это сообщение ).
Также просьба не флудить.
---
(c) Артем Писаренко, для roboforum.ru, 2010г.