OSD на ATmega1281
Прошил , включил питание .Моргает светодиод на 31 ноге (для чего светодиоды и кнопки ?) на кварце 20 мег есть. В очках или на телеке ничего нет (камеру подключил ). Возможно чёта не так припаял (уважаемый MSV можно посмотреть фото вашей платки ?)
Начнем с аналоговой части… В основе видео-микшера простейший каскад с общим коллектором. Проверьте его работу по постоянному току (цешкой). Видео должно проходить с камеры на передатчик даже при неработающей цифровой части.
(Питание на камеру/передатчик(лучше для начала видео-выход OSD сразу в телек) через соответствующий разъем OSD не забыли подать? 😃 )
Хм по ходу я голова, два уха .На работе всё подключил - работает и картинка есть.
Камера PAL? Пока только он поддерживается… Смотрите сигнал кадровой синхронизации с 3-ей ноги LM1881. Должны быть четкие одиночные импульсы 50Гц. Возможно потребуется увеличить резистор на 6-й ноге LM-ки до 1мОма. Или даже уменьшить резистор по ее входу до 470ом… На схеме показаны номиналы из даташита 1881, но жизнь иногда приподносит сюрпризы…
ЗЫ Пока я ответ сочинял все заработало? В чем была проблема?
Я резистор на 6 ноге лм1881 не тот поставил ,680 ом вместо 680ком.Поменял и бежать перестало😒
*TO MSV*
Прочитайте личку.
Раз подняли тему, мой отчетец…
С уменьшением пиксела до 0.15мкс (три такта CPU) во всей красе вылезли цветные факела из-за того, что спектр OSD стал активно налазить на цветовую поднесущую… Простых идей, без полного вырезания из суммарного видео+OSD цветовой поднесущей и отдельным подмешивания к этому, чисто яркостному сигналу, исходной поднесущей пока нет…
Наконец разжился вертикальной пиропарой, любезно задаренной Сергеем (ubd). Забацал честную 3d-математику:
void GetAngleCurrent(void)
{
s_int a, x, y, z, x1;
s_long l, l1;
// Cur Sensor
x1=gADC_Val[ADC_SENSOR1]- gCalibr.SensorMid[0];
y=gADC_Val[ADC_SENSOR2]- gCalibr.SensorMid[1];
z=gADC_Val[ADC_SENSORZ]- gCalibr.SensorMid[2];
// Rotate
l=x1; l*=gSensor.COS_Matrix; a=(s_int)(l/128); // COS_Matrix=0..128
l=y; l*=gSensor.SIN_Matrix; x=a-(s_int)(l/128); // SIN_Matrix=0..128
l=x1; l*=gSensor.SIN_Matrix; a=(s_int)(l/128);
l=y; l*=gSensor.COS_Matrix; y=a+(s_int)(l/128);
// length vector
l=x; l*=x;
l1=y; l1*=y; l+=l1;
l1=z; l1*=z; l+=l1;
a=lsqrt(l);
// angle
gRollAngle=a_tan2(y, z); // +180..-180
gPitchAngle=a_sin(x, a); // +90..-90
if(gRollAngle>90 || gRollAngle<-90) gPitchAngle=-gPitchAngle;
// Trimm
gRollAngle-=gSensor.RollTrimmer;
if(gRollAngle>180) gRollAngle-=360;
else if(gRollAngle<-180) gRollAngle+=360;
gPitchAngle-=gSensor.PitchTrimmer;
if(gPitchAngle>90) gPitchAngle=180-gPitchAngle;
else if(gPitchAngle<-90) gPitchAngle=-180-gPitchAngle;
}
Конечно все как-то работает… Но после того как вывел в поля отладки значения сенсоров, не удивился, что все работает именно “как-то”… Может и не хуже, чем в других подобных проектах, но до идеала ой как далеко… Возможно проблема, что сами корпуса пиросенсоров в полете по разному нагреваются/охлаждаются от солнца/ветра и от этого сигнал диф. пары весьма сильно плывет…
Вообщем не зря народ поголовно переходит на IMU, наверное и мне пора… 😃
Недавно решил проверить, можно ли сгенерировать видео на MSP430 и LM1881 - был приятно удивлен - не можно, а, видимо, нужно 😃 Причем процессор и делать почти ничего не должен. Одно прерывание - от Vsync - сбрасываю счетчики. Hsync заведен на вход таймера - при приходе следующий таймер настораживается на время, когда должна пойти развертка своего изображения, ну и считает строки. Дальше процессор просто отдыхает автоматически выбрасывая посылки через SPI контроллером прямого доступа. Первый канал DMA выплевывает первый байт буферной строки по готовности настороженного таймера. Второй канал выплевывает в буфер SPI байты по его готовности, сколько байт закажешь. Все! И никаких разрывов. Нужно только буферную строку приготовить или если вся память используется как видеобуфер, менять адрес для DMA. Программа написана на С++, никаких ассемблерных вставок, и еще операционка успевает крутиться. Если это можно назвать программой - практически только аппаратуру инициализировать и несколько строк в обработчике прерывания. Внешнего кристалла не надо - внутри калиброванный генератор 32 кгц и умножитель - я поставил 24 мгц. При цене процессора 1.5-2 доллара - неплохо.
Никаких ухищрении для того, чтобы изображение не дышало не надо - все делается на железном уровне.
Сделать в двух строках еще один канал для вывода черных каемочек пока не получилось - всего 3 канала DMA, ставить процессор с 7 каналами не хочется - куда мне столько ног?
А на счет IMU - похоже, пора. Гироскоп с акселерометром в одном флаконе с доставкой уже продают дешевле 7 долларов. Можно поставить не нормальный кальман, а два простейших, выдрано из моей проверенной программы, в свою очередь откуда-то скопипасчено (налетят знатоки - по ушам надают за безграмотность и незнание арифметики, а свое решение все равно при себе оставят):
const float Sw[2][2]={0.001, 0.003, 0.003, 0.003};
const float dT=0.05;
const float Sz=0.07701688;
float roll_kalman_update(float gyro_rate, float accel_angle)
{
float s_00;
float angle_err;
float K_00;
float K_10;
float AP[2][2];
float APAT[2][2];
float KCPAT[2][2];
static float angle=0;
static float bias=0;
static float P[2][2];
angle += dT*gyro_rate - dT*bias;
angle_err = accel_angle - angle;
s_00 = P[0][0] + Sz;
if (s_00 == 0) s_00 = 0.001;
AP[0][0] = P[0][0] - dT * P[1][0];
AP[0][1] = P[0][1] - dT * P[1][1];
AP[1][0] = P[1][0];
AP[1][1] = P[1][1];
K_00 = AP[0][0] / s_00;
K_10 = AP[1][0] / s_00;
angle += K_00 * angle_err;
bias += K_10 * angle_err;
APAT[0][0] = AP[0][0] - AP[0][1] * dT;
APAT[0][1] = AP[0][1];
APAT[1][0] = AP[1][0] - AP[1][1] * dT;
APAT[1][1] = AP[1][1];
KCPAT[0][0] = K_00 * P[0][0] - K_00 * P[0][1] * dT;
KCPAT[0][1] = K_00 * P[0][1];
KCPAT[1][0] = K_10 * P[0][0] - K_10 * P[0][1] * dT;
KCPAT[1][1] = K_10 * P[0][1];
P[0][0] = APAT[0][0] - KCPAT[0][0] + Sw[0][0];
P[0][1] = APAT[0][1] - KCPAT[0][1] + Sw[0][1];
P[1][0] = APAT[1][0] - KCPAT[1][0] + Sw[1][0];
P[1][1] = APAT[1][1] - KCPAT[1][1] + Sw[1][1];
return angle;
}
Владимир, надеюсь мои сомнения не воспримете как “…по ушам надают за безграмотность и незнание арифметики…”. 😃
DMA- замечательная штука… Но не решает проблемы неопределенностью времени входа в прерывание, которое, имхо, существует практически для всех процов в несколько тактов. Вы, для определения момента времени начала вывода строки, используете последовательно два прерывания, и вроде бы визуально строка должна заметно подергиваться по горизонтали.
По коду, конечно не разобрался с Вашим алгоритмом коррекции дрифта, но показалось, что для определения углов ориентации используете прямое интегрирование значения скорости поворота вокруг одной оси. Тут есть известная засада в том, что углы поворота вокруг осей не определяют ориентацию модели из-за некоммутативности (о, каких слов набрался…) этих поворотов…
Те. поворот на 90 вокруг оси X и поворот на 90 вокруг оси Y могут представлять две абсолютно разные ориентации в зависимости от порядка выполнения.
Я пока для начала хочу попробовать банальный DCM. Забавно, но похоже получиться уместить весь код и по объему и по скорости даже с float на меге8 …
ЗЫ Может у кого есть идеи по модулятору OSD, способному выдавать качественное наложение белого и черного без искажений исходной цветовой поднесущей?
DMA- замечательная штука… Но не решает проблемы неопределенностью времени входа в прерывание, которое, имхо, существует практически для всех процов в несколько тактов.
В этом случае решает. Прерывание время не определят - оно определяет, когда слудующий таймер аппаратно запустит DMA. Т.е. никакие критичные по времени операции программно не обрабатываются. Неопределенность исключительно с точностью до разности между Hsync и фронтом 24-мгц генератора.
С фильтром одна гадость есть - он не работает, когда самолет вверх ногами - там точка разрыва. Для стабилизированного полета не очень реальная ситуация, а для индикации - нужно фильтр дофильтровывать 😃 вручную, когда угол близок к 180. При проходе через разрыв фильтр действительно с ума сходит. Но не надолго 😃
Да, и я писал - алгоритм не мой, откуда-то скопированный и немного подправленный в основном для лучшей читаемости. Ответственности я за него не несу 😃, на авторство тем более не претендую.
Те. проц можно сконфигурировать, что-бы дернув ножкой можно аппаратно запустить таймер, который в свою очередь аппаратно запустит DMA? Реально круто (как сказала бы младшая дочь), почти ПЛИС получается…
Мертвые углы это другая проблема… Тангаж всегда определен, поскольку это угол между осью X и горизонтальной плоскостью и имеет значения +90…-90град. А вот крен (+180…-180) при углах тангажа близких к 90град действительно неопределен, в чем даже вики сознается… Это видно и из выражения Roll=atan2(y, z);, где при тангаже близкому к ±90град Z стремится к нулю. Во всех алгоритмах, которые я смотрел, это только проблема конечной интерпретации.
Те. проц можно сконфигурировать, что-бы дернув ножкой можно аппаратно запустить таймер, который в свою очередь аппаратно запустит DMA?
Об этом я и пытаюсь сказать. Делалось вообще-то абсолютно другая вещь, но вот как-то вылезло, что и видео можно сформировать. Конверсионный продукт 😃 Сегодня подключил к реальному телевизору - понял, что слегка все не так красиво. PLL плавает - нужно все-таки кварц ставить 😦 , а не 32 кгц умножать до 24 мгц. Но в интернете ни разу не встречал, чтобы кто-то OSD делал на MSP. Разве что пинг-понг доисторический в старых аппликухах лежит.
Может у кого есть идеи по модулятору OSD, способному выдавать качественное наложение белого и черного без искажений исходной цветовой поднесущей?
С этим разберемся I hope so.
Как с последними прошивками и фичами?
НЕ РЕКЛАМА - так… к размышлению
Насчёт видеобуфера MAX4090 - вот вам разница в цене:
На общем аукционе 😃
на китайском рынке😒
:)Кому дешевле заниматься хобби?!
Как с последними прошивками и фичами?
Модулятор вперед… 😃
Модулятор вперед… 😃
Всмысле.
Ах да да да конечно
ближе к выходным посмотрим модулятор. Цветовая поднесущая 4.43, плюс полоса
цветоразностного сигнала, полагаю в районе 1-1.5МГц.
Игорь, режекторный фильтр это еще не решение проблемы (тут практически достаточно одного контура- “пробки”)…
Кстати, не хотелось бы связываться контурами, может есть для этого ПАВы?
Если его ставить на выход осд до сумматора, то как сложить сигналы с камеры и osd что-бы уровень белого osd был на уровне белого видеосигнала при его любом текущем значении (ставить мультиплексор- опять получим “разрывы” в поднесущей), а уровень черного, соответственно, на уровне черного?
Если после сложения, то как добавить поднесущую цвета (в идеале без подкрашивания OSD текущим цветом)?
Конечно все это наверняка решаемо, но надеюсь, что есть простое, оригинальное и красивое решение.
ЗЫ Интересно бы подсмотреть, как сделано у “конкурентов”… 😃
Игорь, режекторный фильтр это еще не решение проблемы (тут практически достаточно одного контура- “пробки”)…
Кстати, не хотелось бы связываться контурами, может есть для этого ПАВы?
Если его ставить на выход осд до сумматора, то как сложить сигналы с камеры и osd что-бы уровень белого osd был на уровне белого видеосигнала при его любом текущем значении (ставить мультиплексор- опять получим “разрывы” в поднесущей), а уровень черного, соответственно, на уровне черного?
Если после сложения, то как добавить поднесущую цвета (в идеале без подкрашивания OSD текущим цветом)?
Конечно все это наверняка решаемо, но надеюсь, что есть простое, оригинальное и красивое решение.
ЗЫ Интересно бы подсмотреть, как сделано у “конкурентов”… 😃
Не ПАВ а керамика, вроде даже есть на 4.43 по типу режекции звуковой поднесущей. Но заламывают цену мама не горюй.
Ceramic Trap XT SERIES Frequency range: 3.58MHz, 4.43MHz
Shenzhen, China. 😉