06-29-2023 09:41 PM
I am in the process of refactoring a single VI control system (sig gen, laser, camera, and oscope) to use the actor framework.
This is my first time writing g-code since college (very simple simulation / data acquisition scripts) and I am having a hard time understanding when I should / shouldn't use a local variable. The code I am refactoring has them littered all over the place with several feedback nodes to process the data we are recording. I don't think I should use them to manipulate data and I was trying to avoid using them entirely, but I don't see a way to get this indicator working as I want without this.
Is there a better way to do what I implemented here?
And if you could point me to any good (and cheap) g-code learning resources I'd greatly appreciate it.
Ian
Solved! Go to Solution.
06-30-2023 02:37 AM - edited 06-30-2023 02:38 AM
In this particular case, the Serial Communication Log data should be stored in the actor class. The appending of new data should happen in a subVI and then send to the Actor Core, no need for local variables. Same for the initial empty string write to the local variable. Just fire the beforementioned subVI in the beginning when the string in the Actor Core data is empty.
Some people will say that local variables should be avoid at all costs. Generally I use local variables only if I have to update front panel elements in different places (for example when loading settings from a file). Technically, you can do everything without local variables, but if they are called only sporadically, like when loading a settings file, the easyness of using a local variable outweighs the additional programming for me.
It should NOT be used as a sort of data buffer, like in your example, especially if this buffer is increasing over time. As a rule of thumb, I avoid reading from local variables.
06-30-2023 03:30 AM
That's an ok use as it cannot cause a race condition, though i'd use a feedback node in the event case.
06-30-2023 09:21 AM
A better way would be to have the log in an initialized shift register and the terminal before the event structure and going through linked tunnels across the event structure. Now you can eliminate the original outside write to the local (which is in principle a race condition because it runs in parallel to the rest of the code! You cannot absolutely guarantee that the inner local is only read after the outside local has been written!) and don't need any locals at all.
(See also slide 21-25 in my old presentation here)
It is hard to tell from a truncated picture what else there is.
06-30-2023 09:27 AM
@altenbach wrote:
It is hard to tell from a truncated picture what else there is.
It's a standard Actor Core.vi with a helper loop for user events. The helper loop with the event structure is often used to update front panel elements by utilizing user events. Generally there shouldn't be any logic in the helper loop, it should all be done in the Actor Core. This way you completely eliminate race conditions as there is only one place where the log string is stored (the actor core) and one place where the front panel is updated (the helper loop). Data flow is dictated by the order of messages send to the actor.
06-30-2023 10:49 AM - edited 06-30-2023 10:55 AM
@Basjong
By storing this log string in the private data and the indicator aren't I doubling the amount of data I am storing? (update_private_data.PNG)
@Yamaeda
I hadn't used the feedback node before and your solution is pretty clean and easy to implement. This will be easy to replace with a message to a logging actor when the time comes / the boss deems it necessary. (feedback_node.PNG)
@altenbach
Is this what you mean by using a shift register? Previous commands disappear with each new set of commands (send + recv commands are sent in separate messages), but I don't understand why this history isn't maintained. (shift.PNG) Your slide deck link returns an error page.
edit: ninja
06-30-2023 11:30 AM
@ianzur wrote:
@altenbach
Is this what you mean by using a shift register? Previous commands disappear with each new set of commands (send + recv commands are sent in separate messages), but I don't understand why this history isn't maintained. (shift.PNG) Your slide deck link returns an error page.
You did not initialize the shift register and you did not place the indicator before the event structure.
(The link works fine for me. Maybe there is a permission issue. You can probably ask the moderator to troubleshoot.)
06-30-2023 01:54 PM
@altenbach wrote:
@ianzur wrote:
@altenbach
Is this what you mean by using a shift register? Previous commands disappear with each new set of commands (send + recv commands are sent in separate messages), but I don't understand why this history isn't maintained. (shift.PNG) Your slide deck link returns an error page.
You did not initialize the shift register and you did not place the indicator before the event structure.
(The link works fine for me. Maybe there is a permission issue. You can probably ask the moderator to troubleshoot.)
I made the changes as you show in your diagram I am still loosing the history. Did I miss wire something?
I do not understand the shift register entirely and need to spend some time reading up.
If anyone has opinions on which of these solutions is optimal (speed / memory consumption) or how to test small snippets of gcode please let me know (and I know storing an ever increasing long string cannot be memory safe, but the system is used for short periods of time and once the siggen is set to the desired waveform, freq, amplitude, there will be minimal communication).
PS. Do I call the support line to ask for a moderator help for the link you shared? Or can I tag a username in this forum?
06-30-2023 02:05 PM
@altenbach
Nevermind, I am an idiot. I need to wire through every event case if I want this solution to meet my goal.
Still, if you know how best to contact the moderators please let me know.
PS. Can I only mark one solution as the correct one?
06-30-2023 03:49 PM