0

I am currently trying to write data to a modbus server via the UI tkinter. To do this, I'm using tkinter to create the UI and implement a button that internally calls me a function called print_entry(), starts the Modbus and writes the entered values to the respective addresses.

`


from tkinter import *
import tkinter as tk
import time
from pyModbusTCP.server import ModbusServer

   
# Create a Window
root = tk.Tk()

root.geometry("300x290")
# Edit Title
root.title("Resolve Batterie Profil")

#Edit fields for Descrition
#------------------------------------------------------------------------------
IPFensterLabel=Label(root,  text="Server IP", fg="black", bg= "white")
IPFensterLabel.place(y=0, x=0, width= 100,height= 30)
    
PortFenster =Label(root,text = "Port", fg="black", bg="white")
PortFenster.place(y=30, x=0, width= 100, height= 30)
    
SOCFenster =Label(root,text = "SOC", fg="black", bg="white")
SOCFenster.place(y=80, x=0, width= 100, height= 30)
    
SOHFenster =Label(root,text = "SOH", fg="black", bg="white")
SOHFenster.place(y=110, x=0, width= 100, height= 30)
    
EntladeFenster =Label(root,text = "Entladeleistung", fg="black", bg="white")
EntladeFenster.place(y=140, x=0, width= 100, height= 30)
    
LadeFenster =Label(root,text = "Ladeleistung", fg="black", bg="white")
LadeFenster.place(y=170, x=0, width= 100, height= 30)
    
#Edit fields for data entry
#------------------------------------------------------------------------------
IPEntry=Entry(root,fg="black", bg="white")
IPEntry.place(y=0, x=100,width= 100,height= 30)
    
PortEntry=Entry(root,fg="black", bg="white")
PortEntry.place(y=30, x=100,width= 100,height= 30)
    
SOCEntry=Entry(root,fg="black", bg="white")
SOCEntry.place(y=80, x=100,width= 100,height= 30)
    
SOHEntry=Entry(root,fg="black", bg="white")
SOHEntry.place(y=110, x=100,width= 100,height= 30)
    
EntladeEntry=Entry(root,fg="black", bg="white")
EntladeEntry.place(y=140, x=100,width= 100,height= 30)
    
LadeEntry=Entry(root,fg="black", bg="white")
LadeEntry.place(y=170, x=100,width= 100,height= 30)
    
#
#------------------------------------------------------------------------------
      
def print_entry():
    server= ModbusServer(IPEntry.get(),PortEntry.get() , no_block=True)
    
    print("\n")
    print("Server is run:" + str(server.is_run)) 
    
    print("Value before writing:" + str(server.data_bank.get_input_registers(7)))
    
    IPFensterLabel=Label(root,  text=IPEntry.get(), fg="black", bg= "white")
    IPFensterLabel.place(y=0, x=200, width= 100,height= 30)
        
    PortFenster =Label(root,text = PortEntry.get(), fg="black", bg="white")
    PortFenster.place(y=30, x=200, width= 100, height= 30)
        
    SOCFenster =Label(root,text = SOCEntry.get(), fg="black", bg="white")
    SOCFenster.place(y=80, x=200, width= 100, height= 30)
        
    SOHFenster =Label(root,text = SOHEntry.get(), fg="black", bg="white")
    SOHFenster.place(y=110, x=200, width= 100, height= 30)
        
    EntladeFenster =Label(root,text = EntladeEntry.get(), fg="black", bg="white")
    EntladeFenster.place(y=140, x=200, width= 100, height= 30)
        
    LadeFenster =Label(root,text = LadeEntry.get(), fg="black", bg="white")
    LadeFenster.place(y=170, x=200, width= 100, height= 30)
        
    ConnectionFenster =Label(root,text = "connected", fg="black", bg="white")
    ConnectionFenster.place(y=200, x=90, width= 120, height= 30)
            
    try:
               
        server.start()
        print("Server online")
        server.data_bank.set_input_registers(7, [SOCEntry.get()])
        server.data_bank.set_input_registers(8, [SOHEntry.get()])
        server.data_bank.set_input_registers(9, [EntladeEntry.get()])
        server.data_bank.set_input_registers(10, [LadeEntry.get()])
        time.sleep(1)
               
    except:
        server.stop()
        print("Server offline")
        

    print("Server is run:" + str(server.is_run)) 
    
    print("Value after writing:" + str(server.data_bank.get_input_registers(7)))
                  
   
 
#Button to entry print_entry()
#------------------------------------------------------------------------------
Button2= tk.Button(text="Write Data to Server",command= print_entry)
Button2.place(y=230, x=90,width= 120,height= 30)
    
#Button to close Programm
#------------------------------------------------------------------------------
QuitButton = tk.Button(text="Close Programm", command=root.destroy)    
QuitButton.place(y=260, x=90,width= 120,height= 30)

        
root.mainloop()

enter image description here `

When I run the script the UI window opens and I can write data into the fields. With a click on "Write Data to Server" the function print_entry() is called and the corresponding data is written into the registers. But this value is not saved. I see the value immediately after writing the data via the debug output, but when I call the function again there is a '0' in the register. I probably have a comprehension problem. Can you help me here?

enter image description here

Hotte
  • 11
  • 2
  • I think the code looks solid, so this is a modbus problem. Can you confirm that modbus does accept these values on these addresses you want to write to? – Ovski Dec 08 '22 at 22:13
  • You have created new server whenever `print_entry()` is executed, so the initial values in those registers are zero. – acw1668 Dec 09 '22 at 01:31
  • This looks like a [scope issue](https://www.w3schools.com/python/python_scope.asp); you are declaring `server` within the function `print_entry` which means it has Local Scope (and is lost when the function exits). Simplest solution is probably to make it a global (e.g. move `server=...` to the top level - see [this answer](https://stackoverflow.com/a/423596/11810946)). – Brits Dec 09 '22 at 01:32
  • If you want to *connect to a Modbus Server*, you need to create a *Modbus Client* instead. – acw1668 Dec 09 '22 at 02:12
  • @Ovski Thanks for your answer. How can i check this? In my print_entry() function i read the content of register 7, and it show the written data. – Hotte Dec 09 '22 at 08:40
  • @Hotte I have to say I don't know much about ModBus. But I just checked and it seems that input registers might be read only. You would have to try another register depending on what is available for you. For example the holding regsiter is read write. Hope this helps. – Ovski Dec 09 '22 at 19:19
  • @Ovski - Input registers are read only, but that only applies when communicating via Modbus. You can create a Modbus server and present whatever values you want (this is what the code is doing). The code in the question is, in effect, a Modbus server and the values are being set directly (not via Modbus). To test this Hotte is reading the values using a separate Modbus client (which should work; they could not use the Modbus client to change the value of the input registers). – Brits Dec 10 '22 at 02:35
  • @Brits I see... Makes sense that the sever should be able to write into its own register. And it also makes sense that the values can be read while the server is running. So the real question is: Is storing and loading of register data part of `pyModbusTCP.server.ModbusServer` or not. – Ovski Dec 12 '22 at 12:51

1 Answers1

0

Thanks for your answers! With the comment from @acw1668 i can now run a continous Modbus Server

enter image description here

Unfortunately, I can't read out the values ​​via a client. It seems the values ​​are still not being stored in the register

enter image description here

enter image description here

Hotte
  • 11
  • 2
  • When I run the client code, I can read the correct values from the server. – acw1668 Dec 09 '22 at 17:46
  • @acw1668 okay crazy now it works for me too. I am in the home office today, at work it had not worked. There was apparently a network problem. Thanks for your help :) – Hotte Dec 14 '22 at 09:29