<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Culverson Software-Custom DAQ Software labVIEW</title>
	<atom:link href="http://culverson.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://culverson.com</link>
	<description>Custom Labview Data Acquisition Software Maine</description>
	<lastBuildDate>Sat, 05 Mar 2011 21:12:21 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>Needle in the Haystack</title>
		<link>http://culverson.com/needle-haystack/</link>
		<comments>http://culverson.com/needle-haystack/#comments</comments>
		<pubDate>Sat, 05 Mar 2011 21:12:21 +0000</pubDate>
		<dc:creator>Steve</dc:creator>
				<category><![CDATA[Beginners]]></category>
		<category><![CDATA[Data Handling]]></category>
		<category><![CDATA[LabVIEW]]></category>

		<guid isPermaLink="false">http://culverson.com/?p=305</guid>
		<description><![CDATA[Finding the best answer is not always straightforward. Scientists are not programmers. Repeat that after me: scientists are not programmers. It&#8217;s not their fault; it&#8217;s just a lack of proper training.  If you are implementing some algorithm given you by a scientist, it&#8217;s important to know this and account for it. Certain algorithms are not [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: center;"><em><strong>Finding the best answer is not always straightforward.</strong></em></p>
<p>Scientists are not programmers. Repeat that after me: <em>scientists are not programmers</em>. It&#8217;s not their fault; it&#8217;s just a lack of proper training.  If you are implementing some algorithm given you by a scientist, it&#8217;s important to know this and account for it.</p>
<p>Certain algorithms are not direct &#8211; most often for some process which is not easily reversible.  For example, I was given the task of implementing a way of finding the Wet-Bulb temperature, given the Dewpoint temperature, the Dry-Bulb temperature, and the Barometric Pressure.  Accompanying this task was some code, written by a scientist, in some form of BASIC.</p>
<p>To accomplish this, they started with an estimate (the DewPoint Temp) and worked forward, using the known equations to convert wet-bulb temp into dewpoint temp, then compared that result to the known dewpoint (Tdew).  If the result was less than the known dewpoint, they added a constant 0.05 degrees to the estimate, and tried again. When the result exceeded the dewpoint, they called it good and returned the latest estimate as the final answer.</p>
<p><em>Scientists are not programmers.</em> If you asked them about this, they will say that it gets the right answer.  If you ask them how they came to choose 0.05 as the step size, after the blank stare (while they think about it), you will get an answer something like &#8220;Well, that&#8217;s the tolerance I want&#8221;. If you really press them, they will come up with &#8220;Well, any smaller and it&#8217;ll take too long &#8211; any larger and it&#8217;ll not be correct enough&#8221;, which is exactly true. That step size is somebody&#8217;s wild guess.</p>
<p>Being the obsessive speed freak that I am, I figured a better way.  What the scientist didn&#8217;t realize, is that you don&#8217;t have to have a constant step size.  With a modicum of further effort, you can adjust the step size dynamically, and get to the final answer much more quickly.</p>
<p>Simply start with a relatively large positive step, and do your estimates as before.  Afterward, make a decision &#8211; if you haven&#8217;t exceeded your target, step again in the same direction.  If you exceeded the target, don&#8217;t simply quit and call it good, REDUCE and REVERSE your step size and go again.  Now you&#8217;re heading negative. When you go BELOW your target, REDUCE and REVERSE your step size. Repeat this until the absolute value of your step size is below your tolerance.</p>
<p>In certain cases, this will take LONGER, but in the vast majority of cases where a fine tolerance is needed, this will get a more accurate answer in FEWER iterations.</p>
<p>You of course need to check things out and match your particular case. Use an iteration counter. You always want to reduce your step size when you reverse it: a factor of -1 would never converge and a factor of near -1 would converge slowly. But a factor of -0.01 would reduce your tolerance.  Best to use a factor of -0.1 to -0.4.</p>
<p>I have seen reductions of 100:1 in iteration counts between the original method and this improved search.  In cases where it was worse, it was around 15 vs. 10 iterations, in cases where it was better it was around  30 vs. 500 iterations.</p>
<p>Use your common sense, and don&#8217;t hold it against them.  <em>Scientists are not programmers.</em></p>
]]></content:encoded>
			<wfw:commentRss>http://culverson.com/needle-haystack/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Beware Simplicity</title>
		<link>http://culverson.com/beware-simplicity/</link>
		<comments>http://culverson.com/beware-simplicity/#comments</comments>
		<pubDate>Fri, 25 Feb 2011 13:49:44 +0000</pubDate>
		<dc:creator>Steve</dc:creator>
				<category><![CDATA[Beginners]]></category>
		<category><![CDATA[Data Handling]]></category>
		<category><![CDATA[LabVIEW]]></category>
		<category><![CDATA[Timing]]></category>

		<guid isPermaLink="false">http://culverson.com/?p=295</guid>
		<description><![CDATA[Simpler ≠ faster : you still have to know what happens &#8220;under the hood&#8221;. If you read the post about en masse operations, you might remember that I pointed out that you should know what is happening behind the scenes. Here is a particular case where what looks like simpler code actually takes longer to [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: center;"><strong><em>Simpler ≠ faster : you still have to know what happens &#8220;under the hood&#8221;.</em></strong></p>
<p>If you read the post about <a href="http://culverson.com/operations-en-masse/" target="_blank">en masse operations</a>, you might remember that I pointed out that you should know what is happening behind the scenes. Here is a particular case where what looks like simpler code actually takes longer to execute.  If you don&#8217;t take the time to think about what is actually going on, then you might be fooled.</p>
<p>Consider a pair of signals, each around 12000 samples. Regulations state that I am allowed to drop (delete) certain samples from those signals before performing statistical operations on them.  The number of points to be dropped might be 2-10%, or up  to 1200 of the points. I have the indexes to be dropped in a third array. For graphing purposes, I need to keep the dropped points in separate arrays.</p>
<p>Now every programmer worth his salt has fallen into the trap of deleting elements 3, 5, and 8 from an array: If you try the straightforward way, you find out that after you delete element 3, that element 5 is not in the same place it was before!  So  you either have to delete element 8 BEFORE you delete element 5 and then 3, or you have to delete element (3-0), then element (5-1), and then element (8-2).</p>
<p>Having fallen into that pothole my share of times many years ago, I avoided it this time by doing the reversing trick: My list of points to drop was known to be in ascending order, so I reversed it, and then did the deletions.  Because I needed the deleted points in proper order, I had to reverse those after the deletion.  Here&#8217;s the code:</p>
<p><a href="http://culverson.com/site09/wp-content/uploads/2011/02/DropPoints1.png"><img class="alignnone size-full wp-image-299" title="DropPoints1" src="http://culverson.com/site09/wp-content/uploads/2011/02/DropPoints1.png" alt="Deletions with reversal" width="606" height="233" /></a></p>
<p>That worked fine for some time, but while revisiting this code, it occurred to me that it might be faster to manipulate the index while deleting, and avoid the reversals and speed things up.  Here&#8217;s the code:</p>
<p><a href="http://culverson.com/site09/wp-content/uploads/2011/02/DropPoints2.png"><img class="alignnone size-full wp-image-300" title="DropPoints2" src="http://culverson.com/site09/wp-content/uploads/2011/02/DropPoints2.png" alt="" width="648" height="272" /></a></p>
<p>That&#8217;s certainly simpler, right?  As one should always do, I applied a <a href="http://culverson.com/what-time-is-it/" target="_blank">Timing Measurement</a> to it. And I was surprised.  I created two arrays of 12000 numbers and an array of 1200 random (0..11999) indexes.  It was consistently 5-6% MORE TIME this simpler way.</p>
<p>But if you stop and think about what&#8217;s going on, the reason is clear.  Suppose your signal array contains [0, 1, 2, 3, 4, 5] and you want to delete elements [1, 3, 4 ]</p>
<p>Using method A you reverse the list to get [4, 3, 1 ].<br />
You delete element 4.  {that moves element 5 down &#8211; 1 move}<br />
You delete element 3.  {that moves element 5 down &#8211; 1 more move}<br />
You delete element 1. {that moves elements 2, 5 down &#8211; 2 more moves}<br />
That&#8217;s 4 moves that were made in the shuffling process.</p>
<p>Now consider the &#8220;simpler&#8221; method:<br />
You delete element [1-0].  {that moves elements 2,3,4,5 down = 4 moves }<br />
You delete element [3-1].  {that moves elements 4,5 down = 2 moves}<br />
You delete element [4-2].  {that moves element 5 down = 1 move }<br />
That&#8217;s a total of SEVEN moves that were made.</p>
<p>So even though we eliminated three REVERSAL operations, we actually take LONGER because we are doing more work.  The increased amount of data-shuffling was enough to overcome the benefit of removing the reversals.</p>
<p>This was done using a random list of indexes to drop; I&#8217;d bet that there are possible scenarios where this wouldn&#8217;t hold true (for example if the points to drop were few, and confined to the end of the signal), but given that neither of those will be true in my case, I&#8217;m sticking with the original plan &#8211; on average it will be faster.</p>
<p>But don&#8217;t assume that fewer operations on the diagram means less work !</p>
]]></content:encoded>
			<wfw:commentRss>http://culverson.com/beware-simplicity/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Terminator 2: the Sequel</title>
		<link>http://culverson.com/terminator-2-sequel/</link>
		<comments>http://culverson.com/terminator-2-sequel/#comments</comments>
		<pubDate>Thu, 30 Dec 2010 17:53:54 +0000</pubDate>
		<dc:creator>Steve</dc:creator>
				<category><![CDATA[Beginners]]></category>
		<category><![CDATA[Easier Programming]]></category>
		<category><![CDATA[LabVIEW]]></category>

		<guid isPermaLink="false">http://culverson.com/?p=290</guid>
		<description><![CDATA[Make sure that quitting time is followed by happy hour. As mentioned earlier, a compiled LabVIEW application behaves similarly to the development system when terminating.  Namely, it leaves the main window on the screen, waiting for you to close it.  That&#8217;s handy in the DevSys, because you usually want to work some more on the [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: center;"><em><strong>Make sure that quitting time is followed by happy hour.</strong></em></p>
<p>As mentioned <a href="http://culverson.com/the-terminator/" target="_blank">earlier</a>, a compiled LabVIEW application behaves similarly to the development system when terminating.  Namely, it leaves the main window on the screen, waiting for you to close it.  That&#8217;s handy in the DevSys, because you usually want to work some more on the program after quitting.</p>
<p>But in an executable, it&#8217;s not so good, because the user doesn&#8217;t understand why the window hangs around.</p>
<p>The earlier article offered a way to have it both ways by simply detecting whether or not you were running with the main VI from an LLB, or something else, and performing a QUIT LABVIEW if it was something else.</p>
<p>With the advent of LabVIEW 2009, the scheme of detecting whether you were in an LLB or not was broken, because LV2009 started putting VIs into an EXE using the folder structure that they came from.  Before 2009, an EXE was a container for ALL VIs in the program, regardless of their folder structure on disk.  It was like having one folder.</p>
<p>Using THIS VI&#8217;s PATH would point to one of those VIs, stripping it ONCE would point to the container, and stripping it TWICE would refer to the containing folder.</p>
<p>With LV2009 and later, we can no longer use that logic.  What we do instead is to examine the path to MAIN:</p>
<ul>
<li>If we find an &#8220;.EXE&#8221;  in it, then we are in an executable, and we strip twice to get the containing folder</li>
<li>else if we find &#8220;.LLB&#8221; in it, we are in a library, and we strip twice (from the point of the LLB) to get the containing folder</li>
<li>else if we find &#8220;.VI&#8221; in it, we are in a stand-alone VI and strip ONCE to get to the containing folder</li>
</ul>
<p>The attached VI is a replacement for the ROOT FOLDER vi mentioned in the earlier article, and is in LV 2009 format  (works in LV2010, too).</p>
<p>Use it when you&#8217;re ready to quit &#8211; see this snippet:</p>
<p><a href="http://culverson.com/site09/wp-content/uploads/2010/12/Quit.png"><img class="alignnone size-full wp-image-292" title="Quit" src="http://culverson.com/site09/wp-content/uploads/2010/12/Quit.png" alt="QUIT if not in LLB" width="185" height="97" /></a></p>
<p>Click to download the <a href="http://culverson.com/site09/wp-content/uploads/2010/12/Root-Folder.vi_.zip">Root Folder.vi</a> .</p>
<p>By using the NOT IN LIBRARY signal as an input for QUIT LABVIEW, you can run the same code unmodified in an app, or in the DevSys, and it does the right thing either way.</p>
]]></content:encoded>
			<wfw:commentRss>http://culverson.com/terminator-2-sequel/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Virtual Devices</title>
		<link>http://culverson.com/virtual-devices/</link>
		<comments>http://culverson.com/virtual-devices/#comments</comments>
		<pubDate>Fri, 12 Mar 2010 13:12:11 +0000</pubDate>
		<dc:creator>Steve</dc:creator>
				<category><![CDATA[Easier Programming]]></category>
		<category><![CDATA[LabVIEW]]></category>
		<category><![CDATA[Tips & Tricks]]></category>

		<guid isPermaLink="false">http://culverson.com/?p=284</guid>
		<description><![CDATA[When you don&#8217;t have the DAQ hardware you need&#8230; Any version of NI-DAQ and the Measurement and Automation Explorer (MAX) released recently has provisions for &#8220;simulated&#8221; devices.  You choose which devices you want, and then NI-DAQ will pretend those devices are actually installed on your system, any calls to DAQ functions concerning that device will [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: center;"><strong><em>When you don&#8217;t have the DAQ hardware you need&#8230;</em></strong></p>
<p style="text-align: center;">
<p>Any version of NI-DAQ and the Measurement and Automation Explorer (MAX) released recently has provisions for &#8220;simulated&#8221; devices.  You choose which devices you want, and then NI-DAQ will pretend those devices are actually installed on your system, any calls to DAQ functions concerning that device will succeed (or fail) just as if a real device was installed.</p>
<p>This lets you simulate a client&#8217;s setup without having their hardware shipped to you and do most (if not all) of the programming on your own terms without being at their site.  The data produced is, of course, simulated data.  For an analog input channel it&#8217;s a sine wave, for a digital port, it&#8217;s a counting pattern.  It&#8217;s enough for you to tell if your software is working correctly with NI-DAQ.</p>
<p>With their hardware simulated on your machine, you can handle the basic communication part to get data in and out. Then you can install conditional-compilation pieces to substitute data more realistic for your particular situation if you need to.</p>
<p>You can be reasonably confident that the DAQ part of a program you develop this way will work on the real hardware, the same as it did on your simulated hardware.  Of course, for any extreme cases (high sample rate, high channel count), the simulation will be less exact, but it&#8217;s a useful feature to develop faster with fewer headaches.</p>
]]></content:encoded>
			<wfw:commentRss>http://culverson.com/virtual-devices/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>What time is it, again?</title>
		<link>http://culverson.com/what-time-is-it-again/</link>
		<comments>http://culverson.com/what-time-is-it-again/#comments</comments>
		<pubDate>Mon, 02 Nov 2009 17:36:08 +0000</pubDate>
		<dc:creator>Steve</dc:creator>
				<category><![CDATA[Tips & Tricks]]></category>

		<guid isPermaLink="false">http://culverson.com/?p=272</guid>
		<description><![CDATA[The TIMESTAMP indicator is smart enough to get you into trouble. Just ran into what at first appeared to be a bug, but turned out to be proper, if misunderstood, behavior. I have a project which records data files. When the actual recording starts, and again when it stops, I remember the time (by using [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: center;"><em><strong>The TIMESTAMP indicator is smart enough to get you into trouble.</strong></em></p>
<p>Just ran into what at first appeared to be a bug, but turned out to be proper, if misunderstood, behavior.</p>
<p>I have a project which records data files. When the actual recording starts, and again when it stops, I remember the time (by using a GET DATE/TIME in SECONDS function) in a TIMESTAMP variable, which is stored in the data file. There might or might not be some calibration activity after the recording has stopped.  When the DONE button is finally clicked, I record the current time using a FORMAT DATE and TIME STRING function, into another string field called &#8220;TEST TIME&#8221;</p>
<p>I have a viewer which examines the data files and reports various info about them. The indicator that shows the TEST TIME is on a different window from the one that shows the START TIME and END TIME.</p>
<p>If there&#8217;s no CAL operations done, then the TEST TIME has always been just a few seconds later than the STOP time (enough time to react to the test being done and click the DONE button), or it could be a few minutes later.</p>
<p>However, I recently noticed that, on a data file sent from my client to me, that the TEST TIME was almost an hour EARLIER than the STOP time.  How could that be?  Further rummaging thru other files that I had from him shows the same thing: the TEST TIME was short of an hour EARLIER than the DONE time.  If there were CAL operations done, this difference was 45-55 minutes; if not, it was a few seconds short of an hour.</p>
<p>I have run thousands of tests on my machine without noticing this; my client has also run nearly a thousand, and has never brought it up.  Whay is that?</p>
<p><span id="more-272"></span></p>
<p>There&#8217;s one piece of info missing from the above description that&#8217;s critical to figuring out what&#8217;s happening: My client is on CENTRAL time, while I am on EASTERN time.</p>
<p>It took a while to figure out what was really happening:  The TIMESTAMP value was being sent whole: encoded with that value somewhere must be the TIMEZONE that it was recorded in.  When the file crossed the timezone line, the value (as it was displayed to me) actually changed.  I confirmed this with my client; a given file showed a START time of 9:39:20 on his machine, but the same file showed a START time of 10:39:20 on my machine.  Of course, those are the exact same moments, just expressed in different time zones.</p>
<p>The TEST TIME, however was recorded as a STRING, and as such, has no mechanism for changing.</p>
]]></content:encoded>
			<wfw:commentRss>http://culverson.com/what-time-is-it-again/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Beating the Jitters</title>
		<link>http://culverson.com/beating-the-jitters/</link>
		<comments>http://culverson.com/beating-the-jitters/#comments</comments>
		<pubDate>Sun, 25 Oct 2009 16:10:42 +0000</pubDate>
		<dc:creator>Steve</dc:creator>
				<category><![CDATA[Tips & Tricks]]></category>

		<guid isPermaLink="false">http://culverson.com/?p=264</guid>
		<description><![CDATA[A shortcut to determinism in real-time applications Determinism in software is the ability to ensure that any and all paths taken through the code take a consistent amount of time to execute.  Most desktop applications have no interest in this consistency because A) it doesn&#8217;t affect anything, and B) the existence of interrupts and preemptive [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: center;"><em><strong><span style="color: #888888;">A shortcut to determinism in real-time applications</span></strong></em></p>
<p><span style="color: #000000;"><span style="color: #888888;">Determinism in software is the ability to ensure that any and all paths taken through the code take a consistent amount of time to execute.  Most desktop applications have no interest in this consistency because A) it doesn&#8217;t affect anything, and B) the existence of interrupts and preemptive multitasking means that you cannot do anything about it anyway.<br />
</span> </span><span style="color: #000000;"><span style="color: #888888;"><br />
</span> </span><span style="color: #000000;"><span style="color: #888888;">In an embedded control application, or one running under a real-time OS however, determinism is often important because it is critical that the control outputs be changed at a consistent time with respect to the control input sampling time. On the input side, when a signal is changing at a relatively rapid rate, any error in the TIME of measurement is just as destructive to the measurement accuracy as an error in AMPLITUDE.  For applications such as PID loops, this is even more important, since derivative terms are adversely affected by timing inaccuracies.<br />
</span> </span><span style="color: #000000;"><span style="color: #888888;"><br />
</span> </span><span style="color: #888888;">Equally important, but not always equally recognized, is the fact that the timing of the output samples has exactly the same effect.  If your control output is not consistently timed, then loop stability is compromised.</span></p>
<p><span style="color: #000000;"><span id="more-264"></span><span style="color: #888888;"><br />
</span> </span><span style="color: #000000;"><span style="color: #888888;"><br />
</span> </span><span style="color: #000000;"><span style="color: #888888;">One way to make your code deterministic is to go through it and make sure that all path lengths are identical.  For example, if your code includes an option to scale the signal to percent of full scale or not, then the proper way to make this deterministic is to compute the full-scale percentage in all cases, then decide to use the scaled or the unscaled value depending on the option setting.  This goes against the programmer&#8217;s natural instinct to do work only when required; but it&#8217;s necessary to ensure that both paths consume an equal time.<br />
</span> </span><span style="color: #000000;"><span style="color: #888888;"><br />
</span> </span><span style="color: #000000;"><span style="color: #888888;">Beginners to real-time programming are rightly warned about this situation.  If you look at the larger picture, you realize that the goal of all this is to ensure that the outputs change at a consistent time relative to each other and to absolute time.  The assumption inherent in the idea of equalizing code paths is that you want the outputs to follow as soon as possible after the control inputs are sampled.<br />
</span> </span><span style="color: #000000;"><span style="color: #888888;"><br />
</span> </span><span style="color: #888888;">That assumption is true in some cases, but by no means all.  There is another way to achieve the same result (consistency of output timing), without the drudgery of counting cycles and finding all the places where such path decisions are made.</span></p>
<p><span style="color: #888888;">By building in a hardware-controlled delay, you can achieve rock-solid precision of output timing, without fretting over every single operation. One way to do this is to use the very same clock signal that drives the input timing to drive the output timing.  For example, in the following code, we:</span></p>
<ul>
<li><span style="color: #888888;">Create the task for the Analog Output channels</span></li>
<li><span style="color: #888888;">Set the AO SAMPLE CLOCK timing parameters to the AI clock signal</span></li>
<li><span style="color: #888888;">Start the task</span></li>
</ul>
<p><span style="color: #888888;"><img class="alignnone size-full wp-image-265" title="AO Config" src="http://culverson.com/site09/wp-content/uploads/2009/10/AO-Config.PNG" alt="AO Config" width="532" height="348" /></span></p>
<p><span style="color: #888888;">This instructs the OUTPUT task to use the same clock as the INPUT.  When you WRITE to the output task, the values you write will stay in the output buffer until the clock ticks; at that point they will be transferred to the actual analog output.</span></p>
<p><strong><span style="color: #888888;">What Does this Do for Me? </span></strong></p>
<p><span style="color: #888888;">By doing this, you have freed yourself from all constraints of cycle-counting and path-equalization. Your control output will change exactly one clock tick after the inputs that produce it. No more and no less.  You have only one constraint: you must get the job done in one clock cycle. If you are running at a loop rate of 100 Hz, then you have 10 mSec to get your work done. If it takes 10 microseconds or 9.99 mSec, it makes NO difference, the output will change at the same point in time either way. You do have to ensure that it&#8217;s 10 mSec or less, but that&#8217;s a constraint you have in any case.</span></p>
<p><span style="color: #888888;">In most cases, where you are waiting on a clock-controlled input sample, performing some control processing with the measured values and writing control values out, the delay you are introducing is not significant.  And a precisely controlled </span><span style="text-decoration: underline;"><span style="color: #888888;">constant</span></span><span style="color: #888888;"> delay is often more easily dealt with in a control loop than an unpredictable jitter, and easier to produce in hardware than in software.</span></p>
]]></content:encoded>
			<wfw:commentRss>http://culverson.com/beating-the-jitters/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Writing Non-Fragile Code</title>
		<link>http://culverson.com/writing-non-fragile-code/</link>
		<comments>http://culverson.com/writing-non-fragile-code/#comments</comments>
		<pubDate>Wed, 14 Oct 2009 20:48:59 +0000</pubDate>
		<dc:creator>Steve</dc:creator>
				<category><![CDATA[Beginners]]></category>
		<category><![CDATA[Easier Programming]]></category>
		<category><![CDATA[LabVIEW]]></category>

		<guid isPermaLink="false">http://culverson.com/?p=254</guid>
		<description><![CDATA[Oooops&#8230;. who broke it? &#8220;Fragile&#8221; code is code that breaks in one place because of changes you make in some other place. It&#8217;s most aggravating when you&#8217;re due to ship a new version tomorrow and you need to make one last tweak at 11:30 PM, or your client is looking over your shoulder and this [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: center;"><strong><em>Oooops&#8230;. who broke it?</em></strong></p>
<p>&#8220;Fragile&#8221; code is code that breaks in one place because of changes you make in some other place. It&#8217;s most aggravating when you&#8217;re due to ship a new version tomorrow and you need to make one last tweak at 11:30 PM, or your client is looking over your shoulder and this little &#8220;harmless&#8221; change shows up as a smoldering heap during the demo.</p>
<p>In this case, &#8220;break&#8221; doesn&#8217;t ONLY mean &#8220;broken arrow&#8221; , or uncompilable code (at least you can chase those down easily enough). Here, &#8220;break&#8221; also means &#8220;operates incorrectly&#8221; or &#8220;completely wrecks itself like it never did before&#8221; or somewhere in between.</p>
<p>These sorts of breaks come from unrecognized dependencies, and they&#8217;re all too easy to make: the header size has been 3 for months and months now, so when you add a new function that needs it, it&#8217;s easy to stick in a constant 3 and be done with it.</p>
<p>DON&#8217;T DO IT.</p>
<p><span id="more-254"></span>If you&#8217;re an old-hand bit-banging cycle counter like me, it&#8217;s easy to think of saving a few cycles and adding up the bytes in this cluster, and using a constant of 53 when you need the size of it.</p>
<p>DON&#8217;T DO IT.</p>
<p>The problem is, or course, then when (not <em>if</em>, but <em>when</em>) these things change, then you will have to track down ALL the instances where you use this number and change them.  Not a good plan.  The compiler won&#8217;t complain &#8211; the code is still valid.  But reading thee bytes when you should be reading four will not get you where you want to go.</p>
<p>One tip to solving this is to reduce the number of places that you use such numbers. Focus such procedures into a single VI if you can. But the real key to solving this is to recognize these things when you originate them.</p>
<p><strong>Example #1</strong></p>
<p>Here we need to receive a packet header, consisting of a cluster of a U8 enum command and a U16 integer.  It&#8217;s easy enough to count up to three bytes, and it would be easy to plop down a 3 constant.  However, it is safer to use a constant of the header&#8217;s typedef and calculate its size in code.  This might go against your instincts (it does mine), but in fact the extra time taken (to flatten into string and get string length) is trivial (<a href="http://culverson.com/what-time-is-it/" target="_blank">measure it yourself</a> if you have doubts). On top of a TCP READ operation, this burden is truly insignificant.</p>
<p>And the benefit is that when the integer needs to become an U32 or the command must become a U16, here&#8217;s one less thing YOU have to worry about.  Since the constant here is a TYPEDEF, and since you&#8217;re calculating the size every time, then it will keep on working.</p>
<p><img class="alignnone size-full wp-image-256" title="Fragile1" src="http://culverson.com/site09/wp-content/uploads/2009/10/Fragile1.PNG" alt="Fragile1" width="234" height="158" /></p>
<p><strong>Example #2</strong></p>
<p><strong><span style="font-weight: normal;">This example is similar &#8211; sending a packet header plus a payload thru a connection. Even if your payload is always the same size, it&#8217;s better to calculate it than to use a constant.  With any luck at all, the STRING LENGTH operation will get the same answer every time. and if you do change it at some point, then this code won&#8217;t break.</span></strong></p>
<div><img class="alignnone size-full wp-image-258" title="Fragile2" src="http://culverson.com/site09/wp-content/uploads/2009/10/Fragile2.PNG" alt="Fragile2" width="344" height="140" /></div>
<div><strong>Example #3</strong></div>
<div>Here&#8217;s another use.  When you have an ENUM, it might be useful to loop over every value. But how do you know how many values to use?  You could count them and plop down a constant. That&#8217;s no good, because it leaves you vulnerable.  You know the first value has a numeric equivalent of 0, you could add a value called &#8220;Last&#8221;, but that&#8217;s ugly if the enum is a control onscreen somewhere.</div>
<div>My answer is to cast a large U16 (or whatever data type the ENUM is) into that type (and then possibly back to an integer if needed).</div>
<div>Here, the FOLDER is an enum listing the various folders my program can refer to. I don&#8217;t know how many there are, maybe 25-30 (in this case, ignorance really is bliss), because I don&#8217;t care.</div>
<div>This code is responsible for creating them all (with exceptions) at startup time.</div>
<div>First we start with a large U16.  I picked U16 to match the representation of the enum itself; that&#8217;s necessary for proper casting results.</div>
<div>Then we typecast it to the folder type.  Presumably, 9999 is more than the number of entries in the ENUM, so the typecasting process can&#8217;t let a literal cast stand, as it would be an illegal value.  So what comes out is the last possible value.</div>
<div>Inside the loop, we convert the &#8220;i&#8221; variable to a U16 to match the representation of the enum itself.</div>
<div>Then we typecast that value into the folder type.</div>
<div>The result is a variable that cycles from first ENUM value to the last ENUM value, and does something with each value, all without knowing how many there are!</div>
<div>If we add a new folder type to the ENUM (it is a typedef), then this code does not need changing.</div>
<div><img class="alignnone size-full wp-image-259" title="Fragile3" src="http://culverson.com/site09/wp-content/uploads/2009/10/Fragile3.PNG" alt="Fragile3" width="351" height="183" /></div>
<div>I hope that this thought will help you create code that is more robust.  Your clients will love you for it.</div>
<div>Enjoy.</div>
]]></content:encoded>
			<wfw:commentRss>http://culverson.com/writing-non-fragile-code/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Time Alignment of Signals</title>
		<link>http://culverson.com/time-alignment-of-signals/</link>
		<comments>http://culverson.com/time-alignment-of-signals/#comments</comments>
		<pubDate>Fri, 25 Sep 2009 21:09:43 +0000</pubDate>
		<dc:creator>Steve</dc:creator>
				<category><![CDATA[Tips & Tricks]]></category>

		<guid isPermaLink="false">http://culverson.com/?p=230</guid>
		<description><![CDATA[A picture is worth 1024 words I discussed the idea of a time-alignment scheme in the article Delays, Delays, Delays.  The idea is that signals which have a mechanical delay of some kind (gas transport time, for example) can be time-aligned with signals that have a lesser or no such delay by means of a [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: center;"><strong><em>A picture is worth 1024 words</em></strong></p>
<p>I discussed the idea of a time-alignment scheme in the article <a title="Delays, Delays, Delays" href="http://culverson.com/delays-delays-delays/" target="_blank">Delays, Delays, Delays</a>.  The idea is that signals which have a mechanical delay of some kind (gas transport time, for example) can be time-aligned with signals that have a lesser or no such delay by means of a &#8220;logical&#8221; delay line inserted into all channels.  If the sum of all channel&#8217;s physical + logical delays is a constant, then the final output is time-aligned.</p>
<p>Here is a test of that concept, where three signals are generated, with different phases, and then fed thru that process. The outputs, as you can see, have been aligned.</p>
<p><img class="alignnone size-full wp-image-233" title="TimeAlignment" src="http://culverson.com/site09/wp-content/uploads/2009/09/TimeAlignment1.PNG" alt="TimeAlignment" width="568" height="528" /></p>
<p>You have to know the physical delay time, however; it does not guess.  You also have to account for the fact that some data is lost at the beginning, if that&#8217;s of concern, then start your recording early enough to account for that.</p>
<p>Even with those caveats, this scheme allows you to shift signals to account for mechanical delays, EVEN IN REAL TIME, if you need to.</p>
]]></content:encoded>
			<wfw:commentRss>http://culverson.com/time-alignment-of-signals/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Web Deflection Mapping Software</title>
		<link>http://culverson.com/web-deflection-mapping-software/</link>
		<comments>http://culverson.com/web-deflection-mapping-software/#comments</comments>
		<pubDate>Fri, 18 Sep 2009 19:07:11 +0000</pubDate>
		<dc:creator>Jim</dc:creator>
				<category><![CDATA[Best Works]]></category>

		<guid isPermaLink="false">http://culverson.com/?p=214</guid>
		<description><![CDATA[Operators of large industrial engines are able to measure the deflection of a single segment of a crankshaft (known as a web) to determine that web&#8217;s stress on the shaft. Unfortunately the operators that contracted us for this program were unable to assess the cumulative stress of multiple webs on a single shaft. Based on [...]]]></description>
			<content:encoded><![CDATA[<img alt="" src="http://culverson.com/site09/wp-content/uploads/2009/09/webdef.thumb.gif" class="wppt_float_left" /><p>Operators of large industrial engines are able to measure the deflection of a single segment of a crankshaft (known as a web) to determine that web&#8217;s stress on the shaft. Unfortunately the operators that contracted us for this program were unable to assess the cumulative stress of multiple webs on a single shaft.</p>
<p>Based on a unifying equation, our program allows users to compile multiple web deflection measurements into a complete and easy to understand picture of the crank shaft&#8217;s shape and motion.</p>
<p>Using this program has helped many operators prevent crankshaft breakage (a costly occurrence) by focusing their maintenance dollars on the units showing the worst distortion.</p>
<div id="attachment_209" class="wp-caption aligncenter" style="width: 310px"><a href="http://culverson.com/site09/wp-content/uploads/2009/09/WebDefMain.png"><img class="size-medium wp-image-209" title="WebDefMain" src="http://culverson.com/site09/wp-content/uploads/2009/09/WebDefMain-300x224.png" alt="The main window shows a diagram that the user can manipulate to indicate throw and bearing positions, and miscellaneous input parameters." width="300" height="224" /></a><p class="wp-caption-text">MainThe main window shows a diagram that the user can manipulate to indicate throw and bearing positions, and miscellaneous input parameters.</p></div>
<div id="attachment_207" class="wp-caption aligncenter" style="width: 310px"><a href="http://culverson.com/site09/wp-content/uploads/2009/09/WebDefEntry.png"><img class="size-medium wp-image-207" title="WebDefEntry" src="http://culverson.com/site09/wp-content/uploads/2009/09/WebDefEntry-300x214.png" alt="For each throw on the crankshaft, the user enters readings of web deflection and the program calculates the path taken by the web as it rotates. " width="300" height="214" /></a><p class="wp-caption-text">For each throw on the crankshaft, the user enters readings of web deflection and the program calculates the path taken by the web as it rotates. </p></div>
<div id="attachment_208" class="wp-caption aligncenter" style="width: 310px"><a href="http://culverson.com/site09/wp-content/uploads/2009/09/WebDefGraph.png"><img class="size-medium wp-image-208" title="WebDefGraph" src="http://culverson.com/site09/wp-content/uploads/2009/09/WebDefGraph-300x206.png" alt="This is a graph of the bearing displacements, shown as deviations from a straight line. " width="300" height="206" /></a><p class="wp-caption-text">This is a graph of the bearing displacements, shown as deviations from a straight line. </p></div>
<div id="attachment_211" class="wp-caption aligncenter" style="width: 310px"><a href="http://culverson.com/site09/wp-content/uploads/2009/09/WebDefAnimation.gif"><img class="size-medium wp-image-211" title="WebDefAnimation" src="http://culverson.com/site09/wp-content/uploads/2009/09/WebDefAnimation-300x186.gif" alt="By recording the bearing displacements over time, an animation can be displayed, alerting the user to possibly dangerous trends. " width="300" height="186" /></a><p class="wp-caption-text">By recording the bearing displacements over time, an animation can be displayed, alerting the user to possibly dangerous trends. </p></div>
<div id="attachment_206" class="wp-caption aligncenter" style="width: 310px"><a href="http://culverson.com/site09/wp-content/uploads/2009/09/WebDef3DAnimation.gif"><img class="size-medium wp-image-206" title="WebDef3DAnimation" src="http://culverson.com/site09/wp-content/uploads/2009/09/WebDef3DAnimation-300x205.gif" alt="Using the calculated displacements, a 3-D graph can be constructed to clearly indicate physical deformation of the shaft. The user can view the deformed shaft from any angle." width="300" height="205" /></a><p class="wp-caption-text">Using the calculated displacements, a 3-D graph can be constructed to clearly indicate physical deformation of the shaft. The user can view the deformed shaft from any angle.</p></div>
]]></content:encoded>
			<wfw:commentRss>http://culverson.com/web-deflection-mapping-software/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Watch your step</title>
		<link>http://culverson.com/watch-your-step/</link>
		<comments>http://culverson.com/watch-your-step/#comments</comments>
		<pubDate>Wed, 16 Sep 2009 12:42:45 +0000</pubDate>
		<dc:creator>Steve</dc:creator>
				<category><![CDATA[Beginners]]></category>
		<category><![CDATA[Easier Programming]]></category>
		<category><![CDATA[LabVIEW]]></category>

		<guid isPermaLink="false">http://culverson.com/?p=203</guid>
		<description><![CDATA[But who&#8217;s watching the watchers? Some development environments have a concept called &#8220;watching&#8221;, where you choose a variable to watch and you see a continuous display of that variable in some window.  This is very useful during debugging, as you can step through your program and find out where this variable is being changed. LabVIEW [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: center;"><em><strong>But who&#8217;s watching the watchers?</strong></em></p>
<p>Some development environments have a concept called &#8220;watching&#8221;, where you choose a variable to watch and you see a continuous display of that variable in some window.  This is very useful during debugging, as you can step through your program and find out where this variable is being changed.</p>
<p>LabVIEW has no such built-in feature, but it doesn&#8217;t really need one.  You can construct your own watch windows, have them run independently of your main code and accomplish the same thing.</p>
<p>Simply make a new VI with a WHILE loop and a STOP button.  Add a WAIT for 200 mSec (or something) inside it (so you don&#8217;t hog the CPU).  Each time thru the loop, grab your watch variable, process it, and display it.</p>
<p>The &#8220;processing&#8221; can be unbundling a single item from a complicated cluster, or picking an element out of an array, or anything you need to display the item in question.  Perhaps you need to call a VI to get it. Perhaps you need to query an I/O port, or a TCP instrument. Whatever you need to do to watch your troublesome variable.</p>
<p>SUGGESTION:  When you&#8217;re done with it, save it in a folder called &#8220;Miscellaneous Stuff&#8221; or something, so you can get at it easy next time.  There will be a next time.</p>
]]></content:encoded>
			<wfw:commentRss>http://culverson.com/watch-your-step/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

