From ede7fc88f1f57e45e8f9a35da8382f56e1d8b099 Mon Sep 17 00:00:00 2001 From: Israel Herrera Date: Tue, 3 Jun 2025 19:26:39 +0000 Subject: [PATCH] Code --- BMP180 | Bin 0 -> 13444 bytes HTU21D | Bin 0 -> 8928 bytes bmp180-library/bmp180.c | 116 ++++++++++++++++++++++++++++++++++++++ bmp180-library/bmp180.h | 17 ++++++ bmp180-library/main.c | 49 ++++++++++++++++ data/BMP180.json | 1 + data/HTU21D.json | 1 + data/test.json | 0 htu21d-library/.gitignore | 1 + htu21d-library/HTU21D.c | 45 +++++++++++++++ htu21d-library/htu21d.h | 20 +++++++ htu21d-library/main.c | 43 ++++++++++++++ ui/BMP180.json | 0 ui/HTU21D.json | 0 ui/index.html | 35 ++++++++++++ ui/index.js | 28 +++++++++ ui/style.css | 85 ++++++++++++++++++++++++++++ 17 files changed, 441 insertions(+) create mode 100755 BMP180 create mode 100755 HTU21D create mode 100644 bmp180-library/bmp180.c create mode 100644 bmp180-library/bmp180.h create mode 100644 bmp180-library/main.c create mode 100644 data/BMP180.json create mode 100644 data/HTU21D.json create mode 100644 data/test.json create mode 100644 htu21d-library/.gitignore create mode 100644 htu21d-library/HTU21D.c create mode 100644 htu21d-library/htu21d.h create mode 100644 htu21d-library/main.c create mode 100644 ui/BMP180.json create mode 100644 ui/HTU21D.json create mode 100644 ui/index.html create mode 100644 ui/index.js create mode 100644 ui/style.css diff --git a/BMP180 b/BMP180 new file mode 100755 index 0000000000000000000000000000000000000000..f3f6e74710d3349d1b68bad43138362d512680b7 GIT binary patch literal 13444 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 literal 0 HcmV?d00001 diff --git a/bmp180-library/bmp180.c b/bmp180-library/bmp180.c new file mode 100644 index 0000000..a8ee589 --- /dev/null +++ b/bmp180-library/bmp180.c @@ -0,0 +1,116 @@ +#include "bmp180.h" +#include +#include +#include +#include +#include + +#define BMP180_ADDR 0x77 + +// Lectura de 16 bits de un registro (dos bytes) +static int read16(int fd, uint8_t reg, int16_t *value) { + uint8_t buf[2]; + if (write(fd, ®, 1) != 1) return -1; + if (read(fd, buf, 2) != 2) return -1; + *value = (buf[0] << 8) | buf[1]; + return 0; +} + +// Escritura de 8 bits a un registro +static int write8(int fd, uint8_t reg, uint8_t value) { + uint8_t buf[2] = {reg, value}; + if (write(fd, buf, 2) != 2) return -1; + return 0; +} + +// Leer calibración desde el sensor +int bmp180_init(int fd, bmp180_calib_data_t *calib) { + if (read16(fd, 0xAA, &calib->AC1) < 0) return -1; + if (read16(fd, 0xAC, &calib->AC2) < 0) return -1; + if (read16(fd, 0xAE, &calib->AC3) < 0) return -1; + if (read16(fd, 0xB0, (int16_t*)&calib->AC4) < 0) return -1; + if (read16(fd, 0xB2, (int16_t*)&calib->AC5) < 0) return -1; + if (read16(fd, 0xB4, (int16_t*)&calib->AC6) < 0) return -1; + if (read16(fd, 0xB6, &calib->B1) < 0) return -1; + if (read16(fd, 0xB8, &calib->B2) < 0) return -1; + if (read16(fd, 0xBA, &calib->MB) < 0) return -1; + if (read16(fd, 0xBC, &calib->MC) < 0) return -1; + if (read16(fd, 0xBE, &calib->MD) < 0) return -1; + return 0; +} + +// Leer temperatura sin procesar (raw temp) +static int bmp180_read_raw_temperature(int fd, int32_t *raw_temp) { + if (write8(fd, 0xF4, 0x2E) < 0) return -1; // start temp measurement + usleep(4500); // esperar 4.5 ms + int16_t value; + if (read16(fd, 0xF6, &value) < 0) return -1; + *raw_temp = value; + return 0; +} + +// Leer presión sin procesar (raw pressure) +static int bmp180_read_raw_pressure(int fd, int32_t *raw_press, int oss) { + if (write8(fd, 0xF4, 0x34 + (oss << 6)) < 0) return -1; // start pressure measurement + usleep(25000); // esperar 25 ms para oss=0 (simple oversampling) + uint8_t buf[3]; + uint8_t reg = 0xF6; + if (write(fd, ®, 1) != 1) return -1; + if (read(fd, buf, 3) != 3) return -1; + *raw_press = ((buf[0] << 16) | (buf[1] << 8) | buf[2]) >> (8 - oss); + return 0; +} + +int bmp180_read_temperature(int fd, bmp180_calib_data_t *calib, double *temperature) { + int32_t UT; + if (bmp180_read_raw_temperature(fd, &UT) < 0) return -1; + + int32_t X1 = ((UT - calib->AC6) * calib->AC5) >> 15; + int32_t X2 = (calib->MC << 11) / (X1 + calib->MD); + int32_t B5 = X1 + X2; + *temperature = ((B5 + 8) >> 4) / 10.0; + return 0; +} + +int bmp180_read_pressure(int fd, bmp180_calib_data_t *calib, double *pressure) { + int oss = 0; // oversampling setting 0..3 + int32_t UP; + if (bmp180_read_raw_pressure(fd, &UP, oss) < 0) return -1; + + // Recalcular B5 para temperatura, necesario para presión + int32_t UT; + if (bmp180_read_raw_temperature(fd, &UT) < 0) return -1; + + int32_t X1 = ((UT - calib->AC6) * calib->AC5) >> 15; + int32_t X2 = (calib->MC << 11) / (X1 + calib->MD); + int32_t B5 = X1 + X2; + + int32_t B6 = B5 - 4000; + X1 = (calib->B2 * ((B6 * B6) >> 12)) >> 11; + X2 = (calib->AC2 * B6) >> 11; + int32_t X3 = X1 + X2; + int32_t B3 = (((calib->AC1 * 4 + X3) << oss) + 2) >> 2; + + X1 = (calib->AC3 * B6) >> 13; + X2 = (calib->B1 * ((B6 * B6) >> 12)) >> 16; + X3 = ((X1 + X2) + 2) >> 2; + + uint32_t B4 = (calib->AC4 * (uint32_t)(X3 + 32768)) >> 15; + uint32_t B7 = ((uint32_t)UP - B3) * (50000 >> oss); + + int32_t p; + if (B7 < 0x80000000) { + p = (B7 << 1) / B4; + } else { + p = (B7 / B4) << 1; + } + + X1 = (p >> 8) * (p >> 8); + X1 = (X1 * 3038) >> 16; + X2 = (-7357 * p) >> 16; + + p = p + ((X1 + X2 + 3791) >> 4); + + *pressure = p / 100.0; // Pa a hPa (mbar) + return 0; +} diff --git a/bmp180-library/bmp180.h b/bmp180-library/bmp180.h new file mode 100644 index 0000000..d8a7157 --- /dev/null +++ b/bmp180-library/bmp180.h @@ -0,0 +1,17 @@ +#ifndef BMP180_H +#define BMP180_H + +#include + +typedef struct { + int16_t AC1, AC2, AC3; + uint16_t AC4, AC5, AC6; + int16_t B1, B2; + int16_t MB, MC, MD; +} bmp180_calib_data_t; + +int bmp180_init(int fd, bmp180_calib_data_t *calib); +int bmp180_read_temperature(int fd, bmp180_calib_data_t *calib, double *temperature); +int bmp180_read_pressure(int fd, bmp180_calib_data_t *calib, double *pressure); + +#endif diff --git a/bmp180-library/main.c b/bmp180-library/main.c new file mode 100644 index 0000000..62b16dd --- /dev/null +++ b/bmp180-library/main.c @@ -0,0 +1,49 @@ +#include +#include +#include +#include +#include +#include "bmp180.h" + +#define I2C_BUS "/dev/i2c-2" +#define BMP180_ADDR 0x77 + +int main() { + int fd = open(I2C_BUS, O_RDWR); + if (fd < 0) { + perror("Error abriendo el bus I2C"); + return 1; + } + + if (ioctl(fd, I2C_SLAVE, BMP180_ADDR) < 0) { + perror("Error configurando la dirección I2C"); + close(fd); + return 1; + } + + bmp180_calib_data_t calib; + if (bmp180_init(fd, &calib) < 0) { + fprintf(stderr, "Error leyendo datos de calibración BMP180\n"); + close(fd); + return 1; + } + + double temperature, pressure; + + if (bmp180_read_temperature(fd, &calib, &temperature) < 0) { + fprintf(stderr, "Error leyendo temperatura BMP180\n"); + close(fd); + return 1; + } + + if (bmp180_read_pressure(fd, &calib, &pressure) < 0) { + fprintf(stderr, "Error leyendo presión BMP180\n"); + close(fd); + return 1; + } + + printf("{\"temperature\": %.2f, \"pressure\": %.2f}\n", temperature, pressure); + + close(fd); + return 0; +} diff --git a/data/BMP180.json b/data/BMP180.json new file mode 100644 index 0000000..d3af33e --- /dev/null +++ b/data/BMP180.json @@ -0,0 +1 @@ +{ "temperature": 28.70, "pressure": 813.51} \ No newline at end of file diff --git a/data/HTU21D.json b/data/HTU21D.json new file mode 100644 index 0000000..ca9eba0 --- /dev/null +++ b/data/HTU21D.json @@ -0,0 +1 @@ +{ "temperature": 24.60, "humidity": 52.50 } diff --git a/data/test.json b/data/test.json new file mode 100644 index 0000000..e69de29 diff --git a/htu21d-library/.gitignore b/htu21d-library/.gitignore new file mode 100644 index 0000000..1377554 --- /dev/null +++ b/htu21d-library/.gitignore @@ -0,0 +1 @@ +*.swp diff --git a/htu21d-library/HTU21D.c b/htu21d-library/HTU21D.c new file mode 100644 index 0000000..a29b4b6 --- /dev/null +++ b/htu21d-library/HTU21D.c @@ -0,0 +1,45 @@ +#include //Send and recive I2C commands +#include //setup i2c devices +#include //Definitions and structures +#include //smbus commands +#include //To print error + +#include "htu21d.h" + +//Temperature +int getTemp(int fd, double *temp){ + getReset(fd); + char buffer[3]; + __s32 res = i2c_smbus_read_i2c_block_data(fd,HTU21D_TEMP, 3, buffer); + if(res<0){ + perror("ERROR-1: Failed to read Temperature"); + return -1; + } + *temp = -46.85+175.72*(buffer[0]*256+buffer[1])/65536.0; + return 0; +} + +//Humidity +int getHum(int fd, double *hum){ + getReset(fd); + char buffer[3]; + __s32 res = i2c_smbus_read_i2c_block_data(fd,HTU21D_HUM, 3, 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; +} + + +//reset function: +int getReset(int fd){ + if(0>ioctl(fd, I2C_SLAVE, HTU21D_ADDR)){ + perror("ERROR -2: Failed in reset"); + return -2; + } + i2c_smbus_write_byte(fd, HTU21D_RESET); + return 0; + +} diff --git a/htu21d-library/htu21d.h b/htu21d-library/htu21d.h new file mode 100644 index 0000000..83499c9 --- /dev/null +++ b/htu21d-library/htu21d.h @@ -0,0 +1,20 @@ +#ifndef HTU21D_H +#define HTU21D_H + +// HTU21D i2c address +#define HTU21D_ADDR 0x40 + +//commands for readings +#define HTU21D_TEMP 0xE3 +#define HTU21D_HUM 0xE5 +#define HTU21D_RESET 0xFE + +//funtion declarations + +//Temp: +int getTemp(int fd, double *temp); +//HUM +int getHum(int fd, double *hum); +//RESET +int getReset(int fd); +#endif diff --git a/htu21d-library/main.c b/htu21d-library/main.c new file mode 100644 index 0000000..aeabac4 --- /dev/null +++ b/htu21d-library/main.c @@ -0,0 +1,43 @@ +/* Example code of using htu21d.h + Israel Herrera + 20/03/2025 +*/ + +#include +#include +#include +//Aditional librarys +#include +#include +#include "htu21d.h" + +#define I2C_PATH "/dev/i2c-%d" +#define I2C_PORT 2 +int main(){ + char filePath[20]; + snprintf(filePath, sizeof(filePath), I2C_PATH, I2C_PORT ); + int fd = open(filePath, O_RDWR); + + if(fd<0){ + fprintf(stderr, "Error: Unable to access HTU21D sensor: %s",strerror(errno)); + exit(-1); + } + //measurements + double temperature=0; + double humidity=0; + if((getTemp(fd, &temperature)<0)||(getHum(fd, &humidity)<0)){ + fprintf(stderr,"Error -404: Measurments not read"); + exit(-1); + } + + + //printf("HTU21D Module \n"); + //printf("%5.2fC \n", temperature); + //printf("%5.2fC \n", humidity); + printf("{"); + printf("\"temperature\": %5.2f,", temperature); + printf("\"humidity\": %5.2f", humidity); + printf("}"); + return 0; + +} diff --git a/ui/BMP180.json b/ui/BMP180.json new file mode 100644 index 0000000..e69de29 diff --git a/ui/HTU21D.json b/ui/HTU21D.json new file mode 100644 index 0000000..e69de29 diff --git a/ui/index.html b/ui/index.html new file mode 100644 index 0000000..5de0824 --- /dev/null +++ b/ui/index.html @@ -0,0 +1,35 @@ + + + + + + Sensor Dashboard + + + +
+
+

Sensor Dashboard

+ +
+ Temperature & Pressure Icon +

BMP180

+
+ Temperature: -- °C + Pressure: -- hPa +
+
+ +
+ Humidity Icon +

HTU21D

+
+ Humidity: -- % + Temperature: -- °C +
+
+
+ + + + diff --git a/ui/index.js b/ui/index.js new file mode 100644 index 0000000..5654753 --- /dev/null +++ b/ui/index.js @@ -0,0 +1,28 @@ +function updateBMP180() { + fetch('BMP180.json') + .then(res => res.json()) + .then(data => { + document.getElementById('temperature').textContent = `Temperature: ${data.temperature.toFixed(2)} °C`; + document.getElementById('pressure').textContent = `Pressure: ${data.pressure.toFixed(2)} hPa`; + }) + .catch(err => console.error("Error BMP180:", err)); +} + +function updateHTU21D() { + fetch('HTU21D.json') + .then(res => res.json()) + .then(data => { + document.getElementById('humidity').textContent = `Humidity: ${data.humidity.toFixed(1)} %`; + document.getElementById('tempHTU').textContent = `Temperature: ${data.temperature.toFixed(1)} °C`; + }) + .catch(err => console.error("Error HTU21D:", err)); +} + +setInterval(() => { + updateBMP180(); + updateHTU21D(); +}, 3000); + +// Carga inicial +updateBMP180(); +updateHTU21D(); diff --git a/ui/style.css b/ui/style.css new file mode 100644 index 0000000..ca37440 --- /dev/null +++ b/ui/style.css @@ -0,0 +1,85 @@ +* { + margin: 0; + padding: 0; + box-sizing: border-box; + font-family: "Segoe UI", sans-serif; +} + +body, html { + height: 100%; + background-color: #0d1117; + color: #ffffff; + position: relative; + overflow: hidden; +} + +.background { + background-image: url('https://wallpapers.com/images/hd/blue-circuit-board-traces-zn0xezd4t8axj9r6.webp'); + background-size: cover; + background-position: center; + opacity: 0.1; + filter: blur(3px); + position: absolute; + top: 0; left: 0; + width: 100%; + height: 100%; + z-index: -1; +} + +.container { + max-width: 800px; + margin: 40px auto; + background-color: #161b22; + padding: 30px; + border-radius: 20px; + box-shadow: 0 0 30px rgba(0, 255, 255, 0.2); + animation: fadeIn 1s ease-in; +} + +h1 { + text-align: center; + margin-bottom: 30px; + font-size: 2.5rem; + color: #58a6ff; +} + +.sensor-card { + background-color: #1f2937; + padding: 20px; + border-radius: 15px; + margin-bottom: 20px; + box-shadow: 0 0 20px rgba(100, 255, 255, 0.1); + animation: slideIn 1s ease; + display: flex; + flex-direction: column; + align-items: center; + text-align: center; +} + +.sensor-card img { + width: 64px; + height: 64px; + margin-bottom: 10px; +} + +.sensor-card h2 { + margin-bottom: 10px; + color: #90cdf4; +} + +.data span { + display: block; + margin: 5px 0; + font-size: 1.2rem; + color: #ffffff; +} + +@keyframes fadeIn { + from { opacity: 0; transform: translateY(-20px); } + to { opacity: 1; transform: translateY(0); } +} + +@keyframes slideIn { + from { opacity: 0; transform: scale(0.9); } + to { opacity: 1; transform: scale(1); } +}