реклама на сайте
подробности

 
 
4 страниц V   1 2 3 > »   
Reply to this topicStart new topic
> передискретизация, как?
TigerSHARC
сообщение Feb 22 2010, 16:22
Сообщение #1


Знающий
****

Группа: Свой
Сообщений: 688
Регистрация: 4-09-09
Пользователь №: 52 195



Здравствуйте.
Есть сигнал:

Fs = 6400;
N = 128;
Ts = 1/Fs;
T = Ts*N;
f = 45;
t = 0:Ts:T-Ts;
A = 10;
Y = A*sin(2*pi*f*t)+ A*sin(2*pi*2*f*t)+ A*sin(2*pi*3*f*t);

как и какой функцией в MATLAB пересчитать частоту дискретизации с 6400 на 5760.
Причём с тем же числом отсчётов (128).

Это нужно для корректировки спектра сигнала.
Дело в том, что когда меняю частоту "руками":

Fs = 5760;
N = 128;
Ts = 1/Fs;
T = Ts*N;
f = 45;
t = 0:Ts:T-Ts;
A = 10;
df = Fs/N;
f1 = 0:df:Fs-(Fs/N);
Y = A*sin(2*pi*f*t)+ A*sin(2*pi*2*f*t)+ A*sin(2*pi*3*f*t);
X = fft(Y)/length(t);
>> stem(f1, abs(X)), grid

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

да и вообще, не толкьо в MATLAB, как из 128 отсчётов получается 128 передискретизированных отсчётов... полюбому время выборки должно как-то варьироваться...
Go to the top of the page
 
+Quote Post
Andron_
сообщение Feb 22 2010, 16:59
Сообщение #2


.NET developer
***

Группа: Свой
Сообщений: 218
Регистрация: 20-10-07
Из: Новосибирск
Пользователь №: 31 532



Цитата
как и какой функцией в MATLAB пересчитать частоту дискретизации с 6400 на 5760.
Причём с тем же числом отсчётов (128).


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

что вы хотите добиться - я не понял.
Go to the top of the page
 
+Quote Post
bahurin
сообщение Feb 22 2010, 17:10
Сообщение #3


Местный
***

Группа: Участник
Сообщений: 240
Регистрация: 20-09-08
Пользователь №: 40 347



Передискретизацию можно выполнить на основе интерполятора. Часто прибегают к лагранжевой интерполяции и фильтрам фарроу. Там же есть программная реализация на с++. При ресамплигнге на более низкую частоту дискретизации не забудьте поставить фильтр антиалисинга. Однако если вы хотите получить спектр сигнала, то вам стоит рассмотреть окна сглаживания
Go to the top of the page
 
+Quote Post
TigerSHARC
сообщение Feb 22 2010, 17:11
Сообщение #4


Знающий
****

Группа: Свой
Сообщений: 688
Регистрация: 4-09-09
Пользователь №: 52 195



с точки зрения такой науки как численные методы возможно провести интерполяцию сигнала.

P.S. не использую оконное взвешиване здесь так как ГОСТ это запрещает (для моего случая) вот и приходится частоту менять программно.

Сообщение отредактировал TigerSHARC - Feb 22 2010, 17:15
Go to the top of the page
 
+Quote Post
bahurin
сообщение Feb 22 2010, 17:16
Сообщение #5


Местный
***

Группа: Участник
Сообщений: 240
Регистрация: 20-09-08
Пользователь №: 40 347



Цитата(TigerSHARC @ Feb 22 2010, 20:11) *
P.S. не использую оконное взвешиване здесь так как ГОСТ это запрещает (для моего случая)

В штате Индиана (США) в 1897 году был выпущен билль (см.: en:Indiana Pi Bill), законодательно устанавливающий значение числа Пи равным 3,2.

Вобще странная ситуация, когда гост запрещает чтото использовать. Почему бы не использовать окна, если они позволяют получить установленные гостом харакетристики? Чудно однако.
Go to the top of the page
 
+Quote Post
Andron_
сообщение Feb 22 2010, 17:19
Сообщение #6


.NET developer
***

Группа: Свой
Сообщений: 218
Регистрация: 20-10-07
Из: Новосибирск
Пользователь №: 31 532



чтобы число отсчетов осталось тем же, нужна экстраполяция.
Go to the top of the page
 
+Quote Post
TigerSHARC
сообщение Feb 22 2010, 17:23
Сообщение #7


Знающий
****

Группа: Свой
Сообщений: 688
Регистрация: 4-09-09
Пользователь №: 52 195



тогда так.
1) при интерполяции всегда используется фиксированное число отсчётов с АЦП?
2) количесвто отсчётов(идущих на блок БПФ) после ресемплинга остаётся прежним? (в моём случае 128)

Просто использую я и фильтр фарроу на С и матлаб... ну не получается и всё... когда руками меняю частоту

Fs = 5760;
N = 128;
Ts = 1/Fs;
T = Ts*N;
f = 45;
t = 0:Ts:T-Ts;
A = 10;
df = Fs/N;
f1 = 0:df:Fs-(Fs/N);
Y = A*sin(2*pi*f*t)+ A*sin(2*pi*2*f*t)+ A*sin(2*pi*3*f*t);
X = fft(Y)/length(t);
>> stem(f1, abs(X)), grid

тогда всё окей.
но тогда и меняется и длинна окна (стала 0,0222).
как это при ресемплинге происходит?
Go to the top of the page
 
+Quote Post
bahurin
сообщение Feb 22 2010, 17:33
Сообщение #8


Местный
***

Группа: Участник
Сообщений: 240
Регистрация: 20-09-08
Пользователь №: 40 347



Цитата(TigerSHARC @ Feb 22 2010, 20:23) *
как это при ресемплинге происходит?


Если частота понижается, то для сохранения количества отсчетов ПОСЛЕ ресамплинга надо уведить ИСХОДНОЕ количество отсчетов, потом применить рэсамплер.

Код
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define M_PI       3.14159265358979323846

// Функция сохранения результатов анализа в текстовый файл для
// построения графиков.
void saveToTXT(double* t, double* s, int n, char* fileName){
    FILE *file = fopen(fileName, "w");
    if(!file) return;
    for(int i = 0; i < n; i++)
        fprintf(file,"%e\t%e\n",t[i],s[i]);
    fclose(file);
}


// Функция расчета кубического полинома
// на основе модифицированного фильтра Фарроу
double farrow3(double *y, double x){
    double a3 = (y[3]-y[0])/6.0+(y[1]-y[2])/2.0;
    double a1 = (y[3]-y[1])/2.0-a3;
    double a2 = y[3]-a3-a1-y[2];
    return x*(x*(x*a3+a2)+a1)+y[2];
}

int main(){
            
    double Fs0 = 16E3;            // исходная частота дискретизации
    double Fs1 = 12E3;            // частота дискретизации после ресэмплинга
    
    int K = 128;// количество отсчетов после ресэмплинга
    int N = (int)K*Fs0/Fs1;// количество исходных отсчетов
    // выделяю память под исходный сигнал
    double* y0 = (double*) malloc(N*sizeof(double));
    double* t0 = (double*) malloc(N*sizeof(double));
    // выделяю память под результат ресэмплинга
    double* y1 = (double*) malloc(K*sizeof(double));
    double* t1 = (double*) malloc(K*sizeof(double));
    // формирую исходный сигнал
    for(int i = 0; i<N; i++){
        t0[i] = double(i)/Fs0;
        y0[i] = cos(2*M_PI*3E3*t0[i]);        // гармоническое колебание на частоте 3 кГц.
    }
    // произвожу ресэмплинг
    for(int i = 0; i<K; i++){
        t1[i] = (double)i/Fs1;                // текущий момент дискретизации
        int j = int((double)i*Fs0/Fs1)-2;    // пересчитываю индекс исходного сигнала
        if(j<0) j =0;                        // если индекс отрицателььный то приравниваю его к 0
        double x = (t1[i]-t0[j])*Fs0-2;        // пересчитываю значение x
        y1[i] = farrow3(y0+j, x);            // фильтр Фарроу
        t1[i] *= 1E3;                        // перевожу время результата ресэмплинга в мс
    }
    // перевожу исходное время в мс
    for(int i = 0; i<N; i++){
        t0[i] *= 1E3;                        
    }
    // сохраняю результат в файлы
    saveToTXT(t0, y0, N, "исходный сигнал.txt");
    saveToTXT(t1, y1, K, "resampling.txt");
    system("Pause");
    return 0;
}


все работает.

Сообщение отредактировал bahurin - Feb 22 2010, 17:40
Go to the top of the page
 
+Quote Post
TigerSHARC
сообщение Feb 22 2010, 17:42
Сообщение #9


Знающий
****

Группа: Свой
Сообщений: 688
Регистрация: 4-09-09
Пользователь №: 52 195



Цитата(bahurin @ Feb 22 2010, 20:16) *
В штате Индиана (США) в 1897 году был выпущен билль (см.: en:Indiana Pi Bill), законодательно устанавливающий значение числа Пи равным 3,2.

Вобще странная ситуация, когда гост запрещает чтото использовать. Почему бы не использовать окна, если они позволяют получить установленные гостом харакетристики? Чудно однако.


не хотелось бы чтобы дисскусия ушла в рксло обсуждения гостов, НО...!

Там так сказано видимо потому, что частотное разрешение должно быть 5 Гц ( а не 50 как раньше)*, чтобы интергармоники (кратные 5 Гц) содержали полезную информацию, а не информацию о расползаном спектре.
А чтобы обеспечить такое разрешние по частоте придётся брать выборку с огромным запасом, что скажется на быстродействии в реальном времени (к тому же предполагается работа сразу 8-ми каналов одновременно по 3 фазы тока и напряжения и нейтраль)
Алгоритм с использованием окна, по-моему, на 8 каналов DSP проц не потянет (по моему)...
Подход с передискретизацией и прямоуг. окне хорош тем, что позволит при заданной точности обеспечить минимальную выборку сигнала.
Я думаю так.

* имеется ввиду гост на качество электроэнергии и нововведённые госты на измерение гармоник и интергармоник в электрических сетях.



но я не о ГОСТах я о самом алгоритме. Возможно же такое преобразование сигнала, чтобы в окно уместилось целое (с некоторой малой погрешностью) количесвто периодов. НО как!?

1) при интерполяции всегда используется фиксированное число отсчётов с АЦП?
2) количесвто отсчётов(идущих на блок БПФ) после ресемплинга остаётся прежним? (в моём случае 128)

... иными словами я хочу "поджать сигнал" во временной области под окно 0,02с.(даже если его период больше, или меньше этого значения), сохраненив его параметы. При передискретизации происходит этот эффект?



но я не о ГОСТах я о самом алгоритме. Возможно же такое преобразование сигнала, чтобы в окно уместилось целое (с некоторой малой погрешностью) количесвто периодов. НО как!?

1) при интерполяции всегда используется фиксированное число отсчётов с АЦП?
2) количесвто отсчётов(идущих на блок БПФ) после ресемплинга остаётся прежним? (в моём случае 128)

... иными словами я хочу "поджать сигнал" во временной области под окно 0,02с.(даже если его период больше, или меньше этого значения), сохраненив его параметы. При передискретизации происходит этот эффект?



но я не о ГОСТах я о самом алгоритме. Возможно же такое преобразование сигнала, чтобы в окно уместилось целое (с некоторой малой погрешностью) количесвто периодов. НО как!?

1) при интерполяции всегда используется фиксированное число отсчётов с АЦП?
2) количесвто отсчётов(идущих на блок БПФ) после ресемплинга остаётся прежним? (в моём случае 128)

... иными словами я хочу "поджать сигнал" во временной области под окно 0,02с.(даже если его период больше, или меньше этого значения), сохраненив его параметы. При передискретизации происходит этот эффект?
Go to the top of the page
 
+Quote Post
bahurin
сообщение Feb 22 2010, 17:42
Сообщение #10


Местный
***

Группа: Участник
Сообщений: 240
Регистрация: 20-09-08
Пользователь №: 40 347



Цитата(TigerSHARC @ Feb 22 2010, 20:34) *
не хотелось бы чтобы дисскусия ушла в рксло обсуждения гостов, НО...!


Согласен воздух сотрясать глупо. Выше программа на си которая делает ресамплинг с фиксированным количеством отсчетов на выходе
Go to the top of the page
 
+Quote Post
TigerSHARC
сообщение Feb 22 2010, 18:00
Сообщение #11


Знающий
****

Группа: Свой
Сообщений: 688
Регистрация: 4-09-09
Пользователь №: 52 195



Цитата(bahurin @ Feb 22 2010, 20:33) *
Если частота понижается, то для сохранения количества отсчетов ПОСЛЕ ресамплинга надо уведить ИСХОДНОЕ количество отсчетов, потом применить рэсамплер.

Код
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define M_PI       3.14159265358979323846

// Функция сохранения результатов анализа в текстовый файл для
// построения графиков.
void saveToTXT(double* t, double* s, int n, char* fileName){
    FILE *file = fopen(fileName, "w");
    if(!file) return;
    for(int i = 0; i < n; i++)
        fprintf(file,"%e\t%e\n",t[i],s[i]);
    fclose(file);
}


// Функция расчета кубического полинома
// на основе модифицированного фильтра Фарроу
double farrow3(double *y, double x){
    double a3 = (y[3]-y[0])/6.0+(y[1]-y[2])/2.0;
    double a1 = (y[3]-y[1])/2.0-a3;
    double a2 = y[3]-a3-a1-y[2];
    return x*(x*(x*a3+a2)+a1)+y[2];
}

int main(){
            
    double Fs0 = 16E3;            // исходная частота дискретизации
    double Fs1 = 12E3;            // частота дискретизации после ресэмплинга
    
    int K = 128;// количество отсчетов после ресэмплинга
    int N = (int)K*Fs0/Fs1;// количество исходных отсчетов
    // выделяю память под исходный сигнал
    double* y0 = (double*) malloc(N*sizeof(double));
    double* t0 = (double*) malloc(N*sizeof(double));
    // выделяю память под результат ресэмплинга
    double* y1 = (double*) malloc(K*sizeof(double));
    double* t1 = (double*) malloc(K*sizeof(double));
    // формирую исходный сигнал
    for(int i = 0; i<N; i++){
        t0[i] = double(i)/Fs0;
        y0[i] = cos(2*M_PI*3E3*t0[i]);        // гармоническое колебание на частоте 3 кГц.
    }
    // произвожу ресэмплинг
    for(int i = 0; i<K; i++){
        t1[i] = (double)i/Fs1;                // текущий момент дискретизации
        int j = int((double)i*Fs0/Fs1)-2;    // пересчитываю индекс исходного сигнала
        if(j<0) j =0;                        // если индекс отрицателььный то приравниваю его к 0
        double x = (t1[i]-t0[j])*Fs0-2;        // пересчитываю значение x
        y1[i] = farrow3(y0+j, x);            // фильтр Фарроу
        t1[i] *= 1E3;                        // перевожу время результата ресэмплинга в мс
    }
    // перевожу исходное время в мс
    for(int i = 0; i<N; i++){
        t0[i] *= 1E3;                        
    }
    // сохраняю результат в файлы
    saveToTXT(t0, y0, N, "исходный сигнал.txt");
    saveToTXT(t1, y1, K, "resampling.txt");
    system("Pause");
    return 0;
}


все работает.


у них там да. А вы задайте частоту дискретизации 6400 для синуса c частотой f0 = 45,35Гц. при выборке N = 1024 (такое соотношение частоты дискретизации и количества выборок дают верный спектр лишь при f0 = 50Гц, так как тогда в окне ровно 8 периодов), а мы же для f0 = 45,35Гц здесь видим нецелое число периодов в окне.
затем попробуйте передискретизировать этот синус на на частоту 5804.8 (заметьте дробная частота получается как N/8*f0) и должны увидеть целое количесвто периодов в окне.

Но в моих экспериментах с этим кодом получается ерунда при передискретизации.

Ну бог с ним, с эти кодом С-шным. Хотябы в MATLAB бы увидеть положительный результат.
Go to the top of the page
 
+Quote Post
bahurin
сообщение Feb 22 2010, 18:07
Сообщение #12


Местный
***

Группа: Участник
Сообщений: 240
Регистрация: 20-09-08
Пользователь №: 40 347



Цитата(TigerSHARC @ Feb 22 2010, 21:00) *
Но в моих экспериментах с этим кодом получается ерунда при передискретизации.


ставьте
Код
    

double Fs0 = 6400;            // исходная частота дискретизации
double Fs1 = 5804.8;        // частота дискретизации после ресэмплинга
    
int K = 1024;// количество отсчетов после ресэмплинга
int N = (int)K*Fs0/Fs1;// количество исходных отсчетов


а также сигнал:

Код
    

// формирую исходный сигнал
    for(int i = 0; i<N; i++){
        t0[i] = double(i)/Fs0;
        y0[i] = cos(2*M_PI*45.35*t0[i]);        // гармоническое колебание на частоте 3 кГц.
    }


все замечательно работает. Количество входных отсчетов 1128 выходный 1024. На выходе ровно 8 периодов колебания
Go to the top of the page
 
+Quote Post
TigerSHARC
сообщение Feb 23 2010, 13:12
Сообщение #13


Знающий
****

Группа: Свой
Сообщений: 688
Регистрация: 4-09-09
Пользователь №: 52 195



Цитата(bahurin @ Feb 22 2010, 21:07) *
ставьте
Код
    

double Fs0 = 6400;            // исходная частота дискретизации
double Fs1 = 5804.8;        // частота дискретизации после ресэмплинга
    
int K = 1024;// количество отсчетов после ресэмплинга
int N = (int)K*Fs0/Fs1;// количество исходных отсчетов


а также сигнал:

Код
    

// формирую исходный сигнал
    for(int i = 0; i<N; i++){
        t0[i] = double(i)/Fs0;
        y0[i] = cos(2*M_PI*45.35*t0[i]);        // гармоническое колебание на частоте 3 кГц.
    }


все замечательно работает. Количество входных отсчетов 1128 выходный 1024. На выходе ровно 8 периодов колебания


странно, когда я пробовал не выходило. после праздников просмотрю ещё раз. Наверно конкретно в моём коде косяк какойто...
Скажите, а для повышения частоты дискретизации такой метод подойдёт? Скажем нужно 6400 пересчитать на 7360 гц. просто соответствующие значения вставить?

Да и почему то исходное количесвто отсчётов разное всегда... наверно исходное число должно быть постоянным а выходное менятся в зависимости от соотношения F0/F1. Так?

Да и скажите где вы этот код взяли.
тот что у меня с того же сайта:

int main()
{
int N = 64; // количество исходных отсчетов
double Fs0 = 20E3; // исходная частота дискретизации
double Fs1 = 15E3; // частота дискретизации после ресэмплинга
int K = (int)(N*Fs1/Fs0); // количество отсчетов после ресэмплинга
// выделяю память под исходный сигнал
.......


вот тут как раз исходное количесвто отсчётов постоянно(как и должно быть), а на выходе меняется...

странно

Сообщение отредактировал TigerSHARC - Feb 23 2010, 13:32
Go to the top of the page
 
+Quote Post
Andron_
сообщение Feb 23 2010, 16:38
Сообщение #14


.NET developer
***

Группа: Свой
Сообщений: 218
Регистрация: 20-10-07
Из: Новосибирск
Пользователь №: 31 532



wacko.gif wacko.gif wacko.gif

это что-то нереальное...

сдайте дилера, я тоже хочу...
Go to the top of the page
 
+Quote Post
TigerSHARC
сообщение Feb 23 2010, 18:29
Сообщение #15


Знающий
****

Группа: Свой
Сообщений: 688
Регистрация: 4-09-09
Пользователь №: 52 195



Здаётся мне у меня какие-то принципиальные затруднения....
Хочу просто "поджать" сигнал во временной области под жестко заданное временное окно с сохранением информации о сигнале.
Гуру, подскажите!!!!
Go to the top of the page
 
+Quote Post

4 страниц V   1 2 3 > » 
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 16th June 2025 - 16:07
Рейтинг@Mail.ru


Страница сгенерированна за 0.01425 секунд с 7
ELECTRONIX ©2004-2016