OSD на ATmega1281
Вспомнил, что этой ветке последнее видео так невесело закончилось. Можно подумать, что не этом проект и закончился… Ан- нет! Давно уже летаю, правда далеко и высоко пока не рискую… Вот крайний полет:
До этого регулятор автопилота был только с “П”-ветвью. Выводил на базу довольно точно, но как-то раздражало, что все время недоворачивает на цель. Добавил “И”-ветвь и появилась вполне предсказуемая раскачка. Инерция самолета, запаздывание GPS-данных, время интеграции И-ветви… Что-то не соображу как все это увязать, и демпфировать раскачку.
Люди, а кто как борется с дрожанием камеры? Камера у меня поворачивается только по вертикали прямым приводом от сервы. Во первых у сервы небольшой люфт, и от вибрации двигов камеру потряхивает. Во вторых серва сама в некоторых положениях зудит. Причем если механически пытаться демпфировать для уменьшения дрожания от первого пункта, то растет проявление второго…
Или это лечится только какой-нибудь дорогучей цифровой сервой?
msv
Расскажите, плз, как у Вас устроен видеовывод - в частности те самые “золотые” три инструкции 😃 и сопряжение ассемблера с Си
Кста, схему можно немного удешавить/упростить - видеозахват замечательно работает со встроенным в Мегу компаратором.
Код вывода строки сделан “в лоб” и не отличается особым изяществом:
;
;gNumLine++
MOV R26,gNumLineL
MOV R27,gNumLineH
ADIW R26,1
MOV gNumLineL,R26
MOV gNumLineH,R27
;if(gNumLine>=TOPLINE_SCR && gNumLine<TOPLINE_SCR+VSIZE_SCR)
CPI R26,LOW(TOPLINE_SCR)
LDI R16,HIGH(TOPLINE_SCR)
CPC R27,R16
BRLT _end1
CPI R26,LOW(TOPLINE_SCR+VSIZE_SCR)
LDI R16,HIGH(TOPLINE_SCR+VSIZE_SCR)
CPC R27,R16
BRLT _con1
BRNE _end1
LDI R16,1
MOV f_work,R16
_end1:
RJMP _USART_RX
; pause
_con1:
LDI R16,WAIT_START_OUT
_pause:
DEC R16
BRNE _pause
; out string
MOV R27,gScrBuffPointH
MOV R26,gScrBuffPointL
LDI R16,BYTES_FROM_STRING
LD R18,X+
_out_ch:
MOV R17,R18
OUT V_PORT,R17 ;1
NOP
NOP
LSR R17
OUT V_PORT,R17 ;2
NOP
NOP
LSR R17
OUT V_PORT,R17 ;3
NOP
NOP
LSR R17
OUT V_PORT,R17 ;4
NOP
NOP
LSR R17
OUT V_PORT,R17 ;5
NOP
NOP
LSR R17
OUT V_PORT,R17 ;6
LD R18,X+
LSR R17
OUT V_PORT,R17 ;7
LSR R17
DEC R16
NOP
OUT V_PORT,R17 ;8
brne _out_ch
LDI R17,0
NOP
OUT V_PORT,R17 ;8
SBIW R26, 1
MOV gScrBuffPointL,R26
MOV gScrBuffPointH,R27
Пасиб.
Если здесь:
LDI R16,BYTES_FROM_STRING
LD R18,X+
убрать плюс, то в конце можно будет убрать всю инструкцию:
SBIW R26, 1
Мелочь, а приятно )
Пишу в IAR, и всю голову поломал - как красиво передать ассемблерной части адрес на видеобуфер.
Как у вас это получилось - так и не понял. Или gScrBuffPoint задан вручную? (как и размещение видеобуфера в опертивке)
Сорри, ошибся, не все так просто.
…как красиво передать ассемблерной части адрес на видеобуфер
Не уверен, что это красиво, но у меня так:
register unsigned char* gScrBuffPoint @5;
#asm (".def gScrBuffPointL=R5")
#asm (".def gScrBuffPointH=R6")
Инициализация в прерывании от КСИ:
interrupt [INT0] void ext_int0_isr(void)
{ // КСИ
gNumLine=0;
gScrBuffPoint=gScrBuff;
}
Что-то и топикстартер молчит и окружающие не интересуюццо…
Появилась мысля как увеличить точность измерения тока - ставим в меге источником опорного внутренние 2.56 вольта - и при нулевом токе (через датчик) считываем значение порядка 950.
И работаем на отрицательной ветви токового датчика - т.е. при растущем токе значение с АЦП будет падать до нуля.
Даст повышение точности в два раза.
/*
еще немного мыслей просто из записной книжки:
Ток и напряжение лучше мерить тинькой в режиме ADC noise reduction, с полной обвязкой АЦП и как можно ближе к датчику - результат будет чище и лучше.
Работаем на пониженной частоте АЦП.
Имеет смысл вставить RC фильтр от помех между датчиком и мегой
Датчик чувствителен в магнитному полю - ставим рядом катушку, включаем, измеряем ток, отключаем, измеряем ток, усредняем два измерения - это неопробовано, неизвестно что из этого получится, неоправданно…
*/
Да, народ не слишком активен… Может по результатам сезона выложу hex (от НАСA похоже не дождусь предложения на приобретение проекта 😃). Может активность увеличится… Хотя финальной печатки нет (то что у меня, уже можно считать макеткой+кучка платок апгрейда, слишком много поменялось, от начальной идеи), поэтому на повальный интерес по повторению не рассчитываю…
Сейчас играюсь с управляющими алгоритмами автопилота. Правда пока чем мудренее алгоритм, тем обычно хуже все в реале, хотя в модели на ПК, все отрабатывается идеально. Видать слишком “хороша” модель, но сделать ее более правдоподобной, задачка посложнее чем саму управляющую программу… 😃
Добавил режим, похожий на настоящий АП- если в режиме стабилизации щелкнуть доп. тумблер- АП начинает удерживать текущий курс и высоту (такого вроде бы нет у “конкурентов”). При выключении этого режима, устанавливаются нули сенсоров горизонта (для этого, автокалибровки, чес. говоря этот режим и задумывался).
Еще не испытал…
внутренние 2.56 вольта - и при нулевом токе (через датчик) считываем значение порядка 950.
И работаем на отрицательной ветви токового датчика
Именно так у меня и сделано. Правда не столько ради увеличения разрешения, а больше ради упрощения схемы (не нужен свой источник напряжения, и даже ставить делитель напряженияне надо).
Имеет смысл вставить RC фильтр от помех между датчиком и мегой
Практика показала, что это обязательно. Датчик слишком быстродействующий и выдает все пульсации на силовом проводе.
Остальное, по вкусу… 😃 Надо считать какую точность хотите получить, достаточно ли мала погрешность самого датчика, дабы ее обеспечить, ну и нужна ли она…
Да, народ не слишком активен…
Лето, жара, отпуска, ДАЧА!!😛
поэтому на повальный интерес по повторению не рассчитываю…
…
IMHO, большинству из тех, кто следит за этой темой интереснее направление по развитию, чем простой повтор конструкции. Поэтому куски исходников( раз уж нет желания выложить полный проект), наверное, будут более интересны, чем HEX…
как красиво передать ассемблерной части адрес на видеобуфер.
Обычно так и делают - вешают буфер по известному адресу (только не в самом начале:
signed char array [BUFFER] @0xC0;
И обращаются хоть из Си по указателю, хоть из асма. Если буфер небольшой, можно упихать в регистры как у автора. Будет ещё быстрее. Но тут надо в ассме посмотреть, сколько регистров компилер сохраняет. ИАР вообще ассм недолюбливает, и склонность к гонянию регистров из ОЗУ и обратно имеет. То есть разместив буфер в регистрах можно всё равно получить лишнее сохранение/вызов.
У меня были ошибки в получении адреса, поэтому спрашивал
Сейчас без указания конкретного адреса все работает прекрасно.
Но все равно спасибо.
Если буфер небольшой, можно упихать в регистры как у автора.
Какая разница какой размер буфера? У меня в регистрах указатель на него, хоть все ОЗУ адресуй.
Сейчас без указания конкретного адреса все работает прекрасно.
Так поделитесь, как решили задачку?..
Вобсчем вот основа всего OSD. Может кому интересно будет:
narod.ru/disk/24027327000/OSD_demo.rar.html
писал в IAR
Глянул Вашу заготовку OSD. Попиксельный вывод строк символов скорее всего получится слишком тормозной. Можно не успеть обновить все надписи за межкадровый интервал. Мне пришлось оптимизировать вывод строки сразу в одной функции и на асме. Использовать встроенный компаратор для определения синхроимпульсов, мысль хорошая. А в железе уже проверили работу?
Да, скриншоты в архиве это кадры с уже реального железа. Картинку захватывал такой железякой: nix.ru/…/STLab_M320_Grabber_USB2.0_SVideo_86320.ht…
Кстати, телевизор, на котором я проверял качество картиники надежно устранял все факелы - так что “удешевленное” подмешивание тоже жизнеспособно.
Насчет обновления - некоторые данные нет смысла перерисовывать в каждом кадре , можно делать это чуть реже. Я разбил такие фрагменты кода на несколько частей, и в зависимости от счетчика кадров вызывается только один фрагмент:
if (task++>T) task=0;
if (task==0) {compass(ang);}
if (task==1) {alt_ruler(); speed_ruler();}
if (task==2) {discharge(cap);}
Примерно так. Мой GPS приемник отдает данные вообще раз в секунду - поэтому смысла перерисовывать координаты/высоту/скорость/etc в каждом кадре нет.
Уже писАл выше, что у меня вывод графики в каждом условно нечетном полукадре (25Гц, реже -не будет плавности), а вывод текстовой информации в четном, тоже как у Вас, поочередно группами. Хоть GPS у меня 5-ти герцовый, но для получения плавных движений шкал пришлось интерполировать получаемые значения на 25Гц, иначе картинка стробит.
Проблема с факелами у меня началась, когда начал пытаться рисовать тени…
Я поражаюсь с этого чувака: www.rowlhouse.co.uk/main.html 😮
На странице конечно много всего, но больше мне понравился RC-симулятор с автопилотом! Более того, этот товарищ выложил все исходники! (I’ve written a flight simulator for R/C model gliders)
Если посмотреть остальные проекты, остается сказать только “Во дает!” ибо это действительно сильно!
Не удивлюсь если он уже работает в НАСА…
Вобсчем вот основа всего OSD. Может кому интересно будет
Вывод строки пикселей по 3 цикла процессора на пиксель вместо четырех ( тогда в строку вроде влезет 32 символа вместо 24 ). Это если в Ваш проект, содержательная часть video_driver.asm
Может, кому интересно будет.
P.S. Реально это не проверял, могут быть ошибки.
LDI R16,WAIT
_pause:
DEC R16
BRNE _pause
; Загружаем указатель из оперативки в регистровую пару X:
LDS R27,gScrBuffPointH
LDS R26,gScrBuffPointL
LDI R16,STR_LENGTH ; Загружаем длину строки в счетчик
; Остальные биты порта - могут использоваться для чего-то полезного
; ( например, для ввода цифровых сигналов ), и на всякий случай сохраняем
; исходное состояние порта ( для входов - подключен ли к нему внутренний
; подтягивающий резистор; это м.б. важно ):
IN R17,VIDPORT ; Начальное состояние порта: в конце - восстановим
; Входим в цикл, экономя на RJMP ( первый раз - будет холостой вывод
; из R17 в порт того же, что только что ввели оттуда ).
_out_ch: ; Сюда приходим при продолжении цикла
OUT VIDPORT,R17 ; Выводим 8-й пиксель от предыдущего
; Начинаем вывод 8 пикселей следующего символа:
LD R18,X+ ; Загружаем данные из оперативки в регистр
OUT VIDPORT,R18 ; 1
; Пока что - переносим 8-й пиксель из R18 в 0-й бит R17, откуда его
; в итоге и выведем:
BST R18,7 ; 8-й пиксель - в T ( это бит в SREG )
LSR R18
OUT VIDPORT,R18 ; 2
BLD R17,0 ; 8-й пиксель - в 0-й бит R17 ( из T )
LSR R18
OUT VIDPORT,R18 ; 3
NOP
LSR R18
OUT VIDPORT,R18 ; 4
NOP
LSR R18
OUT VIDPORT,R18 ; 5
NOP
LSR R18
OUT VIDPORT,R18 ; 6
LSR R18
DEC R16 ; Уменьшаем счетчик оставшихся символов
OUT VIDPORT,R18 ; 7
BRNE _out_ch ; Если в R16 не ноль - продолжаем
; Иначе - это конец строки:
NOP
OUT VIDPORT,R17 ; 8 последнего символа
NOP
ANDI R17,0xFE ; Сбрасываем 0-й бит в R17 ( чистим пин на выходе )
OUT VIDPORT,R17 ; Чистим пин на выходе
STS gScrBuffPointL,R26 ; Обратно в оперативку
STS gScrBuffPointH,R27
Все работает “из коробки”!
Снимаю перед вами шляпу! ©
Да, пиксель стал квадратный - это здорово 😃
Мысля: взять кристалл с большим количеством оперативки, и на нем собрать “видеокарту”.
И не сваливать всю работу на один контроллер - это неудобно
Появляется вопрос: как общаться с этим контроллерами? И целесообразно-ли это вообще?