Page 1 of 2
Алгоритм обработки АЦП ДАД
Posted: Wed Dec 14, 2011 8:34 pm
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 и приводим тип
}
Re: Алгоритм обработки АЦП ДАД
Posted: Wed Dec 14, 2011 9:53 pm
by STC
Используй нормальное деление (дели на 120). Процессор ARM Cortex M3 выполняет 32-х битное деление за 1 такт. Можно делить как угодно и на что угодно.
Re: Алгоритм обработки АЦП ДАД
Posted: Wed Dec 14, 2011 10:43 pm
by nikll
хм, немогу найти подтверждение этой информации, нашел только что умножение 32х32 за один такт, деление 2-7 тактов...
Re: Алгоритм обработки АЦП ДАД
Posted: Wed Dec 14, 2011 11:37 pm
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
Re: Алгоритм обработки АЦП ДАД
Posted: Thu Dec 15, 2011 12:27 am
by nikll
просто вся суть в том что отклонение линейное и не зависит от частоты и амплитуды, достаточно полученное значение умножить на (128/120) и мы получим истенное усредненное значение АЦП, вот только зачем нам оно? всеравно значение АЦП надо приводить к давлению через смещщение и наклон характеристики ДАД, прощще в прошивку заносить параметры дад разделенные на (128/120) чем в каждом цикле терять семь тактов... Я понимаю что stm32 кажется сверхмощным безграничным МК

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

))
Re: Алгоритм обработки АЦП ДАД
Posted: Thu Dec 15, 2011 12:48 am
by STC
Игра не стоит свеч. Применим, скажем другой шкив и нужно будет усреднять, скажем 60 раз за оборот и константа 128/120 все равно не подойдет.
Не усложняй жизнь такими вещами. Усреднение ДАД будет происходить в основном цикле (в прерываниях такие вещи лучше не делать), а для него лишние 7 тактов погоды не сделают.
Тем более вспомни как говорят: "Излишняя оптимизация на раннем этапе не есть хорошо".
Re: Алгоритм обработки АЦП ДАД
Posted: Thu Dec 15, 2011 1:08 am
by nikll
Надо именно в прерывании запускать АЦП, ждать результат не надо, можно через прерывание АЦП данные в таблицу сохранять, думаю еще DMA покурить, есть подозрения что можно пошагово отрабатывать данные из АЦП в таблицу по средствам DMA.
В основном цикле дергать АЦП синхронно с положением коленвала? Как??? через условные флаг который взводить в прерывании и обрабатывать основном цикле? получится неконролируемый разброс по времени, и тем он больше будет чем реже этот флаг будет проверятся в основном цикле, вплоть до пропусков при больших обротах.
Можно конечно скрестить АЦП с DMA через таймер и рулить таймером согласно времени ДПКВ но там еще сложней все получается да и по ресурсам затратней.
Вот именно что излишняя

, тут ее нету, вот если развернуть циклы убрать функции и впихать все стопкой кода прямо в обработчик прерывания вот тогда да получится пресловутое "преждевременная оптимизация".
60-2 является стандартом, практически де-факто, для изменения диска ДПКВ достаточно поменять две константы в прошивке (размер таблицы и делитель) и одну в менеждере (та самая 128/120)
К примеру требуется обрабатывать диск ДПКВ 12-2: соответсвенно получается за оброт кв 28 прерываний, оптимальным делителем будет 32 (сдвиг на 5), в менеджер соответсвенно впишем 32/28, все банально.
Re: Алгоритм обработки АЦП ДАД
Posted: Thu Dec 15, 2011 2:07 am
by STC
В прерывании только заполнять кольцевой буфер, а усреднять в основном цикле.
Re: Алгоритм обработки АЦП ДАД
Posted: Thu Dec 15, 2011 2:15 am
by nikll
Да естественно

.
Расчет наполнения будет происходить в основном цикле, перед расчетом наполнения брать темпиратуру воздуха и усреднять дад, ДТОЖ врятли стоит брать в каждом цикле, вполне достаточно в одном из таймеров к примеру раз в секунду или когда удобней.
Re: Алгоритм обработки АЦП ДАД
Posted: Thu Dec 15, 2011 5:09 am
by nikll
в общем разобрался, полная схема следующщая:
1. инициализируем АЦП (настройки, автокалибровка и прочая при запуске МК), вешаем прерывание по окончанию преобразования.
2. в прерывании ДПКВ запускаем преобразование АЦП
3. в прерывании АЦП вызываем add_map(uint16_t adc) для записи данных в таблицу.
Прерывания в stm32 работают с минимальными накладными расходами, однако АЦП при нормальном качестве распознования работает 239,5 циклов + 12,5 циклов это не мало, на частоте АЦП (12мгц) это 21мкс что при частоте ядра равняется ~1512 тактам. Накладные расходы на прерывание несколько тактов, поэтому такой подход актуален.