Jerzy Tarasiuk Posted February 22, 2024 Report Posted February 22, 2024 Hello, I am just trying using Scripting to put Property Node and Method Nodes for accessing a serial port in FPGA VI. I can get these Nodes, and I suppose the property list and method are correct - but I don't know how am I to specify the serial port for these Nodes - when I select the port manually for a Node, it becomes correct. I can get the Property Node with FPGA I/O terminals (till npow I did not try this with a Method Node), but I don't know what should I put into a constant that I will connect to FPGA I/O input terminal (when I added the constant manually there, I was unable to select a serial port from I/O items menu). I can also use the Scripting to find serial ports in the target where I am putting the edited VI (it has Type String "RIO Subresource", Name "Port1", and Item ID (non-0, while its Source ID contains 0-s only). I am creating these Nodes using EIOPlaceDownEIOPropertyNode.vi and EIOPlaceDownEIOMethodNode.vi; the State input contains item="Mod1\Port1", the name is shown in the Node header line, and it is the same after assigning the serial port manually, but the manual assignment is needed to get the port name recognized. Have anyone found what function and how can be used to specify a serial port for these Nodes? Thanks in advance for any hint, Jerzy Tarasiuk Quote
Jerzy Tarasiuk Posted February 24, 2024 Author Report Posted February 24, 2024 (edited) Hello. Likely the problem could be solved if there were a way to create an "I/O Constant" (like this from FPGA I/O Palette) specifying a serial port - I can create an FPGA I/O terminal for a Method or Property Node., so connecting such an I/O Constant would configure these nodes. Unfortunately, seems I/O Constant cannot specify a serial port - at least I cannot select it in LabVIEW editor. Maybe some future LabVIEW version... The I/O Constant allows selection of project items that can be found using "Get All Descendents" method with Type="Elemental I/O" on an FPGA Target reference, or "eio_Utilities_GetAliasNames.vi" on an FPGA Application reference. Serial ports can be found using "eio_Utilities_GetNonAliasNames.vi" on an FPGA Application reference. Edited February 24, 2024 by Jerzy Tarasiuk added more info Quote
Rolf Kalbermatter Posted February 27, 2024 Report Posted February 27, 2024 On 2/24/2024 at 8:05 PM, Jerzy Tarasiuk said: Hello. Likely the problem could be solved if there were a way to create an "I/O Constant" (like this from FPGA I/O Palette) specifying a serial port - I can create an FPGA I/O terminal for a Method or Property Node., so connecting such an I/O Constant would configure these nodes. Unfortunately, seems I/O Constant cannot specify a serial port - at least I cannot select it in LabVIEW editor. Maybe some future LabVIEW version... The I/O Constant allows selection of project items that can be found using "Get All Descendents" method with Type="Elemental I/O" on an FPGA Target reference, or "eio_Utilities_GetAliasNames.vi" on an FPGA Application reference. Serial ports can be found using "eio_Utilities_GetNonAliasNames.vi" on an FPGA Application reference. I think you are confusing an IO signal with a logical interface. The serial port is typically a logical device that contains a TxD and RxD pin and possibly others. On the FPGA you deal exclusively with IO signals. But there is no way to access the serial port as an IO signal. Either you would have to access the individual IO pins that make up the serial port individually and implement the serial port bit protocol yourself in FPGA or you need to access the serial port through the RT OS on the controller as serial port and let the OS driver handle the actual IO control (usually it doesn't really control the IO pins directly but uses a device driver to communicate with the serial port registers). Quote
Jerzy Tarasiuk Posted February 27, 2024 Author Report Posted February 27, 2024 (edited) Are you sure? I initially supposed NI-9871 serial ports are accessed via the RT OS, but I was pointed that I was wrong - they are connected to FPGA and the RT OS accessed them via FPGA. Seems to be sure I need a test: write a LabVIEW FPGA program that will send data via a serial port, start the FPGA program and reboot the RT OS (it is configured to allow the FPGA program to continue), monitoring the serial port data on a PC host: if the serial port is accessed via the RT OS, the data will be disturbed. I hope these serial ports are connected directly to FPGA - it is important for safety of the system. In LabVIEW FPGA NI-9871 serial ports are accessed using Property and Method nodes (there are several properties and 3 methods - Read Byte, Write Byte, Clear Rx FIFO); I/O Node cannot be used for them. Seems that two serial ports on cRIO itself (not on a C-Module) can be accessed from RT OS only, as well as serial ports connected via USB ports. Edited February 27, 2024 by Jerzy Tarasiuk added serial port method names Quote
Rolf Kalbermatter Posted February 28, 2024 Report Posted February 28, 2024 15 hours ago, Jerzy Tarasiuk said: Are you sure? I initially supposed NI-9871 serial ports are accessed via the RT OS, but I was pointed that I was wrong - they are connected to FPGA and the RT OS accessed them via FPGA. Seems to be sure I need a test: write a LabVIEW FPGA program that will send data via a serial port, start the FPGA program and reboot the RT OS (it is configured to allow the FPGA program to continue), monitoring the serial port data on a PC host: if the serial port is accessed via the RT OS, the data will be disturbed. I hope these serial ports are connected directly to FPGA - it is important for safety of the system. In LabVIEW FPGA NI-9871 serial ports are accessed using Property and Method nodes (there are several properties and 3 methods - Read Byte, Write Byte, Clear Rx FIFO); I/O Node cannot be used for them. Seems that two serial ports on cRIO itself (not on a C-Module) can be accessed from RT OS only, as well as serial ports connected via USB ports. Well I'm for sure sure about the built in serial ports on cRIOs and sbRIOs. The987x serial C modules are a different story. And serial ports through USB ports definitely never ever could be just accessed from FPGA mode. You need at least a USB-CDC driver and while that might be possible in FPGA, it is not something that the Xilinx chips that are used on the RIO hardwares would even support, even if you might find some IP design somewhere implementing that. The communication channels such as Ethernet, Uart, USB and similar are NOT directly routable to the FPGA fabric but only accessible through their register interface, which requires a software driver to control them (and an OS on which that driver can be loaded). Quote
Jerzy Tarasiuk Posted February 28, 2024 Author Report Posted February 28, 2024 Hello. I need access serial ports of NI-9871. From https://www.ni.com/pl-pl/shop/model/ni-9871.html they are directly accessible from FPGA: Quote The NI‑9871 adds RS485/RS422 serial ports to CompactRIO systems. The serial ports are accessed directly from the FPGA to offer you flexibility in communicating with serial devices. The module has individual buffers on every port that save FPGA space and simplify programming. Quote
Rolf Kalbermatter Posted February 28, 2024 Report Posted February 28, 2024 (edited) 8 minutes ago, Jerzy Tarasiuk said: Hello. I need access serial ports of NI-9871. From https://www.ni.com/pl-pl/shop/model/ni-9871.html they are directly accessible from FPGA: So what is your problem or question? I never said that you can't access the 987x modules from FPGA. But you never specified in your OP that you meant those. As far as scripting these things, it's undocumented territory. And complicated enough that reverse engineering would be a pretty tedious job. Supposedly the C module development Toolkit has some documentation about how so called Elemental IO can be created, but I highly doubt that it documents how that is done through scripting, but it simply provides some tools that do all these things behind the surface. That Toolkit was however not free (~1600 for non-commercial version, 6k for commercial version). The non-commercial version does let you develop your own C modules, but you are not allowed to sell them to others. However it is not anymore findable in the NI store as an order-able product. Edited February 28, 2024 by Rolf Kalbermatter Quote
Jerzy Tarasiuk Posted February 29, 2024 Author Report Posted February 29, 2024 Hello, Rolf. Thank you for the time you are spending on it. My problem is: I can create - using Scripting - a serial port Method Node (with EIOPlaceDownEIOMethodNode.vi, for any of 3 methods the port has), or a Property Node (with EIOPlaceDownEIOPropertyNode.vi, having read/write elements for a set of properties which I wish); and then I can assign a serial port to the node using LabVIEW editor (i.e. click the node with a mouse, select from menu...); but I cannot assign the port with Scripting. When creating these nodes using Scripting, I was putting the port name as 'item' in the State cluster (EIOMethodNode.xnode:EIOMethodNode.ctl or EIOPropertyNode.xnode:EIOPropertyNode.ctl) - the name was shown in the created node title, as it is shown after manual assignment, but the node did not recognize the name as a serial port and was shown as misconfigured. I don't know where it is going wrong: maybe the port name I specify is incorrect (it requires some prefix that isn't shown in the node title, but is necessary for the name to be recognized), maybe except the EIOPlaceDownEIO* some other function is necessary to make the setting active. Is there a way to get State from such a node that was configured manually and see what is its 'item' value? With kind regards, Jerzy Quote
Rolf Kalbermatter Posted March 2, 2024 Report Posted March 2, 2024 (edited) This is undocumented territory for sure and as such there is a high chance that: - parts of what you want to do might be obscure and difficult to impossible to find out without the according non-public documentation - it might be present but not implemented, either returning an error or simply doing nothing - it might be simply not possible as the LabVIEW developers haven't found a need for this particular operation yet, and why would they spend time on implementing something that is neither a public function nor required for internal use? Edited March 2, 2024 by Rolf Kalbermatter Quote
Mads Posted March 3, 2024 Report Posted March 3, 2024 On 2/28/2024 at 12:33 AM, Jerzy Tarasiuk said: Are you sure? I initially supposed NI-9871 serial ports are accessed via the RT OS, but I was pointed that I was wrong - they are connected to FPGA and the RT OS accessed them via FPGA. Seems to be sure I need a test: write a LabVIEW FPGA program that will send data via a serial port, start the FPGA program and reboot the RT OS (it is configured to allow the FPGA program to continue), monitoring the serial port data on a PC host: if the serial port is accessed via the RT OS, the data will be disturbed. I hope these serial ports are connected directly to FPGA - it is important for safety of the system. In LabVIEW FPGA NI-9871 serial ports are accessed using Property and Method nodes (there are several properties and 3 methods - Read Byte, Write Byte, Clear Rx FIFO); I/O Node cannot be used for them. Seems that two serial ports on cRIO itself (not on a C-Module) can be accessed from RT OS only, as well as serial ports connected via USB ports. The 987x modules *can* be accessed just like any other in-built serial port (using the VISA serial functions) as long as you have installed the 987x support package on the cRIO (option that should be available in the list when you choose to install the system image etc on it). No need to even think about their connection to the FPGA then. Now, before that support package was available you did need to add FPGA code, but even then that code is available as an example so you do not need to figure much out anymore...We used the FPGA-method 15 years back or so, now we just install the support package and use it with VISA. Quote
Jerzy Tarasiuk Posted March 3, 2024 Author Report Posted March 3, 2024 Hello. My aim is to access these ports directly from FPGA program, without VISA and drivers that are in RT part. It is possible when the program is edited manually in LabVIEW development environment. Quote
Mads Posted March 4, 2024 Report Posted March 4, 2024 8 hours ago, Jerzy Tarasiuk said: Hello. My aim is to access these ports directly from FPGA program, without VISA and drivers that are in RT part. It is possible when the program is edited manually in LabVIEW development environment. And to do that you can use the examples you find if you search for 987 in LabVIEW examples. But you are for some reason also trying to script the creation of such code, is that an additional requirement or could you just edit the examples and compile it into your bitfile? Quote
Jerzy Tarasiuk Posted March 4, 2024 Author Report Posted March 4, 2024 Hello. Seems none of these examples show how to use VI Scripting to create an FPGA VI that accesses NI-987x serial port... Quote
Rolf Kalbermatter Posted March 4, 2024 Report Posted March 4, 2024 Elemental IO is not a public documented feature. The according project provider knows how to do it but it was never intended to have that interface opened as a user accessible feature. And the main reason is not that NI is evil and wants to deprive you of the fun to thinker with this but because they want to prevent customers to create easily crashing projects that require an immense support demand that NI is not able to fulfill. Quote
Mads Posted March 4, 2024 Report Posted March 4, 2024 2 hours ago, Jerzy Tarasiuk said: Hello. Seems none of these examples show how to use VI Scripting to create an FPGA VI that accesses NI-987x serial port... Yes, I never said they did, but I did wonder why you need to script their creation. Quote
Neil Pate Posted March 5, 2024 Report Posted March 5, 2024 @Jerzy TarasiukI think what a few of us are saying is do you really need to script this code, or can you just make it once or twice manually for your use-cases and move on with life? It should be a pretty big red flag that after several decades of LabVIEW FPGA/RT nobody else has really done this. Quote
Jerzy Tarasiuk Posted March 5, 2024 Author Report Posted March 5, 2024 Hello. I want to create a VI for each serial port that will configure the port according to configuration data sent to the VI - this requires many connections inside the VI and results in many possibilities of mistakes in these connections if they are to be done manually. I would like to avoid these mistakes. Currently, I can use Scripting to create Method Nodes and Property Nodes needed, then request setting the serial port in them manually, then use Scripting to create connections, and finally report all connections to a text file for verification. But I neither know how to set the serial port in these nodes using Scripting, nor I know how to get these settings for verification. BTW: is it possible that two Property Nodes for a serial port look identically (have the same port in their header lines, the same elements, data types for these elements are shown by the same colors...), but have different functionality (e.g. something hidden was created in one of these nodes while editing it)? Quote
Mads Posted March 5, 2024 Report Posted March 5, 2024 1 hour ago, Jerzy Tarasiuk said: Hello. I want to create a VI for each serial port that will configure the port according to configuration data sent to the VI - this requires many connections inside the VI and results in many possibilities of mistakes in these connections if they are to be done manually. I would like to avoid these mistakes. Currently, I can use Scripting to create Method Nodes and Property Nodes needed, then request setting the serial port in them manually, then use Scripting to create connections, and finally report all connections to a text file for verification. But I neither know how to set the serial port in these nodes using Scripting, nor I know how to get these settings for verification. BTW: is it possible that two Property Nodes for a serial port look identically (have the same port in their header lines, the same elements, data types for these elements are shown by the same colors...), but have different functionality (e.g. something hidden was created in one of these nodes while editing it)? Any code can contain errors. If you script the code you are just adding another layer where you can have errors (the script itself, in addition to the code it generates). When the script has created the code you still have to test the generated code to see if it works correctly. If you write it manually and test it (easier than testing scripts as you can test its intermediate steps directly as you progress) you can use that code for all ports, not just for one. Having to repeatedly create complex but similar code from scratch could justify doing it with scripting to reduce the risk of human errors, but here you can still handle it by having the code cover all scenarios and/or with code reuse . And much of the code has been written and tested for you already (examples) so all you need to do is add whatever extra functionality you need and test those changes. Have you tried solving this the easy way by relying on the RT OS and VISA support already, but observed that it does not meet the your reliability requirements? Or have you just assumed that it will not and are optimizing it prematurely, making the path to a working solution unnecessarily hard and complex? Quote
Jerzy Tarasiuk Posted April 9, 2024 Author Report Posted April 9, 2024 (edited) I need a program in FPGA to control a hardware, without mediation of RT part - and I plan to use LabVIEW for the FPGA only. Because of this, there is no place for using VISA. I want to have the same code for each serial port - they are to be configured differently, but the configuration should be passed as data to the code that is to set it to these ports. FPGA has access to these ports (the VISA would access them via FPGA), but I don't know how to place a port name in LabVIEW - the only way I know is to select manually the port resource for each Property and Method used to access the port. And I don't know how can I programmatically verify that the correct port resource is selected in each place, as I have no way to read it. Edited April 10, 2024 by Jerzy Tarasiuk corrected misspelling Quote
Jerzy Tarasiuk Posted April 12, 2024 Author Report Posted April 12, 2024 Hi, seems I found a solution. The program should do the following: use Invoke Node for This Application constant to open a project with an FPGA target; use Property Node on the project ref to get targets; look for a matching FPGA target (in my example I also compare target name, so it can handle a project with many FPGA targets if it happens), closing the other target refs; use Property Node on the selected target ref to get its Application ref; create (or open) a VI for the Application, open its BD window, gets its BD ref; (the above action is in the upper line of my VI) use eio_Utilities_GetNonAliasNames.vi on the Application to get names to be used: - "persistent names" output gives names (array of strings) that can be used, - "resource names" and "display names" (arrays of strings) can be used to find an element in the "persistent names" - choose e.g. Mod1\Port3 in display names, and use its index on the "persistent names" to get required persistent name; the persistent name is to be used as "item" for EIOPlaceDownEIOMethodNode.vi and for EIOPlaceDownEIOPropertyNode.vi - the "item" is in "State" cluster; few other elements of the "State" cluster, common for these both "Place"-s, are: "alias selected", "DoSpecify", "ref in wired", "ignore ref inputs"; the "alias selected" must be False, the "ref in wired" must be True; do the other matter? I don't know; making a Method needs also a "method name" to be set, valid methods for an NI9871 serial port are "Clear Rx FIFO", "Read Byte", "Write Byte"; for making a property I specified "id counter" = 1 (is it needed? I don't know), and of course the "properties" - an array of clusters, in each of them I set: "name" (string), "direction" (enum, I used read or write), "terminal id" (int); each "Place" needs also Diagram (I used the BD ref), context (= Application ref), and "Position" (a cluster containing left-top corner coordinates); each "Place" returns a "Terms[]" - an array of terminals - I show some info on them. Attached files: a picture w/ BD and FP, a PDF containing the BD, the VI (LabVIEW 2018). ni9871cmp.pdf ni9871cmp.vi Quote
Jerzy Tarasiuk Posted April 16, 2024 Author Report Posted April 16, 2024 Yet another program: list I/O names and methods/properties available for each of them. Inputs for the VI: LabVIEW project path, FPGA target name, log path (for writing the info). A sample of I/O name lines from the log: Quote +++crio_M3 +++crio_M4 +++crio_Module5 +++crio_Mod6 +++crio_Mod1 +++crio_Mod1/Port1 +++crio_Mod1/Port2 +++crio_Mod1/Port3 +++crio_Mod1/Port4 +++crio_Mod7 +++/Chassis Temperature +++/Sleep +++/System Reset +++/USER FPGA LED +++/USER Push Button +++/Scan Clock +++/crio_M3/DO0 +++/crio_M3/DO1 +++/crio_M3/DO2 +++/crio_M3/DO3 These '+'-es at the beginning of each line tell that looking for methods/properties of the I/O item found the item and no error resulted from the operation (each '+' has a different meaning, but I was getting +++ only). First 10 names have no leading '/' - they were found as non-alias names, all remaining - as alias names. Quote +++crio_Module5 m: Check Output Status p: Module ID (R) p: Serial Number (R) p: Vendor ID (R) +++crio_Mod6 m: IO Sample m: Set Terminal Mode m: Set Triggers m: Set Voltage Range p: Linearization Coefficient 0 (R) p: Linearization Coefficient 1 (R) p: Linearization Coefficient 2 (R) p: Linearization Coefficient 3 (R) p: LSB Weight (+/- 10V range) (R) p: LSB Weight (+/- 1V range) (R) p: LSB Weight (+/- 200mV range) (R) p: LSB Weight (+/- 5V range) (R) p: Module ID (R) p: Offset (+/- 10V range) (R) p: Offset (+/- 1V range) (R) p: Offset (+/- 200mV range) (R) p: Offset (+/- 5V range) (R) p: Serial Number (R) p: Vendor ID (R) +++crio_Mod1 p: Module ID (R) p: Serial Number (R) p: Vendor ID (R) +++crio_Mod1/Port1 m: Clear Rx FIFO m: Read Byte m: Write Byte p: Baud Rate (W) p: Baud Rate Divider (Bw) p: Baud Rate Prescaler (Bw) p: Break state (W) p: Bytes at Port (R) p: CTS state (R) p: Data Bits (Bw) p: DTR state (W) p: Flow Control (Bw) p: Parity (Bw) p: RTS state (W) p: Stop Bits (Bw) p: Transceiver Mode (Bw) p: XOFF character (Bw) p: XON character (Bw) Here crio_Module5 is NI9476, it has a "Check Output Status" method and 3 properties (these properties common to all C-Modules, and they are read-only, it is shown by '(R)'); crio_Mod6 is NI9205, it has 4 methods and 15 properties; crio_Mod1 is NI9871, it has 3 properties and no methods; its Port1 has 3 methods and several properties, some are read-only (R), some write-only (W), some bidirectional default-write (Bw), a (Br) would mean bidirectional default-read. Quote +++crio_Mod7 p: Conversion Time (Bw) p: Module ID (R) p: Serial Number (R) p: Vendor ID (R) +++/Chassis Temperature m: Read +++/Sleep m: Read m: Write +++/System Reset m: Read m: Write +++/USER FPGA LED m: Read m: Write +++/USER Push Button m: Read +++/Scan Clock m: Read m: Wait on Rising Edge p: Enabled (R) p: High Time (R) Here crio_Mod7 is NI9208, it has 4 properties (an additional is "Conversion Time"). Then alias I/O items follow: "Chassis Temperature" can be read, "Sleep" can be read and written, as well as "System Reset" and "USER FPGA LED", "USER Push Button" can be read, and "Scan Clock" has 2 methods and 2 properties. Quote +++/crio_M3/DO0 m: Read m: Write +++/crio_M4/DI0 m: Read +++/crio_Module5/DO0 m: Read m: Write +++/crio_Mod6/AI0 m: Read +++/crio_Mod6/AI31 m: Read +++/crio_Mod6/Trig m: Read +++/crio_Mod6/DI0 m: Read +++/crio_Mod6/DO0 m: Write +++/v1/SignalList/a.b0 m: Write +++/v1/SignalList/aw m: Read Here crio_M3 is NI9477, its DO0 signal can be read and written, as well as DO0 signal of crio_Module5 (NI9476); crio_M4 is NI9425, its DI signal can be read, as well as crio_Mod6 (NI9205) AI0 and AI31 signals. The NI9205 has also Trig signal (read-only), DI0 signal (read-only), DO0 signal (write-only). And finally few CLIP signals: "/v1/SignalList/a.b0" is "a.b0" of CLIP "v1" (write-only), "/v1/SignalList/aw" is "aw" signal of the CLIP (read-only). Attached: a VI used to produce the list and its BD picture. io_names_list2l.vi Quote
Jerzy Tarasiuk Posted April 18, 2024 Author Report Posted April 18, 2024 Some additions: the name ni9871cmp is an abbreviation from NI9871 Create Methods and Properties. when looking for a way to create them, I attempter to use "pylabview" https://github.com/mefistotelis/pylabview to examine VI-s created manually and with scripting and to find their differences; first of all, the "pylabview" is said to be for LabVIEW 2014 - in fact, it couldn't handle VI-s from the LabVIEW 2018 I am using, and it couldn't handle VI-s saved for older LabVIEW versions until I specified as old as 2011; even then, when I used the pylabview to extract contents of a VI containing a valid serial port Method or Property, none of text files produced contained the port name - I found the port name in a binary file only, and it contained UUID-s in "{}", with ">>" as a separator, like "Mod1.{uuid1}>>Port2.{uuid2}" - and I found this all must be exactly the same for the port to be recognized - when I put exactly this string in the alue used for port specification, the scripting produced valid Methods and Properties; then I started to look for a function that can get such a string from my project... 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.