Перейти к содержанию
    

Оцифровка сигнала [под управлением atmega]

ATMega16 управляет внешним АЦП TLV1570 по встроенному SPI и пытаемся оцифровать гармонический сигнал с частотами до 20кгц.

 

Немного о TLV1570 - 8ми канальный 10ти разрядный последовательный АЦП 1.25MSPS. Входные напряжения: 0 .. 5В

 

По теореме Котельникова, частота дискретизации: Fдиcкр > 2Fmax

В моём случае 2Fmax = 40кГц, а частота дискретизации АЦП по даташиту считается так: Fдискр = 1/16*Fsclk (на каждую выборку нужно передать 2 байта) (в обвязке к ATMega стоит резонатор на 16МГц, при настройках SPI получил: Fsclk = 4Mhz ) => Fдиск = 1\16*4Mhz = 250кГц

 

Т.е. мы укладываемся с головой. Частота дискретизации 250 кГц, а сигнал 20кГц

 

Код прошивки такой:

while (1) {     
for (i=0;i<100;i++) {     
ADC_CS = 0;
adc_result_hi[i] = spi(0x00);
adc_result_low[i] = spi(0x60);   
ADC_CS = 1;       
}               

for (i=0;i<100;i++){
putchar(adc_result_hi[i]);        
putchar(adc_result_low[i]);        
}
}

* я сначала собираю отсчеты по 100 точек и сохраняю их в буффер, а затем отправляю по UART на COM порт в ПК. (так быстрее производительность, т.к. отправка по уарту занимает значительное время)

 

Просимулировал этот код в VMLAB, получил следующие тайминги:

 

34f76.jpg

 

С учетом всех погрешностей на запись в переменные и т.п - получил, что снятие одного отсчета займет 10мкс - т.е. частота дискретизации 100кГц - все равно укладываемся.

 

Итак, на практике вот что я получаю:

 

Оцифровка сигнала частотой 10кГц амплитуда около 1В:

703b1.jpg

Здесь около 10ти точек на период. Качество оцифровки неудовлетворительное.

 

Сразу же в настройках SPI выставил галочку SCLK x2 Rate - т.е. удвоили частоту тактирующего импульса (я предполагал что и качество оцифровки увеличится в 2 раза)

 

Вот как получилось с этой настройкой:

Оцифровка сигнала частотой 10кГц амплитуда около 1В (SPI SCLK x2 rate):

a37f3.jpg

Получилось 13 точек на период - совсем небольшой прирост =(

 

Мучил код, пробывал и так и сяк, симулировал.

Вот как получается, если после получения отсчета от АЦП - сразу выплевывать его на UART:

while (1) {     

ADC_CS = 0;        
putchar(spi(0x00));
putchar(spi(0x60));
ADC_CS = 1;     

}

b2e65.jpg

Совсем не так как хотелось бы.

 

* Сигнал с меньшей частотой оцифровывает прелестно. Вот пример оцифровки синуса с частотой 1кГц:

afe69.jpg

Здесь меня всё устраивает. Около 90 точек на период. Качество отличное

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

...

Т.е. мы укладываемся с головой. Частота дискретизации 250 кГц, а сигнал 20кГц

...

 

На вид все картинки у вас правильные. Разве что иногда у вас теряются отсчёты (видно на второй картинке "синуса").

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

То вам "Fдиcкр > 2Fmax" А то 10 точек на период мало 8) Тогда и считайте частоту, отталкиваясь от минимально количества этих самых точек 8) Эти десять точек на период в 10КГц синусоиды.... уже 100Кгц дискретизации.

 

Мне собственно непонятно - что вам не нравится.

 

На вид все картинки у вас правильные. Разве что иногда у вас теряются отсчёты (видно на второй картинке "синуса").

Это имхо не потеря, а места склейки семплов по 100 точек.

Изменено пользователем Dx!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Да, сейчас тоже пересчитал - получается что ацп правильно работает - и там получается 10 точек на период. Буду пытаться увеличить частоту дискретизации каким то образом.

 

Непонятно пока - сколько этих точек на период в среднем необходимо для более менее верной оцифровки? Или это определяется исходя из личных условий задачи? Вы как считаете?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Непонятно пока - сколько этих точек на период в среднем необходимо для более менее верной оцифровки? Или это определяется исходя из личных условий задачи? Вы как считаете?

Верной для чего?

Чтобы измерить частоту? Амплитуду? С какой точностью?

P.S.

В хороших цифровых осциллографах частоту дискретизации выбирают в 10 раз большую, чем максимальная наблюдаемая. В дешёвых от 2х раз. Правда там ещё дополнительно применяют цифровую интерполяцию. Для наблюдения синуса достаточно хорошо подходит "sin(x)/x correction".

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Измерять нужно амплитуду. Про цифровую интерполяцию интересно! Пойду искать информацию по этой теме, спасибо за идею.

 

* Если кто нибудь знает хорошую ссылку на алгоритм/или мат. описание интерполяции sinc(x) прошу поделится

Изменено пользователем zi4rox

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Измерять нужно амплитуду. Про цифровую интерполяцию интересно! Пойду искать информацию по этой теме, спасибо за идею.

 

* Если кто нибудь знает хорошую ссылку на алгоритм/или мат. описание интерполяции sinc(x) прошу поделится

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Пытаюсь сделать интерполяцию синком - не получается немного ...

 

Вот формула, для восстановления сигнала:

f1.jpg

 

 

x(t) - исходный сигнал

Fmax - частота сигнала, пусть Fmax = 1000 Гц

dt = 1/2Fmax (отсчеты идут через этот интервал времени) dt = 1/2*1000 = 0.0005

 

При это допустим что ацп выдает нам 13 отсчетов сигнала на период. Сам же период T = 1/f = 0.001. Вот на интервале времени в 1 период я и хочу восстановить сигнал. Тогда суммирование будет идти от n=0 до n=2Fmax*T=2000*0.001=2 // Всего 2 отсчета будет использоваться, а не все 13? //

 

s(n*dt) - это как раз сами отсчеты которые у меня есть.

 

// Это массив с отсчетами, которые у меня есть за 1 период

data_01[0]:= 1.10929;
data_01[1]:= 1.02396;
data_01[2]:= 0.85501;
data_01[3]:= 0.54537;
data_01[4]:= 0.31164;
data_01[5]:= 0.08533;
data_01[6]:= 0.02226;
data_01[7]:= 0.09275;
data_01[8]:= 0.26341;
data_01[9]:= 0.56763;
data_01[10]:= 0.81249;
data_01[11]:= 1.0388;
data_01[12]:= 1.09445;

...

//константы, что обговорили выше:
f_max:=1000;
dt:= 0.0005;
x:= 0.0004;

// вычисление значения восстановленного сигнала x(t) в точке x

  for n:=0 to 2 do begin
    buff:= data_01[n]*sin(2*3.14*f_max*(x-n*dt))/(2*3.14*f_max*(x-n*dt));
    result:= result+buff;
  end;

 

Я получаю 1,0849 - довольно близкий отсчет. Пробую строить сам график, беру 100 точек интерполяции с шагом в 0.0004

 

for j:=1 to 100 do begin
  result:=0; // обнуляю результат вычисления для каждой новой точки
  dx:= j*0.0004; // шаг восстановления: 0.0004, 0.0008, 0.0016 и.т.д.

  for n:=0 to 2 do begin
    buff:= data_01[n]*sin(2*3.14*f_max*(dx-n*dt))/(2*3.14*f_max*(dx-n*dt));
    result:= result+buff;
  end;

  // И добавляю вычесленную точку на график (x,y)
  Series2.AddXY(dx,result,'',clRed);

 

В результате получаю вот такую картинку:

22c9c.jpg

 

синк он мне рисует ... но это не восстановленный сигнал. Как я понял - тут должна быть сумма синков - и тогда образуется нужное.

Или я ошибаюсь? Помогите пожалуйста разобраться, а то голова кругом уже

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Всё, вроде разобрался - нужно быть более аккуратным при подборе коэффициентов. Сигнал действительно можно восстановить с любой точностью, для гармонического сигнала - ещё можно и форму подсгладить.

 

19e30.jpg

* на рисунку 250 точек на период - это число может быть теоретически любым

 

Всем спасибо кто помогал!

Изменено пользователем zi4rox

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Измерять нужно амплитуду. Про цифровую интерполяцию интересно!

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

Моменты перехода косинуса через 0 будут соответствовать амплитуде синуса. Компаратор контроллера ловит переход косинуса из 0(минус обрезан, понятное дело) в + и запускает замер АЦП. При спаде из + в 0 можно замерять нижнюю амплитуду.

Может в перерывах успеет в комп согнать ин-фу?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...