Dušan Ferbas Programování Mosaic 12. 6. 2024 12:02 22. 5. 2023 14:35

Dobrý den,

rád bych si uložil informace, známé v čase inicializace tak, abych je později nemusel do dalších funkčních bloků předávat.
Ve funkčním bloku Init mám OUT proměnnou datovou strukturu, kterou  v ST mohu použít v dalším funkčním bloku jako IN_OUT, tím se předává do bloku ukazatel na datovou strukturu. To ale v CFC nelze - viz 1. screenshot. Tak jsem jedinou cestu našel, že ukazatel na začátek každé takové proměnné / pole musím předávat i do dalších funkčních bloků - viz 2. snímek obrazovky níže.

Další varianta (než IN_OUT) mě napadlo uložit pointer do datové struktury, takovou deklaraci ale Mosaic nedovolí.

Původně to bylo vyřešeno globálními proměnnými (kdysi se kvůli tomu upravoval Mosaic, aby šlo glob. var z knihovny použít v programu), ale zákazník požaduje více instancí komunikace a tím pádem globální proměnné nejsou možné.

Je nějaká elegantnější cesta než několik ADR(var_array) na vstupu funkčních bloků?

Děkuji za odpověď.

Dušan Ferbas

Odpovědi 5

Luboš Urban 17. 4. 2023 14:20

Dobrý den,

nejjednodušší řešení bude asi to, když funkční blok naplní při inicializaci strukturu nebo pole daty a bude předávat na výstupu pointer na strukturu/pole jako UDINT. V tomto případě půjde instance funkčních bloků navázat na sebe, protože proměnnou typu UDINT už můžeme navázat jako zdroj pro VAR_IN_OUT a uvnitř toho druhého bloku převedeme UDINT na pointer a můžeme přes něj na příslušnou strukturu / pole přistupovat.

FUNCTION_BLOCK fbInit
  VAR_OUTPUT
    out : REAL;
    ptrOut : UDINT;
  END_VAR

  ptrOut := PTR_TO_UDINT(ADR(out));

END_FUNCTION_BLOCK

FUNCTION_BLOCK fbSmRead
  VAR_INPUT
    ptrTest : UDINT;
  END_VAR
  VAR
    pTest : PTR_TO REAL;
  END_VAR
 
  pTest := UDINT_TO_PTR(ptrTest);

END_FUNCTION_BLOCK

PROGRAM prgMainCfc
  VAR
    Init : fbInit;
    Read1 : fbSmRead;
    Read2 : fbSmRead;
  END_VAR
 
Dušan Ferbas 17. 4. 2023 20:05

Děkuji za tip.

Koukám, že UDINT byl vybrán jako zástupce za ukazatel, protože jiné funkce pro převod z / na PTR nejsou :-).
Nicméně pak podle mě postrádá mysl striktní kontrola na typ proměnných, když je mohu takto přetypovat. Něco jako void * v jazyce C.

 

Dušan Ferbas 18. 4. 2023 23:56

Vidím další nevýhodu - pokud mám VAR_IN typu UDINT, tak v CFC tam klidně dám ADR(smInit.Instance) /tedy PTR_TO/ a Mosaic ani neškytne a program sestaví.
Nač mi je potom striktní kontrola v ST, když v CFC tam uživatel knihovny pak může strčit leccos. To by podle mě byl zdroj chyb.

V podstatě se přimlouvám za vylepšení Mosaicu - co jde v ST, aby šlo v CFC a co nejde v ST, aby nešlo v CFC. Přijde mi to konzistentní.

I.L. 19. 4. 2023 12:38

Jen ze zvědavosti: Nešlo by inicializační data definovat jako samostatnou globální proměnnou, která by se předávala do fbInit i fbSmRead jako IN_OUT? Tj. knihovna by definovala jen typ takové proměnné, aplikační program by deklaroval její globální instance.

Dušan Ferbas 22. 5. 2023 14:35

Dobrý den,

upozornění na Vaši odpověď mi přišlo až dnes :-).

V podstatě tak jsem to udělal - je definována struktura, proměnná s touto strukturou je pak použita jako IN_OUT, proměnná nemusí být globální.
Má to ovšem několik nectností:

  1. Tím, že obsah struktury (proměnné) je definován až po 1. průchodu funkčním blokem, musí být tento blok v POU jako první. Pokud není, ostatní funkční bloky pracují s ještě nenainicializovanými údaji.
  2. Strukturu nejde staticky nadefinovat, protože to Mosaic nedovolí - viz screenshot níže. Struktura bude vždy stejná, pouze velikost polí Inverter atd. je jiná, ale to řeší překladač.
  3. Tuším byl nějaký problém s předáváním do vnořeného bloku, nakonec jsem zvolil variantu s ADR(té_proměnné_se_strukturou) - něcona způsob 2. screenshotu v 1. příspěvku.
  4. Zajímavé bylo, že jsem omylem nadefinoval (V záhlaví CFC)  typ proměnné IN_OUT jako funkční blok, Mosaic nezařval, že tp je jiý typ a vše fungovalo :-).

Šla by udělat alespoň ta statická inicializace?

Tento dotaz je vyřešený.