Phidgets work properly through GUI but I cannot duplicate responses through 8/8/8

Supporting 2.7 and 3.2+
Post Reply
dlowey
Fresh meat
Posts: 3
Joined: Fri Apr 17, 2020 9:25 am
Contact:

Phidgets work properly through GUI but I cannot duplicate responses through 8/8/8

Post by dlowey »

I am using an old 1013_0 8/8/8. I have written a GUI using Python and tkinter.

Right now I have it programmed to click a button on the GUI which turns an output on or off. This all works fine when using the GUI. What I want to do though is also be able to touch a 'touchpad' to perform the same function as the GUI button. The touchpad works fine if i simply tell it to print to the screen, but I cannot make it duplicate the button press.

In other programs I have used the performclick() function 'btn1.performclick()' but I cant seem to do this with Python.

Any suggestions for a wannabe programmer?? Code below
My apologies, but the code will not work without the phidget attached :(

Code: Select all

"""this is written to test my phidget train
track operation"""
import tkinter
from tkinter import *
from Phidget22.PhidgetException import *
from Phidget22.Phidget import *
from Phidget22.Devices.VoltageInput import *
from Phidget22.Devices.DigitalInput import *
from Phidget22.Devices.DigitalOutput import *
import traceback
import time
import tkinter.messagebox
			window = tkinter(dot)Tk() #the messageboard would not let me post tkninter . Tk() for some reason
# to rename the title of the window
window.title("Welcome Model Railroading by Daryl Lowey!")
# pack is used to show the object in the window


# You will first create a division with the help of Frame class and align them on TOP and BOTTOM with pack() method.
image_frame = tkinter.Frame(window)
image_frame.pack(side="top")
top_frame = tkinter.Frame(window)
top_frame.pack()
bottom_frame = tkinter.Frame(window)
bottom_frame.pack(side="top")
slider_frame = tkinter.Frame(window)
slider_frame.pack(side="bottom")




# Once the frames are created then you are all set to add widgets in both the frames.
# the lines below adds a picture to the top frame (image_frame)
icon = tkinter.PhotoImage(file = "Layout.png")
label = tkinter.Label(image_frame, image = icon)
label.pack()

# the following def's are the functions related to button clicks
def Power1():
	if (btn1["fg"]=="Green"):
		btn1["fg"]=("Red")
		btn1["relief"]=("sunken")
		digitalOutput0.setDutyCycle(0)
	else:
		btn1["fg"]=("Green")
		btn1["relief"]=("raised")
		digitalOutput0.setDutyCycle(1)

def Power2():
	if (btn2["fg"]=="Green"):
		btn2["fg"]=("Red")
		btn2["relief"]=("sunken")
		digitalOutput1.setDutyCycle(0)		
	else:
		btn2["fg"]=("Green")
		btn2["relief"]=("raised")	
		digitalOutput1.setDutyCycle(1)	
	
def Power3():
	if (btn3["fg"]=="Green"):
		btn3["fg"]=("Red")
		btn3["relief"]=("sunken")
		digitalOutput2.setDutyCycle(0)
	else:
		btn3["fg"]=("Green")
		btn3["relief"]=("raised")
		digitalOutput2.setDutyCycle(1)
		
def Power4():
	if (btn4["fg"]=="Green"):
		btn4["fg"]=("Red")
		btn4["relief"]=("sunken")
		digitalOutput3.setDutyCycle(0)
	else:
		btn4["fg"]=("Green")
		btn4["relief"]=("raised")
		digitalOutput3.setDutyCycle(1)
		
def Power5():
	if (btn5["fg"]=="Green"):
		btn5["fg"]=("Red")
		btn5["relief"]=("sunken")
		digitalOutput4.setDutyCycle(0)
	else:
		btn5["fg"]=("Green")
		btn5["relief"]=("raised")
		digitalOutput4.setDutyCycle(1)
		
def Power6():
	if (btn6["fg"]=="Green"):
		btn6["fg"]=("Red")
		btn6["relief"]=("sunken")
		digitalOutput5.setDutyCycle(0)
	else:
		btn6["fg"]=("Green")
		btn6["relief"]=("raised")
		digitalOutput5.setDutyCycle(1)
		
def Power7():
	if (btn7["fg"]=="Green"):
		btn7["fg"]=("Red")
		btn7["relief"]=("sunken")
		digitalOutput6.setDutyCycle(0)
	else:
		btn7["fg"]=("Green")
		btn7["relief"]=("raised")
		digitalOutput6.setDutyCycle(1)	
		
def Power8():
	if (btn8["fg"]=="Green"):
		btn8["fg"]=("Red")
		btn8["relief"]=("sunken")
		digitalOutput7.setDutyCycle(0)
	else:
		btn8["fg"]=("Green")
		btn8["relief"]=("raised")
		digitalOutput7.setDutyCycle(1)
		
def Power9():
	if (btn9["fg"]=="Green"):
		btn9["fg"]=("Red")
		btn9["relief"]=("sunken")
	else:
		btn9["fg"]=("Green")	
		btn9["relief"]=("raised")
		
def Power10():
	if (btn10["fg"]=="Green"):
		btn10["fg"]=("Red")
		btn10["relief"]=("sunken")
	else:
		btn10["fg"]=("Green")
		btn10["relief"]=("raised")	
		
def Power11():
	if (btn11["fg"]=="Green"):
		btn11["fg"]=("Red")
		btn11["relief"]=("sunken")
	else:
		btn11["fg"]=("Green")	
		btn11["relief"]=("raised")
		
def Power11a():
	if (btn11a["fg"]=="Green"):
		btn11a["fg"]=("Red")
		btn11a["relief"]=("sunken")
	else:
		btn11a["fg"]=("Green")	
		btn11a["relief"]=("raised")
def Power12():
	if (btn12["fg"]=="Green"):
		btn12["fg"]=("blue")
		btn12["relief"]=("sunken")
	else:
		btn12["fg"]=("Green")
		btn12["relief"]=("raised")		
def Power13():
	if (btn13["fg"]=="Green"):
		btn13["fg"]=("blue")
		btn13["relief"]=("sunken")
	else:
		btn13["fg"]=("Green")
		btn13["relief"]=("raised")		
def Power14():
	if (btn14["fg"]=="Green"):
		btn14["fg"]=("blue")
		btn14["relief"]=("sunken")
	else:
		btn14["fg"]=("Green")
		btn14["relief"]=("raised")	
# the following define the button clicks
btn1 = tkinter.Button(top_frame, text = " Power 1 ", fg = "red",relief = "sunken", command=Power1)
btn1.pack(side = "left") #'fg or foreground' is for coloring the contents (buttons)
btn2 = tkinter.Button(top_frame, text = " Power 2 ", fg = "red",relief = "sunken",command=Power2)
btn2.pack(side = "left")
btn3 = tkinter.Button(top_frame, text = " Power 3 ", fg = "red",relief = "sunken",command=Power3)
btn3.pack(side = "left")
btn4 = tkinter.Button(top_frame, text = " Power 4 ", fg = "red",relief = "sunken",command=Power4)
btn4.pack(side = "left")
btn5 = tkinter.Button(top_frame, text = " Power 5 ", fg = "red",relief = "sunken",command=Power5)
btn5.pack(side = "left")
btn6 = tkinter.Button(top_frame, text = " Power 6 ", fg = "red",relief = "sunken",command=Power6)
btn6.pack(side = "left")
btn7 = tkinter.Button(top_frame, text = "Power Roundhouse", fg = "red",relief = "sunken",command=Power7)
btn7.pack(side = "left")
btn8 = tkinter.Button(bottom_frame, text = " Turn A ", fg = "red",relief = "sunken",command=Power8)
btn8.pack(side = "left") #'side' is used to left or right align the widgets
btn9 = tkinter.Button(bottom_frame, text = " Turn B ", fg = "red",relief = "sunken",command=Power9)
btn9.pack(side = "left")
btn10 = tkinter.Button(bottom_frame, text = " Turn C ", fg = "red",relief = "sunken",command=Power10)
btn10.pack(side = "left")
btn11 = tkinter.Button(bottom_frame, text = " Turn D ", fg = "red",relief = "sunken",command=Power11)
btn11.pack(side = "left")
btn11a = tkinter.Button(bottom_frame, text = " Turn E ", fg = "red",relief = "sunken",command=Power11a)
btn11a.pack(side = "left")
btn12 = tkinter.Button(bottom_frame, text = " Streetlights ", fg = "blue",relief = "sunken",command=Power12)
btn12.pack(side = "left")
btn13 = tkinter.Button(bottom_frame, text = " Buildings 1 ", fg = "blue",relief = "sunken",command=Power13)
btn13.pack(side = "left")
btn14 = tkinter.Button(bottom_frame, text = " Buildings 2 ", fg = "blue",relief = "sunken",command=Power14)
btn14.pack(side = "left")
scale = Scale( slider_frame, from_ = -25, to = 100, orient = HORIZONTAL, length=500)  
scale.pack(anchor=CENTER)  


# the following defs are the funtions related to phidget actions.
def onVoltageChange(self, voltage):
	if (str(voltage) < "2.5"):
		print("voltage: " + str(voltage))
	
def onStateChange(self, state):
	print("State: " + str(state))

#def main():
voltageInput0 = VoltageInput()

#digitalInput0 = DigitalInput()

digitalOutput0 = DigitalOutput()
digitalOutput1 = DigitalOutput()
digitalOutput2 = DigitalOutput()
digitalOutput3 = DigitalOutput()
digitalOutput4 = DigitalOutput()
digitalOutput5 = DigitalOutput()
digitalOutput6 = DigitalOutput()
digitalOutput7 = DigitalOutput()

digitalOutput0.setChannel(0)
digitalOutput1.setChannel(1)
digitalOutput2.setChannel(2)
digitalOutput3.setChannel(3)
digitalOutput4.setChannel(4)
digitalOutput5.setChannel(5)
digitalOutput6.setChannel(6)
digitalOutput7.setChannel(7)

voltageInput0.setOnVoltageChangeHandler(onVoltageChange)
#digitalInput0.setOnStateChangeHandler(onStateChange)

voltageInput0.openWaitForAttachment(5000)
voltageInput0.setVoltageChangeTrigger(3)
voltageInput0.setDataInterval(100)
#digitalInput0.openWaitForAttachment(5000)
digitalOutput0.openWaitForAttachment(5000)
digitalOutput1.openWaitForAttachment(5000)
digitalOutput2.openWaitForAttachment(5000)
digitalOutput3.openWaitForAttachment(5000)
digitalOutput4.openWaitForAttachment(5000)
digitalOutput5.openWaitForAttachment(5000)
digitalOutput6.openWaitForAttachment(5000)
digitalOutput7.openWaitForAttachment(5000)



try:
	input("Press Enter to Stop\n")
except (Exception, KeyboardInterrupt):
	pass

voltageInput0.close()
#digitalInput0.close()

digitalOutput0.close()
digitalOutput1.close()
digitalOutput2.close()
digitalOutput3.close()
digitalOutput4.close()
digitalOutput5.close()
digitalOutput6.close()
digitalOutput7.close()

window.mainloop()
User avatar
mparadis
Site Admin
Posts: 660
Joined: Fri Oct 28, 2011 12:17 pm
Contact:

Re: Phidgets work properly through GUI but I cannot duplicate responses through 8/8/8

Post by mparadis »

Is the touch pad the device connected to voltageInput0?

You should be able to copy the code from your button press function into the 'if' statement inside the onVoltageChange handler, but you'll need to add attributes to voltageInput object that will be able to be accessed using the "self" parameter in the event handler.

See "Referencing Other Phidgets from Events" on this page for an example.
dlowey
Fresh meat
Posts: 3
Joined: Fri Apr 17, 2020 9:25 am
Contact:

Re: Phidgets work properly through GUI but I cannot duplicate responses through 8/8/8

Post by dlowey »

Hi... thank you for the quick response.
The touch sensor is indeed connected to voltageInput(1) and when I touch it, it prints properly but if I add the button code as shown below, i get the following error: - . have been replaced with (dot)

Traceback (most recent call last):
File "_ctypes/callbacks.c", line 237, in 'calling callback function'
File "C:\Users\Daryl\Python projects\Phidget22\Devices\VoltageInput(dot)py", line 71, in _localVoltageChangeEvent
self._VoltageChange(self, voltage)
File "C:\Users\Daryl\Python projects\Train(dot)py", line 210, in onVoltageChange
if (btn1["fg"]=="Green"):
File "C:\Users\Daryl\AppData\Local\Programs\Python\Python38-32\lib\tkinter\__init__(dot)py", line 1643, in cget
return self(dot)tk(dot)call(self(dot)_w, 'cget', '-' + key)
RuntimeError: main thread is not in main loop

Code: Select all

def onVoltageChange(self, voltage):
	if (str(voltage) < "2.5"):
		if (btn1["fg"]=="Green"):
			btn1["fg"]=("Red")
			btn1["relief"]=("sunken")
			digitalOutput0.setDutyCycle(0)
		else:
			btn1["fg"]=("Green")
			btn1["relief"]=("raised")
			digitalOutput0.setDutyCycle(1)
		#print("voltage: " + str(voltage))
User avatar
mparadis
Site Admin
Posts: 660
Joined: Fri Oct 28, 2011 12:17 pm
Contact:

Re: Phidgets work properly through GUI but I cannot duplicate responses through 8/8/8

Post by mparadis »

Googling that error message it seems like Tkinter doesn't play nice with programs that use multiple threads. Phidget events are executed in a separate thread than your main function.

You could use polling instead of events (i.e. repeatedly calling getVoltage on the voltage input in your main function) but I don't know enough about Tkinter to know how that works with your GUI loop.
dlowey
Fresh meat
Posts: 3
Joined: Fri Apr 17, 2020 9:25 am
Contact:

Re: Phidgets work properly through GUI but I cannot duplicate responses through 8/8/8

Post by dlowey »

Is there anything you would suggest other than Tkinter? What do you folks use to develop GUI in python?
Post Reply

Who is online

Users browsing this forum: No registered users and 0 guests