From 559f512beea5b0a6df4bf67bd9021f5177d6a5f7 Mon Sep 17 00:00:00 2001 From: Vincent Hanewinkel Date: Thu, 14 Aug 2025 22:40:44 +0200 Subject: [PATCH] fix --- DeviceController.py | 78 +++++++++++++++------------------------------ 1 file changed, 26 insertions(+), 52 deletions(-) diff --git a/DeviceController.py b/DeviceController.py index b35375a..b0f9d37 100644 --- a/DeviceController.py +++ b/DeviceController.py @@ -1,5 +1,5 @@ # 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 CHUNK_RAW = 2000 # ~20 ms pro Chunk pro Gerät @@ -40,92 +40,66 @@ class DeviceController: # -------- Reader: liest roh und decimiert -------- 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(): - # Kommandos + # Start/Stop Kommandos try: cmd, _ = self.cmdq.get_nowait() if cmd == "start" and not self.running: - self.sm.start() # Session ggf. starten + self.sm.start() self.running = True elif cmd == "stop" and self.running: + self.sm.stop() self.running = False - self.sm.stop() # Session ggf. stoppen except queue.Empty: pass if not self.running: - time.sleep(0.02) + time.sleep(0.05) continue try: - # pysmu: Liste von [VA, IA, VB, IB] - samples = self.dev.read(CHUNK_RAW, -1) # je nach Version evtl. .read(CHUNK_RAW) + # Rohdaten holen (filter_window_size Samples) + samples = self.dev.read(filter_window_size, -1) if not samples: - time.sleep(0.001) + time.sleep(interval) continue - # Kanäle extrahieren - va_raw = [row[0] for row in samples] - vb_raw = [row[2] for row in samples] + # Kanäle extrahieren & mitteln + va = statistics.mean(row[0] for row in samples) + vb = statistics.mean(row[2] for row in samples) - # -------- Decimation: jedes N-te Sample -------- - if self.decim > 1: - va = va_raw[::self.decim] - vb = vb_raw[::self.decim] - 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 + now = time.time() + if now - last_log_time >= 1.0: # nur jede Sekunde loggen + self.writer_q.put((now, va, vb)) + last_log_time = now except Exception as e: print(f"[{self.serial}] Read-Fehler: {e}") time.sleep(0.01) - print(f"[{self.serial}] Reader stop") + # Loop-Rate steuern + time.sleep(max(0.05, interval)) # -------- Writer: Wide-Format, effektive Zeitachse -------- def writer_loop(self): os.makedirs(OUTDIR, exist_ok=True) fn = os.path.join(OUTDIR, f"{time.strftime('%Y%m%d_%H%M%S')}_{self.serial}.csv") - sample_idx = 0 - rows_since_flush = 0 - print(f"[{self.serial}] Writer -> {fn} (dt={self.dt:.6e}s)") + print(f"[{self.serial}] Writer -> {fn}") try: with open(fn, "w", newline="") as 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()): try: - va, vb = self.writer_q.get(timeout=0.5) + ts, va, vb = self.writer_q.get(timeout=0.5) except queue.Empty: continue - - n = min(len(va), len(vb)) - # 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 + w.writerow([ts, va, vb]) + f.flush() except Exception as e: print(f"[{self.serial}] Writer-Fehler: {e}") finally: