[an error occurred while processing this directive]
Пожалуйста. Справедливости ради нужно сказать, что ЭТО выкладывал посетитель с ником cout, за что ему и от меня сенкс.(+)
(«Телесистемы»: Конференция «Микроконтроллеры и их применение»)

миниатюрный аудио-видеорекордер mAVR

Отправлено Lameг 01 сентября 2006 г. 14:20
В ответ на: А мне можно ? отправлено Aleksey_n 01 сентября 2006 г. 12:14


Для нахождения значений функции в промежутках между узлами (точками измерений)удобно применять сплайн-интерполяцию, одним из достоинств которой является то, что ВЫЧИСЛЕННЫЕ по ней значения функции в узлах (точках измерения) гарантированно совпадут с ИЗМЕРЕННЫМИ значениями, что не всегда достижимо при "обычной" интерполяции полиномами (Ньютона,Лагранжа,Эверетта, где для повышения точности применяются полиномы высокой степени, что само по себе дает погрешность, да и время вычисления увеличивается. В случае сплайна достаточно полинома 3-ей степени). Ниже приведена Си-функция для вычисления по сплайн-методу значения Y в промежутках между известными узлами (точками измерений).Работать с ней очень просто (покажу на примере 6 узловых точек):
Пусть в известные Вам 6 точек времени Вы намеряли 6 значений и хотите построить на экране плавненький график.
1. Сохраните измеренные значения (вольты, омы, градусы, литры...) во float-виде в глобальном массиве Yy[1]...Yy[6].
(Обратите внимание, что здесь индекс массива идет не с нуля, а с 1. Это рудимент Бейсика, т.к. первоначально программа была написана на нем, и работала на Синклере и БК).
2. ВременА измерений сохраните во float-виде в глобальном массиве Xx[1]...Xx[6] (Конечно, каждое время Xx[i] должно соответствовать "своему" измерению Yy[i] ).
Пусть для определенности временА измерений 1, 2, 3, 4, 5, 6 мс. Промежутки между измерениями, вообще-то, могут быть неодинаковыми. Сплайну пох.
3. Ну, и запускайте функцию задавая ей в качестве аргумента интересующее Вас время.
"Просканируйте" таким образом Ваш временной диапазон - и выводите
график на экран прибора.
4. С чувством выполненного долга займите очередь в кассу предприятия за премией.
Примеры вызова:
Value1 = Spline( 1.5 ); // вычислит значение функции для 1.5 мс
........................
Value2 = Spline( 4.0 ); // даст то же значение, что Вы намеряли в узловой точке 4 мс
........................
Исходный код на Си:
////////////////////////////////////////////
#define MAXIMAL 6
/* Для изменения количества узлов изменять только значение MAXIMAL, но не трогая констант 6.0 внутри функции */
/*******************************************/
float power3(float zx )
{
return (zx*zx*zx);
}/*power3*/
/*******************************************/
float Spline( float TimePoint )
{
unsigned char ii, jj, kk;
float dd, ee, hh, ff, pp, xxx, rrr, yyy;
float Ll[MAXIMAL+2], Rr[MAXIMAL+2], Ss[MAXIMAL+2], Mm[MAXIMAL+2];

dd = Xx[2] - Xx[1];

ee = ( Yy[ 2 ] - Yy[ 1 ] ) / dd;

for( kk=2; kk <= MAXIMAL-1; kk++ )
{
hh = dd;
dd = Xx[kk+1] - Xx[kk];
ff = ee;
ee = ( Yy[kk+1] - Yy[kk] ) / dd;
Ll[kk] = dd / ( dd + hh);
Rr[kk] = 1.0 - Ll[kk];
Ss[kk] = ( 6.0 * (ee - ff) ) / ( hh + dd );
}/*for*/

for( kk = 2; kk <= MAXIMAL-1; kk++ )
{
pp = 1.0 / ( Rr[kk] * Ll[kk-1] + 2 );
Ll[kk] = (-Ll[kk]) * pp;
Ss[kk] = ( Ss[kk] - Rr[kk] * Ss[kk-1] ) * pp;
}/*for*/

Mm[ MAXIMAL ] = 0.0;
Ll[ MAXIMAL-1 ] = Ss[ MAXIMAL-1 ];
Mm[ MAXIMAL-1 ] = Ll[ MAXIMAL-1 ];

for( kk = MAXIMAL-2; kk >= 1; kk-- )
{
Ll[kk] = Ll[kk] * Ll[kk+1] + Ss[kk];
Mm[kk] = Ll[kk];
}/*for*/

xxx = TimePoint;

ii = 0;

if( xxx > Xx[ MAXIMAL ] )
{
// экстраполяция вправо по оси времени
dd = Xx[MAXIMAL] - Xx[MAXIMAL-1];
yyy = dd * Mm[ MAXIMAL-1 ] / 6.0 + ( Yy[MAXIMAL] - Yy[MAXIMAL-1] ) / dd;
yyy = yyy * ( xxx - Xx[MAXIMAL] ) + Yy[MAXIMAL];
}/*if*/

else if( xxx <= Xx[ 1 ] )
{
// экстраполяция влево по оси времени
dd = ( Xx[2] - Xx[1] );
yyy = (((-dd) * Mm[2]) / 6.0) + (( Yy[2] - Yy[1] ) / dd);
yyy = (yyy * ( xxx - Xx[1] ) ) + Yy[1];
}/*else if*/

else
{
// интерполяция
do{ ii++; }while( xxx > Xx[ ii ] );
jj = ( ii - 1 );
dd = ( Xx[ii] - Xx[jj] );
hh = ( xxx - Xx[jj] );
rrr = ( Xx[ii] - xxx );
pp = dd * dd / 6.0;
yyy = ( ( Mm[jj]*(power3(rrr)) + Mm[ii]*(power3(hh)) ) / 6.0 ) / dd;
yyy = yyy+((( Yy[jj]-(Mm[jj]*pp))*rrr) + ((Yy[ii]-(Mm[ii]*pp))*hh) ) / dd;
}/*else*/

return yyy;

}/*Spline*/
/*********************************/
Легко заметить, что задавать значения времени можно и за пределами периода измерений, т.е. можно проводить экстраполяцию. Но не ждите от такой экстраполяции чудес, здесь это будет всего лишь прямая линия с наклоном, равным первой производной от крайних точек интервала. Это линейная экстраполяция или т.н. Задание Асимптотического Поведения.


Составить ответ  |||  Конференция  |||  Архив

Ответы


Отправка ответа
Имя (обязательно): 
Пароль: 
E-mail: 

Тема (обязательно):
Сообщение:

Ссылка на URL: 
Название ссылки: 
URL изображения: 


Rambler's Top100 Рейтинг@Mail.ru
Перейти к списку ответов  |||  Конференция  |||  Архив  |||  Главная страница  |||  Содержание