Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

Modbus Tcp script problem!

Discussion in 'Scripting' started by kabouras33, Sep 6, 2019.

  1. kabouras33

    kabouras33

    Joined:
    Feb 16, 2018
    Posts:
    10
    Hello and nice to meet you all!
    My name is George and after 6 backbreaking days of trying to solve a single problem (and failed), I came here to ask for your help.
    I try to make a simple android app which will be connected through TCP/IP with my embedded module through Modbus. I decided to try unity for its graphics environment. I am aware of the basics of unity as well as C# (just the basics). So by researching a good example for Modbus TCP/IP I came up only with one result
    https://github.com/nodlag/umodbustcp.
    I believe that he has done a pretty amazing job but I cannot seem to fully understand it.
    As the example is pretty great I try to do two changes
    1. Read more addresses from the same IP and Port And display them in different input fields
    (ex. Modbus address 1 to inputfield1, Modbus address 2 to inputfield2 and so on)

    2. Remove the buttons and run the button functions automatically to update the values.

    Thank you for your time!

    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.UI;
    3. using System;
    4.  
    5. public class ExampleUModbusTCP2 : MonoBehaviour {
    6.  
    7.     //Public vars
    8.     public InputField inputIP;
    9.     public InputField inputPort;
    10.     public InputField inputAddress;
    11.     public InputField inputResponseValue;
    12.     public InputField inputResponseValue2;
    13.     public InputField inputResponseValue3;
    14.     ushort usAddress;
    15.     //Private vars
    16.     //UModbusTCP
    17.     UModbusTCP m_oUModbusTCP;
    18.     UModbusTCP.ResponseData m_oUModbusTCPResponse;
    19.     UModbusTCP.ExceptionData m_oUModbusTCPException;
    20.  
    21.     bool m_bUpdateResponse;
    22.     int m_iResponseValue;
    23.     int m_iResponseValue2;
    24.     int m_iResponseValue3;
    25.     void Awake() {
    26.         //UModbusTCP
    27.         m_oUModbusTCP = null;
    28.         m_oUModbusTCPResponse = null;
    29.         m_oUModbusTCPException = null;
    30.         m_bUpdateResponse = false;
    31.         m_iResponseValue = -1;
    32.         m_iResponseValue2 = -1;
    33.         m_iResponseValue3 = -1;
    34.         m_oUModbusTCP = UModbusTCP.Instance;
    35.     }
    36.  
    37.     void Start() {
    38.         //Fast values
    39.         //inputIP.text = "192.168.1.3";
    40.         //inputPort.text = "502";
    41.         //inputAddress.text = "2";
    42.     }
    43.  
    44.  
    45.     void Update() {
    46.         if(m_bUpdateResponse) {
    47.             m_bUpdateResponse = false;
    48.             inputResponseValue.text = m_iResponseValue.ToString();
    49.             inputResponseValue2.text = m_iResponseValue2.ToString();
    50.             inputResponseValue3.text = m_iResponseValue3.ToString();
    51.             m_oUModbusTCP.Dispose();
    52.         }
    53.        
    54.     }
    55.  
    56.     public void ButtonReadCoils() {
    57.  
    58.         //Reset response
    59.         m_bUpdateResponse = false;
    60.         m_iResponseValue = -1;
    61.        
    62.         //inputResponseValue2.text = string.Empty;
    63.  
    64.         //Connection values
    65.         string sIp = "192.168.1.3";
    66.         ushort usPort = 502;
    67.         usAddress = 1;
    68.  
    69.         if(!m_oUModbusTCP.connected) {
    70.             m_oUModbusTCP.Connect(sIp, usPort);
    71.         }
    72.  
    73.         if(m_oUModbusTCPResponse != null) {
    74.             m_oUModbusTCP.OnResponseData -= m_oUModbusTCPResponse;
    75.         }
    76.         m_oUModbusTCPResponse = new UModbusTCP.ResponseData(UModbusTCPOnResponseData);
    77.         m_oUModbusTCP.OnResponseData += m_oUModbusTCPResponse;
    78.  
    79.         //Exception callback
    80.         if(m_oUModbusTCPException != null) {
    81.             m_oUModbusTCP.OnException -= m_oUModbusTCPException;
    82.         }
    83.         m_oUModbusTCPException = new UModbusTCP.ExceptionData(UModbusTCPOnException);
    84.         m_oUModbusTCP.OnException += m_oUModbusTCPException;
    85.  
    86.         //Read coils
    87.         m_oUModbusTCP.ReadCoils(1, 1, usAddress, 1);
    88.  
    89.     }
    90.  
    91.     public void ButtonReadCoils2()
    92.     {
    93.  
    94.         //Reset response
    95.         m_bUpdateResponse = false;
    96.         m_iResponseValue2 = -1;
    97.         //inputResponseValue2.text = string.Empty;
    98.  
    99.         //Connection values
    100.         string sIp = "192.168.1.3";
    101.         ushort usPort = 502;
    102.         usAddress = 2;
    103.  
    104.         if (!m_oUModbusTCP.connected)
    105.         {
    106.             m_oUModbusTCP.Connect(sIp, usPort);
    107.         }
    108.  
    109.         if (m_oUModbusTCPResponse != null)
    110.         {
    111.             m_oUModbusTCP.OnResponseData -= m_oUModbusTCPResponse;
    112.         }
    113.         m_oUModbusTCPResponse = new UModbusTCP.ResponseData(UModbusTCPOnResponseData);
    114.         m_oUModbusTCP.OnResponseData += m_oUModbusTCPResponse;
    115.  
    116.         //Exception callback
    117.         if (m_oUModbusTCPException != null)
    118.         {
    119.             m_oUModbusTCP.OnException -= m_oUModbusTCPException;
    120.         }
    121.         m_oUModbusTCPException = new UModbusTCP.ExceptionData(UModbusTCPOnException);
    122.         m_oUModbusTCP.OnException += m_oUModbusTCPException;
    123.  
    124.         //Read coils
    125.         m_oUModbusTCP.ReadCoils(1, 1, usAddress, 1);
    126.  
    127.     }
    128.  
    129.     public void ButtonReadCoils3()
    130.     {
    131.  
    132.         //Reset response
    133.         m_bUpdateResponse = false;
    134.         m_iResponseValue3 = -1;
    135.         //inputResponseValue2.text = string.Empty;
    136.  
    137.         //Connection values
    138.         string sIp = "192.168.1.3";
    139.         ushort usPort = 502;
    140.         usAddress = 3;
    141.  
    142.         if (!m_oUModbusTCP.connected)
    143.         {
    144.             m_oUModbusTCP.Connect(sIp, usPort);
    145.         }
    146.  
    147.         if (m_oUModbusTCPResponse != null)
    148.         {
    149.             m_oUModbusTCP.OnResponseData -= m_oUModbusTCPResponse;
    150.         }
    151.         m_oUModbusTCPResponse = new UModbusTCP.ResponseData(UModbusTCPOnResponseData);
    152.         m_oUModbusTCP.OnResponseData += m_oUModbusTCPResponse;
    153.  
    154.         //Exception callback
    155.         if (m_oUModbusTCPException != null)
    156.         {
    157.             m_oUModbusTCP.OnException -= m_oUModbusTCPException;
    158.         }
    159.         m_oUModbusTCPException = new UModbusTCP.ExceptionData(UModbusTCPOnException);
    160.         m_oUModbusTCP.OnException += m_oUModbusTCPException;
    161.  
    162.         //Read coils
    163.         m_oUModbusTCP.ReadCoils(1, 1, usAddress, 1);
    164.  
    165.     }
    166.  
    167.  
    168.  
    169.     void UModbusTCPOnResponseData(ushort _oID, byte _oUnit, byte _oFunction, byte[] _oValues)
    170.     {
    171.  
    172.         //Number of values
    173.         int iNumberOfValues = _oValues[8];
    174.  
    175.         /*
    176.         //Get values pair with 2
    177.         int oCounter = 0;
    178.         for(int i = 0; i < iNumberOfValues; i += 2) {
    179.             byte[] oResponseFinalValues = new byte[2];
    180.             for(int j = 0; j < 2; ++j) {
    181.                 oResponseFinalValues[j] = _oValues[9 + i + j];
    182.             }
    183.             ++oCounter; //More address
    184.         }
    185.         */
    186.  
    187.         //Get values
    188.         if (usAddress == 1)
    189.         {
    190.             byte[] oResponseFinalValues = new byte[iNumberOfValues];
    191.             for (int i = 0; i < iNumberOfValues; ++i)
    192.             {
    193.                 oResponseFinalValues[i] = _oValues[9 + i];
    194.             }
    195.  
    196.             int[] iValues = UModbusTCPHelpers.GetIntsOfBytes(oResponseFinalValues);
    197.             m_iResponseValue = iValues[0];
    198.             m_bUpdateResponse = true;
    199.         }
    200.         if (usAddress == 2)
    201.         {
    202.             byte[] oResponseFinalValues = new byte[iNumberOfValues];
    203.             for (int i = 0; i < iNumberOfValues; ++i)
    204.             {
    205.                 oResponseFinalValues[i] = _oValues[9 + i];
    206.             }
    207.  
    208.             int[] iValues = UModbusTCPHelpers.GetIntsOfBytes(oResponseFinalValues);
    209.             m_iResponseValue2 = iValues[0];
    210.             m_bUpdateResponse = true;
    211.         }
    212.         if (usAddress == 3)
    213.         {
    214.             byte[] oResponseFinalValues = new byte[iNumberOfValues];
    215.             for (int i = 0; i < iNumberOfValues; ++i)
    216.             {
    217.                 oResponseFinalValues[i] = _oValues[9 + i];
    218.             }
    219.  
    220.             int[] iValues = UModbusTCPHelpers.GetIntsOfBytes(oResponseFinalValues);
    221.             m_iResponseValue3 = iValues[0];
    222.             m_bUpdateResponse = true;
    223.         }
    224.     }
    225.  
    226.     void UModbusTCPOnException(ushort _oID, byte _oUnit, byte _oFunction, byte _oException) {
    227.         Debug.Log("Exception: " + _oException);
    228.     }
    229. }
    230.  
     
  2. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,847
    You failed to mention what problem you're having beyond it "failed".
     
  3. kabouras33

    kabouras33

    Joined:
    Feb 16, 2018
    Posts:
    10
    I am very sorry!
    What I am trying to accomplish is to receive values from different addresses
    ButtonReadCoils()
    ButtonReadCoils2()
    and put them in their respected Input Fields and depict the values.
    With the above code, I can succeed to that but I have to press each button every time to do that.
    Basically I am trying to remove the buttons and run the functions
    ButtonReadCoils()
    ButtonReadCoils2()
    ButtonReadCoils3()
    from the update using invoke with a delay...but then all hell breaks loose...values are mixed depicting in every field available.
    I am trying to find a way to call the functions without pressing any buttons every 10seconds to update the values...
     
  4. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,847
    The use of usAddress looks like a problem to me. So when you make the request you set this to a different value based on which method is called, and when you process a response you use the same variable to determine which m_iResponseValueX to update. So if you call two different ButtonReadCoils methods, calling the second before getting the response back from calling the first, then the response from the first will be applied to the wrong m_iResponseValue variable since usAddress was changed before the response came back.

    How to fix this best I'm not exactly sure. I'd either prevent calling another ButtonReadCoils method until getting a response to an earlier one (which would probably break if getting a response isn't 100% guaranteed unless you use some kind of timeout, but still could get weird if responses occasionally come in after a timeout), or it would be better if there was some data included in the response itself which would tell you what m_iResponseValue variable you should use.

    Just as a quick test, try the below. Adjust the value of TimeBetweenRequests in the inspector to tighten or loosen the timing between requests as needed for how long it takes to reliably complete a response before the next request. I'd probably somehow use UModbusTCPOnResponseData to kick off the next request though, and if that request times out then initiate the next request from update. Not sure though, I've never played with what you're doing.

    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.UI;
    3. using System;
    4.  
    5. public class ExampleUModbusTCP2 : MonoBehaviour {
    6.  
    7.     //Public vars
    8.     public InputField inputIP;
    9.     public InputField inputPort;
    10.     public InputField inputAddress;
    11.     public InputField inputResponseValue;
    12.     public InputField inputResponseValue2;
    13.     public InputField inputResponseValue3;
    14.     ushort usAddress;
    15.     //Private vars
    16.     //UModbusTCP
    17.     UModbusTCP m_oUModbusTCP;
    18.     UModbusTCP.ResponseData m_oUModbusTCPResponse;
    19.     UModbusTCP.ExceptionData m_oUModbusTCPException;
    20.  
    21.     bool m_bUpdateResponse;
    22.     int m_iResponseValue;
    23.     int m_iResponseValue2;
    24.     int m_iResponseValue3;
    25.  
    26.     public float TimeBetweenRequests = 5f;
    27.     private float lastRequest = 0f;
    28.  
    29.     void Awake() {
    30.         //UModbusTCP
    31.         m_oUModbusTCP = null;
    32.         m_oUModbusTCPResponse = null;
    33.         m_oUModbusTCPException = null;
    34.         m_bUpdateResponse = false;
    35.         m_iResponseValue = -1;
    36.         m_iResponseValue2 = -1;
    37.         m_iResponseValue3 = -1;
    38.         m_oUModbusTCP = UModbusTCP.Instance;
    39.     }
    40.  
    41.     void Start() {
    42.         //Fast values
    43.         //inputIP.text = "192.168.1.3";
    44.         //inputPort.text = "502";
    45.         //inputAddress.text = "2";
    46.     }
    47.  
    48.  
    49.     void Update() {
    50.         if (Time.time >= lastRequest + TimeBetweenRequests)
    51.         {
    52.             switch (usAddress)
    53.             {
    54.                 case 1:
    55.                     ButtonReadCoils2();
    56.                     break;
    57.                 case 2:
    58.                     ButtonReadCoils3();
    59.                     break;
    60.                 case 3:
    61.                     ButtonReadCoils();
    62.                     break;
    63.                 default:
    64.                     ButtonReadCoils();
    65.                     break;
    66.             }
    67.             lastRequest = Time.time;
    68.         }
    69.  
    70.         if(m_bUpdateResponse) {
    71.             m_bUpdateResponse = false;
    72.             inputResponseValue.text = m_iResponseValue.ToString();
    73.             inputResponseValue2.text = m_iResponseValue2.ToString();
    74.             inputResponseValue3.text = m_iResponseValue3.ToString();
    75.             m_oUModbusTCP.Dispose();
    76.         }
    77.      
    78.     }
    79.  
    80.     public void ButtonReadCoils() {
    81.  
    82.         //Reset response
    83.         m_bUpdateResponse = false;
    84.         m_iResponseValue = -1;
    85.      
    86.         //inputResponseValue2.text = string.Empty;
    87.  
    88.         //Connection values
    89.         string sIp = "192.168.1.3";
    90.         ushort usPort = 502;
    91.         usAddress = 1;
    92.  
    93.         if(!m_oUModbusTCP.connected) {
    94.             m_oUModbusTCP.Connect(sIp, usPort);
    95.         }
    96.  
    97.         if(m_oUModbusTCPResponse != null) {
    98.             m_oUModbusTCP.OnResponseData -= m_oUModbusTCPResponse;
    99.         }
    100.         m_oUModbusTCPResponse = new UModbusTCP.ResponseData(UModbusTCPOnResponseData);
    101.         m_oUModbusTCP.OnResponseData += m_oUModbusTCPResponse;
    102.  
    103.         //Exception callback
    104.         if(m_oUModbusTCPException != null) {
    105.             m_oUModbusTCP.OnException -= m_oUModbusTCPException;
    106.         }
    107.         m_oUModbusTCPException = new UModbusTCP.ExceptionData(UModbusTCPOnException);
    108.         m_oUModbusTCP.OnException += m_oUModbusTCPException;
    109.  
    110.         //Read coils
    111.         m_oUModbusTCP.ReadCoils(1, 1, usAddress, 1);
    112.  
    113.     }
    114.  
    115.     public void ButtonReadCoils2()
    116.     {
    117.  
    118.         //Reset response
    119.         m_bUpdateResponse = false;
    120.         m_iResponseValue2 = -1;
    121.         //inputResponseValue2.text = string.Empty;
    122.  
    123.         //Connection values
    124.         string sIp = "192.168.1.3";
    125.         ushort usPort = 502;
    126.         usAddress = 2;
    127.  
    128.         if (!m_oUModbusTCP.connected)
    129.         {
    130.             m_oUModbusTCP.Connect(sIp, usPort);
    131.         }
    132.  
    133.         if (m_oUModbusTCPResponse != null)
    134.         {
    135.             m_oUModbusTCP.OnResponseData -= m_oUModbusTCPResponse;
    136.         }
    137.         m_oUModbusTCPResponse = new UModbusTCP.ResponseData(UModbusTCPOnResponseData);
    138.         m_oUModbusTCP.OnResponseData += m_oUModbusTCPResponse;
    139.  
    140.         //Exception callback
    141.         if (m_oUModbusTCPException != null)
    142.         {
    143.             m_oUModbusTCP.OnException -= m_oUModbusTCPException;
    144.         }
    145.         m_oUModbusTCPException = new UModbusTCP.ExceptionData(UModbusTCPOnException);
    146.         m_oUModbusTCP.OnException += m_oUModbusTCPException;
    147.  
    148.         //Read coils
    149.         m_oUModbusTCP.ReadCoils(1, 1, usAddress, 1);
    150.  
    151.     }
    152.  
    153.     public void ButtonReadCoils3()
    154.     {
    155.  
    156.         //Reset response
    157.         m_bUpdateResponse = false;
    158.         m_iResponseValue3 = -1;
    159.         //inputResponseValue2.text = string.Empty;
    160.  
    161.         //Connection values
    162.         string sIp = "192.168.1.3";
    163.         ushort usPort = 502;
    164.         usAddress = 3;
    165.  
    166.         if (!m_oUModbusTCP.connected)
    167.         {
    168.             m_oUModbusTCP.Connect(sIp, usPort);
    169.         }
    170.  
    171.         if (m_oUModbusTCPResponse != null)
    172.         {
    173.             m_oUModbusTCP.OnResponseData -= m_oUModbusTCPResponse;
    174.         }
    175.         m_oUModbusTCPResponse = new UModbusTCP.ResponseData(UModbusTCPOnResponseData);
    176.         m_oUModbusTCP.OnResponseData += m_oUModbusTCPResponse;
    177.  
    178.         //Exception callback
    179.         if (m_oUModbusTCPException != null)
    180.         {
    181.             m_oUModbusTCP.OnException -= m_oUModbusTCPException;
    182.         }
    183.         m_oUModbusTCPException = new UModbusTCP.ExceptionData(UModbusTCPOnException);
    184.         m_oUModbusTCP.OnException += m_oUModbusTCPException;
    185.  
    186.         //Read coils
    187.         m_oUModbusTCP.ReadCoils(1, 1, usAddress, 1);
    188.  
    189.     }
    190.  
    191.  
    192.  
    193.     void UModbusTCPOnResponseData(ushort _oID, byte _oUnit, byte _oFunction, byte[] _oValues)
    194.     {
    195.  
    196.         //Number of values
    197.         int iNumberOfValues = _oValues[8];
    198.  
    199.         /*
    200.         //Get values pair with 2
    201.         int oCounter = 0;
    202.         for(int i = 0; i < iNumberOfValues; i += 2) {
    203.             byte[] oResponseFinalValues = new byte[2];
    204.             for(int j = 0; j < 2; ++j) {
    205.                 oResponseFinalValues[j] = _oValues[9 + i + j];
    206.             }
    207.             ++oCounter; //More address
    208.         }
    209.         */
    210.  
    211.         //Get values
    212.         if (usAddress == 1)
    213.         {
    214.             byte[] oResponseFinalValues = new byte[iNumberOfValues];
    215.             for (int i = 0; i < iNumberOfValues; ++i)
    216.             {
    217.                 oResponseFinalValues[i] = _oValues[9 + i];
    218.             }
    219.  
    220.             int[] iValues = UModbusTCPHelpers.GetIntsOfBytes(oResponseFinalValues);
    221.             m_iResponseValue = iValues[0];
    222.             m_bUpdateResponse = true;
    223.         }
    224.         if (usAddress == 2)
    225.         {
    226.             byte[] oResponseFinalValues = new byte[iNumberOfValues];
    227.             for (int i = 0; i < iNumberOfValues; ++i)
    228.             {
    229.                 oResponseFinalValues[i] = _oValues[9 + i];
    230.             }
    231.  
    232.             int[] iValues = UModbusTCPHelpers.GetIntsOfBytes(oResponseFinalValues);
    233.             m_iResponseValue2 = iValues[0];
    234.             m_bUpdateResponse = true;
    235.         }
    236.         if (usAddress == 3)
    237.         {
    238.             byte[] oResponseFinalValues = new byte[iNumberOfValues];
    239.             for (int i = 0; i < iNumberOfValues; ++i)
    240.             {
    241.                 oResponseFinalValues[i] = _oValues[9 + i];
    242.             }
    243.  
    244.             int[] iValues = UModbusTCPHelpers.GetIntsOfBytes(oResponseFinalValues);
    245.             m_iResponseValue3 = iValues[0];
    246.             m_bUpdateResponse = true;
    247.         }
    248.     }
    249.  
    250.     void UModbusTCPOnException(ushort _oID, byte _oUnit, byte _oFunction, byte _oException) {
    251.         Debug.Log("Exception: " + _oException);
    252.     }
    253. }
    254.  
     
    eisenpony likes this.
  5. kabouras33

    kabouras33

    Joined:
    Feb 16, 2018
    Posts:
    10
    Dear Mr Joe!
    I am amazed!!! really!!!
    Your code worked like a charm the first time!!!
    Firstly I can not thank you enough for taking the time to bother and give me such a detailed and perfect solution!
    Secondly well done because without you knowing the complete project you could understand the main purpose and give the correct solution in a matter of hours...
    Bravo simply Bravo!
     
    Joe-Censored and eisenpony like this.
  6. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,847
    Glad it worked for you, and like I said I don't think this is the best solution, just a kind of brute force way just to see things working. You can certainly improve on it by making it a bit smarter.