Jump to content


  • Posts

  • Joined

  • Last visited

  • Days Won


Everything posted by JKSH

  1. What's the context? Traditionally, I've treated good desktop app design as different from good industrial HMI design as different from good web app design, etc. But, contemporary designers are moving towards a unified approach. What are your thoughts on Google's Material Design, Microsoft's Fluent Design, or Apple's Human Interface Guidelines? https://material.io/design https://www.microsoft.com/design/fluent/ https://developer.apple.com/design/
  2. Can you say, "Here is the STOP button! The big red 'X' in the top-right corner of the window"? 😁
  3. Missing as in "field does not exist in the object", or missing as in "field exists but the value is an empty string"? The latter is not truly missing. It exists, and its value is an empty string. The former can be handled using the "Data Type and Default Value" inputs Sounds like you're using "Find Item.vim"? Make use of the "Found" output, OR switch to "Find Item (as LVtype).vim" to specify the default value. How do you envision providing the default value if you are able to filter out the proposed "Empty String" error?
  4. The current pink wire datatype needs to remain as a "byte string" plus "locally encoded text string" to maintain backwards compatibility. A new type of wire (Purple? Darker than pink, paler than DAQmx wires?) should be introduced as a "universal text string" datatype. Explicit conversion (with user-selectable encoding) should be done to change pink wires to purple wires and vice-versa. Binary nodes like "TCP Read"/"TCP Write" should only use pink wires. Purple wires not accepted. Text nodes like "Read from Text File"/"Write to Text File" should ideally only use purple wires, but they need to allow pink wires too for backwards compatibility. VI Analyzer should flag the use of pink wires with these nodes. Perhaps a project-wide setting could be introduced to disable the use of pink wires for text nodes.
  5. How about wiring the string into a case structure selector? Case "": Do your special output Case Default: Wire the string into the JSON VIM
  6. If you only need to read the basic standard messages defined in J1939, then you can can treat the frames like any regular CAN frame. You just need to map the frame IDs to J1939 PGNs (for example, CAN frame ID 0x0CF00401 is for "Electronic Engine Controller 1" and bytes 4-5 contain the "Engine Speed" value) However, if you need to do do complex things like read multi-frame data or send a command and read the response, then you need to write a lot more custom code. Fortunately, NI has provided an example that covers a big chunk of what you need with the NI-9853: https://forums.ni.com/t5/Example-Code/J1939-Transport-Protocol-Reference-Example/ta-p/3984291 (use the non-XNET code) On the bright side, since you're doing FPGA programming, it doesn't matter if the CAN module is on an Ethernet expansion chassis or if it's plugged directly to your controller -- your code would be the same either way AFAIK, that only provides mapping for the basic messages that fit within a single frame, and some basic standard hanshaking + diagnostics. NI-XNET has no built-in support for multi-packet data or complex comms. I used the XNET example from https://forums.ni.com/t5/Example-Code/J1939-Transport-Protocol-Reference-Example/ta-p/3984291 as a starting point, but still had to write a lot of custom code to encode/decode messages and handle command-response handshakes.
  7. @Rolf Kalbermatter has the answer, as usual: The parameter type is a pointer-to-InstanceDataPtr (i.e. a pointer-to-a-pointer, or a Handle in LabVIEW terms). LabVIEW owns the handle, you own the data pointer: You allocate the data in Reserve and you can access that same data in Unreserve/Abort. LabVIEW can't free your pointer since it doesn't know the type/size of your data. // C++ example #include <ctime> MgErr reserveCallback(InstanceDataPtr* instanceState) { if (*instanceState == nullptr) { time_t* start = new time_t; *start = time(nullptr); *instanceState = start; } else { // We should never reach this point, unless the InstanceDataPtr was not cleared after the last run } return 0; } MgErr unreserveCallback(InstanceDataPtr* instanceState) { time_t end = time(nullptr); time_t* start = static_cast<time_t*>(*instanceState); // Calculate how much time has passed between reserving and unreserving double elapsedSecs = difftime(end, *start); // Note: The handle must be explicitly cleared, otherwise the LabVIEW IDE will pass the old pointer // to reserveCallback() when the VI is re-run delete start; *instanceState = nullptr; return 0; }
  8. It's a pretty common spam technique, designed to sneak spam links into innocent-sounding posts. A moderator should clean out the spam.
  9. JKSH

    Slow MD5

    That means it is using OpenSSL 1.0.x or earlier. In OpenSSL 1.1.0, "libeay32" was renamed to "libcrypto"
  10. Or even better: Replace "Write To Text file"/"Read From Text File" with "Write To Binary File"/"Read From Binary File". The output of "Flatten to String" is not text. (String != Text)
  11. If it's a new-ish installation, the uninstall utility is replaced by NIPM. But that does also provide a comprehensive list of installed NI software.
  12. I don't have one for sale, but our customers would like to purchase cRIO 904x too. Unfortunately, current lead times from NI are around 12 weeks.
  13. Ouch. Can you please wave this in NI's face? https://forums.ni.com/t5/LabVIEW-2021-Public-Beta/bd-p/labview-2021-beta
  14. For those who don't want to watch the video, the list of improvements is also published in the Public Beta: https://forums.ni.com/t5/LabVIEW-2021-Public-Beta/LabVIEW-2021-Beta-Now-Available/td-p/4144143 I don't think that's a bad thing. NI can't exist as a silo and still hope to be relevant to the rest of the world. Better interoperability makes it easier to justify using LabVIEW in a multi-technology environment (which is often the case in large organizations), and makes it easier for scientists and engineers to start using LabVIEW. Yeah, those are a bit vague. The second half of the list sounds like the porting over of features from NXG, which seems like a sensible direction (consolidate existing features before coming up with new ones)
  15. Hi @LVmigrant, and welcome! I think nothing beats the effectiveness of a well-designed and well-delivered training course -- you'd learn the most from them in the shortest amount of time and you can be taught to avoid bad habits that might be found online. Still, forums are definitely a helpful way to learn. I studied electrical engineering and basically developed most of my software-related skills via forums, StackOverflow, and lots of home practice. After that, I got my full-time job as a LabVIEW-based programmer in a systems integration company.
  16. Depends on what the server's role is, right? If the server is my cloud backup, then yes I should push all local branches to the server all the time. If the server is hosting a large open-source project that I'm contributing to, then I'm usually not allowed to push my changes to the server until I've finished everything. If the server is hosting my public project releases, then I keep my WIPs and experiments local, and I only push "polished" (possibly squashed/amended) commits. That last scenario minimizes low-quality commits like "Fix typo in previous commit" that make commit history difficult to read and bloat the repository size -- this is especially important with LabVIEW, where each VI change could potentially increase the repo size by 100s of KB, leading to multi-GB repositories very quickly.
  17. Not from NI, that I know of. I did make a similar API that wraps the Qt framework. That involves creating external windows though; your toolkit has the benefit of being integrated with VI front panels. Original LAVA post: https://lavag.org/topic/19611-utf-8-text-svg-images-inheritable-gui-components-dynamically-composed-guis-layout-management-splitters-in-tabs-mdis-taskbar-integration-and-much-more/ NIPM installation instructions: https://jksh.github.io/LQ-Bindings/docs/ As Mikael and Rolf said, class constants are not needed: Definitely! LabVIEW's built-in support for dynamic GUIs is very poor. NXG was starting to show some promise with dynamic controls, but that's now dead. So, community-built tools are sorely needed. Are you planning to make public releases of your work? Layouts are common concept in a wide variety of GUI toolkits. Makes it so much easier to create resizable GUIs and support a variety of screen resolutions.
  18. I'm not sure what you mean by "totally different structure". Could you elaborate? Is it captured in the illustration below? Alice and Bob clone the same repo and checked out the "master" branch. Bob doesn't like master/slave terminology so he renamed his local branch to "main". Alice and Bob each want to implement a new feature, so they each created local feature branches. On Alice's PC, "master" tracks "origin/master". "featureA" doesn't track anything. On Bob's PC, "main" tracks "origin/master". "featureB" doesn't track anything.
  19. 🙌 🎉 🎊 🥳 What if you check out a commit that is part of multiple branches at the same time? Indeed. There's not much I can offer that's not already excellently covered by websites like the one you linked. So, I'll offer some fun facts instead: A "remote" repository is usually located on a different machine, which is usually a server. But, the "remote" can also located in a different folder on your local machine. Try it for fun and for education. You usually set your local repository to track a remote repository, which is usually on a server and considered the "authoritative"/"master" copy. But at the same time, that remote repository also could choose to track you -- such that from their POV, your copy of the repository is their "remote".
  20. Correct, the LabVIEW Python Node currently supports desktop only, not cRIOs. Here is an Idea Exchange post calling for support to be extended to cRIOs: https://forums.ni.com/t5/LabVIEW-Real-Time-Idea-Exchange/Python-Node-support-on-LabVIEW-Realtime-systems/idi-p/3904897?profile.language=en No, that's wrong. In NI Linux RT, VIs can access the entire system (as long as the lvuser account is given the required permissions). It's the LINX Toolkit (for BeagleBone and Raspberry Pi) that puts LabVIEW in a chroot jail. So, although the Python Node isn't available on cRIOs, you can share data between a LabVIEW application and a Python application via inter-process communication (IPC).
  21. Wow... I've been scripting that node for years but never noticed that bug. I apply a non-default name to all my return value nodes, but the result is all blank. Someone in NI must have made some "optimizations" since return values of C functions can't have names.
  22. Acknowledged. Nonetheless, I still contend that all of these use-cases are still borderline abuse of the queue API -- @infinitenothing will be fighting an uphill battle trying to explain to text-based programmers why we use SEQs, no matter which use case he picked. It would be cleaner if LabVIEW had proper language constructs for these use cases (even if it's just syntactic sugar that wraps a SEQ behind the scenes)
  23. Functionally, dequeueing a SEQ is analogous to reading the DVR in "In Place Element" and analogous to locking a mutex. The 2 LabVIEW code paths above are analogous to this C++ code snippet: // Global variable and mutex std::mutex mtx; int* globalvar = new int; // 1a. Initialize shared resource ("Obtain Queue") int main() { // 1b. Initialize shared resource ("Enqueue Element") *globalvar = 0; // 2. Lock shared resource ("Dequeue Element") mtx.lock(); // 3. Modify shared resource ("Increment") *globalvar += 1; // 4. Unlock shared resource ("Enqueue Element") mtx.unlock(); // 5. Free/Delete shared resource ("Release Queue") delete globalvar; } Notes: It doesn't make much sense to use a global pointer-to-integer in C++; we would just use a global integer directly (or find ways to avoid globals altogether). The code above is to show equivalence to LabVIEW nodes; you'll get funny looks if you present C++ code like this. Using a SEQ like this is unintuitive. Using Queue concepts to share data and lock/unlock access is borderline API abuse. Likewise, using a non-reentrant VI's internal state to act as a global variable (i.e. Functional Globals) is borderline API abuse. Therefore, I would not introduce SEQs and FGVs to newcomers until they are comfortable with other basic concepts of LabVIEW. I would not use them as a starting point for discussions. Nonetheless, we accept/embrace SEQs because they are useful (FGVs are less useful since proper Global Variables exist now). I consider DVRs more intuitive than SEQs, but I prefer SEQs on a block diagram as they don't require the huge rectangular frame.
  24. Reentrant: Roughly also "Reentrant", although... LabVIEW VIs are non-reentrant by default, C/C++ functions are reentrant by default. Unlike LabVIEW, there is no setting to force C/C++ functions to become non-reentrant -- you simply code them in a way that makes them reentrant. In LabVIEW, non-reentrant VIs are impossible to run multiple instances simultaneously. In C/C++, non-reentrant functions are unsafe to run multiple instances simultaneously (it's possible; you'll just break things). Single element queue: Depends on how you use it. I often use it as a nicer form of Data Value Reference (see below). Data value reference: "Pointer" (as per the Wiki) or "Reference" Functional global: Doesn't really exist in textual languages. They were invented to fill the role of Global Variables, back in LabVIEW 2 when Global Variables didn't exist. However, an Action Engine (see https://forums.ni.com/t5/LabVIEW/Community-Nugget-4-08-2007-Action-Engines/td-p/503801) roughly maps to a "Singleton". Sounds good to me. However, note that a LabVIEW "variable" is quite different from a textual "variable". A textual variable is more like a LabVIEW wire.
  25. One cause is file metadata. For example, VIs store a "Revision Number" which can be different even if the block diagram, front panel, and icon are unchanged. There are probably other causes too, but I don't know what those bytes represent. Pretty often, unfortunately. This is one thing that makes it hard to use source control with LabVIEW. I try to minimize these occurrences by making sure that I don't save a VI unless I've actually modified its contents. P.S. Minor nitpick: It's not that "LabVIEW falsely report differences exist". Rather, LabVIEW causes differences to exist (in the byte sequences of a VI) even when the code is the same.
  • Create New...

Important Information

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