You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
118 lines
3.8 KiB
C
118 lines
3.8 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#include <fcntl.h>
|
|
#include <termios.h>
|
|
|
|
// --- 1. FUNCIÓN DE INICIALIZACIÓN ---
|
|
// Devuelve el descriptor de archivo (fd) o -1 si falla.
|
|
int init_uart(const char *puerto, speed_t baudrate) {
|
|
// Abrir el puerto: Lectura/Escritura, no ser la terminal controladora, no bloquear.
|
|
int fd = open(puerto, O_RDWR | O_NOCTTY | O_NDELAY);
|
|
if (fd == -1) {
|
|
perror("Error al abrir el puerto UART");
|
|
return -1;
|
|
}
|
|
|
|
struct termios tty;
|
|
if (tcgetattr(fd, &tty) != 0) {
|
|
perror("Error al obtener los atributos del puerto");
|
|
close(fd);
|
|
return -1;
|
|
}
|
|
|
|
// Configurar Baudios
|
|
cfsetispeed(&tty, baudrate);
|
|
cfsetospeed(&tty, baudrate);
|
|
|
|
// MODO CRUDO: 8N1 (8 bits, Sin paridad, 1 bit de parada)
|
|
tty.c_cflag &= ~PARENB; // Sin paridad
|
|
tty.c_cflag &= ~CSTOPB; // 1 bit de parada
|
|
tty.c_cflag &= ~CSIZE; // Limpiar máscara de tamaño
|
|
tty.c_cflag |= CS8; // 8 bits de datos
|
|
|
|
// Desactivar control de flujo por hardware y señales de módem
|
|
tty.c_cflag &= ~CRTSCTS;
|
|
tty.c_cflag |= CREAD | CLOCAL;
|
|
|
|
// Desactivar procesamiento de software (Modo crudo absoluto)
|
|
tty.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
|
|
tty.c_oflag &= ~OPOST;
|
|
tty.c_iflag &= ~(IXON | IXOFF | IXANY);
|
|
tty.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL);
|
|
|
|
// Configuración de tiempos de espera (Timeout)
|
|
tty.c_cc[VMIN] = 0; // No exigir un mínimo de bytes
|
|
tty.c_cc[VTIME] = 20; // Esperar máximo 2 segundos (20 decimas)
|
|
|
|
// Limpiar basura del búfer y aplicar la configuración
|
|
tcflush(fd, TCIFLUSH);
|
|
if (tcsetattr(fd, TCSANOW, &tty) != 0) {
|
|
perror("Error al aplicar la configuración UART");
|
|
close(fd);
|
|
return -1;
|
|
}
|
|
|
|
// Quitar el modo "No Bloqueante" para que VTIME y VMIN funcionen correctamente
|
|
fcntl(fd, F_SETFL, 0);
|
|
return fd;
|
|
}
|
|
|
|
// --- 2. FUNCIÓN PARA ENVIAR ---
|
|
void send_uart(int fd, unsigned char *trama, int longitud) {
|
|
tcflush(fd, TCIOFLUSH); // Limpiar tubería antes de hablar
|
|
int escritos = write(fd, trama, longitud);
|
|
if (escritos < 0) {
|
|
perror("Error al escribir en el puerto");
|
|
}
|
|
}
|
|
|
|
// --- 3. FUNCIÓN PARA RECIBIR ---
|
|
int receive_uart(int fd, unsigned char *buffer, int longitud_esperada) {
|
|
int bytes_leidos = read(fd, buffer, longitud_esperada);
|
|
return bytes_leidos;
|
|
}
|
|
|
|
// --- EJEMPLO DE USO ---
|
|
int main() {
|
|
int uart_fd = init_uart("/dev/serial0", B9600);
|
|
if (uart_fd == -1) return 1;
|
|
|
|
unsigned char comando[] = {0xFF, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79};
|
|
unsigned char respuesta[9];
|
|
|
|
while(1) {
|
|
send_uart(uart_fd, comando, sizeof(comando));
|
|
usleep(100000); // 100ms para que el sensor responda
|
|
|
|
int bytes = receive_uart(uart_fd, respuesta, 9);
|
|
|
|
if (bytes == 9) {
|
|
// 1. Calcular el valor real
|
|
int co2_ppm = (respuesta[2] * 256) + respuesta[3];
|
|
|
|
// 2. Imprimir en consola (para tu propio monitoreo)
|
|
printf("Respuesta OK: CO2 = %d ppm\n", co2_ppm);
|
|
|
|
// 3. Escribir el valor en el archivo JSON para la interfaz web
|
|
FILE *archivo_json = fopen("Data/MHZ19B.json", "w"); // "w" sobreescribe el archivo cada vez
|
|
if (archivo_json != NULL) {
|
|
// Formatear estrictamente como JSON
|
|
fprintf(archivo_json, "{\n \"ppm\": %d\n}\n", co2_ppm);
|
|
fclose(archivo_json); // Liberar el archivo para que JS pueda leerlo
|
|
} else {
|
|
perror("Error: No se pudo crear/abrir el archivo JSON");
|
|
}
|
|
|
|
} else {
|
|
printf("Error: Bytes recibidos = %d\n", bytes);
|
|
}
|
|
|
|
sleep(10);
|
|
}
|
|
|
|
close(uart_fd);
|
|
return 0;
|
|
}
|