When I tried to do parallel tasks (e.g. multiple producer/consumer loops) in LabVIEW, it was always painful to quit all loops “elegantly”. What I wanted was a notifier to tell all loops when an error occours in any loop. I know there are a few error manager VIs in the internet already but I just reinvented the wheel anyway.
In this error manager.vi there are 3 states: reset (clear errors in the shift registor), read (monitor if there is an error) and hold (stop reading when error).
So I sort of created a functional global variable here using the single loop to store the error. You can use this VI in every loop and it will quit all loops if an error happens. Here is an example:
Hope this is useful to you:)
In my projects sometime I need to write a 2D array in the same line into the text file (see the figure below).
We know that LabVIEW can write 2D arrays directly to the text file using “Array to Spreadsheet String.vi” or “Write to Spreadsheet File.vi”. But when we want to convert it to a single line it is not straight forward. We can convert the 2D array into 1D array before writing using “Reshape Array”. I don’t like this method, which is inefficient in term of space and time. Alternatively, we can write the 2D array row by row using a for loop. But LabVIEW just automatically start a new line for each iteration . The method I used is simple, but took me a while to come up with. I set the file position (“Set File Position”) each time when a row is writen, as shown below
The file position is set at the end and the offset is changed to -2 to delete the carriage symbol. A tab string is added afterwards to keep format the same. This program does the job without converting the 2D array. You can add “Transpose 2D Array” for the 2D array if needed.
Recently I had been dealing with bugs and cells. I was trying to locate the moving cells Euglena with a camera. The Euglena is a single cell that belongs both to the plans and the animals. A picture of the Euglena is shown below. The length of a single Euglena is about 50 um.
The illumination was not good due to my poor optical setup. I tried to identify the cells according to its intensity and size but neither worked well. The strategy I took at last was extracting the stable background and then compare it with the live video, so that the moving targets can be identified. The way of generating the background is averaging all the grabbed images (or, video as we call them). The changing bits are then smoothed by the number of the frames.
When averaging the images, we assume the mean of N framesimages is A_n and the (N+1)th frame is I_(n+1). Both variables are 2D arrays. Then the mean of (N+1) frames is
A_n+1 = (N * A_n + I_(n+1))/(n+1)
The code is shown below (with re-calculate/ clear function):
This SubVI can be called without external shift registers. This simple function allows us to extract the still background from the video. And thus the moving (or any changing) targets can be extracted no matter how messy the background is. The result is shown in the video below:
As I said in the description of the video, “This demo shows using an algorithm tracing an Euglena in the dish with poor (non-uniform) illumination. The mid-left and mid-right videos are raw videos from the camera. The bottom-left video is the background generated from the video in real-time. The bottom-right video is the target (Euglena) extracted from the video. The top-left video is the coords of the Euglena.” We can see that the Euglena were identified from the video even the illumination is non-uniform and the background is a bit messy.
I have been working on using a USB webcam as a research tool to observe the heart beat of a Daphina (water flea) these days. Since LabVIEW 2009 IMAQdx is available for 3rd party USB cameras, no extra USB driver is required. So I used the old but classic webcam Philips SPC 900NC to build a Daphnia observation system. I may talk more about this later.
To cut a long story short, I tried to process only the Region of Interest (ROI) of the grabbed image rather than the whole one. This can make the analysis easier. Since this USB webcam does not support ROI imaging, we cannot set XY pixels on it. I tried to google the solution and found creating a mask or, a pseudo ROI, can block the unwanted image. I programmed an example for blocking the unwanted image by selecting ROI on the image:
For some unknown reason I cannot create snippet from this VI, so I save the screenshot instead.
In this example three memories were created to store the original image, the mask and the modified image. If an ROI is selected (FALSE case), firstly convert the ROI info to a mask, and then mask the source image with the mask image. If no ROI is selected (TRUE case), the destination image is linked to the source image.
Note that:1. The property node “ROI” is created by right clicking the “image” indicator in the block diagram and selecting “Create>Property Node>ROI”.
2. The image type of the “Mask” must be Grayscale U8. The original and the changed images can be any image type.
3. It is masking the image rather than ROI imaging. So it will NOT increase the frame rate nor decrease the image size. All black regions are filled with 255 by default.
Hope this example can be helpful. Let me know if you have any problem or are interested in controlling conventional USB webcams with LabVIEW IMAQdx.
I should have written this post one month ago before I took the CLD exam. The good news is I passed that. 80 out of 100, which is more than I expected (I’ll carry on this later).
I will not talk anything about the exam itself, as I promised in the exam. But just finish the things I prepared for the exam.
1. I found this blog “Pass your CLD/CLA exams the JKI way” very useful, which gave me the confidence of carry on preparing for the exam. Though I didnt use it at the end, it is very helpful for preparing your own template.
2. Timing problem. The timing problem is the tricky part in the exam, such as how to pause/resume/restart your state machine. I made a subVI beforehand to practise it. You can find it here.
3. Pay attention to the documentation, which should be the easiest part to get the credits.
4. If you can finish the sample exams within 4 hours, I’m pretty sure you can pass the exam. If you can finish that within 3 hours, you can get the full marks in the exam.
Since I didn’t finish all the functions during the exam, I felt bad about it. But it turned out I got almost full marks in the programming style and the documentation parts, which saved my life. I didn’t have the plan to take the CLA before, but now I’m considering about it.
Good luck to all of you who are going to take the CLD exams.
Related post: Preparing for LabVIEW CLD exam (1)