# Example: Multi-channel Thermocouple

The [Thermocouple Monitoring](thermocouple-monitoring.md) example reads one channel. This variation reads all four channels of an SLM-THM-4 using a `FOR` loop and arrays, with per-channel burnout tracking.

## Hardware

| Slot | Module |
|---|---|
| 1 | **SLM-THM-4** (4-channel thermocouple input) |

Wire thermocouples on channels 1 through 4.

## Backplane configuration

Same as the base example. Configure each channel's sensor type to match the fitted thermocouples.

| Slot | Channel | Address | Alias |
|---|---|---|---|
| 1 | TC1 | `%ID0` | `TC1_Temp` |
| 1 | TC1 Burnout | `%IX0.0` | `TC1_Burnout` |
| 1 | TC2 | `%ID1` | `TC2_Temp` |
| 1 | TC2 Burnout | `%IX0.1` | `TC2_Burnout` |
| 1 | TC3 | `%ID2` | `TC3_Temp` |
| 1 | TC3 Burnout | `%IX0.2` | `TC3_Burnout` |
| 1 | TC4 | `%ID3` | `TC4_Temp` |
| 1 | TC4 Burnout | `%IX0.3` | `TC4_Burnout` |

## The program

### Variables

`````{tab-set}
````{tab-item} Variables table
| Name | Class | Type | Location | Initial Value | Documentation |
|---|---|---|---|---|---|
| `tc1` | Local | `REAL` | `TC1_Temp` | | Channel 1 |
| `tc2` | Local | `REAL` | `TC2_Temp` | | Channel 2 |
| `tc3` | Local | `REAL` | `TC3_Temp` | | Channel 3 |
| `tc4` | Local | `REAL` | `TC4_Temp` | | Channel 4 |
| `tc1_bo` | Local | `BOOL` | `TC1_Burnout` | | Channel 1 burnout |
| `tc2_bo` | Local | `BOOL` | `TC2_Burnout` | | Channel 2 burnout |
| `tc3_bo` | Local | `BOOL` | `TC3_Burnout` | | Channel 3 burnout |
| `tc4_bo` | Local | `BOOL` | `TC4_Burnout` | | Channel 4 burnout |
| `temps` | Local | `ARRAY [1..4] OF REAL` | | | Gathered readings |
| `burnouts` | Local | `ARRAY [1..4] OF BOOL` | | | Gathered status bits |
| `i` | Local | `INT` | | | Loop counter |
| `any_fault` | Local | `BOOL` | | | TRUE if any channel is in burnout |
````

````{tab-item} Text mode
```pascal
  VAR
    tc1 : REAL AT TC1_Temp;
    tc2 : REAL AT TC2_Temp;
    tc3 : REAL AT TC3_Temp;
    tc4 : REAL AT TC4_Temp;
    tc1_bo : BOOL AT TC1_Burnout;
    tc2_bo : BOOL AT TC2_Burnout;
    tc3_bo : BOOL AT TC3_Burnout;
    tc4_bo : BOOL AT TC4_Burnout;
    temps : ARRAY [1..4] OF REAL;
    burnouts : ARRAY [1..4] OF BOOL;
    i : INT;
    any_fault : BOOL;
  END_VAR
```
````
`````

### Code body

```pascal
temps[1] := tc1;    burnouts[1] := tc1_bo;
temps[2] := tc2;    burnouts[2] := tc2_bo;
temps[3] := tc3;    burnouts[3] := tc3_bo;
temps[4] := tc4;    burnouts[4] := tc4_bo;

any_fault := FALSE;
FOR i := 1 TO 4 DO
  IF burnouts[i] THEN
    any_fault := TRUE;
  END_IF;
END_FOR;
```

A located variable can also be declared as an array, bound to consecutive addresses (OpenPLC Editor 4.3.0 or newer):

```pascal
temps AT %ID0 : ARRAY [1..4] OF REAL;      (* %ID0 to %ID3 *)
burnouts AT %IX0.0 : ARRAY [1..4] OF BOOL; (* %IX0.0 to %IX0.3 *)
```

This example binds each channel through its alias instead and copies it into the array, so the program keeps reading the correct channels if the IEC addresses change. Arrays and other custom data types are covered in the [OpenPLC data types documentation](https://edge.autonomylogic.com/docs/openplc-editor/custom-data-types/array-datatypes).
