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

iiv

Свой
  • Постов

    2 895
  • Зарегистрирован

  • Посещение

  • Победитель дней

    3

Весь контент iiv


  1. если к концу этой записи из 500 выборок ваш сигнал не сделает точно 10 периодов, то мой алгоритм, что я привел выше, покажет лажу. Как правильно заметил выше уважаемый Plain - надо о синхронизации подумать. Более точное значение лажи: если у вас клок убежит на n отсчетов, то при ваших 50 отсчетов на период, вы поимеете ошибку в фазе порядка 360*n/25 градусов, может чуть меньше. Много или нет - Вам судить.
  2. тогда все просто! Я нарисовал аналог Герцеля с вычислением фазы и добавил тестовый пример, фаза вычисляется довольно точно. Может не только Вам на форуме это будет полезно. #include <stdio.h> #include <stdlib.h> #include <math.h> class sPhase { float c, s; // это все вспомогательные float c1, s1, c2, s2; // переменные, float c_ini, s_ini; // их не надо int CurCount, Len; // трогать public: float Angle; // уже после полного первого периода тут будет сохраняться разность фаз сигналов в радианах void Ini(int PLen) // PLen - длина периода в количестве отсчетов АЦП, то есть, например, если АЦП работает на 500кГц, период сигнала 10кГц, то PLen = 500/10=50 { if(PLen<4) { printf("Ini: incorrect argument\nTerminated\n"); exit(1); } sincosf(2.*M_PI/(float)(Len=PLen), &s_ini, &c_ini); CurCount=0; c1=s1=c2=s2=s=Angle=0.; c=1.; }; void InputData(float v1, float v2) { c1+=c*v1; c2+=c*v2; s1+=s*v1; s2+=s*v2; if(CurCount==Len-1) { CurCount=0; Angle=atan2f(c1*s2 - c2*s1, c1*c2 + s1*s2); c=1.; c1=s1=c2=s2=s=0.; } else { CurCount++; float new_c=c*c_ini-s*s_ini; float new_s=s*c_ini+c*s_ini; c=new_c; s=new_s; } }; sPhase(int PLen) { Ini(PLen); }; // фиктивный конструктор, чтобы не повадно было не инициализировать этот класс }; inline float my_rand() { return (float)(2.*((float)rand()/(float)RAND_MAX-0.5)); } // функция генерации случайного числа в диапазоне от -1. до 1. int main() // тестовый пример { const float Alpha1=0.1, Alpha2=2.; // две фазы для первого и второго сигналов в радианах const int PLen = 50; // длина одного периода в количестве отсчетов АЦП const float Amp1 = 9.4, Amp2 = 2.1; // амплитуды сигналов, возьмем разные, от балды const float Bias1 = 2.6, Bias2 = -3.5; // сдвиг нуля сигналов, тоже возьмем два разных от балды const float NoiseLevel=0.5; // уровень шума sPhase sP(PLen); // вызовем конструктор с аргументом в виде длины периода сигнала for(int i=0; i<1000; i++) { float v1 = Bias1 + Amp1*sinf(((float)i)*2.*M_PI/(float)PLen + Alpha1) + NoiseLevel*my_rand(); float v2 = Bias2 + Amp2*sinf(((float)i)*2.*M_PI/(float)PLen + Alpha2) + NoiseLevel*my_rand(); sP.InputData(v1, v2); // подавать сюда два измеренных сигнала printf("%f %f %f\n", v1, v2, sP.Angle); // и радоваться получению разности фаз в sP.Angle } printf("We are expecting the angle as %f, and it was computed as %f\n", Alpha1-Alpha2, sP.Angle); return 0; } код на минималистическом С++ с тестовым примером под gnu-linux компилятор. На каждый приход пары данных из АЦП надо вычислять всего-то 8 умножений и 7 сложений, и на каждый период дополнительно вычислять один арктангенс. Если что-то не понятно - спрашивайте.
  3. вы прежде скажите на сколько синхронны ваша частота и частота оцифровки: 1. всегда имеют фиксированный коэффициент, 2. плывет во времени, 3. не знаю, так как это из разных клоковых домейнов - (нужное подчеркнуть). Если сонхронна, то на каждую пару оцифрованных данных вам надо будет 12 умножений и с десяток сложений + примерно на каждый сотый раз прихода оцифрованных данных одно дополнительное вычисление квадратного корня, и в момент, когда вы хотите посчитать фазу, один раз вычисление арктангенса, который atan2(x,y). Вспомогательной памяти с десяток чисел. Любой самый дохлый М0 кортекс справится, даже в атмегу могу на спор засунуть, если она сама оцифровывать будет 🙂 Использовать плисину на такую задачу - реально очень жирно и бессмысленно.
  4. Для алгоритма Герцеля (он проще в понимании и реализации) важно не только ее примерное значение, а тот факт, что АЦП будет синхронно с источником этой частоты работать. Герцель я тоже несколько раз применял, если не найду у себя готовый, напишу, он реально проще методов Прони. Хотя Прони будет работать всегда. Если под непрерывностью измерений вам достаточно каждую миллисекунду знать на сколько фазы разбежались, то это как раз возможно. Если еще в 10 раз чаще, то тоже можно, но немного сложнее.
  5. согласен, что смысла нет, но Герцель-то тоже не бесплатно считается. Для последовательности из n чисел ему надо 6n операций, а ФФТ (при n=1024) потребует только 25n, то есть от 5-ой частоты ФФТ будет быстрее. Да и для Герцеля основное преимущество - работа на дробной частоте, но если она заранее не известна и подбирается, то тоже хранить все придется. То есть будь я на месте ТС примерно с его уровнем знаний, и если бы частота точно известна была бы, то да, Герцелем или МНК, а если частота известна только прикидочно - тут все будет зависеть от того, что проще где-то утянуть, чтобы самому не отлаживать.
  6. по идее да, я тоже так вначале подумал, но если ТС аналогом где-то не в МК это делает и там еще какой-нибудь Доплер над ней шаманит, там может быть не все так просто. Но, дождемся ответа ТС. ох от там глюков наловит, и данные все хранить надо. Там проще Фурьем грохнуть сразу и на спектральной части параболу строить, по крайней мере из коробки Фурье для STMов думаю, найти можно. Не спорю, что через сингулярное разложение посложнее для понимания, но арифметическая сложность совсем копеешная получается, и всегда во Фробениусовой норме все как-то надежнее и точнее вычисляется.
  7. а у ТС частота известна точно, или нет? Если точно, то да, Герцелем тоже можно, но ИМХО, еще проще и понятнее вообще через МНК оба сигнала по синусу, косинусу и константе разложить и по полученным коэффициентам посчитать фазу.
  8. точность от АЦП конечно зависит, но я много раз такие вещи считал в цифре и хочу вас склонить к этому методу 🙂 Вам надо оцифровать два сигнала длительностью больше, чем одна амплитуда, и на основе этого набора чисел можно посчитать сдвиг фаз. Вычислительная стоимость будет несколько синусов/арктангенсов + сколько-то (константное число около полусотни) арифметических операций + 7*n умножений и 7*n сложений, где n - число оцифрованных точек. В вашем случае, если оцифровывать на частоте 500кГц, скажем примерно 5 периодов, то есть 0.5мс, то должно хватить с очень большим запасом да и процессор, как а понимаю, должен справиться. Что именно делать могу рассказать, но будет заумно. Если решитесь, могу запрограммировать (вытащив из своих наработок) и здесь выложить. Ключевая идея в следующем: у вас есть два сигнала, f(x), g(x), каждый из которых есть сумма синуса и косинуса с одной и той же частотой. Вы к этому всему добавляете еще пару сигналов f(x+dx), g(x+dx), где dx - шаг оцифровки, и получаете уже набор из 4 таких сумм. На них надо набросить сингулярное разложение и вытащить две самые "численно яркие" функции, которые как раз соответствуют этим синусам и косинусам. Если не добавить f(x+dx), g(x+dx) - вы получите только линейную комбинацию с шумами, и это вас тотально запутает. Получив синусы и косинусы надо только посчитать МНК каждого из сигналов в терминах этих синусов и косинусов, а потом по коэффициентам выполнить тригонометрическую формулу и посчитать фазу. Если у вас есть эти два оцифрованных сигнала, и вы готовы их здесь выложить, могу прогнать на своем софте и посчитать фазу, если понравится, преобразую свой софт под эту задачу и выложу полученную софтину здесь. EDIT: то, что я предлагаю относится к классу алгоритмов Generalized pencil-of-function method и метода Прони, ссылки на эти методы конечно же гуглятся.
  9. можно было погуглить добавив тот процессор, на котором я это тестировал (esp32), можно было догадаться, что это - измерение времени в тактах процессора. Такое чувство, что мне больше надо, чтобы у вас это запустилось, чем вам, так как вы, к моему полнейшему сожалению, совершенно не проявляете любопытства и не пытаетесь додумать что в каких местах этого кода могло бы быть написано 😞 Призываю, или действительно забить на мое решение и искать свой самостийный путь, или начать хоть чуть чуть читать, что я уже написал и хоть чуть-чуть думать. Вы за это время могли бы сами этот код в вами удобных обозначениях записать и оттестировать, но похоже, вам больше интересно это обсуждать, чем реально получить результат. Предвкушая ваш следующий вопрос, а то вы опять что-то не дочитаете, тайминги у вас могут слегка отличаться от моих, поэтому значения NOP_Param_1, NOP_Param_2 могут быть на несколько единиц больше или меньше и их надо подобрать методом научного тыка, ну или решив не сильно сложное уравнение. Это уравнение я не стал здесь приводить, так как по опыту предыдущих Ваших вопросов я уверен, что не смогу даже за неделю вам это объяснить, и предлагаю совместно сэкономить наше время, а решать научным тыком. да, очень вас понимаю, поэтому в своих подделках в первую очередь стараюсь создать удобную для себя среду разработки, и только потом начинаю что-то разрабатывать. Часто из-за этото бываю сильно ограничен типами используемых контроллеров, но зато, могу разрабатывать довольно заумные алгоритмы прямо в железе. Попробуйте также, может этот совет вам тоже будет полезен.
  10. вы на форуме эти жалкие три строчки обсуждаете дольше, чем если бы взяли мой специально для вас готовый код и посмотрели бы как работает. Вам же разжевали и на блюдечко положили, а вы все сомневаетесь, и, что самое удивительное, ни прилагаете ни малейшей попытки понять эту идею.
  11. у вас наверное сложности сравнить 36 с 40 🙂 конечно там масса возможностей, главное - уловить суть - сделать два цикла, один на 6 тактов, другой на 7, и для любой произвольной задержки выбрать сколько надо первого и второго цикла. Дешего, сердито, и довольно кросс-платформено.
  12. 700кГц по идее должно потянуть, вернее если на вашем процессоре первый цикл тоже как у меня 6 тактов, то 888кГц и ниже все должно охватить. а чем он больше-то? У меня в страницу поместилось все со всеми тестами. Если говорить о том, что вам конкретно надо, так это только nop_delay1 и nop_delay2, которые займут примерно 50 байт в бинарнике. Я сомневаюсь, что простыня нопов и скачки по ним будут лучше, а то, что ваш метод дает вольность контроллеру не закачивать часть нопов из флеша, даст вам сказочные неприятности, у вас то будет работать, то не будет работать.
  13. сделаю еще одну попытку прояснить вам мою идею. У вас stm32g070, у которого такт - 64МГц и вам нужен ногодрыг на 500кГц, то есть между переключениями у вас есть как минимум 64 такта. То, что я предлагаю, позволяет дозировать задержку с точностью до одного такта в диапазоне от 36 тактов до бесконечности. То есть вы с легкостью получите 500кГц, выставив 64 такта задержку, и 64/65/2*1000=492.3кГц, а если согласитесь на слегка не 50% форму сигнала, то и 64/129*1000=496.12кГц. Больше с этого дохлого контроллера взять не получится. ЗЫ: хоть и мое решение занимает меньше страницы уже отлаженного кода, считаю, что ТС надо при таких хотелках задуматься о более жирном процессоре, а лучше плиске. Не рекламы ради, очень советую взять мелкий GoWin - на нем с легкостью можно сделать шаг в районе 500кГц вплоть до единиц Герцев, если конечно еще подавать слегка не равномерные длины окон тактовой.
  14. спасибо большое за совет, но вот это правило я не смогу выполнить. От АКБ питается суммарно 4 мотора (у каждого по драйверу) с токами по 10-20А на каждый и с пиковыми токами до 50А на каждый. Кроме этого на том же АКБ висит два вычислительных модуля, которые тоже по 5-10А потребляют. Вот они-то и общаются с МК, который напрямую управляет драйверами моторов. То есть я в любом случае имею систему в виде звезды, что от АКБ к сильноточным идут свои провода, но вот есть малоточный блок с МК, который дергает драйверы моторов. Вот в нем был вопрос, но похоже правильно как сказал Amaora: его землю зацеплять на землю драйвера и ловить шумы при общении его с другими модулями.
  15. не, наверное я не совсем понятно написал в первом сообщении. АКБ у меня питает все, и мотор и МК, который управляет драйверами мотора, и другие МК, которые общаются с МК по SPI. Но вот скачки тока до 50А по 6мм^2 сечению провода длиной 30см (это около 1миллиома) уже могут дать скачки порядка 50мВ, а может и больше, если там будет возникать скин эффект.
  16. Прочитайте внимательно что я вам посоветовал не выдирая из всего кода кусочки, и вам обязательно откроется тайна одного такта 🙂 Для тех, кто совсем в танке, повторяю: два цикла с длительностью (С) первого на один такт меньше, чем второй (С+1). Для любой величины задержки T>C^2 всегда можно выбрать такие два числа t1, t2, так, что C*t1 + (C+1)*t2 = T.
  17. вы все-таки хотя бы немного задумайтесь что именно я вам советую. Я же не зря специально для вашего случая пару часов кодил и тестировался. У меня точность в один такт разрешение моего таймера получается.
  18. Добрый день, у меня есть трехфазный мотор (коптера), который управляется через 3 полумоста. Управление мостов на МК. Мотор потребляет примерно 10-20А на 11В или 14В, а может и на 22В перейду, но в пике там и 50А бывает. От БП (литийполимерных аккумуляторов) идет примерно 30см провода (6мм сечения) до этого блока. У меня есть две версии системы, которые работают, но я не проводил долговременные и всеобъемлющие испытания. В первой - у меня земля драйверов мосфетов на плате соединена с землей МК. По проводу, который идет к этой плате (30см) я измеряю еще одним дополнительным проводом падение и, через дифф-усилитель подучаю ток. МК соединен со внешним миром и общается по SPI на 1МГц пакетами по несколько байт и синхроимпульсом на 80кГц. Во второй - у меня земля драйверов отделена от земли МК, а земля МК соединена с землей того, кто посылает SPI пакеты этому МК. По разнице напряжения земель драйвера и МК я примерно измеряю ток по драйверу. Сам я вижу, что у первой схемы могут быть проблемы при передаче данных, если вдруг земля драйвера из-за высоких токов будет создавать наводки. Во второй - вроде могут возникать наводки или не быстрые включения мосфетов (мосфеты включаю через драйверы). Грубо говоря обе схемы погонял примерно по часу, работают они примерно одинаково, КПД примерно одинаковый, битые пакеты по SPI редко, но встречаются. Тестировать долговременно довольно сложно, и хочется остановиться на одной из них. Посоветуйте, пожалуйста, на какой схеме правильнее остановиться и почему? Спасибо! ИИВ
  19. Может чтобы обойти проблему со считыванием из флеша длинного кода попробовать по-другому: взять два цикла с одним и с двумя НОПами, и в зависимости от величины задержки крутить оба цикла с разной длиной параметров. Я попробовал это на другой архитектуре (esp32), не могу сказать, что стоит как вкопанное, так как много другого дергается попутно, но у Вас может и будет с точностью до такта получаться. Сам код: #pragma GCC push_options #pragma GCC optimize ("Ofast") #include <stdio.h> #include <math.h> #include <Arduino.h> static int NOP_Param_1=6; static int NOP_Param_2=6; void nop_delay1(unsigned int t1, unsigned int t2) { unsigned int i; i=t1; while(i>0) { asm("nop"); i--; } i=t2; while(i>0) { asm("nop"); asm("nop"); i--; } return; } // total time is: t1*C1 + t2*(C1+1) + C2, where NOP_Param_1 = C1, NOP_Param_2 = C2. // (t1+t2)*C1 + t2 = time - C2; void nop_delay(unsigned int time) { unsigned int q = time - NOP_Param_2; unsigned int q2 = q/NOP_Param_1; unsigned int q1 = q - q2*NOP_Param_1; nop_delay1(q1, q2-q1); } unsigned int nop_delay_ini1(unsigned int time) { unsigned int begin, end; RSR(CCOUNT, begin); nop_delay(time); RSR(CCOUNT, end); return end-begin-1; } void test() { unsigned int TestVal[]={1000, 10000, 20000, 1999, 8999, 12345}; for(int j=0; j<3; j++) for(int i=0; i<sizeof(TestVal)/sizeof(TestVal[0]); i++) Serial.printf("%d %d\n", TestVal[i], nop_delay_ini1(TestVal[i])); } void setup() { Serial.begin(115200); Serial.printf("Starting ini\n"); } int count=0; void loop() { test(); Serial.printf("count=%d\n", count++); delay(2000); } #pragma GCC pop_options В коде два важных параметра (NOP_Param_1, NOP_Param_2) которые надо подобрать под ваш контроллер - первый - длительность в тактах цикла с одним НОПом, второй - общая задержка. Также замечу, что код не сможет работать если надо отмерить только несколько тактов и примерно работает от 30-40 тактов задержек (если NOP_Param_1/2 как у меня).
  20. если так хочется делать ногодрыгами и НОПами, я бы сделал по-другому: создал бы с десяток функций void f1() { asm("nop"); return; } void f2() { asm("nop"); asm("nop"); return; } ... void f10() { asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); return; } запихнул бы их адреса в массив указателей на функцию, измерил бы точно сколько они длятся и вызывал бы так, что f10() вызывается в цикле сколько надо раз, а потом управление попадает на одну из тех, что в массиве. Тогда при точном измерении длительности такого извращения можно с точностью до такта настроить такую задержку.
  21. у меня тот же эффект был и от трансформаторного масла. ИМХО, там, где органической жижей заливают, электролиты противопоказаны. Парафин - тоже сильное зло, он при нагреве сильно расширяется, и если он в жидком состоянии (низкоплавкий парафин) то съедает электролиты также, а если высокотемпературный, то совсем тепло не отводит.
  22. Почитайте в соседнем форуме про плиски- тамошние завсегдатаи давно на этого производителя перешли. Если не хотеть 10-ого стратикса, а просто решать обычные плиснутые задачи, ИМХО, уделывает всех остальных по простоте, удобству, числу вентилей на бакс просто в разы. И да, тоже санкционка, ибо делают в Тайване. Сам долго использовал массу циклонов и стратиксов, даже что-то сам разводил, но сейчас предпочитаю именно GoWin.
  23. Можно конечно, но как я написал выше, на GoWin будет удобнее, а он тоже умеет на борту прошивку хранить. Рад за вас, что вы умеете так, у меня во время отладки меньше нескольких сотен перепрошивок никогда не получалось. Да и надо понимать, что шимы могут быть слегка сдвинутыми по времени, с пропусками и может еще что придётся делать, а эти параметры сильно зависят от того, как все остальные контроллеры работают, а их в аппаратуре больше сотни и я ни за что не поведусь на разработку аппаратуры, которую нельзя собрать одним makefile все эти 100 прошивок и потом загрузить по воздуху. А, да, аппаратура очень не настольная, вы же принимали участие в обсуждении до этого, думал, что такой вопрос у вас не возникнет.
  24. мелкий GoWin конечно можно поставить, туда все что мне надо влезет, но я его не научился пока прошивать из esp32, а каждый раз тыкаться программатором - реально повеситься можно. Поэтому все также хочу обойтись средствами самого этого TI контроллера
×
×
  • Создать...