фазоимпульсное управление на таймерах STM32

Кто любит RISC в жизни, заходим, не стесняемся.
Ответить
Собутыльник Кота
Аватара пользователя
Сообщения: 2708
Зарегистрирован: Сб май 14, 2011 21:16:04
Откуда: г. Чайковский

Сообщение Z_h_e »

Нормально все dosikus расписюлил :beer: . Все стало на свои места. Я когда разбирался с таймерам смотрел на схему таймеров. Там написано, что таймер тактируется от Internal Clock. Я решил что это частота ядра (а по факту опять случайное совпадение по частоте), хотя там же подписано TIMx CLK from RCC.
Поглядите, шина работает на своей допустимой частоте, CLK таймера умножается на 2.
Изображение
Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
Реклама
Нашел транзистор. Понюхал.
Аватара пользователя
Сообщения: 197
Зарегистрирован: Пн янв 24, 2011 01:51:48
Откуда: Украина, Киев

Сообщение RusikOk »

и когда уже начнут писать datasheet-ы на русском))))

запускаю в режме ШИМ все работает и сихронизируется от детектора нуля. только вот может запрыгивать в следующий полупериод

Код: Выделить всё

void MX_TIM2_Init(void)
{

  TIM_ClockConfigTypeDef sClockSourceConfig;
  TIM_SlaveConfigTypeDef sSlaveConfig;
  TIM_MasterConfigTypeDef sMasterConfig;
  TIM_OC_InitTypeDef sConfigOC;

  htim2.Instance = TIM2;
  htim2.Init.Prescaler = 7200;
  htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim2.Init.Period = 100;
  htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  HAL_TIM_Base_Init(&htim2);

  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig);

  HAL_TIM_PWM_Init(&htim2);

  sSlaveConfig.SlaveMode = TIM_SLAVEMODE_RESET;
  sSlaveConfig.InputTrigger = TIM_TS_ETRF;
  sSlaveConfig.TriggerPolarity = TIM_TRIGGERPOLARITY_NONINVERTED;
  sSlaveConfig.TriggerPrescaler = TIM_TRIGGERPRESCALER_DIV1;
  sSlaveConfig.TriggerFilter = 0;
  HAL_TIM_SlaveConfigSynchronization(&htim2, &sSlaveConfig);

  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig);

  sConfigOC.OCMode = TIM_OCMODE_PWM1;
  sConfigOC.Pulse = 75;
  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
  HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_3);

}

int main(void)
{
  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
  MX_TIM2_Init();
   
        if(HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_3) != HAL_OK)
          printf("\r\nrror -> HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_3)");

        HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_7); 
        printf("\r\nOK");

  while(1);
}
запускаю в режме одиночного запуска ничего не работает. может я что то не так делаю ткните носом

Код: Выделить всё

void MX_TIM2_Init(void)
{

  TIM_ClockConfigTypeDef sClockSourceConfig;
  TIM_SlaveConfigTypeDef sSlaveConfig;
  TIM_MasterConfigTypeDef sMasterConfig;
  TIM_OC_InitTypeDef sConfigOC;

  htim2.Instance = TIM2;
  htim2.Init.Prescaler = 7200;
  htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim2.Init.Period = 100;
  htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  HAL_TIM_Base_Init(&htim2);

  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig);

  HAL_TIM_PWM_Init(&htim2);

  HAL_TIM_OnePulse_Init(&htim2, TIM_OPMODE_SINGLE);

  sSlaveConfig.SlaveMode = TIM_SLAVEMODE_RESET;
  sSlaveConfig.InputTrigger = TIM_TS_ETRF;
  sSlaveConfig.TriggerPolarity = TIM_TRIGGERPOLARITY_NONINVERTED;
  sSlaveConfig.TriggerPrescaler = TIM_TRIGGERPRESCALER_DIV1;
  sSlaveConfig.TriggerFilter = 0;
  HAL_TIM_SlaveConfigSynchronization(&htim2, &sSlaveConfig);

  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig);

  sConfigOC.OCMode = TIM_OCMODE_PWM1;
  sConfigOC.Pulse = 75;
  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
  HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_3);

}

int main(void)
{
  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
  MX_TIM2_Init();
   
        if(HAL_TIM_OnePulse_Start(&htim2, TIM_CHANNEL_3) != HAL_OK)
          printf("\r\nerror -> HAL_TIM_OnePulse_Start(&htim2, TIM_CHANNEL_3)");

        HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_7);
        printf("\r\nOK");

  while(1);
}
Контактная информация:
Реклама
Нашел транзистор. Понюхал.
Аватара пользователя
Сообщения: 197
Зарегистрирован: Пн янв 24, 2011 01:51:48
Откуда: Украина, Киев

Сообщение RusikOk »

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

Код: Выделить всё

void MX_TIM1_Init(void)
{

  TIM_ClockConfigTypeDef sClockSourceConfig;
  TIM_SlaveConfigTypeDef sSlaveConfig;
  TIM_MasterConfigTypeDef sMasterConfig;
  TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig;
  TIM_OC_InitTypeDef sConfigOC;

  htim1.Instance = TIM1;
  htim1.Init.Prescaler = 360;
  htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim1.Init.Period = 1300;
  htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim1.Init.RepetitionCounter = 0;
  HAL_TIM_Base_Init(&htim1);

  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  HAL_TIM_ConfigClockSource(&htim1, &sClockSourceConfig);

  HAL_TIM_PWM_Init(&htim1);

  HAL_TIM_OnePulse_Init(&htim1, TIM_OPMODE_SINGLE);

  sSlaveConfig.SlaveMode = TIM_SLAVEMODE_TRIGGER;
  sSlaveConfig.InputTrigger = TIM_TS_ETRF;
  sSlaveConfig.TriggerPolarity = TIM_TRIGGERPOLARITY_INVERTED;
  sSlaveConfig.TriggerPrescaler = TIM_TRIGGERPRESCALER_DIV1;
  sSlaveConfig.TriggerFilter = 0;
  HAL_TIM_SlaveConfigSynchronization(&htim1, &sSlaveConfig);

  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig);

  sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE;
  sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF;
  sBreakDeadTimeConfig.DeadTime = 0;
  sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE;
  sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH;
  sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;
  HAL_TIMEx_ConfigBreakDeadTime(&htim1, &sBreakDeadTimeConfig);

  sConfigOC.OCMode = TIM_OCMODE_PWM1;
  sConfigOC.Pulse = 1298;   // учитывается длинна импульса
  sConfigOC.OCPolarity = TIM_OCPOLARITY_LOW;
  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
  sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;
  sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
  HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_4);

}
Контактная информация:
Грызет канифоль
Аватара пользователя
Сообщения: 262
Зарегистрирован: Пт окт 30, 2009 22:33:56
Откуда: Санкт-Петербург

Сообщение Alex_Megavolt_79 »

RusikOk писал(а):используется только один таймер.
Делал я недавно полууправляемый выпрямитель. СИФУ я реализовал на трёх таймерах. Один из таймеров - Systick, его я использовал для формирования угла открытия тиристоров. Второй таймер в режиме захвата по детектору нуля расчитывал период и направление вращение фаз, он же запускал СИФУ. Третий таймер в режиме ШИМ управлял тиристорами. Время открытия тиристоров регулировал регистрами CCP CCP1 (контроллер аля Миландр).
Реклама
Эиком - электронные компоненты и радиодетали
Это не хвост, это антенна
Аватара пользователя
Сообщения: 1368
Зарегистрирован: Вс мар 28, 2010 12:52:22
Откуда: Беларусь

Сообщение dr.doc »

Делал фазовый регулятор на PIC16. Измерял несколько периодов сетевого напряжения, высчитывал среднее значение. Это среднее делил на 2. Для хорошего регулирования ограничивал угол открытия симистора по 5% от полученного значения полупериода. В противном случае имело место быть перерегулирование (скачек в след. полупериод) и редкий пропуск полуволны.
Работа строилась на одном таймере. При синхронизации в таймер пишется сумма 5% + необходимый угол открытия. По прерыванию запускается этот же таймер на фиксированную длительность импульса. В след. прерывании таймера выполняется запуск на полупериод минус длительность открывающего импульса. Код довольно объемный, но работает красиво. Плюс - абсолютный пофигизм к частоте питающей сети.
«Еще я хотел бы, чтобы наши ученые изобрели какой-то новый источник энергии, чтобы мы на коленях не ползали даже перед нашими братьями, умоляя их и выпрашивая тонну нефти или кубометр газа», — рассказал белорусский президент.
Реклама
Родился
Сообщения: 5
Зарегистрирован: Вт авг 08, 2017 15:15:11

Сообщение AVPD »

Я делал управление симистором диммера на одном таймере. Симистор управлялся оптопарой 3052, Таймер 2 в режиме PWM и генерации одного импульса. Детектор ноля подавал на аппаратное прерывание. Функция обработчика прерывания запускала таймер каждый раз по переходу через ноль. Для изменения задержки менял регистр ССR.
Значением в ARR задавал немного меньше полпериода, для защиты от перескока на следующий. Выключаю нагрузку запретом/отключением прерывания.
Работает вполне нормально. Управление при 100 (почти 100 изза защитных интервалов) % получается не коротким импульсом, а в почти весь полупериод. Возможно это энергетически не оптимально, но вполне себе просто и работает.
Реклама
Собутыльник Кота
Аватара пользователя
Сообщения: 2708
Зарегистрирован: Сб май 14, 2011 21:16:04
Откуда: г. Чайковский

Сообщение Z_h_e »

Я в другом проекте сделал тоже от одного таймера. Только запускается таймер не от прерывания, а от внешнего события и если задержку поправлять не надо, то программа не участвует в формировании управляющего импульса совсем.
AVPD писал(а):Управление при 100 (почти 100 изза защитных интервалов) % получается не коротким импульсом, а в почти весь полупериод.
Не, смысла нет в этом. Но я так тоже делал, а потом посчитал и оказалось что до 20 градусов задержки открытия мощность практические не теряется, а 20 градусов это прилично.
Изображение
Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
Родился
Сообщения: 5
Зарегистрирован: Вт авг 08, 2017 15:15:11

Сообщение AVPD »

[uquote="Z_h_e",url="/forum/viewtopic.php?p=3158515#p3158515"]Я в другом проекте сделал тоже от одного таймера. Только запускается таймер не от прерывания, а от внешнего события и если задержку поправлять не надо, то программа не участвует в формировании управляющего импульса совсем.


AVPD писал(а):Управление при 100 (почти 100 изза защитных интервалов) % получается не коротким импульсом, а в почти весь полупериод.
Не, смысла нет в этом. Но я так тоже делал, а потом посчитал и оказалось что до 20 градусов задержки открытия мощность практические не теряется, а 20 градусов это прилично.[/uquote]


Можно поподробнее, я только начал изучать контроллеры, и не понял что за "внешнее событие". Что это физически?

Да, обычно так и делают. У меня тоже получается около 1 мс съедается на защитные интервалы в начале и в конце полупериода.
Собутыльник Кота
Аватара пользователя
Сообщения: 2708
Зарегистрирован: Сб май 14, 2011 21:16:04
Откуда: г. Чайковский

Сообщение Z_h_e »

Таймер может получить пинок для старта не только от программы, но и от других некоторых событий. Например для таймера можно выбрать источник события и реакцию его на это событие.

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

Код: Выделить всё

//затактируем Таймер2 (36 МГц*2)
		RCC->APB1ENR|=RCC_APB1ENR_TIM2EN;

	       ...
               ...
		//----------

		//слайв мод регистр запуск от ETR
		TIM2->SMCR=
				//TIM_SMCR_ETP|	//ETR полярность, спад в данном случае
				TIM_SMCR_TS|	//ETR включен
				TIM_SMCR_SMS_2|TIM_SMCR_SMS_1|	//110: Trigger Mode - The counter starts at a rising edge of the trigger
						0;
               ....
               ....
При событии фронт на лапе TIM2_CH1_ETR , таймер получает пинок старта аппаратно.
Изображение
Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
Нашел транзистор. Понюхал.
Аватара пользователя
Сообщения: 197
Зарегистрирован: Пн янв 24, 2011 01:51:48
Откуда: Украина, Киев

Сообщение RusikOk »

[uquote="Z_h_e",url="/forum/viewtopic.php?p=3159006#p3159006"]Например для таймера можно выбрать источник события и реакцию его на это событие[/uquote]у меня тоже по этому принципу реализвано
Контактная информация:
Прорезались зубы
Аватара пользователя
Сообщения: 202
Зарегистрирован: Сб янв 09, 2016 15:51:17

Сообщение AVI-crak »

Третий ответ в этой теме от vastani - имеет верное решение. dr.doc - аналогично.
Необходима синхронизация с частотой сети - для исключения помех из сети, и исключения генерации помех самим регулятором.
Контактная информация:
Собутыльник Кота
Аватара пользователя
Сообщения: 2708
Зарегистрирован: Сб май 14, 2011 21:16:04
Откуда: г. Чайковский

Сообщение Z_h_e »

Есть у меня устройство на 2.5кВт. Ложных срабатываний детектора фазы ( обычный мост и оптопара) не замечал. Если есть аппаратная возможность формирования управляющего импульса, то по-моему ее грех не использовать.
Изображение
Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
Нашел транзистор. Понюхал.
Аватара пользователя
Сообщения: 197
Зарегистрирован: Пн янв 24, 2011 01:51:48
Откуда: Украина, Киев

Сообщение RusikOk »

[uquote="AVI-crak",url="/forum/viewtopic.php?p=3159938#p3159938"]Третий ответ в этой теме от vastani - имеет верное решение. dr.doc - аналогично.[/uquote]тоесть Вы считаете когда контроллер подвиснет то пропусков синхронизации не будет?
ИМХО аппаратно все же надежнее и проще
Контактная информация:
Друг Кота
Аватара пользователя
Сообщения: 3385
Зарегистрирован: Пн окт 11, 2010 19:00:08

Сообщение Мурик »

RusikOk писал(а): когда контроллер подвиснет
Если завис, нагрузку нужно выключить, что автоматически произойдет если таймер работает в режиме One Pulse с программным запуском.
Собутыльник Кота
Аватара пользователя
Сообщения: 2708
Зарегистрирован: Сб май 14, 2011 21:16:04
Откуда: г. Чайковский

Сообщение Z_h_e »

Мурик писал(а):автоматически произойдет если таймер работает в режиме One Pulse с программным запуском.
Очень даже не факт. Зависнуть можно, например, в низко приоритетном прерывании и функция диммирования может остаться в работе. Так что, если думать о возможном зависании (и прочих нештатных ситуёвин), нужно реализовывать какой-то супервизор или не парится об этом совсем.
Изображение
Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
Друг Кота
Аватара пользователя
Сообщения: 3385
Зарегистрирован: Пн окт 11, 2010 19:00:08

Сообщение Мурик »

Для криво написанного кода придумали собаку.
Последний раз редактировалось Мурик Пт авг 11, 2017 11:54:41, всего редактировалось 2 раза.
Прорезались зубы
Аватара пользователя
Сообщения: 202
Зарегистрирован: Сб янв 09, 2016 15:51:17

Сообщение AVI-crak »

[uquote="Z_h_e",url="/forum/viewtopic.php?p=3160150#p3160150"]нужно реализовывать какой-то супервизор или не парится об этом совсем.[/uquote]
stm может зависнуть при исправном коде - сбой на уровне периферии. В этом случае выручает сорвавшийся с цепи собака, которая кусает ресет. У st чипов есть целая псарня для таких случаев, не все собаки кусают насмерть - но всегда очень больно.
Две собаки wwdg и iwdg - только для ресета. Прерывания по ошибкам шины данных, защиты данных, сбой pll блоков, и по сбою линий связи. Кроме того на самой периферии есть собственные обработчики ошибок в огромном ассортименте.
Критическими считаются собака IWDG, и прерывание BusFault_IRQn - после них свет гаснет. Всё остальное можно дополнительно обработать перед выключением света. Это бывает полезным и необходимым, например переключение важных ног мк в нужное положение, и даже выдержка их в подобном состоянии.

Использовать код от кубика для таких случаев не логично. В кубике есть все описания для подобных событий - но ни одной строчки кода для реальной обработки. Всё это придётся писать самостоятельно, попутно изучая глюки самого кубика. Есть более простой вариант - читать и использовать доку от чипа.

Ошибки программной части исправить во время работы нельзя.
Например один дурик использовал ацп для перехода по абсолютным адресам (опрос кнопок). Такие пациенты уже неизлечимы.
Контактная информация:
Собутыльник Кота
Аватара пользователя
Сообщения: 2708
Зарегистрирован: Сб май 14, 2011 21:16:04
Откуда: г. Чайковский

Сообщение Z_h_e »

Мурик писал(а):Для криво написанного кода придумали собаку.
"Чтобы забивать гнутные гвозди, нужен гнутый молоток"

Не понимаю почему тема по таймерам для диммера переходит в описание работы собак и при чем тут куб? :dont_know:
Изображение
Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
Вымогатель припоя
Аватара пользователя
Сообщения: 616
Зарегистрирован: Вс ноя 01, 2015 13:13:49

Сообщение scorpi_0n »

Третий ответ в этой теме от vastani - имеет верное решение. dr.doc - аналогично.
Необходима синхронизация с частотой сети - для исключения помех из сети, и исключения генерации помех самим регулятором.
Избавляйтесь от АВРовских привычек, как от вредных.
stm может зависнуть при исправном коде - сбой на уровне периферии.
Нонсенс! Это уже не исправный код, а кривой до не могу.

========
Самое правильное решение, ведь таймер по любому используется. Так почему его не задействовать как положено, а не с лишними извращениями?
Я в другом проекте сделал тоже от одного таймера. Только запускается таймер не от прерывания, а от внешнего события и если задержку поправлять не надо, то программа не участвует в формировании управляющего импульса совсем.
Прорезались зубы
Аватара пользователя
Сообщения: 202
Зарегистрирован: Сб янв 09, 2016 15:51:17

Сообщение AVI-crak »

[uquote="scorpi_0n",url="/forum/viewtopic.php?p=3160252#p3160252"]Избавляйтесь от АВРовских привычек, как от вредных.[/uquote]
Это не привычка, это алгоритм синхронизации с сетью. Он не зависит от используемого мк.
Например есть нагрузка, которой может резко стать плохо от стартового номинального напряжения. Это банальный коллекторный двигатель на пол киловатта с постоянными магнитами. Такие устанавливаются в тренажеры, в детские машинки и так далее. Везде где требуется динамическое торможение и малые габариты.
Если на такой двигатель сразу подать полное напряжение, его ток возрастёт примерно в 300 раз от номинала. Отчего его ресурс будет резко сокращаться.

У вас проскочила бяка по сети, и мк уверенно поймал ноль через помеху - в этом случае двигатель получит хороший пинок под зад. А если оный установлен на беговой дорожке - то человек с большой вероятностью упадёт. А потом суд, финансы...
Включение мощного трансформатора не стой ноги - бросок тока.
Переключение нагрузки с сети на ups без синхронизации - к красивому фейерверку.
Есть масса примеров кривых алгоритмов, лечится собственным рублём.

Чип st может зависнуть, так как он хоть чем-то но управляет. В этом случае импульсная помеха может исказить внешние данные, или даже нарушить его питание.
От прямого попадания молнии - защиты не существует. Но и оставлять линии вовсе без защиты - себе дороже. Баланс между маниакальностью и пофигизмом - ценность самого прибора и устройства в целом. Для каждого случая свой баланс, но не использовать ресурсы мк по прямому назначению - это просто глупо.
Контактная информация:
Ответить

Вернуться в «ARM»