What's in the Flow?
The functionality is simple. Six outputs of a PiFace are switched on in sequence.
Then they are switched off in sequence again.
Repeat until the Stop button is clicked.
See the video in the header of this blog to see what's happening.
There are a few things in this flow that are commonly used in LabVIEW
- while loop: the outer square, that runs until you tell it to stop. With a shift register to pass the exit value back to the input of the loop
- case block: the smaller square, in this case having a path for TRUE or FALSE case. (if then else)
- IVI Driver blocks: the 3 Pi blocks with the yellow header are custom IVI driver blocks. Most SCPI instruments provide such blocks.
I use a connection block, then a switch to control the outputs of a PiFace Digital hat, and a disconnect block.
- a reusable block: the incrementor (with the ++ label inside) is a custom reusable block I made. Versatile and pre-tested/
The Custom PiFace Blocks
These reusable modules (in LabVIEW lingo: IVI driver blocks) are high-level controls that talk to a RaspBerry Pi.
To read their design in detail, check SCPI on a Linux Board - Part 5a: LabVIEW Driver for LAB Switch: Open, Close and Switch functions.
The design is similar to what you'll find when you use the drivers for an oscilloscope, PSU or DMM in LabVIEW.
There's an init and close pair. These are used at the start and end of the flow to set up connectivity and close it properly.
The init block typically has an associated connection resource control:
The switch block in the middle of the flow is used to control (switch) one of the outputs of a PiFace Digital hat that's mounted on the RaspBerry Pi.
This one accepts a pin number (PiFace output port #) and a command (either On or Off).
Any instrument you use in LabVIEW will come with one or more control blocks. In a DMM that may be: Measure Volt. In an Oscilloscope: Set Vertical Scale, ...
If you're wondering where the SCPI language comes in to play? That's encapsulated within these blocks. If you open them in LabVIEW, you'll see that they (often) are SCPI reader/writers.
Here's the intestines of the switch. You can see the : DIGITAL : OUTPUT%u %s command string, where the %u will be replaced by the pin number, and the %s by either ON or OFF.
You can download that LabVIEW driver from the 5a post of this series.
Reusable Incrementer Block
The incrementor is an example of a generic LabVIEW mini-process that can be reused across projects.
You often need to loop over a range of values, and either stop at the end or start over again.
If you are clumsy like me, you'll always get the border conditions wrong. That's why I created one that's reusable and well tested, so that you can just plug it in and use it.
It also saves precious space on the flow diagram, making it easier to read.
This block takes a start count, upper limit, increment value and a counter index as inputs.
Usually, that increment counter is the index of a LabVIEW loop construct. In this example it's the index of the while loop.
There is a mistake in this part of the flow, fixed in the attached LabVIEW project. One of the number constants is wrong.
You can also see it in the video, when you look at the values assigned to pin on the LabVIEW form during execution.
And by the fact that there's a 400 ms pause between last LED and first LED in the loop.
I leave it to the reader to spot it.
It will start counting from the start value, increment the value at each increase of the index, and wrap around when the end value is reached.
When the block has reached the end value, it'll also put the "finished" output to TRUE. You can use that to exit the loop, if you only want to run it once, or make a decision based on that.
In our example, we use the finished value to switch between "turn on LEDs" and "turn off LEDs".
The index input can be seen as the clock ticker for this increment block.
In summary, such a generic reusable block gives you a chunk of functionality that's tested for all border conditions. Saves you headaches.
Why do I not use the first two outputs of the PiFace Digital?
For two reasons: to show off the Start Value option of this block, and because there are Relays attached to output 0 and 1. I don't want to have them clicking constantly.
The While Loop
This construct runs until it's asked to stop.
In our case, the stop condition is the user pushing the Stop button in the control panel for this flow.
Unless you press that button, the while loop keeps spinning, incrementing the index in the lower left corner each time.
Shift registers (the arrow boxes on the left and right border of the while box) feed the output back to the start of the loop.
The green T box in front of the while box is the initial condition for the switch command. It's TRUE, meaning that the TRUE value is passed into the while initially.
Ignore the purple and yellow lines. They are the connection and error signals. They are required by the switch but don't play a decision role. They are utilitary.
In our loop, a number of things are happening. Some are described already, other will be addressed later.
- the increment block calculates which pin (between 2 and 7) needs to be controlled
- the correct pin is set to desired switch state. TRUE initially, but this changes later ...
- only if this was pin 7, then the TRUE flow in the little CASE block will be executed, toggling the witch state .
- if you press the Stop button on the flow form, the exit condition is met and the process flow continues after the while block.
It's not smart of me to take the switch state after the case block. I get away with it but it's a bug. I should take that signal before that block.
In the attached flow this is fixed, but I left it in for discussion purpose.
The Case Block
A Case in LabVIEW is a construct that can run a different subflow based on the "control input" value.
In our case, the input is a boolean, so we'll have 2 flows. One executed if the input is TRUE. The alternative when the input is FALSE. That's an IF / THEN / ELSE statement.
In our case, the "finished output" of the incrementer is the "control input" for our statement.
From the previous section we know that the "finished output" is only TRUE when the 7th LED is active.
When LEDs 2 up to 6 are active, the "finished output" is FALSE.
When the "control input" is false, this sublow is executed (the ELSE case):
The "switch command" is passed through without changing. That means that at the next iteration of the While block, the value will be the same as in the current iteration.
When the "control input" is TRUE (we just toggled the last LED in the series, #7), a different flow is executed (the THEN case):
Now, there is a change. The input value is toggled by the NOT function inside this subflow.
So the next iteration, the "switch command" is the opposite of what it was in the current iteration.
This is how the flow first switches the 6 LEDs on, then switches all of them off, and back again.
All code, either LabVIEW, Raspberry Pi C / C++, shell scripts and service wrappers, are documented in this blog series.
The generic incrementer and this specific LabVIEW example are attached here.
The Project14 Photonics month is a good hook to explain some fundamentals and blink some LEDs. Thanks for reading.