Jump to content

smithd

Members
  • Content Count

    716
  • Joined

  • Last visited

  • Days Won

    42

Everything posted by smithd

  1. i think if you put the img display in snapshot mode its synchronous? I agree that imaq needs refs, but why does it need named refs? Thats the part thats horrifying
  2. Yes, I don't really care about that, and I will use block diagram cleanup until its pried from my cold dead hands 👻 Some of the key parts (like the engine) are relatively neat (by my standards) but due to the complexity its definitely still a hot mess. And of course a lot of the code dealing with all of the data types is scripted because aint nobody got time for that. Your other comments are fair though, some definite mistakes were made in the design, but all told I think it does a decent job. Yeah, I made an aborted attempt (https://github.com/LabVIEW-DCAF/ModuleInterface/tree/StreamingAndEvents and https://github.com/LabVIEW-DCAF/ExecutionInterface/tree/StreamsAndEvents) but...then I left NI. The nature of labview merging is such that those branches are probably now useless edit: theres probably a few implementation-side branches too like https://github.com/LabVIEW-DCAF/StandardEngine/tree/StreamsAndEvents
  3. Labview doesn't provide a way to check the status of the TCP connection except by trying to use it. Serial modbus has no physical way to check the connection except by using it. In both cases you need to use it to see if it still works. On the master (client) side you will see any of the TCP error codes (56, 62 and 63 being the most common as I recall) for the TCP master. For serial masters, you will only ever see 56. I suppose some VISA-specific codes are also possible, like if there are parity bit errors or if you're using a usb-serial device that gets unplugged, that sort of stuff. Modbus protocol errors are - 389110 as mentioned above. On the slave (server) side you will never see an error from the data access methods because the access is local. You can check (via a property node, I think) on the status of all connected masters (clients) for TCP. Serial is 1-1 and has no concept of a connection, so I think it just tells you the last error to occur for the serial comms process.
  4. cRIO is all linux, PXI now supports linux: https://www.ni.com/product-documentation/55164/en/
  5. I wouldn't do this. Its probably ok in this limited case, but its possible to make labview crash in this way. A better route is the variant, which has the same capabilities (cast to an opaque untyped blob and back again) but without the danger.
  6. Doing a quick search, C++ doesn't permit access scope for the class itself -- only at the member level. In other words the class itself is always public
  7. As described, anyone can take your DVR, unbundle it, and get access to the class. Since this is possible, and the class is private, it must be blocked. Technically this doesn't make much sense for labview classes since their data is private by default. Makes more sense for clusters, where enclosed data is private, so maybe thats why. You can make the methods of the class private, but the class itself must be public. Or, you could use a DVR of the base labview object and then cast it when you use it, inside of your library.
  8. Depends on the database. For example, oracle does not support multiple inserts in a single query like that. Instead you'd have to use: INSERT INTO T_Column (C_Name , C_Status) VALUES('21' , 'Not realised'); INSERT INTO T_Column (C_Name , C_Status) VALUES('22' , 'Not realised'); On the one hand this sucks, but on the other hand if you're using oracle this is probably the least of your worries. On a related note, it looks like you are manually generating sql queries. While fine for development, its generally recommended to use parameterized statements to help avoid sql injection attacks.
  9. afraid not, I moved on to 2017. At this point I think your best bet is to use a pre-2017 version (pre-vim). You can backsave but the vims make it annoying. If you are windows-only, I think the labview runtime now supports several versions back and forth, so it might be possible to build the 2017 library into a packed library (very much like a dll, but pure labview code) and reference that. Probably not worth it though. 2015 is 4 years old at this point, might be worth investigating an update.
  10. the terminology NI was using a few years ago was tag/stream/message and i believe the descriptions are as follows: messages have a non-fixed rate, mixed data types, and should generally be as lossless as possible with minimal latency, with the note that anything requiring confirmation of action must be request-response which takes you down the rabbit hole of idempotence (ie what happens if the response is lost, request is reissued -- does the customer get 2 orders?). Messages are usually 1:N (N workers for 1 producer) or N:1 (N clients for 1 process), but this isn't required. streams have a fixed rate, fixed type, and generally latency isn't an issue but throughput is. Losslessness is a must. Usually 1:1. tags are completely lossy with a focus on minimal latency. The addon to this would be an 'update' which is basically a message oriented tag (eg notifier, single element queue). Usually 1:N with 1 writer and N readers. all three overlap, but I think these three concepts make sense.
  11. Of the messaging things plain queues should be the fastest message-oriented option because everything else (I think) is built on top. Notifiers, channels, etc use queues. All these options are pretty quick. >Last I remember reading, user event queues rely on some of the same underlying bits, but the UI-oriented and pub-sub nature of the code makes them a bit slower. Still generally fast enough for anything anyone ever uses them for. >>User events are completely nondeterministic (every option in this category is nondeterministic technically, but user events behave like garbage if you stress them). Property nodes obviously require locking the UI thread and suck, but control indices are sufficiently fast for most anything. If you eliminate the update-oriented part -- just sharing scalar values in other words -- then the fastest would be a global (requires a lock for write but I think the read side doesn't), then a DVR in read-only mode, then a standard DVR or FGV implementation (both need to lock a mutex). These are all faster than the message oriented variations, obviously, but thats because you get less than half the functionality.
  12. Its similar to flattening a cluster, except its cross language. It accomplishes this by having scripts which take a message definition and generate code in that language. This makes it easy to send a protobuf message, which might be represented in labview as a cluster*, to C or java or python or go or wherever. Its primary benefit over something like json is a slightly more extensive type system and speed. This won't get you any of what I described but if you just need super basic support for generating a valid message manually: https://github.com/smithed/experiments/tree/master/Protocol Buffers It would need a ton of work to actually support scripting. Doesn't seem like there is enough of an advantage. *I'm pretty sure it always has to be a class actually due to things like optional data values.
  13. https://www.ni.com/pdf/manuals/371780r.pdf yay! 🎉 too bad nxg breaks the code
  14. The term you are looking for is a cluster, equivalent to a C struct more or less. You create a type definition like this: https://zone.ni.com/reference/en-XX/help/371361R-01/lvhowto/creating_type_defs/ once you are in the control editor for the type definition, what you want to do is drop down a cluster control. ctrl+f for "clusters" on this document for a video: https://www.ni.com/getting-started/labview-basics/data-structures or in tutorial form: https://www.ni.com/tutorial/7571/en/ Depending on where you're at, you may have access to NI online training, or other resources found on this page: https://labviewwiki.org/wiki/Training
  15. To go further, the timed loop is the not the right choice, and the RT FIFO has a negative performance impact on this application. The data source (daqmx) is nondeterministic, the data client (tdms) is nondeterministic, so using an RT FIFO as I understand it will result in performing a memory copy on every iteration to copy from the (newly allocated and thus non-deterministic) daqmx buffer to the preallocated RT FIFO buffer. In contrast a normal queue (again as I understand) will simply shuffle around a pointer to the buffer provided by daqmx*. No allocation past the one performed by daqmx and a minor one to allocate the queue structure. By using a timed loop you're forcing everything to run in a single thread, so if you add any additional code later into the daqmx loop, it would have to run in series with the daqmx api reads. You're also telling the RT OS that the HIGHEST priority loop/thread in your entire codebase is something which immediately hits an asynchronous call and waits for that call to return. *I think technically its passing around a struct with an inline timestamp and dt, and then a variant pointer and an array pointer, but you get the idea. 2.2: you can make it fixed by passing in a samples to read per channel input on the daqmx read VI. The default is -1, which tells the driver to return whatever is available but don't wait for new data. 4 By definition the two loops have to run at the same rate...on average. As shown (a kind of producer-consumer implementation), you really want the daqmx loop to be driving the logger loop, which is easy to do with a fifo or queue -- you pass in -1 for the timeout, and as data arrives the bottom loop will run. As you have it, the tdms loop is simply running every 5 ms. Instead of a queue or shared variable, you can also use channel wires which are intended to make data communication a bit more user friendly. They even have an RT FIFO option if you ever do need that: https://www.ni.com/product-documentation/53423/en/
  16. What are you trying to output to? A graph? A daq card? If its in one of the pictures, only 2 came through on my end, the rest show up as blank squares.
  17. Generally RT code doesn't have a UI, and as mentioned you have to use a special add-on to use events with shared variables. The usual equivalent is to use a messaging tool to handle communication and generate events in your RT code. I personally use HTTP and/or websockets since its free and there are many clients out there. I believe there is a tcp handler for drjdp's messenger lib (https://sine.ni.com/nips/cds/view/p/lang/en/nid/213091), actor framework has a networking addon, and for quick and dirty, AMC (https://www.ni.com/example/31091/en/) works. To put it another way, where you might use a UI event (queue) structure on a windows machine, you would typically use asynchronous I/O (eg tcp, udp, serial) to feed a queue on the rt system.
  18. there is hardly support in labview itself In reality this is a pretty easy fix to do on your own branch of the code. Inside here: https://bitbucket.org/drjdpowell/jsontext/src/default/Variant to JSON Text.vi and here: https://bitbucket.org/drjdpowell/jsontext/src/default/JSON text to Variant.vi If you look for every case structure using the type enum, find the case for "extended precision" and then add "Fixed Point" to the same case. Numeric variants automatically coerce so it should work as simple as that. (I suggest extended because of the different variations of fixed point, potentially using 64 bits in a more efficient manner than say a 64 bit double. You will still possibly lose precision)
  19. I re-read your (rscott) post and it occurred to me you might be missing something more fundamental wrt labview applications. I don't claim that this code is good or bad, but it can serve as a reasonable example for this conversation: https://forums.ni.com/t5/Example-Program-Drafts/LabVIEW-Real-Time-Sample-Template-Embedded-UI/ta-p/3511679?profile.language=en Note that there is some UI code, but theres also a deterministic control loop and various monitoring loops.This is typical and in fact kind of on the low side. This is why message oriented frameworks like actor framework or drjdp's messenger library or delacor's dqmh are fairly popular as they provide some of the plumbing and structure common to many applications.
  20. to convert this into c-style: while(1) { pathwire=pathin waitforinput(timeout=forever) pathout=pathwire } you didnt 'hose the rest of the system' but your loop will stop because you told it to wait for input. You generally have many many many loops in a labview program. You can change this loop to a polling style by setting timeout to something besides forever. also note that the order of operations in the loop is not specified. I wrote one possibility.
  21. daqmx is a driver that supports all of NI's standalone daq cards as well as cdaq devices and now the newest generation of crio
  22. This is a good guide to look through: https://www.ni.com/en-us/shop/compactrio/compactrio-developers-guide.html Mark mostly covered it, the way I'd think about it: Default -> run on host Does my code protect human beings -> generally don't use NI products* and don't even touch the application unless you know what you're doing (*exception is maybe the SIL module but even then I'd want an experienced safety person consulting) To move to the compactRIO you want one or both of these to be true: Does my code need to run 24/7 headlessly Does my code need to operate in a moderately precise (~100 usec) time frame To push the code from RT down to FPGA you want one of these to be true: Does my code protect a mechanical system (eg look for voltage to go past limit, open relay) Does my code need to close a loop in a precise (>25 ns variation) time frame (eg motor control) Does my code analyze a large amount of data that my RT CPU is unable to keep up with, AND Does my code analyze data in such a way that otherwise wasted time (eg time between samples of an ADC chip) can be effectively utilized (eg performing a filtering operation on each sample) Does my code analyze data in such a way that a large amount of data can be compressed to a small amount of data (eg integrate a curve after a trigger, or find peak and valley of a waveform) The reason that last one is an AND is that if you can't pretty easily pick up the slack on the FPGA by seriously reducing the data rate or doing a lot of work in otherwise 'idle' time, its probably cheaper to just buy better hardware. Theres a limit to this of course, but...
  23. I dont know what an ENI is, but you can add third party slaves with the standard xml files: https://knowledge.ni.com/KnowledgeArticleDetails?id=kA00Z000000P9CqSAK&l=en-US
  24. The issue drjd/wiebe identified will interfere with any application where you want to generically accept a data element and inspect the names contained elements. I think that is mostly the serialization libs. I'm actually very surprised this doesn't bother you, I'd have assumed you would use these features.
×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.