Это уже серьёзная задача, граничащая местами с профессиональной разработкой. Готовьтесь к трудному пути.
Хотя, конечно, камера то уже есть, и надо только научиться ей пользоваться
Изучаем усилия предшественников, коим хвала – 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).