Record PM67 ZPT voltages in UMP logger v3
This commit is contained in:
@@ -35,10 +35,10 @@ EEPROM не используется: под отключением в этой
|
||||
## Память и точность
|
||||
|
||||
Использована существующая секция `.logg` по адресу 0x200000: 64000
|
||||
16-битных слов. Два банка по 800 записей × 40 слов занимают её целиком.
|
||||
Текущий банк кольцевой. При триггере сохраняются последние до 399 записей,
|
||||
16-битных слов. Два банка по 760 записей × 42 слова занимают 63840 слов (160 слов свободны).
|
||||
Текущий банк кольцевой. При триггере сохраняются последние до 379 записей,
|
||||
добавляется событие отключения, оставшаяся половина банка отведена
|
||||
постинтервалу. При 20 мс это до примерно 8 секунд до отключения и 1 секунды
|
||||
постинтервалу. При 20 мс это до примерно 7.6 секунды до отключения и 1 секунды
|
||||
после. Дополнительные события CAN и дискретов сокращают временную глубину.
|
||||
|
||||
При интенсивном потоке событий или периоде 1 мс постинтервал может заполнить
|
||||
@@ -51,7 +51,7 @@ EEPROM не используется: под отключением в этой
|
||||
одинаковую отметку; порядок сохраняется порядком записей. На перезапуске
|
||||
регистратора счётчик продолжает прежнюю шкалу, при перезагрузке платы — 0.
|
||||
|
||||
Онлайн-опрос возвращает три последних записи каждые 40 мс. Он не гарантирует
|
||||
Онлайн-опрос возвращает две последние записи каждые 40 мс. Он не гарантирует
|
||||
передачу каждого события при высоком CAN-трафике, медленном UART или паузах
|
||||
GUI. Номера записей позволяют убрать дубликаты и явно показать пропуски.
|
||||
Полный сохранившийся фрагмент следует читать кнопкой архива. Частота 20 мс
|
||||
@@ -63,7 +63,7 @@ GUI. Номера записей позволяют убрать дублика
|
||||
EEPROM, выделения памяти или копирования целого банка. Реальную задержку
|
||||
прерываний и длительность критических секций нужно измерить на F28335.
|
||||
|
||||
## Состав записи: 40 слов
|
||||
## Состав записи v3: 42 слова
|
||||
|
||||
| Слова | Данные | Единицы/смысл |
|
||||
|---|---|---|
|
||||
@@ -91,6 +91,16 @@ EEPROM, выделения памяти или копирования целог
|
||||
| 33–34 | эффективные dac_go/dac_stop + 4 | 0.1 мА после ограничений алгоритма; GUI переводит в мА |
|
||||
| 35 | kod | целочисленное положение, используемое Anal_output |
|
||||
| 36–39 | ADC_table[0..3] | значения таблицы АЦП в исходном масштабе прошивки |
|
||||
| 40 | ЗПТ1: U1 + U2, ПМ67 регистр 306 / индекс 305 | исходное 16-битное слово без пересчёта |
|
||||
| 41 | ЗПТ2: U3 + U4, ПМ67 регистр 9 / индекс 8 | исходное 16-битное слово без пересчёта |
|
||||
|
||||
Напряжения принимаются из технологических CAN-кадров с нулевыми индексами
|
||||
305 и 8. Учитываются все три позиции и биты маски 0x8000/0x4000/0x2000.
|
||||
Они хранятся отдельно от массива modbus[0..127], обновляются и при выключенном
|
||||
логгере. Запись содержит последние принятые значения; до первого приёма — 0.
|
||||
При потере связи остаётся последнее значение: отдельного признака свежести нет.
|
||||
Масштаб и знаковость физического напряжения не заданы исходной таблицей;
|
||||
SetGUI показывает исходное беззнаковое слово, коэффициент задаётся в интерфейсе.
|
||||
|
||||
**Отправленный код ЦАП не является измеренным током выхода.** В этом проекте
|
||||
не установлено, какой вход аппаратно измеряет ток ЦАП. При включённом
|
||||
@@ -116,9 +126,9 @@ FC03, 0x1000, 16 слов:
|
||||
|
||||
| Смещение | Значение |
|
||||
|---|---|
|
||||
| 0,1 | 0x554D, версия 2 |
|
||||
| 0,1 | 0x554D, версия 3 |
|
||||
| 2,3 | состояние и число записей выбранного источника |
|
||||
| 4,5 | 40 слов в записи, 800 записей в банке |
|
||||
| 4,5 | 42 слова в записи, 760 записей в банке |
|
||||
| 6 | период периодических снимков, мс |
|
||||
| 7,8 | счётчик времени, младшее/старшее слово |
|
||||
| 9,10 | Desk (требуется 6 / dsk_LOAD), Mode |
|
||||
@@ -133,25 +143,28 @@ FC03, 0x1000, 16 слов:
|
||||
FC06:
|
||||
- 0x1000: 1 — новый текущий журнал, 0 — остановить его;
|
||||
- 0x1001: период 1..1000, менять только при остановленном журнале;
|
||||
- 0x1002: хронологический индекс первой записи окна 0..799;
|
||||
- 0x1002: хронологический индекс первой записи окна 0..759;
|
||||
- 0x1003: источник окна, 0 — текущий остановленный банк, 1 — архив отключения.
|
||||
|
||||
FC03, 0x1010, до 120 слов: окно до трёх записей от установленного индекса.
|
||||
FC03, 0x1010, до 120 слов: окно от установленного индекса; для целых записей v3 читать 42 или 84 слова.
|
||||
CAN допускает 42/84 и прежние размеры 40/80/120; RTU допускает 1..120 слов.
|
||||
Чтение текущего банка этим окном во время записи не выдаёт изменяющиеся
|
||||
данные. GUI сначала останавливает его; архив можно читать при работающем
|
||||
текущем банке. После всех блоков GUI повторно проверяет поколение архива;
|
||||
при замене во время чтения результат не подменяет предыдущий график.
|
||||
|
||||
FC03, 0x1100, ровно 124 слова: онлайн-блок. Слова 0,1 — 32-битный номер
|
||||
первой записи, 2 — число записей 0..3, 3 — поколение архива, далее до трёх
|
||||
записей по 40 слов. Неиспользованные слова равны нулю. Окно онлайн не
|
||||
первой записи, 2 — число записей 0..2, 3 — поколение архива, далее до двух
|
||||
записей по 42 слова. Неиспользованные слова равны нулю. Окно онлайн не
|
||||
зависит от курсора/выбора архива. Разделение 0x1010 и 0x1100 предотвращает
|
||||
пересечение двух окон.
|
||||
|
||||
Недопустимые диапазоны и значения возвращают исключения Modbus 2/3.
|
||||
CRC и разбор стандартного ответа GUI используют существующее общее ядро.
|
||||
Расширение описано отдельно в core/ump_logger.py, без изменения общей
|
||||
библиотеки и без необходимости пересобирать её DLL.
|
||||
SetGUI распознаёт v2 (40 слов, 800 записей) и v3 (42 слова, 760 записей).
|
||||
Для v2 новые напряжения недоступны (NaN), для v3 доступны графики и CSV.
|
||||
CAN-валидация общей библиотеки расширена размерами 42/84 слова.
|
||||
Исходники протокола подключаются к прошивке из templates/c/set-protocol.
|
||||
|
||||
## Проверка и запуск
|
||||
|
||||
@@ -176,3 +189,6 @@ TI. Отдельно выполнена синтаксическая прове
|
||||
подать откл. → через секунду прочитать архив → сверить код ЦАП, ток внешним
|
||||
измерителем и физические входы/выходы; затем повторить с разрывом RS.
|
||||
Период 1 мс проверить отдельно под максимальной CAN-нагрузкой.
|
||||
|
||||
Для сборки v3 нужен templates/main начиная с коммита c0ee7c4
|
||||
(поддержка CAN-чтения 42/84 слов и порт TMS320F28335).
|
||||
|
||||
@@ -33,12 +33,13 @@ extern LOG Log;
|
||||
void clear_mem();
|
||||
|
||||
/* Ëîããåð ÓÌÏ: îòäåëüíîå àäðåñíîå ïðîñòðàíñòâî Modbus, áåç èçìåíåíèÿ
|
||||
* 128 òåõíîëîãè÷åñêèõ ðåãèñòðîâ. Äâà áàíêà ïî 800 çàïèñåé:
|
||||
* 128 òåõíîëîãè÷åñêèõ ðåãèñòðîâ. Äâà áàíêà ïî 760 çàïèñåé:
|
||||
* òåêóùèé êîëüöåâîé æóðíàë è çàôèêñèðîâàííûé ôðàãìåíò îòêëþ÷åíèÿ. */
|
||||
#define UMP_LOG_BASE 0x1000U
|
||||
#define UMP_LOG_DATA 0x1010U
|
||||
#define UMP_LOG_WORDS 40U
|
||||
#define UMP_LOG_CAPACITY 800U
|
||||
#define UMP_LOG_WORDS 42U
|
||||
#define UMP_LOG_CAPACITY 760U
|
||||
#define UMP_LOG_LIVE_RECORDS (120U / UMP_LOG_WORDS)
|
||||
#define UMP_LOG_LIVE 0x1100U
|
||||
extern unsigned int ump_dac_ramp, ump_dac_duration, ump_dac_go10, ump_dac_stop10, ump_dac_position;
|
||||
void ump_log_tick(void);
|
||||
|
||||
@@ -43,6 +43,8 @@ static unsigned int ump_bank, ump_archive_bank = 1;
|
||||
static unsigned int ump_archive_count, ump_archive_next, ump_generation;
|
||||
static unsigned int ump_source, ump_post, ump_post_dropped;
|
||||
static unsigned int ump_can_header, ump_can_data[3], ump_can_count;
|
||||
/* Latest PM67 sums: register 306 (index 305), register 9 (index 8). */
|
||||
static unsigned int ump_pm67_voltage[2];
|
||||
static unsigned int ump_prev_commands, ump_prev_inputs, ump_prev_outputs;
|
||||
extern int CanTimeOutErrorTR;
|
||||
/* Äèàãíîñòèêà âíóòðåííèõ ïåðåìåííûõ ðàçãîíà. Îáíîâëÿåòñÿ ñàìèì Load_runner,
|
||||
@@ -113,6 +115,7 @@ static void ump_capture(unsigned int reason)
|
||||
p[31] = ump_dac_ramp; p[32] = ump_dac_duration;
|
||||
p[33] = ump_dac_go10; p[34] = ump_dac_stop10; p[35] = ump_dac_position;
|
||||
for (i = 0; i < 4; i++) p[36+i] = ADC_table[i];
|
||||
p[40] = ump_pm67_voltage[0]; p[41] = ump_pm67_voltage[1];
|
||||
ump_prev_commands = commands; ump_prev_inputs = p[4]; ump_prev_outputs = p[5];
|
||||
ump_next++;
|
||||
if (ump_next == UMP_LOG_CAPACITY) ump_next = 0;
|
||||
@@ -161,9 +164,20 @@ void ump_log_io(void)
|
||||
* íîâûå êîìàíäû, à òàêæå èñõîäíûé àäðåñ/ìàñêó è âñå òðè ñëîâà êàäðà. */
|
||||
void ump_log_can(unsigned int header, unsigned int a, unsigned int b, unsigned int c)
|
||||
{
|
||||
unsigned int saved;
|
||||
if (ump_state != 1 || Desk != dsk_LOAD) return;
|
||||
unsigned int saved, i, address, mask, data[3];
|
||||
if (Desk != dsk_LOAD) return;
|
||||
saved = __disable_interrupts();
|
||||
data[0] = a; data[1] = b; data[2] = c;
|
||||
address = header & 0x1FFFU;
|
||||
mask = 0x8000U;
|
||||
/* Track reception even while recording is stopped. Each mask bit
|
||||
* refers to its own address, including disabled words in between. */
|
||||
for (i = 0; i < 3; i++, address++, mask >>= 1) {
|
||||
if (!(header & mask)) continue;
|
||||
if (address == 305U) ump_pm67_voltage[0] = data[i];
|
||||
if (address == 8U) ump_pm67_voltage[1] = data[i];
|
||||
}
|
||||
if (ump_state != 1) { __restore_interrupts(saved); return; }
|
||||
ump_can_header = header;
|
||||
ump_can_data[0] = a; ump_can_data[1] = b; ump_can_data[2] = c;
|
||||
ump_can_count++;
|
||||
@@ -227,7 +241,7 @@ unsigned int ump_log_read(unsigned int address)
|
||||
unsigned long first;
|
||||
switch (address) {
|
||||
case UMP_LOG_BASE: return 0x554D;
|
||||
case UMP_LOG_BASE+1: return 2;
|
||||
case UMP_LOG_BASE+1: return 3;
|
||||
case UMP_LOG_BASE+2: return ump_source ? 3 : ump_state;
|
||||
case UMP_LOG_BASE+3: return ump_source ? ump_archive_count : ump_count;
|
||||
case UMP_LOG_BASE+4: return UMP_LOG_WORDS;
|
||||
@@ -250,7 +264,7 @@ unsigned int ump_log_read(unsigned int address)
|
||||
/* Ïîñëåäíèå òðè çàïèñè äëÿ îíëàéí-ãðàôèêà, áåç îñòàíîâêè è áåç
|
||||
* èçìåíåíèÿ êóðñîðà àðõèâíîãî ÷òåíèÿ. Ïåðâûå äâà ñëîâà — èõ íîìåð. */
|
||||
if (address >= UMP_LOG_LIVE && address < UMP_LOG_LIVE+124) {
|
||||
count = ump_count < 3 ? ump_count : 3;
|
||||
count = ump_count < UMP_LOG_LIVE_RECORDS ? ump_count : UMP_LOG_LIVE_RECORDS;
|
||||
first = ump_sequence - count;
|
||||
offset = address - UMP_LOG_LIVE;
|
||||
if (offset == 0) return (unsigned int)first;
|
||||
|
||||
@@ -20,12 +20,23 @@ __declspec(dllexport) int run_tests(void)
|
||||
modbus[127] = 0x80;
|
||||
modbus[0x50] = 6; modbus[0x51] = 16;
|
||||
modbus[0x7B] = 1234; modbus[0x1C] = 160;
|
||||
/* PM67 reception is independent of recording; all three CAN slots work. */
|
||||
ump_log_can(0x8000U | 305U, 0xFEDCU, 0, 0);
|
||||
ump_log_can(0x4000U | 7U, 0, 456, 0);
|
||||
CHECK(ump_pm67_voltage[0] == 0xFEDCU && ump_pm67_voltage[1] == 456);
|
||||
ump_log_can(305U, 1, 2, 3); /* Masked-out word must not overwrite. */
|
||||
ump_log_can(0x2000U | 303U, 0, 0, 123);
|
||||
ump_log_can(0x2000U | 6U, 0, 0, 789);
|
||||
CHECK(ump_pm67_voltage[0] == 123 && ump_pm67_voltage[1] == 789);
|
||||
ump_log_can(0x8000U | 306U, 999, 0, 0); /* Not a one-based CAN address. */
|
||||
CHECK(ump_log_write(UMP_LOG_BASE, 1));
|
||||
CHECK(ump_word(0, 0, 40) == 123 && ump_word(0, 0, 41) == 789);
|
||||
CHECK(2UL * UMP_LOG_CAPACITY * UMP_LOG_WORDS <= LOG_PAGE_LEN);
|
||||
CHECK(!ump_log_write(UMP_LOG_BASE, 1));
|
||||
CHECK(!ump_log_write(UMP_LOG_BASE+1, 20));
|
||||
for (i=0; i<900; i++) ump_log_tick();
|
||||
CHECK(ump_count == UMP_LOG_CAPACITY);
|
||||
CHECK(ump_word(0, 0, 0) == 101);
|
||||
CHECK(ump_word(0, 0, 0) == 901-UMP_LOG_CAPACITY);
|
||||
CHECK(ump_word(0, UMP_LOG_CAPACITY-1, 0) == 900);
|
||||
CHECK(ump_word(0, 0, 8) == 1234);
|
||||
CHECK(ump_word(0, 0, 24) == 6);
|
||||
@@ -43,6 +54,11 @@ __declspec(dllexport) int run_tests(void)
|
||||
CHECK(ump_word(1, UMP_LOG_CAPACITY/2-1, 2) == 0x102);
|
||||
CHECK(ump_word(1, UMP_LOG_CAPACITY-1, 2) == 0x205);
|
||||
CHECK(ump_count == 0 && ump_state == 1);
|
||||
CHECK(ump_word(1, UMP_LOG_CAPACITY-1, 40) == 123);
|
||||
CHECK(ump_word(1, UMP_LOG_CAPACITY-1, 41) == 789);
|
||||
ump_log_can(0x8000U | 305U, 999, 0, 0);
|
||||
CHECK(ump_word(0, ump_count-1, 40) == 999);
|
||||
CHECK(ump_word(1, UMP_LOG_CAPACITY-1, 40) == 123);
|
||||
generation = ump_generation;
|
||||
archived = ump_word(1, UMP_LOG_CAPACITY-1, 0);
|
||||
sequence = ump_sequence;
|
||||
@@ -50,8 +66,8 @@ __declspec(dllexport) int run_tests(void)
|
||||
CHECK(ump_word(1, UMP_LOG_CAPACITY-1, 0) == archived);
|
||||
CHECK(ump_generation == generation);
|
||||
CHECK(ump_sequence == sequence + 200);
|
||||
CHECK(ump_log_read(UMP_LOG_LIVE+2) == 3);
|
||||
CHECK(ump_log_read(UMP_LOG_LIVE+4) == ump_time-2);
|
||||
CHECK(ump_log_read(UMP_LOG_LIVE+2) == UMP_LOG_LIVE_RECORDS);
|
||||
CHECK(ump_log_read(UMP_LOG_LIVE+4) == ump_time-(UMP_LOG_LIVE_RECORDS-1));
|
||||
CHECK(ump_log_write(UMP_LOG_BASE+3, 1));
|
||||
CHECK(ump_log_write(UMP_LOG_BASE+2, UMP_LOG_CAPACITY-1));
|
||||
CHECK(ump_log_read(UMP_LOG_DATA) == archived);
|
||||
@@ -72,9 +88,15 @@ __declspec(dllexport) int run_tests(void)
|
||||
/* CAN читает те же регистры и формирует цельный снимок из 124 слов.
|
||||
* Запись по старым технологическим адресам через сервис запрещена. */
|
||||
length = ump_can_prepare(3, UMP_LOG_BASE, 16, reply, &error);
|
||||
CHECK(!error && length == 16 && reply[0] == 0x554D && reply[1] == 2);
|
||||
CHECK(!error && length == 16 && reply[0] == 0x554D && reply[1] == 3);
|
||||
length = ump_can_prepare(3, UMP_LOG_LIVE, 124, reply, &error);
|
||||
CHECK(!error && length == 124);
|
||||
CHECK(reply[2] <= UMP_LOG_LIVE_RECORDS);
|
||||
for (i=4+reply[2]*UMP_LOG_WORDS; i<124; i++) CHECK(reply[i] == 0);
|
||||
length = ump_can_prepare(3, UMP_LOG_DATA, 84, reply, &error);
|
||||
CHECK(!error && length == 84);
|
||||
length = ump_can_prepare(3, UMP_LOG_DATA, 42, reply, &error);
|
||||
CHECK(!error && length == 42);
|
||||
ump_can_prepare(3, UMP_LOG_LIVE, 126, reply, &error);
|
||||
CHECK(error == 2);
|
||||
ump_can_prepare(6, 127, 0x80, reply, &error);
|
||||
|
||||
Reference in New Issue
Block a user