2

I am using NI instrument to read data and display it on GUI. Have used tkinter. But could not find a way to update the data using while loop.

import nidaqmx
import time
from tkinter import *
master = Tk()
while True:
    with nidaqmx.Task() as task:
        task.ai_channels.add_ai_voltage_chan("Dev1/ai0")
        print('1 Channel 1 Sample Read: ')
        data = task.read()
        sensor_value ='%.2f' % data #said sensor value
        master.minsize(width=400, height=400)
        w = Label(master, text=sensor_value) #shows as text in the window
        w.pack() #organizes widgets in blocks before placing them in the parent.          
        time.sleep(5)
        mainloop()
Saad
  • 3,340
  • 2
  • 10
  • 32
damu_d
  • 53
  • 1
  • 8

4 Answers4

1

try this code:

import time
from tkinter import *
import nidaqmx

master = Tk()

def test():
    while True:
        with nidaqmx.Task() as task:
            task.ai_channels.add_ai_voltage_chan("Dev1/ai0")
            print('1 Channel 1 Sample Read: ')
            data = task.read()
            sensor_value = '%.2f' % data  # said sensor value
            
            w['text'] = sensor_value
            master.update()
            time.sleep(2)

w = Label(master)
w.pack()
btn = Button(text="Start read from sensor", command=test)
btn.pack()
mainloop()
Sajjad Aemmi
  • 2,120
  • 3
  • 13
  • 25
1

You'll likely need a second thread to poll the sensor.

import nidaqmx
import time
import threading
from tkinter import *


stop_signal = threading.Event()


def read_loop():
    with nidaqmx.Task() as task:
        task.ai_channels.add_ai_voltage_chan("Dev1/ai0")
        while True:
            data = task.read()
            label["text"] = "%.2f" % data

            # Wait for the signal, or 5 seconds
            if stop_signal.wait(timeout=5):
                break  # If the signal was set, break


# Build window
master = Tk()
master.minsize(width=400, height=400)
label = Label(master, text="")
label.pack()

# Set up & start reading thread
threading.Thread(target=read_loop).start()

try:
    # Enter Tk main loop
    mainloop()
finally:
    # Clean up afterwards
    stop_signal.set()
AKX
  • 152,115
  • 15
  • 115
  • 172
1

Keep in mind that mainloop() is blocking, so time.sleep() is useless as you won't get back to the task.read() line. Consider using the Thread module from the threading lib importing it like this:

from threading import Thread

or using a button to refresh the value as someone else suggested you.

1

When working with Tkinter we should avoid Threading, while loop with root.update() it is not like we can't use them but not advisable instead use after(delay_ms, callback=None, *args) method provided by Tkinter itself for a reason.

Now to your code, there are few issues in your code.

  1. In while loop you are creating a Label every 5 secs instead create one label and update the value of that label inside the loop with w['text'] = '...' or w.configure(text='...').

  2. Don't put mainloop inside the loop, instead call it in the last line with the instance of the main window in your case master (master.mainloop()).

  3. Same with master.minsize(width=400, height=400), you don't have to tell the master window every 5 sec to set the minimum size to 400x400 it should be called once if not decide to change the minimum size to different geomentry.

Your code should look like this.

import nidaqmx
from tkinter import *

master = Tk()
master.minsize(width=400, height=400)
w = Label(master) #shows as text in the window
w.pack() #organizes widgets in blocks before placing them in the parent.   

def run():
    with nidaqmx.Task() as task:
        task.ai_channels.add_ai_voltage_chan("Dev1/ai0")
        print('1 Channel 1 Sample Read: ')
        data = task.read()
        w['text'] = '%.2f' % data #said sensor value
    master.after(5000, run)

run() # run the function once.
master.mainloop()

This should be the right way of doing this and as i couldn't run your code if anything doesn't work, let me know otherwise.

Saad
  • 3,340
  • 2
  • 10
  • 32