Activity

Нужна помощь по коду для AVR (ATTiny85)

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

GIMSK &= ~_BV(PCIE); не достаточно

PCMSK &= ~_BV(PCINT0); обязательно, в противном случае постоянно проваливался в прерывание ISR(PCINT0_vect)

второй момент - while(!lightCycle){} - это не сон, а ожидание, проц будет продолжать жрать питание. Термин “сон” - это перевод камня в состояние, при котором у него часть функции будут отключены и режим потребления питания будет минимален. Про сон погуглите watchdog и как этот таймер можно использовать, я не пользовался им поэтому не могу ничего утверждать.

Нужна помощь по коду для AVR (ATTiny85)
We-BEER:

А как сделать чтобы light считался встроенным счетчиком, как в моей втором варианте? Если усыпить проц до срабатывания прерывания, он же не будет гонять цикл и считать.

  1. если как у Вас, то я бы исправил

ISR(PCINT0_vect) {
	...
	lightValue = TCNT1L;		// Значение, до которого досчитал таймер low byte
	//lightValue = TCNT1;		// если сделать lightValue типом uint16_t, то можно так
}
  1. есть один момент: цикл main->while(1) должен крутиться всегда и работать с последним значением освещенности, расчитанным параллельно в таймерах, нельзя вот так останавливать работу до получения значения while(!lightCycle){}. Если конечно это не особые требования функционала.
Нужна помощь по коду для AVR (ATTiny85)

Попробуйте, следующий код, в симуляторе atmel studio отрабатывает, но конечно pb0 я в ручную сбрасываю в 0, чтобы прерывание сработало. Если не решите вопрос - на выходных соберу прототип, пока со временем вилы.

volatile uint8_t flag = 1;
uint8_t light = 0;

ISR(PCINT0_vect) {
    GIMSK &= ~_BV(PCIE);                // Отключаем прерываения по смене состояния
    PCMSK &= ~_BV(PCINT0);
    flag = 1;                    // Взводим флаг
}

int main(void)
{
    while (1)
    {
        if(flag){
            // задержка для визуализации результата замера
            if(light){
                while(light--){
                    _delay_ms(1);
                }
            }
            cli();
            DDRB |= _BV(LED_A) | _BV(LED_K);    // Порты на выход
            PORTB |= _BV(LED_A);            // Моргнуть
            PORTB &= ~_BV(LED_K);
            _delay_ms(10);

            PORTB &= ~_BV(LED_A);            // Подаем обратное напряжение
            PORTB |= _BV(LED_K);

            DDRB &= ~_BV(LED_K);            // Катод на вход
            PORTB &= ~(_BV(LED_K) | _BV(LED_K));    // Отклочаем подтяжку

            GIMSK |= _BV(PCIE);            // Разрешаем прерывание по смене состояния PB0
            PCMSK |= _BV(PCINT0);

            light = 0;
            flag = 0;
            sei();
        }
        if(light<255)
        {
            light++;
        }
    }
}
Нужна помощь по коду для AVR (ATTiny85)

не нашел как повторно редактировать свое сообщение, прерывание


ISR(PCINT0_vect) {
	// Отключаем прерываения по смене состояния на INT0
	GIMSK &= ~_BV(PCIE);
	PCMSK &= ~_BV(PCINT0);
	flag = 1;	// Взводим флаг
}
Нужна помощь по коду для AVR (ATTiny85)
volatile uint8_t flag = 1;

ISR(PCINT0_vect) {
	GIMSK &= ~_BV(PCIE);				// Отключаем прерываения по смене состояния
	flag = 1;					// Взводим флаг
}

int main(void)
{
    while (1)
    {
		if(flag){
			flag = 0;
			cli();

			DDRB |= _BV(LED_A) | _BV(LED_K);	// Порты на выход
			PORTB |= _BV(LED_A);			// Моргнуть
			PORTB &= ~_BV(LED_K);
			_delay_ms(10);

			PORTB &= ~_BV(LED_A);			// Подаем обратное напряжение
			PORTB |= _BV(LED_K);

			DDRB &= ~_BV(LED_K);			// Катод на вход
			PORTB &= ~(_BV(LED_K) | _BV(LED_K));	// Отклочаем подтяжку

			GIMSK |= _BV(PCIE);			// Разрешаем прерывание по смене состояния PB0
			PCMSK |= _BV(PCINT0);

			sei();
		}

    }
}
Mini Talon - носитель Fpv
brat002:

Кривые руки. Иначе объяснить сложно.

Может быть и так, но уверяю я написал все проделав большую работу.

brat002:

Даже у новичков летит без каких-либо проблем.

Летит, летит, куда же ему бедному деваться, никто с этим не спорит, но как летит, лучше бы ему висеть на стене, доставляя эстетическое удовольствие.

ehduarg:

Интересно на что поменяли?

на bixler, для скорости есть zephyr.

kostya-tin:

…что у него телон был

модель называется ТАЛОН, талон, таааа…лоооо…нннн, что за неуважение

Свое OSD и проблемы графического video overlay

Большое спасибо за ответы!!!

oleg70:

Для меги8 вся алгоритмика сводится к выводу по строчному синхроимпульсу (int0 у Вас) расчетного количества байт в строку, похоже у Вас уже это работает, в чём тогда вопрос (?)…

Вы не могли бы пояснить по NOP-ам в конце моего поста не совсем понял как правильно их считать (то что у меня работает я подсмотрел в cl-osd) и как грамотно использовать, чтобы четко попадать во время.

oleg70:

У stm32 всё одновременно и сложней и проще, там DMA есть, но куча других нюансов, требующих отдельного разговора…

Скажите в stm32 Вы рисуете задержками или каким-то образом используете SPI? Здесь на форуме видел схему Вашего OSD и изучал конфигурацию stm-а, конечно большого опята нет, у Вас там TIM1,TIM2,TIM9 и SPI1 используется по схеме и судя по точным задержкам таймеров они Вам нужны для отрисовки строк. Интересуюсь чисто алгоритмически.

SPI при таком использовании очень удобен, закинул байт и забыл, но в как быть с обводкой черным (или градацией черного) белого цвета. Меняя направление порта черного цвета (в моем случае DDB0) можно сделать все нулевые биты данным цветом, т.е. получается черный фон, вопрос как сделать именно окаймление черным. На данном форуме читал, что для этого на stm-ах используют SPI1,SPI2 и получается выводят два слоя черный и белый?

На STM32 Вы контролируете вывод каждого пиксела?

Свое OSD и проблемы графического video overlay
emax:

Из за жестких таймингов надо писать не асме, хотя бы формирование одной строки. Си делает много лишнего уходя в прерывание. Не всегда используют SPI можно и регистр крутить и выводить его.

провел эксперемент:

  1. Вывожу в прерывании INT0 (начало новой строки) через SPI следующим образом при размере графики 80x80, т.е. массив screen[10][80]
#define WAIT while(!(SPSR & (1<<SPIF)))
//
for (uint8_t i = 0; i < GRAPHICS_WIDTH; ++i) {
            SPDR = screen[i][currentline];
            WAIT;
        }

80x80 результат
32x32 результат

  1. Все тоже что и в первом эксперименте, не не пользуюсь макрос WAIT, т.е. просто кидаю в регистр SPDR байт и NOP-ами делаю задержки. Какие NOP-ы и где подсмотрел в cl-osd.
for (uint8_t i = 0; i < GRAPHICS_WIDTH; ++i) {
            DELAY_9_NOP();
            SPDR = screen[i][currentline];
            DELAY_9_NOP();
            DELAY_1_NOP();
}
DELAY_10_NOP        ();
DELAY_7_NOP            ();
SPDR = 0x00;

получаю допустимый 80x80 результат
---------- резюме -------------
1 эксперимент своего рода tcp (гарантия проталкивания SPDR), 2 эксперимент второй udp (без гарантии проталкивания SPDR), т.е. гарантия проталкивания SPDR приводит к “конским” задержкам.

Вопрос по теме несколько сужается: как рассчитываются данные NOP-ы? каждый NOP - это NoOPeration один такт, в моем случае 1/16Мгц=62.5us. Длина строки 64us. Таким образом перед внесением в регистр SPDR байта заставляем сделать 9 NOP-ов, т.е. 62.5*9=562.5us и столько же после - почему? Как рассчитать какие NOP-ы использовать? И где их делать - сколько до внесения в SPDR, сколько после, сколько после всей строки?

Свое OSD и проблемы графического video overlay

Пересмотрел много open source кода по OSD, video overlay и пробовал делать по аналогии (часть кода и алгоритм был взят из проекта osxosd) вывод графики через spi интерфейс. Но вывод в spi байта 0b10000000 приводит к отрисовке не небольшого участка - пиксела, а небольшой линии, тоже с задержками какая-то борода.

Конечная цель понять алгоритмику рисования и отрисовывать графику приблизительно как Smalltim, PitLab, Oleg70. Понятно дело что у них используются серьезные камни, но на данном этапе мне хотя бы понять как они это делают, алгоритм скорее всего один.
Может кто знает какие методы у них используются для video overlay? spi? просто порты и задержки?

#define F_CPU 16000000UL // CPU speed

#include <stdlib.h>
#include <stdio.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <stdbool.h>

#include "timings.h"

// swith pin 0 port B
#define NORM DDRB &=~(1<<DDB0)
#define DIM     DDRB |=(1<<DDB0)
// wait SPI transfer
#define WAIT while(!(SPSR & (1<<SPIF)))
// graphic size
#define GRAPHICS_HEIGHT 80
#define GRAPHICS_WIDTH GRAPHICS_HEIGHT/8

// buffer
uint8_t screen[GRAPHICS_WIDTH][GRAPHICS_HEIGHT];
// line counter
static uint16_t line = 1;

void setPixel(uint8_t x, uint8_t y, uint8_t state) {
    uint8_t bitPos = 7-(x%8);
    uint8_t temp = screen[x/8][y];
    if (state == 0) {
        temp &= ~(1<<bitPos);
    }
    else if (state == 1) {
        temp |= (1<<bitPos);
    }
    else {
        temp ^= (1<<bitPos);
    }
    screen[x/8][y] = temp;
}


int main(void)
{
    // set white color to 7 bit on buffer array screen 0,0
    setPixel(0,0,1);
    //
    DDRB  = 0b00111100;    // SPI master output
    PORTB = 0b00000100;    // SS=1
    DDRD  = 0b00000000;    // INT0:1 as input
    DDRC  = 0b00000000;    // PC0 & PC1 as input
    // INT1 on falling; INT0 on any change
    MCUCR = (1<<ISC01) | (1<<ISC11); /* Set interrupt on falling edge             */
    GICR  = (1<<INT0)|(1<<INT1);    // enable INT0:1 interrupts
    // SPI enable | master mode | phase shift | invert polarity
    SPCR =(1<<SPE)|(1<<MSTR)|(1<<CPHA)|(1<<CPOL); // CPOL - ???
    // set interrupt enable
    sei();

    while (1)
    {
    }
}

// VSYNC interrupt
ISR(INT1_vect)
{
    line = 1;
}

// HSYNC interrupt
ISR(INT0_vect)
{
   // reset color
   NORM;

    if ((line >= 60) && (line < (60 + GRAPHICS_HEIGHT))){
        // skip begin pulse
        delay4700ns;
        delay5700ns;
        // dim color
        DIM;
        // speed spi 2x faster
        SPSR = (1<<SPI2X);
        // out current line from screen array
        for (uint8_t i = 0; i < GRAPHICS_WIDTH; ++i) {
            SPDR = screen[i][line-60];
            WAIT;
        }
        // reset color
        NORM;
        SPDR=0x00;
    }
    ++line;
}
Свое OSD и проблемы графического video overlay

Создаю свое OSD (atmega8+кварц16Мгц+lm1881), для себя, или точнее учусь работать с видео и микроконтроллерами. Просмотрел здесь много тем - очень классно у многих получается. По разработке есть вопрос и просто не знаю где найти ответы, перечитано много информации. Парни, подскажите в чем проблема, чувствую что что-то делаю в корне не так. Т.к. используется atmega8 - много не жду, SRAM памяти всего 1024 байт, но все таки возникают проблемы, которые на таком камне решаемы, видел примеры. Подскажите пож-та:

  1. во всех open source OSD вывод текста и графики осуществляется через SPI интерфейс, присваивание регистра SPDR и фактически дерганьем MOSI пина и switch DDR черно-белого пина. SPI интерфейс - это единственное решение? почему все используют SPI - простота или другие причины?
  2. Из нескольких статей Ричарда решил сделать по алгоритму как у него описано, только не создание видео с ноля, а видео оверлей через Lm1881. Полный контроль над выводом, все то что мне нужно, можно замоделить несколько аппаратных градаций черно-белого изображения. Но как раз по данному алгоритму получаются полные грабли. Схема, код и результат ниже. Прерывание работает некорректно, отсчет строк ползет, возможно код в прерывании долго отрабатывает. Теоретически все должно работать, практически полный абзац.

Буду очень благодарен любому направлению, совету.
Спасибо!

Схема:

#define F_CPU 16000000UL // 16 MHz

#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>

#define GRAPHICS_HEIGHT 64
#define GRAPHICS_WIDTH GRAPHICS_HEIGHT/8

#define bit_is_set(sfr,bit) (_SFR_BYTE(sfr) & _BV(bit))

uint8_t screen[GRAPHICS_WIDTH][GRAPHICS_HEIGHT];

uint16_t line = 1; // текущая строка
uint8_t box_line = 50;
uint8_t active_line = 0;
uint8_t bit;

void setPixel(uint8_t x, uint8_t y, uint8_t state) {
    uint8_t bitPos = 7-(x%8);
    uint8_t temp = screen[x/8][y];
    if (state == 0) {
        temp &= ~(1<<bitPos);
    }
    else if (state == 1) {
        temp |= (1<<bitPos);
    }
    else {
        temp ^= (1<<bitPos);
    }
    screen[x/8][y] = temp;
}

int main(void)
{
    setPixel(0,0,1);
    //setPixel(0,63,1);
    //setPixel(63,0,1);
    //setPixel(63,63,1);

    DDRD  &=~(1<<DDD2); // INT0 as input
    DDRD  &=~(1<<DDD3); // INT1 as input
    //
    DDRB  |= (1<<DDB3); // PB3 output MOSI
    PORTB &=~(1<<PB3);

    // enable INT0:1 interrupts
    MCUCR = (1<<ISC00) | (1<<ISC01);
    GICR = (1<<INT0)|(1<<INT1);    /* Enable interrupt for interrupt0            */

    sei(); // set interrupt enable

    while (1)
    {
    }
}

// VSYNC interrupt
ISR(INT1_vect)
{
    line = 1;
}

// HSYNC interrupt
ISR(INT0_vect)
{
    if((line >= 50) && (line < (50+GRAPHICS_HEIGHT))){
        _delay_us(5);

        active_line = line-50;
        //
        for (uint8_t i = 0; i < GRAPHICS_WIDTH; ++i) {
            bit = screen[i][active_line];
            //
            for (uint8_t bitPos = 7; bitPos >= 0; bitPos--) {
                if(bit_is_set(bit, bitPos)){
                    PORTB |= (1<<PB3);
                    //_delay_us(0.1);
                    }else{
                    PORTB &=~(1<<PB3);
                }
            }
        }
    }
    ++line;
}

Текущий результат banned link

Как правильно клеить бумагу на ПВА?

Предстоит оклеивание ЛК бумагой для факсов на клей ПВА. Решил потренироваться на простой конструкции - вырезал и склеил из пены толщиной 20мм коробку. Решил цельным фрагментом бумаги сразу оклеить все боковые стороны, решил что так будет крепче конструкция в результате. Нанес на боковые стенки коробки клей и бумагу и пытался разгладить появившиеся на бумаге мелкие складки, но, к моему сожалению, ничего не вышло. Бумага сильно намокла и ни валик (импровизированный) ни кусок потолочки не позволяют выровнять. Подумал может это клей в складках и при высыхании подтянется, нет все как было с вечера так и осталось.

Пробовал совсем тонким слоем клей наносить, эффект тот же - слушком быстро бумага становиться мелкими волнами, которые разгладить не получается.

Посоветуйте как правильно клеить на пену бумагу на ПВА, чтобы получить идеально гладкую поверхность, ощущение что я что-то совсем не так делаю.
Поискал в нете, в основном это совету по декупажу, нашел один интересный способ - клей наноситься вообще сверху бумаги от центра склейки к краям и пропитывая бумагу клеится
Спасибо.

Создание OSD на базе одноплаточника с linux
Tahorg:

имея полный линукс и мощный проц выводить все текстом … к чему тогда все это? Надо графику, горизонт, спидбар и альтбар, иконки сгнала и направления … перехватывать поток, накладывать графику и т.д.

конечно так и планируется, пока просто алгоритм и инструменты пытаюсь найти. Такой работой ранее не занимался, познакомился с virt2real и посмотрел chiefpilot.ru вот и понеслось…

Создание OSD на базе одноплаточника с linux
Tahorg:

Ок, но тогда вопрос не в gstreamer - Вам надо ДО него влиниться в поток, отдаваемый raspivid.

Я вижу все следующим образом (меня получилось следующая инструкция с штатным good plugin):
gst-launch-1.0 uridecodebin uri=http://192.168.0.15/mjpg/video.mjpg ! cairotextoverlay text=“Привет Мурманск” xpad=500 ypad=500 ! ffmpegcolorspace ! jpegenc ! multipartmux ! tcpserversink port=5000
Расклад:

  1. забираем video поток gst-launch-1.0 uridecodebin uri=http://192.168.0.15/mjpg/video.mjpg
  2. используем плагин textoverlay от pango накладываем текст в позиции x=500,y=500 cairotextoverlay text=“Привет Мурманск” xpad=500 ypad=500
  3. выводим в tcp сокет порт 5000, tcpserversink port=5000
    ----резюме--------
    запустим vlc и откроем видео по url tcp://ip-linux:5000 и увидим видео с ip камеры 192.168.0.15 с текстом Привет Мурманск в позиции 500,500
    ----продолжение----
  4. качаем gst-template
  5. кодим plugin для gstreamer с нанесением osd информации
  6. ставим плагин
    -----используем новый плагин-------
    gst-launch-1.0 uridecodebin uri=http://192.168.0.15/mjpg/video.mjpg ! новый плагин для gstreamer ! tcpserversink port=5000
    -----результат-------
    запустим vlc и откроем видео по url tcp://ip-linux:5000 и увидим видео с ip камеры 192.168.0.15 с osd текстом согласно логике работы плагина
Создание OSD на базе одноплаточника с linux
Tahorg:

Подобная плата избыточна. Достаточно мощности любого STM32F0, хотя на F4, конечно, проще и не сильно дороже. Главная проблема не ГСтример, а сам линукс. Если что - он потребует вермени на перезагрузку. А микроконтроллер готов к бою сразу.

Во-первых - я полностью с Вами согласен, просто не представляю как на STM32 реализовать: беспилотник с APM и камерой + STM32 + съем video stream данных + video overlay данных с АРМ = раздача микшированного видео потока по wifi.
Во-вторых - все эти перезагрузки, вообще глючность и медленность оси, на мой взгляд можно порешать выстроив соответствующую архитектуру работы. Да и на данном этапе для меня это не особо значимо.
В-третьих - немного уточню обсуждаемую тему: создание дублирующей OSD на базе одноплаточника с linux, некий subOSD на борту. Просто сам по себе linux дает разработчику очень большие возможности, которые более отлаженные, чем будет мой код под STM32. Для примера приведу использование opencv на борту, под stm32 КомпьютерВизион я не видел, придется городить свой огород. Задумка состоит не просто в создание OSD

Создание OSD на базе одноплаточника с linux

Добрый день!
В настоящее время собираю информацию для разработки своей OSD на базе linux. Основной вопрос: микширование video потока с текстовыми и графическими данными, причем это должно происходить на борту. Конечный результат - реализации следующей схемы: беспилотник с APM + одноплаточник с камерой + съем video stream данных + video overlay данных с АРМ = раздача микшированного видео потока по wifi.

Ранее я пользовался ffmpeg и его плагинами для создания OSD подобного функционала - забирал поток с ip камеры + drawtext/draw*** + раздача rtp потока. Но там сразу возникла проблема программной реализации плагинов draw***, которую так и не решили с ffmpeg разработчиками и все тогда было заброшено.

После знакомства с virt2real узнал больше gstreamer, спасибо виртурильщикам за свои демо и wiki на сайте. Ранее gstreamer не рассматривал, т.к. попал сразу на негативные отзывы о gstreamer. После virt2real и более детального теста gstreamer пришел к выводу:

  1. gstreamer достаточно глючная не стабильно работающая штука
  2. штатными good плагины gstreamer как мне кажется не собрать полноценной OSD
  3. стоит ли пытаться реализовать свой OSD плагин по gstreamer.freedesktop.org/data/doc/…/html/
  4. чем примерно пользовались парни для разработки OSD chiefpilot.ru
  5. какие еще возможны варианты video overlay в linux

Сейчас все тестирую в ubuntu, которая гнездится в vmware workstation. Ubuntu выбран по причине того, что у него из репозитария идет свежая версия gstreamer и нормально собирается gst-template.

Буду признателен за любую информацию по моим вопросам.
Спасибо.

Как организовать OSD для IP камеры
msv:

Про linux не ведаю, а под виндой- DirectShow. Задачка не самая простая, но имхо вполне решаема.

почитал про DirectShow, я так понял, что в основном он используется для видеозахвата+обработки+воспроизведения/записи. На одном из форумов было обсуждение трансляции видеопотока с помощью фильтра Direct Network, но обсуждение зашло в тупик, задача для DirectShow не типовая.

Dinotron:

Видеопоток отдельно, телеметрия отдельно, причём у телеметрии приоритет. Передаётся хоть по одному каналу, хоть голубиной почтой. Складывается программно на конечном устройстве. Не? Или вы с нечто собрались передавать полностью обработанный видеосигнал по ютубу или торренту? Достойно.

Наверное я неверно объяснил:
Дано:

  1. в локальной сети есть ip камера, которая смотрит на проходную на территорию нашего предприятия (видео с данной камеры доступно, например по адресу 192.168.1.27/mjpg/video.mjpg)
  2. данная проходная снабжена RFID reader-ом и проходя через проходную работники фиксят свой проход карточкой, что пишется в базу предприятия
  3. данная проходная снабжена системой распознавания номеров а/м, распознанные номера также пишутся в базу предприятия
    Задача:
  • захват видео с 192.168.1.27
  • нанесении текстовой информации вида: сколько работников прошло с начала смены, машин проехало, из каких подразделений …
  • организовать видеопоток с телеметрией по адресу 192.168.1.28
    Итого
  • зайдя на 192.168.1.27 смотришь обычное видео, на 192.168.1.28 видео с телеметрией
Как организовать OSD для IP камеры

Подскажите алгоритм, направление по следующему вопросу: в сети есть IP камера, необходимо организовать osd систему, т.е. взять видеопоток с IP камеры, нанести данные датчиков, отдать видеопоток в сеть, т.е. фактически ретрансляция видеопотока с нанесение дополнительных данных (текстовых - гуд, графических - супергуд). Видится два варианта реализации:

  1. программный. Пробовал связку linux+ffmpeg+DrawText filter. К сожалению фильтры ffmpeg работают только при записи в файл: беру поток, накладываю текст+пишу в файл-все ок. При попытке писать на выходе в видеопоток фильтр просто отсутствует. Писал разработчикам , да такой баг существует. Другого программного обеспечения с нужным функционалом не нашел.

  2. аппаратный. немного работал с OSD системой построенной на max7456. Но все osd системы построены на аналоговом сигнале. Как работать с ip камерой: tcp пакеты декодить в аналог пропускать через max и опять кодить в tcp, на первый взгляд только это приходит на ум. Возможно есть аналог max-а для цифровых видеоданных.

Вот здесь примерно то что мне нужно, но как они это сделали не понятно. Буду благодарен за любую информацию.
Спасибо.