|
@@ -1,738 +1,738 @@
|
|
|
-#include "at32f403a_407.h"
|
|
|
-#include "analog_input.h"
|
|
|
-#include "shift_reg.h"
|
|
|
-#include "utility.h"
|
|
|
-#include "FreeRTOS.h"
|
|
|
-#include "task.h"
|
|
|
-#include "settings_api.h"
|
|
|
-#include "adc_transport.h"
|
|
|
-#include "ms5192t.h"
|
|
|
-#include "monitoring.h"
|
|
|
-#include "mux.h"
|
|
|
-#include "filter.h"
|
|
|
-#include <stdio.h>
|
|
|
-
|
|
|
-#undef DBG
|
|
|
-#define DBG if(0)
|
|
|
-
|
|
|
-#if defined (MAI_12)
|
|
|
-
|
|
|
-#define VOLTAGE_FACTOR 0.182382
|
|
|
-#define CURRENT_FACTOR 0.00091191
|
|
|
-#define CRNT_LIM_V_FACTOR 0.0476
|
|
|
-#define VOLT_ALARM_LIMIT 10000.0
|
|
|
-#define CUR_ALARM_PAUSE 300 // время в секундах на остывание токового шунта
|
|
|
-#define CUR_LIM_LOW_LIMIT 23.0
|
|
|
-#define CUR_LIM_LOW_LIMIT 25.0
|
|
|
-#define CUR_LIM_DELTA_U 0.6
|
|
|
-
|
|
|
-
|
|
|
-uint8_t ai_mux; // выход сдвигового регистра U1010 (управляет MUX 301, 401)
|
|
|
- // мультиплексоры отвечат за коммутацию аналоговых входов и АЦП
|
|
|
-
|
|
|
-uint16_t ai_mode; // режим измерения аналоговых каналов (ток или напряжение)
|
|
|
- // 0000 0000 0000 0000
|
|
|
- // младшие 6 (с 1..6) бит - каналы с 1 по 6 соответственно
|
|
|
- // биты 9..14 - каналы с 7 по 12 соответственно
|
|
|
-
|
|
|
-uint16_t ai_alarm; // слово аварий входов
|
|
|
-
|
|
|
-uint16_t ai_gain[AI_COMMON_NUMBER]; // массив коэффициентов усиленя (modbus)
|
|
|
-
|
|
|
-uint16_t adc_com_raw_data[AI_COMMON_NUMBER]; // сырые данные
|
|
|
-float adc_com_data[AI_COMMON_NUMBER]; // пересчитанные, фильтрованные данные
|
|
|
-
|
|
|
-uint16_t adc_com_fil_data[AI_COMMON_NUMBER]; // Фильтрованные данные (только для отладки)
|
|
|
-
|
|
|
-uint16_t adc_add_raw_data[AI_ADD_NUMBER];
|
|
|
-
|
|
|
-
|
|
|
-led_t ai_alarm_led[12] = {IO_1_R, IO_2_R, IO_3_R, IO_4_R,
|
|
|
- IO_5_R, IO_6_R, IO_7_R, IO_8_R,
|
|
|
- IO_9_R, IO_10_R, IO_11_R, IO_12_R};
|
|
|
-
|
|
|
-led_t ai_input_led[12] = {IO_1_G, IO_2_G, IO_3_G, IO_4_G,
|
|
|
- IO_5_G, IO_6_G, IO_7_G, IO_8_G,
|
|
|
- IO_9_G, IO_10_G, IO_11_G, IO_12_G};
|
|
|
-
|
|
|
-uint16_t ai_state_bit; // состояние аналоговых входов (вкл/выкл) битовое поле
|
|
|
-
|
|
|
-ai_alarm_t ai_alarm_f[AI_COMMON_NUMBER]; // Вспомогательная структура для
|
|
|
- //работы с авариями
|
|
|
-
|
|
|
-ai_alarm_t ai_cur_lim; // Вспомогательная структура для работы с аварией
|
|
|
- // модуля питания внешних датчиков
|
|
|
-
|
|
|
-
|
|
|
-// Авария датчика, значение ниже диапазона (не обрыв)
|
|
|
-// Авария, не обрыв линии (возможно неисправен датчик)
|
|
|
-// Авария датчика, значение выше диапазона (не обрыв)
|
|
|
-uint16_t ai_voltage_alarm; // аварии в режиме измерения напряжения
|
|
|
-
|
|
|
-// аварии в режиме измерения тока
|
|
|
-uint16_t ai_current_low; // значение ниже диапазона
|
|
|
-uint16_t ai_current_high; // значение выше диапазона
|
|
|
-uint16_t ai_current_fail; // авария (возможно неисправен датчик)
|
|
|
-uint16_t ai_load_sens_alarm;// авария превышения нагрузки на блок питания внешних датчиков
|
|
|
-
|
|
|
-//
|
|
|
-void ai_init(void)
|
|
|
-{
|
|
|
- // Фильтры (скользящее среднее) для 12-и основных каналов
|
|
|
- average_filter_init();
|
|
|
-
|
|
|
- // Зеленые LED сигнализируют (вкл/выкл) входов.
|
|
|
- ai_led_update();
|
|
|
-
|
|
|
- // Сдвиговые регистры
|
|
|
- sh_init();
|
|
|
-
|
|
|
- // Режим измерения
|
|
|
- ai_set_meas_mode();
|
|
|
-
|
|
|
- // Питание внешних датчиков
|
|
|
- ai_ext_sens_power(settings.ext_sens_power);
|
|
|
-
|
|
|
- // Внешинй ADC
|
|
|
- ai_adc_init();
|
|
|
-
|
|
|
- // Modbus параметры
|
|
|
- ai_init_modbus_params();
|
|
|
-}
|
|
|
-
|
|
|
-//
|
|
|
-void ai_init_modbus_params(void)
|
|
|
-{
|
|
|
- for (uint8_t i = 0; i < AI_COMMON_NUMBER; i++) {
|
|
|
- ai_gain[i] = settings.ai[i].gain_factor;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-// Управление LED для 12-и основных входов
|
|
|
-void ai_led_update(void)
|
|
|
-{
|
|
|
- for (int i = 0; i < AI_COMMON_NUMBER; i++)
|
|
|
- {
|
|
|
- if (settings.ai[i].state)
|
|
|
- leds[ai_input_led[i]].state = LED_ON;
|
|
|
- else
|
|
|
- leds[ai_input_led[i]].state = LED_OFF;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-// Установить режим измерения каналов с 1 по 12.
|
|
|
-void ai_set_meas_mode(void)
|
|
|
-{
|
|
|
- for (int i = 0; i < AI_COMMON_NUMBER; i++)
|
|
|
- {
|
|
|
- if (settings.ai[i].mode)
|
|
|
- ai_set_mode_word((MEAS_CHAN_MODE_t)1, i + 1);
|
|
|
- else
|
|
|
- ai_set_mode_word((MEAS_CHAN_MODE_t)0, i + 1);
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-// Настройка внешнего ADC
|
|
|
-bool ai_adc_init(void)
|
|
|
-{
|
|
|
- uint8_t ret;
|
|
|
- unsigned long value;
|
|
|
-
|
|
|
- adc_gpio_init();
|
|
|
-
|
|
|
- for (uint32_t i = 0; i < 100; i++) {
|
|
|
- MS5192T_Reset();
|
|
|
- ret = MS5192T_Init();
|
|
|
- DBG printf("ADC init status: %s\r\n", ret == 1 ? "OK" : "FAILED");
|
|
|
- if (ret == 1)
|
|
|
- break;
|
|
|
- vTaskDelay(10);
|
|
|
- }
|
|
|
-
|
|
|
- if (!ret) {
|
|
|
- mon_set_err(ADC_ERR, true);
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- // Запрос регистра конфигурации для (0x710 - значение по умолчанию)
|
|
|
- value = MS5192T_GetRegisterValue(MS5192T_REG_CONF, 2, 1);
|
|
|
- DBG printf("ADC cfg reg: 0x%X: ", value);
|
|
|
- DBG print_binary_half_word((uint16_t)value);
|
|
|
-
|
|
|
- // Коэф-т усиления: 1
|
|
|
- DBG printf("ADC. Set gain rate 1\r\n");
|
|
|
- MS5192T_SetGain(MS5192T_GAIN_1);
|
|
|
- value = MS5192T_GetRegisterValue(MS5192T_REG_CONF, 2, 1);
|
|
|
- DBG printf("ADC cfg reg: 0x%X: ", value);
|
|
|
- DBG print_binary_half_word((uint16_t)value);
|
|
|
-
|
|
|
- // Униполярный режим
|
|
|
- DBG printf("Set unipolar input mode...\r\n");
|
|
|
- MS5192T_SetPolar(MS5192T_CONF_UNIPOLAR);
|
|
|
- value = MS5192T_GetRegisterValue(MS5192T_REG_CONF, 2, 1);
|
|
|
- DBG printf("ADC cfg reg: 0x%X: ", value);
|
|
|
- DBG print_binary_half_word((uint16_t)value);
|
|
|
-
|
|
|
- // Регистр статуса
|
|
|
- value = MS5192T_GetRegisterValue(MS5192T_REG_STAT, 1, 1);
|
|
|
- DBG printf("ADC status reg: 0x%X: ", value);
|
|
|
- DBG print_binary_byte((uint8_t)value);
|
|
|
-
|
|
|
- // Установка внутреннего опорного напряжения
|
|
|
- MS5192T_SetIntReference(MS5192T_REFSEL_INT); // select internal 1.17V reference
|
|
|
- value = MS5192T_GetRegisterValue(MS5192T_REG_CONF, 2, 1);
|
|
|
- DBG printf("ADC cfg reg: 0x%X: ", value);
|
|
|
- DBG print_binary_half_word((uint16_t)value);
|
|
|
-
|
|
|
- // Регистр режима (MODE register)
|
|
|
- value = MS5192T_GetRegisterValue(MS5192T_REG_MODE, 2, 1);
|
|
|
- DBG printf("ADC mode reg: 0x%X: ", value);
|
|
|
- DBG print_binary_half_word((uint16_t)value);
|
|
|
-
|
|
|
- // Установить update rate
|
|
|
- DBG printf("Set update rate.\r\n");
|
|
|
- MS5192T_SetUpdateRate(MS5192T_UP_RATE_500);
|
|
|
- value = MS5192T_GetRegisterValue(MS5192T_REG_MODE, 2, 1);
|
|
|
- DBG printf("ADC mode reg: 0x%X: ", value);
|
|
|
- DBG print_binary_half_word((uint16_t)value);
|
|
|
-
|
|
|
- // Калибровка
|
|
|
-
|
|
|
- // 1 - ый канал
|
|
|
- MS5192T_Calibrate(MS5192T_MODE_CAL_INT_ZERO, MS5192T_CH_AIN1P_AIN1M);
|
|
|
- MS5192T_Calibrate(MS5192T_MODE_CAL_INT_FULL, MS5192T_CH_AIN1P_AIN1M);
|
|
|
-
|
|
|
- // 2 - ой канал
|
|
|
- MS5192T_Calibrate(MS5192T_MODE_CAL_INT_ZERO, MS5192T_CH_AIN2P_AIN2M);
|
|
|
- MS5192T_Calibrate(MS5192T_MODE_CAL_INT_FULL, MS5192T_CH_AIN2P_AIN2M);
|
|
|
-
|
|
|
- return true;
|
|
|
-}
|
|
|
-
|
|
|
-// Оцифровка всех 16-и каналов (входы + дополнительные каналы)
|
|
|
-void ai_processing(void)
|
|
|
-{
|
|
|
- float filter_factor;
|
|
|
-
|
|
|
- // 12 основных каналов
|
|
|
- for (uint8_t i = 0; i < AI_COMMON_NUMBER/2; i++)
|
|
|
- {
|
|
|
- adc_meas_two_channels(&settings.ai[i], &settings.ai[i + 6],
|
|
|
- &adc_com_raw_data[i], &adc_com_raw_data[i + 6]);
|
|
|
-
|
|
|
- // ---------------------------------------------------------------------
|
|
|
- // Фильтрованные данные
|
|
|
-
|
|
|
- filter_factor = settings.ai[i].mode == 0 ? VOLTAGE_FACTOR : CURRENT_FACTOR;
|
|
|
-
|
|
|
- adc_com_data[i] = (float)adc_com_raw_data[i]*filter_factor*
|
|
|
- settings.ai[i].k_factor + settings.ai[i].b_factor;
|
|
|
-
|
|
|
- filter_factor = settings.ai[i + 6].mode == 0 ? VOLTAGE_FACTOR : CURRENT_FACTOR;
|
|
|
-
|
|
|
- adc_com_data[i + 6] = (float)adc_com_raw_data[i + 6]*filter_factor*
|
|
|
- settings.ai[i + 6].k_factor + settings.ai[i + 6].b_factor;
|
|
|
-
|
|
|
- // ---------------------------------------------------------------------
|
|
|
- // Фильтрация. Скользящее среднее. Только для отладки.
|
|
|
- adc_com_fil_data[i] = average_int(&average_filter[i], adc_com_raw_data[i]);
|
|
|
- adc_com_fil_data[i + 6] = average_int(&average_filter[i + 6], adc_com_raw_data[i + 6]);
|
|
|
- }
|
|
|
-
|
|
|
- // 4 дополнительных канала
|
|
|
- for (uint8_t i = 0; i < AI_ADD_NUMBER/2; i++)
|
|
|
- {
|
|
|
- adc_meas_two_channels(&settings.ai_add[i], &settings.ai_add[i + 2],
|
|
|
- &adc_add_raw_data[i], &adc_add_raw_data[i + 2]);
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
-#if 0
|
|
|
- printf("end\r\n");
|
|
|
- adc_print_data();
|
|
|
- //adc_print_data_extend();
|
|
|
- printf("end\r\n");
|
|
|
-#endif
|
|
|
-}
|
|
|
-
|
|
|
-//
|
|
|
-void adc_meas_two_channels(ai_t *one, ai_t *two, uint16_t *out_one, uint16_t *out_two)
|
|
|
-{
|
|
|
- uint8_t gain;
|
|
|
-
|
|
|
- // 1 - ый канал
|
|
|
- if (one->state == 0) {
|
|
|
- DBG printf("[one] channel name: %u off\r\n", one->name);
|
|
|
-
|
|
|
- }
|
|
|
- else {
|
|
|
- DBG printf("[one] channel name: %u on\r\n", one->name);
|
|
|
-
|
|
|
- gain = adc_get_gain(one->gain_factor);
|
|
|
- MS5192T_SetGain(gain);
|
|
|
- ai_connect_channel(one->name);
|
|
|
- vTaskDelay(1);
|
|
|
- MS5192T_SetChannel(MS5192T_CH_AIN1P_AIN1M);
|
|
|
- *out_one = MS5192T_SingleConversion();
|
|
|
- }
|
|
|
-
|
|
|
- // 2 - ой канал
|
|
|
- if (two->state == 0) {
|
|
|
- DBG printf("[two] channel name: %u off\r\n", two->name);
|
|
|
- }
|
|
|
- else {
|
|
|
- DBG printf("[two] channel name: %u on\r\n", two->name);
|
|
|
-
|
|
|
- gain = adc_get_gain(two->gain_factor);
|
|
|
- MS5192T_SetGain(gain);
|
|
|
- ai_connect_channel(two->name);
|
|
|
- vTaskDelay(1);
|
|
|
- MS5192T_SetChannel(MS5192T_CH_AIN2P_AIN2M);
|
|
|
- *out_two = MS5192T_SingleConversion();
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-//
|
|
|
-uint8_t adc_get_gain(uint8_t tmp)
|
|
|
-{
|
|
|
- uint8_t ret;
|
|
|
-
|
|
|
- switch (tmp)
|
|
|
- {
|
|
|
- case 1 : ret = MS5192T_GAIN_1; break;
|
|
|
- case 2 : ret = MS5192T_GAIN_2; break;
|
|
|
- case 4 : ret = MS5192T_GAIN_4; break;
|
|
|
- case 8 : ret = MS5192T_GAIN_8; break;
|
|
|
- case 16 : ret = MS5192T_GAIN_16; break;
|
|
|
- case 32 : ret = MS5192T_GAIN_32; break;
|
|
|
- case 64 : ret = MS5192T_GAIN_64; break;
|
|
|
- case 128: ret = MS5192T_GAIN_128; break;
|
|
|
- default : ret = MS5192T_GAIN_1; break;
|
|
|
- }
|
|
|
- return ret;
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-//
|
|
|
-void adc_print_data(void)
|
|
|
-{
|
|
|
- printf("\033[2J");
|
|
|
- printf("\033[H");
|
|
|
-
|
|
|
-#if 1
|
|
|
- printf("AN_INP_1: 0x%X, %.3f\r\n", adc_com_raw_data[0], adc_com_data[0]);
|
|
|
- printf("AN_INP_2: 0x%X, %.3f\r\n", adc_com_raw_data[1], adc_com_data[1]);
|
|
|
- printf("AN_INP_3: 0x%X, %.3f\r\n", adc_com_raw_data[2], adc_com_data[2]);
|
|
|
- printf("AN_INP_4: 0x%X, %.3f\r\n", adc_com_raw_data[3], adc_com_data[3]);
|
|
|
- printf("AN_INP_5: 0x%X, %.3f\r\n", adc_com_raw_data[4], adc_com_data[4]);
|
|
|
- printf("AN_INP_6: 0x%X, %.3f\r\n", adc_com_raw_data[5], adc_com_data[5]);
|
|
|
- printf("AN_INP_7: 0x%X, %.3f\r\n", adc_com_raw_data[6], adc_com_data[6]);
|
|
|
- printf("AN_INP_8: 0x%X, %.3f\r\n", adc_com_raw_data[7], adc_com_data[7]);
|
|
|
- printf("AN_INP_9: 0x%X, %.3f\r\n", adc_com_raw_data[8], adc_com_data[8]);
|
|
|
- printf("AN_INP_10: 0x%X, %.3f\r\n", adc_com_raw_data[9], adc_com_data[9]);
|
|
|
- printf("AN_INP_11: 0x%X, %.3f\r\n", adc_com_raw_data[10],adc_com_data[10]);
|
|
|
- printf("AN_INP_12: 0x%X, %.3f\r\n", adc_com_raw_data[11],adc_com_data[11]);
|
|
|
-
|
|
|
- printf("V_ISO_CL: 0x%X, %f\r\n", adc_add_raw_data[0], (double)adc_add_raw_data[0]*VOLTAGE_FACTOR);
|
|
|
- printf("V_ISO : 0x%X, %f\r\n", adc_add_raw_data[1], (double)adc_add_raw_data[1]*VOLTAGE_FACTOR);
|
|
|
- printf("CRNT_LIM_U_BFR_R : 0x%X, %f\r\n", adc_add_raw_data[2],(double)adc_add_raw_data[2]*VOLTAGE_FACTOR);
|
|
|
- printf("CRNT_LIM_U_ABFR_R: 0x%X, %f\r\n", adc_add_raw_data[3],(double)adc_add_raw_data[3]*VOLTAGE_FACTOR);
|
|
|
-#endif
|
|
|
-}
|
|
|
-
|
|
|
-//
|
|
|
-void adc_print_data_extend(void)
|
|
|
-{
|
|
|
- printf("\033[2J");
|
|
|
- printf("\033[H");
|
|
|
-
|
|
|
- printf("AN_INP_1: 0x%X 0x%X %f %f\r\n", adc_com_raw_data[0], adc_com_fil_data[0], (double)adc_com_raw_data[0]*0.00001785305/0.0961538, (double)adc_com_fil_data[0]*0.00001785305/0.0961538);
|
|
|
- printf("AN_INP_2: 0x%X 0x%X %f %f\r\n", adc_com_raw_data[1], adc_com_fil_data[1], (double)adc_com_raw_data[1]*0.00001785305/0.0961538, (double)adc_com_fil_data[1]*0.00001785305/0.0961538);
|
|
|
- printf("AN_INP_3: 0x%X 0x%X %f %f\r\n", adc_com_raw_data[2], adc_com_fil_data[2], (double)adc_com_raw_data[2]*0.00001785305/0.0961538, (double)adc_com_fil_data[2]*0.00001785305/0.0961538);
|
|
|
- printf("AN_INP_4: 0x%X 0x%X %f %f\r\n", adc_com_raw_data[3], adc_com_fil_data[3], (double)adc_com_raw_data[3]*0.00001785305/0.0961538, (double)adc_com_fil_data[3]*0.00001785305/0.0961538);
|
|
|
- printf("AN_INP_5: 0x%X 0x%X %f %f\r\n", adc_com_raw_data[4], adc_com_fil_data[4], (double)adc_com_raw_data[4]*0.00001785305/0.0961538, (double)adc_com_fil_data[4]*0.00001785305/0.0961538);
|
|
|
- printf("AN_INP_6: 0x%X 0x%X %f %f\r\n", adc_com_raw_data[5], adc_com_fil_data[5], (double)adc_com_raw_data[5]*0.00001785305/0.0961538, (double)adc_com_fil_data[5]*0.00001785305/0.0961538);
|
|
|
- printf("AN_INP_7: 0x%X 0x%X %f %f\r\n", adc_com_raw_data[6], adc_com_fil_data[6], (double)adc_com_raw_data[6]*0.00001785305/0.0961538, (double)adc_com_fil_data[6]*0.00001785305/0.0961538);
|
|
|
- printf("AN_INP_8: 0x%X 0x%X %f %f\r\n", adc_com_raw_data[7], adc_com_fil_data[7], (double)adc_com_raw_data[7]*0.00001785305/0.0961538, (double)adc_com_fil_data[7]*0.00001785305/0.0961538);
|
|
|
- printf("AN_INP_9: 0x%X 0x%X %f %f\r\n", adc_com_raw_data[8], adc_com_fil_data[8], (double)adc_com_raw_data[8]*0.00001785305/0.0961538, (double)adc_com_fil_data[8]*0.00001785305/0.0961538);
|
|
|
- printf("AN_INP_10: 0x%X 0x%X %f %f\r\n", adc_com_raw_data[9], adc_com_fil_data[9],(double)adc_com_raw_data[9]*0.00001785305/0.0961538, (double)adc_com_fil_data[9]*0.00001785305/0.0961538);
|
|
|
- printf("AN_INP_11: 0x%X 0x%X %f %f\r\n", adc_com_raw_data[10], adc_com_fil_data[10], (double)adc_com_raw_data[10]*0.00001785305/0.0961538, (double)adc_com_fil_data[10]*0.00001785305/0.0961538);
|
|
|
- printf("AN_INP_12: 0x%X 0x%X %f %f\r\n", adc_com_raw_data[11], adc_com_fil_data[11], (double)adc_com_raw_data[11]*0.00001785305/0.0961538, (double)adc_com_fil_data[11]*0.00001785305/0.0961538);
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-//
|
|
|
-void adc_task(void *params)
|
|
|
-{
|
|
|
- for (;;)
|
|
|
- {
|
|
|
- ai_alarm = sh_ai_mode(ai_mode);
|
|
|
-
|
|
|
- ai_processing();
|
|
|
-
|
|
|
- ai_leds_processing();
|
|
|
-
|
|
|
- vTaskDelay(10);
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-// -------------------------------------------------------------------------- //
|
|
|
-// Определение аварий
|
|
|
-
|
|
|
-//
|
|
|
-void adc_alarm_task(void *params)
|
|
|
-{
|
|
|
- for (;;)
|
|
|
- {
|
|
|
-#if 1
|
|
|
- //printf("Analog input mode: ");
|
|
|
- //print_binary_half_word(ai_mode);
|
|
|
-
|
|
|
- ai_voltage_alarm_detect();
|
|
|
-#endif
|
|
|
- vTaskDelay(1000);
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-// Определение аварий в режиме измерения напряжения
|
|
|
-// ai_voltage_alarm
|
|
|
-void ai_voltage_alarm_detect(void)
|
|
|
-{
|
|
|
- for (int i = 0; i < AI_COMMON_NUMBER; i++)
|
|
|
- {
|
|
|
- // Вход включен и находится в режиме измерения напряжения
|
|
|
- if (settings.ai[i].state && (settings.ai[i].mode == 0))
|
|
|
- {
|
|
|
- if (adc_com_data[i] > VOLT_ALARM_LIMIT)
|
|
|
- ai_voltage_alarm |= 1 << i;
|
|
|
- else
|
|
|
- ai_voltage_alarm &= ~(1 << i);
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-// Опеределение аварий в режиме измерения тока
|
|
|
-// ai_current_low - авария датчика, значение ниже диапазона (не обрыв)
|
|
|
-// ai_current_high - авария, не обрыв линии (возможно неисправен датчик)
|
|
|
-// ai_current_fail - авария датчика, значение выше диапазона (не обрыв)
|
|
|
-void ai_current_alarm_detect(void)
|
|
|
-{
|
|
|
- for (int i = 0; i < AI_COMMON_NUMBER; i++)
|
|
|
- {
|
|
|
- // Вход включен и находится в режиме измерения тока
|
|
|
- if (settings.ai[i].state && (settings.ai[i].mode == 1))
|
|
|
- {
|
|
|
- if (adc_com_data[i] < 4.0)
|
|
|
- {
|
|
|
- // Вход в режиме измерения 4-20 mA
|
|
|
- if (settings.ai[i].current_mode == 1)
|
|
|
- {
|
|
|
- if (adc_com_data[i] > 1.0)
|
|
|
- {
|
|
|
- // Авария датчика, значение ниже диапазона (не обрыв)
|
|
|
- ai_current_low |= 1 << i;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- // Авария, не обрыв линии (возможно неисправен датчик)
|
|
|
- ai_current_fail |= 1 << i;
|
|
|
- }
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- // Снять флаги с аварий
|
|
|
- // Авария датчика, значение ниже диапазона (не обрыв)
|
|
|
- // Авария, не обрыв линии (возможно неисправен датчик)
|
|
|
- ai_current_low &= ~(1 << i);
|
|
|
- ai_current_fail &= ~(1 << i);
|
|
|
- }
|
|
|
- }
|
|
|
- // Измеряемый ток больше 4 mA
|
|
|
- else
|
|
|
- {
|
|
|
- if (adc_com_data[i] > 20.0)
|
|
|
- {
|
|
|
- // Снять флаги аварий
|
|
|
- // Авария, не обрыв линии (возможно неисправен датчик)
|
|
|
- ai_current_high &= ~(1 << i);
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- // Авария датчика, значение выше диапазона (не обрыв)
|
|
|
- ai_current_high |= 1 << i;
|
|
|
-
|
|
|
- if (adc_com_data[i] > 22.0)
|
|
|
- {
|
|
|
- // Перевести вход в режим измерения напряжения
|
|
|
- ai_alarm_f[i].alarm_flag = true;
|
|
|
- // Ждать 5 минут (шунт должен остыть)
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-// Контроль питания внешних датчиков
|
|
|
-// TODO добавить событие в журнал
|
|
|
-void ai_ext_sens_current_control(void)
|
|
|
-{
|
|
|
- float crnt_lim_u_bfr = (float)adc_add_raw_data[2]*CRNT_LIM_V_FACTOR;
|
|
|
- float crnt_lim_u_abfr = (float)adc_add_raw_data[3]*CRNT_LIM_V_FACTOR;
|
|
|
-
|
|
|
- if ((CUR_LIM_LOW_LIMIT < 23.0) || (CUR_LIM_LOW_LIMIT > 25.0))
|
|
|
- return;
|
|
|
-
|
|
|
- if (settings.ext_sens_power == 0)
|
|
|
- return;
|
|
|
-
|
|
|
- if ((crnt_lim_u_bfr - crnt_lim_u_abfr) < CUR_LIM_DELTA_U)
|
|
|
- {
|
|
|
- // Снять флаг аварии
|
|
|
- ai_load_sens_alarm = 0;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- ai_load_sens_alarm = 1;
|
|
|
-
|
|
|
- ai_cur_lim.alarm_flag = true;
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- //adc_add_raw_data[2],(double)adc_add_raw_data[2]*VOLTAGE_FACTOR);
|
|
|
- //VOLTAGE_FACTOR
|
|
|
-
|
|
|
- //printf("CRNT_LIM_U_BFR_R : 0x%X, %f\r\n", adc_add_raw_data[2],(double)adc_add_raw_data[2]*VOLTAGE_FACTOR);
|
|
|
- //printf("CRNT_LIM_U_ABFR_R: 0x%X, %f\r\n", adc_add_raw_data[3],(double)adc_add_raw_data[3]*VOLTAGE_FACTOR);
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-// Отсчет времени при возникновении аварий на входах.
|
|
|
-// Вызывается раз в секунду.
|
|
|
-void ai_alarm_tim_handler(void)
|
|
|
-{
|
|
|
- // Обычне каналы
|
|
|
- for (int i = 0; i < AI_COMMON_NUMBER; i++)
|
|
|
- {
|
|
|
- if (ai_alarm_f[i].alarm_flag) {
|
|
|
- ai_alarm_f[i].cnt++;
|
|
|
-
|
|
|
- // Принудительно перевести канал в режим измерения напряжения
|
|
|
- ai_set_mode_word((MEAS_CHAN_MODE_t)0, i + 1);
|
|
|
- }
|
|
|
- else {
|
|
|
- ai_alarm_f[i].cnt = 0;
|
|
|
- }
|
|
|
-
|
|
|
- if (ai_alarm_f[i].cnt > CUR_ALARM_PAUSE)
|
|
|
- {
|
|
|
- ai_alarm_f[i].cnt = 0;
|
|
|
- ai_alarm_f[i].alarm_flag = false;
|
|
|
-
|
|
|
- // Режим измерения канала из настроек. Он мог измениться.
|
|
|
- ai_set_mode_word((MEAS_CHAN_MODE_t)(settings.ai[i].mode), i + 1);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // Мониторинг аварии питания внешних датчиков
|
|
|
- if (ai_cur_lim.alarm_flag) {
|
|
|
- ai_cur_lim.cnt++;
|
|
|
-
|
|
|
- // отключить питание внешних датчиков
|
|
|
- ai_ext_sens_power(0);
|
|
|
- }
|
|
|
- else {
|
|
|
- ai_cur_lim.cnt = 0;
|
|
|
- }
|
|
|
-
|
|
|
- if (ai_cur_lim.cnt > CUR_ALARM_PAUSE)
|
|
|
- {
|
|
|
- ai_cur_lim.cnt = 0;
|
|
|
- ai_cur_lim.alarm_flag = false;
|
|
|
-
|
|
|
- // Питание внешних датчиков из настроек. Настройка могла измениться
|
|
|
- ai_ext_sens_power(settings.ext_sens_power);
|
|
|
- }
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-// Подключить канал к АЦП
|
|
|
-// Одновременно могут быть подключены только 2 канала из наборов:
|
|
|
-// 1: AN_INP_1, AN_INP_2, AN_INP_3, AN_INP_4, AN_INP_5, AN_INP_6, V_ISO_CL,
|
|
|
-// V_ISO
|
|
|
-//
|
|
|
-// 2: AN_INP_7, AN_INP_8, AN_INP_9, AN_INP_10, AN_INP_11, AN_INP_12,
|
|
|
-// CRNT_LIM_U_BFR_R, CRNT_LIM_U_ABFR_R
|
|
|
-void ai_connect_channel(uint8_t channel)
|
|
|
-{
|
|
|
- if (channel < MUX_401_CH)
|
|
|
- {
|
|
|
- ai_mux &= 0xF0;
|
|
|
-
|
|
|
- switch (channel)
|
|
|
- {
|
|
|
- case AN_INP_1: ai_mux |= 0x03; break; // U301 Y3
|
|
|
- case AN_INP_2: ai_mux |= 0x00; break; // U301 Y0
|
|
|
- case AN_INP_3: ai_mux |= 0x05; break; // U301 Y5
|
|
|
- case AN_INP_4: ai_mux |= 0x07; break; // U301 Y7
|
|
|
- case AN_INP_5: ai_mux |= 0x06; break; // U301 Y6
|
|
|
- case AN_INP_6: ai_mux |= 0x04; break; // U301 Y4
|
|
|
- case V_ISO_CL: ai_mux |= 0x01; break; // U301 Y1
|
|
|
- case V_ISO : ai_mux |= 0x02; break; // U301 Y2
|
|
|
- default: break;
|
|
|
- }
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- ai_mux &= 0x87;
|
|
|
-
|
|
|
- switch (channel)
|
|
|
- {
|
|
|
- case AN_INP_7: ai_mux |= (0x04 << 4); break; // U401 Y4
|
|
|
- case AN_INP_8: ai_mux |= (0x06 << 4); break; // U401 Y6
|
|
|
- case AN_INP_9: ai_mux |= (0x07 << 4); break; // U401 Y7
|
|
|
- case AN_INP_10:ai_mux |= (0x05 << 4); break; // U401 Y5
|
|
|
- case AN_INP_11:ai_mux |= (0x02 << 4); break; // U401 Y2
|
|
|
- case AN_INP_12:ai_mux |= (0x01 << 4); break; // U401 Y1
|
|
|
- case CRNT_LIM_U_BFR_R: ai_mux |= (0x00 << 4); break; // U401 Y0
|
|
|
- case CRNT_LIM_U_ABFR_R: ai_mux |= (0x03 << 4); break; // U401 Y3
|
|
|
- default: break;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- sh_ai_connect(ai_mux);
|
|
|
-
|
|
|
- //printf("Analog input connect register: ");
|
|
|
- //print_binary_byte(ai_mux);
|
|
|
-}
|
|
|
-
|
|
|
-//
|
|
|
-void ai_set(void)
|
|
|
-{
|
|
|
- for (int i = 0; i < AI_COMMON_NUMBER; i++)
|
|
|
- {
|
|
|
- if (((settings.ai_state_bits >> i) & 1) != settings.ai[i].state)
|
|
|
- {
|
|
|
- settings.ai[i].state = ((settings.ai_state_bits >> i) & 1);
|
|
|
- if (settings.ai[i].state == 0) {
|
|
|
- leds[ai_input_led[i]].state = LED_OFF;
|
|
|
- adc_com_raw_data[i] = 0;
|
|
|
- adc_com_data[i] = 0;
|
|
|
- }
|
|
|
- else {
|
|
|
- leds[ai_input_led[i]].state = LED_ON;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-// Утсновить режим измерения канала (ток или напряжение)
|
|
|
-void ai_set_mode(MEAS_CHAN_MODE_t mode, uint8_t channel)
|
|
|
-{
|
|
|
- if (mode == MEAS_CURRENT)
|
|
|
- {
|
|
|
- if (channel < 7)
|
|
|
- ai_mode |= (1 << (channel - 1));
|
|
|
- else
|
|
|
- ai_mode |= (1 << (channel + 1));
|
|
|
- }
|
|
|
- else
|
|
|
- if (channel < 7)
|
|
|
- ai_mode &= ~(1 << (channel - 1));
|
|
|
- else
|
|
|
- ai_mode &= ~(1 << (channel + 1));
|
|
|
-
|
|
|
- sh_ai_mode(ai_mode);
|
|
|
-
|
|
|
- //printf("Analog input mode: ");
|
|
|
- print_binary_half_word(ai_mode);
|
|
|
-}
|
|
|
-
|
|
|
-// Формируем слово режима работы каналов (ai_mode)
|
|
|
-void ai_set_mode_word(MEAS_CHAN_MODE_t mode, uint8_t channel)
|
|
|
-{
|
|
|
- if (mode == MEAS_CURRENT)
|
|
|
- {
|
|
|
- if (channel < 7)
|
|
|
- ai_mode |= (1 << (channel - 1));
|
|
|
- else
|
|
|
- ai_mode |= (1 << (channel + 1));
|
|
|
- }
|
|
|
- else
|
|
|
- if (channel < 7)
|
|
|
- ai_mode &= ~(1 << (channel - 1));
|
|
|
- else
|
|
|
- ai_mode &= ~(1 << (channel + 1));
|
|
|
-}
|
|
|
-
|
|
|
-// Сигнал питания внешних датчиков
|
|
|
-void ai_ext_sens_power(uint16_t state)
|
|
|
-{
|
|
|
- if (state)
|
|
|
- ai_mux |= 0x80;
|
|
|
- else
|
|
|
- ai_mux &= ~(0x80);
|
|
|
-}
|
|
|
-
|
|
|
-// Управления LED
|
|
|
-void ai_leds_processing(void)
|
|
|
-{
|
|
|
- // Управление индикацией аварий (12 красных LED) (слово ai_alarm)
|
|
|
- for (uint8_t i = 0; i < AI_COMMON_NUMBER; i++) {
|
|
|
- if (ai_alarm & (1 << i)) {
|
|
|
- leds[ai_alarm_led[i]].state = LED_ON;
|
|
|
- }
|
|
|
- else {
|
|
|
- leds[ai_alarm_led[i]].state = LED_OFF;
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-//
|
|
|
-void adc_alarm_detect(void)
|
|
|
-{
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-// -------------------------------------------------------------------------- //
|
|
|
-// Тесты
|
|
|
-
|
|
|
-//
|
|
|
-void ai_connect_test(void)
|
|
|
-{
|
|
|
- ai_connect_channel(AN_INP_1);
|
|
|
- ai_connect_channel(AN_INP_2);
|
|
|
- ai_connect_channel(AN_INP_3);
|
|
|
- ai_connect_channel(AN_INP_4);
|
|
|
- ai_connect_channel(AN_INP_5);
|
|
|
- ai_connect_channel(AN_INP_6);
|
|
|
- ai_connect_channel(V_ISO_CL);
|
|
|
- ai_connect_channel(V_ISO);
|
|
|
-
|
|
|
- ai_connect_channel(AN_INP_7);
|
|
|
- ai_connect_channel(AN_INP_8);
|
|
|
- ai_connect_channel(AN_INP_9);
|
|
|
- ai_connect_channel(AN_INP_10);
|
|
|
- ai_connect_channel(AN_INP_11);
|
|
|
- ai_connect_channel(AN_INP_12);
|
|
|
- ai_connect_channel(CRNT_LIM_U_BFR_R);
|
|
|
- ai_connect_channel(CRNT_LIM_U_ABFR_R);
|
|
|
-}
|
|
|
-
|
|
|
-//
|
|
|
-void ai_mode_test(void)
|
|
|
-{
|
|
|
- for (uint8_t i = 1; i < 13; i++)
|
|
|
- {
|
|
|
- ai_set_mode(MEAS_VOLTAGE, i);
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
+#include "at32f403a_407.h"
|
|
|
+#include "analog_input.h"
|
|
|
+#include "shift_reg.h"
|
|
|
+#include "utility.h"
|
|
|
+#include "FreeRTOS.h"
|
|
|
+#include "task.h"
|
|
|
+#include "settings_api.h"
|
|
|
+#include "adc_transport.h"
|
|
|
+#include "ms5192t.h"
|
|
|
+#include "monitoring.h"
|
|
|
+#include "mux.h"
|
|
|
+#include "filter.h"
|
|
|
+#include <stdio.h>
|
|
|
+
|
|
|
+#undef DBG
|
|
|
+#define DBG if(0)
|
|
|
+
|
|
|
+#if defined (MAI_12)
|
|
|
+
|
|
|
+#define VOLTAGE_FACTOR 0.182382
|
|
|
+#define CURRENT_FACTOR 0.00091191
|
|
|
+#define CRNT_LIM_V_FACTOR 0.0476
|
|
|
+#define VOLT_ALARM_LIMIT 10000.0
|
|
|
+#define CUR_ALARM_PAUSE 300 // время в секундах на остывание токового шунта
|
|
|
+#define CUR_LIM_LOW_LIMIT 23.0
|
|
|
+#define CUR_LIM_LOW_LIMIT 25.0
|
|
|
+#define CUR_LIM_DELTA_U 0.6
|
|
|
+
|
|
|
+
|
|
|
+uint8_t ai_mux; // выход сдвигового регистра U1010 (управляет MUX 301, 401)
|
|
|
+ // мультиплексоры отвечат за коммутацию аналоговых входов и АЦП
|
|
|
+
|
|
|
+uint16_t ai_mode; // режим измерения аналоговых каналов (ток или напряжение)
|
|
|
+ // 0000 0000 0000 0000
|
|
|
+ // младшие 6 (с 1..6) бит - каналы с 1 по 6 соответственно
|
|
|
+ // биты 9..14 - каналы с 7 по 12 соответственно
|
|
|
+
|
|
|
+uint16_t ai_alarm; // слово аварий входов
|
|
|
+
|
|
|
+uint16_t ai_gain[AI_COMMON_NUMBER]; // массив коэффициентов усиленя (modbus)
|
|
|
+
|
|
|
+uint16_t adc_com_raw_data[AI_COMMON_NUMBER]; // сырые данные
|
|
|
+float adc_com_data[AI_COMMON_NUMBER]; // пересчитанные, фильтрованные данные
|
|
|
+
|
|
|
+uint16_t adc_com_fil_data[AI_COMMON_NUMBER]; // Фильтрованные данные (только для отладки)
|
|
|
+
|
|
|
+uint16_t adc_add_raw_data[AI_ADD_NUMBER];
|
|
|
+
|
|
|
+
|
|
|
+led_t ai_alarm_led[12] = {IO_1_R, IO_2_R, IO_3_R, IO_4_R,
|
|
|
+ IO_5_R, IO_6_R, IO_7_R, IO_8_R,
|
|
|
+ IO_9_R, IO_10_R, IO_11_R, IO_12_R};
|
|
|
+
|
|
|
+led_t ai_input_led[12] = {IO_1_G, IO_2_G, IO_3_G, IO_4_G,
|
|
|
+ IO_5_G, IO_6_G, IO_7_G, IO_8_G,
|
|
|
+ IO_9_G, IO_10_G, IO_11_G, IO_12_G};
|
|
|
+
|
|
|
+uint16_t ai_state_bit; // состояние аналоговых входов (вкл/выкл) битовое поле
|
|
|
+
|
|
|
+ai_alarm_t ai_alarm_f[AI_COMMON_NUMBER]; // Вспомогательная структура для
|
|
|
+ //работы с авариями
|
|
|
+
|
|
|
+ai_alarm_t ai_cur_lim; // Вспомогательная структура для работы с аварией
|
|
|
+ // модуля питания внешних датчиков
|
|
|
+
|
|
|
+
|
|
|
+// Авария датчика, значение ниже диапазона (не обрыв)
|
|
|
+// Авария, не обрыв линии (возможно неисправен датчик)
|
|
|
+// Авария датчика, значение выше диапазона (не обрыв)
|
|
|
+uint16_t ai_voltage_alarm; // аварии в режиме измерения напряжения
|
|
|
+
|
|
|
+// аварии в режиме измерения тока
|
|
|
+uint16_t ai_current_low; // значение ниже диапазона
|
|
|
+uint16_t ai_current_high; // значение выше диапазона
|
|
|
+uint16_t ai_current_fail; // авария (возможно неисправен датчик)
|
|
|
+uint16_t ai_load_sens_alarm;// авария превышения нагрузки на блок питания внешних датчиков
|
|
|
+
|
|
|
+//
|
|
|
+void ai_init(void)
|
|
|
+{
|
|
|
+ // Фильтры (скользящее среднее) для 12-и основных каналов
|
|
|
+ average_filter_init();
|
|
|
+
|
|
|
+ // Зеленые LED сигнализируют (вкл/выкл) входов.
|
|
|
+ ai_led_update();
|
|
|
+
|
|
|
+ // Сдвиговые регистры
|
|
|
+ sh_init();
|
|
|
+
|
|
|
+ // Режим измерения
|
|
|
+ ai_set_meas_mode();
|
|
|
+
|
|
|
+ // Питание внешних датчиков
|
|
|
+ ai_ext_sens_power(settings.ext_sens_power);
|
|
|
+
|
|
|
+ // Внешинй ADC
|
|
|
+ ai_adc_init();
|
|
|
+
|
|
|
+ // Modbus параметры
|
|
|
+ ai_init_modbus_params();
|
|
|
+}
|
|
|
+
|
|
|
+//
|
|
|
+void ai_init_modbus_params(void)
|
|
|
+{
|
|
|
+ for (uint8_t i = 0; i < AI_COMMON_NUMBER; i++) {
|
|
|
+ ai_gain[i] = settings.ai[i].gain_factor;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// Управление LED для 12-и основных входов
|
|
|
+void ai_led_update(void)
|
|
|
+{
|
|
|
+ for (int i = 0; i < AI_COMMON_NUMBER; i++)
|
|
|
+ {
|
|
|
+ if (settings.ai[i].state)
|
|
|
+ leds[ai_input_led[i]].state = LED_ON;
|
|
|
+ else
|
|
|
+ leds[ai_input_led[i]].state = LED_OFF;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// Установить режим измерения каналов с 1 по 12.
|
|
|
+void ai_set_meas_mode(void)
|
|
|
+{
|
|
|
+ for (int i = 0; i < AI_COMMON_NUMBER; i++)
|
|
|
+ {
|
|
|
+ if (settings.ai[i].mode)
|
|
|
+ ai_set_mode_word((MEAS_CHAN_MODE_t)1, i + 1);
|
|
|
+ else
|
|
|
+ ai_set_mode_word((MEAS_CHAN_MODE_t)0, i + 1);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// Настройка внешнего ADC
|
|
|
+bool ai_adc_init(void)
|
|
|
+{
|
|
|
+ uint8_t ret;
|
|
|
+ unsigned long value;
|
|
|
+
|
|
|
+ adc_gpio_init();
|
|
|
+
|
|
|
+ for (uint32_t i = 0; i < 100; i++) {
|
|
|
+ MS5192T_Reset();
|
|
|
+ ret = MS5192T_Init();
|
|
|
+ DBG printf("ADC init status: %s\r\n", ret == 1 ? "OK" : "FAILED");
|
|
|
+ if (ret == 1)
|
|
|
+ break;
|
|
|
+ vTaskDelay(10);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!ret) {
|
|
|
+ mon_set_err(MON_ADC_EXT, 1);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Запрос регистра конфигурации для (0x710 - значение по умолчанию)
|
|
|
+ value = MS5192T_GetRegisterValue(MS5192T_REG_CONF, 2, 1);
|
|
|
+ DBG printf("ADC cfg reg: 0x%X: ", value);
|
|
|
+ DBG print_binary_half_word((uint16_t)value);
|
|
|
+
|
|
|
+ // Коэф-т усиления: 1
|
|
|
+ DBG printf("ADC. Set gain rate 1\r\n");
|
|
|
+ MS5192T_SetGain(MS5192T_GAIN_1);
|
|
|
+ value = MS5192T_GetRegisterValue(MS5192T_REG_CONF, 2, 1);
|
|
|
+ DBG printf("ADC cfg reg: 0x%X: ", value);
|
|
|
+ DBG print_binary_half_word((uint16_t)value);
|
|
|
+
|
|
|
+ // Униполярный режим
|
|
|
+ DBG printf("Set unipolar input mode...\r\n");
|
|
|
+ MS5192T_SetPolar(MS5192T_CONF_UNIPOLAR);
|
|
|
+ value = MS5192T_GetRegisterValue(MS5192T_REG_CONF, 2, 1);
|
|
|
+ DBG printf("ADC cfg reg: 0x%X: ", value);
|
|
|
+ DBG print_binary_half_word((uint16_t)value);
|
|
|
+
|
|
|
+ // Регистр статуса
|
|
|
+ value = MS5192T_GetRegisterValue(MS5192T_REG_STAT, 1, 1);
|
|
|
+ DBG printf("ADC status reg: 0x%X: ", value);
|
|
|
+ DBG print_binary_byte((uint8_t)value);
|
|
|
+
|
|
|
+ // Установка внутреннего опорного напряжения
|
|
|
+ MS5192T_SetIntReference(MS5192T_REFSEL_INT); // select internal 1.17V reference
|
|
|
+ value = MS5192T_GetRegisterValue(MS5192T_REG_CONF, 2, 1);
|
|
|
+ DBG printf("ADC cfg reg: 0x%X: ", value);
|
|
|
+ DBG print_binary_half_word((uint16_t)value);
|
|
|
+
|
|
|
+ // Регистр режима (MODE register)
|
|
|
+ value = MS5192T_GetRegisterValue(MS5192T_REG_MODE, 2, 1);
|
|
|
+ DBG printf("ADC mode reg: 0x%X: ", value);
|
|
|
+ DBG print_binary_half_word((uint16_t)value);
|
|
|
+
|
|
|
+ // Установить update rate
|
|
|
+ DBG printf("Set update rate.\r\n");
|
|
|
+ MS5192T_SetUpdateRate(MS5192T_UP_RATE_500);
|
|
|
+ value = MS5192T_GetRegisterValue(MS5192T_REG_MODE, 2, 1);
|
|
|
+ DBG printf("ADC mode reg: 0x%X: ", value);
|
|
|
+ DBG print_binary_half_word((uint16_t)value);
|
|
|
+
|
|
|
+ // Калибровка
|
|
|
+
|
|
|
+ // 1 - ый канал
|
|
|
+ MS5192T_Calibrate(MS5192T_MODE_CAL_INT_ZERO, MS5192T_CH_AIN1P_AIN1M);
|
|
|
+ MS5192T_Calibrate(MS5192T_MODE_CAL_INT_FULL, MS5192T_CH_AIN1P_AIN1M);
|
|
|
+
|
|
|
+ // 2 - ой канал
|
|
|
+ MS5192T_Calibrate(MS5192T_MODE_CAL_INT_ZERO, MS5192T_CH_AIN2P_AIN2M);
|
|
|
+ MS5192T_Calibrate(MS5192T_MODE_CAL_INT_FULL, MS5192T_CH_AIN2P_AIN2M);
|
|
|
+
|
|
|
+ return true;
|
|
|
+}
|
|
|
+
|
|
|
+// Оцифровка всех 16-и каналов (входы + дополнительные каналы)
|
|
|
+void ai_processing(void)
|
|
|
+{
|
|
|
+ float filter_factor;
|
|
|
+
|
|
|
+ // 12 основных каналов
|
|
|
+ for (uint8_t i = 0; i < AI_COMMON_NUMBER/2; i++)
|
|
|
+ {
|
|
|
+ adc_meas_two_channels(&settings.ai[i], &settings.ai[i + 6],
|
|
|
+ &adc_com_raw_data[i], &adc_com_raw_data[i + 6]);
|
|
|
+
|
|
|
+ // ---------------------------------------------------------------------
|
|
|
+ // Фильтрованные данные
|
|
|
+
|
|
|
+ filter_factor = settings.ai[i].mode == 0 ? VOLTAGE_FACTOR : CURRENT_FACTOR;
|
|
|
+
|
|
|
+ adc_com_data[i] = (float)adc_com_raw_data[i]*filter_factor*
|
|
|
+ settings.ai[i].k_factor + settings.ai[i].b_factor;
|
|
|
+
|
|
|
+ filter_factor = settings.ai[i + 6].mode == 0 ? VOLTAGE_FACTOR : CURRENT_FACTOR;
|
|
|
+
|
|
|
+ adc_com_data[i + 6] = (float)adc_com_raw_data[i + 6]*filter_factor*
|
|
|
+ settings.ai[i + 6].k_factor + settings.ai[i + 6].b_factor;
|
|
|
+
|
|
|
+ // ---------------------------------------------------------------------
|
|
|
+ // Фильтрация. Скользящее среднее. Только для отладки.
|
|
|
+ adc_com_fil_data[i] = average_int(&average_filter[i], adc_com_raw_data[i]);
|
|
|
+ adc_com_fil_data[i + 6] = average_int(&average_filter[i + 6], adc_com_raw_data[i + 6]);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 4 дополнительных канала
|
|
|
+ for (uint8_t i = 0; i < AI_ADD_NUMBER/2; i++)
|
|
|
+ {
|
|
|
+ adc_meas_two_channels(&settings.ai_add[i], &settings.ai_add[i + 2],
|
|
|
+ &adc_add_raw_data[i], &adc_add_raw_data[i + 2]);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+#if 1
|
|
|
+ printf("end\r\n");
|
|
|
+ adc_print_data();
|
|
|
+ //adc_print_data_extend();
|
|
|
+ printf("end\r\n");
|
|
|
+#endif
|
|
|
+}
|
|
|
+
|
|
|
+//
|
|
|
+void adc_meas_two_channels(ai_t *one, ai_t *two, uint16_t *out_one, uint16_t *out_two)
|
|
|
+{
|
|
|
+ uint8_t gain;
|
|
|
+
|
|
|
+ // 1 - ый канал
|
|
|
+ if (one->state == 0) {
|
|
|
+ //DBG printf("[one] channel name: %u off\r\n", one->name);
|
|
|
+
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ //DBG printf("[one] channel name: %u on\r\n", one->name);
|
|
|
+
|
|
|
+ gain = adc_get_gain(one->gain_factor);
|
|
|
+ MS5192T_SetGain(gain);
|
|
|
+ ai_connect_channel(one->name);
|
|
|
+ vTaskDelay(1);
|
|
|
+ MS5192T_SetChannel(MS5192T_CH_AIN1P_AIN1M);
|
|
|
+ *out_one = MS5192T_SingleConversion();
|
|
|
+ }
|
|
|
+
|
|
|
+ // 2 - ой канал
|
|
|
+ if (two->state == 0) {
|
|
|
+ //DBG printf("[two] channel name: %u off\r\n", two->name);
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ //DBG printf("[two] channel name: %u on\r\n", two->name);
|
|
|
+
|
|
|
+ gain = adc_get_gain(two->gain_factor);
|
|
|
+ MS5192T_SetGain(gain);
|
|
|
+ ai_connect_channel(two->name);
|
|
|
+ vTaskDelay(1);
|
|
|
+ MS5192T_SetChannel(MS5192T_CH_AIN2P_AIN2M);
|
|
|
+ *out_two = MS5192T_SingleConversion();
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+//
|
|
|
+uint8_t adc_get_gain(uint8_t tmp)
|
|
|
+{
|
|
|
+ uint8_t ret;
|
|
|
+
|
|
|
+ switch (tmp)
|
|
|
+ {
|
|
|
+ case 1 : ret = MS5192T_GAIN_1; break;
|
|
|
+ case 2 : ret = MS5192T_GAIN_2; break;
|
|
|
+ case 4 : ret = MS5192T_GAIN_4; break;
|
|
|
+ case 8 : ret = MS5192T_GAIN_8; break;
|
|
|
+ case 16 : ret = MS5192T_GAIN_16; break;
|
|
|
+ case 32 : ret = MS5192T_GAIN_32; break;
|
|
|
+ case 64 : ret = MS5192T_GAIN_64; break;
|
|
|
+ case 128: ret = MS5192T_GAIN_128; break;
|
|
|
+ default : ret = MS5192T_GAIN_1; break;
|
|
|
+ }
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+//
|
|
|
+void adc_print_data(void)
|
|
|
+{
|
|
|
+ printf("\033[2J");
|
|
|
+ printf("\033[H");
|
|
|
+
|
|
|
+#if 1
|
|
|
+ printf("AN_INP_1: 0x%X, %.3f\r\n", adc_com_raw_data[0], adc_com_data[0]);
|
|
|
+ printf("AN_INP_2: 0x%X, %.3f\r\n", adc_com_raw_data[1], adc_com_data[1]);
|
|
|
+ printf("AN_INP_3: 0x%X, %.3f\r\n", adc_com_raw_data[2], adc_com_data[2]);
|
|
|
+ printf("AN_INP_4: 0x%X, %.3f\r\n", adc_com_raw_data[3], adc_com_data[3]);
|
|
|
+ printf("AN_INP_5: 0x%X, %.3f\r\n", adc_com_raw_data[4], adc_com_data[4]);
|
|
|
+ printf("AN_INP_6: 0x%X, %.3f\r\n", adc_com_raw_data[5], adc_com_data[5]);
|
|
|
+ printf("AN_INP_7: 0x%X, %.3f\r\n", adc_com_raw_data[6], adc_com_data[6]);
|
|
|
+ printf("AN_INP_8: 0x%X, %.3f\r\n", adc_com_raw_data[7], adc_com_data[7]);
|
|
|
+ printf("AN_INP_9: 0x%X, %.3f\r\n", adc_com_raw_data[8], adc_com_data[8]);
|
|
|
+ printf("AN_INP_10: 0x%X, %.3f\r\n", adc_com_raw_data[9], adc_com_data[9]);
|
|
|
+ printf("AN_INP_11: 0x%X, %.3f\r\n", adc_com_raw_data[10],adc_com_data[10]);
|
|
|
+ printf("AN_INP_12: 0x%X, %.3f\r\n", adc_com_raw_data[11],adc_com_data[11]);
|
|
|
+
|
|
|
+ printf("V_ISO_CL: 0x%X, %f\r\n", adc_add_raw_data[0], (double)adc_add_raw_data[0]*VOLTAGE_FACTOR);
|
|
|
+ printf("V_ISO : 0x%X, %f\r\n", adc_add_raw_data[1], (double)adc_add_raw_data[1]*VOLTAGE_FACTOR);
|
|
|
+ printf("CRNT_LIM_U_BFR_R : 0x%X, %f\r\n", adc_add_raw_data[2],(double)adc_add_raw_data[2]*VOLTAGE_FACTOR);
|
|
|
+ printf("CRNT_LIM_U_ABFR_R: 0x%X, %f\r\n", adc_add_raw_data[3],(double)adc_add_raw_data[3]*VOLTAGE_FACTOR);
|
|
|
+#endif
|
|
|
+}
|
|
|
+
|
|
|
+//
|
|
|
+void adc_print_data_extend(void)
|
|
|
+{
|
|
|
+ printf("\033[2J");
|
|
|
+ printf("\033[H");
|
|
|
+
|
|
|
+ printf("AN_INP_1: 0x%X 0x%X %f %f\r\n", adc_com_raw_data[0], adc_com_fil_data[0], (double)adc_com_raw_data[0]*0.00001785305/0.0961538, (double)adc_com_fil_data[0]*0.00001785305/0.0961538);
|
|
|
+ printf("AN_INP_2: 0x%X 0x%X %f %f\r\n", adc_com_raw_data[1], adc_com_fil_data[1], (double)adc_com_raw_data[1]*0.00001785305/0.0961538, (double)adc_com_fil_data[1]*0.00001785305/0.0961538);
|
|
|
+ printf("AN_INP_3: 0x%X 0x%X %f %f\r\n", adc_com_raw_data[2], adc_com_fil_data[2], (double)adc_com_raw_data[2]*0.00001785305/0.0961538, (double)adc_com_fil_data[2]*0.00001785305/0.0961538);
|
|
|
+ printf("AN_INP_4: 0x%X 0x%X %f %f\r\n", adc_com_raw_data[3], adc_com_fil_data[3], (double)adc_com_raw_data[3]*0.00001785305/0.0961538, (double)adc_com_fil_data[3]*0.00001785305/0.0961538);
|
|
|
+ printf("AN_INP_5: 0x%X 0x%X %f %f\r\n", adc_com_raw_data[4], adc_com_fil_data[4], (double)adc_com_raw_data[4]*0.00001785305/0.0961538, (double)adc_com_fil_data[4]*0.00001785305/0.0961538);
|
|
|
+ printf("AN_INP_6: 0x%X 0x%X %f %f\r\n", adc_com_raw_data[5], adc_com_fil_data[5], (double)adc_com_raw_data[5]*0.00001785305/0.0961538, (double)adc_com_fil_data[5]*0.00001785305/0.0961538);
|
|
|
+ printf("AN_INP_7: 0x%X 0x%X %f %f\r\n", adc_com_raw_data[6], adc_com_fil_data[6], (double)adc_com_raw_data[6]*0.00001785305/0.0961538, (double)adc_com_fil_data[6]*0.00001785305/0.0961538);
|
|
|
+ printf("AN_INP_8: 0x%X 0x%X %f %f\r\n", adc_com_raw_data[7], adc_com_fil_data[7], (double)adc_com_raw_data[7]*0.00001785305/0.0961538, (double)adc_com_fil_data[7]*0.00001785305/0.0961538);
|
|
|
+ printf("AN_INP_9: 0x%X 0x%X %f %f\r\n", adc_com_raw_data[8], adc_com_fil_data[8], (double)adc_com_raw_data[8]*0.00001785305/0.0961538, (double)adc_com_fil_data[8]*0.00001785305/0.0961538);
|
|
|
+ printf("AN_INP_10: 0x%X 0x%X %f %f\r\n", adc_com_raw_data[9], adc_com_fil_data[9],(double)adc_com_raw_data[9]*0.00001785305/0.0961538, (double)adc_com_fil_data[9]*0.00001785305/0.0961538);
|
|
|
+ printf("AN_INP_11: 0x%X 0x%X %f %f\r\n", adc_com_raw_data[10], adc_com_fil_data[10], (double)adc_com_raw_data[10]*0.00001785305/0.0961538, (double)adc_com_fil_data[10]*0.00001785305/0.0961538);
|
|
|
+ printf("AN_INP_12: 0x%X 0x%X %f %f\r\n", adc_com_raw_data[11], adc_com_fil_data[11], (double)adc_com_raw_data[11]*0.00001785305/0.0961538, (double)adc_com_fil_data[11]*0.00001785305/0.0961538);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+//
|
|
|
+void adc_task(void *params)
|
|
|
+{
|
|
|
+ for (;;)
|
|
|
+ {
|
|
|
+ ai_alarm = sh_ai_mode(ai_mode);
|
|
|
+
|
|
|
+ ai_processing();
|
|
|
+
|
|
|
+ ai_leds_processing();
|
|
|
+
|
|
|
+ vTaskDelay(10);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+// -------------------------------------------------------------------------- //
|
|
|
+// Определение аварий
|
|
|
+
|
|
|
+//
|
|
|
+void adc_alarm_task(void *params)
|
|
|
+{
|
|
|
+ for (;;)
|
|
|
+ {
|
|
|
+#if 1
|
|
|
+ //printf("Analog input mode: ");
|
|
|
+ //print_binary_half_word(ai_mode);
|
|
|
+
|
|
|
+ ai_voltage_alarm_detect();
|
|
|
+#endif
|
|
|
+ vTaskDelay(1000);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+// Определение аварий в режиме измерения напряжения
|
|
|
+// ai_voltage_alarm
|
|
|
+void ai_voltage_alarm_detect(void)
|
|
|
+{
|
|
|
+ for (int i = 0; i < AI_COMMON_NUMBER; i++)
|
|
|
+ {
|
|
|
+ // Вход включен и находится в режиме измерения напряжения
|
|
|
+ if (settings.ai[i].state && (settings.ai[i].mode == 0))
|
|
|
+ {
|
|
|
+ if (adc_com_data[i] > VOLT_ALARM_LIMIT)
|
|
|
+ ai_voltage_alarm |= 1 << i;
|
|
|
+ else
|
|
|
+ ai_voltage_alarm &= ~(1 << i);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+// Опеределение аварий в режиме измерения тока
|
|
|
+// ai_current_low - авария датчика, значение ниже диапазона (не обрыв)
|
|
|
+// ai_current_high - авария, не обрыв линии (возможно неисправен датчик)
|
|
|
+// ai_current_fail - авария датчика, значение выше диапазона (не обрыв)
|
|
|
+void ai_current_alarm_detect(void)
|
|
|
+{
|
|
|
+ for (int i = 0; i < AI_COMMON_NUMBER; i++)
|
|
|
+ {
|
|
|
+ // Вход включен и находится в режиме измерения тока
|
|
|
+ if (settings.ai[i].state && (settings.ai[i].mode == 1))
|
|
|
+ {
|
|
|
+ if (adc_com_data[i] < 4.0)
|
|
|
+ {
|
|
|
+ // Вход в режиме измерения 4-20 mA
|
|
|
+ if (settings.ai[i].current_mode == 1)
|
|
|
+ {
|
|
|
+ if (adc_com_data[i] > 1.0)
|
|
|
+ {
|
|
|
+ // Авария датчика, значение ниже диапазона (не обрыв)
|
|
|
+ ai_current_low |= 1 << i;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ // Авария, не обрыв линии (возможно неисправен датчик)
|
|
|
+ ai_current_fail |= 1 << i;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ // Снять флаги с аварий
|
|
|
+ // Авария датчика, значение ниже диапазона (не обрыв)
|
|
|
+ // Авария, не обрыв линии (возможно неисправен датчик)
|
|
|
+ ai_current_low &= ~(1 << i);
|
|
|
+ ai_current_fail &= ~(1 << i);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // Измеряемый ток больше 4 mA
|
|
|
+ else
|
|
|
+ {
|
|
|
+ if (adc_com_data[i] > 20.0)
|
|
|
+ {
|
|
|
+ // Снять флаги аварий
|
|
|
+ // Авария, не обрыв линии (возможно неисправен датчик)
|
|
|
+ ai_current_high &= ~(1 << i);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ // Авария датчика, значение выше диапазона (не обрыв)
|
|
|
+ ai_current_high |= 1 << i;
|
|
|
+
|
|
|
+ if (adc_com_data[i] > 22.0)
|
|
|
+ {
|
|
|
+ // Перевести вход в режим измерения напряжения
|
|
|
+ ai_alarm_f[i].alarm_flag = true;
|
|
|
+ // Ждать 5 минут (шунт должен остыть)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+// Контроль питания внешних датчиков
|
|
|
+// TODO добавить событие в журнал
|
|
|
+void ai_ext_sens_current_control(void)
|
|
|
+{
|
|
|
+ float crnt_lim_u_bfr = (float)adc_add_raw_data[2]*CRNT_LIM_V_FACTOR;
|
|
|
+ float crnt_lim_u_abfr = (float)adc_add_raw_data[3]*CRNT_LIM_V_FACTOR;
|
|
|
+
|
|
|
+ if ((CUR_LIM_LOW_LIMIT < 23.0) || (CUR_LIM_LOW_LIMIT > 25.0))
|
|
|
+ return;
|
|
|
+
|
|
|
+ if (settings.ext_sens_power == 0)
|
|
|
+ return;
|
|
|
+
|
|
|
+ if ((crnt_lim_u_bfr - crnt_lim_u_abfr) < CUR_LIM_DELTA_U)
|
|
|
+ {
|
|
|
+ // Снять флаг аварии
|
|
|
+ ai_load_sens_alarm = 0;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ ai_load_sens_alarm = 1;
|
|
|
+
|
|
|
+ ai_cur_lim.alarm_flag = true;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ //adc_add_raw_data[2],(double)adc_add_raw_data[2]*VOLTAGE_FACTOR);
|
|
|
+ //VOLTAGE_FACTOR
|
|
|
+
|
|
|
+ //printf("CRNT_LIM_U_BFR_R : 0x%X, %f\r\n", adc_add_raw_data[2],(double)adc_add_raw_data[2]*VOLTAGE_FACTOR);
|
|
|
+ //printf("CRNT_LIM_U_ABFR_R: 0x%X, %f\r\n", adc_add_raw_data[3],(double)adc_add_raw_data[3]*VOLTAGE_FACTOR);
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+// Отсчет времени при возникновении аварий на входах.
|
|
|
+// Вызывается раз в секунду.
|
|
|
+void ai_alarm_tim_handler(void)
|
|
|
+{
|
|
|
+ // Обычне каналы
|
|
|
+ for (int i = 0; i < AI_COMMON_NUMBER; i++)
|
|
|
+ {
|
|
|
+ if (ai_alarm_f[i].alarm_flag) {
|
|
|
+ ai_alarm_f[i].cnt++;
|
|
|
+
|
|
|
+ // Принудительно перевести канал в режим измерения напряжения
|
|
|
+ ai_set_mode_word((MEAS_CHAN_MODE_t)0, i + 1);
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ ai_alarm_f[i].cnt = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (ai_alarm_f[i].cnt > CUR_ALARM_PAUSE)
|
|
|
+ {
|
|
|
+ ai_alarm_f[i].cnt = 0;
|
|
|
+ ai_alarm_f[i].alarm_flag = false;
|
|
|
+
|
|
|
+ // Режим измерения канала из настроек. Он мог измениться.
|
|
|
+ ai_set_mode_word((MEAS_CHAN_MODE_t)(settings.ai[i].mode), i + 1);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // Мониторинг аварии питания внешних датчиков
|
|
|
+ if (ai_cur_lim.alarm_flag) {
|
|
|
+ ai_cur_lim.cnt++;
|
|
|
+
|
|
|
+ // отключить питание внешних датчиков
|
|
|
+ ai_ext_sens_power(0);
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ ai_cur_lim.cnt = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (ai_cur_lim.cnt > CUR_ALARM_PAUSE)
|
|
|
+ {
|
|
|
+ ai_cur_lim.cnt = 0;
|
|
|
+ ai_cur_lim.alarm_flag = false;
|
|
|
+
|
|
|
+ // Питание внешних датчиков из настроек. Настройка могла измениться
|
|
|
+ ai_ext_sens_power(settings.ext_sens_power);
|
|
|
+ }
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+// Подключить канал к АЦП
|
|
|
+// Одновременно могут быть подключены только 2 канала из наборов:
|
|
|
+// 1: AN_INP_1, AN_INP_2, AN_INP_3, AN_INP_4, AN_INP_5, AN_INP_6, V_ISO_CL,
|
|
|
+// V_ISO
|
|
|
+//
|
|
|
+// 2: AN_INP_7, AN_INP_8, AN_INP_9, AN_INP_10, AN_INP_11, AN_INP_12,
|
|
|
+// CRNT_LIM_U_BFR_R, CRNT_LIM_U_ABFR_R
|
|
|
+void ai_connect_channel(uint8_t channel)
|
|
|
+{
|
|
|
+ if (channel < MUX_401_CH)
|
|
|
+ {
|
|
|
+ ai_mux &= 0xF0;
|
|
|
+
|
|
|
+ switch (channel)
|
|
|
+ {
|
|
|
+ case AN_INP_1: ai_mux |= 0x03; break; // U301 Y3
|
|
|
+ case AN_INP_2: ai_mux |= 0x00; break; // U301 Y0
|
|
|
+ case AN_INP_3: ai_mux |= 0x05; break; // U301 Y5
|
|
|
+ case AN_INP_4: ai_mux |= 0x07; break; // U301 Y7
|
|
|
+ case AN_INP_5: ai_mux |= 0x06; break; // U301 Y6
|
|
|
+ case AN_INP_6: ai_mux |= 0x04; break; // U301 Y4
|
|
|
+ case V_ISO_CL: ai_mux |= 0x01; break; // U301 Y1
|
|
|
+ case V_ISO : ai_mux |= 0x02; break; // U301 Y2
|
|
|
+ default: break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ ai_mux &= 0x87;
|
|
|
+
|
|
|
+ switch (channel)
|
|
|
+ {
|
|
|
+ case AN_INP_7: ai_mux |= (0x04 << 4); break; // U401 Y4
|
|
|
+ case AN_INP_8: ai_mux |= (0x06 << 4); break; // U401 Y6
|
|
|
+ case AN_INP_9: ai_mux |= (0x07 << 4); break; // U401 Y7
|
|
|
+ case AN_INP_10:ai_mux |= (0x05 << 4); break; // U401 Y5
|
|
|
+ case AN_INP_11:ai_mux |= (0x02 << 4); break; // U401 Y2
|
|
|
+ case AN_INP_12:ai_mux |= (0x01 << 4); break; // U401 Y1
|
|
|
+ case CRNT_LIM_U_BFR_R: ai_mux |= (0x00 << 4); break; // U401 Y0
|
|
|
+ case CRNT_LIM_U_ABFR_R: ai_mux |= (0x03 << 4); break; // U401 Y3
|
|
|
+ default: break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ sh_ai_connect(ai_mux);
|
|
|
+
|
|
|
+ //printf("Analog input connect register: ");
|
|
|
+ //print_binary_byte(ai_mux);
|
|
|
+}
|
|
|
+
|
|
|
+//
|
|
|
+void ai_set(void)
|
|
|
+{
|
|
|
+ for (int i = 0; i < AI_COMMON_NUMBER; i++)
|
|
|
+ {
|
|
|
+ if (((settings.ai_state_bits >> i) & 1) != settings.ai[i].state)
|
|
|
+ {
|
|
|
+ settings.ai[i].state = ((settings.ai_state_bits >> i) & 1);
|
|
|
+ if (settings.ai[i].state == 0) {
|
|
|
+ leds[ai_input_led[i]].state = LED_OFF;
|
|
|
+ adc_com_raw_data[i] = 0;
|
|
|
+ adc_com_data[i] = 0;
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ leds[ai_input_led[i]].state = LED_ON;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// Утсновить режим измерения канала (ток или напряжение)
|
|
|
+void ai_set_mode(MEAS_CHAN_MODE_t mode, uint8_t channel)
|
|
|
+{
|
|
|
+ if (mode == MEAS_CURRENT)
|
|
|
+ {
|
|
|
+ if (channel < 7)
|
|
|
+ ai_mode |= (1 << (channel - 1));
|
|
|
+ else
|
|
|
+ ai_mode |= (1 << (channel + 1));
|
|
|
+ }
|
|
|
+ else
|
|
|
+ if (channel < 7)
|
|
|
+ ai_mode &= ~(1 << (channel - 1));
|
|
|
+ else
|
|
|
+ ai_mode &= ~(1 << (channel + 1));
|
|
|
+
|
|
|
+ sh_ai_mode(ai_mode);
|
|
|
+
|
|
|
+ //printf("Analog input mode: ");
|
|
|
+ print_binary_half_word(ai_mode);
|
|
|
+}
|
|
|
+
|
|
|
+// Формируем слово режима работы каналов (ai_mode)
|
|
|
+void ai_set_mode_word(MEAS_CHAN_MODE_t mode, uint8_t channel)
|
|
|
+{
|
|
|
+ if (mode == MEAS_CURRENT)
|
|
|
+ {
|
|
|
+ if (channel < 7)
|
|
|
+ ai_mode |= (1 << (channel - 1));
|
|
|
+ else
|
|
|
+ ai_mode |= (1 << (channel + 1));
|
|
|
+ }
|
|
|
+ else
|
|
|
+ if (channel < 7)
|
|
|
+ ai_mode &= ~(1 << (channel - 1));
|
|
|
+ else
|
|
|
+ ai_mode &= ~(1 << (channel + 1));
|
|
|
+}
|
|
|
+
|
|
|
+// Сигнал питания внешних датчиков
|
|
|
+void ai_ext_sens_power(uint16_t state)
|
|
|
+{
|
|
|
+ if (state)
|
|
|
+ ai_mux |= 0x80;
|
|
|
+ else
|
|
|
+ ai_mux &= ~(0x80);
|
|
|
+}
|
|
|
+
|
|
|
+// Управления LED
|
|
|
+void ai_leds_processing(void)
|
|
|
+{
|
|
|
+ // Управление индикацией аварий (12 красных LED) (слово ai_alarm)
|
|
|
+ for (uint8_t i = 0; i < AI_COMMON_NUMBER; i++) {
|
|
|
+ if (ai_alarm & (1 << i)) {
|
|
|
+ leds[ai_alarm_led[i]].state = LED_ON;
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ leds[ai_alarm_led[i]].state = LED_OFF;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+//
|
|
|
+void adc_alarm_detect(void)
|
|
|
+{
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+// -------------------------------------------------------------------------- //
|
|
|
+// Тесты
|
|
|
+
|
|
|
+//
|
|
|
+void ai_connect_test(void)
|
|
|
+{
|
|
|
+ ai_connect_channel(AN_INP_1);
|
|
|
+ ai_connect_channel(AN_INP_2);
|
|
|
+ ai_connect_channel(AN_INP_3);
|
|
|
+ ai_connect_channel(AN_INP_4);
|
|
|
+ ai_connect_channel(AN_INP_5);
|
|
|
+ ai_connect_channel(AN_INP_6);
|
|
|
+ ai_connect_channel(V_ISO_CL);
|
|
|
+ ai_connect_channel(V_ISO);
|
|
|
+
|
|
|
+ ai_connect_channel(AN_INP_7);
|
|
|
+ ai_connect_channel(AN_INP_8);
|
|
|
+ ai_connect_channel(AN_INP_9);
|
|
|
+ ai_connect_channel(AN_INP_10);
|
|
|
+ ai_connect_channel(AN_INP_11);
|
|
|
+ ai_connect_channel(AN_INP_12);
|
|
|
+ ai_connect_channel(CRNT_LIM_U_BFR_R);
|
|
|
+ ai_connect_channel(CRNT_LIM_U_ABFR_R);
|
|
|
+}
|
|
|
+
|
|
|
+//
|
|
|
+void ai_mode_test(void)
|
|
|
+{
|
|
|
+ for (uint8_t i = 1; i < 13; i++)
|
|
|
+ {
|
|
|
+ ai_set_mode(MEAS_VOLTAGE, i);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
#endif
|