КУЧА ВСЕГО
добавлены параметры работы упп (частота сети, максимальный и минимальный угол открытия тиристора, длительность плавного пуска) добавлены всякие режимы по флагам (отключение, остановка, подготовка, го) добавлен флаг для безопасным управлением упп (GoSafe) добавлен режим торможения параметры угла (angleInit) унифицированы для всех фаз
This commit is contained in:
parent
d7fe7b0ba1
commit
942cb12948
@ -1 +1 @@
|
||||
Subproject commit 08719ffc055e27b3b22a9c37742add86ece43ea4
|
||||
Subproject commit c3d30fa6f13e7874019a9661fee66d4ccb1929b1
|
@ -1,4 +1,3 @@
|
||||
#include "upp.h"
|
||||
#include "tiristor.h"
|
||||
// управление тиристором
|
||||
void tiristor_control(TiristorControl_t *ctrl)
|
||||
@ -30,37 +29,49 @@ void tiristor_angle_update(TiristorAngleControl_t *angle)
|
||||
{
|
||||
uint32_t current_time_ms = HAL_GetTick();
|
||||
|
||||
if ((current_time_ms - angle->last_update_ms) >= angle->sample_time_ms)
|
||||
if ((current_time_ms - angle->last_update_ms) >= angle->Init->sample_time_ms)
|
||||
{
|
||||
angle->last_update_ms = current_time_ms;
|
||||
|
||||
if (angle->delay_us > angle->delay_min_us)
|
||||
if(angle->Init->direction)
|
||||
angle->delay_us += angle->Init->delay_step_us;
|
||||
else
|
||||
angle->delay_us -= angle->Init->delay_step_us;
|
||||
|
||||
|
||||
if (angle->delay_us < angle->Init->delay_min_us)
|
||||
{
|
||||
angle->delay_us -= angle->delay_step_us;
|
||||
if (angle->delay_us < angle->delay_min_us)
|
||||
angle->delay_us = angle->delay_min_us;
|
||||
angle->delay_us = angle->Init->delay_min_us;
|
||||
}
|
||||
else if (angle->delay_us > angle->Init->delay_max_us)
|
||||
{
|
||||
angle->delay_us = angle->Init->delay_max_us;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void tiristor_angle_control(TiristorControl_t *ctrl)
|
||||
{
|
||||
tiristor_angle_update(&ctrl->angle);
|
||||
|
||||
if ((uint16_t)((uint16_t)TIMER->CNT - ctrl->angle.start_delay_us) > ctrl->angle.delay_us)
|
||||
if(ctrl->angle.delay_us != 0)
|
||||
{
|
||||
if(ctrl->f.TiristorDone == 0)
|
||||
if ((uint16_t)((uint16_t)TIMER->CNT - ctrl->angle.start_delay_tick) > ctrl->angle.delay_us)
|
||||
{
|
||||
if(ctrl->f.TiristorReady)
|
||||
{
|
||||
ctrl->f.EnableTiristor = 1;
|
||||
ctrl->f.TiristorDone = 1;
|
||||
ctrl->f.TiristorReady = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void tiristor_start_angle_delay(TiristorControl_t *ctrl)
|
||||
{
|
||||
ctrl->f.TiristorDone = 0;
|
||||
ctrl->angle.start_delay_us = TIMER->CNT;
|
||||
ctrl->f.TiristorReady = 1;
|
||||
ctrl->angle.start_delay_tick = TIMER->CNT;
|
||||
}
|
||||
|
||||
void tiristor_enable(TiristorControl_t *ctrl)
|
||||
@ -77,15 +88,17 @@ void tiristor_disable(TiristorControl_t *ctrl)
|
||||
ctrl->f.TiristorIsEnable = 0;
|
||||
}
|
||||
|
||||
void tiristor_angle_reset(TiristorControl_t *ctrl)
|
||||
{
|
||||
if(ctrl->angle.Init->direction)
|
||||
ctrl->angle.delay_us = ctrl->angle.Init->delay_min_us;
|
||||
else
|
||||
ctrl->angle.delay_us = ctrl->angle.Init->delay_max_us;
|
||||
}
|
||||
|
||||
void tiristor_init(TiristorControl_t *ctrl, GPIO_TypeDef *gpiox, uint32_t gpio_pin)
|
||||
{
|
||||
ctrl->gpiox = gpiox;
|
||||
ctrl->gpio_pin = gpio_pin;
|
||||
ctrl->angle.delay_max_us = 8000;
|
||||
ctrl->angle.delay_min_us = 100;
|
||||
ctrl->angle.delay_us = 7000;
|
||||
ctrl->angle.delay_step_us = 500;
|
||||
ctrl->angle.sample_time_ms = 100;
|
||||
ctrl->open_time = 1;
|
||||
TIMER->CR1 |= TIM_CR1_CEN;
|
||||
tiristor_angle_reset(ctrl);
|
||||
}
|
@ -15,20 +15,24 @@ typedef struct
|
||||
{
|
||||
unsigned EnableTiristor:1;
|
||||
unsigned TiristorIsEnable:1;
|
||||
unsigned TiristorDone:1;
|
||||
unsigned TiristorReady:1;
|
||||
}TiristorControlFlags;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t delay_min_us; // Минимальная задержка (максимальное открытие тиристора)
|
||||
uint32_t delay_max_us; // Начальная задержка (практически закрыт)
|
||||
uint32_t delay_step_us; // Шаг уменьшения задержки
|
||||
uint32_t sample_time_ms; // Интервал между шагами (например, 200 мс)
|
||||
unsigned direction; // Направление разгон/торможение
|
||||
}AngleInit_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t delay_us; // Текущая задержка (в микросекундах)
|
||||
uint32_t delay_min_us; // Минимальная задержка (максимальное открытие тиристора)
|
||||
uint32_t delay_max_us; // Начальная задержка (практически закрыт)
|
||||
uint32_t delay_step_us; // Шаг уменьшения задержки
|
||||
uint32_t last_update_ms; // Время последнего обновления
|
||||
uint32_t sample_time_ms; // Интервал между шагами (например, 200 мс)
|
||||
AngleInit_t *Init;
|
||||
|
||||
uint16_t start_delay_us;
|
||||
uint32_t last_update_ms; // Время последнего обновления
|
||||
uint32_t delay_us; // Текущая задержка (в микросекундах)
|
||||
uint16_t start_delay_tick;
|
||||
}TiristorAngleControl_t;
|
||||
|
||||
typedef struct TiristorControl_t TiristorControl_t;
|
||||
@ -48,6 +52,7 @@ void tiristor_control(TiristorControl_t *ctrl);
|
||||
void tiristor_angle_update(TiristorAngleControl_t *angle);
|
||||
void tiristor_angle_control(TiristorControl_t *ctrl);
|
||||
void tiristor_start_angle_delay(TiristorControl_t* ctrl);
|
||||
void tiristor_angle_reset(TiristorControl_t *ctrl);
|
||||
void tiristor_enable(TiristorControl_t *ctrl);
|
||||
void tiristor_disable(TiristorControl_t *ctrl);
|
||||
void tiristor_init(TiristorControl_t *ctrl, GPIO_TypeDef *gpiox, uint32_t gpio_pin);
|
||||
|
@ -3,9 +3,93 @@
|
||||
Phase_t phase_A;
|
||||
Phase_t phase_B;
|
||||
Phase_t phase_C;
|
||||
UPP_Control_t Upp;
|
||||
// главная функция
|
||||
void upp_main(void)
|
||||
{
|
||||
if(GetAngleInit(&Upp.angleInit))
|
||||
{
|
||||
tiristor_angle_reset(&phase_A.ctrl);
|
||||
tiristor_angle_reset(&phase_B.ctrl);
|
||||
tiristor_angle_reset(&phase_C.ctrl);
|
||||
}
|
||||
|
||||
// безопасный запуск
|
||||
upp_safe_go();
|
||||
|
||||
// останавливаем УПП (убираем питание с выхода упп) если выставлен флаг
|
||||
if(Upp.ForceStop)
|
||||
{
|
||||
Upp.Go = 0;
|
||||
connect_upp();
|
||||
return;
|
||||
}
|
||||
|
||||
// отключаем упп если выставлен флаг
|
||||
if(Upp.GoDisconnect)
|
||||
{
|
||||
disconnect_upp();
|
||||
}
|
||||
// останавливаем упп если выставлен флаг
|
||||
if(Upp.GoStop)
|
||||
{
|
||||
Upp.Go = 0;
|
||||
connect_upp();
|
||||
}
|
||||
|
||||
if(Upp.Prepare)
|
||||
{
|
||||
if(Upp.Disconnected)
|
||||
{
|
||||
connect_upp();
|
||||
}
|
||||
upp_phase_routine(&phase_A);
|
||||
upp_phase_routine(&phase_B);
|
||||
upp_phase_routine(&phase_C);
|
||||
}
|
||||
if(Upp.Go)
|
||||
{
|
||||
if(Upp.Prepare)
|
||||
{
|
||||
if(phase_A.ctrl.f.TiristorReady && phase_B.ctrl.f.TiristorReady && phase_C.ctrl.f.TiristorReady)
|
||||
{
|
||||
Upp.Prepare = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
if(Upp.Disconnected)
|
||||
{
|
||||
Upp.ForceStop = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
// если все фазы дошли до минимума в режиме разгона, то выставляем флаг на отключение упп (прямая подача питания на двигатель)
|
||||
if( (phase_A.ctrl.angle.delay_us == phase_A.ctrl.angle.Init->delay_min_us) &&
|
||||
(phase_B.ctrl.angle.delay_us == phase_B.ctrl.angle.Init->delay_min_us) &&
|
||||
(phase_C.ctrl.angle.delay_us == phase_C.ctrl.angle.Init->delay_min_us) && (Upp.angleInit.direction == 0))
|
||||
{
|
||||
Upp.GoDisconnect = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
Upp.GoDisconnect = 0;
|
||||
}
|
||||
|
||||
// если все фазы дошли до максимума в режиме торможения, то выставляем флаг на остановку упп (выключения питания на двигателе)
|
||||
if( (phase_A.ctrl.angle.delay_us == phase_A.ctrl.angle.Init->delay_max_us) &&
|
||||
(phase_B.ctrl.angle.delay_us == phase_B.ctrl.angle.Init->delay_max_us) &&
|
||||
(phase_C.ctrl.angle.delay_us == phase_C.ctrl.angle.Init->delay_max_us) && (Upp.angleInit.direction == 1))
|
||||
{
|
||||
Upp.GoStop = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
Upp.GoStop = 0;
|
||||
}
|
||||
|
||||
upp_phase_routine(&phase_A);
|
||||
upp_phase_routine(&phase_B);
|
||||
upp_phase_routine(&phase_C);
|
||||
@ -13,10 +97,90 @@ void upp_main(void)
|
||||
upp_phase_control(&phase_A);
|
||||
upp_phase_control(&phase_B);
|
||||
upp_phase_control(&phase_C);
|
||||
}
|
||||
else
|
||||
{
|
||||
tiristor_angle_reset(&phase_A.ctrl);
|
||||
tiristor_angle_reset(&phase_B.ctrl);
|
||||
tiristor_angle_reset(&phase_C.ctrl);
|
||||
}
|
||||
}
|
||||
|
||||
void upp_safe_go(void)
|
||||
{
|
||||
static int prev_gosafe;
|
||||
|
||||
|
||||
if(Upp.GoSafe > prev_gosafe)
|
||||
{
|
||||
Upp.angleInit.direction = 0;
|
||||
Upp.ForceStop = 0;
|
||||
Upp.Prepare = 1;
|
||||
Upp.Go = 1;
|
||||
tiristor_angle_reset(&phase_A.ctrl);
|
||||
tiristor_angle_reset(&phase_B.ctrl);
|
||||
tiristor_angle_reset(&phase_C.ctrl);
|
||||
}
|
||||
else if (Upp.GoSafe < prev_gosafe)
|
||||
{
|
||||
Upp.angleInit.direction = 1;
|
||||
Upp.Prepare = 1;
|
||||
Upp.Go = 1;
|
||||
tiristor_angle_reset(&phase_A.ctrl);
|
||||
tiristor_angle_reset(&phase_B.ctrl);
|
||||
tiristor_angle_reset(&phase_C.ctrl);
|
||||
}
|
||||
|
||||
prev_gosafe = Upp.GoSafe;
|
||||
}
|
||||
|
||||
void disconnect_upp(void)
|
||||
{
|
||||
if(phase_A.ctrl.f.TiristorReady)
|
||||
{
|
||||
disconnect_phase(&phase_A);
|
||||
}
|
||||
|
||||
if(phase_B.ctrl.f.TiristorReady)
|
||||
{
|
||||
disconnect_phase(&phase_B);
|
||||
}
|
||||
|
||||
if(phase_C.ctrl.f.TiristorReady)
|
||||
{
|
||||
disconnect_phase(&phase_C);
|
||||
}
|
||||
|
||||
if(phase_A.disconnect.Disconnected && phase_B.disconnect.Disconnected && phase_C.disconnect.Disconnected)
|
||||
{
|
||||
Upp.Disconnected = 1;
|
||||
Upp.GoDisconnect = 0;
|
||||
Upp.Go = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void connect_upp(void)
|
||||
{
|
||||
tiristor_disable(&phase_A.ctrl);
|
||||
tiristor_disable(&phase_B.ctrl);
|
||||
tiristor_disable(&phase_C.ctrl);
|
||||
|
||||
connect_phase(&phase_A);
|
||||
connect_phase(&phase_B);
|
||||
connect_phase(&phase_C);
|
||||
|
||||
Upp.Disconnected = 0;
|
||||
}
|
||||
|
||||
void upp_phase_control(Phase_t *phase)
|
||||
{
|
||||
tiristor_angle_control(&phase->ctrl);
|
||||
tiristor_control(&phase->ctrl);
|
||||
}
|
||||
|
||||
void upp_phase_routine(Phase_t *phase)
|
||||
{
|
||||
zero_cross_update(&phase->zc_detector);
|
||||
if(is_zero_cross(&phase->zc_detector))
|
||||
{
|
||||
tiristor_start_angle_delay(&phase->ctrl);
|
||||
@ -26,19 +190,109 @@ void upp_phase_control(Phase_t *phase)
|
||||
}
|
||||
}
|
||||
|
||||
void upp_phase_routine(Phase_t *phase)
|
||||
|
||||
int GetAngleInit(AngleInit_t *angle)
|
||||
{
|
||||
tiristor_angle_control(&phase->ctrl);
|
||||
tiristor_control(&phase->ctrl);
|
||||
zero_cross_update(&phase->zc_detector);
|
||||
static float sine_freq_old = 0;
|
||||
static float Duration_old = 0;
|
||||
static float max_duty_old = 0, min_duty_old = 0; // Задаются в процентах
|
||||
int update = 0;
|
||||
|
||||
|
||||
if( (Upp.sine_freq != sine_freq_old) &&
|
||||
(Upp.max_duty != max_duty_old) &&
|
||||
(Upp.min_duty != min_duty_old) )
|
||||
{
|
||||
update = 1;
|
||||
min_duty_old = Upp.min_duty;
|
||||
max_duty_old = Upp.max_duty;
|
||||
sine_freq_old = Upp.sine_freq;
|
||||
|
||||
}
|
||||
|
||||
if(Upp.Duration != Duration_old)
|
||||
{
|
||||
update = 1;
|
||||
Duration_old = Upp.Duration;
|
||||
}
|
||||
|
||||
if(update)
|
||||
{
|
||||
// max/min duty
|
||||
uint32_t half_period_us = (500000.0f / Upp.sine_freq) - 1000; // полупериод в мкс - время открытия тиристоры
|
||||
|
||||
angle->delay_max_us = (uint32_t)(Upp.max_duty * half_period_us);
|
||||
angle->delay_min_us = (uint32_t)(Upp.min_duty * half_period_us);
|
||||
|
||||
if((angle->delay_max_us > 0xFFFF) || (angle->delay_min_us > 0xFFFF))
|
||||
{
|
||||
// увеличение прескалера в 10 раз (с 1мкс до 10мкс, с 7Гц до 0.7Гц)
|
||||
angle->delay_max_us /= 10;
|
||||
angle->delay_min_us /= 10;
|
||||
TIMER->PSC = 719;
|
||||
|
||||
if((angle->delay_max_us > 0xFFFF) || (angle->delay_min_us > 0xFFFF))
|
||||
{
|
||||
// увеличение прескалера в 10 раз (с 10мкс до 0,1мс, с 0.7Гц до 0.07 Гц)
|
||||
angle->delay_max_us /= 10;
|
||||
angle->delay_min_us /= 10;
|
||||
TIMER->PSC = 7299;
|
||||
|
||||
if ((angle->delay_max_us > 0xFFFF) || (angle->delay_min_us > 0xFFFF))
|
||||
{
|
||||
// если все еще переполнение то выключаем всё
|
||||
Upp.ForceStop = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
TIMER->PSC = 71;
|
||||
}
|
||||
|
||||
// duration
|
||||
float duration_ms = Duration_old * 1000.0f;
|
||||
uint32_t steps = duration_ms / angle->sample_time_ms;
|
||||
if (steps == 0) steps = 1;
|
||||
|
||||
if (angle->delay_max_us > angle->delay_min_us)
|
||||
angle->delay_step_us = (angle->delay_max_us - angle->delay_min_us) / steps;
|
||||
else
|
||||
angle->delay_step_us = 0;
|
||||
|
||||
}
|
||||
|
||||
return update;
|
||||
}
|
||||
|
||||
void upp_init(void)
|
||||
{
|
||||
Upp.max_duty = 0.8;
|
||||
Upp.min_duty = 0.1;
|
||||
Upp.angleInit.sample_time_ms = 100;
|
||||
|
||||
phase_A.disconnect.gpiox = GPIOA;
|
||||
phase_A.disconnect.gpio_pin = GPIO_PIN_5;
|
||||
|
||||
phase_B.disconnect.gpiox = GPIOA;
|
||||
phase_B.disconnect.gpio_pin = GPIO_PIN_6;
|
||||
|
||||
phase_C.disconnect.gpiox = GPIOA;
|
||||
phase_C.disconnect.gpio_pin = GPIO_PIN_7;
|
||||
|
||||
phase_A.ctrl.angle.Init = &Upp.angleInit;
|
||||
phase_B.ctrl.angle.Init = &Upp.angleInit;
|
||||
phase_C.ctrl.angle.Init = &Upp.angleInit;
|
||||
|
||||
tiristor_init(&phase_A.ctrl, GPIOB, GPIO_PIN_12);
|
||||
tiristor_init(&phase_B.ctrl, GPIOB, GPIO_PIN_13);
|
||||
tiristor_init(&phase_C.ctrl, GPIOB, GPIO_PIN_14);
|
||||
|
||||
TIMER->CR1 |= TIM_CR1_CEN;
|
||||
|
||||
tiristor_angle_reset(&phase_A.ctrl);
|
||||
tiristor_angle_reset(&phase_B.ctrl);
|
||||
tiristor_angle_reset(&phase_C.ctrl);
|
||||
#ifndef HARDWARE_ZERO_CROSS_DETECT
|
||||
adc_Attach(&phase_A.zc_detector.AdcFilter, &hadc);
|
||||
zero_cross_Init(&phase_A.zc_detector, ADC_INITIAL_ZERO_LEVEL);
|
||||
@ -46,5 +300,6 @@ void upp_init(void)
|
||||
adc_Attach(&phase_A.zc_detector.AdcFilter, &hadc);
|
||||
zero_cross_Init(&phase_A.zc_detector, ADC_INITIAL_ZERO_LEVEL);
|
||||
#endif
|
||||
//Upp.GoSafe = 1;
|
||||
}
|
||||
|
||||
|
@ -12,19 +12,56 @@
|
||||
#define hadc hadc1
|
||||
#define ADC_INITIAL_ZERO_LEVEL 2048
|
||||
|
||||
#define disconnect_phase(_ph_) { (_ph_)->disconnect.gpiox->ODR |= (_ph_)->disconnect.gpio_pin; (_ph_)->disconnect.Disconnected = 1;}
|
||||
#define connect_phase(_ph_) { (_ph_)->disconnect.gpiox->ODR &= ~(_ph_)->disconnect.gpio_pin; (_ph_)->disconnect.Disconnected = 0;}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
struct
|
||||
{
|
||||
unsigned Disconnected:1;
|
||||
GPIO_TypeDef *gpiox;
|
||||
uint32_t gpio_pin;
|
||||
}disconnect;
|
||||
|
||||
ZeroCrossDetector_t zc_detector;
|
||||
TiristorControl_t ctrl;
|
||||
} Phase_t; // структура для фазы
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned GoSafe:1;
|
||||
unsigned Go:1;
|
||||
unsigned GoStop:1;
|
||||
unsigned Prepare:1;
|
||||
unsigned Disconnected:1;
|
||||
unsigned GoDisconnect:1;
|
||||
unsigned ForceStop:1;
|
||||
unsigned PreGoDone:1;
|
||||
|
||||
|
||||
float Duration;
|
||||
float sine_freq;
|
||||
float max_duty;
|
||||
float min_duty;
|
||||
|
||||
AngleInit_t angleInit;
|
||||
}UPP_Control_t;
|
||||
|
||||
|
||||
extern Phase_t phase_A;
|
||||
extern Phase_t phase_B;
|
||||
extern Phase_t phase_C;
|
||||
extern UPP_Control_t Upp;
|
||||
|
||||
void upp_main(void);
|
||||
void upp_safe_go(void);
|
||||
void disconnect_upp(void);
|
||||
void connect_upp(void);
|
||||
void upp_phase_routine(Phase_t *phase);
|
||||
void upp_phase_control(Phase_t *phase);
|
||||
int GetAngleInit(AngleInit_t *angle);
|
||||
void upp_init(void);
|
||||
|
||||
|
||||
|
File diff suppressed because one or more lines are too long
@ -1,4 +1,4 @@
|
||||
upp/tiristor.o: ..\Core\upp\tiristor.c ..\Core\upp\upp.h \
|
||||
upp/tiristor.o: ..\Core\upp\tiristor.c ..\Core\upp\tiristor.h \
|
||||
..\Core\Inc\main.h ..\Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal.h \
|
||||
..\Core\Inc\stm32f1xx_hal_conf.h \
|
||||
..\Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_rcc.h \
|
||||
@ -30,6 +30,4 @@ upp/tiristor.o: ..\Core\upp\tiristor.c ..\Core\upp\upp.h \
|
||||
..\Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_tim.h \
|
||||
..\Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_tim_ex.h \
|
||||
..\Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_uart.h \
|
||||
..\Core\Inc\adc.h ..\Core\Inc\tim.h ..\Core\Inc\usart.h \
|
||||
..\Core\Inc\gpio.h ..\Core\upp\zero_cross.h ..\Core\upp\adc_filter.h \
|
||||
..\Core\upp\tiristor.h
|
||||
..\Core\Inc\tim.h
|
||||
|
Loading…
Reference in New Issue
Block a user