Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Тахометр на AVR
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
ivainc1789
Есть необходимость сделать автомобильный тахометр 300...6000 об/мин. Для этого в программе организован буфер unsigned int TaxBuf[BufSize], написана п/программы взятия отсчета, сдвига буфера, вычисления результата как среднего арифметического содержимого буфера. Т. е. наблюдаются последние BufSize отсчетов. Проблема в том, что данные о текущей частоте вращения необходимо выводить на LCD с "точностью" до +-1 об/мин. Понятно, что на самом деле такая точность не нужна, а отображать на дисплее практически невозможно - цифры "скачут", считать показания затруднительно.
Хотелось бы написать алгоритм аналога стрелки обычного микроамперметра стрелочных тахометров. При этом неравномерность вращения коленвала на холостых оборотах в соседних отсчетах может достигать +-50 об/мин.
Помогите с идеей такого алгоритма для AVR...
_sR_
Цитата(ivainc1789 @ Sep 1 2005, 21:22)
Хотелось бы написать алгоритм аналога стрелки обычного микроамперметра стрелочных тахометров. При этом неравномерность вращения коленвала на холостых оборотах в соседних отсчетах может достигать +-50 об/мин.
*

мне кажется что:
1. стрелка обычного микроамперметра не дает возможность считывать показания с точностью до +-1 об/мин, следовательно, можно округлять до "нужных" цифр (ну не нравится младший 0 - берите единицы от последнего результата smile.gif )
2. частвительность стрелочного прибора так же ниже чем цифрового

поэтому я бы начал с округления и может поигрался с интервалом интегрирования

P.S. возможно что неравномерность врашения на не холостых оборотах будет отличаться
yung
Стрелочный амперметр представляет собой интегратор с большой постоянной времени и низкой разрешающей способностью (даже +-50 оборотов на тахометре практически не видны). Честный быстрый прибор не для наших автомобилей smile.gif. Отсюда вывод: если как стрелочный - то выдавать результат в сотнях оборотов, а не в единицах, плюс увеличить размерность буфера. И неплохо бы этот буфер перед суммированием пропустить через какой-либо математический фильтр (медианный или еще какой).
CDT
В программе Sonic Foundry Sound Forge есть линейный индикатор уровня выходного сигнала.
Когда сигнал резко падает, на месте старого значения на некоторое время остается полоска, отмечающая пик.
В Вашем случае я бы интегрировал до удобочитаемого уровня значения основного индикатора и добавил бы разряды (только младшие), индицирующие максимальные и минимальные значения за время интегрирования. Можно в виде отклонения (+,-).
Это может быть специальный режим индикации.
Тогда будет видно среднее значение, и в каких пределах оно прыгает.
BVU
Да просто вычисляйте среднее значение своих измерений и ничего мудрить не надо. Я делал такие вещи, на практике достаточно брать пять значений что бы получить хорошее сглаживание:
Aср = (a'1 + a'2 + a'3 + a'4 + a'5) / 5.
А интервал показаний установите кратный двум или пяти, тогда и цыфорки скакать не будут!
Я так понял, что Вы пересчитываете импульсы с датчика Холла перемноженного на некий коэффициент?
bzx
BVU сделал вполне уместное замечание. Надо увеличить интервал показаний между измерениями.

По поводу сглаживания показаний. В реализации проще будет БИХ фильтр первого порядка. АЧХ что у этого фильтра, что у сглаживания по 5ти отсчётам, с небольшой натяжкой, одинаковые.

Yn = Yn-1 + N*(Xn - Yn-1)
где N положительное число, меньшее 1, определяющее частоту среза фильтра (степень сглаживания). Его лучше брать кратным степени 2, N=2^(-m), т.е. эту операцию можно реализовать в МК простым сдвигом

Код
////////////////////////////////////////////////////////////////////////
//
// Альфа фильтр
// БИХ фильтр первого порядка
//
void alfa(unsigned int *hXn, unsigned int *hYn, unsigned int *hYn1)
{
    *hYn = (unsigned int)((signed int)*hYn1+(((signed int)*hXn-(signed int)*hYn1)>>1));
    *hYn1 = *hYn;
}
ivainc1789
Цитата(BVU @ Sep 2 2005, 08:16)
Да просто вычисляйте среднее значение своих измерений и ничего мудрить не надо.  Я делал такие вещи, на практике достаточно брать пять значений что бы получить хорошее сглаживание:
Aср = (a'1 + a'2 + a'3 + a'4 + a'5) / 5.
А интервал показаний установите кратный двум или пяти, тогда и цифорки скакать не будут!
Я так понял, что Вы пересчитываете импульсы с датчика Холла перемноженного на некий коэффициент?
*


Большое спасибо всем ответившим. В настоящий момент работает вот такой алгоритм соотв. подпрограммы:
/********************************************************************************
****/
// программа расчета N, N[об/мин] = (30*Fbq)/(T1Div*TTAX)
void GetTaxData() {
unsigned char i,SkoSummaPlusCnt=0,SkoSummaMinusCnt=0;
unsigned int DatMin,DatMax,DatNew;
unsigned long DatSumma=0,SkoSummaPlus=0,SkoSummaMinus=0;
float Sko;

// если новые данные готовы,разрешить их обработку
if (TaxNew != 0) {
// безопасное быстрое копирование обновленного буфера для обработки
CLRBIT(GICR,INT1); // запретить изменение буфера
for (i=0;i<TaxBufSize;i++) DatBuf[i] = TaxBuf[i];
DatNew = TaxNew;
SETBIT(GICR,INT1); // разрешить изменение буфера

// если новый отсчет как старые,принять старые значения
// иначе,полный перерасчет с учетом нового отсчета
DatMin = DatSr - DatMinus;
DatMax = DatSr + DatPlus;
if ((DatNew < DatMin) || (DatNew > DatMax)) {

// перерасчет среднего значения в DatBuf[]
for (i=0;i<TaxBufSize;i++) DatSumma += DatBuf[i];
DatSr = DatSumma / TaxBufSize;

// среднеквадратическое отклонение вверх и вниз
for (i=0;i<TaxBufSize;i++) {
if (DatBuf[i] > DatSr) {
SkoSummaPlus += (DatBuf[i] - DatSr)*(DatBuf[i] - DatSr);
SkoSummaPlusCnt++;
}
if (DatBuf[i] < DatSr) {
SkoSummaMinus += (DatSr - DatBuf[i])*(DatSr - DatBuf[i]);
SkoSummaMinusCnt++;
}
}
Sko = sqrt((SkoSummaPlus+SkoSummaMinus)/(SkoSummaPlusCnt+SkoSummaMinusCnt-1));
DatPlus = Sko + 1;
DatMinus = Sko + 1;

// получение и отображение N
if ((DatSr > 0) && (DatSr < 0xFFFF)) {
TaxResult = Const/DatSr;// unsigned long __flash Const = 30*Fbq/T1Div;
TaxSko = TaxResult - Const/(DatSr+DatPlus);
}
}
TaxNew = 0;// запретить повторную обработку отсчета
}
}
/********************************************************************************
****/
И все же с приходом нового "нетипового" отсчета содержимое TaxResult изменяется весьма значительно, что вообще говоря ожидаемо - этот алгоритм несовершенен и задачу сглаживания не решает.

Если просто считать среднее от пяти значений, то:
"...А интервал показаний установите кратный двум или пяти, тогда и цифорки скакать не будут!..."
Никак в толк не возьму, почему? Отсчеты поступают непериодично (движок ведь работает неравномерно). Вы предлагаете обновлять показания на индикаторе только в моменты, когда полностью обновится пятиэлементный буфер?

Статистика: прогретый движок Москвича-2140 по вышеприведенному алгоритму показал среднюю неравномерность вращения коленвала около 100 об/мин.
yung
Медианный фильтр. Смысл - все элементы массива упорядочиваются по возрастанию. За результат берется элемент из середины массива. Рабочая процедура:

//Медианный фильтр размерностью glub
float MED_FILTR(char glub,float *mass)
{

for (ab=0;ab<glub;ab++) {massw[ab]=mass[ab];} // копируем в рабочий массив

for(ab=0;ab<(glub-1);ab++)
{
for(aa=(ab+1);aa<(glub);aa++)
{
if (massw[ab]<massw[aa])
{
BNM=massw[ab];
massw[ab]=massw[aa];
massw[aa]=BNM;
}
}
} // в массиве massw элементы расположены по возрастанию
aa=glub/2;
return massw[aa]; // Результат
}

Обязательно создавать отдельный массив и упорядочивать в нем. Если делать в исходном, то показания обновляться вообще не будут. После этого можно сделать еще усреднение по нескольким результатам.
lolikandr
Для того, чтобы получить фиксированную величину неравномерность получаемых значений, необходимо иметь фиксированную длину буфера. Ждать когда заполнится буфер - несерьезно. Буфер надо организовать кольцевой и усреднять его в необходимые моменты времени для индикации.
Правда такой подход будет работать с инерционностью равной времени заполнения буфера.
ivainc1789
После серии экспериментов удалось прийти к следующим выводам:
1. Применение только программных ФНЧ с дополнительным последующим усреднением последних 16 отсчетов буфера недостаточно для нормального отображения данных пользователю. Как не подстраивай постоянную времени фильтра, результат будет или сильно запаздывать, или цифры "бегать". Можно было бы попытаться сделать постоянную времени адаптивной на основе выходных данных ФНЧ, но мне не показалось, что это перспективный путь...
2. Наверное единственное решение - "загрублять" показания перед выводом на LCD. Вычислять среднее значение последних n отсчетов и определять текущие допуски вверх и вниз для этих отсчетов. Допустим, после такой обработки получены данные: 1000 об/мин +10 об/мин -20 об/мин. На дисплей выводим 1000 об/мин. Каждый новый отсчет записывается в буфер и проверяется на значение в допуске 980...1020 об/мин. Если значение в допуске, на индикаторе сохраняется показание 1000 об/мин., иначе содержимое буфера с записанным новым отсчетом перерассчитывается и получаются новые среднее значение и новые допуски. Таким образом, если приходит новый "похожий" на предыдущие отсчет, это не требует изменения показаний LCD.
3. Сами допуски я рассчитывал как среднеквадратическое отклонение от среднего для всех отсчетов больших среднего и соотв. меньших. Можно было бы вообще за допуск "вверх" и "вниз" от среднего брать величину самого большого по величине отсчета, но это ведь не учитывает статистику других отсчетов буфера...
4. Хотя во внутреннем представлении микроконтроллера результат тахометра все равно изменяется часто, на LCD выводим три раза в секунду.

В принципе после всего этого, удалось получить приемлемую работу прибора. Но достичь иллюзии поведения стрелочного тахометра в части отображения при максимальной достоверности показаний полностью не удалось...
lolikandr
Странно, что вообще есть большие отклонения. С какой точностью измеряется длительность одного оборота?
BVU
Цитата(ivainc1789 @ Sep 5 2005, 23:07)
4. Хотя во внутреннем представлении микроконтроллера результат тахометра все равно изменяется часто, на LCD выводим три раза в секунду.

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


Частоты вывода 3-раза в секунду - недостаточно!!! Вы 'проглатываете' много промежуточных значений (которые также создают эффект линиаризации). Вывод должен быть в три раза чаще (8 - 12 раз в секунду).
А при усреднении равномерность у Вас такая же, как и у стрелочника (однозначно). Просто работает психо-визуальный эффект восприятия нестандартной информации.
ivainc1789
Цитата(lolikandr @ Sep 7 2005, 17:48)
Странно, что вообще есть большие отклонения. С какой точностью измеряется длительность одного оборота?
*


ATMEGA8, кварц 4MHz, таким образом, N[об.мин]=Const/Timer1value , где
Const = 1875000;
Timer1value - период сигнала датчика Холла в ед. счета, прескалер = 64;

Два варианта - либо в буфер совать готовые предвычисленные отсчеты N, или
отсчеты Timer1value. На вопрос, что правильнее писать в буфер ответить
затрудняюсь, мне кажется это непринципиально, поэтому пишу Timer1value для
исключения потерь на округлении, хотя такая точность наверно все равно не
нужна.

Далее надо обработать буфер с Timer1value отсчетами, найти приемлемое
значение для целей индикации на LCD в формате "ХХХХ об/мин." и вычислить
окончательное N по вышеуказанной формуле.
ivainc1789
[quote=BVU,Sep 7 2005, 18:00]
[quote=ivainc1789,Sep 5 2005, 23:07]
Частоты вывода 3-раза в секунду - недостаточно!!! Вы 'проглатываете' много промежуточных значений (которые также создают эффект линиаризации). Вывод должен быть в три раза чаще (8 - 12 раз в секунду).
А при усреднении равномерность у Вас такая же, как и у стрелочника (однозначно). Просто работает психо-визуальный эффект восприятия нестандартной информации.
*

[/quote]

Индикация - абсолютно отдельный постпроцесс. Ведь в любом случае анализируются последние n отсчетов буфера, они обрабатываются, вычисляется окончательно N (на текущий момент!!!), а выводится уже когда нужно, т. е. 1 раз в 300ms. Поэтому вся возможная статистика полностью учитывается. В настоящий момент в буфере 32 последних отсчета. Вопрос только в том, как правильно обработать эти отсчеты в конкретике поставленной задачи. С моей точки зрения, метод допусков - одно из нескольких верных решений, т. к. учитывает разную неравномерность вращения разных двигателей.

Прилагаю неплохо себя зарекомендовавшую подпрограмму обработки буфера.
Айский
Все-таки читаемость аналоговых индикаторов гораздо выше, цем цифровых. Я бы выводил данные в виде линейной шкалы, 64 сегмента вроде бы обеспечивают точность +-10 об/мин, в то же время "дрожание" конца шкалы не мешает воспринимать информацию. Впрочем можно и применить алгоритмы сглаживания для более красивой визуализации.
white.wind
А может быть использовать пишалку или светодид мигающий пропорционально скорости нарастания сигнала. Или даже один из сегментов ЖКИ. Тогда можно будет чувствовать не хуже, а может и лучше аналогового индикатора.
vooon
Кстати зря отметаете стрелочный индикатор
только сделанный на основе шагового двигателя,
а не миллиамперметра.

на многих иномарах так и сделали

и вибрации авто не влияют на показания.

можно и светодиодную полоску - как в "Формуле" biggrin.gif
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2024 Invision Power Services, Inc.