попытка параллельной работы в ccs12 и legacy
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,2 +1,3 @@
|
|||||||
/Debug/
|
/Debug/
|
||||||
|
/Release/
|
||||||
/UKSSTMS320F28335.CS_/
|
/UKSSTMS320F28335.CS_/
|
||||||
|
|||||||
3
Bin/CCS12/.gitignore
vendored
Normal file
3
Bin/CCS12/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# CCS 12 output files
|
||||||
|
*
|
||||||
|
!.gitignore
|
||||||
598
PHASE_COMPARISON_BALSAM_165_167.md
Normal file
598
PHASE_COMPARISON_BALSAM_165_167.md
Normal file
@@ -0,0 +1,598 @@
|
|||||||
|
# Сравнение фазовой части Balsam 165 и Balsam 167
|
||||||
|
|
||||||
|
## Область сравнения
|
||||||
|
|
||||||
|
Сравнивались:
|
||||||
|
|
||||||
|
- захват фазных сигналов АЦП;
|
||||||
|
- удаление нулевого смещения;
|
||||||
|
- масштабирование в физические единицы;
|
||||||
|
- расчёт общего действующего значения;
|
||||||
|
- расчёт уровней отдельных фаз A, B и C;
|
||||||
|
- диагностика перекоса и обрыва фаз;
|
||||||
|
- диагностические биты и регистры Modbus;
|
||||||
|
- пороги напряжения и выдержки времени.
|
||||||
|
|
||||||
|
Исходные проекты:
|
||||||
|
|
||||||
|
- `K:/git_project/Balsam_165_periph`;
|
||||||
|
- `K:/git_project/Balsam_167_periph`.
|
||||||
|
|
||||||
|
Основные файлы:
|
||||||
|
|
||||||
|
| Проект | Файл |
|
||||||
|
|---|---|
|
||||||
|
| Balsam 165 | `K:/git_project/Balsam_165_periph/Source/Internal/measure.c` |
|
||||||
|
| Balsam 165 | `K:/git_project/Balsam_165_periph/Source/Internal/ADC.c` |
|
||||||
|
| Balsam 165 | `K:/git_project/Balsam_165_periph/Source/Internal/Include/measure.h` |
|
||||||
|
| Balsam 165 | `K:/git_project/Balsam_165_periph/Doc/Balsam 165 data stru.xls` |
|
||||||
|
| Balsam 167 | `Source/Internal/measure.c` |
|
||||||
|
| Balsam 167 | `Source/Internal/ADC.c` |
|
||||||
|
| Balsam 167 | `Source/Internal/Include/measure.h` |
|
||||||
|
| Balsam 167 | `Doc/Balsam 167 data stru.xls` |
|
||||||
|
|
||||||
|
## Вывод
|
||||||
|
|
||||||
|
Balsam 167 использует более правильный способ расчёта действующих значений
|
||||||
|
отдельных фаз: усреднение квадрата с последующим извлечением корня. Balsam 165
|
||||||
|
сглаживает модуль сигнала, что не является настоящим RMS.
|
||||||
|
|
||||||
|
При этом в Balsam 167 появились две ошибки индексации:
|
||||||
|
|
||||||
|
1. Парный канал записывается по абсолютному индексу, но читается по
|
||||||
|
относительному.
|
||||||
|
2. Бит `Ignor` устанавливается у абсолютного номера датчика, но проверяется у
|
||||||
|
относительного `chan`.
|
||||||
|
|
||||||
|
Для УМП, где `pow_addr == 0`, первая ошибка не проявляется. Для силового блока
|
||||||
|
она может приводить к дублированию фазных уровней и ложному `Wry + Stop`.
|
||||||
|
|
||||||
|
Рекомендуемый вариант: сохранить RMS-алгоритм Balsam 167, исправить индексацию
|
||||||
|
и выполнять диагностику трёх фаз один раз после обработки всей пары каналов.
|
||||||
|
|
||||||
|
## Сводная таблица
|
||||||
|
|
||||||
|
| Параметр | Balsam 165 | Balsam 167 | Оценка |
|
||||||
|
|---|---|---|---|
|
||||||
|
| Частота АЦП | 5000 Гц | 3750 Гц | Изменена |
|
||||||
|
| Выбор фазных входов АЦП | `CONV02…CONV05` | `CONV02…CONV05` | Одинаковый |
|
||||||
|
| Формула `im_calc()` | Одинаковая | Одинаковая | Без изменений |
|
||||||
|
| Фаза B | `-A-C`, для `dsk_COMM` эквивалентная разность | `-A-C` после смены знака A | По модулю эквивалентно |
|
||||||
|
| Уровень отдельной фазы | EMA от `abs(x)` | `sqrt(EMA(x²))` | 167 корректнее |
|
||||||
|
| Частота фильтра результата | 5 Гц | 3 Гц | 167 медленнее |
|
||||||
|
| Тип `lev_count[]` | `float` | `int` | В 167 раньше теряется дробная часть |
|
||||||
|
| Порог перекоса | 20% | 30% | 167 менее чувствителен |
|
||||||
|
| Выдержка измеряемой фазы | около 1,5 с | около 3 с | 167 медленнее |
|
||||||
|
| Выдержка восстановленной фазы | около 0,75 с | около 1,5 с | В обеих версиях вдвое короче |
|
||||||
|
| `Curr_Edge`, УМП | 100 | 300 | Порог существенно повышен |
|
||||||
|
| `Curr_Edge`, силовой блок | 40 | 200 | Порог существенно повышен |
|
||||||
|
| Низкое `Utr` | без выдержки | счётчик около 3 с | Улучшено, но блокируется `Ignor` |
|
||||||
|
| Верхнее `Utr` | без выдержки | без выдержки | Без улучшения |
|
||||||
|
| Калибровка входов | жёсткий `curK[]` | Modbus/EEPROM `Caliber[]` | 167 гибче |
|
||||||
|
| Пары каналов силового блока | корректные относительные индексы | несогласованные индексы | Регрессия 167 |
|
||||||
|
| Обработка `Ignor` | правильный абсолютный датчик | проверяется `chan` | Регрессия 167 |
|
||||||
|
| Отдельные биты фаз A/B/C | нет | нет | Общий недостаток |
|
||||||
|
| Контроль пределов АЦП U/I | нет | нет | Общий недостаток |
|
||||||
|
|
||||||
|
## 1. Захват сигналов АЦП
|
||||||
|
|
||||||
|
Для УМП обе версии используют одинаковые входы:
|
||||||
|
|
||||||
|
```c
|
||||||
|
CONV02 = 0x5; // напряжение 1
|
||||||
|
CONV03 = 0x4; // напряжение 2
|
||||||
|
CONV04 = 0x7; // ток 1
|
||||||
|
CONV05 = 0x2; // ток 2
|
||||||
|
```
|
||||||
|
|
||||||
|
Данные читаются из результатов `ADCRESULT2…ADCRESULT5`, после чего вызывается
|
||||||
|
`Current_count(i)`.
|
||||||
|
|
||||||
|
Различается частота обработки:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Balsam 165: ADC_FREQ = 5000 Гц
|
||||||
|
Balsam 167: ADC_FREQ = 3750 Гц
|
||||||
|
```
|
||||||
|
|
||||||
|
Назначение входов УМП:
|
||||||
|
|
||||||
|
| `chan` | Сигнал |
|
||||||
|
|---:|---|
|
||||||
|
| 0 | `Utr A` |
|
||||||
|
| 1 | `Utr C` |
|
||||||
|
| 2 | `Itr A` |
|
||||||
|
| 3 | `Itr C` |
|
||||||
|
|
||||||
|
Фаза B физически не измеряется.
|
||||||
|
|
||||||
|
## 2. Нулевое смещение
|
||||||
|
|
||||||
|
В обеих версиях используется медленное усреднение:
|
||||||
|
|
||||||
|
```text
|
||||||
|
zero[n] = zero[n-1] + (ADC-zero[n-1]) / (5 * ADC_FREQ)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Balsam 165
|
||||||
|
|
||||||
|
Ноль записывается постоянно:
|
||||||
|
|
||||||
|
```c
|
||||||
|
Zero_lev[chan] = filterbat(&out_filter[chan], zer_count[chan]);
|
||||||
|
```
|
||||||
|
|
||||||
|
Для подстройки используются те же `out_filter[]`, которые участвуют в другой
|
||||||
|
обработке сигналов.
|
||||||
|
|
||||||
|
### Balsam 167
|
||||||
|
|
||||||
|
Добавлены отдельные фильтры `zer_filter[]`:
|
||||||
|
|
||||||
|
```c
|
||||||
|
Zer = filterbat(&zer_filter[chan], zer_count[chan]);
|
||||||
|
if (WAKE < (WAKE_TIME / 2)) Zero_lev[chan] = Zer;
|
||||||
|
```
|
||||||
|
|
||||||
|
Разделение фильтров является улучшением. Однако после того как `WAKE` достиг
|
||||||
|
нуля, условие остаётся истинным. Подстройка нуля фактически продолжается во
|
||||||
|
время всей работы.
|
||||||
|
|
||||||
|
Если подстройка нужна только при запуске, должно проверяться также `WAKE > 0`.
|
||||||
|
|
||||||
|
## 3. Масштабирование
|
||||||
|
|
||||||
|
### Balsam 165
|
||||||
|
|
||||||
|
Используются жёстко заданные коэффициенты `curK[]`:
|
||||||
|
|
||||||
|
| Устройство | Напряжение | Ток |
|
||||||
|
|---|---:|---:|
|
||||||
|
| УМП 1/2 | `0.386` | `4.82` |
|
||||||
|
| Силовой блок | `0.402` | — |
|
||||||
|
|
||||||
|
Коэффициенты одинаковы для однотипных каналов и не берутся из EEPROM.
|
||||||
|
|
||||||
|
### Balsam 167
|
||||||
|
|
||||||
|
Коэффициенты вычисляются из `Caliber[0…3]`:
|
||||||
|
|
||||||
|
```text
|
||||||
|
напряжение: powK = Caliber / 10000
|
||||||
|
ток: powK = Caliber / 1000
|
||||||
|
```
|
||||||
|
|
||||||
|
Преимущества:
|
||||||
|
|
||||||
|
- индивидуальная калибровка каждого входа;
|
||||||
|
- отдельные значения для экземпляров устройств;
|
||||||
|
- сохранение и загрузка через EEPROM.
|
||||||
|
|
||||||
|
Значения тока заметно отличаются от Balsam 165. Например, для УМП 1 в
|
||||||
|
Balsam 167 используются `3.505` и `3.380` вместо `4.82`. Это может быть связано
|
||||||
|
с изменением аппаратной части или новой калибровкой и требует стендовой сверки.
|
||||||
|
|
||||||
|
## 4. Общий уровень трёхфазного сигнала
|
||||||
|
|
||||||
|
Функция `im_calc()` в проектах совпадает:
|
||||||
|
|
||||||
|
```text
|
||||||
|
isA = -1.5 * (a + b)
|
||||||
|
isB = cos(π/6) * (a - b)
|
||||||
|
Amplitude = 2/3 * sqrt(isA² + isB²)
|
||||||
|
Level = Amplitude / sqrt(2)
|
||||||
|
```
|
||||||
|
|
||||||
|
Эквивалентная формула амплитуды:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Amplitude = 2/sqrt(3) * sqrt(a² + a*b + b²)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Фильтрация общего уровня
|
||||||
|
|
||||||
|
Balsam 165 сначала делит амплитуду на `sqrt(2)`, затем фильтрует `Level`
|
||||||
|
фильтром 5 Гц. Для тока и всех каналов `dsk_COMM` используется дополнительная
|
||||||
|
статическая переменная `ffLev`.
|
||||||
|
|
||||||
|
`ffLev` одна на все вызовы функции. На силовом блоке результаты разных пар
|
||||||
|
могут влиять друг на друга.
|
||||||
|
|
||||||
|
Balsam 167 фильтрует амплитуду отдельным фильтром текущего датчика:
|
||||||
|
|
||||||
|
```c
|
||||||
|
Amplitude = filterbat(&out_filter[sens], im_calc(Current, aCurrent));
|
||||||
|
Level = Amplitude / RADIX2;
|
||||||
|
```
|
||||||
|
|
||||||
|
Это устраняет общий `ffLev` и разделяет состояния фильтров разных пар.
|
||||||
|
|
||||||
|
### Зона нечувствительности
|
||||||
|
|
||||||
|
Balsam 165:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Level < Curr_Edge -> Level = 0
|
||||||
|
```
|
||||||
|
|
||||||
|
Для УМП порог равен 100 единицам RMS.
|
||||||
|
|
||||||
|
Balsam 167:
|
||||||
|
|
||||||
|
```text
|
||||||
|
напряжение: Amplitude < 20 -> 0
|
||||||
|
ток: Amplitude < 75 -> 0
|
||||||
|
```
|
||||||
|
|
||||||
|
В пересчёте на RMS это примерно 14,1 для напряжения и 53,0 для тока. Поэтому
|
||||||
|
Balsam 167 публикует слабые сигналы, которые Balsam 165 обнулял.
|
||||||
|
|
||||||
|
## 5. Уровни отдельных фаз
|
||||||
|
|
||||||
|
### Balsam 165: среднее модуля
|
||||||
|
|
||||||
|
```c
|
||||||
|
lev_count[chan] +=
|
||||||
|
(fabs(Current) - lev_count[chan]) / (ADC_FREQ / 5);
|
||||||
|
```
|
||||||
|
|
||||||
|
Для синусоиды установившееся значение соответствует среднему модулю:
|
||||||
|
|
||||||
|
```text
|
||||||
|
MeanAbs = 2/π * Amplitude ≈ 0.6366 * Amplitude
|
||||||
|
```
|
||||||
|
|
||||||
|
### Balsam 167: настоящий RMS
|
||||||
|
|
||||||
|
```c
|
||||||
|
lev_quadr[chan] +=
|
||||||
|
(Current * Current - lev_quadr[chan]) / ADC_FREQ;
|
||||||
|
lev_count[chan] = sqrt(lev_quadr[chan]);
|
||||||
|
```
|
||||||
|
|
||||||
|
Для синусоиды:
|
||||||
|
|
||||||
|
```text
|
||||||
|
RMS = 1/sqrt(2) * Amplitude ≈ 0.7071 * Amplitude
|
||||||
|
```
|
||||||
|
|
||||||
|
При одинаковом входном масштабе Balsam 167 показывает примерно в 1,1107 раза,
|
||||||
|
или на 11,1%, больше Balsam 165.
|
||||||
|
|
||||||
|
Это изменение влияет на абсолютные фазные уровни, но почти не влияет на
|
||||||
|
отношение минимальной фазы к максимальной, используемое для `Wry`.
|
||||||
|
|
||||||
|
### Скорость сглаживания
|
||||||
|
|
||||||
|
Balsam 165 использует коэффициент `5/ADC_FREQ`, что соответствует постоянной
|
||||||
|
времени около 0,2 с.
|
||||||
|
|
||||||
|
Balsam 167 использует коэффициент `1/ADC_FREQ`, что соответствует постоянной
|
||||||
|
времени около 1 с. Фазные уровни Balsam 167 изменяются медленнее и стабильнее.
|
||||||
|
|
||||||
|
## 6. Восстановление фазы B
|
||||||
|
|
||||||
|
Для УМП в обеих версиях:
|
||||||
|
|
||||||
|
```text
|
||||||
|
B = -A - C
|
||||||
|
```
|
||||||
|
|
||||||
|
Для силового блока в Balsam 165 используется:
|
||||||
|
|
||||||
|
```text
|
||||||
|
third = current_channel - first_channel
|
||||||
|
```
|
||||||
|
|
||||||
|
В Balsam 167 сначала меняется знак сохранённого первого канала, затем
|
||||||
|
применяется общая формула `-Current-aCurrent`. Результат отличается знаком, но
|
||||||
|
для RMS знак не имеет значения.
|
||||||
|
|
||||||
|
Основной недостаток общий: фаза B не измеряется. Неисправность B определяется
|
||||||
|
только через математическую связь с A и C.
|
||||||
|
|
||||||
|
## 7. Карта фазных регистров
|
||||||
|
|
||||||
|
В Balsam 165 код записывает:
|
||||||
|
|
||||||
|
```text
|
||||||
|
0x68 + n*3 + 0 = текущий нечётный канал, для УМП фаза C
|
||||||
|
0x68 + n*3 + 1 = парный канал, для УМП фаза A
|
||||||
|
0x68 + n*3 + 2 = восстановленная фаза B
|
||||||
|
```
|
||||||
|
|
||||||
|
То есть фактический порядок для УМП:
|
||||||
|
|
||||||
|
```text
|
||||||
|
C, A, B
|
||||||
|
```
|
||||||
|
|
||||||
|
В Balsam 167 первые две записи переставлены:
|
||||||
|
|
||||||
|
```text
|
||||||
|
0x68 + n*3 + 0 = парный канал A
|
||||||
|
0x68 + n*3 + 1 = текущий канал C
|
||||||
|
0x68 + n*3 + 2 = восстановленная фаза B
|
||||||
|
```
|
||||||
|
|
||||||
|
Порядок соответствует карте Balsam 167:
|
||||||
|
|
||||||
|
| Регистр | УМП |
|
||||||
|
|---:|---|
|
||||||
|
| `0x68` | `Utr A` |
|
||||||
|
| `0x69` | `Utr C` |
|
||||||
|
| `0x6A` | `Utr B` |
|
||||||
|
| `0x6B` | `Itr A` |
|
||||||
|
| `0x6C` | `Itr C` |
|
||||||
|
| `0x6D` | `Itr B` |
|
||||||
|
|
||||||
|
В карте Balsam 165 эти регистры не описаны как фазные. Адрес `0x68` обозначен
|
||||||
|
как яркость ламп, хотя исходный код записывает туда фазный уровень. Это риск
|
||||||
|
несовместимости прошивки с внешним ПО и документацией.
|
||||||
|
|
||||||
|
## 8. Диагностика `Wry`
|
||||||
|
|
||||||
|
В обеих версиях используется отношение:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Max = max(phase_A, phase_C, phase_B)
|
||||||
|
deviation = (Max - phase) / Max
|
||||||
|
```
|
||||||
|
|
||||||
|
### Balsam 165
|
||||||
|
|
||||||
|
```text
|
||||||
|
deviation > 20%
|
||||||
|
Max > Curr_Edge
|
||||||
|
выдержка измеряемой фазы ≈ 1,5 с
|
||||||
|
```
|
||||||
|
|
||||||
|
`Curr_Edge`:
|
||||||
|
|
||||||
|
| Режим | Значение |
|
||||||
|
|---|---:|
|
||||||
|
| УМП | 100 |
|
||||||
|
| Силовой блок | 40 |
|
||||||
|
|
||||||
|
### Balsam 167
|
||||||
|
|
||||||
|
```text
|
||||||
|
deviation > 30%
|
||||||
|
Max > Curr_Edge
|
||||||
|
выдержка измеряемой фазы ≈ 3 с
|
||||||
|
```
|
||||||
|
|
||||||
|
`Curr_Edge`:
|
||||||
|
|
||||||
|
| Режим | Значение |
|
||||||
|
|---|---:|
|
||||||
|
| УМП | 300 |
|
||||||
|
| Силовой блок | 200 |
|
||||||
|
|
||||||
|
Balsam 167 значительно менее чувствителен к перекосу и реагирует медленнее.
|
||||||
|
|
||||||
|
### Ошибка выдержки восстановленной фазы
|
||||||
|
|
||||||
|
Один счётчик `err_count[thrd]` вызывается при обработке обоих каналов пары.
|
||||||
|
Поэтому он увеличивается дважды за цикл АЦП.
|
||||||
|
|
||||||
|
Фактическая выдержка постоянного дефекта фазы B:
|
||||||
|
|
||||||
|
| Проект | Заданная | Фактическая для B |
|
||||||
|
|---|---:|---:|
|
||||||
|
| Balsam 165 | 1,5 с | около 0,75 с |
|
||||||
|
| Balsam 167 | 3 с | около 1,5 с |
|
||||||
|
|
||||||
|
Проблема присутствует в обеих версиях.
|
||||||
|
|
||||||
|
### Деление на ноль
|
||||||
|
|
||||||
|
Обе версии сначала вычисляют отношение с делением на `Max`, а затем проверяют
|
||||||
|
нижний порог:
|
||||||
|
|
||||||
|
```c
|
||||||
|
((Max - phase) / Max > limit) && (Max > Curr_Edge)
|
||||||
|
```
|
||||||
|
|
||||||
|
При `Max == 0` выполняется `0/0`. Безопасный порядок:
|
||||||
|
|
||||||
|
```c
|
||||||
|
(Max > Curr_Edge) && (((Max - phase) / Max) > limit)
|
||||||
|
```
|
||||||
|
|
||||||
|
## 9. Различия обработки `Ignor`
|
||||||
|
|
||||||
|
### Balsam 165
|
||||||
|
|
||||||
|
Используется правильный абсолютный номер датчика:
|
||||||
|
|
||||||
|
```c
|
||||||
|
sens = tpl_cans + chan;
|
||||||
|
ignor = sens_error[sens].bit.Ignor;
|
||||||
|
```
|
||||||
|
|
||||||
|
Ошибки `Wry`, `Out` и `Hyper` продолжают вычисляться и передаваться, но
|
||||||
|
`Stop` не устанавливается для игнорируемого канала.
|
||||||
|
|
||||||
|
### Balsam 167
|
||||||
|
|
||||||
|
Проверяется относительный индекс:
|
||||||
|
|
||||||
|
```c
|
||||||
|
sens = pow_addr + chan;
|
||||||
|
if (WAKE || sens_error[chan].bit.Ignor) goto fin;
|
||||||
|
```
|
||||||
|
|
||||||
|
Последствия различаются по типу устройства.
|
||||||
|
|
||||||
|
#### УМП
|
||||||
|
|
||||||
|
Для УМП `pow_addr == 0`, поэтому индекс формально совпадает. Каналам напряжения
|
||||||
|
`0x00` и `0x01` по умолчанию устанавливается `Ignor`. В результате Balsam 167
|
||||||
|
полностью пропускает для напряжения:
|
||||||
|
|
||||||
|
- `Wry`;
|
||||||
|
- `Out` при `Utr < 300 В`;
|
||||||
|
- `Hyper` при `Utr > 420 В`;
|
||||||
|
- `Stop`.
|
||||||
|
|
||||||
|
В Balsam 165 эти информационные биты вычислялись, но `Stop` блокировался.
|
||||||
|
|
||||||
|
#### Силовой блок
|
||||||
|
|
||||||
|
На силовом блоке `pow_addr != 0`. `Ignor` устанавливается в
|
||||||
|
`sens_error[pow_addr+chan]`, но проверяется `sens_error[chan]`.
|
||||||
|
|
||||||
|
Из-за этого игнорирование может не сработать, а `Wry + Stop` сформироваться для
|
||||||
|
канала, который должен быть исключён из диагностики.
|
||||||
|
|
||||||
|
## 10. Регрессия `sens_pair` в Balsam 167
|
||||||
|
|
||||||
|
В Balsam 165 пары хранятся относительно `chan`:
|
||||||
|
|
||||||
|
```c
|
||||||
|
sens_pair[0] = 1;
|
||||||
|
sens_pair[1] = 0;
|
||||||
|
sens_pair[2] = 3;
|
||||||
|
sens_pair[3] = 2;
|
||||||
|
pair = sens_pair[chan];
|
||||||
|
```
|
||||||
|
|
||||||
|
В Balsam 167 пары записываются по абсолютному индексу:
|
||||||
|
|
||||||
|
```c
|
||||||
|
sens_pair[pow_addr+i] = pow_addr+(i^1);
|
||||||
|
```
|
||||||
|
|
||||||
|
Но чтение осталось старым:
|
||||||
|
|
||||||
|
```c
|
||||||
|
pair = sens_pair[chan];
|
||||||
|
```
|
||||||
|
|
||||||
|
Для силового блока элементы `sens_pair[0…3]` после общей инициализации равны
|
||||||
|
`0, 1, 2, 3`. Следовательно, `pair` указывает на текущий канал, а не на
|
||||||
|
соседний.
|
||||||
|
|
||||||
|
Последствия:
|
||||||
|
|
||||||
|
- один фазный уровень может записываться дважды;
|
||||||
|
- максимальная фаза выбирается из неполного набора;
|
||||||
|
- `Wry` может быть пропущен или сформирован ошибочно;
|
||||||
|
- карта `0x68…0x6D` для силового блока не соответствует ожидаемой.
|
||||||
|
|
||||||
|
Вероятное исправление:
|
||||||
|
|
||||||
|
```c
|
||||||
|
pair = sens_pair[sens] - pow_addr;
|
||||||
|
```
|
||||||
|
|
||||||
|
Окончательный вариант следует подтвердить стендовым тестом и ожидаемым
|
||||||
|
порядком фаз в регистрах.
|
||||||
|
|
||||||
|
## 11. Пороговые уровни УМП
|
||||||
|
|
||||||
|
Заводские уставки в проектах совпадают:
|
||||||
|
|
||||||
|
| Сигнал | Нижний порог | Верхний порог |
|
||||||
|
|---|---:|---:|
|
||||||
|
| `Utr` | 300 В | 420 В |
|
||||||
|
| `Itr` | 800 А, предупреждение | 900 А, авария |
|
||||||
|
|
||||||
|
Различается обработка нижнего напряжения:
|
||||||
|
|
||||||
|
| Проект | Реакция `Utr < 300 В` |
|
||||||
|
|---|---|
|
||||||
|
| Balsam 165 | `Out` сразу; `Stop` блокируется при штатном `Ignor` |
|
||||||
|
| Balsam 167 | счётчик около 3 с, но при штатном `Ignor` проверка не выполняется |
|
||||||
|
|
||||||
|
Верхний порог `Utr > 420 В` в обеих версиях не имеет отдельной выдержки и
|
||||||
|
гистерезиса.
|
||||||
|
|
||||||
|
## 12. Диагностические биты
|
||||||
|
|
||||||
|
Расположение основных битов не изменилось:
|
||||||
|
|
||||||
|
| Бит | Маска | Имя | Назначение |
|
||||||
|
|---:|---:|---|---|
|
||||||
|
| 0 | `0x0001` | `Tear` | обрыв датчика/предельное значение АЦП |
|
||||||
|
| 2 | `0x0004` | `Wry` | перекос фаз |
|
||||||
|
| 3 | `0x0008` | `Out` | ниже нижнего порога |
|
||||||
|
| 4 | `0x0010` | `Over` | выше предупредительного порога |
|
||||||
|
| 5 | `0x0020` | `Hyper` | выше аварийного порога |
|
||||||
|
| 8 | `0x0100` | `Stop` | авария |
|
||||||
|
| 9 | `0x0200` | `Ready` | готовность |
|
||||||
|
| 14 | `0x4000` | `Ignor` | игнорировать аварию |
|
||||||
|
| 15 | `0x8000` | `Bypas` | отключить канал |
|
||||||
|
|
||||||
|
В обеих версиях `Current_count()` не формирует `Tear` для фазных входов U/I.
|
||||||
|
Поэтому неисправность измерительного тракта нельзя надёжно отличить от
|
||||||
|
пропадания напряжения или тока.
|
||||||
|
|
||||||
|
## 13. Что следует перенести из Balsam 165
|
||||||
|
|
||||||
|
В Balsam 167 полезно вернуть следующие свойства реализации 165:
|
||||||
|
|
||||||
|
1. Согласованную систему индексов `sens_pair`.
|
||||||
|
2. Проверку `Ignor` через абсолютный индекс `sens_error[sens]`.
|
||||||
|
3. Использование `float` для внутренних фазных уровней до момента публикации.
|
||||||
|
|
||||||
|
Не следует возвращать:
|
||||||
|
|
||||||
|
- усреднение `fabs()` вместо RMS;
|
||||||
|
- общий статический фильтр `ffLev`;
|
||||||
|
- немедленное срабатывание нижнего напряжения;
|
||||||
|
- жёсткие коэффициенты `curK[]`.
|
||||||
|
|
||||||
|
## 14. Рекомендуемая итоговая реализация
|
||||||
|
|
||||||
|
1. Считать все абсолютные номера датчиков один раз:
|
||||||
|
|
||||||
|
```c
|
||||||
|
sens = pow_addr + chan;
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Хранить `sens_pair[]` либо полностью в относительных, либо полностью в
|
||||||
|
абсолютных индексах. Не смешивать системы адресации.
|
||||||
|
3. Сохранить RMS Balsam 167, но хранить `lev_count[]` как `float`.
|
||||||
|
4. После поступления обоих отсчётов пары вычислять A, C и B в одном месте.
|
||||||
|
5. Один раз за цикл обновлять три RMS и три диагностических счётчика.
|
||||||
|
6. Проверять `Max > Curr_Edge` до деления.
|
||||||
|
7. Проверять `Ignor` через `sens_error[sens]`.
|
||||||
|
8. Разделить понятия:
|
||||||
|
|
||||||
|
- информационная ошибка присутствует;
|
||||||
|
- ошибка участвует в формировании `Stop`.
|
||||||
|
|
||||||
|
9. Добавить отдельную маску фаз A/B/C.
|
||||||
|
10. Добавить `Tear` по сырому значению АЦП.
|
||||||
|
11. Добавить выдержку и гистерезис для 300/420 В.
|
||||||
|
12. Явно определить, должна ли подстройка нуля работать после запуска.
|
||||||
|
|
||||||
|
## 15. Минимальные сравнительные тесты
|
||||||
|
|
||||||
|
| Тест | Что проверить |
|
||||||
|
|---|---|
|
||||||
|
| Одинаковая синусоида на обеих версиях | Разницу MeanAbs и RMS около 11,1% |
|
||||||
|
| Номинальные A и C | Правильный порядок A/C/B в `0x68…0x6D` |
|
||||||
|
| Обрыв A | RMS A, `Wry`, выдержку |
|
||||||
|
| Обрыв C | RMS C, `Wry`, выдержку |
|
||||||
|
| Нарушение вычисленной B | Отсутствие двойной скорости счётчика |
|
||||||
|
| Перекос 20%, 25%, 30%, 35% | Различия порогов 165 и 167 |
|
||||||
|
| `Max == 0` | Отсутствие деления на ноль |
|
||||||
|
| `Utr = 299 В` | `Out` и выдержку |
|
||||||
|
| `Utr = 421 В` | `Hyper` и отсутствие дребезга |
|
||||||
|
| `Ignor = 1` | Ошибка видна, но не создаёт `Stop`, если это требуемая семантика |
|
||||||
|
| Силовой блок, две пары | Отсутствие дублирования фазных RMS |
|
||||||
|
| АЦП около 0 и 4095 | Формирование `Tear` |
|
||||||
|
|
||||||
|
## Заключение
|
||||||
|
|
||||||
|
Фазовый расчёт Balsam 167 является хорошей основой благодаря настоящему RMS,
|
||||||
|
раздельным фильтрам и калибровке из регистров. Главный риск версии 167 находится
|
||||||
|
не в математике RMS, а в адресации состояния каналов.
|
||||||
|
|
||||||
|
До исправления `sens_pair` и `Ignor` фазные регистры и `Wry` силового блока
|
||||||
|
нельзя считать надёжными. Для УМП необходимо отдельно решить, должны ли
|
||||||
|
напряжения с установленным `Ignor` продолжать формировать информационные
|
||||||
|
`Wry`, `Out` и `Hyper`, как это происходило в Balsam 165.
|
||||||
342
PHASE_VOLTAGE_CALCULATION.md
Normal file
342
PHASE_VOLTAGE_CALCULATION.md
Normal file
@@ -0,0 +1,342 @@
|
|||||||
|
# Расчёт входных фаз, диагностика обрыва и уровни напряжения
|
||||||
|
|
||||||
|
Документ составлен по исходникам прошивки Balsam 167 и карте регистров
|
||||||
|
`Doc/Balsam 167 data stru.xls`.
|
||||||
|
|
||||||
|
## Где находится код
|
||||||
|
|
||||||
|
Основная обработка входных напряжений и токов находится в
|
||||||
|
`Source/Internal/measure.c`:
|
||||||
|
|
||||||
|
- `im_calc()` — восстановление амплитуды трёхфазного сигнала, строки 82–89;
|
||||||
|
- `Current_count()` — смещение АЦП, масштабирование, RMS фаз, общий уровень и
|
||||||
|
диагностика перекоса/пропадания, строки 444–614;
|
||||||
|
- `Power_count()` — контроль отдельных источников питания шкафа ВЭП,
|
||||||
|
строки 769–841;
|
||||||
|
- `er_anal()` — выдержка времени для диагностических признаков,
|
||||||
|
строки 423–432.
|
||||||
|
|
||||||
|
Частота расчёта задаётся как `ADC_FREQ = 3750 Гц` в
|
||||||
|
`Source/Internal/Include/measure.h:73`. Выбор каналов АЦП выполняется в
|
||||||
|
`Source/Internal/ADC.c`, а пороги по умолчанию — в
|
||||||
|
`Source/Internal/message.c:24–135`.
|
||||||
|
|
||||||
|
## 1. Получение входных отсчётов
|
||||||
|
|
||||||
|
Для плат с измерением напряжения/тока обрабатываются четыре входа:
|
||||||
|
|
||||||
|
| `chan` | Назначение для УМП (`dsk_LOAD`) | Сырой регистр |
|
||||||
|
|---:|---|---:|
|
||||||
|
| 0 | напряжение фазы A (`Utr A`) | `0x64` |
|
||||||
|
| 1 | напряжение фазы C (`Utr C`) | `0x65` |
|
||||||
|
| 2 | ток фазы A (`Itr A`) | `0x66` |
|
||||||
|
| 3 | ток фазы C (`Itr C`) | `0x67` |
|
||||||
|
|
||||||
|
В `ADC.c:228–233` результат АЦП читается так:
|
||||||
|
|
||||||
|
```c
|
||||||
|
adc_table_lem[i] = *((&AdcRegs.ADCRESULT0)+i+2) >> 4;
|
||||||
|
Current_count(i);
|
||||||
|
```
|
||||||
|
|
||||||
|
То есть используются 12 старших значащих бит результата АЦП.
|
||||||
|
|
||||||
|
### Удаление нулевого смещения и перевод в физические единицы
|
||||||
|
|
||||||
|
В `Current_count()` выполняется:
|
||||||
|
|
||||||
|
```text
|
||||||
|
N = adc_table_lem[chan]
|
||||||
|
X = (N - Zero_lev[chan]) * powK[chan]
|
||||||
|
```
|
||||||
|
|
||||||
|
`Zero_lev[0..3]` хранится в регистрах `0x70…0x73`; значение по умолчанию —
|
||||||
|
`0x800 = 2048`. Ноль дополнительно подстраивается медленным фильтром:
|
||||||
|
|
||||||
|
```text
|
||||||
|
zero[n] = zero[n-1] + (N - zero[n-1]) / (5 * 3750)
|
||||||
|
```
|
||||||
|
|
||||||
|
Коэффициент `powK` формируется из калибровки `Caliber[0..3]`:
|
||||||
|
|
||||||
|
```text
|
||||||
|
для напряжения: powK = Caliber / 10000
|
||||||
|
для тока: powK = Caliber / 1000
|
||||||
|
```
|
||||||
|
|
||||||
|
Калибровочные значения находятся в Modbus-регистрах `0x74…0x77`, могут быть
|
||||||
|
загружены из EEPROM и поэтому не обязаны совпадать со значениями по умолчанию.
|
||||||
|
|
||||||
|
Для Balsam 167 значения по умолчанию такие:
|
||||||
|
|
||||||
|
| Устройство | Каналы | `Caliber` | `powK` |
|
||||||
|
|---|---|---|---|
|
||||||
|
| Силовой 1, адрес 3 | `UA1, UB1, UA2, UB2` | `4936, 4877, 4972, 4857` | `0.4936, 0.4877, 0.4972, 0.4857` |
|
||||||
|
| Силовой 2, адрес 4 | `UA1, UB1, UA2, UB2` | `4876, 5005, 4876, 4847` | `0.4876, 0.5005, 0.4876, 0.4847` |
|
||||||
|
| УМП 1, адрес 5 | `Utr A, Utr C, Itr A, Itr C` | `3820, 3790, 3505, 3380` | `0.3820, 0.3790, 3.505, 3.380` |
|
||||||
|
| УМП 2, адрес 6 | `Utr A, Utr C, Itr A, Itr C` | `3835, 3785, 3522, 3332` | `0.3835, 0.3785, 3.522, 3.332` |
|
||||||
|
|
||||||
|
Источник значений: `Source/Internal/Include/caliber.h`, секция
|
||||||
|
`#if BALSAM == 167`.
|
||||||
|
|
||||||
|
## 2. Расчёт амплитуды и действующего значения
|
||||||
|
|
||||||
|
Функция `im_calc(a, b)` использует два измеренных фазных сигнала:
|
||||||
|
|
||||||
|
```text
|
||||||
|
isA = -1.5 * (a + b)
|
||||||
|
isB = cos(π/6) * (a - b)
|
||||||
|
Amplitude = 2/3 * sqrt(isA² + isB²)
|
||||||
|
```
|
||||||
|
|
||||||
|
Эквивалентная свёрнутая формула:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Amplitude = 2/sqrt(3) * sqrt(a² + a*b + b²)
|
||||||
|
```
|
||||||
|
|
||||||
|
После цифрового фильтра Баттерворта 3 Гц получается амплитуда сигнала.
|
||||||
|
Действующее значение вычисляется как:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Level = Amplitude / sqrt(2)
|
||||||
|
```
|
||||||
|
|
||||||
|
Для каналов напряжения амплитуда принудительно обнуляется при
|
||||||
|
`Amplitude < 20`; для каналов тока — при `Amplitude < 75`.
|
||||||
|
|
||||||
|
Результат пары записывается в два регистра данных:
|
||||||
|
|
||||||
|
```text
|
||||||
|
sens_data[нечётный канал] = Amplitude
|
||||||
|
sens_data[чётный канал] = Level
|
||||||
|
```
|
||||||
|
|
||||||
|
Для УМП это даёт:
|
||||||
|
|
||||||
|
| Регистр | Значение |
|
||||||
|
|---:|---|
|
||||||
|
| `0x18` | действующее `Utr` |
|
||||||
|
| `0x19` | амплитудное `Utr` |
|
||||||
|
| `0x1A` | действующее `Itr` |
|
||||||
|
| `0x1B` | амплитудное `Itr` |
|
||||||
|
|
||||||
|
Для силового блока адреса данных сдвинуты из-за температурных каналов:
|
||||||
|
`0x28/0x29` — действующее/амплитудное `Uвх1`, `0x2A/0x2B` —
|
||||||
|
действующее/амплитудное `Uвх2`.
|
||||||
|
|
||||||
|
## 3. Действующие значения отдельных фаз
|
||||||
|
|
||||||
|
Для каждой пары измеряются две фазы, третья восстанавливается по условию
|
||||||
|
трёхпроводной системы:
|
||||||
|
|
||||||
|
```text
|
||||||
|
x3 = -x1 - x2
|
||||||
|
```
|
||||||
|
|
||||||
|
Для каждого из трёх сигналов считается скользящее среднеквадратичное значение:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Qphase[n] = Qphase[n-1] + (xphase² - Qphase[n-1]) / 3750
|
||||||
|
RMSphase = sqrt(Qphase)
|
||||||
|
```
|
||||||
|
|
||||||
|
`lev_count[]` имеет тип `int`, поэтому сохранённый RMS усекается до целого.
|
||||||
|
|
||||||
|
Карта регистров фаз для УМП:
|
||||||
|
|
||||||
|
| Регистр | Пара входов | Значение |
|
||||||
|
|---:|---|---|
|
||||||
|
| `0x68` | напряжение | RMS фазы A (`Utr A`) |
|
||||||
|
| `0x69` | напряжение | RMS фазы C (`Utr C`) |
|
||||||
|
| `0x6A` | напряжение | RMS восстановленной фазы B (`Utr B`) |
|
||||||
|
| `0x6B` | ток | RMS фазы A (`Itr A`) |
|
||||||
|
| `0x6C` | ток | RMS фазы C (`Itr C`) |
|
||||||
|
| `0x6D` | ток | RMS восстановленной фазы B (`Itr B`) |
|
||||||
|
|
||||||
|
В коде назначение пары определяется как `feed = chan >> 1`, а начальный адрес
|
||||||
|
фазных уровней — как `0x68 + feed * 3`.
|
||||||
|
|
||||||
|
## 4. Диагностика обрыва или сильного перекоса фазы
|
||||||
|
|
||||||
|
Отдельных битов «обрыв фазы A», «обрыв фазы B» и «обрыв фазы C» в прошивке
|
||||||
|
нет. Есть общий признак сильного отличия одной из трёх фаз — `Wry`.
|
||||||
|
Конкретную пропавшую фазу надо определять по минимальному значению среди
|
||||||
|
регистров `0x68…0x6A` или `0x6B…0x6D`.
|
||||||
|
|
||||||
|
Алгоритм в `Current_count()`:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Max = max(RMS_A, RMS_B, RMS_C)
|
||||||
|
|
||||||
|
перекос фазы = ((Max - RMS_phase) / Max > 0.30) AND (Max > Curr_Edge)
|
||||||
|
```
|
||||||
|
|
||||||
|
Условие проходит через реверсивный счётчик `er_anal()`: при наличии ошибки он
|
||||||
|
увеличивается, а при исчезновении уменьшается, но не сбрасывается сразу. Порог
|
||||||
|
для измеряемой фазы равен примерно 3 секундам
|
||||||
|
(`time_3sec = 3 * ADC_FREQ = 11250` отсчётов). Для восстановленной фазы один и
|
||||||
|
тот же счётчик вызывается из обоих каналов пары, поэтому при постоянной ошибке
|
||||||
|
порог фактически достигается примерно вдвое быстрее — около 1,5 секунды.
|
||||||
|
После достижения порога устанавливаются:
|
||||||
|
|
||||||
|
| Бит диагностического слова | Маска | Имя | Значение |
|
||||||
|
|---:|---:|---|---|
|
||||||
|
| 2 | `0x0004` | `Wry` | перекос/пропадание одной из фаз более чем на 30% от максимальной |
|
||||||
|
| 8 | `0x0100` | `Stop` | авария, устанавливается вместе с `Wry` |
|
||||||
|
|
||||||
|
Для УМП `Curr_Edge = 300`. Поэтому фазовая диагностика не работает при
|
||||||
|
`Max <= 300` и не реагирует на слабый сигнал/шум около нуля.
|
||||||
|
|
||||||
|
Диагностические слова УМП:
|
||||||
|
|
||||||
|
| Регистр | Канал |
|
||||||
|
|---:|---|
|
||||||
|
| `0x00` | `Utr A` |
|
||||||
|
| `0x01` | `Utr C` |
|
||||||
|
| `0x02` | `Itr A` |
|
||||||
|
| `0x03` | `Itr C` |
|
||||||
|
|
||||||
|
При одиночном пропадании фаз ожидается следующая комбинация:
|
||||||
|
|
||||||
|
| Пропавшая фаза | Напряжение | Ток |
|
||||||
|
|---|---|---|
|
||||||
|
| A | `0x00.Wry` | `0x02.Wry` |
|
||||||
|
| C | `0x01.Wry` | `0x03.Wry` |
|
||||||
|
| B, восстановленная | `0x00.Wry` и `0x01.Wry` | `0x02.Wry` и `0x03.Wry` |
|
||||||
|
|
||||||
|
Вместе с каждым `Wry` ставится `Stop`. Эта комбинация выведена из порядка
|
||||||
|
проверок в коде, но при сложном перекосе она неоднозначна. Надёжнее определять
|
||||||
|
проблемную фазу по тройке RMS-регистров.
|
||||||
|
|
||||||
|
В месте чтения Modbus признаки можно проверять масками:
|
||||||
|
|
||||||
|
```c
|
||||||
|
// Напряжение УМП
|
||||||
|
bool phase_a_fault = (modbus[0x00] & 0x0004) != 0;
|
||||||
|
bool phase_c_fault = (modbus[0x01] & 0x0004) != 0;
|
||||||
|
bool voltage_stop = ((modbus[0x00] | modbus[0x01]) & 0x0100) != 0;
|
||||||
|
|
||||||
|
// Ток УМП
|
||||||
|
bool current_a_fault = (modbus[0x02] & 0x0004) != 0;
|
||||||
|
bool current_c_fault = (modbus[0x03] & 0x0004) != 0;
|
||||||
|
bool current_stop = ((modbus[0x02] | modbus[0x03]) & 0x0100) != 0;
|
||||||
|
```
|
||||||
|
|
||||||
|
Названия `phase_a_fault` и `phase_c_fault` здесь условные: каждый `Wry` также
|
||||||
|
участвует в контроле восстановленной фазы B. Для точной индикации следует
|
||||||
|
сравнить сами уровни `0x68…0x6D`.
|
||||||
|
|
||||||
|
### Другие связанные биты диагностики
|
||||||
|
|
||||||
|
Структура диагностического слова задана в
|
||||||
|
`Source/Internal/Include/measure.h:19–46`:
|
||||||
|
|
||||||
|
| Бит | Маска | Имя | Назначение |
|
||||||
|
|---:|---:|---|---|
|
||||||
|
| 0 | `0x0001` | `Tear` | обрыв датчика/крайнее значение АЦП; в фазовом расчёте не формируется |
|
||||||
|
| 2 | `0x0004` | `Wry` | перекос парных датчиков/фаз |
|
||||||
|
| 3 | `0x0008` | `Out` | уровень ниже нижней уставки |
|
||||||
|
| 4 | `0x0010` | `Over` | уровень выше предупредительной уставки |
|
||||||
|
| 5 | `0x0020` | `Hyper` | уровень выше аварийной верхней уставки |
|
||||||
|
| 6 | `0x0040` | `Contr` | нет сигнала на одном из дискретных входов контроля |
|
||||||
|
| 8 | `0x0100` | `Stop` | аварийный останов |
|
||||||
|
| 9 | `0x0200` | `Ready` | готовность, равна `!Stop` |
|
||||||
|
| 10–13 | `0x0400…0x2000` | `Discr1…Discr4` | отдельные дискретные входы контроля |
|
||||||
|
| 14 | `0x4000` | `Ignor` | игнорировать диагностику |
|
||||||
|
| 15 | `0x8000` | `Bypas` | отключить канал |
|
||||||
|
|
||||||
|
`reset_errs()` сохраняет управляющие биты 13–15 маской `NOER = 0xE000`,
|
||||||
|
добавляет вычисленные ошибки и каждый цикл формирует `Ready = !Stop`.
|
||||||
|
|
||||||
|
## 5. Уровни напряжения УМП
|
||||||
|
|
||||||
|
Проверка уровня выполняется только после расчёта общей амплитуды/RMS пары и
|
||||||
|
только для нечётного канала пары (`Current_count():569–591`).
|
||||||
|
|
||||||
|
### Входное напряжение `Utr`
|
||||||
|
|
||||||
|
| Условие | Выдержка | Устанавливаемые биты |
|
||||||
|
|---|---:|---|
|
||||||
|
| `Level < 300 В` | около 3 с | `Out` (бит 3) + `Stop` (бит 8) |
|
||||||
|
| `Level > 420 В` | без отдельной выдержки | `Hyper` (бит 5) + `Stop` (бит 8) |
|
||||||
|
|
||||||
|
Уставки находятся в `sens_lo_edge[0/1]` (Modbus `0x48/0x49`) и
|
||||||
|
`sens_hi_edge[0/1]` (Modbus `0x30/0x31`). Значения выше — заводские; записью
|
||||||
|
по Modbus или загрузкой EEPROM они могут быть изменены.
|
||||||
|
|
||||||
|
### Ток `Itr`
|
||||||
|
|
||||||
|
Для полноты связанной логики:
|
||||||
|
|
||||||
|
| Условие | Биты |
|
||||||
|
|---|---|
|
||||||
|
| `Level > 800 А` | `Over` (бит 4), предупреждение |
|
||||||
|
| `Level > 900 А` | `Hyper` (бит 5) + `Stop` (бит 8) |
|
||||||
|
|
||||||
|
## 6. Контроль напряжений шкафа ВЭП (`Power_count`)
|
||||||
|
|
||||||
|
На плате шкафа каждый канал масштабируется напрямую:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Power = ADC_table[chan] * powK[sens_type[chan]]
|
||||||
|
```
|
||||||
|
|
||||||
|
Коэффициенты заданы в `measure.c:52–65`: `0.127` для каналов 380 В и
|
||||||
|
`0.0076` для низковольтных каналов.
|
||||||
|
|
||||||
|
Нижние уровни по умолчанию:
|
||||||
|
|
||||||
|
| Каналы | Контролируемое напряжение | Нижний уровень |
|
||||||
|
|---:|---|---:|
|
||||||
|
| 0, 1 | 380 В, фидеры 1 и 2 | 300 В |
|
||||||
|
| 2, 3 | 31 В, фидеры 1 и 2 | 15 В |
|
||||||
|
| 4, 5 | 31 В UC, фидеры 1 и 2 | 15 В |
|
||||||
|
| 6 | 24 В ПУ | 20 В |
|
||||||
|
| 7 | 27 В ФА | 22 В |
|
||||||
|
| 8 | 24 В ПК | 20 В |
|
||||||
|
| 9 | 15 В ДР | 10 В |
|
||||||
|
| 10 | +24 В ДТ | 20 В |
|
||||||
|
| 11 | −24 В ДТ | 20 В по модулю измеряемого значения |
|
||||||
|
| 12 | 24 В ПМУ | 20 В |
|
||||||
|
|
||||||
|
Если `Power < sens_lo_edge[chan]`, ставится `Out` (бит 3). `Stop` (бит 8)
|
||||||
|
ставится, когда `Out` уже установлен и у парного канала. Пары заданы как
|
||||||
|
`0↔1`, `2↔3`, `4↔5`; одиночные каналы спарены сами с собой. Поэтому для
|
||||||
|
двухфидерных источников аварийный останов означает пропадание обоих фидеров,
|
||||||
|
а пропадание одного фидера даёт только `Out` в его диагностическом слове.
|
||||||
|
|
||||||
|
Проверка превышения верхней уставки в `Power_count():829–835` закомментирована
|
||||||
|
и фактически не выполняется.
|
||||||
|
|
||||||
|
## 7. Особенности текущей реализации
|
||||||
|
|
||||||
|
1. На силовых блоках (`dsk_COMM`) четырём каналам назначается `Ignor` по
|
||||||
|
абсолютным индексам `pow_addr…pow_addr+3` (`measure.c:359–365`), но проверка
|
||||||
|
в `Current_count()` обращается к `sens_error[chan].Ignor`. Из-за разных
|
||||||
|
индексов назначенный `Ignor` может не отключать фазовую диагностику.
|
||||||
|
2. В `Current_count()` используется `pair = sens_pair[chan]`, тогда как для
|
||||||
|
силового блока пары инициализируются по абсолютному индексу
|
||||||
|
`sens_pair[pow_addr + chan]`. Для УМП, где `pow_addr == 0`, это работает как
|
||||||
|
задумано. На силовом блоке индекс `pair` остаётся равен текущему `chan`, что
|
||||||
|
может дублировать один фазовый RMS вместо чтения парного канала.
|
||||||
|
3. Следствие двух ошибок индексации: на силовом блоке `Wry` может формироваться,
|
||||||
|
хотя для канала выставлен `Ignor`, и опираться на неверно сопоставленные
|
||||||
|
фазовые уровни. Эту часть логики нельзя считать надёжной без исправления или
|
||||||
|
стендовой проверки.
|
||||||
|
4. В выражении перекоса деление на `Max` записано раньше проверки
|
||||||
|
`Max > Curr_Edge`. При `Max == 0` сначала вычисляется деление `0/0`.
|
||||||
|
Безопаснее сначала проверять порог, затем выполнять деление.
|
||||||
|
5. Все публикуемые значения и пороги хранятся в 16-битных регистрах как целые числа;
|
||||||
|
дробная часть после вычислений отбрасывается.
|
||||||
|
|
||||||
|
## Краткий итог
|
||||||
|
|
||||||
|
- Фазы: два сигнала измеряются, третий восстанавливается как `-x1-x2`.
|
||||||
|
- RMS каждой фазы: корень из экспоненциально усреднённого квадрата.
|
||||||
|
- Общий RMS входа: амплитуда `im_calc()` после фильтра, делённая на `sqrt(2)`.
|
||||||
|
- Обрыв/перекос одной фазы: `Wry`, бит 2; авария: `Stop`, бит 8.
|
||||||
|
- Определение конкретной фазы: по минимальному из трёх RMS-регистров, отдельного
|
||||||
|
фазового бита нет.
|
||||||
|
- Низкое `Utr`: ниже 300 В около 3 секунд — `Out + Stop`.
|
||||||
|
- Высокое `Utr`: выше 420 В — `Hyper + Stop`.
|
||||||
287
PHASE_VOLTAGE_WEAK_POINTS.md
Normal file
287
PHASE_VOLTAGE_WEAK_POINTS.md
Normal file
@@ -0,0 +1,287 @@
|
|||||||
|
# Слабые места расчёта фаз и контроля напряжения
|
||||||
|
|
||||||
|
Документ относится к алгоритмам из `Source/Internal/measure.c`, структуре
|
||||||
|
диагностики из `Source/Internal/Include/measure.h` и карте регистров
|
||||||
|
`Doc/Balsam 167 data stru.xls`.
|
||||||
|
|
||||||
|
## Критические проблемы
|
||||||
|
|
||||||
|
### 1. Неверная индексация парного канала на силовом блоке
|
||||||
|
|
||||||
|
В `Current_count()` используется:
|
||||||
|
|
||||||
|
```c
|
||||||
|
pair = sens_pair[chan];
|
||||||
|
```
|
||||||
|
|
||||||
|
При этом пары каналов инициализируются по абсолютному адресу:
|
||||||
|
|
||||||
|
```c
|
||||||
|
sens_pair[pow_addr+i] = pow_addr+(i^1);
|
||||||
|
```
|
||||||
|
|
||||||
|
Для УМП `pow_addr == 0`, поэтому ошибка не проявляется. На силовом блоке
|
||||||
|
`pow_addr != 0`, и `sens_pair[chan]` остаётся равным самому `chan`.
|
||||||
|
|
||||||
|
Последствия:
|
||||||
|
|
||||||
|
- вместо парного фазового RMS может использоваться текущий канал;
|
||||||
|
- регистры `0x68…0x6D` могут содержать дублирующиеся значения;
|
||||||
|
- расчёт максимальной фазы и диагностика `Wry` могут быть неверными.
|
||||||
|
|
||||||
|
Рекомендуемое исправление требует определить, в какой системе индексов должен
|
||||||
|
работать `lev_count[]`. Вероятный вариант:
|
||||||
|
|
||||||
|
```c
|
||||||
|
pair = sens_pair[sens] - pow_addr;
|
||||||
|
```
|
||||||
|
|
||||||
|
Перед изменением необходимо проверить ожидаемую карту каналов на силовом блоке.
|
||||||
|
|
||||||
|
### 2. Бит `Ignor` проверяется по неверному индексу
|
||||||
|
|
||||||
|
В `Init_sensors_more()` бит устанавливается так:
|
||||||
|
|
||||||
|
```c
|
||||||
|
Modbus[pow_addr+i].bit.bitE = 1;
|
||||||
|
```
|
||||||
|
|
||||||
|
Но в `Current_count()` проверяется:
|
||||||
|
|
||||||
|
```c
|
||||||
|
if (WAKE || sens_error[chan].bit.Ignor) goto fin;
|
||||||
|
```
|
||||||
|
|
||||||
|
Следует проверять диагностическое слово текущего датчика:
|
||||||
|
|
||||||
|
```c
|
||||||
|
if (WAKE || sens_error[sens].bit.Ignor) goto fin;
|
||||||
|
```
|
||||||
|
|
||||||
|
Последствие текущего кода: `Wry` может формироваться для канала, который должен
|
||||||
|
быть исключён из диагностики.
|
||||||
|
|
||||||
|
### 3. Деление на ноль в расчёте перекоса
|
||||||
|
|
||||||
|
Текущее условие:
|
||||||
|
|
||||||
|
```c
|
||||||
|
((Numb - lev_count[chan]) / Numb > 0.3) && (Numb > Curr_Edge)
|
||||||
|
```
|
||||||
|
|
||||||
|
Левая часть вычисляется раньше проверки `Numb > Curr_Edge`. При `Numb == 0`
|
||||||
|
сначала выполняется деление `0/0`.
|
||||||
|
|
||||||
|
Безопасный порядок:
|
||||||
|
|
||||||
|
```c
|
||||||
|
(Numb > Curr_Edge) &&
|
||||||
|
(((Numb - lev_count[chan]) / Numb) > 0.3)
|
||||||
|
```
|
||||||
|
|
||||||
|
Такое же изменение требуется для проверки `lev_count[thrd]`.
|
||||||
|
|
||||||
|
## Высокий приоритет
|
||||||
|
|
||||||
|
### 4. Нет независимых признаков обрыва фаз A, B и C
|
||||||
|
|
||||||
|
Прошивка формирует общий бит:
|
||||||
|
|
||||||
|
| Бит | Маска | Имя |
|
||||||
|
|---:|---:|---|
|
||||||
|
| 2 | `0x0004` | `Wry` |
|
||||||
|
|
||||||
|
Отдельных битов `PhaseA`, `PhaseB`, `PhaseC` нет. Конкретная фаза определяется
|
||||||
|
косвенно по RMS-регистрам `0x68…0x6D`.
|
||||||
|
|
||||||
|
Фаза B физически не измеряется и восстанавливается:
|
||||||
|
|
||||||
|
```text
|
||||||
|
B = -A - C
|
||||||
|
```
|
||||||
|
|
||||||
|
Из-за этого повреждение фазы B не всегда можно однозначно отличить от
|
||||||
|
изменения измеряемых фаз A и C.
|
||||||
|
|
||||||
|
Рекомендуется формировать отдельную маску состояния фаз, например:
|
||||||
|
|
||||||
|
| Бит | Назначение |
|
||||||
|
|---:|---|
|
||||||
|
| 0 | низкий RMS фазы A |
|
||||||
|
| 1 | низкий RMS фазы B |
|
||||||
|
| 2 | низкий RMS фазы C |
|
||||||
|
| 3 | общий перекос фаз |
|
||||||
|
|
||||||
|
### 5. Выдержка восстановленной фазы примерно вдвое короче
|
||||||
|
|
||||||
|
Для восстановленной фазы используется `err_count[thrd]`. Одна и та же ячейка
|
||||||
|
счётчика проверяется при обработке обоих каналов пары. Поэтому она может
|
||||||
|
увеличиваться два раза за один цикл АЦП.
|
||||||
|
|
||||||
|
Ожидаемое время:
|
||||||
|
|
||||||
|
```text
|
||||||
|
11250 / 3750 = 3 секунды
|
||||||
|
```
|
||||||
|
|
||||||
|
Фактическое время для восстановленной фазы при двух вызовах за цикл:
|
||||||
|
|
||||||
|
```text
|
||||||
|
11250 / (2 * 3750) ≈ 1,5 секунды
|
||||||
|
```
|
||||||
|
|
||||||
|
Рекомендуется выполнять проверку всех трёх фаз один раз после обновления всей
|
||||||
|
пары каналов.
|
||||||
|
|
||||||
|
### 6. Для входов U/I не формируется `Tear`
|
||||||
|
|
||||||
|
Бит `Tear` объявлен как бит 0 диагностического слова, но `Current_count()` его
|
||||||
|
не устанавливает. Нет отдельной проверки АЦП на значения около 0 или 4095.
|
||||||
|
|
||||||
|
Последствия:
|
||||||
|
|
||||||
|
- обрыв или короткое замыкание измерительного тракта может выглядеть как
|
||||||
|
обычное отсутствие напряжения;
|
||||||
|
- невозможно отличить пропадание сети от неисправности самого датчика.
|
||||||
|
|
||||||
|
Рекомендуется добавить контроль сырого значения АЦП с выдержкой времени и
|
||||||
|
отдельными порогами около нижней и верхней границ диапазона.
|
||||||
|
|
||||||
|
### 7. Подстройка нуля продолжается после запуска
|
||||||
|
|
||||||
|
Ноль обновляется при условии:
|
||||||
|
|
||||||
|
```c
|
||||||
|
if (WAKE < (WAKE_TIME / 2)) Zero_lev[chan] = Zer;
|
||||||
|
```
|
||||||
|
|
||||||
|
`WAKE` уменьшается до нуля. После запуска выражение `0 < WAKE_TIME/2` остаётся
|
||||||
|
истинным, поэтому `Zero_lev` продолжает изменяться во время работы.
|
||||||
|
|
||||||
|
Риск: медленная постоянная составляющая или неисправность входа может частично
|
||||||
|
компенсироваться алгоритмом нуля.
|
||||||
|
|
||||||
|
Если подстройка нужна только при запуске, условие должно ограничивать окно:
|
||||||
|
|
||||||
|
```c
|
||||||
|
if ((WAKE > 0) && (WAKE < (WAKE_TIME / 2))) {
|
||||||
|
Zero_lev[chan] = Zer;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Если непрерывная подстройка задумана, её следует явно документировать и
|
||||||
|
ограничить допустимым диапазоном изменения.
|
||||||
|
|
||||||
|
## Средний приоритет
|
||||||
|
|
||||||
|
### 8. Жёсткая зона нечувствительности
|
||||||
|
|
||||||
|
Для напряжения применяется:
|
||||||
|
|
||||||
|
```c
|
||||||
|
if (Amplitude < 20) Amplitude = 0;
|
||||||
|
```
|
||||||
|
|
||||||
|
Для тока применяется порог 75. Реальный слабый сигнал ниже порога становится
|
||||||
|
неотличим от полного отсутствия сигнала.
|
||||||
|
|
||||||
|
Рекомендуется использовать отдельные пороги включения и выключения
|
||||||
|
(гистерезис), а также сохранить необрезанное диагностическое значение.
|
||||||
|
|
||||||
|
### 9. Несимметричная запись ошибок пары
|
||||||
|
|
||||||
|
Проверки общего уровня `Level` выполняются только при `!ist`, то есть в
|
||||||
|
нечётном канале пары. Поэтому `Out` и `Hyper` записываются только в одно из двух
|
||||||
|
диагностических слов.
|
||||||
|
|
||||||
|
Например, для напряжения УМП низкий общий уровень записывается в `0x01`, хотя
|
||||||
|
само измерение относится ко всей трёхфазной системе.
|
||||||
|
|
||||||
|
Рекомендуется выделить отдельное диагностическое слово системы или явно
|
||||||
|
дублировать общий признак в оба слова пары.
|
||||||
|
|
||||||
|
### 10. Контроль перенапряжения шкафа ВЭП отключён
|
||||||
|
|
||||||
|
В `Power_count()` проверка:
|
||||||
|
|
||||||
|
```c
|
||||||
|
if (Power > sens_hi_edge[chan])
|
||||||
|
```
|
||||||
|
|
||||||
|
закомментирована. В рабочем коде контролируется только падение напряжения.
|
||||||
|
Неисправность с повышением напряжения не создаёт `Hyper` и `Stop`.
|
||||||
|
|
||||||
|
Перед включением проверки необходимо задать и проверить верхние уставки для
|
||||||
|
всех типов источников питания.
|
||||||
|
|
||||||
|
### 11. Недостаточный гистерезис порогов
|
||||||
|
|
||||||
|
Верхний порог `Utr > 420 В` проверяется непосредственно, без отдельного
|
||||||
|
счётчика и без порога возврата. При шуме около 420 В диагностический бит может
|
||||||
|
часто переключаться.
|
||||||
|
|
||||||
|
Для нижнего порога используется реверсивный счётчик, но состояние также не
|
||||||
|
имеет явно заданных разных порогов срабатывания и возврата.
|
||||||
|
|
||||||
|
Рекомендуется добавить:
|
||||||
|
|
||||||
|
- выдержку времени для перенапряжения;
|
||||||
|
- разные пороги срабатывания и возврата;
|
||||||
|
- насыщение и явный сброс диагностических счётчиков.
|
||||||
|
|
||||||
|
### 12. Потеря дробной части RMS
|
||||||
|
|
||||||
|
`lev_count[]` и Modbus-регистры имеют целочисленный тип. Результат `sqrt()`
|
||||||
|
сохраняется с отбрасыванием дробной части.
|
||||||
|
|
||||||
|
Для текущих порогов в сотнях вольт это не критично, но ухудшает точность
|
||||||
|
индикации и поведение около границы. При необходимости можно передавать
|
||||||
|
значения в десятых долях единицы.
|
||||||
|
|
||||||
|
## Дополнительные риски
|
||||||
|
|
||||||
|
### Разная задержка аварии у парных источников
|
||||||
|
|
||||||
|
В `Power_count()` бит `Stop` устанавливается, если `Out` уже присутствует у
|
||||||
|
парного канала. Из-за последовательной обработки второй канал пары может
|
||||||
|
получить `Stop` раньше первого. Первый получит его только при следующем опросе.
|
||||||
|
|
||||||
|
### Одиночный источник спарен сам с собой
|
||||||
|
|
||||||
|
Для непарных источников `sens_pair[chan] == chan`. После первого обнаружения
|
||||||
|
`Out` бит `Stop` появится при следующем вызове, когда будет прочитано собственное
|
||||||
|
предыдущее состояние `Out`. Это неочевидная зависимость от предыдущего цикла.
|
||||||
|
|
||||||
|
### Уставки доступны для записи без локальной проверки диапазона
|
||||||
|
|
||||||
|
Команда Modbus записывает переданное значение непосредственно в массив
|
||||||
|
регистров. В расчёте не видно проверки допустимого диапазона порогов. Ошибочная
|
||||||
|
уставка может полностью отключить контроль или вызвать постоянную аварию.
|
||||||
|
|
||||||
|
## Рекомендуемый порядок исправлений
|
||||||
|
|
||||||
|
1. Исправить индексацию `sens_pair` и `sens_error[].Ignor`.
|
||||||
|
2. Переставить проверку `Numb > Curr_Edge` перед делением.
|
||||||
|
3. Перенести расчёт и диагностику трёх фаз в один вызов на пару каналов.
|
||||||
|
4. Добавить отдельные признаки состояния фаз A/B/C.
|
||||||
|
5. Добавить диагностику предельных значений АЦП (`Tear`).
|
||||||
|
6. Определить требуемый режим подстройки нуля и ограничить его.
|
||||||
|
7. Добавить выдержку и гистерезис верхнего/нижнего напряжения.
|
||||||
|
8. Проверить все изменения стендовыми тестами: нормальная сеть, обрыв каждой
|
||||||
|
фазы, перекос, пропадание обоих фидеров, пониженное и повышенное напряжение.
|
||||||
|
|
||||||
|
## Минимальный набор тестов
|
||||||
|
|
||||||
|
| Тест | Ожидаемый результат |
|
||||||
|
|---|---|
|
||||||
|
| Номинальное трёхфазное напряжение | `Wry=0`, `Out=0`, `Hyper=0`, `Stop=0` |
|
||||||
|
| Обрыв измеряемой фазы A | снижение RMS A, отдельный признак A, затем `Stop` |
|
||||||
|
| Обрыв измеряемой фазы C | снижение RMS C, отдельный признак C, затем `Stop` |
|
||||||
|
| Нарушение восстановленной фазы B | снижение вычисленного RMS B без двойной скорости счётчика |
|
||||||
|
| Перекос ровно 30% | проверка граничного условия `>` |
|
||||||
|
| `Max = 0` | отсутствие деления на ноль |
|
||||||
|
| `Utr < 300 В` | `Out`, после выдержки `Stop` |
|
||||||
|
| `Utr > 420 В` | `Hyper`, после заданной выдержки `Stop` |
|
||||||
|
| АЦП около 0 или 4095 | `Tear`, отличие от пропадания сети |
|
||||||
|
| Канал с `Ignor=1` | отсутствие новых автоматических ошибок этого канала |
|
||||||
|
| Отключённый канал `Bypas=1` | нулевые данные, сохранён только `Bypas` |
|
||||||
29
README_CCS12.md
Normal file
29
README_CCS12.md
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
# Сборка проекта в Code Composer Studio 12
|
||||||
|
|
||||||
|
Проект поддерживает обе IDE параллельно:
|
||||||
|
|
||||||
|
- CCS 3 использует корневой файл `UKSSTMS320F28335.pjt`;
|
||||||
|
- CCS 12 использует проект из каталога `UKSSTMS320F28335`.
|
||||||
|
|
||||||
|
Файлы CCS 3 не изменялись. Объектные файлы и итоговые образы двух систем
|
||||||
|
сборки разнесены по разным каталогам и не перезаписывают друг друга.
|
||||||
|
|
||||||
|
## Импорт
|
||||||
|
|
||||||
|
1. Откройте **File → Import → Code Composer Studio → CCS Projects**.
|
||||||
|
2. В **Select search-directory** укажите каталог репозитория.
|
||||||
|
3. Выберите проект **UKSSTMS320F28335** и нажмите **Finish**.
|
||||||
|
4. Выберите конфигурацию **Debug** или **Release** и выполните **Build Project**.
|
||||||
|
|
||||||
|
Проект настроен для `TMS320F28335`, COFF ABI и C2000 Compiler
|
||||||
|
`22.6.0.LTS`, входящего в CCS 12.3.
|
||||||
|
|
||||||
|
## Результаты сборки
|
||||||
|
|
||||||
|
- CCS 3 продолжает использовать прежние каталоги `Debug`, `Release` и `Bin`.
|
||||||
|
- CCS 12 Debug создаёт `.out`, `.hex`, `.bin` и `.map` в `Bin/CCS12`.
|
||||||
|
- CCS 12 Release создаёт `UKSSTMS320F28335_Release.out` и
|
||||||
|
`UKSSTMS320F28335_Release.map` в `Bin/CCS12`.
|
||||||
|
|
||||||
|
Все пути к исходникам заданы относительно каталога проекта через `SRC_ROOT`;
|
||||||
|
перенос репозитория в другой каталог не требует изменения настроек.
|
||||||
@@ -2,9 +2,9 @@
|
|||||||
<?ccsproject version="1.0"?>
|
<?ccsproject version="1.0"?>
|
||||||
<projectOptions>
|
<projectOptions>
|
||||||
<ccsVersion value="12.3.0"/>
|
<ccsVersion value="12.3.0"/>
|
||||||
<deviceVariant value="TMS320C28XX"/>
|
<deviceVariant value="TMS320C28XX.TMS320F28335"/>
|
||||||
<deviceFamily value="C2000"/>
|
<deviceFamily value="C2000"/>
|
||||||
<deviceEndianness value="UNKNOWN"/>
|
<deviceEndianness value="little"/>
|
||||||
<codegenToolVersion value="22.6.0.LTS"/>
|
<codegenToolVersion value="22.6.0.LTS"/>
|
||||||
<isElfFormat value="false"/>
|
<isElfFormat value="false"/>
|
||||||
<rts value=""/>
|
<rts value=""/>
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
1
UKSSTMS320F28335/.gitignore
vendored
1
UKSSTMS320F28335/.gitignore
vendored
@@ -3,3 +3,4 @@
|
|||||||
/.launches/
|
/.launches/
|
||||||
/targetConfigs/
|
/targetConfigs/
|
||||||
/project.log
|
/project.log
|
||||||
|
/Release/
|
||||||
|
|||||||
@@ -14,3 +14,18 @@ encoding//Debug/objects.mk=UTF-8
|
|||||||
encoding//Debug/sources.mk=UTF-8
|
encoding//Debug/sources.mk=UTF-8
|
||||||
encoding//Debug/subdir_rules.mk=UTF-8
|
encoding//Debug/subdir_rules.mk=UTF-8
|
||||||
encoding//Debug/subdir_vars.mk=UTF-8
|
encoding//Debug/subdir_vars.mk=UTF-8
|
||||||
|
encoding//Release/Libraries/subdir_rules.mk=UTF-8
|
||||||
|
encoding//Release/Libraries/subdir_vars.mk=UTF-8
|
||||||
|
encoding//Release/Source/External/v120/DSP2833x_common/source/subdir_rules.mk=UTF-8
|
||||||
|
encoding//Release/Source/External/v120/DSP2833x_common/source/subdir_vars.mk=UTF-8
|
||||||
|
encoding//Release/Source/External/v120/DSP2833x_headers/cmd/subdir_rules.mk=UTF-8
|
||||||
|
encoding//Release/Source/External/v120/DSP2833x_headers/cmd/subdir_vars.mk=UTF-8
|
||||||
|
encoding//Release/Source/External/v120/DSP2833x_headers/source/subdir_rules.mk=UTF-8
|
||||||
|
encoding//Release/Source/External/v120/DSP2833x_headers/source/subdir_vars.mk=UTF-8
|
||||||
|
encoding//Release/Source/Internal/subdir_rules.mk=UTF-8
|
||||||
|
encoding//Release/Source/Internal/subdir_vars.mk=UTF-8
|
||||||
|
encoding//Release/makefile=UTF-8
|
||||||
|
encoding//Release/objects.mk=UTF-8
|
||||||
|
encoding//Release/sources.mk=UTF-8
|
||||||
|
encoding//Release/subdir_rules.mk=UTF-8
|
||||||
|
encoding//Release/subdir_vars.mk=UTF-8
|
||||||
|
|||||||
@@ -1,34 +1,14 @@
|
|||||||
@echo off
|
@echo off
|
||||||
setlocal
|
setlocal
|
||||||
|
|
||||||
for %%I in ("%~dp0..") do set "SRC_ROOT=%%~fI"
|
set "HEX_TOOL=%~1"
|
||||||
|
set "OUT_FILE=%~2"
|
||||||
|
set "BIN_DIR=%~3"
|
||||||
|
|
||||||
:process_arg
|
if not exist "%BIN_DIR%" mkdir "%BIN_DIR%"
|
||||||
if "%1"=="" goto end_process_arg
|
|
||||||
set name=%1
|
|
||||||
set value=
|
|
||||||
|
|
||||||
:process_arg_value
|
"%HEX_TOOL%" "%OUT_FILE%" -boot -sci8 -map "%BIN_DIR%\UKSSTMS320F28335.map" -o "%BIN_DIR%\UKSSTMS320F28335.hex" -i
|
||||||
if NOT "%value%"=="" set value=%value% %2
|
if errorlevel 1 exit /b %errorlevel%
|
||||||
if "%value%"=="" set value=%2
|
|
||||||
shift
|
|
||||||
if "%2"=="!" goto set_arg
|
|
||||||
if "%2"=="" goto set_arg
|
|
||||||
goto process_arg_value
|
|
||||||
|
|
||||||
:set_arg
|
"%HEX_TOOL%" "%OUT_FILE%" -boot -sci8 -map "%BIN_DIR%\UKSSTMS320F28335.map" -o "%BIN_DIR%\UKSSTMS320F28335.bin" -b
|
||||||
set %name%=%value%
|
exit /b %errorlevel%
|
||||||
shift
|
|
||||||
shift
|
|
||||||
goto process_arg
|
|
||||||
:end_process_arg
|
|
||||||
|
|
||||||
echo. > temp_postBuildStep_Debug.bat
|
|
||||||
|
|
||||||
echo "%SRC_ROOT%\Bin\hex2000.exe" "%SRC_ROOT%\Bin\UKSSTMS320F28335.out" -boot -sci8 -map "%SRC_ROOT%\Bin\UKSSTMS320F28335.map" -o "%SRC_ROOT%\Bin\UKSSTMS320F28335.hex" -i >> temp_postBuildStep_Debug.bat
|
|
||||||
echo "%SRC_ROOT%\Bin\hex2000.exe" "%SRC_ROOT%\Bin\UKSSTMS320F28335.out" -boot -sci8 -map "%SRC_ROOT%\Bin\UKSSTMS320F28335.map" -o "%SRC_ROOT%\Bin\UKSSTMS320F28335.bin" -b >> temp_postBuildStep_Debug.bat
|
|
||||||
|
|
||||||
call temp_postBuildStep_Debug.bat
|
|
||||||
del temp_postBuildStep_Debug.bat
|
|
||||||
|
|
||||||
endlocal
|
|
||||||
|
|||||||
Reference in New Issue
Block a user