3

NationalInstrumentsのボードを使用してデータを取得するプロジェクトに取り組んでいます。タスクを実行するための機能的なCコードがありますが、Pythonを使用したいので、GUIプログラミングはそれほど苦痛ではありません。私のCコードでは、定期的にWM_TIMERイベントを発生させるAPI呼び出しsetTimerを使用しています。Tkループにも同様のメカニズムがありますか?次のコードを使ってみました。

def DAQ(self):
    if self.do_DAQ:
        result = self.myDAQ.getData()
        currTime = time.time() - self.start_time
        self.time_label.config(text="{:.1f} seconds".format(currTime))
        self.volt_label.config(text="{:.4f} volts".format(result))
        self.time_data[self.i] = currTime
        self.volt_data[self.i] = result
        self.i += 1
        self.after(1962, self.DAQ)

after()の魔法「1962」は試行錯誤で約2秒の遅延が発生すると判断されましたが、キュー内の他の内容に応じてタイムスライスがドリフトします。タイムスライスをより正確にするためにこれを行う方法はありますか?具体的には、キュー内の他のものよりも先にTkにDAQイベントを実行させることはできますか?

4

2 に答える 2

3

私は実際にPyDAQmxを使用してPythonでNIDAQmxを実行しています。20kHzでデータを取得します(NIボードでクロックタイマーを設定し、データを10Hzで2000のチャンクでファイルにストリーミングします)。

時間的な精度が重要な場合は、GUIプロセスをデータ取得プロセスから分離することを強くお勧めします。

2秒ごとにデータをログに記録するだけの場合は、NIDAQのサンプルクロックを1000、バッファーサイズ1000などに設定し、AutoRegisterEveryNSamplesEventコールバックを使用して、他のすべてのバッファーのデータの最後のインデックスを書き込むことができます( 2秒ごと)をファイルに送信するか、GUIプロセスにパイプします。これにより、GUIの処理キューが、データのサンプリングの精度に影響を与えないようになります。

于 2012-12-18T00:04:12.973 に答える
3

これが私のコメントで話していることの一種の簡単な例です:

import Tkinter as tk
import threading
import random
import time
from Queue import Queue, Empty

root = tk.Tk()
time_label = tk.Label(root, text='<unknown> seconds')
volt_label = tk.Label(root, text='<unknown> volts')
time_label.pack()
volt_label.pack()

def DAQ(q):
    while True:
        q.put((time.time(), random.randrange(100)))
        time.sleep(2)

def update_data(queue, root):
    try:
        timestamp, volts = queue.get_nowait()
    except Empty:
        pass
    else:
        time_label.config(text='{:.1f} seconds'.format(timestamp))
        volt_label.config(text='{:.4f} volts'.format(volts))
    root.after(100, update_data, queue, root)

data_queue = Queue()
t = threading.Thread(target=DAQ, args=(data_queue,))
t.daemon = True
t.start()
update_data(data_queue, root)
root.mainloop()

明らかに、上記のDAQ()関数は本物の代用にすぎません。重要なのは、@ ballsdotballsが回答で示唆しているように、DAQスレッドで任意のレートでサンプリングし、値をキューに追加してから、より適切なレートでGUIを更新できることです。

于 2012-12-18T00:13:37.333 に答える