DEFINE_START with the new NX Series
NZRob
Posts: 70
Ok, been reading people saying not to use the DEFINE_START section of code with the new NX series. (Not talking about the DEFINE_PROGRAM section - fully understand the self resetting loop from variables changing in this section)
1. Blanket ban use of this section is not possible because some commands can only be in here e.g. CREATE_BUFFER.
2. No mention of not using this section is talked about in the NX Series Programming guide and they even use it in examples including the DEFINE_PROGRAM alternative. (The DEFINE_PROGRAM issue IS well explained here)
3. Variable changes in DEFINE_START will fire the DEFINE_PROGRAM section a few times but if nothing is in it then nothing will happen.
So my question is where did this information come from? And if so then what is the reasoning behind it.
1. Blanket ban use of this section is not possible because some commands can only be in here e.g. CREATE_BUFFER.
2. No mention of not using this section is talked about in the NX Series Programming guide and they even use it in examples including the DEFINE_PROGRAM alternative. (The DEFINE_PROGRAM issue IS well explained here)
3. Variable changes in DEFINE_START will fire the DEFINE_PROGRAM section a few times but if nothing is in it then nothing will happen.
So my question is where did this information come from? And if so then what is the reasoning behind it.
0
Comments
I have been doing without DEFNE_PROGRAM for some time. Doing without DEFNE_START is no bid deal either. Migrating older software that has stuff in Def_Start will be easy.
*ERROR: CREATE_BUFFER can only be used in a DEFINE_START section * compiler error.
I was told long ago that DEFINE_MODULEs should be the last things listed under DEFINE_START so that’s where I’ve always put them all. Not sure if that’s a valid point or not but that’s the way I’ve always done it.
Aside from CREATE_BUFFER, I’m not sure what else HAS to go under DEFINE_START. I used to call my initialization routines in DEFINE_START but I was advised that the program would be better served if I called those routines (which do a lot of disk I/O) within the ONLINE event of the first virtual device so that’s what I do now.
I kinda wonder about CREATE_BUFFER too since it seems to handle incoming strings larger than the 2K limit of data.text. I've been using data.text to build buffers anyway for quite a while. (Just appending incmoning datat.text to the end of a buffer in the data_event:string and using a timeline to peel stuff bakc off. )
But, I've not actually used this method with a web page scrape recnetly. So, it would be usedful to know if the data.text event drops any data. the data coming in off the network is 2K packages anyway. I don't remember if each packet constitues a single data.event or not.
I'll just have to write a quick test code to test.
if indeed it's okay, then CREATE_BUFFER can go the way of the dinosaurs too.
On define_module: I tend to put those in a separate include and I don't think I have them anywhere in particular in the code stack. (I just checked) they come right after define_variable in the stack. So, I think as long as they are after define_variable we're okay.
This isn't to say that a potential issue may be lurking that field experience is demonstrating a new concern engineering should be looking at, but I am not personally aware of any cases at this time. When the data started to suggest DEFINE_PROGRAM should be handled differently, we were one of the first to be notified to ensure curriculum is updated to provide alternatives and guidance on how DEFINE_PROGRAM should be used.
Just as a point of clarification the disscion I seem to remember was during a break time - not "On the clcok" discussion. So, while Define_Program was discussed a bit, any discussion about Define_Start was strictly "off the record" water cooler talk. So, it may just be wild rumor.
All this to say - it is entirely possible to write code that functions just like define_start did without using defien_start.
Is the best alternative a timeline with a very short time, and basically move all the define_program stuff into that timeline?
Yes, 300ms is not a terrible delay and it ensures that these items are not processed more frequently then that on the processor. You should also see a decrease in CPU usage for your NI processor by moving feedback out of DEFINE_PROGRAM.
Forums working as it should!
Page 3, 4 and 5: Understanding when DEFINE_PROGRAM Runs
DEFINE_PROGRAM // Feedback Axcess and NI system
[dvTP,1] = nSource = 1;
Better to use a fail save timer
DEFINE_PROGRAM // Feedback NX system (also on NI system)
WAIT 1 // only run 10 times a second
{
[dvTP,1] = nSource = 1;
}
Also to prevent unhandled events which let DEFINE_PROGRAM run by using:
BUTTON_EVENT[dvTP,0]
{
PUSH: {}
RELEASE: {}
}
CHANNEL_EVENT[dvRELAY,0]
{
ON: {}
OFF: {}
}
And special attention when using LOOPS and variables in DEFINE_PROGRAM to prevent a high CPU usage, more on this on page 3, 4, 5.
Yeah, that's what all the hubbub is about.
An easy way to get your stuff out of define_program is to create a repeating timeline that you start at runtime. Then plop your function in there. You can tweak the speed of the timeline dynamically if you like. Speed it up. Slow it down. I'd start with Chris's suggestion of firing it every 300ms. That's three updates per second and is probably going to be plenty fast.
Which brings me back to the subject of this thread... Should I put that in DEFINE_START, or in an ONLINE event for a device? I have a lot of stuff in DEFINE_START too, some INCLUDE statements to load library files, initial opening of IP devices, etc.
All that stuff in DEFINE_START should continue to work OK?
On the Include issue. that's a bit more tricky in that you really think of INCLUDEs as being kind of like a GOTO in basic: in other words the compiler at compile time just treats it like a linear pass and runs immediately off to the include to build the source. So, technically your source will detour in DEFINE_EVENT. But, if the data_event is the first thing in Define_Event then it's basically happening in the same place linearly.
So, for example if the include file starts off with some define_device stuff it will error out since technically you're trying to put define_device and something along the lines of dv_a_Device=5001:01:0 inside a data_event.
But, on the other hand - there's no reason that the include has to happen in define_start either. All my includes (conditional or otherwise) happen within the first lines of my main source file. (even before define_device) I tend to not do includes based upon devices but keep them more code-centric. That way I'm not constantly fighting the whole "This function isn't defined yet" or "that variable isn't defined yet.
I don't know about that honestly (multiple online events)... My example is probably another instance of me not providing a good example to follow. I actually don't use port 1 of device zero for my pseudo-define_start. I typically have a virtual device I assign to all my project for debug purposes. it's in everything. I put the define_start thing there actually.
And I would always say it's a good idea to trap for pesky stuttery events. I do as a matter of practice because I've been bit by them many times. It's almost muscle memory to me now.