Autor Thema: Why is indirect addressing hidden? This deserves proper visibility.  (Gelesen 147 mal)

Offline ablas

  • Jr. Member
  • **
  • Beiträge: 49
Why is indirect addressing hidden? This deserves proper visibility.
« am: Februar 18, 2026, 23:26:40 Nachmittag »
I came across something today that I honestly find unacceptable in the manufacturer’s documentation.
The most powerful feature of this PLC — indirect addressing using bracket notation, such as M[MD100] := I[MD100] — is buried inside a section about arrays, with no emphasis, no dedicated explanation, and no indication of its importance.

Thanks to this feature, I was able to implement indirect fault handling, dynamically iterate through inputs, and manage alarms without duplicating code. It transforms the programming model: scalable logic, cleaner structure, and far fewer lines of repetitive instructions.

It is a serious oversight that such a fundamental capability is not highlighted, documented clearly, or demonstrated with proper examples. Many programmers could go years without realizing it exists simply because it is hidden in a chapter where no one would expect to find the key to the most flexible part of the language.

The manufacturer should reconsider how this is presented.
If anyone here has never used indirect addressing, take a look — it is arguably the most powerful tool this PLC offers.

Offline ablas

  • Jr. Member
  • **
  • Beiträge: 49
Antw:Why is indirect addressing hidden? This deserves proper visibility.
« Antwort #1 am: Februar 19, 2026, 08:15:56 Vormittag »
I know, E4 is restricted and you can't write the INPUT STATE TABLE; I agree that's only appropriate for "large" PLCs. Even so, it's the most valuable resource. In the attached PDF, I've included part of some past work, which I humbly believe can be considered a standard. The header states that it corresponds to a Bosch CL500.
Ya sé, E4 está capado y no se puede escribir la TABLA DE ESTADOS DE ENTRADAS, estoy de acuerdo de que eso solo es apropiado para PLCs “grandes”. Aun así, es el recurso más valioso. En el pdf adjunto, dejo parte de un trabajo de mi pasado, creo humildemente que se puede considerar como un estándar. En la cabecera dice que corresponde a un CL500 de Bosch.

Offline ablas

  • Jr. Member
  • **
  • Beiträge: 49
Antw:Why is indirect addressing hidden? This deserves proper visibility.
« Antwort #2 am: Februar 20, 2026, 11:55:12 Vormittag »
I INSIST!!! IT'S A GREAT TOOL. Here's the list; it's easy.
So that those who aren't registered can see it. If you copy and paste the section 0001-0040 into program E4, it will work without any further issues.

INSISTO!!!, ES UNA BUENA HERRAMIENTA. Dejo el listado, es fácil.
Para que la puedan ver los no registrados. Si copias y pegas la parte 0001-0040, en programa E4, te funcionará sin más.

0001 (*==================================*)
0002 (*           LEER BITS DE ENTRADAS DE PARO                 *)
0003 (*        Tratamiento INDIRECTO de 8 fallos                    *)
0004 (* Con revisión y visualización de cada uno de los fallos  *)
0005 (*==================================*)
0006
0007 D01 (EN :=TRUE);
0008
0009 MD100:=0;
0010 MB100:=0;
0011 REPEAT
0012    MD100:=MD100+1;
0013    (*  Copia los estados de bits de Entradas (1-8) a Marcas (1-8)   *)
0014    M[MD100] := I[MD100];
0015    (*  Cuando alcanza el valor "9", salta y finaliza   *)
0016    (* Si la marca está activa, sumamos 1 al contador de fallos (MB100) *)
0017    IF M[MD100] THEN MB100 := MB100 + 1;
0018    END_IF;
0019    (* Aquí se limita y revisa uno a uno cada "Paro" con el contador manual MB101 *)
0020    (* Cuando el contador de FALLOS es >0 y el de REVISIÓN valen igual; finaliza BUCLE REPEAT*)
0021 UNTIL MD100>=9 OR (MB100>0 AND MB100=MB101)
0022
0023 END_REPEAT;
0024
0025 M10:=MB1>=1;
0026 (* P2, (ED01Q1, Flanco +) desplaza el punto de parada del "Bucle REPEAT" y P6 (ESC), lo resetea "0" *)
0027 ED01 (I1 :=P2);
0028 IF ED01Q1 = TRUE THEN MB101:=MB101+1;
0029 END_IF;
0030
0031 IF MB101>=9 OR P6 THEN MB101:=0;
0032 END_IF;
0033 MB101:=MB101; (* Solo para ver valor *)
0034
0035
0036
0037 (*=====================================*)
0038 (*      LEER FALLOS DE DIAGNÓSTICO DEL SISTEMA             *)
0039 (*     Tratamiento INDIRECTO de 30 fallos   (no programado) *)
0040 (*=====================================*)

Nota: Pasar las entradas a marcas es util si queremos puentear en paralelo señales perdidas.
Con los BUCLES, es necesario tener cuidado en aplicaciones donde se requiere una parada rápida por software. Incrementa el tiempo de ciclo y en este caso lo hace variable. Para 8 señales, carece de importancia. E4, dispone de otra herramienta para solucionar paradas inmediatas con tiempo de scan largo y variable.
Editar la pantalla D01, es muy sencillo, solo hay que inscribir las variables MB100 (cantidad o número de fallo) y MD100 (mensaje de texto por valor exacto)
Valor de estado 1 Mensaje de texto STOP IN EST.01
Valor de estado 2 Mensaje de texto STOP IN EST.02
Valor de estado 3 Mensaje de texto STOP IN EST.03
Y así sucesivamente...
Un saludo.
« Letzte Änderung: Februar 20, 2026, 16:45:09 Nachmittag von ablas »

Offline ablas

  • Jr. Member
  • **
  • Beiträge: 49
Hello again. Both options are now operational: reading bits from consecutive inputs to display the message related to that input, and as a second option, the improved version of the system diagnostics. Finally, I mention another project I plan to undertake soon: the comprehensive handling of FAULTS, DIAGNOSTICS, FORCED STATIONS, MANUFACTURER MODULE ERRORS, and EMAIL NOTIFICATION. If anyone has already done this or is currently doing it, please let me know, and I'll join in to collaborate. Best regards. You know, copy/paste and it works.
Hola otra vez. Ahora las dos opciones están operativas, leer bits de entradas correlativas para postrar el mensaje relativo a dicha entrada y como segunda opción, la versión mejorada del diagnóstico del sistema. Al final hago referencia otro trabajo que deseo hacer en breve: El tratamiento global de FALLOS, DIAGÓSTICO, FORZADOS, ERRORES DE MÓDULOS DE FABRICANTE Y ENVÍO DE EMAIL. Si alguien ya lo ha hecho o lo está haciendo, lo dice y me sumo a colaborar. Un saludo. Ya sabes, copia/pega y a funcionar.

0001 (*=========================================================*)
0002 (*          LEER BITS DE ENTRADAS DE PARO                                                                        *)
0003 (*        Tratamiento INDIRECTO de 8 fallos                                                                          *)
0004 (* Con revisión y visualización de cada uno de los fallos                                                       *)
0005 (*=========================================================*)
0006
0007 D01 (EN :=TRUE);(* PANTALLA DE FALLOS *)
0008
0009 MD100:=0;(* Índice para leer y escribir *)
0010 MB395:=0;(* Contador parcial/total de fallos activos *)
0011 REPEAT
0012    MD100:=MD100+1;
0013    (*  Copia los estados de bits de Entradas (1-8) a Marcas (1-8)   *)
0014    M[MD100] := I[MD100];
0015    (* Si la marca está activa, sumamos 1 al contador de fallos (MB395) *)
0016    IF M[MD100] THEN MB395 := MB395+1;
0017    END_IF;
0018
0019 UNTIL MD100>=9 OR (MB395>0 AND MB395=MB396)(* Ver FALLO en pantalla *)
0020 END_REPEAT;
0021
0022 M10:=MB1>=1;
0023 ED01 (I1 :=D01Q1 AND P1);
0024 ED02 (I1 :=D01Q1 AND P3);
0025 IF ED01Q1 AND MB396>1 THEN MB396:=MB396-1;
0026 END_IF;
0027 IF ED02Q1 THEN MB396:=MB396+1;(* Anterior *)
0028 END_IF;
0029 IF D01Q1 AND (MB396>=9 OR P6) THEN MB396:=0;
0030 END_IF;
0031
0032 MB396:=MB396;
0033
0034 (*=========================================================*)
0035 (*      LEER FALLOS DE DIAGNÓSTICO DEL SISTEMA                                                            *)
0036 (*        Tratamiento INDIRECTO de 30 fallos                                                                        *)
0037 (*=========================================================*)
0038
0039 MD101:=0;(* Índice para leer *)
0040 MB405:=0;(* Contador parcial/total de fallos activos *)
0041 REPEAT
0042    MD101:=MD101+1;
0043    IF ID[MD101] THEN MB405 := MB405+1;
0044    END_IF;   
0045 UNTIL MD101>=31 OR (MB405>0 AND MB405=MB406)(* Ver FALLO en pantalla *)
0046 END_REPEAT;
0047
0048 M11:=MB405>=1;
0049 ED03 (I1:=D01Q1 AND P2);
0050 ED04 (I1:=D01Q1 AND P4);
0051 IF ED03Q1 THEN MB406:=MB406+1;(* Siguiente *)
0052 END_IF;
0053 IF ED04Q1 AND MB406>0 THEN MB406:=MB406-1;(* Anterior *)
0054 END_IF;
0055 IF (MB406>=31 OR P6) THEN MB406:=0;(* Resetear *)
0056 END_IF;
0057
0058 MB405:=MB405;
0059 MB406:=MB406;
0060
0061(*==========================================================*)
0062 (*                                --- SIGUIENTE TRABAJO ---                                                              *)
0063 (*           Tratamiento estándar global de FALLOS, DIAGÓSTICO Y DATOS                                *)
0064 (*               Para la VISUALIZACIÓN, FORZADOS  y envío de email                                         *)
0065(*==========================================================*)
0066

Ah, se me olvidaba, tenemos el problema de los números de línea. Para cuando necesitéis
hacerlo es fácil: seleccionamos todo el programa y le "damos" a COMENTAR. Nos quedará
así "0059 //MB406:=MB406;". A partir de ahora lo tenemos facilísimo: Lo abrimos con una
hoja de cálculo excel por ejemplo y nos inicia la plantilla de importación en la que
deberemos seleccionar "Unicode (UTF8) para caracteres y "//" como separador de columnas.
Ya en Excel o Calc, eliminamos las dos columnas sobrantes y le damos imprimir como pdf
Ya en pdf sin números de línea copiar/pegar y corregir algunos defectos de compatibilidad
claramente visibles.

(*=========================================================*)
(*          LEER BITS DE ENTRADAS DE PARO                                                                        *)
(*        Tratamiento INDIRECTO de 8 fallos                                                                          *)
(* Con revisión y visualización de cada uno de los fallos                                                        *)
(*=========================================================*)

D01 (EN :=TRUE);(* PANTALLA DE FALLOS *)

MD100:=0;(* Índice para leer y escribir *)
MB395:=0;(* Contador parcial-total de fallos activos *)
REPEAT
MD100:=MD100+1;
(*  Copia los estados de bits de Entradas (1-8) a Marcas (1-8)   *)
M[MD100] := I[MD100];
(* Si la marca está activa, sumamos 1 al contador de fallos (MB395) *)
IF M[MD100] THEN MB395 := MB395+1;
END_IF;
UNTIL MD100>=9 OR (MB395>0 AND MB395=MB396)(* Ver FALLO en pantalla *)
END_REPEAT;

M10:=MB1>=1;
ED01 (I1 :=D01Q1 AND P1);
ED02 (I1 :=D01Q1 AND P3);
IF ED01Q1 AND MB396>1 THEN MB396:=MB396-1;
END_IF;
IF ED02Q1 THEN MB396:=MB396+1;(* Anterior *)
END_IF;
IF D01Q1 AND (MB396>=9 OR P6) THEN MB396:=0;
END_IF;

MB396:=MB396;

(*=========================================================*)
(*      LEER FALLOS DE DIAGNÓSTICO DEL SISTEMA                                                            *)
(*        Tratamiento INDIRECTO de 30 fallos                                                                        *)
(*=========================================================*)

MD101:=0;(* Índice para leer *)
MB405:=0;(* Contador parcial-total de fallos activos *)
REPEAT
MD101:=MD101+1;
IF ID[MD101] THEN MB405 := MB405+1;
END_IF;   
UNTIL MD101>=31 OR (MB405>0 AND MB405=MB406)(* Ver FALLO en pantalla *)
END_REPEAT;

M11:=MB405>=1;
ED03 (I1:=D01Q1 AND P2);
ED04 (I1:=D01Q1 AND P4);
IF ED03Q1 THEN MB406:=MB406+1;(* Siguiente *)
END_IF;
IF ED04Q1 AND MB406>0 THEN MB406:=MB406-1;(* Anterior *)
END_IF;
IF (MB406>=31 OR P6) THEN MB406:=0;(* Resetear *)
END_IF;

MB405:=MB405;
MB406:=MB406;
« Letzte Änderung: Heute um 22:53:58 von ablas »