This commit is contained in:
Vincent Hanewinkel 2025-08-14 22:40:44 +02:00
parent 5eb500644c
commit 559f512bee

View File

@ -1,5 +1,5 @@
# device_controller.py # device_controller.py
import threading, queue, time, math, os, csv import threading, queue, time, math, os, csv, statistics
RAW_SAMPLE_RATE = 100_000.0 # M1K nominal RAW_SAMPLE_RATE = 100_000.0 # M1K nominal
CHUNK_RAW = 2000 # ~20 ms pro Chunk pro Gerät CHUNK_RAW = 2000 # ~20 ms pro Chunk pro Gerät
@ -40,92 +40,66 @@ class DeviceController:
# -------- Reader: liest roh und decimiert -------- # -------- Reader: liest roh und decimiert --------
def reader_loop(self): def reader_loop(self):
print(f"[{self.serial}] Reader start (decim={self.decim}, eff_rate={self.eff_rate:.0f} S/s)") filter_window_size = 10 # wie in deinem Logger
interval = 0.1 # 10 Hz Mess-Update
last_log_time = 0
while not self.stop_evt.is_set(): while not self.stop_evt.is_set():
# Kommandos # Start/Stop Kommandos
try: try:
cmd, _ = self.cmdq.get_nowait() cmd, _ = self.cmdq.get_nowait()
if cmd == "start" and not self.running: if cmd == "start" and not self.running:
self.sm.start() # Session ggf. starten self.sm.start()
self.running = True self.running = True
elif cmd == "stop" and self.running: elif cmd == "stop" and self.running:
self.sm.stop()
self.running = False self.running = False
self.sm.stop() # Session ggf. stoppen
except queue.Empty: except queue.Empty:
pass pass
if not self.running: if not self.running:
time.sleep(0.02) time.sleep(0.05)
continue continue
try: try:
# pysmu: Liste von [VA, IA, VB, IB] # Rohdaten holen (filter_window_size Samples)
samples = self.dev.read(CHUNK_RAW, -1) # je nach Version evtl. .read(CHUNK_RAW) samples = self.dev.read(filter_window_size, -1)
if not samples: if not samples:
time.sleep(0.001) time.sleep(interval)
continue continue
# Kanäle extrahieren # Kanäle extrahieren & mitteln
va_raw = [row[0] for row in samples] va = statistics.mean(row[0] for row in samples)
vb_raw = [row[2] for row in samples] vb = statistics.mean(row[2] for row in samples)
# -------- Decimation: jedes N-te Sample -------- now = time.time()
if self.decim > 1: if now - last_log_time >= 1.0: # nur jede Sekunde loggen
va = va_raw[::self.decim] self.writer_q.put((now, va, vb))
vb = vb_raw[::self.decim] last_log_time = now
else:
va, vb = va_raw, vb_raw
# In Writer-Queue; bei voller Queue ältestes verwerfen (Ringpuffer)
try:
self.writer_q.put_nowait((va, vb))
except queue.Full:
try:
_ = self.writer_q.get_nowait() # drop oldest
except queue.Empty:
pass
finally:
# (erneut versuchen, blockiert jetzt nicht)
try:
self.writer_q.put_nowait((va, vb))
except queue.Full:
# wenn immer noch voll, dann überspringen wir diesen Chunk
pass
except Exception as e: except Exception as e:
print(f"[{self.serial}] Read-Fehler: {e}") print(f"[{self.serial}] Read-Fehler: {e}")
time.sleep(0.01) time.sleep(0.01)
print(f"[{self.serial}] Reader stop") # Loop-Rate steuern
time.sleep(max(0.05, interval))
# -------- Writer: Wide-Format, effektive Zeitachse -------- # -------- Writer: Wide-Format, effektive Zeitachse --------
def writer_loop(self): def writer_loop(self):
os.makedirs(OUTDIR, exist_ok=True) os.makedirs(OUTDIR, exist_ok=True)
fn = os.path.join(OUTDIR, f"{time.strftime('%Y%m%d_%H%M%S')}_{self.serial}.csv") fn = os.path.join(OUTDIR, f"{time.strftime('%Y%m%d_%H%M%S')}_{self.serial}.csv")
sample_idx = 0 print(f"[{self.serial}] Writer -> {fn}")
rows_since_flush = 0
print(f"[{self.serial}] Writer -> {fn} (dt={self.dt:.6e}s)")
try: try:
with open(fn, "w", newline="") as f: with open(fn, "w", newline="") as f:
w = csv.writer(f) w = csv.writer(f)
w.writerow(["t_rel_s", "A", "B"]) w.writerow(["timestamp", "A", "B"])
while not (self.stop_evt.is_set() and self.writer_q.empty()): while not (self.stop_evt.is_set() and self.writer_q.empty()):
try: try:
va, vb = self.writer_q.get(timeout=0.5) ts, va, vb = self.writer_q.get(timeout=0.5)
except queue.Empty: except queue.Empty:
continue continue
w.writerow([ts, va, vb])
n = min(len(va), len(vb)) f.flush()
# Zeitachse mit effektiver Rate
for i in range(n):
t_rel = (sample_idx + i) * self.dt
w.writerow([t_rel, va[i], vb[i]])
sample_idx += n
rows_since_flush += n
if rows_since_flush >= 10_000: # alle ~10k Samples flushen
f.flush()
rows_since_flush = 0
except Exception as e: except Exception as e:
print(f"[{self.serial}] Writer-Fehler: {e}") print(f"[{self.serial}] Writer-Fehler: {e}")
finally: finally: