添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
Hello everybody,
I am trying to create a tkinter gui 'ACMUSB.py' that has a number of buttons for different operations.. The GUI 'ACMUSB.py' in turn calls another python program calls 'tracer.py' that basically uses the baud rate to capture the incoming data from a serial device .. I am trying to create a toggle button (baudrate) on the GUI 'ACMUSB.py' that sets the baud rate in the sub program 'tracer.py'.
I am using the tkinter's 'entry' widget along with the set() and get() functions..
My buttons and other widgets have been created in my GUI program 'ACMUSB.py'
My code in the sub program 'tracer.py' that needs the value of the baudrate looks something like this..

Code: Select all

def baudrate():
          baudrate = IntVar(root)
          baudrate.set('1')
          option= OptionMenu(root, baudrate, '9600', '115200')
          option.pack()
addr  = '/dev/ttyACM0'  # serial port to read data from
baud  =  baudrate.get()           # baud rate for serial port
fname = 'log.dat'   # log file to save data in
How ever it keeps giving me an error as :

Code: Select all

Exception in Tkinter callback
Traceback (most recent call last):
  File "/usr/lib/python2.7/lib-tk/Tkinter.py", line 1437, in __call__
    return self.func(*args)
  File "ACMUSB.py", line 35, in ACMClicked
    baudrate.get()
Can anybody be kind enough to help me with this.. 
Thank you in advance,
Namita..
there are 2 ways
-1- is to read ( var.get() ) the setting of the widget and wait for change
-2- on operation a command is called and brings the selection with it.
looks also that there you can use text '9600' or number 9600.
tested with IDLE: python2.7.3

Code: Select all

from Tkinter import *
root = Tk()
var = IntVar()
addr  = '/dev/ttyACM0'  # serial port to read data from
fname = 'log.dat'   # log file to save data in
def sel_baudrate(sel):
    global root,var, label
    # there seem to be 2 way to get the selection!
    print "sel %s" % (sel)
    print "get %s" % (var.get())
    selection = "Your selection \n" + str(var.get())
    label.config(text = selection)
def make_baudrate():
    global root, var, label
    Label(root, 
      text="""Choose a 
    baudrate:""",
      justify = LEFT,
      padx = 20).pack()
    var.set(9600)
    option= OptionMenu(root, var, 9600, 115200,command=sel_baudrate)
    option.pack()
    # to show result
    label = Label(root)
    label.pack()
make_baudrate()
mainloop()
					
Thank you for that KLL,
However I could not get that to work.. I put in the code you suggested in my sub program 'tracer.py' that uses the variable baudrate..
this is the entire code :

Code: Select all

#!/usr/bin/sh
# get lines of text from serial port, save them to a file
from __future__ import print_function
from Tkinter import *
import serial, io
import time
ts = time.time()
print (ts)
import datetime
st = datetime.datetime.fromtimestamp(ts).strftime('%Y-%m-%d %H:%M:%S')
print (st)
s = open('log.dat', 'a')
log = time.strftime("%Y%m%d-%H%M%S")
s = open(log + '.dat', 'a')
addr  = '/dev/ttyACM0'  # serial port to read data from
baud  =  make_baudrate()         # baud rate for serial port
fname = 'log.dat'   # log file to save data in
fmode = 'a'             # log file mode = append
with serial.Serial(addr,baud) as pt, open(fname,fmode) as outf:
    spb = io.TextIOWrapper(io.BufferedRWPair(pt,pt,1),
        encoding='ascii', errors='ignore', newline='\r',line_buffering=True)
    spb.readline()
    while (1):
          x = spb.readline()  # read one line of text from serial port
          print (x,end='')    # echo line of text on-screen
          outf.write(x)       # write line of text to file
          outf.flush()        # make sure it actually gets written out
This program uses the baude_rate from the main GUI program which is as follows: 

Code: Select all

#!/usr/bin/python
from __future__ import print_function
from Tkinter import *
from Tkinter import Entry, IntVar, Tk
import serial, io
import time
import Tkinter as tk
import subprocess
import os
#ts = time.time()
#print (ts)
#import datetime
#st = datetime.datetime.fromtimestamp(ts).strftime('%Y-%m-%d %H:%M:%S')
#print (st)
root = Tk()
root.wm_title(" Beagle Bone ")
root.config(background = "#FFFFFF")
root.geometry('200x200')
c = Checkbutton(root , text='STOP', command= quit)
var = IntVar()
def baudrate(sel):
    global root,var, label
    # there seem to be 2 way to get the selection!
    print (' %s') % (sel)
print (" %s") % (var.get())
    selection = "Your selection \n" + str(var.get())
    label.config(text = selection)
def make_baudrate():
    global root, var, label
    Label(root,
      text="""Choose a 
    baudrate:""",
      justify = LEFT,
  padx = 20).pack()
    var.set(9600)
    option= OptionMenu(root, var, 9600, 115200,command=baudrate)
    option.pack()
    # to show result
    label = Label(root)
    label.pack()
make_baudrate()
def ACMClicked():
        os.system("python tracer.py")
        root.update()
def USBClicked():
           os.system("python newtracer.py")
           root.update()
def ACM_logClicked():
           os.system("cat log.dat")
           root.update()
def USB_logClicked():
          os.system("cat binlog.dat")
          root.update()
newButton = Button(text ='baudrate', command=baudrate)
newButton.grid(row =2, column =1, padx=10, pady=2)
newButton = Button(text = "ACM", command=ACMClicked)
newButton.grid(row=0, column=0, padx=10, pady=2)
newButton = Button(text = 'USB', command=USBClicked)
newButton.grid(row=1, column=0, padx=10, pady=2)
newButton = Button(text = 'ACM_log', command=ACM_logClicked)
newButton.grid(row=0, column=1, padx=10, pady=2)
newButton = Button(text = 'USB_log', command=USB_logClicked)
newButton.grid(row=1, column=1, padx=10, pady=2)
root.mainloop()
The problem is when I try to run the main GUi program it begins running but does not give me the GUI and does not either stop.. It seems to go into a loop..
Is what am I doing right??
Thanks for the help
Namita :)
I commented out the make_baudrate() and then the GUI seems to run.. But when i click the button baudrate it gives me a n error saying:

Code: Select all

Exception in Tkinter callback
Traceback (most recent call last):
  File "/usr/lib/python2.7/lib-tk/Tkinter.py", line 1437, in __call__
    return self.func(*args)
TypeError: baudrate() takes exactly 1 argument (0 given)
root@beaglebone:~# 
Kindly Help,
Namita
KLL wrote:is the code i made for you running on your system as stand alone program?
how you start it?
I run the main GUI program by the following command :

Code: Select all

python ACMUSB.py
The code you suggested is part of this program
Namita.
I think I made a mistake.. Instead of calling the function make_baudrate() I just kept calling baudrate() during the button press.. Now I can run the Gui and also get the drop down menu to set the baud rate.. However now i get a new error..

Code: Select all

 %s
Exception in Tkinter callback
Traceback (most recent call last):
  File "/usr/lib/python2.7/lib-tk/Tkinter.py", line 1437, in __call__
    return self.func(*args)
  File "/usr/lib/python2.7/lib-tk/Tkinter.py", line 3165, in __call__
    self.__callback(self.__value, *args)
  File "ACMUSB.py", line 29, in baudrate
    print (' %s') % (sel)
TypeError: unsupported operand type(s) for %: 'NoneType' and 'str'
Here instead of printing the baud rate it prints '%s'
Also regarding the error as far as I see I dont see a different operand type other than string being used here..
Any ide what is wrong here?
Thank you,
Namita.
i need you to confirm first that my above code ( as a stand alone code) works on your system,
( before you copy it into your other program)
only then i might be able to help about the GUI program
KLL wrote:i need you to confirm first that my above code ( as a stand alone code) works on your system,
( before you copy it into your other program)
only then i might be able to help about the GUI program
Yes. It does run perfectly.. Iget the output as :

Code: Select all

sel 9600
get 9600
Could you please take some time out and tell me in which of my programs do I need to make my changes..
Kind Regards,
Namita
Last edited by ggnamita on Thu Feb 05, 2015 11:11 am, edited 1 time in total.
so you could try that version of your GUI program

Code: Select all

#!/usr/bin/python
#from __future__ import print_function
from Tkinter import *
#from Tkinter import Entry, IntVar, Tk
#import serial, io
#import time
#import Tkinter as tk
#import subprocess
import os
#ts = time.time()
#print (ts)
#import datetime
#st = datetime.datetime.fromtimestamp(ts).strftime('%Y-%m-%d %H:%M:%S')
#print (st)
root = Tk()
root.wm_title(" Beagle Bone ")
root.config(background = "#FFFFFF")
root.geometry('200x200')
c = Checkbutton(root , text='STOP', command= quit)
var = IntVar()
baudrate=9600
def sel_baudrate(sel):
    global root, var, baudrate
    # there seem to be 2 way to get the selection!
    #print (' %s') % (sel)
    #print (" %s") % (var.get())
    baudrate=var.get()
    print (' %s') % (baudrate)
    #selection = "Your selection \n" + str(var.get())
    #label.config(text = selection)
def make_baudrate():
    global root, var, baudrate
    #Label(root,
    #  text="""Choose a baudrate:""",
    #  justify = LEFT,padx = 20).pack()
    var.set(9600)
    option21= OptionMenu(root, var, 9600, 115200,command=sel_baudrate)
    #option.pack()
    option21.grid(row =2, column =1, padx=10, pady=2)
    # to show result
    #label = Label(root)
    #label.pack()
    root.update()
def ACMClicked():
    os.system("python tracer.py")
    root.update()
def USBClicked():
    os.system("python newtracer.py")
    root.update()
def ACM_logClicked():
    os.system("cat log.dat")
    root.update()
def USB_logClicked():
    os.system("cat binlog.dat")
    root.update()
newButton00 = Button(text = "ACM", command=ACMClicked)
newButton00.grid(row=0, column=0, padx=10, pady=2)
newButton10 = Button(text = 'USB', command=USBClicked)
newButton10.grid(row=1, column=0, padx=10, pady=2)
newButton01 = Button(text = 'ACM_log', command=ACM_logClicked)
newButton01.grid(row=0, column=1, padx=10, pady=2)
newButton11 = Button(text = 'USB_log', command=USB_logClicked)
newButton11.grid(row=1, column=1, padx=10, pady=2)
newButton20 = Button(text ='baudrate', command=make_baudrate)
newButton20.grid(row =2, column =0, padx=10, pady=2)
root.mainloop()
					
I made these changes in my program.. But now when I select the baudrate of 9600 or 115200 I get the same error as before regarding the operand type..

Code: Select all

%s
Exception in Tkinter callback
Traceback (most recent call last):
  File "/usr/lib/python2.7/lib-tk/Tkinter.py", line 1437, in __call__
    return self.func(*args)
  File "/usr/lib/python2.7/lib-tk/Tkinter.py", line 3165, in __call__
    self.__callback(self.__value, *args)
  File "ACMUSB.py", line 33, in baudrate
    print ('%s') % (baudrate)
TypeError: unsupported operand type(s) for %: 'NoneType' and 'int'
					
elParaguayo wrote:Are you using python 3?

Code: Select all

print (' %s' % (sel))
or

Code: Select all

print ("{}".format(sel))
I use python 2.7.3..
?? pls run the last program i send you, why you say you made any changes ( on your or my version )
and what changes?
OK. But do you also have the line:

Code: Select all

from __future__ import print_function
If you do, that essentially converts python 2.7's print statement into python 3's print function. The function will give you the error message that you've seen.
However, I'm keen not to get too side-tracked on this thread if there are other issues that also need to be resolved e.g. see KLL's emails.
RPi Information Screen: plugin based system for displaying weather, travel information, football scores etc.
elParaguayo wrote:OK. But do you also have the line:

Code: Select all

from __future__ import print_function
If you do, that essentially converts python 2.7's print statement into python 3's print function. The function will give you the error message that you've seen. sorry, in my version i disabled it because not required, thanks and pls stay with us.
Okay. SO I created a new python file 'au.py' that has the code that you just suggested. When i run it I see the selected baud rate being displayed..
When I select the button 'ACM' that is linked to the tracer.py program it gives the error saying :

Code: Select all

 9600
1423137572.83
2015-02-05 11:59:32
Traceback (most recent call last):
  File "tracer.py", line 46, in <module>
    with serial.Serial(addr,'selection') as pt, open(fname,fmode) as outf:
  File "/usr/lib/python2.7/dist-packages/serial/serialutil.py", line 248, in __init__
    self.baudrate = baudrate
  File "/usr/lib/python2.7/dist-packages/serial/serialutil.py", line 316, in setBaudrate
    self._baudrate = int(baudrate)
ValueError: invalid literal for int() with base 10: 'selection'
Here the term selection is from the tracer.py program.. I assign the value of the variable baud to selection.. I am not sure if this is right.. 
I really appreciate all the help..
Thanks a ton,
Namita.
Last edited by ggnamita on Thu Feb 05, 2015 12:23 pm, edited 1 time in total. i understand that the GUI program is running now.
but it spawns a other program what has errors?
anyhow first the big question,
in the GUI program the operator can select a baudrate
( now it is available as a global variable named "baudrate" in THAT program only)
how you plan to bring it to the other program?
and if you choose to send it by parameter like
python tracer.py -b 9600
or by write read file...
there is a other problem, the main GUI must make sure that first the baudrate is selected and then the program can be started!!
KLL wrote:UPS
i understand that the GUI program is running now.
but it spawns a other program what has errors?
anyhow first the big question,
in the GUI program the operator can select a baudrate
( now it is available as a global variable named "baudrate" in THAT program )
how you plan to bring it to the other program?
and if you choose to send it by parameter like
python tracer.py -b 9600
or by write read file...
there is a other problem, the main GUI must make sure that first the baudrate is selected and then the program can be started!!
I plan to get the baudrate from the Gui program into the sub program by the variable baud that I am using in the subprogram ('tracer.py'. Pls have a look at the tracer.py program that I showed in the earlier post..)
I was thinking wether it would be possible to pass the baudrate as a global variable into my sub program.
I think that should be possible right?
Namita.
there is no sub program, you start a separate program for what reason ever.
sorry i do not know of any method on system wide variable level,
you might need help from the pros. i am a beginner like you.
but i checked on the button function,
you could use a

Code: Select all

newButton00['state']=DISABLED
for the make of the button,
and after the baudrate is set, make a

Code: Select all

    newButton00['state']=NORMAL
that would link the ACM button with the baudrate selection in the way that it can be started only after the selection is done.
_____________________________
other question, the program tracer.py, when you start it manually with
python tracer.py
is it running error free?
Yes.. The program tracer.py runs error free when I set a baudrate maually within the program..
Thank you for all your help,
Namita
yes, its a optional parameter, the usual way to handover settings
try that, i take out some unused things and give a example of the parameter handover

Code: Select all

#!/usr/bin/python
# get lines of text from serial port, save them to a file
#from __future__ import print_function
#from Tkinter import *
import serial, io
import time
import sys, getopt
#ts = time.time()
#print (ts)
#import datetime
#st = datetime.datetime.fromtimestamp(ts).strftime('%Y-%m-%d %H:%M:%S')
#print (st)
#s = open('log.dat', 'a')
#s = open(log + '.dat', 'a')
# serial interface
seraddr   = '/dev/ttyACM0'  # serial port to read data from
serbaud   = 0               #make_baudrate()         # baud rate for serial port
sertimeout= 20              #sec
# log file in same directory
fname = 'log.dat'       # log file to save data in
fmode = 'a'             # log file mode = append
logtime = time.strftime("%Y%m%d-%H%M%S")
print logtime
outf=open(fname,fmode)
outf.write(logtime)
outf.close()
def mymain(clbaudrate=9600):
    serbaud=clbaudrate
    with serial.Serial(seraddr,baudrate=serbaud,timeout=sertimeout) as pt, open(fname,fmode) as outf:
        spb = io.TextIOWrapper(io.BufferedRWPair(pt,pt,1),
            encoding='ascii', errors='ignore', newline='\r',line_buffering=True)
        spb.readline()
        while (1):
              x = spb.readline()  # read one line of text from serial port
              #print (x,end='')    # echo line of text on-screen
              print (x)    # echo line of text on-screen
              outf.write(x)       # write line of text to file
              outf.flush()        # make sure it actually gets written out
        opts, args = getopt.getopt(argv,"hb:",["baudrate="])
    except getopt.GetoptError:
        print 'usage: python tracer.py -h -b 9600 '
        sys.exit(0)
    for opt, arg in opts:
        if opt == '-h' or opt == '--help':
            print 'usage: python tracer.py -h -b 9600 '
            sys.exit(0)
        elif opt == '-b' or opt == '--baudrate':
            clbaudrate = int(arg)
            print "clbaudrate %s" % (clbaudrate)
    mymain(clbaudrate)
# _________________________________________________________________
if __name__ == '__main__':
    main(sys.argv[1:])
					
It seems to be running!!!!!!! :)
Thank you so much for that.. I understood the part of your code you modified in mine and I know it is too much but i did not really understand the part of your code from the function ' main(argv)'.
Could you may be tell that to me in a few brief lines..
Thanks a lot again, :)
Namita..