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

 
 
3 страниц V  < 1 2 3  
Reply to this topicStart new topic
> DSP на STM32F4
sigmaN
сообщение Aug 29 2016, 19:11
Сообщение #31


I WANT TO BELIEVE
******

Группа: Свой
Сообщений: 2 617
Регистрация: 9-03-08
Пользователь №: 35 751



Цитата
1) результат вычислений получается float, для вывода на ЦАП, естественно, преобразую его к int - теряется дробная часть, это нормально?
Корректнее наверно тут использвоать округление вместо простого отбрасывания дробной части http://www.cplusplus.com/reference/cmath/ceil/

Цитата
2) Отрицательные значения. Я подаю на вход фильтра белый шум, 24-битный. Соответственно, после фильтра у меня тоже должно получаться 24-битный результат. Но! Отрицательные значения в процессоре - это инвертированное положительное число + 1. А для ЦАП отрицательное значение получается простой инверсией положительного числа.
Что это за ЦАП то такой у вас? Прям с двухполярным питанием и честной выдачей наружу напряжения ниже нуля?
Очень сомневаюсь. Регистр ЦАПа скорее всего беззнаковый от 0 до скольки там разрадность позволяет.
А потому за 0 надобно принять половинку разрядности ЦАПа. Если он например 16ти разрядный, то за 0 надо принять половинку 2^16 / 2 = 32768
Таким образом получившиеся после фильтра циферки перед передачей в ЦАП надо приготовить.
У вас будет еще одна задачка если в процессе цифровой обработки получились космические цифры, которые в диапазон ЦАПа(-32768 до +32767) не влазят.
Что с этим делать это решать вам(зависит от задачи).
Например можно организовать нормализацию https://ru.wikipedia.org/wiki/%D0%9D%D0%BE%...%83%D0%BA%D0%B0 или компрессию динамического диапазона https://ru.wikipedia.org/wiki/%D0%9A%D0%BE%...%B0%D0%BB%D0%B0

Хорошей идеей было бы на выходе тракте цифровой обработки сигнала сделать так, чтобы данные были представлены числами от -1 до 1. Т.е. нормализовать их. Тогда вы будете знать, что 1 это максимальный уровень, а -1 минимальный. "Вписать" такой сигнал в нужный диапазон значений можно будет простым умножением на константу.

В общем потом, когда ваши данные так или иначе укладываются в диапазон ЦАПа(-32768 до +32767) применяете тот самый виртуальный 0.
DAC_REGISTER = 32768 + filter_data[i];
И не надо заморачиваться как там это будет посчитано и как в системе хранится отрицательное значение. Тестировать там какие-то биты в данном случае - дичайший говнокод.

Цитата
3) Мне коэффициенты надо с компьютера передавать, а они у меня float теперь.

Учитывая, что большинство машин сейчас уважают IEEE 754 стандарт ваш хак с вычленением байт конечно будет работать, но назвать этот подход правильным нельзя.
Если делать правильно и портабельно, то в том числе передают даже в виде строки. sprintf() на стороне передатчика, sscanf() на стороне приемника sm.gif
Либо определяйтесь, что между компьютером и устройством коэффициенты передаются в формате с фиксированной точкой, чтобы всё было чётко определено и задокументировано.
Еше стоит учесть, что бывают машины с разным порядком байт https://ru.wikipedia.org/wiki/%D0%9F%D0%BE%...%82%D0%BE%D0%B2




--------------------
The truth is out there...
Go to the top of the page
 
+Quote Post
Atlantis-
сообщение Aug 30 2016, 07:22
Сообщение #32


Местный
***

Группа: Участник
Сообщений: 491
Регистрация: 18-05-11
Пользователь №: 65 102



Цитата(sigmaN @ Aug 29 2016, 22:11) *
Корректнее наверно тут использвоать округление вместо простого отбрасывания дробной части http://www.cplusplus.com/reference/cmath/ceil/

Нашел в интернете округление - просто прибавление 0.5 к float. Жалко с отрицательными не прокатит, там надо вычитать, снова if надо городить


Цитата(sigmaN @ Aug 29 2016, 22:11) *
Что это за ЦАП то такой у вас? Прям с двухполярным питанием и честной выдачей наружу напряжения ниже нуля?
Очень сомневаюсь. Регистр ЦАПа скорее всего беззнаковый от 0 до скольки там разрадность позволяет.
А потому за 0 надобно принять половинку разрядности ЦАПа. Если он например 16ти разрядный, то за 0 надо принять половинку 2^16 / 2 = 32768
Таким образом получившиеся после фильтра циферки перед передачей в ЦАП надо приготовить.
У вас будет еще одна задачка если в процессе цифровой обработки получились космические цифры, которые в диапазон ЦАПа(-32768 до +32767) не влазят.
Что с этим делать это решать вам(зависит от задачи).
Например можно организовать нормализацию https://ru.wikipedia.org/wiki/%D0%9D%D0%BE%...%83%D0%BA%D0%B0 или компрессию динамического диапазона https://ru.wikipedia.org/wiki/%D0%9A%D0%BE%...%B0%D0%BB%D0%B0

Хорошей идеей было бы на выходе тракте цифровой обработки сигнала сделать так, чтобы данные были представлены числами от -1 до 1. Т.е. нормализовать их. Тогда вы будете знать, что 1 это максимальный уровень, а -1 минимальный. "Вписать" такой сигнал в нужный диапазон значений можно будет простым умножением на константу.

В общем потом, когда ваши данные так или иначе укладываются в диапазон ЦАПа(-32768 до +32767) применяете тот самый виртуальный 0.
DAC_REGISTER = 32768 + filter_data[i];
И не надо заморачиваться как там это будет посчитано и как в системе хранится отрицательное значение. Тестировать там какие-то биты в данном случае - дичайший говнокод.

ЦАП - CS4344, пробовал на AD1852. Ни в том ни в другом даташите не нашел, как же представлять отрицательные числа. Но это как то должно наверно быть обозначено?
Для AD1852 написал тестовую синусоиду, сначала я не парился, думал, что максимальное отрицательное значение - это 0х000000. Проверил - какая то фигулька получилась, а не синусоида. Потом вот просто начал инвертировать положительные значения - получилась синусоида, размах вроде как и должен быть. А для CS4344 я просто подал тот же массив - получилась синусоида, ну и хорошо.
А вообще мне интересно, как обозначается в доке, каким способом кодируется отрицательные значения в ЦАП?

Цитата(sigmaN @ Aug 29 2016, 22:11) *
Учитывая, что большинство машин сейчас уважают IEEE 754 стандарт ваш хак с вычленением байт конечно будет работать, но назвать этот подход правильным нельзя.
Если делать правильно и портабельно, то в том числе передают даже в виде строки. sprintf() на стороне передатчика, sscanf() на стороне приемника sm.gif
Либо определяйтесь, что между компьютером и устройством коэффициенты передаются в формате с фиксированной точкой, чтобы всё было чётко определено и задокументировано.
Еше стоит учесть, что бывают машины с разным порядком байт https://ru.wikipedia.org/wiki/%D0%9F%D0%BE%...%82%D0%BE%D0%B2

Да мне главное правильно собрать float из байтов на микроконтроллере. А разобрать его на компе - чисто для проверки. Хотя зачем, я могу даже сразу вручную разобрать все нужные float-ы на байты, на этом сайте http://floatingpoint.ru/online/dec2float.php
Хранить и передавать в виде байт. Тем более коэффициенты у меня все уже вычислены. Наверно так будет наиболее надежно))
Go to the top of the page
 
+Quote Post
sigmaN
сообщение Aug 30 2016, 11:15
Сообщение #33


I WANT TO BELIEVE
******

Группа: Свой
Сообщений: 2 617
Регистрация: 9-03-08
Пользователь №: 35 751



Цитата
Нашел в интернете округление - просто прибавление 0.5 к float. Жалко с отрицательными не прокатит, там надо вычитать, снова if надо городить

Именно так.

Цитата
А вообще мне интересно, как обозначается в доке, каким способом кодируется отрицательные значения в ЦАП?
Ну какие могут быть отрицательные значения при однополярном питании?
В принципе я вам направление для мысли дал. Разбирайтесь....


--------------------
The truth is out there...
Go to the top of the page
 
+Quote Post
ig_z
сообщение Aug 30 2016, 12:00
Сообщение #34


Местный
***

Группа: Свой
Сообщений: 437
Регистрация: 27-08-04
Пользователь №: 551



QUOTE (sigmaN @ Aug 30 2016, 14:15) *
Ну какие могут быть отрицательные значения при однополярном питании?

TC использует аудио цап ацп. Сейчас они все двуполярные по коду и однополярные по питанию. В ацп даже цифровой фильтр на несколько гц встраивают, чтобы фильтровать смещение нуля (аналоговое, как я понимаю).
Go to the top of the page
 
+Quote Post
sigmaN
сообщение Aug 30 2016, 12:05
Сообщение #35


I WANT TO BELIEVE
******

Группа: Свой
Сообщений: 2 617
Регистрация: 9-03-08
Пользователь №: 35 751



Не знал, не знал. Ну тогда даташит на ЦАП в помощь ТСу ))))


--------------------
The truth is out there...
Go to the top of the page
 
+Quote Post
Atlantis-
сообщение Aug 30 2016, 14:02
Сообщение #36


Местный
***

Группа: Участник
Сообщений: 491
Регистрация: 18-05-11
Пользователь №: 65 102



Вот я смотрю даташиты на оба ЦАП и не нахожу даже упоминания про то какие данные отправлять и как кодируется отрицательный диапазон...
Go to the top of the page
 
+Quote Post
Atlantis-
сообщение Aug 31 2016, 12:16
Сообщение #37


Местный
***

Группа: Участник
Сообщений: 491
Регистрация: 18-05-11
Пользователь №: 65 102



Нашел ответ на свой вопрос
Цитата
The AD1852 accepts serial audio data
in MSB first, twos-complement format.
Go to the top of the page
 
+Quote Post
sigmaN
сообщение Sep 1 2016, 10:24
Сообщение #38


I WANT TO BELIEVE
******

Группа: Свой
Сообщений: 2 617
Регистрация: 9-03-08
Пользователь №: 35 751



Ну вот, значит отрицательные числа представлены так-же как и в процессоре
осталось только разобраться с MSB first...
B в MSB имеется ввиду Bit или Byte?
если Byte то получается Big Endian, а проц у вас Little endian.... https://ru.wikipedia.org/wiki/%D0%9F%D0%BE%...%82%D0%BE%D0%B2
Может быть поэтому во время эксперимента у вас не получалась синусоида....


--------------------
The truth is out there...
Go to the top of the page
 
+Quote Post
ig_z
сообщение Sep 1 2016, 17:34
Сообщение #39


Местный
***

Группа: Свой
Сообщений: 437
Регистрация: 27-08-04
Пользователь №: 551



QUOTE (sigmaN @ Sep 1 2016, 13:24) *
если Byte то получается Big Endian, а проц у вас Little endian....

Это забота аппаратного аудио интерфейса в процессоре, если ТС его использует. Более вероятна проблема выбора 32 бит данных через 16 бит порты в некоторых "оптимизированных" платформах
Go to the top of the page
 
+Quote Post
Atlantis-
сообщение Sep 5 2016, 13:51
Сообщение #40


Местный
***

Группа: Участник
Сообщений: 491
Регистрация: 18-05-11
Пользователь №: 65 102



Сделал полосовые фильтры, проверил - все нормально. А с режекторным какая то засада, не понимаю, где может быть ошибка?
Делаю вот так:
Код
        struct {
        
        float a0;
        float a1;
        float a2;
        float b1;
        float b2;
        int k;
        int k1;
        int k2;    
            
        float X[4];
        float Y[4];
            
        int Y1;
            
    } NotchedFilter;


в прерывании I2S
Код
//выдаю данные
hsai_BlockA1.Instance->DR = noise.NotchedFilter.Y1;
hsai_BlockA1.Instance->DR = noise.NotchedFilter.Y1;
//считаю следующий отсчет
//                    noise.NotchedFilter.Y[noise.NotchedFilter.k] = noise.NotchedFilter.a2*noise.NotchedFilter.X[noise.NotchedFilter.k2] +
//                    noise.NotchedFilter.a1*noise.NotchedFilter.X[noise.NotchedFilter.k1] + noise.NotchedFilter.a0*noise.NotchedFilter.X[noise.NotchedFilter.k] -
//                    noise.NotchedFilter.b1*noise.NotchedFilter.Y[noise.NotchedFilter.k1] - noise.NotchedFilter.b2*noise.NotchedFilter.Y[noise.NotchedFilter.k2];
                    
                    noise.NotchedFilter.Y[noise.NotchedFilter.k] = noise.NotchedFilter.a2*(noise.NotchedFilter.X[noise.NotchedFilter.k2] + noise.NotchedFilter.X[noise.NotchedFilter.k]) +
                    noise.NotchedFilter.a1*(noise.NotchedFilter.X[noise.NotchedFilter.k1] - noise.NotchedFilter.Y[noise.NotchedFilter.k1]) -
                    noise.NotchedFilter.b2*noise.NotchedFilter.Y[noise.NotchedFilter.k2];
                    noise.NotchedFilter.Y1 = noise.NotchedFilter.Y[noise.NotchedFilter.k];//оптимизировал а0=а2, а1=b1
                    
                    noise.NotchedFilter.k = (noise.NotchedFilter.k + 1)&BUFFMASK;
                    noise.NotchedFilter.k1 = (noise.NotchedFilter.k - 1)&BUFFMASK;//посчитали индекс Xk-1
                    noise.NotchedFilter.k2 = (noise.NotchedFilter.k - 2)&BUFFMASK;//посчитали индекс Xk-2


что тут может быть не так? проверил под отладкой - k меняется как и должно, сам посчитал один отсчет - сошлось с показанием процессора.
Go to the top of the page
 
+Quote Post
Atlantis-
сообщение Sep 6 2016, 07:45
Сообщение #41


Местный
***

Группа: Участник
Сообщений: 491
Регистрация: 18-05-11
Пользователь №: 65 102



Как то так получается, что при подаче на вход режекторного фильтра 24-битного числа, на выходе получается зашкал. Все нормально фильтрует, если подавать на вход 22-битное число или сдвигать на 2 результат.
Может кто-нибудь подсказать, как такое может получиться? В матлабе у фильтра никакого усиления нет.
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 23rd July 2025 - 00:16
Рейтинг@Mail.ru


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