import threading, queue, time, csv, os CHUNK = 2000 OUTDIR = "logs" os.makedirs(OUTDIR, exist_ok=True) class DeviceController: def __init__(self, dev): self.dev = dev self.cmdq = queue.Queue() self.stop_evt = threading.Event() self.running = False self.writer_q = queue.Queue(maxsize=50) self.reader_t = threading.Thread(target=self.reader_loop, daemon=True) self.writer_t = threading.Thread(target=self.writer_loop, daemon=True) def start(self): if not self.reader_t.is_alive(): self.reader_t.start() if not self.writer_t.is_alive(): self.writer_t.start() self.cmdq.put(("start", None)) def stop(self): self.cmdq.put(("stop", None)) def set_mode(self, ch, mode): self.cmdq.put(("mode", (ch, mode))) def shutdown(self): self.stop() self.stop_evt.set() self.reader_t.join() self.writer_t.join() def reader_loop(self): while not self.stop_evt.is_set(): # Befehle abarbeiten (non-blocking) try: cmd, arg = self.cmdq.get_nowait() if cmd == "start" and not self.running: # kontinuierlich laufen lassen (0 == unendlich) self.dev.run(0) # ← per-Gerät-Start self.running = True elif cmd == "stop" and self.running: self.dev.cancel() # ← per-Gerät-Stop (sofort) # optional sauber aus: self.dev.off() self.dev.flush(-1, True) # Read-Queue leeren self.running = False elif cmd == "mode": ch, mode = arg # ch: 0 (A) / 1 (B) self.set_mode(ch, mode) except queue.Empty: pass if self.running: # blockierend n Samples holen try: data = self.dev.read([], CHUNK, -1, False) # pysmu mappt auf [ [VA,IA,VB,IB], ... ] # In einfachem CSV-Beispiel loggen wir nur Spannungen A/B: # data ist Liste von 4-Float-Arrays vsA = [row[0] for row in data] vsB = [row[2] for row in data] self.writer_q.put((time.time(), vsA, vsB)) except Exception: # bei Überlauf o.ä. kurz atmen und weiter time.sleep(0.001) else: time.sleep(0.01) def writer_loop(self): ts0 = None fn = os.path.join(OUTDIR, f"{time.strftime('%Y%m%d_%H%M%S')}_{self.dev.serial}.csv") with open(fn, "w", newline="") as f: w = csv.writer(f) w.writerow(["t_rel_s", "ch", "value"]) sample_idx = 0 while not (self.stop_evt.is_set() and self.writer_q.empty()): try: ts, va, vb = self.writer_q.get(timeout=0.2) except Exception: continue if ts0 is None: ts0 = ts for i, v in enumerate(va): t_rel = (sample_idx + i) * 1e-5 # 100 kS/s → 10 µs w.writerow([t_rel, "A", v]) for i, v in enumerate(vb): t_rel = (sample_idx + i) * 1e-5 w.writerow([t_rel, "B", v]) sample_idx += len(va) print(f"[{self.dev.serial}] Datei geschlossen.")