Jump to content

MarkCG

Members
  • Posts

    147
  • Joined

  • Last visited

  • Days Won

    17

Posts posted by MarkCG

  1. Mark, does this mean you have 80 controls on your FP?

     

    If this is the case for me, the controls ussually correspond to each other or not, so you put them into clusters, then you just register the value change for cluster.

    Once the event happens,

    the left Event nodes will give you Old + New value, so compare, this gives you the index of the control changed,

    get the control reference out of the cluster, read it's name and wire it to the case structure.

     

    Now you have 8 event cases where each has case struct with 10 cases named by the controls. Works fine for me and makes the BD more readable.

     

    Hi bublina yes I definitely use clusters for parameters that are related. I just look for a cluster change event and send the whole cluster if just one element has changed though, I typically don't care which one has changed. So if I had a cluster of PID loop gains on the front panel, I would just send a message called "PID loop gain changed" whenever the proportional, integral, or derivative gains where twiddled.

     

     

    After re-reading your problem, I guess this approach is better.

     

    Make an array that translates the control names and possible values into messages (or whatever data you use to control your program further).

     

    I use this approach as well, cool thing is that all translations are LabVIEW data, so you can make your own code to add new dictionary entries, so change to FP means you will just need to run some VI that will populate/change the array and you can script your own code to do that.

     

    good to see I'm not the only one thinking this way! Yes I chose to implement he dictionary is a variant hash, I just like being able to look up any kind of data with a string instead of iterating through an array. Probably is a wash performance wise.

     

     

    No, of course not.  You would need one single VI per datatype you are registering events for.  If not everything is a typedef, this tends to not be too many VIs.  Of course there would be 80 VIs in memory (callback VIs), but not 80 VIs on disk

     

    ah ok makes sense.

  2. Your code was not attached, but I often use variants, dynamic registration of arrays of control references, and control labels that encode the message that needs to be sent, as illustrated in this old post.  I also done similar things connecting multiple controls with Camera Attributes or DAQmx channels.

     

    Yep this is pretty much what it is, as shown in that thread. I just made the message name independent of the control name. I also found that sometimes I wanted to associate a particular message name to a particular value of the control.

     

    For example: Log button becoming true sends "Start Logging" command, Log button becoming false send "Stop Logging" command.

     

    The thing I like about this is that I can handle fiddly "stateful" control logic inside XControls. The Xcontrol has an enum value and I can register a particular enum value to a command specific command message.

     

    For example, a "tape deck " type control with play, pause, resume and stop / abort buttons. Three button, four messages "Play" "Pause" "Resume" and "Stop". The X control logic wraps the "button logic" up nicely without having to smear it over 4 cases of you main UI's event structure.  

     

    Advantages: Essentially allows us to split up individual frames of the Event structure into individual (boiler-plate) VIs.

    Disadvantages: Knowing somehow that the events are being handled somewhere and that the callback VIs themselves run int he root thread.

     

    So now would you have 80 boilerplate VIs instead of 80 event structure cases?

  3. Hi all,

     

    as the complexity of some of the systems I have worked on grew, I found that I could have dozens of user controls in my diagrams, handled by an event structure. Almost all of the case structure cases handled "value change" events and simply enqueue the new value and a "X changed" type command to the appropriate module or remote target.

     

    Having 80 cases in an event structure, all doing more or less the same thing seems like it's crying out for refactoring.

     

    I came up with attached class in order to capture UI command-value pairs and write them to a network stream, using just one case of a case of the event structure. It leads to a lot less code repetition (at the expense of some more BD real estate on the left hand side) but I am more or less happy with it because it's less wiring overall.

     

    I made an example (attached) to demonstrate it. What do you all think of this way of structuring my UI code? What improvements could be made?

     

     

     

     

     

     

     

  4.  

     

    Does anyone have a recommendation on a reliable USB to RS232 converter?

     

     

    usconverters.com

    RS232 is a very old standard, so even the cheapest devices are quite reliable. For long-term acquisitions however USB is a bad coice. Rather go for on-board or PCI(e).

     

     

    Several times I have worked with folks decide that the way to build a data acquisition or even machine control system is to take a generic windows PC, install the LabVIEW dev system,  and hook up a new and Ebay-ed variety of virtual RS-232 , virtual RS-485, and GPIB device, and maybe a cDAQ chassis to it. Educating them on why this is not a good idea, most of the time, is a never-ending battle which I am not sure I want to even fight anymore.

  5. I haven’t had an RT project in several years, but if I had a new one I would probably stick to only a single (message-based) method of communication between RT and HMI, and possible only one instance of that. What do other people who do a lot of RT work do?

    Network streams or something simpler based like the STM library are well suited to commands from HMI to RT target or status updates and events from the target to HMI.

    For tag data, where you care only about the last value, unbufferred network shared variables are good.

    Doing it all as one pipe could be done, sure, it's all tcp/ip under the hood anyways

  6. I never understood the logic behind that causes the "bitfile signature does not match" message that forces recompile if you are opening the fpga reference by build specification or by VI. it caused me great annoyance as I was learning the LV FPGA side of things. The ip address should have nothing to do with it but it seems to, also when you pull a copy of the project from the source code repo it wants a recompile. Why? I think that if the hardware in the project matches the bitfile it should not complain.

     

     

    I just gave up and just open a reference to the bitfile exclusively. With custom fpga code on ethercat targets I erase the fpga and download the bitfile directly via right clicking on the fpga target in the project.

  7.  

    I think it's a chicken-and-egg problem: NI doesn't polish it because there are few users; few users use it because it's not polished. I don't think it's the learning curve because the concept of statecharts is quite intuitive, and should be familiar to many people who haven't used LabVIEW before.

     

    I used statecharts for one large project once, for coding complex logic in a CompactRIO. The main issues I had were:

    • Deployment took forever.
    • Bugginess, like you said.
    • Modifying triggers is tedious (and you can't share triggers between different statecharts)
    • Managing static reactions is tedious (you can't reorder them or insert a new one in the middle; you gotta delete them and re-add them in the correct order)

     

     

    Yes deployment is a little long when using interactive mode, not too bad now with newer version of LVRT where it only deploys VIs that have changed after initial deploy.

     

    The bugginess is annoying but I have figured out how to avoid the crashes in edit time. I'm pretty sure I can reproduce on way to make LV hard crash when editing statecharts, but I wonder if NI would care if I did document it...

     

    I also was surprised you couldn't rearrange triggers and static reactions. I just decided I would never rearrange them and deal with it. That's part of the lack of polish for sure.

     

    Primarily, $1555

     

    Yes. That's a big one. I wish NI would give up and include it with the full development system.

     

     

    Because state-machines are hard and have to be debugged with witchcraft. So just avoiding the problem means you don't need tools for that problem. :P

     

    I'm a witch doctor and my magic is strong. Seriously though- I have read some things from functional programming decrying the existence of "state" in programs. But my view of the matter is that the state of the physical system you are controlling needs to be reflected in the computer to be able to do anything useful. Almost always the state of the system is dependent on is prior history and what you can do next is dependent on that.

     

    I don't see what are talking about, when applied to programs that control a machine in the real world. But I am starting to read about it Functional Programming, maybe it'll reveal the answer as to how to avoid the problem!

  8. I believe this NI addon is very unappreciated. I am using it right now to a production machine with multiple stations for a customer. No specs provided beyond asking "what should it do if X" and boy howdy-- doing things in term of statecharts is had made thinking about the problem and crystallizing the logic an absolute breeze. it is also easy to test the logic encoded in the statechart. 

     

    Doing the problem in terms of a conventional LabVIEW "state machine"  would be much less fun and take longer. 

     

    There are of course, some bugs as you might expect for such a little used module, some causing hard crashes of the dev environment during edit time. 

     

    What is it in your opinion that has turned people off LabVIEW statecharts? Is it the the statechart paradigm and the need to learn it? Or the perception that it's just re-inventing the wheel? Or the bugginess and half-finished quality of the module?

  9. Thank you very much for the advice ! I too had issues with connectivity-- for some reason the sbRIO was connected to the test computer with some weird usb to ethernet converter that kept flaking out. Really annoying and wasted valueable time. I had to bypass it and set up a link-local connection the normal way.

     

    The grader claimed that the " The User Interface is not adequatly developed for the UI message Handler, Network Stream to RT,
    Communication intilization, and error handling."

     

    Not really sure how so, as the usual pattern of an event shandler was there, network stream connected when you press the connect button to the correct IP, network stream commands get forwarded, and shared variables are read (programmatically based on IP) .

     

    Not sure what they are expecting as that is how it is done in all the examples, and in most people's real world programs.

     

    Anyways, I'll contain my frustration and try again. Thanks!

  10. I took the CLED and was surprised just how much you were expected to do in a 4 hour test. I did not use a template project as the project file is provided to you.. should I have?

     

    I have used cRIO on four different projects and gotten nice reliable systems that keep ticking along for months at a time.

    This includes writing custom FPGA code. So I was disappointed that I didn't pass.

     

    Any tips out there from people who have done it?

  11. It's because the label is aligning itself to the X control, which contains the string control. I have a very similar X control and didn't figure it out how to make the label align perfectly.

     

    You could alway hide the label and hand align some text typed directly on the front panel

  12. Exactly.  JKI was delivering a framework that is meant to be light weight, flexible, and with as few dependencies and extra steps as possible.  Enums are great, but there is flexibility with strings that JKI wanted.  I don't use it often, but allowing for arguments to be passed is also a handy feature.  I can do something like "Wait >> 100" and have my state wait 100ms.  Or "Close References >> Shutdown" which will close some set of references, but ignore any errors, because we are shutting down and I don't want an error to interrupt the shutdown process.

     

    Or how about the steps involved in adding a new case?  It isn't a ton of work with an enum, but it certainly is less work with a string based design.

     

    I never use enum state machines anymore. Just too much aggravation to edit the enum for me. Any typos are caught pretty quickly by error handling during testing.

  13. This is what I came up with in my work

     

    post-16289-0-58953000-1424983160_thumb.p

     

     

    It is somewhat surprising that there is not an FPGA moving average express VI already provided by NI- there are IIR filters.

     

    I might even try to figure out scripting so I can create a moving average VI with a given fixed point configuration, window size, and choice of memory implementation.

     

     

     

     

  14.  

    Now for the most interesting thing: the effects on deployments and builds. We have absolutely no evidence or even feelings that separation has made anything worse. By this I mean the deployments to RT were just as buggy, unreliable and painful as before separation, but not more. I remember at some point we've even tried to reattach the code (of course, with whole cache clearing, recompilation, etc) to check whether it would help with deployments and it didn't help at all. As far as I remember, we've even reverted the repo to the point before separation and first thing we saw when tried to run the code on RT was "Deployment completed with errors"

     

    Hmm, for me, to the contrary everything has worked without a hitch since unseparating source for that particular project-- it solved the deployment problem I was having. It was in 2014 too.

     

    I have a feeling  cause hiccups when you have dependencies shared by both the windows target and the real time target- for example you have a class that works on the RT side, and a typedef control within that class that gets used somewhere on the windows/HMI side. That's a no-no, disconnect from typedef always if you have too. I don't have conclusive evidence to back it up though.

     

    I wish I had a clearer picture on how the whole dependencies / multiple targets / compiling worked to better understand why things like this might happen

    • Like 1
  15. Indeed. LVOOP is a bit like a religion - a dogmatic ideology that everybody seems to still accept, in spite of all the evidence.

     

    Well. That's a bit unfair. It's not just LabVIEW. I've been laughing my gonads off about the implementation of "namespaces" that were introduced in PHP 5.3. Another example of taking a perfectly usable language and making it worse to fit the doctrine.

     

    It's got its uses, it's definitely helped me simplify certain problems. Just to not be vague, hardware abstraction classes for communicating to various random instruments and hardware, loading those dynamically according to a config file, is one clear slam dunk for LVOOP to me. There are others. 

     

    I definitely get very annoyed by the "everything must be a class" philosophy, with vaguely implied benefits of "reusability" or "so we can change it later" (inheritance) being the justification.

     

    Using OOP does not necessarily practically imply either benefit IME. If you can already see the whole picture of your hierarchy of classes before implementation, and see how it will benefit you, do it. But just using LVOOP that it will somehow be easier or "better" without a clear picture of what you will accomplish with it will just make things more complicated than needed. 

  16. I wrote a small application in it just to see what it was about. I was a utility with AF that would launch multiple actors dynamically, to communicate with multiple Real-time PXI units on a factory floor and push some VIs to them. These VIs would then be executed via VI server is parallel on each unit to do a firmware upgrade on some equipment that was attached to one of PXI's serial ports. Having multiple parallel actors running and keeping track of the upgrade process for each unit, which would take 10-15 minute, was really handy. I would keep the child actor queues in a variant hash and look them up by IP address. I was happy I wrote it with AF.

     

    However, other than that one thing, I decided AF was just too heavy for MY purposes. For the kind of applications I write (machine control on cRIO), needing to launch multiple instances of an Actor is just totally unnecessary, because the number of hardware peripherals the machine is controlling is fixed. There is no need for dynamic launching whatsoever. I do make use of LVOOP to make Hardware abstraction Layers fairly frequently, and occasionally use a strategy pattern for some complicated control algorithm things.

     

    I too am fascinated by the concept and genius behind its implementation-- but I am not convinced it is the way to go for most of what I do. I have had problems with people inheriting the little bit of code I wrote using AF being unfamiliar with framework and having a very steep learning curve. I have read stories on here about how large projects using it would cause the IDE to grind to halt due to coupling of actors (really not AF's fault but the IDE).

     

    That is why I decided to leave it alone for the time being. I don't want to say it's bad by any means, better programmers than I have done great things with it. There is an example application written by Elijah Kerry that is a good demo of AF's potential: https://decibel.ni.com/content/docs/DOC-21441 .

  17. Nope, it works regardless of the gap size between elements-- array  =[1,10,100,1000,10000,100000] with min =99 and max=10001 works just as well, returning [100,1000,10000] . But be sure to do bounds checking on min and max, so an empty array is returned if they are out of bounds.

    • Like 1
×
×
  • Create New...

Important Information

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