Popular Post Porter Posted April 1, 2016 Popular Post Report Posted April 1, 2016 View File Plasmionique Modbus Master This package contains the Plasmionique Modbus Master library for LabVIEW. It supports RTU, ASCII and TCP modes with the following function codes: 0x01 - Read Coils 0x02 - Read Discrete Inputs 0x03 - Read Holding Registers 0x04 - Read Input Registers 0x05 - Write Single Coil 0x06 - Write Single Register 0x07 - Read Exception Status 0x0F - Write Multiple Coils 0x10 - Write Multiple Registers 0x16 - Mask Write Register 0x17 - Read/Write Multiple Registers 0x2B/0x0E - Read Device Identification Other features include: - Sharing a COM port across multiple Modbus sessions using VISA locks (10 second timeout). - Sharing a Modbus session across multiple communication loops. - TCP transaction ID handling to ensure that requests and responses are matched up correctly in case responses are received out of order. - Modbus Comm Tester, available through the "Tools->Plasmionique" menu, for testing communication with a slave device without writing any code. - Detailed help document available through the "Help->Plasmionique" menu. Examples are included in "<LabVIEW>\examples\Plasmionique\MB Master\": MB_Master Comm Tester.vi: Demonstrates usage of API to open/close connection and communicate with a Modbus slave device. MB_Master Multiple Sessions.vi: Demonstrates usage of API to open concurrent Modbus sessions. MB_Master Simple Serial.vi: Demonstrates polling of a single input register over serial line. Download a copy of the user guide here: MB_Master - User Guide.pdf Note that Version 1.3.4 of this library has been certified compatible with LabVIEW and has been released on the LabVIEW Tools Network: http://sine.ni.com/nips/cds/view/p/lang/en/nid/214230 The most recent version of this library will always be released on LAVA first before going through NI's certification process. ***This project is now available on GitHub: https://github.com/rfporter/Modbus-Master Submitter Porter Submitted 04/01/2016 Category LabVIEW Tools Network Certified License Type BSD (Most common) 7 1 Quote
smithd Posted April 3, 2016 Report Posted April 3, 2016 (edited) I like that you decided to simplify the RTU serial read...I was stubborn and wanted to follow the spec, I think that was a mistake. Serial APIs have come too far since RTU was created. The visa lock thing is neat, I didn't know that existed until recently. My only comment there is that if you went with a DVR for both you could put that in the parent class so you can't execute a query unless the parent lets you, which feels nicer to me. Probably not any real reason to do it. I also like that you somewhat simplified the class hierarchy. I can tell you right now I've never seen anyone make a new ADU or implement a new network protocol, so simplifying things on that front is great. The places I've seen extension are adding new function codes or changing slave behavior (which obviously doesn't apply here). A few other thoughts from that perspective: -I'd recommend pulling the PDU out of the ADU class and instead make the PDU a parameter of TX/RX and an output of RX. This is just a style thing of course but it makes the code easier to comprehend and for people adding new function codes its clearer where the data is going and what the library is doing with it. -I'd just make the PDU a typedef cluster. I went back and forth on this and ended up with the class, but I think that was a mistake. It doesn't need extension and doesn't need encapsulation, so.. -Pulling the individual 'build write...' and 'interpret response' functions out of the PDU class or library would, I think, make it feel like more of a level playing field for people adding new functionality. Like, it makes it clear that the function codes are happily mutable while in contrast you really shouldn't be touching "TX ADU". More importantly, it makes it less likely that someone adding a custom function code just adds it to your class and then saves it, making their version incompatible with the baseline. Edited April 3, 2016 by smithd 1 Quote
Porter Posted April 4, 2016 Author Report Posted April 4, 2016 Thanks for taking the time for review my code! I was originally thinking about doing something fancy with the PDU inside of the ADU but decided that it was better to let the PDU deal with itself. I agree there is no reason to have it in the ADU class. The simplification that I made to the RTU serial read was to cheat by having the "build PDU request" function calculate the expected number of data bytes of the PDU response. This way the RTU serial read procedure doesn't depend on timeouts or the function code. The downside of this is that when implementing new function codes, you need to remember to set the NumBytes parameter of the PDU request properly otherwise RTU serial read will not produce the expected response. This is why I was tempted to encapsulate the PDU in a class instead of a cluster. However, to make it easier to add functionality, I agree that it's a better idea make the PDU a cluster. Implementing a new function code is simply a matter of creating a VI that calls Querry.vi with the correct parameters. I've prepared an update with the following changes: Converted MB_PDU class to cluster Removed RTU inter-frame wait time optimization in TX ADU. It may have caused problems when sharing the serial port. Renamed NumBytes of MB_PDU to RTU_DataBytes Split interpret response VI of PDU into 3 VIs to handle different message types Set build and interpret VIs of PDU to private Removed function VIs from MB_Master class Removed PDU_req and PDU_resp from the MB_ADU class 1 Quote
bbean Posted May 3, 2016 Report Posted May 3, 2016 Hi Porter, Very nice library you put together. One quick question. Is there any reason the RX/TX data and timestamps are not available as a Read Property from parent Modbus Master Class. In situations where a device could be either a serial or tcp modbus, it would be nice to have access to that information at the parent level since it appears (unless I'm missing something) that the data is common to both the TCP and Serial Class. Brian 1 Quote
Porter Posted May 5, 2016 Author Report Posted May 5, 2016 During development I was using the RX/TX data and timestamps for debugging purposes only. I didn't really intend to expose them to the top level. I will look into creating accessors for them in the parent modbus master class. I'd rather not have the parent ADU class in the parent modbus master class though. Quote
Porter Posted May 6, 2016 Author Report Posted May 6, 2016 OK. I've worked it out. Modbus Master now has a dynamic dispatch accessor for ADU and Session Valid. I'm going to make an example for a TCP/Serial device this weekend and post an update. 2 Quote
Porter Posted May 24, 2016 Author Report Posted May 24, 2016 New version uploaded (V1.0.4). Now supports function codes with responses of unpredictable length in RTU mode (other modes already supported this). In RTU mode, if the RTU_DataBytes is set to less than zero, RX_ADU.vi expects that, in the response, the byte after function code is the number of data bytes. However, if the function code is 43, Modbus encapsulated interface transport message format is assumed. For now, only MEI type 14 is properly supported. Other MEI types rely on a timeout of 200 ms to determine the end of message. Quote
Porter Posted May 25, 2016 Author Report Posted May 25, 2016 Version 1.0.5 uploaded. Does anyone know the reason why Byte Count of Read FIFO Queue (function code 24) is 2 bytes long? Quote
ensegre Posted May 26, 2016 Report Posted May 26, 2016 Looking on http://www.modbus.org/docs/Modbus_Application_Protocol_V1_1b3.pdf (page 40), "because they say so"... If "why" means the rationale, maybe historical? UARTs with maximal buffers of 16K, and low bauds (not thinking of ethernet), so 16K was almost synonym of infinite time? Only speculating. Quote
Porter Posted May 26, 2016 Author Report Posted May 26, 2016 Perhaps they had the intention of allowing longer length responses at some point. According to the spec, Read FIFO Queue is limited to a maximum byte count of 64. The MSB of byte count will always be zero. This is just a little annoying though since the byte count parameter for any other function code is only 1 byte long. Quote
Mark Balla Posted June 3, 2016 Report Posted June 3, 2016 Certified 06-02-2016 and placed in the Hardware repository Quote
tarsel Posted July 6, 2016 Report Posted July 6, 2016 Hi Porter Great work, this looks excellent, thanks for sharing it. I am currently writing a development application to test an embedded device where we use Modbus to externalise values. Due to memory / power constraints we are probably going to create a custom Modbus version where the transmission protocol is RTU, but we want to use the LRC (ASCII) to check the transmission contents. It looks like I can do this using your library by adding another type of ADU class, inheriting from MB_ADU.lvclass. I have not used classes much at all yet, so I would be grateful if you could tell me whether I am on the right track. Thanks Ray Quote
Porter Posted July 6, 2016 Author Report Posted July 6, 2016 (edited) You can create a copy of the MB_ADU_RTU class and replace the Calc CRC-16 with whatever check that you want to do. You will probably also need to modify the RX ADU and TX ADU. After that, you should create a copy of MB_Master_Serial class and modify Open Serial Session to use your new MB_ADU_RTU class as its ADU. You can then use the function code vis on your new MB_Master_Serial class to communicate with your slave device. Let me know if you come up with a better way of doing this. I don't like creating copies of classes but this avoids modifying the original library. Edited July 6, 2016 by Porter Quote
tarsel Posted July 12, 2016 Report Posted July 12, 2016 Thanks Porter, I did not want to alter the original library either. I will implement this and report back. Thanks for the assistance. Quote
Porter Posted November 1, 2016 Author Report Posted November 1, 2016 Version 1.2.1 uploaded. It attempts to resolve a bug that we found in the VISA locking behavior implemented in MB_Master_Serial. See this forum topic for more information: https://lavag.org/topic/19871-visa-lock-behavior/ This version also adds a 10ms delay between retries in MB_Master_Serial "Querry.vi". Quote
Porter Posted December 5, 2016 Author Report Posted December 5, 2016 (edited) Version 1.2.1 is live on LabVIEW Tools Network. If you like our library, please consider leaving a review on the LVTN product page: http://sine.ni.com/nips/cds/view/p/lang/en/nid/214230 Edited December 5, 2016 by Porter Quote
ASalcedo Posted January 11, 2017 Report Posted January 11, 2017 Hello. Can it use in Labview 2015 SP1? Thanks Quote
ASalcedo Posted January 11, 2017 Report Posted January 11, 2017 Can it be used in an executable created with application builder? Quote
Porter Posted January 11, 2017 Author Report Posted January 11, 2017 Hello ASalcedo, Yes to both of your questions. Quote
ASalcedo Posted January 30, 2017 Report Posted January 30, 2017 Hello. I am trying to use this API. My first attempt in my personal computer was succes (serial RTU with PLC Panasonic) with MB_Master Comm Tester.vi example. Now I am triying to do the same in a laptop (same windows 10, same PLC, same wire, same Modbus configuration, same everything...) but it gives me an error when I click on "open device" and it says me that he could not open the device... The error is -1073807246 Any ideas to solve it? Thanks a lot Quote
Porter Posted January 30, 2017 Author Report Posted January 30, 2017 I haven't run into this error yet with this Library. It seems to be generated when VISA can not access the serial port. http://digital.ni.com/public.nsf/allkb/6807113B057FDE4C86256B41008212ED Sounds like the first thing to try is close LabVIEW and reboot the computer. Quote
ASalcedo Posted January 31, 2017 Report Posted January 31, 2017 On 1/30/2017 at 4:14 PM, Porter said: I haven't run into this error yet with this Library. It seems to be generated when VISA can not access the serial port. http://digital.ni.com/public.nsf/allkb/6807113B057FDE4C86256B41008212ED Sounds like the first thing to try is close LabVIEW and reboot the computer. Expand Hello. Thanks for replying. I fixed that error. It seems that another program was using the COM. Now I have 3 questions more and any help will be apprecciate it!: 1 - Before using this modbus Library I was using ni OPC Server and program run fine. Now I have an issue update rate with this library. I have a while and inside I have an event structure. In timeout event structure I read a holding register each 10ms (timeout=10ms). In some iterations for any reason Labview or modbus can not read the holding register (maybe once per 8 iterations). So Is there any way to solve this? Any update rate? or change time of timeout? 2 - With ni OPC server was easy to read a Real data type (unsigned 32 bits). Now I would like to read DDT8 (double word 32 bits) so I can not read just holding register addres 0x8 because it has just 16bits and I need 32bits. So I need to read 0x8 and 0x9 to form 32 bits. But how can I join those registers? and then How can I pass them to real? Because for exame if number real data type is 1,00 then holding registers are: 0x8=0, 0x9=16256 . So... how can I pass those registers to real data type? 3 - When I run my application the first time It opens modbus session well. Then when I abort the applicacion and restar aggain it says me that "modbus session is invalid". I think that the problem is that my program does not close fine the session. So is there any way to close every sessions before open one? So the first thing that the program does will be to close every session modbus. Config of my modbus session: baud rate=115200, stop bit = 1, parity = odd, timeout = 1000, retries = 1. Thanks a lot. Quote
Porter Posted January 31, 2017 Author Report Posted January 31, 2017 Please post your code, or send it to me via PM and I can take a look. #1, it would be very useful to know what error is reported when the read fails. #2, see attached. 0x8 is the low byte, 0x9 is the high-byte, the output is a single precision floating point number (32-bit) #3, it is very important to run "Close Session.vi" before exiting the program. This releases the lock on the serial port. Join registers to float.vi Quote
ASalcedo Posted February 2, 2017 Report Posted February 2, 2017 On 1/31/2017 at 6:07 PM, Porter said: Please post your code, or send it to me via PM and I can take a look. #1, it would be very useful to know what error is reported when the read fails. #2, see attached. 0x8 is the low byte, 0x9 is the high-byte, the output is a single precision floating point number (32-bit) #3, it is very important to run "Close Session.vi" before exiting the program. This releases the lock on the serial port. Join registers to float.viFetching info... Expand Thanks for replying. 1 - I've fixed the problem. Just I create a while to read every critic input each 10ms. 2 - Thanks a lot. It works. 3 - I am trying to fix this. Thanks again. Quote
Porter Posted February 2, 2017 Author Report Posted February 2, 2017 For #3, check the "MB_Master Simple Serial.vi" example located in "<LabVIEW>\examples\Plasmionique\MB Master\" or search for it in the Example Finder. Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.