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

    

Цифровой частотно-фазовый детектор

Задача тривиальная - стабилизировать скорость вращения электродвигателя с помощью ФАПЧ. В качестве генератора опорного сигнала выступает таймер (потом будет NCO, но это сути не меняет), импульсы с таходатчика производят захват мгновенного значения таймера, эта величина сразу дает текущую ошибку фазы. Проблема состоит в том, что у такого фазового детектора передаточная характеристика пилообразная. Будут захватываться сигналы кратной частоты, чего допустить нельзя. Нужен частотно-фазовый детектор, у которого при больших ошибках передаточная характеристика должна быть горизонтальной. Вроде, это называется phase unwrapping. Как ни странно, не удалось найти вменяемых примеров, как это красиво делается. Придумывается только какая-то громоздкая машина состояний, состояния которой должны меняться в прерываниях по захвату и переполнению, и решение принимается на основе анализа нескольких периодов. Как это обычно делают?

Phd.gif

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


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

вы можете пояснить, что значит 'допустить нельзя'? если двигатель вращается с кратной скоростью, то что должен делать стабилизатор частоты? я предположу, что он должен продолжать попытки стабилизировать.

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

эти переходы надо аккуратно моделировать. 

чд в вашем случае - разность двух последовательных значений таймера, которые вы захватываете.

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


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

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

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

Не хотелось бы детектор разбивать отдельно на частотный и фазовый. Лучше, если фазовый детектор будет иметь зоны насыщения при больших ошибках. Аналогично детекторам микросхем синтезаторов частоты.

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


Ссылка на сообщение
Поделиться на другие сайты
1 час назад, Леонид Иванович сказал:

Лучше, если фазовый детектор будет иметь зоны насыщения при больших ошибках. Аналогично детекторам микросхем синтезаторов частоты.

почему не подходит ЧФД на двух триггерах с выходом типа "зарядовый насос"  ?

700214803_PFD0.3-3kforLeonid.png.c04721fea6432767c3fc7bdd6025a5ea.png

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


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

копите абсолютную фазу (ну или отдельно ещё количество полных оборотов) без переполнения через 180 градусов, и её и стабилизируйте.

phase += enc - enc_prev;

if (enc - enc_prev < 0) phase +=360;

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

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


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

> почему не подходит ЧФД на двух триггерах с выходом типа "зарядовый насос"  ?

Потому что он увеличивает количество компонентов в устройстве. Требуется полностью цифровое решение, которое будет реализовано внутри микроконтроллера.

> копите абсолютную фазу

По сравнению с этим мои костыли выглядят менее страшными:

//Состояния частотно-фазового детектора:

//NCO OVF: _|_____|_____|_____|_____|_____|_
//SENSOR: _____|_____|_____|_____|_____|____
//FDET:     0  1  0  1  0  1  0  1  0  1  0
//FREQ OK               OK (1->0)

//NCO OVF: _|_____|_____|_____|_____|_____|_
//SENSOR:  _____|____|_|___|||____|_____|____
//FDET:     0  1  0 1 2 0 123 0  1  0  1  0
//FREQ HI               H     H(2->0, 3->0, etc)

//NCO OVF: _|_____|_____|_____|_____|_____|_
//SENSOR:  _____|___________|_____|_____|____
//FDET:     0  1  0     0  1  0  1  0  1  0
//FREQ LO               L (0->0)

Самое близкое, что находил по теме, это реализация частотно-фазового детектора на FPGA, но и там нет "честного" насыщения, коды при отклонении частоты дергаются.

 

A FPGA Implementation of a PLL.pdf

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


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

Файл нашелся чуть по другой ссылке: http://homepages.cae.wisc.edu/~brodskye/mr/phaseunwrap/unwrap.c

Только в данном случае не вижу от него пользы. Хотелось бы увидеть пример, как реализуют управление электродвигателями на микроконтроллере не спомощью PID, а с помощью PLL. Вроде, распространенная задача, а ничего найти почему-то не удалось.

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


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

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

успехов

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


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

При чем тут разрядность таймера? Она влияет только на точность измерения ошибки фазы.

 

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


Ссылка на сообщение
Поделиться на другие сайты
25 минут назад, Леонид Иванович сказал:

При чем тут разрядность таймера? Она влияет только на точность измерения ошибки фазы.

 

Имелось в виду, что период счета таймера должен быть больше максимального периода импульсов с таходатчика !

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

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


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

Период таймера - это опорный сигнал, он всегда равен номинальному периоду сигнала таходатчика. То, что Вы описали дальше, это АПЧ, а не ФАПЧ.

 

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


Ссылка на сообщение
Поделиться на другие сайты
19 hours ago, Леонид Иванович said:

Как это обычно делают?

Очень просто.

У Вас два прерывания - по захвату (Capture) и по сбросу опорного таймера (Compare)

	uint cnt;
	uint result;
	void Compare(void)
	{
	 cnt--;
	 if (cnt==0)
	 {
	  result=CaptureVal;
	 }
	 else
	 {
	  if (cnt>0) result=180; else result=-180;
	  cnt=0;
	 }
	}
	 
	void Capture(void)
	{
	 cnt++;
	}
	

Вот и все. Какие тут сложности?

 

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


Ссылка на сообщение
Поделиться на другие сайты
3 hours ago, Леонид Иванович said:

При чем тут разрядность таймера? Она влияет только на точность измерения ошибки фазы.

 

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

я так понимаю, пока у вас вопросы из категории 'как запрограммировать', но, поверьте, работоспособная фапч с широкой полосой захвата - это трудная штука, требующая большого объема моделирования. тем более, если речь идет о каком-то силовом устройстве с двигателем.

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


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

Делал примерно так же. Несколькими постами выше я приводил диаграммы состояний частотно-фазового детектора, значения FDET там - это и есть значения cnt. Только у меня не было cnt-- и сравнение делал с 1. Получается, что именно так и делают, вопрос можно считать закрытым. А не попадался ли какой-нибудь готовый проект или appnote на тему ФАПЧ управления двигателями?

 

Quote

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

Еще раз - разрядность таймера влияет только на точность представления фазы. Полный диапазон кодов таймера - это угол от 0 до 360 градусов. На каждый импульс таходатчика всегда приходится одно переполнение таймера. Меняется частота вращения - меняется и частота переполнений таймера (фактически там будет NCO, а не таймер, я об этом писал).

 

Изменено пользователем Леонид Иванович

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


Ссылка на сообщение
Поделиться на другие сайты
1 hour ago, Леонид Иванович said:

Только у меня не было cnt-- и сравнение делал с 1.

Да, это можно опустить. Сделано исключительно для удобства понимания. Более того, обычно в Capture есть как флаг того, что он сработал, так и флаг того, что произошло переполнение (сработал несколько раз, а значение не вычитано из регистров). Тогда вообще все еще проще:

	void Compare(void)
	{
	 if (CaptureFlag)
	 {
	  if (CaptureOvf) result=180; else result=CaptureVal;
	 }
	 else
	  result=-180;
	}
	

Прерывание Capture не используется вообще.

Но, понятное дело в такой простоте есть тонкости. Связаны они с тем, что импульс может прийти ровно в момент Compare и немного дрожать, и там возможны варианты типа дребезга +180..-180. За этим надо следить. Более точно поведение надо обсуждать с учетом выбранного микроконтроллера и его периферии.

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


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

Для публикации сообщений создайте учётную запись или авторизуйтесь

Вы должны быть пользователем, чтобы оставить комментарий

Создать учетную запись

Зарегистрируйте новую учётную запись в нашем сообществе. Это очень просто!

Регистрация нового пользователя

Войти

Уже есть аккаунт? Войти в систему.

Войти