Форум Радиолюбителей

Цифровая АРУ 0...1

243433 просмотров, 284 ответов — стр. 11 из 19

Игорь 2
Сообщений: 21288
15 ноября 2020 г. в 07:37#151
Это розовый шум!!

Какой же он розовый? Судя по спектру, это всё-таки, белый шум - спектр ровный.
Да и откуда там розовому взяться, только при косячном приёмнике - напомню, розовый шум имеет спектр -6 дБ/октава.
ra0ahcra0ahc
Сообщений: 4868
15 ноября 2020 г. в 08:21#152
Так и есть. Поэтому я им и пользовался для тестов, у него, у шума, низов больше и сигнал более сложный получается чем белый (по структуре). На белом ставишь вроде нормально работает, переключаешь на розовый и упс, идут завалы.
ra0ahcra0ahc
Сообщений: 4868
16 ноября 2020 г. в 05:31#153
Нашел утечку памяти и еще пару досадных ошибок (логических, это же анализ )

Теперь так:
(там где дельта 0 то это стробирование около 1, алгоритм пытается держать 1 без диапазона гистерезиса по усилению, ну и там где дельта 0.3 - это как раз гистерезис)


ra0ahcra0ahc
Сообщений: 4868
16 ноября 2020 г. в 05:32#154
Вот так сейчас
Код: [Выделить]float32_t max = 0.49975586f; //максималка от -0.5 до +0.5 примерно для 12 бит
uint16_t count = 100;
uint8_t stopGoingUp = 0;
float32_t rmsPik = 0;
float32_t rmsFrame = 0;

void agcDo(float32_t *buffer) {

float32_t agcMetrTemp = 0;
float32_t pit1 = -1;
float32_t pit2 = 0;

if (tim > 0)tim--; //уменьшение задержки
stopGoingUp = 0;

for (uint16_t i = 0; i < FRAME_SIZE; i++) {
float32_t a;
//a = (buffer[i] < 0.0f) ? -1.0f * buffer[i] : buffer[i];// adc V
a = fabsf(buffer[i]);
// seach min
if (a > 0)nowAgc = max / a;
else nowAgc = max / 0.000005f;

uint16_t upIdx = i;
uint16_t upIdxNow ;

float32_t pikBuf = -1;
uint8_t exit = 1;
uint8_t exitYN = 0;
uint16_t wait = 48;// 1msec
int direction = 0;//напрвление вниз (отрицательная синусоида)

if (buffer[i] > 0) direction = 1;//напрвление вверх (положительная синусоида)
if (buffer[i] == 0) exit = 0; //пропустим поиск пика в блоке

while (exit) { //поиск пика в блоке от 0 до 0
exit = 0;//выходим
float32_t p1 = fabsf(buffer[upIdx]);//feature
upIdxNow = upIdx;
if (direction) {//+++++++++++++++++++++++++++++
//если условие остановило в ++ то добиваем его до 0
if ((buffer[upIdx] >= 0 && !exitYN) || (upIdx - i < wait)) {
if (p1 > pikBuf) {
pikBuf = p1;
}
if (upIdx + 1 < FRAME_SIZE) {
upIdx++;
exit = 1;//не выходим
}
}
//если условие остановило в -- то добиваем его до 0 и выходим
if ((buffer[upIdxNow] < 0) && (upIdxNow - i >= wait)) {
exitYN = 1; //не дадим пред условию сработать
if (p1 > pikBuf) {
pikBuf = p1;
}
if (upIdxNow + 1 < FRAME_SIZE) {
upIdx++;
exit = 1;//не выходим
}
}

} else { //------------------------
//going up
//если условие остановило в -- то добиваем его до 0 и выходим
if ((buffer[upIdx] <= 0 && !exitYN) || (upIdx - i < wait)) {
if (p1 > pikBuf) {
pikBuf = p1;
}
if (upIdx + 1 < FRAME_SIZE) {
upIdx++;
exit = 1;//не выходим
}
}
//если условие остановило в ++ то добиваем его до 0
if ((buffer[upIdxNow] > 0) && (upIdxNow - i >= wait)) {
exitYN = 1; //не дадим пред условию сработать
if (p1 > pikBuf) {
pikBuf = p1;
}
if (upIdxNow + 1 < FRAME_SIZE) {
upIdx++;
exit = 1;//не выходим
}
}
}
//добавим блок если в нем есть глобальный пик (выброс)
if (upIdx - i >= wait && max / pikBuf > agcLevel) {
if (256 + upIdx < FRAME_SIZE) wait = 256;
}

}//while

if (upIdx > i) { //если блок не пустой то...
//upIdx--;
float32_t locNowAgc;
//проверка на 0
if (pikBuf != 0) {
locNowAgc = max / pikBuf;//максимальное значение
} else locNowAgc = max / 0.00005f;
//типа среднее значение . исползуется для отката .
rmsPik = (rmsPik + pikBuf) / 2.0f;

//agcLevel == текущий уровень ару
if (locNowAgc < agcLevel) { // всплеск или питч V, идем вниз ..........................
stopGoingUp = 0;
//заполним блок
if (i > 0) {
for (uint16_t z = i; z <= upIdx; z++) {
buffer[z] *= locNowAgc;//применить новый коэфф
}
} else {//механизм сочленения с пред фреймом ...ждем первого нуля
if (buffer[0] > 0) direction = 1;//напрвление вверх (положительная синусоида)
exit = 1;
uint16_t idx0 = 0;
while (exit) {
exit = 0;//выходим
if (direction) {//+++++++++++++++++++++++++++++
if (buffer[idx0] > 0) {
idx0++;
exit = 1;//не выходим
}
} else { //------------------------
//going up
if (buffer[idx0] < 0) {
idx0++;
exit = 1;//не выходим
}
}
}//while
for (uint16_t z = 0; z <= upIdx; z++) {
if (z <= idx0)buffer[z] *= agcLevel;//применить старый коэфф
else buffer[z] *= locNowAgc;//применить новый коэфф
}
}

tim = 10;//задежка отпускания
if ((pit2 < pit1 && pit1 < pikBuf)) {//смотрим следующий питч если
agcLevel = locNowAgc;
// agcLevel -= (agcLevel - locNowAgc) / 1;
tim = 30;//задежка отпускания
} else if ((pit2 < pit1 && pit1 > pikBuf)) {//смотрим следующий питч если
agcLevel -= (agcLevel - locNowAgc) / 5;
} else {
agcLevel -= (agcLevel - locNowAgc) / 2;
}

pit2 = pit1;
pit1 = pikBuf;

} else {//идем вверх/////////////////////////////////////////////////////////////////////

float32_t cc;

if (tim == 0) {//подождали и начинаем
cc = agcLevel + (locNowAgc - agcLevel) / 600;
//проверим можем нет еще откатить
if (rmsFrame * cc < max - 0.3f && !stopGoingUp) {//дельта отката 0.4
agcLevel = cc;
} else stopGoingUp = 1; //остановить откат
}
//заполним полупериод
for (uint16_t z = i; z <= upIdx; z++) {
buffer[z] *= agcLevel;//применить новый коэфф
}
}
i = upIdx; // след цикл будет стратовать от upIdx

} else { //это сидуация редкая но тоже надо . сделано по класике одного замера

if (nowAgc < agcLevel) { // всплеск V
agcLevel -= (agcLevel - nowAgc) / 2;
// tim = 10;//задежка отпускания
}
float32_t f = a * agcLevel;
//контроль вылета в out
if (f > max) {//out
if (buffer[i] >= 0) buffer[i] = max;//max
else buffer[i] = -max;//max
// agcLevel = 1;
} else
buffer[i] *= agcLevel;

}

if (a > agcMetrTemp) agcMetrTemp = a; //s-meter макс V
}//for
rmsFrame = (rmsFrame + rmsPik) / 2.0f;
agcMetr = agcMetrTemp; //s-meter

ra0ahcra0ahc
Сообщений: 4868
16 ноября 2020 г. в 05:37#155
дерьмо пришло к нам в семью сегодня ночью
грёбанный вирус , забирает близких
Игорь 2
Сообщений: 21288
16 ноября 2020 г. в 06:44#156
У сестры тоже все болеют...
6Ж2П6Ж2П
Сообщений: 1065
16 ноября 2020 г. в 10:52#157
розовый шум имеет спектр -6 дБ/октава.
Нет, спад 3дб/октава
Игорь 2
Сообщений: 21288
16 ноября 2020 г. в 11:35#158
спад 3дб/октава

Согласен...
ra0ahcra0ahc
Сообщений: 4868
28 ноября 2020 г. в 06:35#159
Замеры, замеры, замеры

Идет CW WW
Запись с WEB SDR Тульского.

3 варианта записи
1. Тульский АРУ выключен, работает только моя платка и мое АРУ
2. Работает Тульское АРУ и мое АРУ
3. Только Тульский WEB SDR, моя платка отключена физически.

PS несложно заметить, что мое ару спасает на 2-3 дб тульское ару, а если вообще без меня то стучит безбожно морзянка и всплески до 10дб ....это абзац.

ra0ahcra0ahc
Сообщений: 4868
28 ноября 2020 г. в 06:38#160
...

ra0ahcra0ahc
Сообщений: 4868
30 ноября 2020 г. в 09:51#161
А я тут опять сел за АРУ

Проблема в том , что нельзя просто применить коэффициент к полупериоду, и даже к полному периоду. И даже нельзя применить последовательное наращивание коэффициента. Все это приводит к изменению синуса (как на картинке).
На фото как раз работа ару по полупериоду. Такой подход стучит и это видно на анализаторе.

ra0ahcra0ahc
Сообщений: 4868
30 ноября 2020 г. в 09:59#162
Что делать? Нужно восстанавливать синусоиду. Мне кажется от пика до пика следующей полуволны. И работать нужно по разному. Тот пик который мы занижаем (реакция на всплеск) мы просто умножаем на 0.ХХ коэффициент и тем самым мы этот полупериод прижимаем ближе к 0. НО! с предыдущем пиком нельзя также делать, у него растет горб. Там нужен другой коэффициент, и причем пик этой полуволны трогать нельзя он должен остаться. Смежные скаты полуволн похожи на улитку. С каждым шагом увеличивается радиус улитки.
Вот я и говорю, синусоиду нужно восстанавливать.
ra0ahcra0ahc
Сообщений: 4868
1 декабря 2020 г. в 02:28#163
Вот этот более наглядней

ra0ahcra0ahc
Сообщений: 4868
1 декабря 2020 г. в 02:30#164
Если идет от 0 изменение амплитуды , то вроде все ок, легкое расширение спектра и всё, но если точка изменение амплитуды отстоит от 0 то спектр разливается почти до конца. Не так конечно как при ступеньке, но все же его видно и слышно.
ra0ahcra0ahc
Сообщений: 4868
1 декабря 2020 г. в 02:32#165
Эксперименты продолжаются. Надо почти полностью алгоритм переделывать. Сейчас я меняю амплитуду скачкообразно внутри системы без АЦП