How to declare local variable (Allen Bradley studio 5000) - plc

How to declare local variable in structured Text in Allen Bradley studio 5000.
I have tried the following which did not work. mnemonic/syntax is not recognized?
VAR
x: INT;
END_VAR
global variables do work as, TEST_INPUT and TEST_INPUT_BOOL are globally declared.
IF TEST_INPUT.0 THEN
TEST_INPUT_BOOL := 1;
ELSE
TEST_INPUT_BOOL := 0;
END_IF;

In Allen-Bradley RSLogix 5000 / Studio 5000, local tags (variables) are not declared inline in structured text routines. Instead, tags are defined in the Tag Browser. "Controller Tags" holds the controller-scoped (global) tags, and each Program has its own "Parameters and Local Tags" section where the program-scoped tags are defined. Tags shown in the Local Tags section of a program can be used in any routine in that program.
Once you add your program-scoped tag to the appropriate Tag Browser, you can use the tag in your structured text routine. If you try to use a tag that is not declared as either a program-scoped or controller-scoped tag, you will get a verify error.

Related

How to access the child nodes in a device tree (DTS) in Zephyr using DT_FOREACH_CHILD

I'm developing an application for an nRF52 SoC to access some external devices, kind of detectors in this case, so I have defined a custom format (and its corresponding yaml file) for my device access description node. It is kind of:
n: detectors {
compatible = "foo-detectors";
// Definition of first channel
det0: det_0 {
irq-pins = <13 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
label = "Bar detector channel 1";
};
// Definition of second channel
det1: det_1 {
irq-pins = <17 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
label = "Bar detector channel 2";
};
};
Suppose I have a structure definition for holding data about the pins to which those devices are physically connected, say:
struct foo_detector_desc {
int irqpin;
int irqpin_flags;
}
Using Zephyr macros, I can use from my code the individual values for those nodes. For instance, DT_PROP_BY_IDX(DT_NODELABEL(det0), irq_pins, 0) expands to 13, DT_PROP_BY_IDX(DT_NODELABEL(det0), irq_pins, 1) expands to the value of OR'ed flags GPIO_PULL_UP | GPIO_ACTIVE_LOW.
But I don't want to create a ten-page code full of conditionals in the form DT_NODE_EXISTS(DT_ALIAS(det#)), but something more compact, flexible and maintainable.
I came across Zephyr macro DT_FOREACH_CHILD that is intended for being used in that scenario with which I can create a list with the labels, as showcased in the example embedded in the documentation:
#define LABEL_AND_COMMA(node_id) DT_LABEL(node_id),
const char *child_labels[] = {
DT_FOREACH_CHILD(DT_NODELABEL(n), LABEL_AND_COMMA)
};
Trying to use that for filling a static structures array, I tried following code but, yet it expands to two elements in the array, the structure fields are not initialised with desired values.
#define PIN_INFO_AND_COMMA(node_id) \
{ \
.pin=DT_PROP_BY_IDX(node_id, irq_pins, 0),\
.flags=DT_PROP_BY_IDX(node_id, irq_pins, 1),\
},
const struct detector_data _det_data[] = {
DT_FOREACH_CHILD(DT_NODELABEL(n), PIN_INFO_AND_COMMA)
};
I'm using Visual Studio Code with the nRF Connect plugin.
Is there a way to generate/see how those macros expand when compiled?
What is the correct way for initialising the structure fields (pins, flags)?
BR
It is possible to expand the macros one level at a time in VS Code. It is needed to click over the macro, then select it by double-clicking on it, and a bulb light will, eventually, show up. The option Insert Macro will replace the macro with its expansion.
Regarding using the DTS in code, the code I wrote in my previous post is OK, but I think I found a bug in the debugger. If I don't include any code using the value of _det_data, the debugger doesn't say the constant was optimised-out and displays wrong values when inspecting its content. That made me waste a lot of time.
For anyone interested on using DTS files for nRF devices in Zephyr, I posted all details in a thread in Nordic's developers forum (here).
BR

Can I use Structured Text in Codesys to initialize a Global Variable List

I'm trying to get my head into the Codesys world and since I'm not a Menu-click type I'm wondering if there is a way to stick to the keyboard and for instance add a PersistentVarsList and Global Vars List via Structured Text in the Editor.
If by add PersistentVarsList/Global Vars list you mean to crate a new list inside the project from Structured Text code, then no. If you just have some variable list (non constant!) inside your project that you want to initialize in runtime (perhaps their values need to be calculated first), then you can have some code that only executes at the begining of the runtime:
PROGRAM POU_1
VAR
init: BOOL := FALSE;
END_VAR
IF (NOT init) THEN
myGVL.someVar := CALLCULATE_VAR();
IF (myPersist.positiveVar < 0) THEN
myPersist.positiveVar := -myPersist.positiveVar;
END_IF
// other initializations
init := TRUE;
END_IF

Joomla 3.9.19 get the constants from global configuration in component display function

I have created a component and need to get a constant value in the component administrator and list the item according to it. I have tried different ways to get the constant value in the 'display()' function in 'view.html.php'. I am expecting the value will be available in the default.php with $this.
I have defined the constant in the configuration.php file, A URL is supposed to define.
define('CONSTANTVALUE', 'the URL string');
in the display() function,
$config = JFactory::getConfig();
$constantvalue = $config->get('CONSTANTVALUE');
$this->constantvalue= $constantvalue;
Seems this is not working.
Then, I have tried
JFactory::getApplication()->get('CONSTANTVALUE');
That also not working.
I have referred to this thread, Joomla 3 - How to get value from configuration file?
How can I get the constant from configuration to component view file?

How to close (in code) a Form which the IDE has open, without closing its associated .Pas file

The code below is simplified from something I'm doing in a design-time .BPL for D7.
Update: Since posting this, I've found one way to do what I'm after, namely just send the form a WM_Close message, but I'd still be interested to know whether there's a more "official" way to do it, because using WM_Close seems like it has the potential for wrong-footing the IDE.
All I'm trying to do in this code that's causing me the problem is to close all files open in the IDE,
and then open a specific .Pas file that happens to have an associated .Dfm file. I don't want the form defined in the .Dfm to be open on-screen, so I'm trying to close it, without closing the .Pas file too - I just want the IDE Form designer and this form out of the way.
Eventually, I found out how to get at the form via OTA + NTA services in my .BPL's code and, naively but for want of any other obvious way to do it, I've tried calling .Close on it, by this snippet.
AForm := TForm(INTAComp.GetComponent);
AForm.Close;
However, the form does not close. I've traced into TCustomForm.Close from the CPU window
and evidently the reason it doesn't close is that its Visible property is already False. This is what evaluating Visible prior to AForm.Close returns, too.
Evaluation various other of its properties prior to AForm.Close tells me that
- its Owner is Nil BUT
- it has an apparently valid window handle // Arrghh! [sound of penny dropping... see update above]
I dare say that this is something to do with how the IDE's form designer works.
My question is simply: What do I need to do in my code to get the form to close,
as it does when I simply click its [x] button on its frame?
Btw, I've confirmed that the instance of the form I'm getting via AForm := [...] is the
instance that's on-screen, by changing on-screen instance's caption in the OI.
procedure TOTAForm.CloseAForm;
var
IServices : IOTAServices;
IActionServices : IOTAActionServices;
IModuleServices : IOTAModuleServices;
IEditorServices : IOTAEditorServices60;
IModule : IOTAModule;
i : Integer;
IEditor : IOTAEditor;
ISourceEditor : IOTASourceEditor;
IFormEditor : IOTAFormEditor;
IComponent : IOTAComponent;
INTAComp : INTAComponent;
AForm : TForm;
begin
IServices := BorlandIDEServices as IOTAServices;
IServices.QueryInterface(IOTAACtionServices, IActionServices);
if IActionServices <> Nil then begin
IServices.QueryInterface(IOTAModuleServices, IModuleServices);
IModuleServices.CloseAll;
if IActionServices.OpenFile(EditorFileName) then begin
IModule := IModuleServices.Modules[0];
ISourceEditor := Nil;
for i := 0 to IModule.ModuleFileCount - 1 do begin
IEditor := IModule.ModuleFileEditors[i];
IEditor.QueryInterface(IOTAFormEditor, IFormEditor);
if IFormEditor <> Nil then begin
IComponent := IFormEditor.GetRootComponent;
IComponent.QueryInterface(INTAComponent, INTAComp);
AForm := TForm(INTAComp.GetComponent);
AForm.Close;
end;
end;
end;
end;
end;
All it needed was:
AForm := TForm(INTAComp.GetComponent);
SendMessage(AForm.Handle, WM_Close, 0, 0);
//AForm.Close;
But I'd still be interested in knowing whether there is an official way to do this, because
my "solution" feels like it's doing an end-run around OTA and NTA services. Otoh, the user can always close the form manually, on-screen, so maybe I'm worrying about nothing

Accesing Values From One Form on Another

Im trying to build in a language switch into one of my programs.
Where the user selects a language and in runtime the app gets translated. I sort of got this working in a small test project. BUT only when the forms are auto created, which i dont want.
the way the forms get created is the following:
SideNote: Most of my forms are fsMDIChild forms.
ParametersForm := TParametersForm.Create(Self); //(consider this the mainform for now)
On ParametersForm I have
procedure TParametersForm.FormCreate(Sender: TObject);
begin
ResourceStringsDM.ParametersF; //(consider this the second form)
end;
this Datamodule houses the captions for ParametersForm.
procedure TResourceStringsDM.ParametersF;
begin
with ParametersForm do
begin
bsSkinLabel1.Caption := 'Execute Nieuwefacturen';
bsSkinLabel2.Caption := 'Execute Viewfacturen';
end;
end;
I have added ResourceStringsDM to the implementation uses of ParametersForm and ParametersForm to the interface uses of ResourceStringsDM.
This all above gives me an access violation cause in the procedure where it sets the captions uses ParametersForm (var name of the form i want to translate) but at that moment this var is nil. Prolly cause it isnt done creating the form yet and hasnt filled in the form var.
The only way i got this all working was by using
Application.CreateForm(TParametersForm, ParametersForm);
But I want to avoid this after reading about it, and that you should only use this on your mainform. Also it doesnt handle passing parameters very well.
Does anyone of you fine people have any hints or tips / help to get me access to the captions of form 1 from form 2?
i probably forgot tons of info you guys need. just tell me and ill add it in.
In an "MDI Application" template (file->new-other->...>, neither MDI childs are auto created nor the child form's unit contains the global form reference. There's a reason for this, more than one instance of a child form should be able to run at the same time. When you have two instances of the same child for instance, which one will the form reference hold?
Anyway, it is of course possible to not to use this design, but then if you don't use the construct you mention in the question, you're responsible for assigning the instance to the reference yourself. So either do it (which I don't recommend):
procedure TParametersForm.FormCreate(Sender: TObject);
begin
ParametersForm := Self;
ResourceStringsDM.ParametersF; //(consider this the second form)
end;
or better, pass the instance to the function in your data module so that it can work on it:
procedure TResourceStringsDM.ParametersF(ParametersForm: TParametersForm);
begin
with ParametersForm do
begin
bsSkinLabel1.Caption := 'Execute Nieuwefacturen';
...
 
procedure TParametersForm.FormCreate(Sender: TObject);
begin
ResourceStringsDM.ParametersF(Self); //(consider this the second form)
end;