Implement a Read_I_Point FB in TwinCAT 2 BeckHoff PLC - st

What I want to do is to create a FB to read the signal of input point when it is given a TAG NAME.
For example, if the tag name is "I_motor_sensor", so "I_motor_sensor" is send to Read_I_Point FB, then the FB will give the current status back. So is there a way to do this?

Yes, you can read the symbol using FB_ReadAdsSymByName block in the DataExchange library. Info here.. It will take more than one scan though, so should be considered "heavy".
If you want to read them quickly, create a dictonary of references to the variables of interest to you in an intialisation routine, and access them via their key (which you will use a string for).
There's a TwinCAT3 dictonary class in my freely available library, Intecre Utilities, available here. You could try to adapt that for TC2.

Related

Possibility of a multilanguage 'source' name with Twincat Eventlogger

Roald has written an excellent guide for the Twincat Eventlogger.
https://roald87.github.io/twincat/2020/11/03/twincat-eventlogger-plc-part.html
https://roald87.github.io/twincat/2021/01/20/twincat-eventlogger-hmi-part.html
For us this is exactly what we want, there is however 1 thing I haven't figured out. How to get the sourcename of the alarm in multiple languages in the HMI. params::sourceName gives the path in the software (example: MAIN.fbConveyor1.Cylinder1) This path can be customized when initializing the alarm (as Roald has shown). This doesn't work in my case, since I would like to define a generic alarm (example: "Cilinder not retracted within maximum time") that is instantiated multiple times.
I was thinking of using the source as a way to show the operator where the alarm occurs. We use this way (path) already for saving machine settings among other things. The machines we build are installed all over the world, so multilanguage is a must.
Beckhoff does support multilanguage alarm names (when defined), but the source is not defined, but dynamically generated.
Anyone have an idea how this problem can be solved?
If I understand your question correctly, then being able to parameterize the event text with information of the source of the problem should help you out.
If you define the event text as Cylinder {0} has not retracted in time. then you can add the arguments of that text during runtime.
IF bRaiseAlarm THEN
bRaiseAlarm := FALSE;
fbAlarm.ipArguments.Clear().AddString('Alice');
fbAlarm.Raise(0);
END_IF
However, since this also stated in the articles you mentioned, I am unsure if this would solve your problem.
'Alice' in this example, can be hard to localize. The following options come to my mind.
The string can be based on an ENUM. Enums can have textlist support, so if you add your translations there, that should allow multilingual output. However... this does require a lot of setup, placing translations inside your code, and making sure the PLC application is aware of the language that the parameter should use.
Use tags to mark the source device, as tags can be language invariant. It is not the most user-friendly method, but it could work for you. It would become something like: "Cylinder 'AA.1123' did not retract in time.". 'AA.1123' as a tag would have to be stored inside your PLC code as a string. You will have to trust that your operator can relate the tag back to the actual source.
Hopefully, this helped, or else please help me understand the problem better.

Most efficient way to change the value of a specific tag in a DICOM file using GDCM

I have a need to go through a set of DICOM files and modify certain tags to be current with the data maintained in the database of an external system. I am looking to use GDCM. I am new to GDCM. A search through stack overflow posts demonstrates that the anonymizer class can be used to change tag values.
Generating a simple CT DICOM image using GDCM
My question is if this is the best use of the GDCM API or if there is a better approach for changing the values of individual tags such as patient name or accession number. I am unfamiliar with all of the API options but have a link to the API documentation. It looks like the DataElement SetValue member could be used, but it doesn't appear that there is a valid constructor for doing this in the Value class. Any assistance would appreciated. This is my current approach:
Anonymizer anon = new Anonymizer();
anon.SetFile(myFile);
anon.Replace(new Tag(0x0010, 0x0010), "BUGS^BUNNY");
Quite late, but maybe it would be still useful. You have not mention if you write in C++ or C#, but I assume the latter, as you do not use pointers. Generally, your approach is correct (unless you use System.IO.File instead of gdcm.File). The value (second parameter of Replace function) has to be a plain string so no special constructor is needed. You should probably start with doxygen documentation of gdcm, and there is especially one complete example. It is in C++, but there should be no problems with translation.
There are two different ways to pad dicom tags:
Anonymizer
gdcm::Anonymizer anon;
anon.SetFile(file);
anon.Replace(gdcm::Tag(0x0002, 0x0013), "Implementation Version Name");
//Implementation Version Name
DatsElement
gdcm::Attribute<0x0018, 0x0088> ss;
ss.SetValue(10.0);
ds.Insert(ss.GetAsDataElement());

Make my google home verify an oral code

I would like to build an app with a oral code verification.
i could just set my cde in dialogflow before then, juste verify it.
GH : "For continue, give me the code"
Me : " 1 2 3 4"
GH " Access granted" / "Access denied"
But how can do an input a get this code on dialogflow?
First of all - consider if you really want to do this. Having someone say a passcode out loud isn't really very secure and adds very little additional security in a multi-user environment.
There are two stages to this - the first is setting up an Intent to handle this, specifically in the format you want, and the second would be handling and verifying this is the correct code.
Setting up the Intent
We'll need two intents - one that prompts and sets a context so we know we're expecting the validation code, and one that checks for the code.
The prompting intent might look something like this:
The notable part here is that it is setting an output context. We'll see why that matters in a moment.
The one to handle numeric input might look like this:
There is a lot more to this one. First note that we're requiring an input context that matches the output context from the last Intent. This means that this Intent should only match if that Context has been set. This lets us talk about numbers elsewhere in our conversation without triggering this validation.
Next we're looking for sequences of numbers that match the #sys.number-sequence built-in Entity type. There are other entity types that may be useful for you - see the documentation for details and pick one that makes sense or experiment to find what works best in your case.
Finally, we're going to use a webhook for fulfillment to verify if the code is correct. Which is the next session...
Verifying the code
While there are ways to do the verification without a webhook, this is really the most straightforward way to do it. If you're using Google's library to handle input from Dialogflow, you can get the value with something like
var code = app.getArgument('number-sequence');
using whatever the parameter name is. If you're not using the library, you can find this in the JSON at result.parameters.number-sequence.
You would then verify this code, however you want, and return a message indicating if it is correct or not.
If you want to use a sequence of numbers as your code you can use the #sys.number-sequence entity to recognize it and then check the code in your webhook.
Another way would be to simply make a custom entity 'code' that has an entry of '1234'.

Matlab Variables in LSL script

I have Matlab code with variable (value varies frequently, say 10 times/Sec) and I want to use that variable's value in second life script i.e. LSL Script. I read somewhere to do this with HTTPRequest/Response methods, but my Matlab code is developed for desktop application. And I do not know much about LSL script.
I think you have quite a bit of learning ahead of you. First you need to choose an interface to the Matlab data. It supports access via many languages, including common Internet-friendly languages. You'll need to get that data to the Internet somehow so that it can communicate with a region server running. Since it supports access via external languages, I think you're in good shape there.
The main question in my mind is whether you are referring to dynamic data. Is the data changing, and you want to provide access to real-time updates in your LSL script? Or are you referring to a historical recording of data that was changing 10 times per second (in other words, a data file)?
If the data is static, and not too large, you could just convert it into a text format, include it in the Contents of the prim with the LSL script, and read that with the Notecard functions in LSL.
Alternatively, you could somehow push it to a file on a hosted website, then use llHTTPRequest from your LSL script to fetch it. You can also do this if it's changing infrequently, and occasional updates are sufficient.
However, if the data is constantly changing, and ideally if MatLab has a way of notifying a remote Internet webserver (for example, if it does HTTP PUTs to a URL with regular updates), or if you can write a script at your end to fetch the data from MatLab and send it to an LSL object, you could directly contact an object in-world via LSL's HTTP-In functionality. See llRequestURL and the http_request event documentation.
There are some good examples on those pages.

Why does the Function Module name of a Smartform change (sometimes)?

Not really critical question, but i'm curious
I am working on a form and sometimes the generated function name is /1BCDWB/SF00000473, and sometimes /1BCDWB/SF00000472. This goes back and forth.
Does anyone know what's the idea behind this? Cuz i'm quite sure it's not a bug (or i might be wrong on that).
It is not a bug. You always have to use SSF_FUNCTION_MODULE_NAME to determine the actual function module name and call it dynamically using CALL FUNCTION l_function_module.
Smartform FMs are tracked by internal numbering and thats saved in the table STXFADMI. You would always notice the different number in Development System if you have deleted any existing Form. Similarly, you would also notice the different number in your Quality system based on the sequence the forms are imported in QAS and the forms as well (as test forms are not migrated to QAS.
Similar behavior is also true for Adobe Form generated FMs.
You need to understand that every smartform has a different interface and hence the automatically generated function module needs to have different import parameters.
Due to this reason the 'SSF*' FMs generate a FM specific for your smartform. The name of the 'generated' FM changes when you migrate from one system to another. And that's the reason why you should use a variable while calling the 'generated' fm and not hardcode it.
The same goes with Adobe form as someone has rightly said in this thread.