Алгоритм обработки АЦП ДАД

Разработка впрыска топлива на базе SECU-3. Fuel injection related discussion.

Moderator: STC

nikll
LQFP144 - On Top Of The Game
Posts: 553
Joined: Sun Nov 06, 2011 9:20 pm
Location: Russia, Yekaterinburg
Contact:

Алгоритм обработки АЦП ДАД

Post by nikll »

Делаем 120 выборок из ацп за оборот кв (в прерываниях ДПКВ), результат каждой выборки складываем в таблицу (кольцевой буфер).
Полученный усредненный результат будет на ~6% меньше фактического т.к. мы делим на 128 вместо 120
На вскидку код получается вот такой:

map.h

Code: Select all

typedef struct {
	uint16_t buffer[120];
	uint16_t *cursor;
}map_t;

map_t map;
#define MAP_START	&map.buffer[0]
#define MAP_END		&map.buffer[119]
for (map.cursor = MAP_START; map.cursor <= MAP_END; map.cursor++) *map.cursor = 0xFFF;	// забиваем в таблицу по дефолту атмосферное давление

map.c

Code: Select all

#include <map.h>

void add_map(uint16_t adc) {
	if (map.cursor == MAP_END)
		map.cursor = MAP_START;
	else	map.cursor++;

	*map.cursor = adc;
}

// Целочислительный алгоритм усреднения без деления:
// в цилке, начиная от текущщей ячейки буфера, выбираем и складываем их вместе, делаем сдвиг >> 16 для деления и отброса дробной части, примерный код:
uint16_t get_avg_map() {
	uint16_t *tmp_cursor;
	uint32_t result;

	// начинаем от текущщей ячейки включительно и до конца таблицы
	for (tmp_cursor = map.cursor; tmp_cursor <= MAP_END; tmp_cursor++) result += *tmp_cursor;

	// продолжаем от начала таблицы и до текущщей ячейки
	for (tmp_cursor = MAP_START; tmp_cursor < map_buffer_cursor; tmp_cursor++) result += *tmp_cursor;

	return ((uint16_t)(result >> 7)); // делим на 128 и приводим тип
}
User avatar
STC
LQFP144 - On Top Of The Game
Posts: 2420
Joined: Fri Oct 22, 2010 10:47 pm
Location: Ukraine, Kiev
Contact:

Re: Алгоритм обработки АЦП ДАД

Post by STC »

Используй нормальное деление (дели на 120). Процессор ARM Cortex M3 выполняет 32-х битное деление за 1 такт. Можно делить как угодно и на что угодно.
Author of the SECU-3 project. SECU-3 Engine control unit / Ignition control system
SECU-3.org (Русский)
SECU-3.org (English)
SECU-3 Club ВКонтакте
SECU-3 EMS Project Facebook
nikll
LQFP144 - On Top Of The Game
Posts: 553
Joined: Sun Nov 06, 2011 9:20 pm
Location: Russia, Yekaterinburg
Contact:

Re: Алгоритм обработки АЦП ДАД

Post by nikll »

хм, немогу найти подтверждение этой информации, нашел только что умножение 32х32 за один такт, деление 2-7 тактов...
User avatar
STC
LQFP144 - On Top Of The Game
Posts: 2420
Joined: Fri Oct 22, 2010 10:47 pm
Location: Ukraine, Kiev
Contact:

Re: Алгоритм обработки АЦП ДАД

Post by STC »

На титульной странице даташита написано что "hardware division", дальше я не смотрел. Даже если 2-7 тактов, то заморачиваться не стоит.
Кроме этого, если нужно разделить на константу, то деление можно заменить умножением на так тазываемое обратное число. Данная техника будет применимой в случае, если система команд процессора позволяет умножить два 32-х разрядных числа и получить 64-х разрядное. ARM вроде умеет такое. Подробнее про "магические" числа можно почитать в книге Генри Уоррена "Алгоритмические трюки для программистов", изд. Вильямс. Это русский перевод. На английском название данной книжки звучит круче - "Hacker's Delight". Можно посетить сайт http://www.hackersdelight.org/
http://www.hackersdelight.org/magic.htm

Так выглядит: http://www.rsdn.ru/res/book/prog/worren.xml
Author of the SECU-3 project. SECU-3 Engine control unit / Ignition control system
SECU-3.org (Русский)
SECU-3.org (English)
SECU-3 Club ВКонтакте
SECU-3 EMS Project Facebook
nikll
LQFP144 - On Top Of The Game
Posts: 553
Joined: Sun Nov 06, 2011 9:20 pm
Location: Russia, Yekaterinburg
Contact:

Re: Алгоритм обработки АЦП ДАД

Post by nikll »

просто вся суть в том что отклонение линейное и не зависит от частоты и амплитуды, достаточно полученное значение умножить на (128/120) и мы получим истенное усредненное значение АЦП, вот только зачем нам оно? всеравно значение АЦП надо приводить к давлению через смещщение и наклон характеристики ДАД, прощще в прошивку заносить параметры дад разделенные на (128/120) чем в каждом цикле терять семь тактов... Я понимаю что stm32 кажется сверхмощным безграничным МК :) но как показывает практика минимальная оптимизация без ухудшения параметров системы никога не бывает избыточной, зато ресурсов железа никогда не бывает много бывает только иногда достаточно :)))
User avatar
STC
LQFP144 - On Top Of The Game
Posts: 2420
Joined: Fri Oct 22, 2010 10:47 pm
Location: Ukraine, Kiev
Contact:

Re: Алгоритм обработки АЦП ДАД

Post by STC »

Игра не стоит свеч. Применим, скажем другой шкив и нужно будет усреднять, скажем 60 раз за оборот и константа 128/120 все равно не подойдет.
Не усложняй жизнь такими вещами. Усреднение ДАД будет происходить в основном цикле (в прерываниях такие вещи лучше не делать), а для него лишние 7 тактов погоды не сделают.

Тем более вспомни как говорят: "Излишняя оптимизация на раннем этапе не есть хорошо".
Author of the SECU-3 project. SECU-3 Engine control unit / Ignition control system
SECU-3.org (Русский)
SECU-3.org (English)
SECU-3 Club ВКонтакте
SECU-3 EMS Project Facebook
nikll
LQFP144 - On Top Of The Game
Posts: 553
Joined: Sun Nov 06, 2011 9:20 pm
Location: Russia, Yekaterinburg
Contact:

Re: Алгоритм обработки АЦП ДАД

Post by nikll »

Надо именно в прерывании запускать АЦП, ждать результат не надо, можно через прерывание АЦП данные в таблицу сохранять, думаю еще DMA покурить, есть подозрения что можно пошагово отрабатывать данные из АЦП в таблицу по средствам DMA.
В основном цикле дергать АЦП синхронно с положением коленвала? Как??? через условные флаг который взводить в прерывании и обрабатывать основном цикле? получится неконролируемый разброс по времени, и тем он больше будет чем реже этот флаг будет проверятся в основном цикле, вплоть до пропусков при больших обротах.

Можно конечно скрестить АЦП с DMA через таймер и рулить таймером согласно времени ДПКВ но там еще сложней все получается да и по ресурсам затратней.
Вот именно что излишняя :), тут ее нету, вот если развернуть циклы убрать функции и впихать все стопкой кода прямо в обработчик прерывания вот тогда да получится пресловутое "преждевременная оптимизация".

60-2 является стандартом, практически де-факто, для изменения диска ДПКВ достаточно поменять две константы в прошивке (размер таблицы и делитель) и одну в менеждере (та самая 128/120)
К примеру требуется обрабатывать диск ДПКВ 12-2: соответсвенно получается за оброт кв 28 прерываний, оптимальным делителем будет 32 (сдвиг на 5), в менеджер соответсвенно впишем 32/28, все банально.
User avatar
STC
LQFP144 - On Top Of The Game
Posts: 2420
Joined: Fri Oct 22, 2010 10:47 pm
Location: Ukraine, Kiev
Contact:

Re: Алгоритм обработки АЦП ДАД

Post by STC »

В прерывании только заполнять кольцевой буфер, а усреднять в основном цикле.
Author of the SECU-3 project. SECU-3 Engine control unit / Ignition control system
SECU-3.org (Русский)
SECU-3.org (English)
SECU-3 Club ВКонтакте
SECU-3 EMS Project Facebook
nikll
LQFP144 - On Top Of The Game
Posts: 553
Joined: Sun Nov 06, 2011 9:20 pm
Location: Russia, Yekaterinburg
Contact:

Re: Алгоритм обработки АЦП ДАД

Post by nikll »

Да естественно :).
Расчет наполнения будет происходить в основном цикле, перед расчетом наполнения брать темпиратуру воздуха и усреднять дад, ДТОЖ врятли стоит брать в каждом цикле, вполне достаточно в одном из таймеров к примеру раз в секунду или когда удобней.
nikll
LQFP144 - On Top Of The Game
Posts: 553
Joined: Sun Nov 06, 2011 9:20 pm
Location: Russia, Yekaterinburg
Contact:

Re: Алгоритм обработки АЦП ДАД

Post by nikll »

в общем разобрался, полная схема следующщая:
1. инициализируем АЦП (настройки, автокалибровка и прочая при запуске МК), вешаем прерывание по окончанию преобразования.
2. в прерывании ДПКВ запускаем преобразование АЦП
3. в прерывании АЦП вызываем add_map(uint16_t adc) для записи данных в таблицу.

Прерывания в stm32 работают с минимальными накладными расходами, однако АЦП при нормальном качестве распознования работает 239,5 циклов + 12,5 циклов это не мало, на частоте АЦП (12мгц) это 21мкс что при частоте ядра равняется ~1512 тактам. Накладные расходы на прерывание несколько тактов, поэтому такой подход актуален.
Post Reply