|
5 days ago | |
---|---|---|
7-sensors | 5 days ago | |
8-react-ui-sensors | 7 days ago | |
ReadMe.md | 5 days ago |
ReadMe.md
Librerías Sensores HTU21D-BH1750 y Código de ejecución main.c
Se desarrollan las librerías referentes al sensor de húmedad y temperatura HTU21D y sensor de luminocidad BH1750. Los presentes sensores utilizan el protocolo de comunicación I2c, por lo que la conexión se realizará en paralelo. Lo primero a realizar es la creación de los headers file, en este caso se crean dos archivos por separado esto con el objetivo de volverlo portable. Dentro de estos archivos declaramos la dirección de cada sensor, así como los comandos que se utilizarán para el desarrollo del proyecto. Tambien se declaran las funciones a utilizar dentro de los archivos ".c".
El contenido del header file referente al sensor HTU21D es el siguiente:
#ifndef HTU21D_H //Definicion del archivo para header
#define HTU21D_H
#define HTU21D_ADDR 0x40 //Definition of sensor address direction
//Commands for reading of temperature or humidity
#define HTU21D_TEMP 0xE3
#define HTU21D_HUM 0xE5
#define HTU21D_RESET 0xFE
//Function declarations
// Temperature:
int get_temp(int fd, double *temp);
// Humidity:
int get_hum(int fd, double *hum);
// Reset:
int reset_sensor(int fd);
#endif
Las funciones declaradas en este archivo es para captura de temperatura y húmedad, además se agrega un función extra para el reseteo del sensor.
El contenido del header fil referente al sensor BH1750 es el siguiente:
#ifndef BH1750_h //Definicion del archivo para header
#define BH1750_h
#define BH1750_ADDR 0x23 //Definition of sensor address direction
//Commands for reading of temperature or humidity
#define BH1750_PON 0x01 //Command for power on
#define BH1750_OTHR 0x20 //Command for One Time H-Resolution
#define BH1750_RESET 0xFE //Command for Reset the sensor
//Function declarations
// Get the brightness:
int get_lux(int fd, double *lux);
// Reset:
int reset_BH1750(int fd);
#endif
En este caso el sensor BH1750 solo mide una variable que es la luminocidad, por lo que se declarán solo dos funciones, una te entrega el valor de luminocidad y la función adicional sirve para el reseteo del sensor.
Archivo HTU21D.c
Dentro de este archivo se desarrolla el contenido de las funciones declaradas dentro del header file. Lo primero que se realiza en este codigo es la declaración de las funciones necesarias para el correcto funcionamiento del archivo. Las librerías son las siguientes:
#include <stdlib.h>
#include <stdio.h> //to print error
#include <unistd.h> //header file for standard I2c send and receive commands
#include <sys/ioctl.h> //setup I2c devices
#include <linux/i2c-dev.h> //definitions and structures
#include <i2c/smbus.h> //smbus commands
#include "HTU21D_H.h"
La siguiente funcion es referente a la obtención del valor de temperatura, esta función te pide como primer argumento el descriptor del archivo del bus I2c y lo siguiente es el puntero a función donde se almacenará el valor de la temperatura. En este caso la forma en que trabaja el sensor es necesario realizar un reset del mismo para que realice la lectura de manera correcta, por lo que se manda a llamar la función reset_sensor.
Una vez reseteado de manera correcta el sensor extrae el dato del bus de I2c y se asigna en un arreglo donde posteriormente se analiza el valor y con este se sabe si se logro establecer la comunicación y que la lectura del dato se realizó de manera correcta. Posteriormente se realiza el calculo del dato y se despliega.
El codigo es el siguiente:
// Temperature:
int get_temp(int fd, double *temp){
reset_sensor(fd);
char buffer[3];
__s32 res = i2c_smbus_read_i2c_block_data(fd, HTU21D_TEMP, sizeof(buffer), buffer);
if (res < 0){
perror("Error -1: Failed to read from the device");
return -1;
}
*temp = -46.85+175.72*(buffer[0]*256+buffer[1])/65536.0;
return 0;
}
La siguiente función sirver para obtener el valor de la húmedad, en este caso como argumento pide los mismos valores que la función para obener la temperatura, sin embargo, estos cambian ya que el comando que se envía es diferente al de la temperatura, además de que el calculo es diferente del valor es diferente. El siguiente codigo es referentea esta funcion:
int get_hum(int fd, double *hum){
reset_sensor(fd);
char buffer[3];
__s32 res = i2c_smbus_read_i2c_block_data(fd, HTU21D_HUM, sizeof(buffer), buffer);
if ( res < 0 ){
perror("Error -3: Failed to read humidity ");
return -1;
}
*hum = -6+125*(buffer[0]*256+buffer[1])/65536.0;
return 0;
}
En la siguiente fución se realiza el reset del sensor en el cual solo pide como argumento la dirección del archivo bus para el I2c. Una vez obtenido se envía el comando para el reseteo del sensor. El codigo es el siguiente:
// Reset Sensor
int reset_sensor(int fd){
if(0 > ioctl(fd, I2C_SLAVE, HTU21D_ADDR)){
perror("Error -2: Failed to reset");
return -2;
}
i2c_smbus_write_byte(fd, HTU21D_RESET);
return 0;
}
Archivo BH1750
Se agregan las mismas librerías que se utilizaron en el sensor HTU21D sin embargo solo se agrega el "header file" correspondiente a este sensor ya que de no ser asi no se podría hacer uso de las funciones escritas en ese archivo.
#include <stdlib.h>
#include <stdio.h> //to print error
#include <fcntl.h>
#include <unistd.h> //header file for standard I2c send and receive commands
#include <sys/ioctl.h> //setup I2c devices
#include <linux/i2c-dev.h> //definitions and structures
#include <i2c/smbus.h> //smbus commands
#include "BH1750_H.h"
En este caso el funcionamiento del sensor es diferente al del HTU21D ya que este no necesita un reseteo previo para la lectura del sensor. En este caso solo se hará uso de una función "get_lux" los argumentos que pide esta función es la direccion del bus del I2c y el puntero a la variable en la cual se regresara el valor estimado. Lo primero que se realiza dentro de esta función es establecer la comunicación con la dirección correspondiente del sensor e indicamos que el sensor será el esclavo.
Lo siguiente es enviar el comando para configurar el tipo de lectura que se desea, en este caso se opto por una sola lectura de alta resolución, posterior a esto hay que esperar un cierto tiempo en el que el sensor se configura. Una vez ya configurado podemos realizar la lectura y de esta manera calcular el valor correspondiente a la luminocidad. El codigo es el siguiente:
int get_lux(int fd, double *lux){
// Establish the direction of the slave
if (ioctl(fd, I2C_SLAVE, BH1750_ADDR) < 0){
perror("Error to stablish the direction of I2C");
//close(fd);
return 1;
}
// Send the command for the mesaurment
if(i2c_smbus_write_byte(fd, BH1750_OTHR) < 0){
perror("Failed to send the command for mesaurment ");
//close(fd);
return 1;
}
usleep(180000);
char buffer[2];
__s32 res = i2c_smbus_read_i2c_block_data(fd, 0x00, sizeof(buffer), buffer);
if (res != 2){
perror("Error -1: Failed to read from the device");
return 1;
}
*lux = ((buffer[0] << 8) | buffer[1]) / 1.2;
return 0;
}
"main.c"
Lo primero que declaramos dentro de este archivo son las librerías correspondiente para la escritura del codigo, tambien agregamos los header files de los sensores, es importante recordar que van dentro de comillas dobles ya que esto indica que los archivos se encuentran dentro de la misma carpeta donde esta el main.c. Tambien definimos los puertos donde se encuentra el bus de I2c y tambien declaramos la dirección del archivo del bus de I2c. Además de estas declaraciones se agregan dos mas correspondientes a los archivos .json correspondientes a cada sensor, ya que estos serán modificados cada que se haga una lectura del sensor.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
//additional libraries:
#include <fcntl.h>
#include "HTU21D_H.h"
#include "BH1750_H.h"
#include <errno.h>
#define I2C_PATH "/dev/i2c-%d"
#define I2C_PORT_2 2
#define I2C_PORT_1 1
#define HTU21D_json_path "/home/debian/CODIGOS/8-react-ui-sensors/ui/HTU21D.json"
#define BH1750_json_path "/home/debian/CODIGOS/8-react-ui-sensors/ui/BH1750.json"
int sensor;
Una vez hecho esto, la primera acción a realizar dentro del bucle infinito es la concatenación del path de la direccion del bus de I2c en el cual se va a establecer la comunicación, una vez hecho esto utilizamos este path para abrirlo en modo lectura y escritura. Una vez que lo habramos verificamos si se abrio de manera correcta en caso que se habra de manera erronea retornará un error.
while (1) {
//if (sensor == 1){
char filePath[99];
snprintf(filePath, sizeof(filePath), I2C_PATH, I2C_PORT_2);
int fd = open(filePath, O_RDWR);
//to do.... complete the structure for the cases when we cant open the file
if(fd < 0){
fprintf(stderr, "Error: Unable to access HTU21D sensor: %s \n ", strerror(errno));
exit(-1);
}
La primera lectura que se realizará es la del sensor HTU21D referente a la temperatura y húmedad. Para esto hacemos uso de las funciones get_temp() y get_hum() y se hace una validación en la cual si el valor de retorno es menor a 0 entonces existe un error extrayendo la información y rompe el ciclo.
double Temperature = 10;
double Humidity = 0;
if((get_temp(fd, &Temperature)<0) || (get_hum(fd, &Humidity)<0)){
fprintf(stderr, "Error -404: Cant do the messaurment \n ");
exit(-1);
}
Una vez que se haya capturado los valores de los sensores se procede a realizar la escritura en los archivos .json correspondientes en este caso el del sensor HTU21D. Una vez que se haya escrito los valores se cierra el archivo y se imprimen los valores en la consola.
FILE *archivo = fopen(HTU21D_json_path, "w");
if (archivo == NULL){
perror("The file can not open ");
return -1;
} else{
fprintf(archivo, "{\"Temperature\" : %5.2f , \"Humidity\" : %5.2f}", Temperature, Humidity);
}
fclose(archivo);
printf ("{\"Temperature\" : %5.2f , \"Humidity\" : %5.2f}", Temperature, Humidity);
Una vez terminado la lectura del sensor HTU21D se procede a realizar la lectura del sensor BH1750, el proceso es el mismo. Como se cerro el bus de comunicación lo volvemos a abrir y verificamos que se haya completado la acción.
fd = open(filePath, O_RDWR);
//to do.... complete the structure for the cases when we cant open the file
if(fd < 0){
fprintf(stderr, "Error: Unable to access HTU21D sensor: %s \n ", strerror(errno));
exit(-1);
}
double Bright = 0;
if((get_lux(fd, &Bright) < 0)){
fprintf(stderr, "Error -404: Cant do the messaurment \n ");
exit(-1);
}
Posteriormente a esto realizamos a lectura del sensor y se verfica que el valor no retorne un error. En caso de no existir algun error con el valor se almacena y se escribe en el archivo ".json" y al final se imprime el valor en la consola.
FILE *archivo_1 = fopen(BH1750_json_path, "w");
if (archivo_1 == NULL){
perror("The file can not open ");
return -1;
} else{
fprintf(archivo_1, "{\"Brightness\" : %5.2f }", Bright);
}
fclose(archivo_1);
printf ("{\"Brightness\" : %5.2f }\n", Bright);
//}
usleep(2000000);
Compilación
Una vez que el archivo main.c se haya completado lo siguiente es realizar la compilación para realizar la prueba correspondiente de funcionamiento. Para la compilación se ejecuta el siguiente comando.
gcc main.c HTU21D.c BH1750_c.c -o executable -li2c
Donde main.c es el documento a compilar, HTU21D.c, BH1750 se agregan estos archivo ya que son necesarios para la poder realizar la compilación y el nombre del archivo que sera la aplicacion y tambien agregamos la libreria li2c para que jale los archivos correspondientes a todo el