Tag: OV7670 Камера Arduino

November 11, 2019 finereader No comments exist

Камера OV7670. Трудный путь

Это уже серьёзная задача, граничащая местами с профессиональной разработкой. Готовьтесь к трудному пути. 

 

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

Изучаем усилия предшественников, коим хвала – computerNerd, статья и статья и ещё статья.

Изучаем как цифровая камера работает – ПЗС матрица… Для программиста это просто двумерный массив с данными пикселей, который надо как-то с камеры забрать, пользуясь строчной и кадровой синхронизацией.

Нужно посмотреть кодировки цвета пикселя RGB, YUV (мы возьмём именно YUV, где на один пиксель приходится 2 байта).

 

Ну и надо понимать, что такой сложный прибор, в котором есть автоматические функции управления временем экспозиции, балансом белого, гаммой, резкостью и много чего ещё потому и сложный изнутри, чтобы быть простым для внешнего управления. Камера внутри себя содержит DSP (ЦОС) процессор. Для программиста задача сводится к начальной конфигурации камеры – установке определенных битов нужных регистров, а затем просто собираем байты пикселей изображения.

Камера способна выдать VGA картинку 640х480 со скоростью до 30 кадров/с, но для ардуины лучше-меньше, 320х240 еще ничего.

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

Лучше подключать вот так (скопировал с одного блога, который пропал куда-то, ну не пропадать же хорошей картинке)

Разъём камеры

Сигнал такта на входе и выходе камеры

Итак, чтобы оживить любое электронное устройство нужен тактирующий импульс или Clock. На ардуине на 11 пине выдадем 8 МГц ШИМ на пин камеры XCLK.

Теперь можно убедиться в работоспособности камеры – на выходе PCLK – те же 8 МГц. Ардуино не сможет обрабатывать байтовые посылки с такой скоростью, поэтому воспользуемся внутренним (для камеры) делителем частоты – максимальное значение 31 – оно хранится в регистре с именем CLKRC.

Расчет внутренней частоты (умножать не будем PLL_Multiplier=1):

Fint = 8 000 000 / (2*31+1) = 125 000 Гц – с такой частотой будут выдаваться байты кадра в ардуину.

Кадр 320х240 = 76800 пикселей. Для RGB и YUV пиксель кодируется двумя байтами. Байт же передаётся за один такт параллельно по D0-D7.

125 000 / (76800 * 2) = 0.8 кадров/сек.

 

Настройка камеры

Далее необходимо сконфигурировать регистры камеры – установить формат изображения 320х240, задать цветовую кодировку, установить делитель частоты и пр. Для этого используется интерфейс SCCB  – аналог I2C (в даташите МК AVR он ещё называется TWI).

Собственно, производитель привел регистры (адрес-значение), которые надо изменить для перехода в режим QVGA (320×240)

Ёще разберемся в них отдельно, а CLKRC тут для 30 кадров/с.

Обработка видео потока

Осталось только забрать видео поток.

Начинается новый кадр – ждём переключения VSYNC с 1 на 0.

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

По байтовому такту PCLK (переход в 0 – начало нового байта) забираем байт с параллельного порта D0-D7 (наверное, совсем правильно будет забирать байт в момент перехода PCLK из 0 в 1). Для YUV первый байт содержит информацию о пикселе в градациях серого, второй – о цвете. Для простоты пока второй байт не берем и просто ждем PCLK 1-0-1.

 

Самая захватывающая (дух и само изображение) часть программы выглядит так:

Большое отступление. Загадочные регистры

Регистры процессора (микроконтроллера) — блок ячеек памяти, образующий сверхбыструю оперативную память внутри процессора. Есть регистры, используемые самим процессором для вычислений, например, при выборке из памяти очередной команды она помещается в регистр команд, а при выборке переменных они помещаются в регистры операндов.

Но в микроконтроллере есть ещё и другие регистры – хранящие настройки разных периферийных устройств. С ними в основном и имеет дело программист. Например регистр PORTB, хранящий состояние выводов (пинов), или регистр DDR, хранящий настройки, находятся ли выводы (пины) в состояние входа или выхода.

В случае с камерой, регистр – это служебная очень быстрая память, например ячейки по 8, 16 бит, к которой можно обратиться по адресу. На стороне камеры работает программа, которая управляет камерой в соответствии с настройками, хранящимися в этих регистрах. Эта программа, в том числе, принимает посылки по I2C – первые 8 бит – адрес, следующие 16 бит – значение регистра. Вот и все. Такой вот протокол обмена.

 

Конфигурировать регистры будем булевыми операциями – AND (&) и OR(|).

Ну, говорить о том, что представлять содержание регистра удобнее всего в шестнадцатеричной или двоичной системе не будем

Также умолчим о возможности калькулятора (вид->инженерный) переводить числа между разными системами

Вот таблица истинности – правила двоичной арифметики, ну это уж почти всем известно.

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

Ну раз регистр это просто ячейка, например, из 8 бит, то выставим в регистре с именем PORTB восемь единичек:

Или все нули:

А теперь, как выставить 1 в первом бите, не изменив состояние других – при помощи OR (операция выполняется побитово):

Как же выставить 0 в любом бите – при помощи AND

Выставляем 0 в первом бите, не изменив состояние других – при помощи AND (операция выполняется побитово):

Если не понятно, прочитайте статью на customelectronics.ru

Начнём с настройки ардуино

Заглянув в datasheet на микроконтроллер ATmega8 семейства AVR (да, да, именно такой и в вашей ардуине), в ужасе ничего не понимаешь понимаешь, что выходы соответствуют трем портам B, C, D – PB0-5, PC0-5, PD0-7. В Arduino эти названия переименованы в цифровые выводы D0-D13 и аналоговые входы A0-A5.

Выводы управляются регистрами PORTх и DDRх.

Например, вывод PB5 управляется пятым битом в регистрах PORTB (состояние вывода – 0 или 1, 0В или 5В) и DDRB (настройка вывода – на вход(0) и выход(1));

Итак, чтобы подать 1 (5В) на 13 пин ардуино (PB5):

Надо настроить пин на работу в режиме выхода

Выставить 1 в 5 бите регистра PORTB

Вот настройки портов ардуино (тут не всё, но многое)

Подробнее о настройке камеры

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

Все адреса и рекомендуемые значения регистров – уже подготовлены и хранятся в .h файлике в виде #define RegName RegAddress.

Перед началом работы производитель рекомендует все регистры сбросить в состояние «default values» выставив 7-й бит в регистре СОМ7 в 1 (СОМ7[7] = 0x80) используя функцию wrReg(reg_addr, reg_val).

Механизм изменения размера картинки (разрешения) выглядит так:

Чтобы получить, например, 256х128 размера картинку, надо сначала передискретизировать (down sampling)VGA – взять каждый второй пиксель и получить 320х240, а затем использовать масштабирование (zoom) с коэффициентами 0.8 по горизонтали и 0,53 по вертикали сделает 256х128.

 

Чтобы изменить разрешение на 320х240 нужен только down sampling

Для этого надо разрешить масштабирование (в нашем случае только down sampling), выставив в 1 второй бит регистра СОМ3

Устанавливаем коэффициент 2 передискретизации по вертикали и горизонтали – 1 в битах [4] и [0] регистра SCALING_DCWCTR

Устанавливаем делитель такта PCLK на 2 на выходе из DSP в регистре SCALING_PCLK_DIV (1 в нулевой бит) – видимо, из-за пониженной скорости выдачи пикселей с матрицы (берем каждый второй) и частота работы DSP должна быть понижена

Разрешая масштабирование в регистре СОМ3, не забыть про СОМ14[3]

Далее вертикальные и горизонтальные размеры окна в регистрах VSTART, VSTOP, HSTART, HSTOP – ничего менять не надо.

Все требуемые для изменения регистры объединены в структуры, которые посылаются по IIC функцией wrSensorRegs(QVGA_OV7670).