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.

93 lines
2.9 KiB
C

#include <unistd.h> // Para enviar comandos y recibir datos desde dispositivos I2C
#include <sys/ioctl.h> // setting up and controlling the I2C device settings
#include <linux/i2c-dev.h> // Definiciones para el sistema de llamadas y estructuras especificaspara I2C
#include <stdio.h> // perror
#include "sen0471_no2.h" // Archivo header
// --- MÉTODO PARA CAMBIAR A MODO Q&A AL SENSOR ---
int changeQA_NO2(int fd) {
// El comando necesita 9 bytes
// 0xFF: Byte de inicio
// 0x01: Dirección
// 0x78: Comando para cambiar tipo
// 0x04: El tipo Q&A
// 0x00...: Rellenos
// 0x83: El checksum (suma de control)
unsigned char cmd[9] = {0xFF, 0x01, 0x78, 0x04, 0x00, 0x00, 0x00, 0x00, 0x83};
// Conecta el driver al sensor en el bus fd a traves de su dirección y estableciendolo como dispositivo esclavo
if (ioctl(fd, I2C_SLAVE, SEN0471_I2C_ADDR) < 0) {
perror("No se pudo conectar al sensor");
return -1;
}
// Envia los 9 bytes
if (write(fd, cmd, 9) != 9) {
perror("Error al escribir el comando de cambio de modo");
return -1; // Falló
}
return 0; // Éxito
}
// --- MÉTODO PARA VERIFICAR EL CHECKSUM (Si el paquete recibido está libre de errores) ---
static int verificar_checksum(unsigned char *buf) {
unsigned char tempq = 0;
int i;
// Suma los bytes del 1 al 7
for (i = 1; i < 8; i++) {
tempq += buf[i];
}
// Calcula el complemento a 2 (negación + 1)
tempq = (~tempq) + 1;
// Compara el resultado con el octavo byte (el checksum recibido)
if (tempq == buf[8]) {
return 1; // El paquete es válido
}
return 0; // El paquete está corrompido
}
// --- MÉTODO PARA OBTENER EL O3 (OZONO) ---
double getNO2(int fd, double *no2_valor){
// Conecta el driver al sensor en el bus fd a traves de su dirección y estableciendolo como dispositivo esclavo
if (ioctl(fd, I2C_SLAVE, SEN0471_I2C_ADDR) < 0) {
perror("No se pudo conectar al sensor de NO2");
return -1;
}
// Enviar el comando de lectura para que el sensor prepare el dato y lo deje listo en el buffer de salida
unsigned char cmd = SEN0471_READ; // 0x86
if (write(fd, &cmd, 1) != 1) {
perror("Error al enviar comando de lectura");
return -1;
}
// Espera a que el sensor prepare el dato
usleep(100000); // 100ms
// Leer el bloque de datos y lo almacena en el arreglo buf
unsigned char buf[9];
int res = read(fd, buf, 9);
if (res < 0) {
perror("Error de lectura I2C");
return -1;
}
// Verifica el checksum
if (!verificar_checksum(buf)) {
printf("Error: Checksum inválido. Datos corruptos descartados.\n");
return -1;
}
// Convierte el valor a valor decimal
int valor_crudo = (buf[2] * 256) + buf[3];
*no2_valor = valor_crudo * 0.1;
return 0;
}