58 lines
2.7 KiB
Python
58 lines
2.7 KiB
Python
"""Синтетические записи УМП для проверки графиков без подключения платы."""
|
||
import math
|
||
|
||
from set_devices import ump_logger as codec
|
||
|
||
|
||
def sample(time_ms, period_ms=20):
|
||
"""Повторяемый цикл: пуск, разгон 6–16 мА, отключение и спад тока."""
|
||
phase = time_ms % 6000
|
||
started = 1000 <= phase < 5000
|
||
reset = 5000 <= phase < 5300
|
||
# Как в прошивке: фронт команды включает выход на 1000 мс.
|
||
start_out = 1000 <= phase < 2000
|
||
stop_out = 5000 <= phase < 6000
|
||
ramp = max(0, min(2500, phase - 1000))
|
||
if started:
|
||
current = 6 + 10 * ramp / 2500 + 0.2 * math.sin(phase / 90)
|
||
elif phase >= 5000:
|
||
current = 4 + 12 * max(0, 1 - (phase - 5000) / 300)
|
||
else:
|
||
current = 4
|
||
|
||
words = [0] * codec.WORDS
|
||
words[0], words[1] = time_ms & 65535, (time_ms >> 16) & 65535
|
||
words[2] = 1 | (0x100 if 5000 <= phase < 5000 + period_ms else 0)
|
||
words[3] = (int(started) << 7) | (int(reset) << 6)
|
||
words[4] = int(1200 <= phase < 5100) | (int(started) << 1) | (int(reset) << 2)
|
||
words[5] = int(start_out) | (int(stop_out) << 1) | (int(started) << 2)
|
||
words[6] = (2000 - phase) if start_out else ((6000 - phase) if stop_out else 0)
|
||
words[7] = max(0, 250 - phase)
|
||
words[8] = round(500 + (current - 4) * 3000 / 16)
|
||
words[9] = round(current * 10)
|
||
for channel in range(4):
|
||
measured = round(120 * math.sin(phase / (180 + channel * 70) + channel))
|
||
words[10 + channel] = measured & 65535
|
||
words[14 + channel] = (1 << channel) if 5100 <= phase < 5400 else 0
|
||
words[36 + channel] = 2048 + measured * 4
|
||
words[18:24] = [0xE07F, words[3], 6, 16, (time_ms // 100) & 65535, 0]
|
||
words[24:31] = [6, 16, 500, 3500, 2000, 500, 3500]
|
||
words[31:36] = [ramp if started else 0, 2500, 60, 160, round(ramp * 1000 / 2500)]
|
||
return codec.sample(words)
|
||
|
||
|
||
def capture(period_ms):
|
||
"""Пример архива: до 399 точек предыстории, отключение и 1 с после него."""
|
||
before = list(range(5000, -1, -period_ms))[1:400][::-1]
|
||
after = list(range(5000 + period_ms, 6000, period_ms)) + [6000]
|
||
available = codec.CAPACITY - len(before) - 1
|
||
truncated = len(after) > available
|
||
if truncated:
|
||
after = after[:available - 1] + after[-1:]
|
||
records = [sample(t, period_ms) for t in before + [5000] + after]
|
||
# Последний снимок относится к концу постинтервала, а не новому циклу.
|
||
records[-1]['event'] = 5 | (0x200 if truncated else 0)
|
||
records[-1]['post_truncated'] = int(truncated)
|
||
records[-1]['off_trigger'] = 0
|
||
return records
|