diff --git a/CTR-commands.pdf b/CTR-commands.pdf new file mode 100644 index 0000000..a705f57 Binary files /dev/null and b/CTR-commands.pdf differ diff --git a/CTlaser-manual.pdf b/CTlaser-manual.pdf new file mode 100644 index 0000000..88959ee Binary files /dev/null and b/CTlaser-manual.pdf differ diff --git a/README.md b/README.md index 2f99722..45afe40 100644 --- a/README.md +++ b/README.md @@ -17,5 +17,216 @@ The image shows the parts that make up the experiment. | 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") -## Comunicación -For the communication of the measuring equipment, it is intended to communicate via USB to a computer. \ No newline at end of file +## 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. +
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). +
The sensor protocol consists of sending single-byte binary commands and receiving two-byte encoded responses, representing data such as temperature in `uint16` format. +
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('', 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('', lambda event: aplicar_valores_fuente()) + +actualizar_lecturas() +ventana.mainloop() +``` \ No newline at end of file diff --git a/Tabla-comandos-pyrometer.PNG b/Tabla-comandos-pyrometer.PNG new file mode 100644 index 0000000..1e83c67 Binary files /dev/null and b/Tabla-comandos-pyrometer.PNG differ diff --git a/Table-Emissivity.PNG b/Table-Emissivity.PNG new file mode 100644 index 0000000..c05e30c Binary files /dev/null and b/Table-Emissivity.PNG differ