roboforum.ru

Технический форум по робототехнике.

Проблема с быстродействием ATmega168

Re: Проблема с быстродействием ATmega168

Michael_K » 22 июл 2011, 22:54

1. Оптимизация тут по большому счету ни при чем. Если компилятор должен что-то знать, а вы ему не говорите - это неоднозначность.
2. Например операция t1 = channel[current_channel]; не атомарная.
3. Ок

4. Что за компилятор?

По сути вот эти ваши "значения скачет" и "условия иногда срабатывает" - это же типичные симптомы.
А фразу "похоже, это глюк компилятора" в 95% случаев нужно понимать как "Я не умею объяснить компилятору, чего я от него хочу".
Последний раз редактировалось Michael_K 22 июл 2011, 22:56, всего редактировалось 1 раз.

Re: Проблема с быстродействием ATmega168

HarryStar » 22 июл 2011, 22:58

Хм... нашел таки как минимум 1 неоднозначность...и посерьезнее, чем неатомарность указанной вами строки. Спасибо, что обратили внимание.
Ща подумаю, как переделать.

Компилятор CVAVR, я писал вначале

Добавлено спустя 1 минуту 46 секунд:
Но кстати, убрав while в майне снимаются все неоднозначности, правда пропадает доп функционал, но фиг с ним, сейчас попробую...

Re: Проблема с быстродействием ATmega168

Michael_K » 22 июл 2011, 22:58

HarryStar писал(а):Хм... нашел таки как минимум 1 неоднозначность...и посерьезнее, чем неатомарность указанной вами строки. Спасибо, что обратили внимание.


Ну :pardon: Сами понимаете - отлаживать чужой код, глядя в текст - занятие неблагодарное.
Рад, что хоть так неделикатно натолкнул на мысль :)

Re: Проблема с быстродействием ATmega168

HarryStar » 22 июл 2011, 23:15

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

Например если в обработчике сделать так
if(PIND & 0b01000000)
{
channel_start[2] = t; // Старт импульса
channel_end[1] = t; // Стоп импульса
channel[1] = channel_end[1] - channel_start[1];
if(channel[1]>1995) channel[1] = 1995; // ПРОБЛЕМНОЕ МЕСТО
return;
}
if(PIND & 0b00100000)
{
channel_start[3] = t; // Старт импульса
channel_end[2] = t; // Стоп импульса
channel[2] = channel_end[2] - channel_start[2];
return;
}
То один канал где нет проверки будет нормально работать, а где есть значение будет скакать от текущего к максимуму. :(
Буду копать дальше, но пока вообще не понятно почему так происходит. Причем число можно поставить любое, например if(channel[1]>65000) channel[1] = 1995; результат тот же. Это условие иногда срабатывает, хотя это невозможно.

Re: Проблема с быстродействием ATmega168

dccharacter » 22 июл 2011, 23:25

Michael_K, я, конечно, преклоняюсь, но нифига не понял :-((((
Harry Star, если ты убрал тот самый цикл, то в конце программы происходит ресет - естественно там все скачет.

Добавлено спустя 5 минут 48 секунд:
Слуш, я так и не увидел переменных channel[] и current_channel, зато увидел, что ты смотришь результат через i2c. Ну так я тебе 102% вероятности даю, что у тебя глюк в i2c.

Re: Проблема с быстродействием ATmega168

HarryStar » 22 июл 2011, 23:35

Если вы намекаете на while(1); в конце программы, то у меня он есть и я это писал, читайте внимательнее. Никакого ресета не происходит.
I2C совершенно не причем, хотя результат я смотрю через него, да.

После некоторых экспериментов я выяснил, что такое происходит когда значение таймера переходит 0xFFFF между измерениями.
Например:
channel_1_start = 65000; // Время старта импульса
channel_1_end = 700; // Время окончания импульса

Должно получится в беззнаковом варианте channel_1 = 700 - 65000 = 1235
А получается что условие channel_1 > 1995 истинно

Re: Проблема с быстродействием ATmega168

Michael_K » 22 июл 2011, 23:41

Да, непонятно...

А вы точно, сто процентов уверены, что прерывание только один раз срабатывает при переходе от одного импулься к следующему?... Я бы, честно, на это не особо расчитывал. Так в жизни не бывает - два строго одновременных события.

Добавлено спустя 4 минуты 32 секунды:
HarryStar писал(а):Должно получится в беззнаковом варианте channel_1 = 700 - 65000 = 1235
А получается что условие channel_1 > 1995 истинно

Ага. Только вы таймер в начале прерывания масштабируете.
Тогда нужно маску накладывать после вычитания. На четыре старших бита, если я правильно понимаю смысл.
Последний раз редактировалось Michael_K 22 июл 2011, 23:44, всего редактировалось 2 раз(а).

Re: Проблема с быстродействием ATmega168

HarryStar » 22 июл 2011, 23:42

Ну так как условие прерывания any change, то прерывание срабатывает когда импульс заканчивается, а потом еще раз, когда следующий стартует. Разница по времени между ними = времени выполнения обработчика, этим можно пренебречь. В условиях же я отлавливаю только начала импульсов.

Большинство китайских передатчиков выдают сервоимпульсы именно последовательно, но например futaba стартует все импульсы одновременно, там пришлось бы алгоритм посложнее писать, но я делал под свои приемники, там именно так.

В принципе можно от этого перехода избавится, если на старте первого импульса обнулять показания таймера. Тогда 8й импульс заканчивается до 0xFFFF и перехода не происходит. Но все равно непонятно почему так получается.

Re: Проблема с быстродействием ATmega168

=DeaD= » 22 июл 2011, 23:43

Если есть уарт - попробуйте просто вывести result из вот такого:

t1=1995;
t1 = (t1-975)/4;
unsigned char result = (unsigned char)t1;

Re: Проблема с быстродействием ATmega168

Michael_K » 22 июл 2011, 23:43

чуть выше дописал.

Re: Проблема с быстродействием ATmega168

HarryStar » 22 июл 2011, 23:45

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

2 Деад: Уарта нет, прведенный вами пример работает корректно, выдает 255

Re: Проблема с быстродействием ATmega168

Michael_K » 23 июл 2011, 00:01

надо надо.

Вот у вас таймер = 0xFFF0
t = 0x0FFF Start = 0x0FFF

Потом таймер равен, допустим, 0x0010
t = 0x0001 Stop = 0x0001

Вычитаем Stop - Start = 0x0001 - 0x0FFF = ?
Типа должно два получится? А получается 0xF002 (!) почему-то.

Если таймеры вычитать без масштабирования, то все правильно:
0x0010 - 0xFFF0 = 0x0020

Добавлено спустя 33 секунды:
HarryStar писал(а):чтоб нагляднее было

Фигассе :)

Добавлено спустя 10 минут 25 секунд:
HarryStar писал(а):В условиях же я отлавливаю только начала импульсов.

Это ошибка. Вы в условиях проверяете состояния порта в момент любого изменения на любой ноге. Это вовсе не "я отлавливаю начала импульсов".

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

Но причина скачков - это масштабирование таймера, как я писал выше.
Последний раз редактировалось Michael_K 23 июл 2011, 00:17, всего редактировалось 1 раз.

Re: Проблема с быстродействием ATmega168

HarryStar » 23 июл 2011, 00:16

Про таймер совершенно точно! Огромное спасибо. Делал чтоб значения были в микросекундах, а что переход через ноль получается неправильный даже не сообразил. Тогда надо сначала вычитать, а потом масштабировать.

Про импульсы. В любой момент времени на ножках либо 0 на всех, либо 1 на каком-то одном. Другого варианта там нет, я все честно промерил осциллографом. Поэтому когда я отлавливаю 1 в каком то бите - это именно старт импульса. На конкретно этом приемнике это так. Метод не универсальный конечно, но пока так оставлю, т.к. других приемников у меня нет. Есть 5 штук разных и все так работают.

Re: Проблема с быстродействием ATmega168

Michael_K » 23 июл 2011, 00:21

Я бы, несмотря на это, ужесточил условия.
Например так
if (PORTD == 0b00100000)

Тогда неоднозначностей не будет (кроме последнего условия, но оно не повлияет на результат).

Мало-ли, может быть у вас фронты завалятся - они это запросто сделают при первом же удобном случае (Например, из-за длины проводов, их индуктивности, паразитных емкостей, сопротивления контактов, разницы в питании - из-за чего угодно).
Последний раз редактировалось Michael_K 23 июл 2011, 00:24, всего редактировалось 1 раз.

Re: Проблема с быстродействием ATmega168

HarryStar » 23 июл 2011, 00:24

Ну в принципе да, можно тогда все в switch запихать. Еще раз спасибо за помощь.
Завтра выложу видео с этим модулем, сейчас уже темно снимать.


Rambler\'s Top100 Mail.ru counter