Чет работает
This commit is contained in:
89
Core/UKSI/foster_student.c
Normal file
89
Core/UKSI/foster_student.c
Normal file
@@ -0,0 +1,89 @@
|
||||
#include "foster_student.h"
|
||||
|
||||
void foster_init(FosterStudent* fs, float t_critical)
|
||||
{
|
||||
if (!fs) return;
|
||||
|
||||
for (int i = 0; i < FS_WINDOW_SIZE; i++) {
|
||||
fs->window[i] = 0.0f;
|
||||
}
|
||||
|
||||
fs->t_critical = t_critical;
|
||||
fs->mse = 1.0f;
|
||||
fs->index = 0;
|
||||
fs->count = 0;
|
||||
fs->ready = false;
|
||||
}
|
||||
|
||||
void foster_set_mse(FosterStudent* fs, float mse)
|
||||
{
|
||||
if (!fs || mse <= 0.0f) return;
|
||||
fs->mse = mse;
|
||||
}
|
||||
|
||||
void foster_add_sample(FosterStudent* fs, float value)
|
||||
{
|
||||
if (!fs) return;
|
||||
|
||||
fs->window[fs->index] = value;
|
||||
fs->index = (fs->index + 1) % FS_WINDOW_SIZE;
|
||||
|
||||
if (fs->count < FS_WINDOW_SIZE) {
|
||||
fs->count++;
|
||||
if (fs->count == FS_WINDOW_SIZE) {
|
||||
fs->ready = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t foster_is_ready(FosterStudent* fs)
|
||||
{
|
||||
return fs && fs->ready;
|
||||
}
|
||||
|
||||
uint8_t foster_check(FosterStudent* fs)
|
||||
{
|
||||
if (!fs || !fs->ready) {
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
float first = fs->window[(fs->index) % FS_WINDOW_SIZE];
|
||||
float max_val = first;
|
||||
float min_val = first;
|
||||
|
||||
uint8_t m = 0;
|
||||
uint8_t l = 0;
|
||||
float d_sum = 0.0f;
|
||||
|
||||
for (int i = 0; i < FS_WINDOW_SIZE; i++) {
|
||||
float val = fs->window[(fs->index + i) % FS_WINDOW_SIZE];
|
||||
|
||||
if (val > max_val) {
|
||||
max_val = val;
|
||||
m = 1;
|
||||
} else {
|
||||
m = 0;
|
||||
}
|
||||
|
||||
if (val < min_val) {
|
||||
min_val = val;
|
||||
l = 1;
|
||||
} else {
|
||||
l = 0;
|
||||
}
|
||||
|
||||
d_sum += (float)(m - l);
|
||||
}
|
||||
|
||||
if (d_sum < 0.0f) d_sum = -d_sum;
|
||||
|
||||
if (fs->mse > 0.0f) {
|
||||
float t_value = d_sum / fs->mse;
|
||||
|
||||
fs->t_current = t_value;
|
||||
|
||||
return (t_value > fs->t_critical) ? 1 : 0;
|
||||
}
|
||||
|
||||
return 0xFF;
|
||||
}
|
||||
28
Core/UKSI/foster_student.h
Normal file
28
Core/UKSI/foster_student.h
Normal file
@@ -0,0 +1,28 @@
|
||||
#ifndef FOSTER_STUDENT_H
|
||||
#define FOSTER_STUDENT_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
/* Конфигурация */
|
||||
#define FS_WINDOW_SIZE 10 /* Размер окна анализа */
|
||||
|
||||
/* Структура контекста */
|
||||
typedef struct {
|
||||
float window[FS_WINDOW_SIZE]; /* Буфер окна */
|
||||
float t_current; /* Текущее значение t */
|
||||
float t_critical; /* Критическое значение t */
|
||||
float mse; /* MSE для нормализации */
|
||||
uint8_t index; /* Индекс в буфере */
|
||||
uint8_t count; /* Количество измерений */
|
||||
uint8_t ready; /* Флаг готовности */
|
||||
} FosterStudent;
|
||||
|
||||
/* Прототипы функций */
|
||||
void foster_init(FosterStudent* fs, float t_critical);
|
||||
void foster_set_mse(FosterStudent* fs, float mse);
|
||||
void foster_add_sample(FosterStudent* fs, float value);
|
||||
uint8_t foster_is_ready(FosterStudent* fs);
|
||||
uint8_t foster_check(FosterStudent* fs);
|
||||
|
||||
#endif /* FOSTER_STUDENT_H */
|
||||
142
Core/UKSI/uksi_calc_res.c
Normal file
142
Core/UKSI/uksi_calc_res.c
Normal file
@@ -0,0 +1,142 @@
|
||||
#include "uksi_calc_res.h"
|
||||
|
||||
|
||||
/**
|
||||
* @brief Конфигуарция коэфициентов АЦП.
|
||||
* @param adc Указатель на кастомный хендл АЦП
|
||||
* @param levelZero Нулевой уровень (в квантах АЦП)
|
||||
* @param valueMax Максимальный уровень Единиц Измерения (в Вольтах/Амперах/Градусах)
|
||||
* @param levelMax Максимальный уровень АЦП (в квантах АЦП)
|
||||
* @return HAL Status.
|
||||
*/
|
||||
HAL_StatusTypeDef ADC_ConfigCoef(ADC_t *adc, uint16_t levelZero, float valueMax, uint16_t levelMax, uint16_t lOffset)
|
||||
{
|
||||
HAL_StatusTypeDef res;
|
||||
if(check_null_ptr_1(adc))
|
||||
return HAL_ERROR;
|
||||
if((valueMax == 0) || (levelMax == 0))
|
||||
return HAL_ERROR;
|
||||
|
||||
adc->Coefs.lMax = levelMax;
|
||||
adc->Coefs.vMax = valueMax;
|
||||
adc->Coefs.lZero = levelZero;
|
||||
adc->Coefs.lOffset = lOffset;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Конфигуарция фильтров АЦП.
|
||||
* @param adc Указатель на кастомный хендл АЦП
|
||||
* @param levelZero Нулевой уровень (в квантах АЦП)
|
||||
* @param valueMax Максимальный уровень Единиц Измерения (в Вольтах/Амперах/Градусах)
|
||||
* @param levelMax Максимальный уровень АЦП (в квантах АЦП)
|
||||
* @return HAL Status.
|
||||
*/
|
||||
HAL_StatusTypeDef ADC_ConfigFilter(ADC_t *adc, uint8_t median_size, uint32_t average_size)
|
||||
{
|
||||
HAL_StatusTypeDef res;
|
||||
if(check_null_ptr_1(adc))
|
||||
return HAL_ERROR;
|
||||
|
||||
FilterMedianInt_Init(&adc->mdn, median_size, 0);
|
||||
FilterAverageInt_Init(&adc->avg, average_size, FILTER_MODE_DEFAULT);
|
||||
|
||||
|
||||
Filter_Start(&adc->mdn);
|
||||
Filter_Start(&adc->avg);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
/**
|
||||
* @brief Расчет напряжения на АЦП.
|
||||
* @param adc Указатель на кастомный хендл АЦП
|
||||
* @param rawval Сырое значение АЦП
|
||||
* @return Напряжение (float).
|
||||
*/
|
||||
float ADC_Calc(ADC_t *adc)
|
||||
{
|
||||
if(check_null_ptr_1(adc))
|
||||
return 0;
|
||||
ADC_Coefs_t *coefs = &adc->Coefs;
|
||||
|
||||
int16_t rawval = (int16_t)HAL_ADC_GetValue(adc->hadc);
|
||||
|
||||
|
||||
rawval = Filter_Process(&adc->mdn, rawval);
|
||||
rawval = Filter_Process(&adc->avg, rawval);
|
||||
|
||||
rawval -= coefs->lOffset;
|
||||
if(rawval < 0)
|
||||
rawval = 0;
|
||||
if(rawval >4095)
|
||||
rawval = 4095;
|
||||
adc->Raw = rawval;
|
||||
|
||||
adc->Voltage = ((float)(rawval)-coefs->lZero) * coefs->vMax / (coefs->lMax-coefs->lZero);
|
||||
return adc->Voltage;
|
||||
}
|
||||
|
||||
HAL_StatusTypeDef UKSI_Calc_Init(UKSI_Calc_t *calc, ADC_HandleTypeDef *hadc)
|
||||
{
|
||||
if(check_null_ptr_2(calc, hadc))
|
||||
return HAL_ERROR;
|
||||
|
||||
calc->adc.hadc = hadc;
|
||||
ADC_ConfigCoef(&calc->adc, 0, 1.411, 1860, 14);
|
||||
ADC_ConfigFilter(&calc->adc, 10, 50000);
|
||||
|
||||
calc->RMeasOhm = 35060;
|
||||
calc->RLimitOhm = 1.5e6;
|
||||
calc->DCVoltage = 63;
|
||||
|
||||
foster_init(&calc->adc.foster, 3000.0f);
|
||||
foster_set_mse(&calc->adc.foster, 0.001f); /* Подберите под ваши значения напряжения */
|
||||
|
||||
HAL_ADCEx_Calibration_Start(hadc, ADC_SINGLE_ENDED);
|
||||
|
||||
return HAL_ADC_Start(hadc);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Расчет изоляции.
|
||||
* @param calc Указатель на структуру для расчета изоляции
|
||||
* @return Сопротивление изоляции (float).
|
||||
*/
|
||||
float UKSI_Calc_Isolation(UKSI_Calc_t *calc)
|
||||
{
|
||||
if(check_null_ptr_1(calc))
|
||||
return 0;
|
||||
|
||||
float voltage = ADC_Calc(&calc->adc);
|
||||
|
||||
if(Filter_isDataReady(&calc->adc.avg))
|
||||
{
|
||||
/* Проверка стабильности напряжения */
|
||||
foster_add_sample(&calc->adc.foster, voltage);
|
||||
|
||||
if(foster_is_ready(&calc->adc.foster)) {
|
||||
uint8_t stability = foster_check(&calc->adc.foster);
|
||||
calc->adc.is_stable = stability;
|
||||
|
||||
/* Если нестабильно, возвращаем 0 или предыдущее значение */
|
||||
if(stability == 1) { /* Нестабильно */
|
||||
return calc->IsoOhm; /* Или calc->IsoOhm для сохранения последнего значения */
|
||||
}
|
||||
}
|
||||
|
||||
/* Расчет изоляции */
|
||||
float current = voltage / calc->RMeasOhm;
|
||||
float Rtotal = calc->DCVoltage / current;
|
||||
float Riso = Rtotal - (calc->RMeasOhm + calc->RLimitOhm);
|
||||
|
||||
calc->IsoOhm = Riso;
|
||||
calc->IsoMOhm = Riso / 1000000.0f;
|
||||
calc->IsoCurrentuA = current * 1000000.0f;
|
||||
|
||||
}
|
||||
return calc->IsoOhm;
|
||||
}
|
||||
|
||||
|
||||
62
Core/UKSI/uksi_calc_res.h
Normal file
62
Core/UKSI/uksi_calc_res.h
Normal file
@@ -0,0 +1,62 @@
|
||||
|
||||
#ifndef _UKSI_CALC_RES_H
|
||||
#define _UKSI_CALC_RES_H
|
||||
#include "main.h"
|
||||
#include "foster_student.h" /* Добавить этот include */
|
||||
|
||||
#define FOSTER_ST
|
||||
|
||||
/**
|
||||
* @brief Коэфициенты канала АЦП для пересчета в единицы измерения
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint16_t lZero; ///< Нулевой уровень (в квантах АЦП)
|
||||
float vMax; ///< Максимальный уровень Единиц Измерения (в Вольтах/Амперах)
|
||||
uint16_t lMax; ///< Максимальный уровень АЦП (в квантах АЦП)
|
||||
uint16_t lOffset; ///< Максимальный уровень АЦП (в квантах АЦП)
|
||||
}ADC_Coefs_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ADC_HandleTypeDef *hadc;
|
||||
|
||||
uint16_t Raw;
|
||||
float Voltage;
|
||||
ADC_Coefs_t Coefs;
|
||||
|
||||
FilterMedianInt_t mdn;
|
||||
FilterAverageInt_t avg;
|
||||
FosterStudent foster; /* Для проверки стабильности */
|
||||
uint8_t is_stable; /* 0-стабильно, 1-нестабильно, 0xFF-ошибка */
|
||||
}ADC_t;
|
||||
|
||||
HAL_StatusTypeDef ADC_ConfigCoef(ADC_t *adc, uint16_t levelZero, float valueMax, uint16_t levelMax, uint16_t lOffset);
|
||||
HAL_StatusTypeDef ADC_ConfigFilter(ADC_t *adc, uint8_t median_size, uint32_t average_size);
|
||||
float ADC_Calc(ADC_t *adc);
|
||||
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ADC_t adc; // АЦП
|
||||
|
||||
float Voltage[100];
|
||||
|
||||
float RMeasOhm; // Сопротивление резистора с которого снимается напряжение
|
||||
float RLimitOhm; // Сопротивление токоограничивающего резистора
|
||||
float DCVoltage; // Нарпяжение подаваемое в изоляцию
|
||||
|
||||
|
||||
|
||||
float IsoOhm; // Измеренное сопротивление изоляции в МОм
|
||||
float IsoMOhm; // Измеренное сопротивление изоляции Ом
|
||||
float IsoCurrentuA; // Ток утечки изоляции в мкА
|
||||
|
||||
|
||||
}UKSI_Calc_t;
|
||||
|
||||
HAL_StatusTypeDef UKSI_Calc_Init(UKSI_Calc_t *calc, ADC_HandleTypeDef *hadc);
|
||||
float UKSI_Calc_Isolation(UKSI_Calc_t *calc);
|
||||
|
||||
#endif //_UKSI_CALC_RES_H
|
||||
33
Core/UKSI/uksi_dc_control.c
Normal file
33
Core/UKSI/uksi_dc_control.c
Normal file
@@ -0,0 +1,33 @@
|
||||
#include "uksi_dc_control.h"
|
||||
|
||||
HAL_StatusTypeDef DC_Init(UKSI_DC_t *dc, TIM_HandleTypeDef *htim, uint32_t activemode, uint32_t inactivemode)
|
||||
{
|
||||
if(check_null_ptr_2(dc, htim))
|
||||
return HAL_ERROR;
|
||||
|
||||
dc->htim = htim;
|
||||
dc->ActiveMode = activemode;
|
||||
dc->InactiveMode = inactivemode;
|
||||
|
||||
HAL_TIMEx_OCN_Start(htim, TIM_CHANNEL_1);
|
||||
return HAL_TIM_OC_Start(htim, TIM_CHANNEL_1);
|
||||
}
|
||||
|
||||
|
||||
HAL_StatusTypeDef DC_Enable(UKSI_DC_t *dc, uint8_t state)
|
||||
{
|
||||
if(check_null_ptr_1(dc))
|
||||
return HAL_ERROR;
|
||||
|
||||
dc->htim->Instance->CCMR1 &= ~TIM_OCMODE_PWM2;
|
||||
if(state)
|
||||
{
|
||||
dc->htim->Instance->CCMR1 |= dc->ActiveMode;
|
||||
}
|
||||
else
|
||||
{
|
||||
dc->htim->Instance->CCMR1 |= dc->InactiveMode;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
16
Core/UKSI/uksi_dc_control.h
Normal file
16
Core/UKSI/uksi_dc_control.h
Normal file
@@ -0,0 +1,16 @@
|
||||
#ifndef _UKSI_DC_CONTROL_H
|
||||
#define _UKSI_DC_CONTROL_H
|
||||
#include "main.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
TIM_HandleTypeDef *htim;
|
||||
uint32_t ActiveMode;
|
||||
uint32_t InactiveMode;
|
||||
}UKSI_DC_t;
|
||||
|
||||
HAL_StatusTypeDef DC_Init(UKSI_DC_t *dc, TIM_HandleTypeDef *htim, uint32_t activemode, uint32_t inactivemode);
|
||||
HAL_StatusTypeDef DC_Enable(UKSI_DC_t *dc, uint8_t state);
|
||||
|
||||
|
||||
#endif //_UKSI_CALC_RES_H
|
||||
61
Core/UKSI/uksi_main.c
Normal file
61
Core/UKSI/uksi_main.c
Normal file
@@ -0,0 +1,61 @@
|
||||
#include "uksi_main.h"
|
||||
#include "adc.h"
|
||||
#include "tim.h"
|
||||
UKSI_Calc_t uksi_calc;
|
||||
UKSI_DC_t uksi_dc;
|
||||
float iso_result;
|
||||
int dbg_dc = 0;
|
||||
int dbg_dc_delay = 5000;
|
||||
void UKSI_Init()
|
||||
{
|
||||
DC_Init(&uksi_dc, &htim1, TIM_OCMODE_INACTIVE, TIM_OCMODE_ACTIVE);
|
||||
UKSI_Calc_Init(&uksi_calc, &hadc1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void UKSI_prewhile()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void UKSI_while()
|
||||
{
|
||||
static uint32_t prev_dc_tick = 0;
|
||||
static uint32_t start_measure_tick = 0;
|
||||
float curr_iso = 0;
|
||||
DC_Enable(&uksi_dc, dbg_dc);
|
||||
|
||||
if(dbg_dc)
|
||||
{
|
||||
curr_iso = UKSI_Calc_Isolation(&uksi_calc);
|
||||
if(uwTick - prev_dc_tick > dbg_dc_delay) // подаем импульс минимум на секунду
|
||||
{
|
||||
if(!foster_check(&uksi_calc.adc.foster)) // если стабильный уровень найден - отключаем на секунду источник
|
||||
{
|
||||
if(start_measure_tick == 0)
|
||||
{
|
||||
start_measure_tick = uwTick; // измеряем еще 5 секунд и выключаем источник
|
||||
}
|
||||
else
|
||||
{
|
||||
if(uwTick - start_measure_tick > dbg_dc_delay)
|
||||
{
|
||||
dbg_dc = 0;
|
||||
start_measure_tick = 0;
|
||||
prev_dc_tick = uwTick;
|
||||
iso_result = curr_iso;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(uwTick - prev_dc_tick > dbg_dc_delay) // подаем импульс минимум на секунду
|
||||
{
|
||||
dbg_dc = 1;
|
||||
prev_dc_tick = uwTick;
|
||||
}
|
||||
}
|
||||
}
|
||||
12
Core/UKSI/uksi_main.h
Normal file
12
Core/UKSI/uksi_main.h
Normal file
@@ -0,0 +1,12 @@
|
||||
|
||||
#ifndef _UKSI_MAIN_H
|
||||
#define _UKSI_MAIN_H
|
||||
|
||||
|
||||
#include "uksi_calc_res.h"
|
||||
#include "uksi_dc_control.h"
|
||||
|
||||
void UKSI_Init();
|
||||
void UKSI_prewhile();
|
||||
void UKSI_while();
|
||||
#endif //_UKSI_MAIN_H
|
||||
Reference in New Issue
Block a user