Чет работает

This commit is contained in:
2025-12-16 17:57:59 +03:00
commit 260a6416ad
2906 changed files with 982301 additions and 0 deletions

View 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;
}

View 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
View 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
View 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

View 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;
}

View 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
View 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
View 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