Jump to content

smithd

Members
  • Content Count

    739
  • Joined

  • Last visited

  • Days Won

    42

Everything posted by smithd

  1. Yeah websockets are easy, theres 12 libraries out there for setting them up using the tcp primitives. 50 ms delay could be nagle -- if its a closed network, 50 ms is at least 25 round trips, likely more. One possibility for the long long delay is if you're using hostname rather than numeric IP address. The hostname lookup is a disaster for any networking code, at least on windows.
  2. When you say cdaq, you mean normal cdaq or one of windows/rt cdaqs? Assuming windows/rt, maybe if you want some basic messages just set up a web service with a named queue to forward messages to. Then you don't need an actor, just call the http api directly (or spawn it as a task).
  3. DAQmx might not work right unless you increase the thread count, depending on how many of those actors have blocking functions
  4. Its worth mentioning that LabVIEW should do this for you, its called loop invariant code motion, so don't worry about it for performance reasons.You should put the code wherever its more readable. In this case, I'd argue the most readable form is leaving the math where it is, but moving the source values (array size, iteration terminal, control) closer in. I'd also say use a local variable for the control -- the downside to this is that, in fact, using a local variable will stop the loop invariant code motion from happening 😕 In this particular case, I'd like to mention that you can make code more readable through various means -- one is code movement, another is labelling wires or using self-labelled elements like clusters. You can also add comments, but before you go adding comments I would always always look at the code and see if it can be changed to use a different tool to make the meaning more self-evident. To stick with the current section of code: personally, I find pretty much all iteration-based math to be incomprehensible. I sat here for like a full minute trying to figure out why on earth you were taking max(0, i-10) ...but stepping back for a second, it looks like it should probably just be a case structure with two cases, "..10" and "11..". There is always a case structure in this code, but in your version its hidden inside the max() function and if you use a case structure its explicit. Then you have the problem of "why 10?", but at least anyone reading the code is not stuck back at "why maximum?". Along these lines, one thing that might really help you is if you find yourself a buddy and try to explain the code to them (bit by bit, i mean, definitely not all at once). As logman said the application isn't really all that complicated, and I would bet that anyone with a semi-softwarish or logical background could follow along if you walked them through it. The purpose would be to rethink code like the above. If you're sitting there explaining to another human being "well I want the index of this listbox to be 0 up until iteration 10 and then I want it to start incrementing by 1, so what I did is I took the maximum of 0 and the iteration terminal and then built that into an array with 0 and used that as the index" you might start thinking to yourself "man I really need to make this easier to follow".
  5. Ah yeah I read a note that said a specific visual studio version was no longer supported, should have scrolled down further.
  6. Yeah I looked again, I don't think matlab can use visual studio. Nah this is a parsing problem. Maybe I'm misreading the error but it looks like it doesn't know what __cdecl is -- __cdecl is visual studio specific. Since I think most compilers use that calling convention by default, you can safely remove all instances of __cdecl from stim.h
  7. I have two answers which might help: Answer A: Purchase Teststand and learn it. Without specific details I cant be sure, but it looks like the sort of application teststand is built for. If someone gives you crap about the cost, I'd argue that for sequential things like you've shown here teststand is a lot more maintainable (the bus factor for the code above is likely 1, and potentially 0 after a few months away from it). I'd also add that it has a lot of standardized reporting stuff built in...and if you're calibrating stuff, this would seem to be critical. So seriously, at least let someone from NI spend an hour giving you a demo. Answer B: Looks to me like your first step might be to take some of those 50 front panel controls and put them into subVIs that are set to run as dialogs (in VI options, show front panel when called and close front panel when done). Those dialogs can take some of the logic thats in your main loop and organize it a bit -- "this event case is associated with this user input", and so on. Those dialogs can return small clusters with the configuration (Monitor is a cluster of model[str] and serial[str] and resistance[u16]). If at the end of this you still have a ton of wires, as hooovahh says you can turn that into a clustersaurus/BFC, but its still better organized (clustersaurus->monitor->model vs just having a control called "monitor model" sitting out there). Once you have some of what I'm going to call the "non-business logic" (eg the UI logic) out of the way, I think a state machine is a reasonable migration point to start with. I would add a caveat to this, which is you should also learn about different communication tools within labview -- in this specific case, queues and user events (a type of queue which works with the event structure) or "channel wires" which are intended as a simpler wrapper around the queue/event concept). I say this because it looks like there are several long-running tasks without user interaction, so creating parallel loops to run different tasks seems like the next logical step. In general you would use a queue to send data (eg "start running standard cal") from the UI loop to the tasks loop, and use a user event to send information (eg "I'm done" or "an error occurred") from the task loop back to the UI loop. drjdp has a video on some of the considerations for this here although it may be too much for you now -- hes coming at it from the other end "I've been using this pattern for a while and heres where bad stuff happens". Once you've mastered this version, and if you feel like its still complex, the next step would be to dive further into frameworks (things like delacor's QMH or drjdp's messenger library or ni's actor framework which are arguably in order of increasing abstract-ness) -- in these frameworks more stuff happens asynchronously from one another which can make the code more modular (the "standard cal process" is always over in this one library while the user dialog input is always over in this other library) but theres obviously a big learning curve and frameworks tend to require you fit into them rather than the reverse.
  8. smithd

    clfn scripting

    Fair enough, its definitely been a while. Last I remember I had to have the whole visual C sdk on my machine because it wanted to find some standard header. To me this is one of the bigger annoyances -- I dont' want to fix up the h file, that seems iffy to me. I suppose it generally doesn't matter since its just use to help the script along, but... Usually strings and arrays are OK, but yeah big structs can be iffy due to offsets -- that is once nice thing about this LLVM-based tool, is it tells you all the byte offsets so technically one could pass in an appropriately sized buffer and restructure the data...but thats a pain as well.
  9. My understanding from what came up is that Matlab is attempting to build a wrapper dll with some more matlab friendly interface. A quick google didn't find me anything about how it does this, but that seems to be what its doing. I say that because the "we dont know the..." come from the labview headers. So it seems like Matlab is running a compiler against stim.h which includes the platdefines header, and since I'm assuming the matlab compiler is not one of the ones NI was expecting when they built this (or if matlab simply doesn't #define the same definitions NI is expecting), the compiler correctly spits out the errors shown, as in this snippet of platdefines: #ifdef _M_PPC #define ProcessorType kPPC #elif defined(_M_IX86) #define ProcessorType kX86 #elif defined(_M_X64) #define ProcessorType kX64 #elif defined(_M_ALPHA) #define ProcessorType kDECAlpha #elif Compiler == kBorlandC #define ProcessorType kX86 #elif defined(_ARM_) #define ProcessorType kARM #else #error "We don't know the ProcessorType architecture" #endif So the question becomes what should it be. My guess is that they should be defined per the labview exe/dll which is why I suggested the MSVC compiler definitions (as I understand it, this is what NI uses for windows builds). However it may be that the right answer is to edit the headers to set something more appropriate. For example, in the section above, you could comment every line out except for "#define ProcessorType kX64". Similarly you could comment out the compiler section and replace it with "#define Compiler kGCC" (if that is what matlab uses, which I assume it is). The only reason these need to be defined is so that extcode.h picks up all the appropriate definitions and headers for the platform. For example. stim.h uses the type "uint32_t". This is defined in stdint.h, but if your compiler isn't including it already then stim.h can't be compiled. So, in fundtypes.h, it has a bunch of platform checks to see if it needs to define those types. The easier route, vs trying to make extcode.h have the proper types, would be to just edit stim.h directly to include the type definitions you need. I would suggest editing your stim.h to look like this (lines 1-7): //#include "extcode.h" //this dll only uses two uncertainly defined types, but they are defined by stdint.h. This section is borrowed from fundtypes.h #if !defined(_STDINT_H_) && !defined(_STDINT_H) && !defined(_STDINT) #include <stdint.h> //alternatively comment the line above and uncomment these lines: //typedef int int32_t; //typedef unsigned int uint32_t; #endif #ifdef __cplusplus extern "C" { #endif .....
  10. If I had to guess, you'll want to edit STIM.h to include (at the very top, before anything else): #define _Win64 1 //if 64 bit #define _Win32 1 //any windows #define _M_AMD64 100 #define _M_X64 100 // same as above #define __x86_64__ // and again, this might be the gcc version or something? #define _MSC_VER 1900 // just a guess, this is ms visual c 2015 The full list of visual c #defines is here at this link, and you can also just go through the NI header file and look for stuff that makes sense. https://docs.microsoft.com/en-us/cpp/preprocessor/predefined-macros?view=vs-2017
  11. just curious if anyone has ever made an attempt to improve scripting out of dlls. I know theres the built in import wizard, but I've literally never seen that work (has anyone here?). The reason i'm asking is that I was thinking about it and came across this tool: https://github.com/CastXML/CastXML (binaries from the build link at the bottom here: https://github.com/CastXML/CastXMLSuperbuild) Essentially it takes a C header (or any C file I guess) and processes it with LLVM to produce an XML tree of all the functions and types. For example it takes the header here: https://github.com/nanomsg/nng/blob/master/include/nng/nng.h and produces xml which includes stuff like this: <Typedef id="_8" name="ptrdiff_t" type="_285" context="_1" location="f1:51" file="f1" line="51"/> <Typedef id="_9" name="wchar_t" type="_286" context="_1" location="f1:90" file="f1" line="90"/> <Typedef id="_14" name="intptr_t" type="_285" context="_1" location="f4:182" file="f4" line="182"/> <Union id="_78" name="nng_sockaddr" context="_1" location="f6:151" file="f6" line="151" members="_328 _329 _330 _331 _332 _333" size="1088" align="64"/> <Struct id="_61" name="nng_aio" context="_1" location="f6:96" file="f6" line="96" incomplete="1"/> <Struct id="_68" name="nng_sockaddr_in6" context="_1" location="f6:124" file="f6" line="124" members="_315 _316 _317" size="160" align="16"/> <Field id="_315" name="sa_family" type="_25" context="_68" access="public" location="f6:125" file="f6" line="125" offset="0"/> <Field id="_316" name="sa_port" type="_25" context="_68" access="public" location="f6:126" file="f6" line="126" offset="16"/> <Field id="_317" name="sa_addr" type="_385" context="_68" access="public" location="f6:127" file="f6" line="127" offset="32"/> <Typedef id="_79" name="nng_sockaddr" type="_334" context="_1" location="f6:158" file="f6" line="158"/> <Enumeration id="_80" name="nng_sockaddr_family" context="_1" location="f6:160" file="f6" line="160" size="32" align="32"> <EnumValue name="NNG_AF_UNSPEC" init="0"/> <EnumValue name="NNG_AF_INPROC" init="1"/> <EnumValue name="NNG_AF_IPC" init="2"/> <EnumValue name="NNG_AF_INET" init="3"/> <EnumValue name="NNG_AF_INET6" init="4"/> <EnumValue name="NNG_AF_ZT" init="5"/> </Enumeration> <Function id="_84" name="nng_close" returns="_293" context="_1" location="f6:194" file="f6" line="194" mangled="?nng_close@@9" attributes="dllimport"> <Argument type="_55" location="f6:194" file="f6" line="194"/> </Function> <Function id="_87" name="nng_setopt" returns="_293" context="_1" location="f6:205" file="f6" line="205" mangled="?nng_setopt@@9" attributes="dllimport"> <Argument type="_55" location="f6:205" file="f6" line="205"/> <Argument type="_338" location="f6:205" file="f6" line="205"/> <Argument type="_339" location="f6:205" file="f6" line="205"/> <Argument type="_5" location="f6:205" file="f6" line="205"/> </Function> <FundamentalType id="_293" name="int" size="32" align="32"/> <FundamentalType id="_294" name="unsigned char" size="8" align="8"/> <FundamentalType id="_295" name="unsigned int" size="32" align="32"/> <PointerType id="_353" type="_352" size="64" align="64"/> <PointerType id="_354" type="_62" size="64" align="64"/> <PointerType id="_355" type="_47" size="64" align="64"/> Its pretty easy to parse because everything has an ID -- I've got some truly gross code for converting all the struct and enum definitions into labview which is simple enough. I guess I'm just testing the waters to see if anyone else thinks this is useful. My usual strategy right now is to minimize the number of C calls I make, but if I could just magically import a header and get the library made for me, it would be pretty cool. But on the other hand, theres so many challenges associated with that which I hadn't thought about going in, like handling structs by value, or what to do with numeric return values (is it an error code? is 0 good or bad?). The particular library I selected as a test case above has two features that are super annoying -- its main 'session' reference is not a pointer like in most C apis, but a struct containing a single int, and it also has a union type..for some reason. So even making this library work, which I thought would be an easy way to try it out, has ballooned in complexity a bit. Thoughts?
  12. Also, this is kind of a side point but the concept is the same. Has anyone noticed that reentrant VIs get super slow sometimes when debugging? Its not always, but I can't figure out what conditions might be causing it. Its like you're going along debugging some code, you step into a reentrant VI, and everything just stops, and it takes like 20-30 seconds for the window to materialize. I know its not just one computer, sadly.
  13. This may have already been mentioned, but have you tried changing the compiler complexity threshold? http://zone.ni.com/reference/en-XX/help/371361P-01/lvdialog/miscellaneous_options/#compiler Its possible its trying to compile while you drag or something, and maybe the drag selector interacts with the UI thread more or something.
  14. There should not be, adapting to type is all you want and thats what vims do. As pointed out, queues are not a runtime-dispatchable type in the same way you cannot dynamic dispatch off a boolean or an array. The contents are irrelevant. Its worth noting that vims support dispatching based on method name rather than class hierarchy. There are examples of using vims to make lvclasses act kind of like interfaces (ie if you have two separate hierarchies with a method "Get queue" which returns a thing at connector pane position 3, you can put that in a vim and it will adapt, including if that outputted thing has a different type). As a side note, you can and should wrap the queue status and index primitives inside of a disable structure.
  15. I'm curious how this would work in more detail if you could share. It sounds interesting, but it also sounds like...a lot. For example I'm not sure where kibana fits in, and I'm curious what mongo gets you that you couldn't get with a more common database like postgres. This kind of reminded me of what you are describing. It wasn't really applicable for me but it came to mind when I read your post. It looks like their "driver" can (in at least this case) just be an ini file. Since it sounds like you're open to python, this have always been on my "neat, but I don't have a use now" list: https://airflow.apache.org/ Its a task graph and you can use something like celery or zeromq or amqp to move data to those tasks. Also, on the topic of kibana+databases, this tool is way cool: https://github.com/apache/incubator-superset its basically a graphical sql editor in python/html which talks to any sql db python can talk to, and with a bunch of cool visualizations. I've not used it 'in production' but its similar to (and 1000x better) than something we had built in house and I demo'd it to some folks and they liked it almost as much as I did. I know its not related to this topic at all but I like it.
  16. mjpeg doesnt work like that, its literally a bunch of jpegs in a wrapper. Random access should work as well as forward access. I'd bet forward access has some caching and pre-fetching though, so for random access check your cpu load, memory, and disk usage while trying to play the video. I'd bet you're hitting some limit. Specifically you are asking a lot of windows to smoothly unpack a randomly accessed frame every 34 ms using software decoding.
  17. I think this important and descriptive org chart diagram is obligatory for any reference to oracle:
  18. Its definitely open source, you just can't use it or copy it...and I imagine flarn could sue you if you release something kind of like his code and its discovered that you knew about this code. In the US, I believe lava gets away with this because of safe harbor provisions in the otherwise frightening DMCA. Even without that, many forums have terms of use which generically cover these things. For example from ni.com: As I read that, it sounds like the site basically says ni can do anything it wants with anything you upload, including distribution and copying. Other parts of the terms of use also make it clear that just because NI has that right, doesn't mean the original uploaded conferred that right to any downloaders, only to NI. So in other words (again, as I interpret this), uploading code means other people can download it, but they still cant use or distribute it without a license from the original uploader.
  19. Yeah if you have only source, 2 GB is plenty even for labview. Not sure about build process issues, but for me I ran a little function post-build to upload the exe/etc to an internal server running an artifact repository. Given that you run lava, I'm guessing you could set something like that up and host it yourself, or maybe your workload is light enough you could use the free tier of amazon/ms/oracle/google's cloud services. As to specifics: I used artifactory, but a nice simple route would be to just set up a separate git server with lfs support and then your post build step is a push to a different repo. Or you could even set up your /build directory as a git submodule or subtree (i forget the diff, I think submodule is right for this) where the main repo points at github while the submodule points at your server. Gitlab I think has a free instance for self hosting, and gitea is a free github clone, and amazon has a hosted version thats free up to a limit as does google. Edit: or just use gitlab: https://about.gitlab.com/2015/04/08/gitlab-dot-com-storage-limit-raised-to-10gb-per-repo/
  20. Along the same lines as the raspberry pi, its pretty annoying that NI has gotten rid of these fine old beasts: http://sine.ni.com/psp/app/doc/p/id/psp-655/lang/en Theres obviously a ton of ethernet->serial boxes out there, but most of them seem to require local windows drivers to emulate them as local serial ports
  21. Not VISA, but it seems simple enough to use linx? https://www.labviewmakerhub.com/doku.php?id=learn:libraries:linx:reference:labview:uart-open
  22. Per the "Details" section of the help here http://zone.ni.com/reference/en-XX/help/370281AE-01/imaqvision/imaq_imagetoimage_2/ I think you just need to reuse the mask you created earlier. If the ROI is a polygon, the mask will be a polygon so when you use imagetoimage it will only copy the pixels inside of the polygon.
  23. It forces the OS to finish any pending writes. Closing the file does the same thing. So if the concern causing you to continuously open and close the file was to ensure that your data was safely on disk rather than pending, flush would give the same result. It sounds like that was not your concern, so flush has no benefit to you.
  24. https://forums.ni.com/t5/LabVIEW/Converting-Controls-to-Silver/td-p/1705536 https://forums.ni.com/t5/Quick-Drop-Enthusiasts/Quick-Drop-Keyboard-Shortcut-Silver-Conversion-Tool/gpm-p/3510319 as a general statement, I'd strongly recommend against doing this on all your code. UIs, ok, if you really like silver controls then by all means, but theres no point to changing subVIs and...its irritating. also, there are more attractive packages out there for UI. A reasonable but by no means complete starting point is here: https://forums.ni.com/t5/UI-Interest-Group-Discussions/bd-p/7116 For example drjdp's flatline controls (which is currently post number 2 in that link) are nice.
×
×
  • Create New...

Important Information

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