02-26-2020 10:59 PM
I have a nice (at least, for me) VI that I run on an FPGA to handle flashing boolean values.
For me, the number of booleans is necessarily fixed (no dynamic arrays) but on a desktop there is no such restriction. I'd suggest replacing the array with perhaps a Map of values (if you have LabVIEW 2019 available) or perhaps Variant Attribute tables in older versions, using Type Cast or similar to get a string from a reference value.
Here I use the following VI on RT to set an LED's frequency and duty cycle:
Ignoring the data packing scheme, I'm sending an amount of time (in ticks) to be high, and then low, and the initial value.
A queue (DMA FIFO here, normal queue if you do something similar on desktop) is used to send information about a change to the frequency to the FPGA. You can see this in the second image, at the FIFO Write node. You'd want to use Enqueue Element instead.
By sharing the queue references into your free-standing loop handling your boolean "LEDs", you can asynchronously pass "requests" for an update to that loop.
In that loop (like the top VI here) you Dequeue an element, and then pass the necessary information (for me, a pair of maximum counts, a current count, the first value (starting value) and the current value) to a loop which processes each time step.
I'd suggest (like in my VI) you pick a specific loop rate for your LED processing loop, and use something like "Wait until next ms multiple" to time it. Note that you can't have better resolution that this update rate for your frequencies - for me, this is 40MHz, for you, a wait of maybe 10ms will allow a responsive update and a moderate freedom in selecting frequency.
Then you can calculate the number of "ticks"/iterations of this loop for a given time.
So if I want a boolean to flash at 1Hz, 50% on and 50% off, I'd send the values 50 (iterations on), 50 (iterations off), T (starting value). 50 is chosen because for a 10ms loop, 50% of a 1Hz loop is 500ms, and then 500ms/10ms = 50 iterations.
For completeness, this is my decoding VI for the requests:
You won't need anything so complicated, because you should directly pass a cluster of appropriate values via your Queue. I have to flatten and unflatten, hence this VI, but you can see here how some additional information ("current count", "current value") are constructed to match the first state (Count 1, Value 1).
You can also see from these VIs that if I want the boolean to be set to solidly on or off, I set the fraction of the second value to be 0. You could do something similar - in my case this means that actually the LED is set to Value 1 every iteration.
02-27-2020 04:35 AM
So the original reason I wanted a subVI was because I needed a blink function several times in different cases of the same case structure. My teacher taught me that if a something is repeated several times throughout your code it is best to use a subVI since you don't have to write the whole thing several times. Now that I have read that the subVI only passes its last value through when it is stopped it seems like with a case like this it won't work.
@altenbach wrote:What are "points"? You mean several different LEDs? Does each LED blink forever at the same speed or can they change on demand, or even stop blinking? What is the speed of your toplevel loop where you are calling the VI? It can all be done, but will be a bit clumsy.
Let me try to explain it as exact as possible. I have about 5 different cases in my case structure. In case 1 for example, I want a blinking LED with 0,5s on, 05s off. Then in case 3, I want that same LED to blink 1s on, 1s off.
This part I have got running using ElapsedTime and a few other things (see attachment). I think the best option now would be to simply copy and paste this where I need it and use the outer while loop instead of a new, separate one.
As for CButcher, your code looks amazing but I am afraid that is a bit beyond the scope of my project for now.
If anyone has any last suggestions/tips for how I otherwise could handle this please let me know. Otherwise I would like to thank everyone for helping me out.
02-27-2020 04:42 AM - edited 02-27-2020 04:47 AM
Hi Joram
@JoramH wrote:
This part I have got running using ElapsedTime and a few other things (see attachment). I think the best option now would be to simply copy and paste this where I need it and use the outer while loop instead of a new, separate one.
If anyone has any last suggestions/tips for how I otherwise could handle this please let me know. Otherwise I would like to thank everyone for helping me out.
No, you still have the problem of this while loop stopping ONLY when you/the user presses this "Stop blink" button! (THINK DATAFLOW!)
Steps:
Replace the shift registers by feedback nodes (using right-click menu).
Then delete the while loop.
Delete the wait function, it belongs into the main VI (IMHO).
Now you can save the remaining stuff as new VI and use it as subVI in each case…
Remarks:
ElapsedTime has an AutoReset feature, no need to reset on your own.
Example:
02-27-2020 04:53 AM - edited 02-27-2020 05:25 AM
@JoramH wrote:
So the original reason I wanted a subVI was because I needed a blink function several times in different cases of the same case structure. My teacher taught me that if a something is repeated several times throughout your code it is best to use a subVI since you don't have to write the whole thing several times.
I definitely agree with your teacher on this topic 🙂
@JoramH wrote:As for CButcher, your code looks amazing but I am afraid that is a bit beyond the scope of my project for now.
I think that the FPGA parts are making it look far more complicated than it will be if you used it on desktop.
I'll have a go at putting a simpler version for PC together later and post it here with a simple example.
02-27-2020 06:08 AM
02-27-2020 10:13 AM - edited 02-27-2020 10:16 AM
@GerdW wrote:
ElapsedTime has an AutoReset feature, no need to reset on your own.
You still have the problem that the calling loops needs to spin at the least common multiple of all waits, i.e. you cannot blink faster than the calling loop.
Here's a reentrant blinker for multiple LEDs that can go to any reasonably fast rate (Don't go below 20ms, because you probably would not see much).
Here's a quick example that can give you another idea (simplfied version!). Code requires more work&features to be useful, e.g. we need a way to stop all of the loops. You figure it out. 😉
Note that the toplevel loop can run slower than the LEDs.