Страница 1 из 1
Оцифровка сигнала [под управлением atmega]
Добавлено: Сб май 23, 2009 18:52:06
zi4rox
ATMega16 управляет внешним АЦП TLV1570 по встроенному SPI и пытаемся оцифровать гармонический сигнал с частотами до 20кгц.
Немного о [url="http://focus.ti.com/lit/ds/symlink/tlv1570.pdf"]TLV1570[/url] - 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, получил следующие тайминги:
С учетом всех погрешностей на запись в переменные и т.п - получил, что снятие одного отсчета займет 10мкс -
т.е. частота дискретизации 100кГц - все равно укладываемся.
Итак, на практике вот что я получаю:
Оцифровка сигнала частотой 10кГц амплитуда около 1В:

Здесь около 10ти точек на период. Качество оцифровки неудовлетворительное.
Сразу же в настройках SPI выставил галочку SCLK x2 Rate - т.е. удвоили частоту тактирующего импульса (я предполагал что и качество оцифровки увеличится в 2 раза)
Вот как получилось с этой настройкой:
Оцифровка сигнала частотой 10кГц амплитуда около 1В (SPI SCLK x2 rate):

Получилось 13 точек на период - совсем небольшой прирост =(
Мучил код, пробывал и так и сяк, симулировал.
Вот как получается, если после получения отсчета от АЦП - сразу выплевывать его на UART:
Код: Выделить всё
while (1) {
ADC_CS = 0;
putchar(spi(0x00));
putchar(spi(0x60));
ADC_CS = 1;
}

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

Здесь меня всё устраивает. Около 90 точек на период. Качество отличное
Прошу помощи - оцифровкой занимаюсь в первый раз, как быть, вроде бы всё правильно - а на деле выходит совсем не то. Возможно код можно ещё как то более оптимизировать, или ещё где ошибку сделал? Прошу совета.
Добавлено: Пн май 25, 2009 10:52:11
uk8amk
1.Для красивой синусоиды 10 точек на период маловато будет.
2.Вижу на графиках параллельно с основным сигналом присутствие еще нескольких. Схема случаем не на макетке собрана? Присутствует ли разделение аналоговой и цифровой земли? Имеется ли хорошая фильтрация и стабилизация цепей питания аналог. части?
3. Что является источником сигнала? Уверены ли вы в его синусоидальности(смотрели ли вы его осцилом)?
Добавлено: Вт май 26, 2009 11:27:02
mackerel
А чем не устраивает результат? По теореме т. Котельникова для восстановления Вашего сигнала (одна-единственная синусоида) достаточно чуть-чуть-чуть больше двух выборок на период (и это действительно так, доказано вековой практикой человечества!). У Вас, как Вы говорите, их 13. В чём проблема-то?
Да, вдогонку: спектр входного сигнала действительно ограничен? Т.е. это действительно "чистый" синус? Если нет - частота выборок должна быть больше удвоенной частоты высшей гармоники, не забывайте. Ну, или фильтр прилепить нужно...
Добавлено: Вт май 26, 2009 14:34:11
zi4rox
2 uk8amk:
Сигнал там один идет - синус с DDS. Получается как бы наложение - из за того что я по 100 отсчетов беру, и сшиваются они иногда плохо.
Питание разделил на аналоговое и цифровое - а вот земля общая.
2 mackerel
Вы абсолютно правы! Именно сейчас этим и занимаюсь, пытаюсь восстановить сигнал через ряд котельникова. Но вот реализация несовсем получается. Не взгляните пожалуйста? (фильтр на входе стоит - так что всё должно выполнятся)
Пытаюсь сделать интерполяцию синком - не получается немного ...
Вот формула, для восстановления сигнала:
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);
В результате получаю вот такую картинку:
синк он мне рисует ... но это не восстановленный сигнал. Как я понял - тут должна быть сумма синков - и тогда образуется нужное.
Или я ошибаюсь? Помогите пожалуйста разобраться, а то голова кругом уже
Добавлено: Вт май 26, 2009 15:27:22
mackerel
В Вашей интерпретации выражение 2Fmax * T ВСЕГДА(!) равно двум, что явно неправильно, как мне кажется. Может, в этом и дело? Сам подобными выкладками не занимался, моё дело было - реализация в железе.
Коты!!! Ведь простая и интересная задача появилась!
Кто поможет решить?
(Самому стало интересно).
О, вот только что нашёл, может, будет полезно?
http://www.radioland.net.ua/contentid-422-page1.html
Добавлено: Ср май 27, 2009 09:11:52
zi4rox
Всё, вроде разобрался - нужно быть более аккуратным при подборе коэффициентов. Сигнал действительно можно восстановить с любой точностью, для гармонического сигнала - ещё можно и форму подсгладить.
* на рисунке 250 точек на период - это число может быть теоретически любым
Всем спасибо кто помогал!
Добавлено: Ср май 27, 2009 09:58:13
mackerel
А не могли бы Вы выложить то же самое, но с 3-5 выборками на период? (Желательно живого сигнала, конечно). Насколько будет близко к оригиналу, интересно.
Добавлено: Ср май 27, 2009 23:14:45
zi4rox
mackerel писал(а):А не могли бы Вы выложить то же самое, но с 3-5 выборками на период? (Желательно живого сигнала, конечно). Насколько будет близко к оригиналу, интересно.
Самому интересно, думаю до конца недели оцифрую такую штуку, и выложу сюда.
Добавлено: Сб май 30, 2009 22:10:06
Mozart
как я понял связь у вас с АЦП и МК идёт по уарту, и частота 8МГц??...
здесь вроде бы всё должно быть нормально, а вот передача в компьютер вы уверены что успеваете передавать всё??... вы используете пинг-понг??
з.ы. сам недавно столкнулся с такой проблемой, и при первом выяснении оказалось что УСАРТ просто не успевает всё передать.
Добавлено: Пн июн 01, 2009 17:04:17
zi4rox
Mozart писал(а):как я понял связь у вас с АЦП и МК идёт по уарту, и частота 8МГц??...
МК с АЦП связаны по SPI - там все что удается выжать - это 8МГЦ частота клока самого, но если учитывать задержки на запись в переменную - получается в 2 раза медленнее по общему времени - не знаю даже как это улучшить
Mozart писал(а):
а вот передача в компьютер вы уверены что успеваете передавать всё??... вы используете пинг-понг??
з.ы. сам недавно столкнулся с такой проблемой, и при первом выяснении оказалось что УСАРТ просто не успевает всё передать.
УАРТ - дико медленный, Вы правы! Я передаю порциями по 100 отсчетов, и сшиваю куски, т.к. - сигнал периодический. Если делать так: Снял отсчет -> передал по уарту - то будет дикая задержка и сигнал оцифровываться будет гораздо хуже.
Добавлено: Пн июн 01, 2009 20:44:42
Mozart
МК с АЦП связаны по SPI - там все что удается выжать - это 8МГЦ частота клока самого, но если учитывать задержки на запись в переменную - получается в 2 раза медленнее по общему времени - не знаю даже как это улучшить
да очепятался просто...
всё равно вы первые 100 порций передали а вторую порцию накопили, пока её накопили первая вся не ушла п уже надо передавать вторую... потом начинаете передавать вторую... первая уже на половину к примеру заполнена...
смутно изъясняюсь??
суть заключается в том что когда вы передали первые 100байт, вторые и третьи 100 байт куда-то записались, когда передаете вторые 100байт, то 4 и 5 записались и так далее...
Добавлено: Пн июн 01, 2009 22:39:32
zi4rox
Конечно, передавать по 100 отсчетов - тоже не самое лучшее решение. Но это пока лучшее что придумал.
Возможно подкините идейку в этом направлении?
Добавлено: Вт июн 02, 2009 10:10:31
Mozart
идей нет... но если заранее известно что это синусоида, тогда передавать значащие точки... к примеру нули (это будет период), потом "полу амплитуду" и пик синусоиды....
можно так попробовать...
Добавлено: Вт июн 02, 2009 15:46:49
zi4rox
Да собственно с синосоидой проблем особо нет, помимо неё есть ещё один, более сложный сигнал. Так что пока борюсь с этим )
Добавлено: Пн июн 08, 2009 17:30:59
DrWatson
Если МК только передает данные с АЦП в компьютер, почему бы не использовать USB вместо UART - теоретически должен успеть передавать и по одному байту. Расковырять к примеру исходник
Отсюда только вместо UARTа использовать SPI.
А если USB использовать нет возможности, а длительность оцифровывания сигнала не более 1,5 сек, можно поставить внешнее ОЗУ для буферизации. В Mega8515, к примеру, есть для этого аппаратные средства.