# Monitoring of Electrical and Thermal Parameters in a Metal Part
# Introduction
This project aims to implement a data acquisition system for measuring temperature, voltage, and current in a metal part subjected to constant current, with the purpose of analyzing its electrical and thermal behavior in real time.
# Methodology
## Representative drawing
The image shows the parts that make up the experiment.

![](Dibujo.png "Diagrama")

## Equipment

| Equipment  |    Model  | Description | Pickture |
|---------|-------------|-------------|----------|
| Digit Multimeter                      | M3500A        | Multimeter used to measure voltage and current     | ![](Multimeter.png "Multimeter")
| Programmable DC Power Supply 0-30 V   | PWS4305       | DC supply for powering the Pyrometer                           | ![](DCPower.png "DCpower")
| System DC Power Supply 150 V / 10 A   | N5770A        | DC source to heat the metal part                              | ![](SystemDC.png "SystemDC")
| Pyrometer CTLaser LT                  | OPTCTLLTSF    | Pyrometer, temperature sensor                                          | ![](Pyrometer.png "Pyrometer")
| Hot plate                             | IKA C-MAG HS7 | Heated bed with temperature control                               | ![](C-MAG.png "c-mag")

## Communication
To communicate the `Digit Multimeter M3500A` and the `System DC Power Supply 150 V / 10 A` a USB cable was used through the VISA protocol (Virtual Instrument Software Architecture) which is a standard for configuring, programming and debugging instrumentation systems that include GPIB interfaces. To do this, you first have to download the NI-VISA software on the computer you intend to use since Python is used to communicate through the Python wrapper `pyvisa` which requires the real VISA installation on the system. Otherwise an error will be thrown.
<br>It is installed `pyvisa`:

```bash
pip install pyvisa
```
To find out if Pyvisa detects the instruments, run the following code in Python:

```python
import pyvisa
rm = pyvisa.ResourceManager()
print(rm.list_resources())
```
If a series of codes are displayed in the Terminal, it means the instruments have indeed been detected and are responding with their data. Something like this:

```Terminal
'USB0::0x164E::0x0DAD::TW00013644::INSTR'
```
### Communication with the Optris CTlaser pyrometer
Communication with the Optris CTlaser pyrometer was performed using the sensor's native binary protocol, using the Python programming language and the standard `pyserial` library for access to the COM port (virtual USB RS-232).
<br>The sensor protocol consists of sending single-byte binary commands and receiving two-byte encoded responses, representing data such as temperature in `uint16` format.
<br>Libraries used:
```python
import serial
import time
```
|communication parameters|    |  
---------------------------|----|
|Baudrate       |115200 bps|
|Bits de datos  |8|
|Paridad        |Ninguna|
|Bits de parada |1|
|Timeout        |1 segundo|

### Command to get temperature
```python
COMANDO_TEMPERATURA = bytes([0x01])
```
This command requests the process temperature (Tprocess). The sensor's response is 2 bytes, which must be interpreted using the following formula:
```python
temperatura = ((byte1 * 256 + byte2) - 1000) / 10
```
All this information was obtained from the manufacturer's manuals which are attached to this repository.

#### Minimum code for pyrometer reading
```python
import serial
import time

sensor = serial.Serial('COM9', baudrate=9600, timeout=1)
time.sleep(2)

sensor.write(bytes([0x01]))  #Comando para solicitar la temperatura
time.sleep(0.2)
respuesta = sensor.read(2)

if len(respuesta) == 2:
    byte1, byte2 = respuesta[0], respuesta[1]
    temperatura = ((byte1 * 256 + byte2) - 1000) / 10
    print(f"Temperatura: {temperatura:.1f} °C")
else:
    print("No se recibió respuesta válida.")

sensor.close()
```
## Code
```python
import tkinter as tk
from tkinter import messagebox
import pyvisa
import time
import csv
from datetime import datetime
import os
from decimal import Decimal
import serial

PUERTO = 'COM9'     #Puerto COM en donde se encuetra el Pyrometer
BAUDRATE = 115200 
COMANDO_TEMPERATURA = bytes([0x01])  # Según protocolo binario del sensor

ID_M3500A = 'USB0::0x164E::0x0DAD::TW00013644::INSTR'           #Multimetro
ID_N5770A = 'USB0::0x0957::0x0807::N5770A-US11M7295J::INSTR'    #Fuente

rm = pyvisa.ResourceManager()

sensor = serial.Serial(
    port=PUERTO,
    baudrate=BAUDRATE,
    bytesize=serial.EIGHTBITS,
    parity=serial.PARITY_NONE,
    stopbits=serial.STOPBITS_ONE,
    timeout=1
)
time.sleep(2)

try:
    # Conectar al multímetro
    m3500a = rm.open_resource(ID_M3500A)
    m3500a.write('*RST')
    m3500a.write('*CLS')
    m3500a.write("CONF:VOLT:DC 100")  # Voltaje DC, rango fijo de 100 V
    m3500a.write("CONF:CURR:DC 10")   # Corriente DC, rango fijo de 10 A

    # Conectar a la fuente de poder
    fuente = rm.open_resource(ID_N5770A)
    fuente.write('*RST')
    fuente.write('*CLS')
    fuente.write('OUTP ON') 

except Exception as e:
    messagebox.showerror("Error", f"Error en la conexión con los instrumentos:\n{e}")
    exit()

directorio = "Mediciones"
os.makedirs(directorio, exist_ok=True)

timestamp = datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
archivo_csv = os.path.join(directorio, f"mediciones_{timestamp}.csv")

with open(archivo_csv, mode='w', newline='') as archivo:
    escritor = csv.writer(archivo)
    escritor.writerow(["Temperatura","Voltaje Medido (V)", "Corriente Medida (A)","Voltaje fuente","Corriente fuente","Fecha"])

##################################################### Lectura del multimetro
def actualizar_lecturas():
    try:
        # === Leer temperatura del sensor ===
        sensor.write(COMANDO_TEMPERATURA)
        time.sleep(0.2)
        respuesta = sensor.read(2)

        if len(respuesta) == 2:
            byte1, byte2 = respuesta[0], respuesta[1]
            temperatura = ((byte1 * 256 + byte2) - 1000) / 10
            label_temperatura.config(text=f"Temperatura: {temperatura:.1f} °C")
        else:
            temperatura = None
            label_temperatura.config(text="Temperatura: --- °C")

        m3500a.write('READ?')                                       # Lectura del multimetro
        voltaje = float(m3500a.read().strip())
        label_voltaje.config(text=f"Voltaje DC: {voltaje:.3f} V")

        fuente.write("VOLT?")                                       # Lectura de la fuente
        voltaje_fuente = float(fuente.read().strip())

        fuente.write("CURR?")
        corriente_fuente = float(fuente.read().strip())

##################################################### Registro en CSV
        fecha_actual = datetime.now().strftime("%H:%M:%S")
        with open(archivo_csv, mode='a', newline='') as archivo:
            escritor = csv.writer(archivo)
            escritor.writerow([temperatura ,voltaje, "", voltaje_fuente, corriente_fuente, fecha_actual])

    except Exception as e:
        label_temperatura.config(text="Temperatura: Error")
        label_voltaje.config(text="Voltaje DC: Error")
        label_corriente.config(text="Corriente DC: Error")
        print(f"Error al leer: {e}")

    # Repetir cada 500 ms
    ventana.after(500, actualizar_lecturas)

##################################################### Control de fuente
def aplicar_valores_fuente():
    try:
        v_set = entrada_voltaje.get()
        i_set = entrada_corriente.get()

        fuente.write(f"VOLT {v_set}")
        fuente.write(f"CURR {i_set}")

        #messagebox.showinfo("Configuración", "Valores aplicados correctamente.")
    except Exception as e:
        messagebox.showerror("Error", f"No se pudo configurar la fuente:\n{e}")

##################################################### Window
ventana = tk.Tk()
ventana.title("CONTROL Y MEDICIÓN")
ventana.geometry("300x250")

######## Lecturas

label_temperatura = tk.Label(ventana, text="temperaruta: --- °C", font=("Arial", 14))
label_temperatura.pack(pady=5)

label_voltaje = tk.Label(ventana, text="Voltaje DC: --- V", font=("Arial", 14))
label_voltaje.pack(pady=5)

label_corriente = tk.Label(ventana, text="Corriente DC: --- A", font=("Arial", 14))
label_corriente.pack(pady=5)

######## Control de fuente

frame_fuente = tk.Frame(ventana)
frame_fuente.pack(pady=10)

tk.Label(frame_fuente, text="Voltaje de salida (V):",font=("Arial",14)).grid(row=0, column=0, padx=5, pady=2)
entrada_voltaje = tk.Entry(frame_fuente, width=10)
entrada_voltaje.grid(row=0, column=1)
entrada_voltaje.bind('<Return>', lambda event: aplicar_valores_fuente())

tk.Label(frame_fuente, text="Corriente límite (A):",font=("Arial",14)).grid(row=1, column=0, padx=5, pady=2)
entrada_corriente = tk.Entry(frame_fuente, width=10)
entrada_corriente.grid(row=1, column=1)
entrada_corriente.bind('<Return>', lambda event: aplicar_valores_fuente())

actualizar_lecturas()
ventana.mainloop()
```