primer commit
commit
7a12bcedaf
@ -0,0 +1,16 @@
|
||||
{
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Linux",
|
||||
"includePath": [
|
||||
"${workspaceFolder}/**"
|
||||
],
|
||||
"defines": [],
|
||||
"compilerPath": "/usr/bin/gcc",
|
||||
"cStandard": "c17",
|
||||
"cppStandard": "gnu++20",
|
||||
"intelliSenseMode": "linux-gcc-x64"
|
||||
}
|
||||
],
|
||||
"version": 4
|
||||
}
|
||||
@ -0,0 +1,155 @@
|
||||
// En bmp180.c
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include "bmp180.h"
|
||||
|
||||
// --- FUNCIÓN AUXILIAR PARA LEER VLOQUES DE DATOS ---
|
||||
int leer_bloque_i2c(int fd, uint8_t registro_inicial, uint8_t *buffer, int longitud) {
|
||||
// Le decimos al sensor desde qué registro queremos empezar a leer
|
||||
// (El sensor cuenta con un puntero autoincrementado que inicia del registro inicial enviando una rafaga)
|
||||
if (write(fd, ®istro_inicial, 1) != 1) {
|
||||
perror("Fallo al escribir el registro inicial");
|
||||
return -1; // Falló
|
||||
}
|
||||
|
||||
// Leemos la cantidad de bytes que pedimos
|
||||
if (read(fd, buffer, longitud) != longitud) {
|
||||
perror("Fallo al leer los bytes del sensor");
|
||||
return -1; // Falló
|
||||
}
|
||||
|
||||
return 0; // Éxito
|
||||
}
|
||||
|
||||
// --- MÉTODO DE INICIALIZACIÓN PARA RECONSTRUIR LOS DATOS DE CALIBRACIÓN ---
|
||||
int bmp180_init(int fd, BMP180_CalibData *calib) {
|
||||
uint8_t buffer[22]; // Necesitamos un arreglo de 22 espacios para guardar los 22 bytes
|
||||
|
||||
printf("Iniciando BMP180 y leyendo calibracion...\n");
|
||||
|
||||
// Leemos los 22 bytes empezando desde el registro 0xAA
|
||||
if (leer_bloque_i2c(fd, 0xAA, buffer, 22) < 0) {
|
||||
printf("Error fatal: No se pudo leer la EEPROM.\n");
|
||||
return -1; // Falló
|
||||
}
|
||||
|
||||
// Unimos los bytes.
|
||||
// El sensor envía primero el byte "pesado" (MSB) y luego el "ligero" (LSB).
|
||||
// Tomamos el MSB, lo desplazamos 8 espacios a la izquierda (<< 8) y le sumamos el LSB (|).
|
||||
calib->ac1 = (buffer[0] << 8) | buffer[1];
|
||||
calib->ac2 = (buffer[2] << 8) | buffer[3];
|
||||
calib->ac3 = (buffer[4] << 8) | buffer[5];
|
||||
|
||||
// Estos tres deben ser tratados como sin signo (unsigned) según el datasheet
|
||||
calib->ac4 = (buffer[6] << 8) | buffer[7];
|
||||
calib->ac5 = (buffer[8] << 8) | buffer[9];
|
||||
calib->ac6 = (buffer[10] << 8) | buffer[11];
|
||||
|
||||
calib->b1 = (buffer[12] << 8) | buffer[13];
|
||||
calib->b2 = (buffer[14] << 8) | buffer[15];
|
||||
calib->mb = (buffer[16] << 8) | buffer[17];
|
||||
calib->mc = (buffer[18] << 8) | buffer[19];
|
||||
calib->md = (buffer[20] << 8) | buffer[21];
|
||||
|
||||
// Verificamos que se realizo correctamente
|
||||
// Si la comunicación falla o el cable está mal, a veces el I2C devuelve puros ceros (0)
|
||||
// o puros unos (0xFFFF = -1 en short)
|
||||
if (calib->ac1 == 0 || calib->ac1 == -1) {
|
||||
printf("Advertencia: Los datos de calibración parecen inválidos.\n");
|
||||
return -1; // Falló
|
||||
}
|
||||
|
||||
printf("Calibracion exitosa. Valor AC1: %d\n", calib->ac1);
|
||||
|
||||
return 0; // Todo listo para medir
|
||||
}
|
||||
|
||||
// --- MÉTODO PARA LEER LA TEMPERATURA CRUDA ---
|
||||
long bmp180_read_ut(int fd) {
|
||||
// 0xF4 es el registro de control, 0x2E es el comando de temperatura
|
||||
uint8_t cmd[2] = {BMP180_REG_CTRL_MEAS, BMP180_CMD_TEMP};
|
||||
|
||||
// Escribimos el comando
|
||||
write(fd, cmd, 2);
|
||||
|
||||
// Esperamos a que el hardware del sensor termine la conversión (4.5ms)
|
||||
usleep(4500);
|
||||
|
||||
uint8_t buf[2];
|
||||
// Leemos los 2 bytes resultantes en el registro 0xF6
|
||||
leer_bloque_i2c(fd, BMP180_REG_ADC_MSB, buf, 2);
|
||||
|
||||
// Ensamblamos los 16 bits
|
||||
return (buf[0] << 8) | buf[1];
|
||||
}
|
||||
|
||||
// --- MÉTODO PARA LEER LA PRESIÓN CRUDA ---
|
||||
long bmp180_read_up(int fd, int oss) {
|
||||
// Calculamos el comando exacto basado en la resolución (oss)
|
||||
uint8_t cmd_val = 0x34 + (oss << 6);
|
||||
uint8_t cmd[2] = {BMP180_REG_CTRL_MEAS, cmd_val};
|
||||
|
||||
write(fd, cmd, 2);
|
||||
|
||||
// El tiempo de espera del hardware aumenta si pides más resolución
|
||||
switch(oss) {
|
||||
case 0: usleep(4500); break;
|
||||
case 1: usleep(7500); break;
|
||||
case 2: usleep(13500); break;
|
||||
case 3: usleep(25500); break;
|
||||
}
|
||||
|
||||
uint8_t buf[3];
|
||||
// Leemos 3 bytes (MSB, LSB, XLSB) desde 0xF6
|
||||
leer_bloque_i2c(fd, BMP180_REG_ADC_MSB, buf, 3);
|
||||
|
||||
// Desplazamiento a nivel de bits exigido por el fabricante
|
||||
return ((long)buf[0] << 16 | (long)buf[1] << 8 | (long)buf[2]) >> (8 - oss);
|
||||
}
|
||||
|
||||
|
||||
// --- MÉTODO PARA MEDIR LA PRESIÓN CALIBRADA ---
|
||||
int bmp180_get_pressure(int fd, BMP180_CalibData *calib, int oss, double *pressure) {
|
||||
// Medimos la temperatura y presión crudas
|
||||
long UT = bmp180_read_ut(fd);
|
||||
long UP = bmp180_read_up(fd, oss);
|
||||
|
||||
// Declaramos las variables locales según la hoja de datos (página 15)
|
||||
long X1, X2, X3, B3, B5, B6, p;
|
||||
unsigned long B4, B7;
|
||||
|
||||
// --- Ecuaciones de Temperatura (Para obtener B5) ---
|
||||
X1 = ((UT - calib->ac6) * calib->ac5) >> 15;
|
||||
X2 = ((long)calib->mc << 11) / (X1 + calib->md); // Cast a long obligatorio en mc
|
||||
B5 = X1 + X2;
|
||||
|
||||
// --- Ecuaciones de Presión ---
|
||||
B6 = B5 - 4000;
|
||||
X1 = (calib->b2 * (B6 * B6 >> 12)) >> 11;
|
||||
X2 = (calib->ac2 * B6) >> 11;
|
||||
X3 = X1 + X2;
|
||||
B3 = ((((long)calib->ac1 * 4 + X3) << oss) + 2) >> 2;
|
||||
|
||||
X1 = (calib->ac3 * B6) >> 13;
|
||||
X2 = (calib->b1 * ((B6 * B6) >> 12)) >> 16;
|
||||
X3 = ((X1 + X2) + 2) >> 2;
|
||||
B4 = (calib->ac4 * (unsigned long)(X3 + 32768)) >> 15;
|
||||
B7 = ((unsigned long)UP - B3) * (50000 >> oss);
|
||||
|
||||
if (B7 < 0x80000000) {
|
||||
p = (B7 * 2) / B4;
|
||||
} else {
|
||||
p = (B7 / B4) * 2;
|
||||
}
|
||||
|
||||
X1 = (p >> 8) * (p >> 8);
|
||||
X1 = (X1 * 3038) >> 16;
|
||||
X2 = (-7357 * p) >> 16;
|
||||
p = p + ((X1 + X2 + 3791) >> 4);
|
||||
|
||||
// El cálculo arroja Pascales, dividimos entre 100 para Hectopascales (hPa)
|
||||
*pressure = p / 100.0;
|
||||
|
||||
return 0; // Éxito
|
||||
}
|
||||
@ -0,0 +1,27 @@
|
||||
#ifndef BMP180_H
|
||||
#define BMP180_H
|
||||
|
||||
// --- DIRECCIÓN I2C ---
|
||||
#define BMP180_I2C_ADDR 0x77
|
||||
// --- REGISTROS DEL BMP180 ---
|
||||
#define BMP180_REG_CTRL_MEAS 0xF4 // Registro de control para iniciar mediciones
|
||||
#define BMP180_REG_ADC_MSB 0xF6 // Registro de salida de datos: Byte Más Significativo
|
||||
#define BMP180_REG_ADC_LSB 0xF7 // Registro de salida de datos: Byte Menos Significativo
|
||||
#define BMP180_REG_ADC_XLSB 0xF8 // Registro de salida de datos: Byte Extendido
|
||||
// --- COMANDOS DE CONTROL (REGISTRO 0xF4) ---
|
||||
#define BMP180_CMD_TEMP 0x2E // Orden de medir temperatura.
|
||||
#define BMP180_CMD_PRES_OSS2 0xB4 // Presión: High Resolution (oss=2)
|
||||
|
||||
// Estructura para almacenar los datos de calibración de fábrica
|
||||
typedef struct {
|
||||
short ac1, ac2, ac3;
|
||||
unsigned short ac4, ac5, ac6;
|
||||
short b1, b2, mb, mc, md;
|
||||
} BMP180_CalibData;
|
||||
|
||||
// --- DECLARACIÓN DE MÉTODOS PARA bmp180.c ---
|
||||
int bmp180_init(int fd, BMP180_CalibData *calib); // Calibración
|
||||
int bmp180_get_temperature(int fd, double *temperature); // Temperatura
|
||||
int bmp180_get_pressure(int fd, BMP180_CalibData *calib, int oss, double *pressure); // Presión
|
||||
|
||||
#endif // BMP180_H
|
||||
@ -0,0 +1,52 @@
|
||||
#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 <i2c/smbus.h> // SMBus commands in a more standardized way for I2C
|
||||
#include <stdio.h> // perror
|
||||
|
||||
#include "htu21d.h" // my own header file
|
||||
|
||||
// Reset function:
|
||||
int reset(int fd)
|
||||
{
|
||||
if(0 > ioctl(fd, I2C_SLAVE, HTU21D_I2C_ADDR))
|
||||
{
|
||||
perror("Failed to open the bus");
|
||||
return -1;
|
||||
}
|
||||
i2c_smbus_write_byte(fd, HTU21D_RESET);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Get temperature:
|
||||
int getTemperature(int fd, double *temperature)
|
||||
{
|
||||
reset(fd);
|
||||
char buf[3];
|
||||
__s32 res = i2c_smbus_read_i2c_block_data(fd, HTU21D_TEMP,3,buf);
|
||||
if(res<0)
|
||||
{
|
||||
perror("Failed to read from the device");
|
||||
return -1;
|
||||
}
|
||||
*temperature = -46.85 + 175.72 * (buf[0]*256 + buf[1]) / 65536.0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// Get humidity:
|
||||
int getHumidity(int fd, double *humidity)
|
||||
{
|
||||
reset(fd);
|
||||
char buf[3];
|
||||
__s32 res = i2c_smbus_read_i2c_block_data(fd, HTU21D_HUMID, 3, buf);
|
||||
if(res<0)
|
||||
{
|
||||
perror("Failed to read from the device");
|
||||
return -1;
|
||||
}
|
||||
*humidity = -6 + 125 * (buf[0]*256 + buf[1]) / 65536.0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,15 @@
|
||||
#ifndef HTU21D_H
|
||||
#define HTU21D_H
|
||||
|
||||
// I2C Address
|
||||
#define HTU21D_I2C_ADDR 0x40
|
||||
// Commands
|
||||
#define HTU21D_TEMP 0xE3
|
||||
#define HTU21D_HUMID 0xE5
|
||||
#define HTU21D_RESET 0xFE
|
||||
|
||||
// --- DECLARACIÓN DE MÉTODOS PARA htu21d.c ---
|
||||
int getTemperature(int fd, double *temperature); // Temperatura
|
||||
int getHumidity(int fd, double *humidity); // Humedad
|
||||
|
||||
#endif // HTU21D_H
|
||||
@ -0,0 +1,188 @@
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <linux/i2c-dev.h>
|
||||
#include <time.h> // Necesario para la fecha y hora
|
||||
#include <sqlite3.h>
|
||||
#include <string.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
// Controladores
|
||||
#include "bmp180.h"
|
||||
#include "htu21d.h"
|
||||
#include "sen0472_o3.h"
|
||||
#include "sen0471_no2.h"
|
||||
#include "sen0470_so2.h"
|
||||
#include "sen0466_co.h"
|
||||
|
||||
// Definimos la ruta donde vivirá tu base de datos final
|
||||
#define RUTA_BD "/var/www/html/AirQualityMicrostation/Database/microestacionAQ.db" // Ajusta esta ruta a tu carpeta real
|
||||
|
||||
void guardar_lote_en_bd(const char *ruta_lote) {
|
||||
sqlite3 *bd;
|
||||
char *mensaje_error = 0;
|
||||
|
||||
// 1. Abrimos o creamos la base de datos
|
||||
if (sqlite3_open(RUTA_BD, &bd) != SQLITE_OK) {
|
||||
printf("Error: No se pudo abrir la base de datos: %s\n", sqlite3_errmsg(bd));
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. Creamos la tabla si no existe
|
||||
const char *instruccion_crear =
|
||||
"CREATE TABLE IF NOT EXISTS mediciones ("
|
||||
"id INTEGER PRIMARY KEY AUTOINCREMENT, "
|
||||
"fecha_hora TEXT, presion REAL, temperatura REAL, "
|
||||
"humedad REAL, ozono REAL, no2 REAL, co INTEGER, so2 REAL, "
|
||||
"ica INTEGER, banda_ica TEXT);";
|
||||
|
||||
if (sqlite3_exec(bd, instruccion_crear, 0, 0, &mensaje_error) != SQLITE_OK) {
|
||||
printf("Error al crear tabla: %s\n", mensaje_error);
|
||||
sqlite3_free(mensaje_error);
|
||||
}
|
||||
|
||||
// 3. Abrimos el archivo temporal que contiene las lecturas de los últimos 5 minutos
|
||||
FILE *archivo = fopen(ruta_lote, "r");
|
||||
if (archivo == NULL) {
|
||||
printf("Advertencia: No se encontró el archivo temporal para guardar.\n");
|
||||
sqlite3_close(bd);
|
||||
return;
|
||||
}
|
||||
|
||||
// Arreglo temporal para guardar cada línea de texto que leamos
|
||||
char linea[256];
|
||||
|
||||
// 4. Leemos el archivo línea por línea hasta llegar al final
|
||||
while (fgets(linea, sizeof(linea), archivo)) {
|
||||
char fecha_hora[64];
|
||||
double presion, temperatura, humedad, ozono, no2, so2;
|
||||
int co;
|
||||
|
||||
// 5. Extraemos los valores separados por comas
|
||||
// El formato %[^,] significa "lee todo el texto hasta encontrar una coma"
|
||||
if (sscanf(linea, "%[^,],%lf,%lf,%lf,%lf,%lf,%d,%lf",
|
||||
fecha_hora, &presion, &temperatura, &humedad,
|
||||
&ozono, &no2, &co, &so2) == 8) {
|
||||
|
||||
// 6. Armamos la instrucción de inserción con los valores exactos
|
||||
char instruccion_insertar[512];
|
||||
sprintf(instruccion_insertar,
|
||||
"INSERT INTO mediciones (fecha_hora, presion, temperatura, humedad, ozono, no2, co, so2, ica, banda_ica) "
|
||||
"VALUES ('%s', %.2f, %.2f, %.2f, %.2f, %.2f, %d, %.2f, NULL, NULL);",
|
||||
fecha_hora, presion, temperatura, humedad, ozono, no2, co, so2);
|
||||
// 7. Ejecutamos la inserción en la base de datos
|
||||
if (sqlite3_exec(bd, instruccion_insertar, 0, 0, &mensaje_error) != SQLITE_OK) {
|
||||
printf("Error al insertar fila: %s\n", mensaje_error);
|
||||
sqlite3_free(mensaje_error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 8. Limpiamos y cerramos todo
|
||||
fclose(archivo);
|
||||
sqlite3_close(bd);
|
||||
}
|
||||
|
||||
int main() {
|
||||
// --- Apertura de los buses ---
|
||||
// Bus principal: Clima (BMP180 y HTU21D)
|
||||
int fd_principal = open("/dev/i2c-1", O_RDWR);
|
||||
if (fd_principal < 0) {
|
||||
printf("Error: No se pudo abrir el bus I2C principal.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Bus secundario: Gases (Familia DFRobot)
|
||||
int fd_secundario = open("/dev/i2c-3", O_RDWR);
|
||||
if (fd_secundario < 0) {
|
||||
printf("Error: No se pudo abrir el bus I2C secundario.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// --- Configuración inicial ---
|
||||
printf("Iniciando microestación...\n");
|
||||
|
||||
// BMP180 en el bus principal (Conexión e inicialización)
|
||||
ioctl(fd_principal, I2C_SLAVE, 0x77); // <- LÍNEA NUEVA
|
||||
BMP180_CalibData calibracion_bmp;
|
||||
bmp180_init(fd_principal, &calibracion_bmp);
|
||||
|
||||
// Sensores de gas en el bus secundario
|
||||
changeQA_O3(fd_secundario);
|
||||
changeQA_NO2(fd_secundario);
|
||||
changeQA_CO(fd_secundario);
|
||||
changeQA_SO2(fd_secundario);
|
||||
|
||||
double presion, temp_htu, humedad, ozono, dioxido_nitrogeno, dioxido_azufre;
|
||||
int monoxido;
|
||||
int contador_bd = 0;
|
||||
|
||||
// --- Ciclo continuo de monitoreo ---
|
||||
while (1) {
|
||||
// 1. Obtener la fecha y hora actual del sistema
|
||||
time_t t = time(NULL);
|
||||
struct tm tm = *localtime(&t);
|
||||
char fecha_hora[64];
|
||||
// Formato: Año-Mes-Día Hora:Minuto:Segundo
|
||||
sprintf(fecha_hora, "%04d-%02d-%02d %02d:%02d:%02d",
|
||||
tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
|
||||
tm.tm_hour, tm.tm_min, tm.tm_sec);
|
||||
|
||||
// 2. Extracción de datos separada por buses
|
||||
// Bus Principal
|
||||
ioctl(fd_principal, I2C_SLAVE, 0x77); // Recuperamos el control del bus para el bmp180
|
||||
bmp180_get_pressure(fd_principal, &calibracion_bmp, 2, &presion);
|
||||
getTemperature(fd_principal, &temp_htu);
|
||||
getHumidity(fd_principal, &humedad);
|
||||
|
||||
// Bus Secundario
|
||||
getO3(fd_secundario, &ozono);
|
||||
getNO2(fd_secundario, &dioxido_nitrogeno);
|
||||
getCO(fd_secundario, &monoxido);
|
||||
getSO2(fd_secundario, &dioxido_azufre);
|
||||
|
||||
// 3. Escribir el estado actual (Sobrescribir archivo para el comando terminal)
|
||||
FILE *archivo_actual = fopen("/dev/shm/aql_actual.txt", "w");
|
||||
if (archivo_actual != NULL) {
|
||||
fprintf(archivo_actual, "PRES=%.2f\n", presion);
|
||||
fprintf(archivo_actual, "TEMP=%.2f\n", temp_htu);
|
||||
fprintf(archivo_actual, "HUM=%.2f\n", humedad);
|
||||
fprintf(archivo_actual, "O3=%.2f\n", ozono);
|
||||
fprintf(archivo_actual, "NO2=%.2f\n", dioxido_nitrogeno);
|
||||
fprintf(archivo_actual, "CO=%d\n", monoxido);
|
||||
fprintf(archivo_actual, "SO2=%.2f\n", dioxido_azufre);
|
||||
fprintf(archivo_actual, "FECHA=\"%s\"\n", fecha_hora);
|
||||
fclose(archivo_actual);
|
||||
}
|
||||
|
||||
// 4. Escribir el historial temporal (Agregar línea para la Base de Datos)
|
||||
// Usamos "a" (append) para añadir sin borrar lo anterior
|
||||
FILE *archivo_lote = fopen("/dev/shm/lote_bd.csv", "a");
|
||||
if (archivo_lote != NULL) {
|
||||
// Guardamos todo separado por comas para facilitar la lectura posterior
|
||||
fprintf(archivo_lote, "%s,%.2f,%.2f,%.2f,%.2f,%.2f,%d,%.2f\n",
|
||||
fecha_hora, presion, temp_htu, humedad, ozono, dioxido_nitrogeno, monoxido, dioxido_azufre);
|
||||
fclose(archivo_lote);
|
||||
}
|
||||
|
||||
// 5. Lógica de almacenamiento masivo en la Base de Datos (Cada 5 minutos)
|
||||
contador_bd++;
|
||||
if (contador_bd >= 30) {
|
||||
// Llamamos a la función pasándole la ruta del archivo temporal
|
||||
guardar_lote_en_bd("/dev/shm/lote_bd.csv");
|
||||
|
||||
// Una vez guardado, borramos el archivo de lote para empezar de cero
|
||||
FILE *limpiar_lote = fopen("/dev/shm/lote_bd.csv", "w");
|
||||
if (limpiar_lote != NULL) fclose(limpiar_lote);
|
||||
|
||||
contador_bd = 0;
|
||||
}
|
||||
|
||||
// Esperar 10 segundos
|
||||
sleep(10);
|
||||
}
|
||||
|
||||
close(fd_principal);
|
||||
close(fd_secundario);
|
||||
return 0;
|
||||
}
|
||||
@ -0,0 +1,92 @@
|
||||
#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 "sen0466_co.h" // Archivo header
|
||||
|
||||
int changeQA_CO(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, SEN0466_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;
|
||||
} /*else {
|
||||
printf("Comando enviado exitosamente. Sensor en modo Q&A.\n");
|
||||
}*/
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
// --- 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
|
||||
}
|
||||
|
||||
int getCO(int fd, int *co_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, SEN0466_I2C_ADDR) < 0) {
|
||||
perror("No se pudo conectar al sensor de CO");
|
||||
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 = SEN0466_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
|
||||
*co_valor = (buf[2] * 256) + buf[3];
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -0,0 +1,15 @@
|
||||
#ifndef SEN0466_H
|
||||
#define SEN0466_H
|
||||
|
||||
// --- DIRECCIÓN I2C ---
|
||||
#define SEN0466_I2C_ADDR 0x76
|
||||
// --- COMANDOS ---
|
||||
#define SEN0466_CTYP 0x78
|
||||
#define SEN0466_QA 0x04
|
||||
#define SEN0466_READ 0x86
|
||||
|
||||
// --- DECLARACIÓN DE MÉTODOS PARA sen0466.c ---
|
||||
int getCO(int fd, int *co_valor); // CO (Monoxido de Carbono)
|
||||
int changeQA_CO(int fd); // Cambio a modo Q&A
|
||||
|
||||
#endif // SEN0466_H
|
||||
@ -0,0 +1,92 @@
|
||||
#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 "sen0470_so2.h" // Archivo header
|
||||
|
||||
// --- MÉTODO PARA CAMBIAR A MODO Q&A AL SENSOR ---
|
||||
int changeQA_SO2(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, SEN0470_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 SO2 (Dioxido de Azufre) ---
|
||||
double getSO2(int fd, double *so2_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, SEN0470_I2C_ADDR) < 0) {
|
||||
perror("No se pudo conectar al sensor de SO2");
|
||||
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 = SEN0470_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];
|
||||
*so2_valor = valor_crudo * 0.1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -0,0 +1,15 @@
|
||||
#ifndef SEN0470_H
|
||||
#define SEN0470_H
|
||||
|
||||
// --- DIRECCIÓN I2C ---
|
||||
#define SEN0470_I2C_ADDR 0x77
|
||||
// --- COMANDOS ---
|
||||
#define SEN0470_CTYP 0x78
|
||||
#define SEN0470_QA 0x04
|
||||
#define SEN0470_READ 0x86
|
||||
|
||||
// --- DECLARACIÓN DE MÉTODOS PARA sen0472.c ---
|
||||
double getSO2(int fd, double *so2_valor); // SO2 (Dióxido de azufre)
|
||||
int changeQA_SO2(int fd); // Cambio a modo Q&A
|
||||
|
||||
#endif // SEN0472_H
|
||||
@ -0,0 +1,92 @@
|
||||
#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;
|
||||
}
|
||||
@ -0,0 +1,15 @@
|
||||
#ifndef SEN0471_H
|
||||
#define SEN0471_H
|
||||
|
||||
// --- DIRECCIÓN I2C ---
|
||||
#define SEN0471_I2C_ADDR 0x75
|
||||
// --- COMANDOS ---
|
||||
#define SEN0471_CTYP 0x78
|
||||
#define SEN0471_QA 0x04
|
||||
#define SEN0471_READ 0x86
|
||||
|
||||
// --- DECLARACIÓN DE MÉTODOS PARA sen0472.c ---
|
||||
double getNO2(int fd, double *no2_valor); // NO2 (Ozono)
|
||||
int changeQA_NO2(int fd); // Cambio a modo Q&A
|
||||
|
||||
#endif // SEN0471_H
|
||||
@ -0,0 +1,92 @@
|
||||
#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 "sen0472_o3.h" // Archivo header
|
||||
|
||||
// --- MÉTODO PARA CAMBIAR A MODO Q&A AL SENSOR ---
|
||||
int changeQA_O3(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, SEN0472_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 getO3(int fd, double *o3_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, SEN0472_I2C_ADDR) < 0) {
|
||||
perror("No se pudo conectar al sensor de O3");
|
||||
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 = SEN0472_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];
|
||||
*o3_valor = valor_crudo * 0.1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -0,0 +1,15 @@
|
||||
#ifndef SEN0472_H
|
||||
#define SEN0472_H
|
||||
|
||||
// --- DIRECCIÓN I2C ---
|
||||
#define SEN0472_I2C_ADDR 0x74
|
||||
// --- COMANDOS ---
|
||||
#define SEN0472_CTYP 0x78
|
||||
#define SEN0472_QA 0x04
|
||||
#define SEN0472_READ 0x86
|
||||
|
||||
// --- DECLARACIÓN DE MÉTODOS PARA sen0472.c ---
|
||||
double getO3(int fd, double *o3_valor); // O3 (Ozono)
|
||||
int changeQA_O3(int fd); // Cambio a modo Q&A
|
||||
|
||||
#endif // SEN0472_H
|
||||
@ -0,0 +1,10 @@
|
||||
Component Description,QTY,Ref Des,Mfg P/N #,Manufacturer,Distributor P/N #
|
||||
"Multilayer Ceramic Capacitors MLCC - SMD/SMT, 100nF, C1206","2","C1,C2","GRM31C5C2A104JA01L","muRata(村田)",""
|
||||
"Schottky Barrier Diodes (SBD), SOD-128_L3.7-W2.5-LS4.7-RD","1","D1","PMEG3020CEP,115","Nexperia(安世)",""
|
||||
"Standoff","4","H1,H2,H3,H4","M2106-2545-AL","RAF Electronic Hardware",""
|
||||
"Connector","1","J1","CON-SOCJ-2155","Gravitech",""
|
||||
"Connector","4","J2,J3,J4,J5","TSW-104-07-T-S","",""
|
||||
"Resistor, 10kΩ","4","R1,R2,R3,R4","RC1206FR-0710KL","",""
|
||||
"Connector","1","RPi1","SC0195","",""
|
||||
"Sensor","1","U1","HTU21D","Measurement Specialties",""
|
||||
"Sensor","1","U2","BMP180","Bosch Sensortec",""
|
||||
|
@ -0,0 +1,10 @@
|
||||
Item #,Ref Des,Qty,Manufacturer,Mfg Part #,Description / Value,Package,Type,Your Instructions / Notes
|
||||
"1","C1,C2","2","muRata(村田)","GRM31C5C2A104JA01L","Multilayer Ceramic Capacitors MLCC - SMD/SMT, 100nF, C1206","C1206","",""
|
||||
"2","D1","1","Nexperia(安世)","PMEG3020CEP,115","Schottky Barrier Diodes (SBD), SOD-128_L3.7-W2.5-LS4.7-RD","SOD-128_L3.7-W2.5-LS4.7-RD","",""
|
||||
"3","H1,H2,H3,H4","4","RAF Electronic Hardware","M2106-2545-AL","Standoff","","",""
|
||||
"4","J1","1","Gravitech","CON-SOCJ-2155","Connector","","",""
|
||||
"5","J2,J3,J4,J5","4","","TSW-104-07-T-S","Connector","","",""
|
||||
"6","R1,R2,R3,R4","4","","RC1206FR-0710KL","Resistor, 10kΩ","","",""
|
||||
"7","RPi1","1","","SC0195","Connector","","",""
|
||||
"8","U1","1","Measurement Specialties","HTU21D","Sensor","","",""
|
||||
"9","U2","1","Bosch Sensortec","BMP180","Sensor","","",""
|
||||
|
@ -0,0 +1,25 @@
|
||||
*Reference,*Manufacturer Part number,*QTY,*Original,Description,Purchase Link
|
||||
"C1, C2","GRM31C5C2A104JA01L","2","","100V 100nF C0G ±5% 1206 Multilayer Ceramic Capacitors Multilayer Ceramic Capacitors MLCC - SMD/SMT
|
||||
GRM31C5C2A104JA01L
|
||||
C1206
|
||||
LCSC Part Number: C405303
|
||||
JLCPCB Part Class: Extended Part
|
||||
Manufactured by muRata(村田) ",""
|
||||
"D1","PMEG3020CEP,115","1","","Schottky Barrier Diodes (SBD)
|
||||
PMEG3020CEP,115
|
||||
SOD-128_L3.7-W2.5-LS4.7-RD
|
||||
LCSC Part Number: C552871
|
||||
JLCPCB Part Class: Extended Part
|
||||
Manufactured by Nexperia(安世) ",""
|
||||
"H1, H2, H3, H4","M2106-2545-AL","4","","Hex Standoff Threaded M2.5x0.45 Aluminum 0.433"" (11.00mm)
|
||||
#Standoff ",""
|
||||
"J1","CON-SOCJ-2155","1","","DC Power Connectors Power Jack/Connector 2.1mm x 5.5mm #CommonPartsLibrary #",""
|
||||
"J2, J3, J4, J5","TSW-104-07-T-S","4","","Through Hole straight pin header, 01x04, 2.54mm pitch, single row #pinheader #tht",""
|
||||
"R1, R2, R3, R4","RC1206FR-0710KL","4","","Chip Resistor 1206 (3216 Metric) Template #noprop",""
|
||||
"RPi1","SC0195","1","","Raspberry Pi 2, 3, 4, 5 or 400 Model B+ connector with RPi board outline and mounting holes. good for Raspberry Pi Shield projects. Insulation Height
|
||||
0.335"" (8.51mm) Compatible part number: PPPC202LFBN-RC #Raspberry_Pi #Shield #RPi #template #part",""
|
||||
"U1","HTU21D","1","","Board Mount Humidity Sensors I.C 21DF RH/T DIGITAL MODULE #commonpartslibrary
|
||||
#integratedcircuit
|
||||
#humiditysensor
|
||||
#digitalmodule",""
|
||||
"U2","BMP180","1","","Pressure Sensor 4.35PSI ~ 15.95PSI (30kPa ~ 110kPa) Absolute 16 ~ 19 b 7-VLGA #CommonPartsLibrary #Sensor #Transducer",""
|
||||
|
@ -0,0 +1,10 @@
|
||||
Reference designators,Quantity,MPN,Manufacturer,Part description,Value,SPN,Supplier,Package
|
||||
"C1,C2","2","GRM31C5C2A104JA01L","muRata(村田)","Multilayer Ceramic Capacitors MLCC - SMD/SMT, 100nF, C1206","100nF","","","C1206"
|
||||
"D1","1","PMEG3020CEP,115","Nexperia(安世)","Schottky Barrier Diodes (SBD), SOD-128_L3.7-W2.5-LS4.7-RD","","","","SOD-128_L3.7-W2.5-LS4.7-RD"
|
||||
"H1,H2,H3,H4","4","M2106-2545-AL","RAF Electronic Hardware","Standoff","","","",""
|
||||
"J1","1","CON-SOCJ-2155","Gravitech","Connector","","","",""
|
||||
"J2,J3,J4,J5","4","TSW-104-07-T-S","","Connector","","","",""
|
||||
"R1,R2,R3,R4","4","RC1206FR-0710KL","","Resistor, 10kΩ","10kΩ","","",""
|
||||
"RPi1","1","SC0195","","Connector","","","",""
|
||||
"U1","1","HTU21D","Measurement Specialties","Sensor","","","",""
|
||||
"U2","1","BMP180","Bosch Sensortec","Sensor","","","",""
|
||||
|
@ -0,0 +1,10 @@
|
||||
Designator,Quantity,Element UIDs,Part UID,Specification,Part Type,Domain,Compliance,JLCPCB Part Class,Operating Voltage,Operating Temperature,Reliability Target (MTBF),Role,Role Details,Software,Connector Type,Connector Gender,Connector Pitch,Connector Positions,Connector Rows,Power Requirements,Connectivity,Human Interface,Manufacturing Quantity Target,Manufacturer Part Number,LCSC Part Number,Digi-Key Part Number,Mouser Part Number,Arrow Part Number,Verical Part Number,TME Part Number,HQonline Part Number,Allow Substitutes,Manufacturer Name,Price Change Threshold,Lead Time Change Threshold,Pricing Notification Frequency,Preferred Distributors,Datasheet URL,Machine Datasheet URL,Implementation Details,License,Package or Case Code,Pin Type,Voltage,Voltage Rating,Forward Voltage,Reverse Voltage,Max Reverse Voltage,Diode Type,Mount,Integrated Circuit Type,Breakdown Voltage,Threshold Voltage,Max Output Voltage,Min Output Voltage,Initial Voltage on Reset,Resistance,Resistor Type,Gate Resistance,On Resistance,Off Resistance,Tolerance,Capacitance,Capacitor Type,Power,Power Rating,Current,Max Current,Desired Temperature Rise,Current Rating,Leakage Current,Saturation Current,Initial Current on Reset,Trigger Current,Holding Current,Frequency,Logic Function,Inductance,Inductor Shielding,Inductor Type,Beta,Drain to Source Voltage,Continuous Drain Current,Transistor Type,Gain,Coupling Coefficient,Ratio,Reference Design URL,Price,Purchase Url,Product Info Url,Product Image Url,Substitute Manufacturer Part Number,KiCAD Library Reference,Exclude from PCB,Controlled Impedance,Controlled Impedance Tolerance,PN Skew Max,Pair to Pair Skew Max,Pin Delay,Controlled Impedance Pair,Bus Group,Pair Role,Pin Role,Bus Type,Symbol Style,Symbol Size,Net Type,Designator Prefix,Exclude from BOM
|
||||
"C1,C2","2","24b6ddf3-0bca-4cad-aec4-00f7d928af61,3c30401b-4abb-4407-9583-a0d1ea577630","b635a371-dabd-48ec-a934-df10294c05e9","Multilayer Ceramic Capacitors MLCC - SMD/SMT, 100nF, C1206","Multilayer Ceramic Capacitors MLCC - SMD/SMT","","","Extended Part","","","","","","","","","","","","","","","","GRM31C5C2A104JA01L","C405303","","","","","","","","muRata(村田)","","","","","","","","","C1206","","","100V","","","","","","","","","","","","","","","","","±5%","100nF","Multilayer Ceramic Capacitors MLCC","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","C",""
|
||||
"D1","1","391671a1-b24a-4d48-b9b1-8af6dd246342","edb8b34e-b9d4-42cd-9bbe-d2d5da299641","Schottky Barrier Diodes (SBD), SOD-128_L3.7-W2.5-LS4.7-RD","Schottky Barrier Diodes (SBD)","","","Extended Part","","","","","","","","","","","","","","","","PMEG3020CEP,115","C552871","","","","","","","","Nexperia(安世)","","","","","","","","","SOD-128_L3.7-W2.5-LS4.7-RD","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","D",""
|
||||
"H1,H2,H3,H4","4","73ccedf8-d5ad-4a2f-98bb-b12c18b11033,7c9a51e0-294f-4392-a806-49bf562a6ecc,9c3a431c-7fd7-4e55-a32a-f6850df2c0ad,c84e7944-bff4-42e1-bee9-891a8cd1da61","351f9178-ebc0-404e-8acd-92168fc157cb","Standoff","Standoff","","","","","","","","","","","","","","","","","","","M2106-2545-AL","","","","","","","","","RAF Electronic Hardware","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","H","false"
|
||||
"J1","1","793c0223-5b5c-4933-88b3-c7a5436d6631","2db66d7a-704e-46a2-afa0-8ddb30e1105e","Connector","Connector","","","","","","","","","","","","","","","","","","","CON-SOCJ-2155","","","","","","","","","Gravitech","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","J",""
|
||||
"J2,J3,J4,J5","4","0405d75e-2977-4ad7-b204-fc1c30d42c08,27e0c528-1c8b-4165-9e4d-4b40f63dd90d,4e8edf92-ff52-408e-a1f2-fa4cb9d00e52,8a6c2842-8062-433c-a659-3c6653045d14","36fff81d-1413-b341-746d-86810eb6d064","Connector","Connector","","","","","","","","","","","","","","","","","","","TSW-104-07-T-S","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","J",""
|
||||
"R1,R2,R3,R4","4","2181dddd-de7f-4487-8405-dc510340c330,583d211a-8265-4019-893f-9947306470f7,c89d5920-01c8-48e5-9d3f-a780fde3002b,d2663bc3-aef1-4cf9-9f4a-a8549d47c35f","2c457990-6429-56ee-7c80-8897f711cd80","Resistor, 10kΩ","Resistor","","","","","","","","","","","","","","","","","","","RC1206FR-0710KL","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","10kΩ","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","R",""
|
||||
"RPi1","1","bb0d762a-7bd1-424d-9e51-faa6f68f4c80","99d76b2a-8a6f-42ab-82f1-746911ec4c04","Connector","Connector","","","","","","","","","","","","","","","","","","","SC0195","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","parametric-v1","","","RPi",""
|
||||
"U1","1","981973d6-5f20-484d-b677-8a2f1c2083c8","abad12c7-f0a1-4902-a244-b747ab9387aa","Sensor","Sensor","","","","","","","","","","","","","","","","","","","HTU21D","","","","","","","","","Measurement Specialties","","","","","","","","https://creativecommons.org/licenses/by/4.0/","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","U",""
|
||||
"U2","1","bb5f0d01-3b05-4e41-86c8-155dbecbff2a","1c3a3d45-055a-4237-a2f0-5f58039abf20","Sensor","Sensor","","","","","","","","","","","","","","","","","","","BMP180","","","","","","","","","Bosch Sensortec","","","","","","","","https://creativecommons.org/licenses/by/4.0/","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","U",""
|
||||
|
@ -0,0 +1,10 @@
|
||||
Comment,Designator,Footprint,JLCPCB Part #,LCSC Part #
|
||||
"GRM31C5C2A104JA01L","C1, C2","C1206","","C405303"
|
||||
"PMEG3020CEP,115","D1","SOD-128_L3.7-W2.5-LS4.7-RD","","C552871"
|
||||
"M2106-2545-AL","H1, H2, H3, H4","","",""
|
||||
"CON-SOCJ-2155","J1","","",""
|
||||
"TSW-104-07-T-S","J2, J3, J4, J5","","",""
|
||||
"RC1206FR-0710KL","R1, R2, R3, R4","","",""
|
||||
"SC0195","RPi1","","",""
|
||||
"HTU21D","U1","","",""
|
||||
"BMP180","U2","","",""
|
||||
|
@ -0,0 +1,10 @@
|
||||
Item #,Designator,Qty,Manufacturer,Mfg Part #,Description / Value,Package/Footprint,Type,Your Instructions / Notes
|
||||
"1","C1,C2","2","muRata(村田)","GRM31C5C2A104JA01L","Multilayer Ceramic Capacitors MLCC - SMD/SMT, 100nF, C1206","C1206","",""
|
||||
"2","D1","1","Nexperia(安世)","PMEG3020CEP,115","Schottky Barrier Diodes (SBD), SOD-128_L3.7-W2.5-LS4.7-RD","SOD-128_L3.7-W2.5-LS4.7-RD","",""
|
||||
"3","H1,H2,H3,H4","4","RAF Electronic Hardware","M2106-2545-AL","Standoff","","",""
|
||||
"4","J1","1","Gravitech","CON-SOCJ-2155","Connector","","",""
|
||||
"5","J2,J3,J4,J5","4","","TSW-104-07-T-S","Connector","","",""
|
||||
"6","R1,R2,R3,R4","4","","RC1206FR-0710KL","Resistor, 10kΩ","","",""
|
||||
"7","RPi1","1","","SC0195","Connector","","",""
|
||||
"8","U1","1","Measurement Specialties","HTU21D","Sensor","","",""
|
||||
"9","U2","1","Bosch Sensortec","BMP180","Sensor","","",""
|
||||
|
@ -0,0 +1,10 @@
|
||||
Designator,Manufacturer Part Number or Seeed SKU,QTY,Link
|
||||
"C1,C2","GRM31C5C2A104JA01L","2",""
|
||||
"D1","PMEG3020CEP,115","1",""
|
||||
"H1,H2,H3,H4","M2106-2545-AL","4",""
|
||||
"J1","CON-SOCJ-2155","1",""
|
||||
"J2,J3,J4,J5","TSW-104-07-T-S","4",""
|
||||
"R1,R2,R3,R4","RC1206FR-0710KL","4",""
|
||||
"RPi1","SC0195","1",""
|
||||
"U1","HTU21D","1",""
|
||||
"U2","BMP180","1",""
|
||||
|
@ -0,0 +1,20 @@
|
||||
Designator,Mid X,Mid Y,Layer,Rotation,Package,Value
|
||||
"C1","-14.1412mm","15.7713mm","Top",180,"C1206","100nF"
|
||||
"C2","-24.3485mm","12.4544mm","Top",0,"C1206","100nF"
|
||||
"D1","23.0604mm","-10.6429mm","Top",90,"SOD-128_L3.7-W2.5-LS4.7-RD",""
|
||||
"H1","-28.8784mm","-24.6985mm","Bottom",0,"",""
|
||||
"H2","29.1216mm","24.3015mm","Bottom",0,"",""
|
||||
"H3","29.1216mm","-24.6985mm","Bottom",0,"",""
|
||||
"H4","-28.8784mm","24.3015mm","Bottom",0,"",""
|
||||
"J1","18.9638mm","-17.0821mm","Top",270,"",""
|
||||
"J2","15.3438mm","-7.4333mm","Top",90,"",""
|
||||
"J3","15.3438mm","-2.2688mm","Top",90,"",""
|
||||
"J4","15.3438mm","2.2811mm","Top",90,"",""
|
||||
"J5","15.3438mm","7.0363mm","Top",90,"",""
|
||||
"R1","-24.3337mm","19.0737mm","Top",0,"","10kΩ"
|
||||
"R2","-21.4087mm","15.7713mm","Top",180,"","10kΩ"
|
||||
"R3","8.6087mm","16.5934mm","Top",180,"","10kΩ"
|
||||
"R4","10.0712mm","12.7015mm","Top",180,"","10kΩ"
|
||||
"RPi1","0.1216mm","0.4365mm","Bottom",0,"",""
|
||||
"U1","-14.9562mm","11.9299mm","Top",180,"",""
|
||||
"U2","-25.7962mm","8.4863mm","Top",270,"",""
|
||||
|
@ -0,0 +1,14 @@
|
||||
Project Name: RPi4-Air-Quality
|
||||
Project Version: #5f84d571
|
||||
Project Url: https://www.flux.ai/gmarx/rpi4-air-quality-b7dcy~qe
|
||||
|
||||
Project Description:
|
||||
Template for Raspberry Pi 4 Shield. Include an official pinout so you will always know Raspberry Pi names, the alternative roles of pins, which one is SDA, or SCL, etc. On PCB you can find the 3D model of the Raspberry Pi itself along with the board outline on the silkscreen.
|
||||
#RaspberryPi #Raspberry #Pi #RPi #Shield #template #project #project-template #raspberry
|
||||
|
||||
Project Properties:
|
||||
|
||||
License:
|
||||
https://creativecommons.org/licenses/by/4.0/
|
||||
|
||||
|
||||
@ -0,0 +1,340 @@
|
||||
%TF.GenerationSoftware,Flux,Pcbnew,9.0.9-9.0.9~ubuntu22.04.1*%
|
||||
%TF.CreationDate,2026-08-02T17:48:17+00:00*%
|
||||
%TF.ProjectId,input,696e7075-742e-46b6-9963-61645f706362,rev?*%
|
||||
%TF.SameCoordinates,Original*%
|
||||
%TF.FileFunction,Copper,L4,Bot*%
|
||||
%TF.FilePolarity,Positive*%
|
||||
%FSLAX46Y46*%
|
||||
G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)*
|
||||
G04 Filename: rpi4-air-quality-b7dcy*
|
||||
G04 Build it with Flux! Visit our site at: https://www.flux.ai (PCBNEW 9.0.9-9.0.9~ubuntu22.04.1) date 2026-08-02 17:48:17*
|
||||
%MOMM*%
|
||||
%LPD*%
|
||||
G01*
|
||||
G04 APERTURE LIST*
|
||||
%TA.AperFunction,ComponentPad*%
|
||||
%ADD10C,0.600000*%
|
||||
%TD*%
|
||||
%TA.AperFunction,ComponentPad*%
|
||||
%ADD11C,1.700000*%
|
||||
%TD*%
|
||||
%TA.AperFunction,ComponentPad*%
|
||||
%ADD12R,1.700000X1.700000*%
|
||||
%TD*%
|
||||
%TA.AperFunction,ComponentPad*%
|
||||
%ADD13C,2.700000*%
|
||||
%TD*%
|
||||
%TA.AperFunction,ComponentPad*%
|
||||
%ADD14O,2.250000X4.500000*%
|
||||
%TD*%
|
||||
%TA.AperFunction,ComponentPad*%
|
||||
%ADD15O,5.000000X2.500000*%
|
||||
%TD*%
|
||||
%TA.AperFunction,ComponentPad*%
|
||||
%ADD16O,4.500000X2.250000*%
|
||||
%TD*%
|
||||
%TA.AperFunction,ComponentPad*%
|
||||
%ADD17C,1.524000*%
|
||||
%TD*%
|
||||
%TA.AperFunction,ComponentPad*%
|
||||
%ADD18R,1.524000X1.524000*%
|
||||
%TD*%
|
||||
%TA.AperFunction,ComponentPad*%
|
||||
%ADD19C,6.200000*%
|
||||
%TD*%
|
||||
%TA.AperFunction,Conductor*%
|
||||
%ADD20C,1.000000*%
|
||||
%TD*%
|
||||
%TA.AperFunction,Conductor*%
|
||||
%ADD21C,0.600000*%
|
||||
%TD*%
|
||||
G04 APERTURE END LIST*
|
||||
D10*
|
||||
%TO.P,,c3241ddd052a4cd29f34c51896eee025throughHole00*%
|
||||
%TO.N,Net 3*%
|
||||
X64456000Y-50146175D03*
|
||||
%TO.P,,3aa9771e4e924536a5d3eb6e4053496dthroughHole00*%
|
||||
%TO.N,Net 4*%
|
||||
X52617600Y-32372375D03*
|
||||
%TO.P,,714774cca06442519315d8ec73f7f803throughHole00*%
|
||||
X54912200Y-43972075D03*
|
||||
%TO.P,,f6df285557064514b98b1b6b7aa4936fthroughHole00*%
|
||||
X54912200Y-34666975D03*
|
||||
%TO.P,,35150496d72b4d88996f5c23762e5bf2throughHole00*%
|
||||
%TO.N,Net 8*%
|
||||
X63894500Y-54546175D03*
|
||||
%TO.P,,aeea024bc7bf4ebcb47f536edcaab0fethroughHole00*%
|
||||
%TO.N,Net 5*%
|
||||
X56339400Y-31710575D03*
|
||||
%TO.P,,2a33a8bd8bc64a68a844a2a93dba4e08throughHole00*%
|
||||
%TO.N,GND*%
|
||||
X59992200Y-61785375D03*
|
||||
%TO.P,,35871135b5cb4ecf9a59823d976e4a7dthroughHole00*%
|
||||
X61888700Y-31150575D03*
|
||||
%TD*%
|
||||
D11*
|
||||
%TO.P,J3,Pin_4*%
|
||||
%TO.N,Net 3*%
|
||||
X62532286Y-43972389D03*
|
||||
%TO.P,J3,Pin_3*%
|
||||
%TO.N,GND*%
|
||||
X59992286Y-43972408D03*
|
||||
%TO.P,J3,Pin_2*%
|
||||
%TO.N,Net 5*%
|
||||
X57452286Y-43972426D03*
|
||||
D12*
|
||||
%TO.P,J3,Pin_1*%
|
||||
%TO.N,Net 4*%
|
||||
X54912286Y-43972445D03*
|
||||
%TD*%
|
||||
D11*
|
||||
%TO.P,J4,Pin_4*%
|
||||
%TO.N,Net 3*%
|
||||
X62532286Y-39422489D03*
|
||||
%TO.P,J4,Pin_3*%
|
||||
%TO.N,GND*%
|
||||
X59992286Y-39422508D03*
|
||||
%TO.P,J4,Pin_2*%
|
||||
%TO.N,Net 5*%
|
||||
X57452286Y-39422526D03*
|
||||
D12*
|
||||
%TO.P,J4,Pin_1*%
|
||||
%TO.N,Net 4*%
|
||||
X54912286Y-39422545D03*
|
||||
%TD*%
|
||||
D11*
|
||||
%TO.P,J5,Pin_4*%
|
||||
%TO.N,Net 3*%
|
||||
X62532286Y-34667289D03*
|
||||
%TO.P,J5,Pin_3*%
|
||||
%TO.N,GND*%
|
||||
X59992286Y-34667308D03*
|
||||
%TO.P,J5,Pin_2*%
|
||||
%TO.N,Net 5*%
|
||||
X57452286Y-34667326D03*
|
||||
D12*
|
||||
%TO.P,J5,Pin_1*%
|
||||
%TO.N,Net 4*%
|
||||
X54912286Y-34667345D03*
|
||||
%TD*%
|
||||
D13*
|
||||
%TO.P,H4,P1*%
|
||||
%TO.N,N/C*%
|
||||
X14500000Y-17401775D03*
|
||||
%TD*%
|
||||
D14*
|
||||
%TO.P,J1,~*%
|
||||
%TO.N,GND*%
|
||||
X64692206Y-58785365D03*
|
||||
D15*
|
||||
%TO.N,Net 8*%
|
||||
X59992200Y-55785375D03*
|
||||
D16*
|
||||
%TO.N,GND*%
|
||||
X59992212Y-61785375D03*
|
||||
%TD*%
|
||||
D13*
|
||||
%TO.P,H3,P1*%
|
||||
%TO.N,N/C*%
|
||||
X72500000Y-66401775D03*
|
||||
%TD*%
|
||||
D11*
|
||||
%TO.P,J2,Pin_4*%
|
||||
%TO.N,Net 3*%
|
||||
X62532286Y-49136889D03*
|
||||
%TO.P,J2,Pin_3*%
|
||||
%TO.N,GND*%
|
||||
X59992286Y-49136908D03*
|
||||
%TO.P,J2,Pin_2*%
|
||||
%TO.N,Net 5*%
|
||||
X57452286Y-49136926D03*
|
||||
D12*
|
||||
%TO.P,J2,Pin_1*%
|
||||
%TO.N,Net 4*%
|
||||
X54912286Y-49136945D03*
|
||||
%TD*%
|
||||
D13*
|
||||
%TO.P,H1,P1*%
|
||||
%TO.N,N/C*%
|
||||
X14500000Y-66401775D03*
|
||||
%TD*%
|
||||
D17*
|
||||
%TO.P,RPi1,3V3*%
|
||||
%TO.N,Net 6*%
|
||||
X39690000Y-18671775D03*
|
||||
%TO.P,RPi1,MOSI0/GPIO10*%
|
||||
%TO.N,N/C*%
|
||||
X42230000Y-18671775D03*
|
||||
%TO.P,RPi1,GPIO20/MOSI1*%
|
||||
X65090000Y-16131775D03*
|
||||
%TO.P,RPi1,GND*%
|
||||
X60010000Y-16131775D03*
|
||||
%TO.P,RPi1,PWM1/GPIO13*%
|
||||
X60010000Y-18671775D03*
|
||||
%TO.P,RPi1,SCL/GPIO3*%
|
||||
%TO.N,Net 2*%
|
||||
X24450000Y-18671775D03*
|
||||
%TO.P,RPi1,GPIO16*%
|
||||
%TO.N,N/C*%
|
||||
X62550000Y-16131775D03*
|
||||
%TO.P,RPi1,GPIO25*%
|
||||
X44770000Y-16131775D03*
|
||||
%TO.P,RPi1,GPIO18/PWM0*%
|
||||
X32070000Y-16131775D03*
|
||||
%TO.P,RPi1,5V*%
|
||||
X21910000Y-16131775D03*
|
||||
%TO.P,RPi1,GPIO26*%
|
||||
X65090000Y-18671775D03*
|
||||
%TO.P,RPi1,GND*%
|
||||
%TO.N,GND*%
|
||||
X24450000Y-16131775D03*
|
||||
%TO.P,RPi1,SCLK0/GPIO11*%
|
||||
%TO.N,N/C*%
|
||||
X47310000Y-18671775D03*
|
||||
%TO.P,RPi1,ID_SC/GPIO1*%
|
||||
X52390000Y-16131775D03*
|
||||
%TO.P,RPi1,GND*%
|
||||
X29530000Y-18671775D03*
|
||||
%TO.P,RPi1,GPIO24*%
|
||||
X39690000Y-16131775D03*
|
||||
%TO.P,RPi1,GND*%
|
||||
%TO.N,GND*%
|
||||
X54930000Y-16131775D03*
|
||||
X49850000Y-18671775D03*
|
||||
%TO.P,RPi1,GPIO19/MISO1*%
|
||||
%TO.N,N/C*%
|
||||
X62550000Y-18671775D03*
|
||||
%TO.P,RPi1,MISO0/GPIO9*%
|
||||
X44770000Y-18671775D03*
|
||||
%TO.P,RPi1,GPIO22*%
|
||||
X37150000Y-18671775D03*
|
||||
%TO.P,RPi1,GND*%
|
||||
X34610000Y-16131775D03*
|
||||
%TO.P,RPi1,GPIO21/SCLK1*%
|
||||
X67630000Y-16131775D03*
|
||||
%TO.P,RPi1,GPIO17*%
|
||||
X32070000Y-18671775D03*
|
||||
%TO.P,RPi1,GPIO15/RXD*%
|
||||
X29530000Y-16131775D03*
|
||||
%TO.P,RPi1,GPIO27*%
|
||||
X34610000Y-18671775D03*
|
||||
%TO.P,RPi1,GND*%
|
||||
X42230000Y-16131775D03*
|
||||
%TO.P,RPi1,GCLK1/GPIO5*%
|
||||
%TO.N,Net 5*%
|
||||
X54930000Y-18671775D03*
|
||||
%TO.P,RPi1,GPIO14/TXD*%
|
||||
%TO.N,N/C*%
|
||||
X26990000Y-16131775D03*
|
||||
%TO.P,RPi1,ID_SD/GPIO0*%
|
||||
X52390000Y-18671775D03*
|
||||
%TO.P,RPi1,GPIO23*%
|
||||
X37150000Y-16131775D03*
|
||||
%TO.P,RPi1,GCLK2/GPIO6*%
|
||||
X57470000Y-18671775D03*
|
||||
%TO.P,RPi1,~CE0~/GPIO8*%
|
||||
X47310000Y-16131775D03*
|
||||
%TO.P,RPi1,5V*%
|
||||
X19370000Y-16131775D03*
|
||||
%TO.P,RPi1,GND*%
|
||||
X67630000Y-18671775D03*
|
||||
%TO.P,RPi1,SDA/GPIO2*%
|
||||
%TO.N,Net 7*%
|
||||
X21910000Y-18671775D03*
|
||||
D18*
|
||||
%TO.P,RPi1,3V3*%
|
||||
%TO.N,Net 1*%
|
||||
X19370000Y-18671775D03*
|
||||
D17*
|
||||
%TO.P,RPi1,~CE1~/GPIO7*%
|
||||
%TO.N,N/C*%
|
||||
X49850000Y-16131775D03*
|
||||
%TO.P,RPi1,GCLK0/GPIO4*%
|
||||
%TO.N,Net 4*%
|
||||
X26990000Y-18671775D03*
|
||||
%TO.P,RPi1,PWM0/GPIO12*%
|
||||
%TO.N,N/C*%
|
||||
X57470000Y-16131775D03*
|
||||
D19*
|
||||
%TO.P,RPi1,S1*%
|
||||
X14500000Y-17401775D03*
|
||||
%TO.P,RPi1,S2*%
|
||||
X72500000Y-17401775D03*
|
||||
%TO.P,RPi1,S3*%
|
||||
X72500000Y-66401775D03*
|
||||
%TO.P,RPi1,S4*%
|
||||
X14500000Y-66401775D03*
|
||||
%TD*%
|
||||
D13*
|
||||
%TO.P,H2,P1*%
|
||||
%TO.N,N/C*%
|
||||
X72500000Y-17401775D03*
|
||||
%TD*%
|
||||
D20*
|
||||
%TO.N,Net 3*%
|
||||
X63541900Y-50146175D02*
|
||||
X62532300Y-49136575D01*
|
||||
X62532200Y-34666975D02*
|
||||
X62532200Y-49136575D01*
|
||||
X64456000Y-50146175D02*
|
||||
X63541800Y-50146175D01*
|
||||
D21*
|
||||
%TO.N,Net 4*%
|
||||
X52617600Y-32372375D02*
|
||||
X54912200Y-34666975D01*
|
||||
D20*
|
||||
X54912200Y-34666975D02*
|
||||
X54912200Y-49136575D01*
|
||||
%TO.N,Net 8*%
|
||||
X63894500Y-54546175D02*
|
||||
X63894500Y-54546175D01*
|
||||
X59992200Y-55785375D02*
|
||||
X62655200Y-55785375D01*
|
||||
X62655300Y-55785375D02*
|
||||
X63894500Y-54546175D01*
|
||||
D21*
|
||||
%TO.N,Net 5*%
|
||||
X56339400Y-31710575D02*
|
||||
X56790400Y-31710575D01*
|
||||
X57452200Y-32372375D02*
|
||||
X57452200Y-34666975D01*
|
||||
X56790400Y-31710575D02*
|
||||
X57452200Y-32372375D01*
|
||||
D20*
|
||||
X57452200Y-34666975D02*
|
||||
X57452200Y-49136575D01*
|
||||
%TO.N,GND*%
|
||||
X59992200Y-61436575D02*
|
||||
X54341000Y-55785375D01*
|
||||
X59302800Y-50823575D02*
|
||||
X54341000Y-55785375D01*
|
||||
X62655200Y-61785375D02*
|
||||
X59992200Y-61785375D01*
|
||||
X59992200Y-50823575D02*
|
||||
X59992200Y-50823575D01*
|
||||
X59992200Y-61785375D02*
|
||||
X59992200Y-61436575D01*
|
||||
X59992200Y-49136575D02*
|
||||
X59992200Y-49136575D01*
|
||||
D21*
|
||||
X61888700Y-31150575D02*
|
||||
X61888700Y-32770575D01*
|
||||
D20*
|
||||
X64692200Y-58785375D02*
|
||||
X64692200Y-59748375D01*
|
||||
X59992200Y-50823575D02*
|
||||
X59302800Y-50823575D01*
|
||||
X59992200Y-34666975D02*
|
||||
X59992200Y-49136575D01*
|
||||
D21*
|
||||
X61888700Y-32770575D02*
|
||||
X59992300Y-34666975D01*
|
||||
D20*
|
||||
X54341000Y-55785375D02*
|
||||
X54341000Y-55785375D01*
|
||||
X64692200Y-59748375D02*
|
||||
X62655200Y-61785375D01*
|
||||
X59992200Y-50823575D02*
|
||||
X59992200Y-49136575D01*
|
||||
%TD*%
|
||||
M02*
|
||||
@ -0,0 +1,131 @@
|
||||
%TF.GenerationSoftware,Flux,Pcbnew,9.0.9-9.0.9~ubuntu22.04.1*%
|
||||
%TF.CreationDate,2026-08-02T17:48:17+00:00*%
|
||||
%TF.ProjectId,input,696e7075-742e-46b6-9963-61645f706362,rev?*%
|
||||
%TF.SameCoordinates,Original*%
|
||||
%TF.FileFunction,Soldermask,Bot*%
|
||||
%TF.FilePolarity,Negative*%
|
||||
%FSLAX46Y46*%
|
||||
G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)*
|
||||
G04 Filename: rpi4-air-quality-b7dcy*
|
||||
G04 Build it with Flux! Visit our site at: https://www.flux.ai (PCBNEW 9.0.9-9.0.9~ubuntu22.04.1) date 2026-08-02 17:48:17*
|
||||
%MOMM*%
|
||||
%LPD*%
|
||||
G01*
|
||||
G04 APERTURE LIST*
|
||||
%ADD10C,1.700000*%
|
||||
%ADD11R,1.700000X1.700000*%
|
||||
%ADD12C,2.700000*%
|
||||
%ADD13O,2.250000X4.500000*%
|
||||
%ADD14O,5.000000X2.500000*%
|
||||
%ADD15O,4.500000X2.250000*%
|
||||
%ADD16C,1.524000*%
|
||||
%ADD17R,1.524000X1.524000*%
|
||||
%ADD18C,6.200000*%
|
||||
G04 APERTURE END LIST*
|
||||
D10*
|
||||
%TO.C,J3*%
|
||||
X62532286Y-43972389D03*
|
||||
X59992286Y-43972408D03*
|
||||
X57452286Y-43972426D03*
|
||||
D11*
|
||||
X54912286Y-43972445D03*
|
||||
%TD*%
|
||||
D10*
|
||||
%TO.C,J4*%
|
||||
X62532286Y-39422489D03*
|
||||
X59992286Y-39422508D03*
|
||||
X57452286Y-39422526D03*
|
||||
D11*
|
||||
X54912286Y-39422545D03*
|
||||
%TD*%
|
||||
D10*
|
||||
%TO.C,J5*%
|
||||
X62532286Y-34667289D03*
|
||||
X59992286Y-34667308D03*
|
||||
X57452286Y-34667326D03*
|
||||
D11*
|
||||
X54912286Y-34667345D03*
|
||||
%TD*%
|
||||
D12*
|
||||
%TO.C,H4*%
|
||||
X14500000Y-17401775D03*
|
||||
%TD*%
|
||||
D13*
|
||||
%TO.C,J1*%
|
||||
X64692206Y-58785365D03*
|
||||
D14*
|
||||
X59992200Y-55785375D03*
|
||||
D15*
|
||||
X59992212Y-61785375D03*
|
||||
%TD*%
|
||||
D12*
|
||||
%TO.C,H3*%
|
||||
X72500000Y-66401775D03*
|
||||
%TD*%
|
||||
D10*
|
||||
%TO.C,J2*%
|
||||
X62532286Y-49136889D03*
|
||||
X59992286Y-49136908D03*
|
||||
X57452286Y-49136926D03*
|
||||
D11*
|
||||
X54912286Y-49136945D03*
|
||||
%TD*%
|
||||
D12*
|
||||
%TO.C,H1*%
|
||||
X14500000Y-66401775D03*
|
||||
%TD*%
|
||||
D16*
|
||||
%TO.C,RPi1*%
|
||||
X39690000Y-18671775D03*
|
||||
X42230000Y-18671775D03*
|
||||
X65090000Y-16131775D03*
|
||||
X60010000Y-16131775D03*
|
||||
X60010000Y-18671775D03*
|
||||
X24450000Y-18671775D03*
|
||||
X62550000Y-16131775D03*
|
||||
X44770000Y-16131775D03*
|
||||
X32070000Y-16131775D03*
|
||||
X21910000Y-16131775D03*
|
||||
X65090000Y-18671775D03*
|
||||
X24450000Y-16131775D03*
|
||||
X47310000Y-18671775D03*
|
||||
X52390000Y-16131775D03*
|
||||
X29530000Y-18671775D03*
|
||||
X39690000Y-16131775D03*
|
||||
X54930000Y-16131775D03*
|
||||
X49850000Y-18671775D03*
|
||||
X62550000Y-18671775D03*
|
||||
X44770000Y-18671775D03*
|
||||
X37150000Y-18671775D03*
|
||||
X34610000Y-16131775D03*
|
||||
X67630000Y-16131775D03*
|
||||
X32070000Y-18671775D03*
|
||||
X29530000Y-16131775D03*
|
||||
X34610000Y-18671775D03*
|
||||
X42230000Y-16131775D03*
|
||||
X54930000Y-18671775D03*
|
||||
X26990000Y-16131775D03*
|
||||
X52390000Y-18671775D03*
|
||||
X37150000Y-16131775D03*
|
||||
X57470000Y-18671775D03*
|
||||
X47310000Y-16131775D03*
|
||||
X19370000Y-16131775D03*
|
||||
X67630000Y-18671775D03*
|
||||
X21910000Y-18671775D03*
|
||||
D17*
|
||||
X19370000Y-18671775D03*
|
||||
D16*
|
||||
X49850000Y-16131775D03*
|
||||
X26990000Y-18671775D03*
|
||||
X57470000Y-16131775D03*
|
||||
D18*
|
||||
X14500000Y-17401775D03*
|
||||
X72500000Y-17401775D03*
|
||||
X72500000Y-66401775D03*
|
||||
X14500000Y-66401775D03*
|
||||
%TD*%
|
||||
D12*
|
||||
%TO.C,H2*%
|
||||
X72500000Y-17401775D03*
|
||||
%TD*%
|
||||
M02*
|
||||
@ -0,0 +1,131 @@
|
||||
%TF.GenerationSoftware,Flux,Pcbnew,9.0.9-9.0.9~ubuntu22.04.1*%
|
||||
%TF.CreationDate,2026-08-02T17:48:18+00:00*%
|
||||
%TF.ProjectId,input,696e7075-742e-46b6-9963-61645f706362,rev?*%
|
||||
%TF.SameCoordinates,Original*%
|
||||
%TF.FileFunction,Paste,Bot*%
|
||||
%TF.FilePolarity,Positive*%
|
||||
%FSLAX46Y46*%
|
||||
G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)*
|
||||
G04 Filename: rpi4-air-quality-b7dcy*
|
||||
G04 Build it with Flux! Visit our site at: https://www.flux.ai (PCBNEW 9.0.9-9.0.9~ubuntu22.04.1) date 2026-08-02 17:48:18*
|
||||
%MOMM*%
|
||||
%LPD*%
|
||||
G01*
|
||||
G04 APERTURE LIST*
|
||||
%ADD10C,1.700000*%
|
||||
%ADD11R,1.700000X1.700000*%
|
||||
%ADD12C,2.700000*%
|
||||
%ADD13O,2.250000X4.500000*%
|
||||
%ADD14O,5.000000X2.500000*%
|
||||
%ADD15O,4.500000X2.250000*%
|
||||
%ADD16C,1.524000*%
|
||||
%ADD17R,1.524000X1.524000*%
|
||||
%ADD18C,6.200000*%
|
||||
G04 APERTURE END LIST*
|
||||
D10*
|
||||
%TO.C,J3*%
|
||||
X62532286Y-43972389D03*
|
||||
X59992286Y-43972408D03*
|
||||
X57452286Y-43972426D03*
|
||||
D11*
|
||||
X54912286Y-43972445D03*
|
||||
%TD*%
|
||||
D10*
|
||||
%TO.C,J4*%
|
||||
X62532286Y-39422489D03*
|
||||
X59992286Y-39422508D03*
|
||||
X57452286Y-39422526D03*
|
||||
D11*
|
||||
X54912286Y-39422545D03*
|
||||
%TD*%
|
||||
D10*
|
||||
%TO.C,J5*%
|
||||
X62532286Y-34667289D03*
|
||||
X59992286Y-34667308D03*
|
||||
X57452286Y-34667326D03*
|
||||
D11*
|
||||
X54912286Y-34667345D03*
|
||||
%TD*%
|
||||
D12*
|
||||
%TO.C,H4*%
|
||||
X14500000Y-17401775D03*
|
||||
%TD*%
|
||||
D13*
|
||||
%TO.C,J1*%
|
||||
X64692206Y-58785365D03*
|
||||
D14*
|
||||
X59992200Y-55785375D03*
|
||||
D15*
|
||||
X59992212Y-61785375D03*
|
||||
%TD*%
|
||||
D12*
|
||||
%TO.C,H3*%
|
||||
X72500000Y-66401775D03*
|
||||
%TD*%
|
||||
D10*
|
||||
%TO.C,J2*%
|
||||
X62532286Y-49136889D03*
|
||||
X59992286Y-49136908D03*
|
||||
X57452286Y-49136926D03*
|
||||
D11*
|
||||
X54912286Y-49136945D03*
|
||||
%TD*%
|
||||
D12*
|
||||
%TO.C,H1*%
|
||||
X14500000Y-66401775D03*
|
||||
%TD*%
|
||||
D16*
|
||||
%TO.C,RPi1*%
|
||||
X39690000Y-18671775D03*
|
||||
X42230000Y-18671775D03*
|
||||
X65090000Y-16131775D03*
|
||||
X60010000Y-16131775D03*
|
||||
X60010000Y-18671775D03*
|
||||
X24450000Y-18671775D03*
|
||||
X62550000Y-16131775D03*
|
||||
X44770000Y-16131775D03*
|
||||
X32070000Y-16131775D03*
|
||||
X21910000Y-16131775D03*
|
||||
X65090000Y-18671775D03*
|
||||
X24450000Y-16131775D03*
|
||||
X47310000Y-18671775D03*
|
||||
X52390000Y-16131775D03*
|
||||
X29530000Y-18671775D03*
|
||||
X39690000Y-16131775D03*
|
||||
X54930000Y-16131775D03*
|
||||
X49850000Y-18671775D03*
|
||||
X62550000Y-18671775D03*
|
||||
X44770000Y-18671775D03*
|
||||
X37150000Y-18671775D03*
|
||||
X34610000Y-16131775D03*
|
||||
X67630000Y-16131775D03*
|
||||
X32070000Y-18671775D03*
|
||||
X29530000Y-16131775D03*
|
||||
X34610000Y-18671775D03*
|
||||
X42230000Y-16131775D03*
|
||||
X54930000Y-18671775D03*
|
||||
X26990000Y-16131775D03*
|
||||
X52390000Y-18671775D03*
|
||||
X37150000Y-16131775D03*
|
||||
X57470000Y-18671775D03*
|
||||
X47310000Y-16131775D03*
|
||||
X19370000Y-16131775D03*
|
||||
X67630000Y-18671775D03*
|
||||
X21910000Y-18671775D03*
|
||||
D17*
|
||||
X19370000Y-18671775D03*
|
||||
D16*
|
||||
X49850000Y-16131775D03*
|
||||
X26990000Y-18671775D03*
|
||||
X57470000Y-16131775D03*
|
||||
D18*
|
||||
X14500000Y-17401775D03*
|
||||
X72500000Y-17401775D03*
|
||||
X72500000Y-66401775D03*
|
||||
X14500000Y-66401775D03*
|
||||
%TD*%
|
||||
D12*
|
||||
%TO.C,H2*%
|
||||
X72500000Y-17401775D03*
|
||||
%TD*%
|
||||
M02*
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,713 @@
|
||||
%TF.GenerationSoftware,Flux,Pcbnew,9.0.9-9.0.9~ubuntu22.04.1*%
|
||||
%TF.CreationDate,2026-08-02T17:48:19+00:00*%
|
||||
%TF.ProjectId,input,696e7075-742e-46b6-9963-61645f706362,rev?*%
|
||||
%TF.SameCoordinates,Original*%
|
||||
%TF.FileFunction,Copper,L1,Top*%
|
||||
%TF.FilePolarity,Positive*%
|
||||
%FSLAX46Y46*%
|
||||
G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)*
|
||||
G04 Filename: rpi4-air-quality-b7dcy*
|
||||
G04 Build it with Flux! Visit our site at: https://www.flux.ai (PCBNEW 9.0.9-9.0.9~ubuntu22.04.1) date 2026-08-02 17:48:19*
|
||||
%MOMM*%
|
||||
%LPD*%
|
||||
G01*
|
||||
G04 APERTURE LIST*
|
||||
G04 Aperture macros list*
|
||||
%AMRoundRect*
|
||||
0 Rectangle with rounded corners*
|
||||
0 $1 Rounding radius*
|
||||
0 $2 $3 $4 $5 $6 $7 $8 $9 X,Y pos of 4 corners*
|
||||
0 Add a 4 corners polygon primitive as box body*
|
||||
4,1,4,$2,$3,$4,$5,$6,$7,$8,$9,$2,$3,0*
|
||||
0 Add four circle primitives for the rounded corners*
|
||||
1,1,$1+$1,$2,$3*
|
||||
1,1,$1+$1,$4,$5*
|
||||
1,1,$1+$1,$6,$7*
|
||||
1,1,$1+$1,$8,$9*
|
||||
0 Add four rect primitives between the rounded corners*
|
||||
20,1,$1+$1,$2,$3,$4,$5,0*
|
||||
20,1,$1+$1,$4,$5,$6,$7,0*
|
||||
20,1,$1+$1,$6,$7,$8,$9,0*
|
||||
20,1,$1+$1,$8,$9,$2,$3,0*%
|
||||
G04 Aperture macros list end*
|
||||
%TA.AperFunction,ComponentPad*%
|
||||
%ADD10C,0.600000*%
|
||||
%TD*%
|
||||
%TA.AperFunction,ComponentPad*%
|
||||
%ADD11C,1.700000*%
|
||||
%TD*%
|
||||
%TA.AperFunction,ComponentPad*%
|
||||
%ADD12R,1.700000X1.700000*%
|
||||
%TD*%
|
||||
%TA.AperFunction,SMDPad,CuDef*%
|
||||
%ADD13RoundRect,0.131300X0.431200X0.743700X-0.431200X0.743700X-0.431200X-0.743700X0.431200X-0.743700X0*%
|
||||
%TD*%
|
||||
%TA.AperFunction,SMDPad,CuDef*%
|
||||
%ADD14R,1.490000X1.730000*%
|
||||
%TD*%
|
||||
%TA.AperFunction,SMDPad,CuDef*%
|
||||
%ADD15R,1.700000X1.250000*%
|
||||
%TD*%
|
||||
%TA.AperFunction,ComponentPad*%
|
||||
%ADD16C,2.700000*%
|
||||
%TD*%
|
||||
%TA.AperFunction,ComponentPad*%
|
||||
%ADD17O,2.250000X4.500000*%
|
||||
%TD*%
|
||||
%TA.AperFunction,ComponentPad*%
|
||||
%ADD18O,5.000000X2.500000*%
|
||||
%TD*%
|
||||
%TA.AperFunction,ComponentPad*%
|
||||
%ADD19O,4.500000X2.250000*%
|
||||
%TD*%
|
||||
%TA.AperFunction,SMDPad,CuDef*%
|
||||
%ADD20R,0.800000X0.450000*%
|
||||
%TD*%
|
||||
%TA.AperFunction,SMDPad,CuDef*%
|
||||
%ADD21R,1.600000X2.500000*%
|
||||
%TD*%
|
||||
%TA.AperFunction,ComponentPad*%
|
||||
%ADD22C,1.524000*%
|
||||
%TD*%
|
||||
%TA.AperFunction,ComponentPad*%
|
||||
%ADD23R,1.524000X1.524000*%
|
||||
%TD*%
|
||||
%TA.AperFunction,ComponentPad*%
|
||||
%ADD24C,6.200000*%
|
||||
%TD*%
|
||||
%TA.AperFunction,SMDPad,CuDef*%
|
||||
%ADD25R,0.700000X0.600000*%
|
||||
%TD*%
|
||||
%TA.AperFunction,SMDPad,CuDef*%
|
||||
%ADD26R,0.500000X0.600000*%
|
||||
%TD*%
|
||||
%TA.AperFunction,SMDPad,CuDef*%
|
||||
%ADD27RoundRect,0.131300X-0.431200X-0.743700X0.431200X-0.743700X0.431200X0.743700X-0.431200X0.743700X0*%
|
||||
%TD*%
|
||||
%TA.AperFunction,Conductor*%
|
||||
%ADD28C,1.000000*%
|
||||
%TD*%
|
||||
%TA.AperFunction,Conductor*%
|
||||
%ADD29C,0.600000*%
|
||||
%TD*%
|
||||
%TA.AperFunction,Conductor*%
|
||||
%ADD30C,0.400000*%
|
||||
%TD*%
|
||||
G04 APERTURE END LIST*
|
||||
D10*
|
||||
%TO.P,,c3241ddd052a4cd29f34c51896eee025throughHole00*%
|
||||
%TO.N,Net 3*%
|
||||
X64456000Y-50146175D03*
|
||||
%TO.P,,3aa9771e4e924536a5d3eb6e4053496dthroughHole00*%
|
||||
%TO.N,Net 4*%
|
||||
X52617600Y-32372375D03*
|
||||
%TO.P,,714774cca06442519315d8ec73f7f803throughHole00*%
|
||||
X54912200Y-43972075D03*
|
||||
%TO.P,,f6df285557064514b98b1b6b7aa4936fthroughHole00*%
|
||||
X54912200Y-34666975D03*
|
||||
%TO.P,,35150496d72b4d88996f5c23762e5bf2throughHole00*%
|
||||
%TO.N,Net 8*%
|
||||
X63894500Y-54546175D03*
|
||||
%TO.P,,aeea024bc7bf4ebcb47f536edcaab0fethroughHole00*%
|
||||
%TO.N,Net 5*%
|
||||
X56339400Y-31710575D03*
|
||||
%TO.P,,2a33a8bd8bc64a68a844a2a93dba4e08throughHole00*%
|
||||
%TO.N,GND*%
|
||||
X59992200Y-61785375D03*
|
||||
%TO.P,,35871135b5cb4ecf9a59823d976e4a7dthroughHole00*%
|
||||
X61888700Y-31150575D03*
|
||||
%TD*%
|
||||
D11*
|
||||
%TO.P,J3,Pin_4*%
|
||||
%TO.N,Net 3*%
|
||||
X62532286Y-43972389D03*
|
||||
%TO.P,J3,Pin_3*%
|
||||
%TO.N,GND*%
|
||||
X59992286Y-43972408D03*
|
||||
%TO.P,J3,Pin_2*%
|
||||
%TO.N,Net 5*%
|
||||
X57452286Y-43972426D03*
|
||||
D12*
|
||||
%TO.P,J3,Pin_1*%
|
||||
%TO.N,Net 4*%
|
||||
X54912286Y-43972445D03*
|
||||
%TD*%
|
||||
D13*
|
||||
%TO.P,R4,P1*%
|
||||
%TO.N,Net 5*%
|
||||
X54912100Y-29001783D03*
|
||||
%TO.P,R4,P2*%
|
||||
%TO.N,Net 6*%
|
||||
X51987100Y-29001767D03*
|
||||
%TD*%
|
||||
D14*
|
||||
%TO.P,C2,1*%
|
||||
%TO.N,Net 1*%
|
||||
X17439900Y-29248875D03*
|
||||
%TO.P,C2,2*%
|
||||
%TO.N,GND*%
|
||||
X20619900Y-29248875D03*
|
||||
%TD*%
|
||||
D11*
|
||||
%TO.P,J4,Pin_4*%
|
||||
%TO.N,Net 3*%
|
||||
X62532286Y-39422489D03*
|
||||
%TO.P,J4,Pin_3*%
|
||||
%TO.N,GND*%
|
||||
X59992286Y-39422508D03*
|
||||
%TO.P,J4,Pin_2*%
|
||||
%TO.N,Net 5*%
|
||||
X57452286Y-39422526D03*
|
||||
D12*
|
||||
%TO.P,J4,Pin_1*%
|
||||
%TO.N,Net 4*%
|
||||
X54912286Y-39422545D03*
|
||||
%TD*%
|
||||
D15*
|
||||
%TO.P,D1,1*%
|
||||
%TO.N,Net 8*%
|
||||
X66438816Y-54546175D03*
|
||||
%TO.P,D1,2*%
|
||||
%TO.N,Net 3*%
|
||||
X66438784Y-50146175D03*
|
||||
%TD*%
|
||||
D14*
|
||||
%TO.P,C1,1*%
|
||||
%TO.N,GND*%
|
||||
X30827200Y-25931983D03*
|
||||
%TO.P,C1,2*%
|
||||
%TO.N,Net 6*%
|
||||
X27647200Y-25931967D03*
|
||||
%TD*%
|
||||
D11*
|
||||
%TO.P,J5,Pin_4*%
|
||||
%TO.N,Net 3*%
|
||||
X62532286Y-34667289D03*
|
||||
%TO.P,J5,Pin_3*%
|
||||
%TO.N,GND*%
|
||||
X59992286Y-34667308D03*
|
||||
%TO.P,J5,Pin_2*%
|
||||
%TO.N,Net 5*%
|
||||
X57452286Y-34667326D03*
|
||||
D12*
|
||||
%TO.P,J5,Pin_1*%
|
||||
%TO.N,Net 4*%
|
||||
X54912286Y-34667345D03*
|
||||
%TD*%
|
||||
D13*
|
||||
%TO.P,R3,P1*%
|
||||
%TO.N,Net 4*%
|
||||
X53449600Y-25109883D03*
|
||||
%TO.P,R3,P2*%
|
||||
%TO.N,Net 6*%
|
||||
X50524600Y-25109867D03*
|
||||
%TD*%
|
||||
D16*
|
||||
%TO.P,H4,P1*%
|
||||
%TO.N,N/C*%
|
||||
X14500000Y-17401775D03*
|
||||
%TD*%
|
||||
D17*
|
||||
%TO.P,J1,~*%
|
||||
%TO.N,GND*%
|
||||
X64692206Y-58785365D03*
|
||||
D18*
|
||||
%TO.N,Net 8*%
|
||||
X59992200Y-55785375D03*
|
||||
D19*
|
||||
%TO.N,GND*%
|
||||
X59992212Y-61785375D03*
|
||||
%TD*%
|
||||
D16*
|
||||
%TO.P,H3,P1*%
|
||||
%TO.N,N/C*%
|
||||
X72500000Y-66401775D03*
|
||||
%TD*%
|
||||
D11*
|
||||
%TO.P,J2,Pin_4*%
|
||||
%TO.N,Net 3*%
|
||||
X62532286Y-49136889D03*
|
||||
%TO.P,J2,Pin_3*%
|
||||
%TO.N,GND*%
|
||||
X59992286Y-49136908D03*
|
||||
%TO.P,J2,Pin_2*%
|
||||
%TO.N,Net 5*%
|
||||
X57452286Y-49136926D03*
|
||||
D12*
|
||||
%TO.P,J2,Pin_1*%
|
||||
%TO.N,Net 4*%
|
||||
X54912286Y-49136945D03*
|
||||
%TD*%
|
||||
D20*
|
||||
%TO.P,U1,NC_1*%
|
||||
%TO.N,N/C*%
|
||||
X29872205Y-28773383D03*
|
||||
%TO.P,U1,VDD*%
|
||||
%TO.N,Net 6*%
|
||||
X26972200Y-29773367D03*
|
||||
%TO.P,U1,SCK*%
|
||||
%TO.N,Net 2*%
|
||||
X26972195Y-30773367D03*
|
||||
%TO.P,U1,DATA*%
|
||||
%TO.N,Net 7*%
|
||||
X29872195Y-30773383D03*
|
||||
%TO.P,U1,GND*%
|
||||
%TO.N,GND*%
|
||||
X29872200Y-29773383D03*
|
||||
D21*
|
||||
%TO.P,U1,EP*%
|
||||
%TO.N,N/C*%
|
||||
X28422200Y-29773375D03*
|
||||
D20*
|
||||
%TO.P,U1,NC_2*%
|
||||
X26972205Y-28773367D03*
|
||||
%TD*%
|
||||
D16*
|
||||
%TO.P,H1,P1*%
|
||||
%TO.N,N/C*%
|
||||
X14500000Y-66401775D03*
|
||||
%TD*%
|
||||
D22*
|
||||
%TO.P,RPi1,3V3*%
|
||||
%TO.N,Net 6*%
|
||||
X39690000Y-18671775D03*
|
||||
%TO.P,RPi1,MOSI0/GPIO10*%
|
||||
%TO.N,N/C*%
|
||||
X42230000Y-18671775D03*
|
||||
%TO.P,RPi1,GPIO20/MOSI1*%
|
||||
X65090000Y-16131775D03*
|
||||
%TO.P,RPi1,GND*%
|
||||
X60010000Y-16131775D03*
|
||||
%TO.P,RPi1,PWM1/GPIO13*%
|
||||
X60010000Y-18671775D03*
|
||||
%TO.P,RPi1,SCL/GPIO3*%
|
||||
%TO.N,Net 2*%
|
||||
X24450000Y-18671775D03*
|
||||
%TO.P,RPi1,GPIO16*%
|
||||
%TO.N,N/C*%
|
||||
X62550000Y-16131775D03*
|
||||
%TO.P,RPi1,GPIO25*%
|
||||
X44770000Y-16131775D03*
|
||||
%TO.P,RPi1,GPIO18/PWM0*%
|
||||
X32070000Y-16131775D03*
|
||||
%TO.P,RPi1,5V*%
|
||||
X21910000Y-16131775D03*
|
||||
%TO.P,RPi1,GPIO26*%
|
||||
X65090000Y-18671775D03*
|
||||
%TO.P,RPi1,GND*%
|
||||
%TO.N,GND*%
|
||||
X24450000Y-16131775D03*
|
||||
%TO.P,RPi1,SCLK0/GPIO11*%
|
||||
%TO.N,N/C*%
|
||||
X47310000Y-18671775D03*
|
||||
%TO.P,RPi1,ID_SC/GPIO1*%
|
||||
X52390000Y-16131775D03*
|
||||
%TO.P,RPi1,GND*%
|
||||
X29530000Y-18671775D03*
|
||||
%TO.P,RPi1,GPIO24*%
|
||||
X39690000Y-16131775D03*
|
||||
%TO.P,RPi1,GND*%
|
||||
%TO.N,GND*%
|
||||
X54930000Y-16131775D03*
|
||||
X49850000Y-18671775D03*
|
||||
%TO.P,RPi1,GPIO19/MISO1*%
|
||||
%TO.N,N/C*%
|
||||
X62550000Y-18671775D03*
|
||||
%TO.P,RPi1,MISO0/GPIO9*%
|
||||
X44770000Y-18671775D03*
|
||||
%TO.P,RPi1,GPIO22*%
|
||||
X37150000Y-18671775D03*
|
||||
%TO.P,RPi1,GND*%
|
||||
X34610000Y-16131775D03*
|
||||
%TO.P,RPi1,GPIO21/SCLK1*%
|
||||
X67630000Y-16131775D03*
|
||||
%TO.P,RPi1,GPIO17*%
|
||||
X32070000Y-18671775D03*
|
||||
%TO.P,RPi1,GPIO15/RXD*%
|
||||
X29530000Y-16131775D03*
|
||||
%TO.P,RPi1,GPIO27*%
|
||||
X34610000Y-18671775D03*
|
||||
%TO.P,RPi1,GND*%
|
||||
X42230000Y-16131775D03*
|
||||
%TO.P,RPi1,GCLK1/GPIO5*%
|
||||
%TO.N,Net 5*%
|
||||
X54930000Y-18671775D03*
|
||||
%TO.P,RPi1,GPIO14/TXD*%
|
||||
%TO.N,N/C*%
|
||||
X26990000Y-16131775D03*
|
||||
%TO.P,RPi1,ID_SD/GPIO0*%
|
||||
X52390000Y-18671775D03*
|
||||
%TO.P,RPi1,GPIO23*%
|
||||
X37150000Y-16131775D03*
|
||||
%TO.P,RPi1,GCLK2/GPIO6*%
|
||||
X57470000Y-18671775D03*
|
||||
%TO.P,RPi1,~CE0~/GPIO8*%
|
||||
X47310000Y-16131775D03*
|
||||
%TO.P,RPi1,5V*%
|
||||
X19370000Y-16131775D03*
|
||||
%TO.P,RPi1,GND*%
|
||||
X67630000Y-18671775D03*
|
||||
%TO.P,RPi1,SDA/GPIO2*%
|
||||
%TO.N,Net 7*%
|
||||
X21910000Y-18671775D03*
|
||||
D23*
|
||||
%TO.P,RPi1,3V3*%
|
||||
%TO.N,Net 1*%
|
||||
X19370000Y-18671775D03*
|
||||
D22*
|
||||
%TO.P,RPi1,~CE1~/GPIO7*%
|
||||
%TO.N,N/C*%
|
||||
X49850000Y-16131775D03*
|
||||
%TO.P,RPi1,GCLK0/GPIO4*%
|
||||
%TO.N,Net 4*%
|
||||
X26990000Y-18671775D03*
|
||||
%TO.P,RPi1,PWM0/GPIO12*%
|
||||
%TO.N,N/C*%
|
||||
X57470000Y-16131775D03*
|
||||
D24*
|
||||
%TO.P,RPi1,S1*%
|
||||
X14500000Y-17401775D03*
|
||||
%TO.P,RPi1,S2*%
|
||||
X72500000Y-17401775D03*
|
||||
%TO.P,RPi1,S3*%
|
||||
X72500000Y-66401775D03*
|
||||
%TO.P,RPi1,S4*%
|
||||
X14500000Y-66401775D03*
|
||||
%TD*%
|
||||
D25*
|
||||
%TO.P,U2,SDA*%
|
||||
%TO.N,Net 7*%
|
||||
X19082203Y-34666972D03*
|
||||
%TO.P,U2,VDD*%
|
||||
%TO.N,Net 1*%
|
||||
X17582197Y-31766975D03*
|
||||
%TO.P,U2,SCL*%
|
||||
%TO.N,Net 2*%
|
||||
X17582203Y-34666975D03*
|
||||
%TO.P,U2,SDO*%
|
||||
%TO.N,Net 1*%
|
||||
X16082203Y-34666978D03*
|
||||
%TO.P,U2,VDDIO*%
|
||||
X16082197Y-31766978D03*
|
||||
%TO.P,U2,CSB*%
|
||||
X19082197Y-31766972D03*
|
||||
D26*
|
||||
%TO.P,U2,GND*%
|
||||
%TO.N,GND*%
|
||||
X19082200Y-33216972D03*
|
||||
%TD*%
|
||||
D16*
|
||||
%TO.P,H2,P1*%
|
||||
%TO.N,N/C*%
|
||||
X72500000Y-17401775D03*
|
||||
%TD*%
|
||||
D27*
|
||||
%TO.P,R1,P1*%
|
||||
%TO.N,Net 7*%
|
||||
X17582200Y-22629575D03*
|
||||
%TO.P,R1,P2*%
|
||||
%TO.N,Net 1*%
|
||||
X20507200Y-22629575D03*
|
||||
%TD*%
|
||||
D13*
|
||||
%TO.P,R2,P1*%
|
||||
%TO.N,Net 2*%
|
||||
X23432200Y-25931983D03*
|
||||
%TO.P,R2,P2*%
|
||||
%TO.N,Net 1*%
|
||||
X20507200Y-25931967D03*
|
||||
%TD*%
|
||||
D28*
|
||||
%TO.N,Net 3*%
|
||||
X64456000Y-50146175D02*
|
||||
X64456000Y-50146175D01*
|
||||
X66438800Y-50146175D02*
|
||||
X64456000Y-50146175D01*
|
||||
D29*
|
||||
%TO.N,Net 1*%
|
||||
X17582200Y-31766975D02*
|
||||
X19082200Y-31766975D01*
|
||||
X15459000Y-31766975D02*
|
||||
X14009000Y-33216975D01*
|
||||
X17582200Y-31766975D02*
|
||||
X16082200Y-31766975D01*
|
||||
X14009000Y-33216975D02*
|
||||
X14009000Y-33283975D01*
|
||||
X20507200Y-22629575D02*
|
||||
X19352200Y-21474575D01*
|
||||
X20507200Y-25931975D02*
|
||||
X20507200Y-26181575D01*
|
||||
X15392000Y-34666975D02*
|
||||
X16082200Y-34666975D01*
|
||||
X17439900Y-29248675D02*
|
||||
X17439900Y-30124675D01*
|
||||
D28*
|
||||
X19352200Y-18671775D02*
|
||||
X19352200Y-21474575D01*
|
||||
D29*
|
||||
X20507200Y-22629575D02*
|
||||
X20507200Y-25931975D01*
|
||||
X14009100Y-33283975D02*
|
||||
X15392100Y-34666975D01*
|
||||
X16082200Y-31766975D02*
|
||||
X15459000Y-31766975D01*
|
||||
X20507300Y-26181575D02*
|
||||
X17439900Y-29248775D01*
|
||||
X17439900Y-30124775D02*
|
||||
X19082100Y-31766975D01*
|
||||
%TO.N,Net 4*%
|
||||
X52617500Y-31057875D02*
|
||||
X52617500Y-32372275D01*
|
||||
X28260000Y-17401775D02*
|
||||
X28260000Y-15758175D01*
|
||||
X52617700Y-14835775D02*
|
||||
X52617700Y-14835775D01*
|
||||
X26972200Y-18671775D02*
|
||||
X26990000Y-18671775D01*
|
||||
X52617700Y-14835775D02*
|
||||
X53129700Y-14835775D01*
|
||||
X29182400Y-14835775D02*
|
||||
X52617600Y-14835775D01*
|
||||
X52617500Y-32372275D02*
|
||||
X52617700Y-32372275D01*
|
||||
X53793200Y-19519675D02*
|
||||
X53793200Y-18069075D01*
|
||||
X53449600Y-30225775D02*
|
||||
X52617600Y-31057775D01*
|
||||
X53795200Y-16444475D02*
|
||||
X53795200Y-16739875D01*
|
||||
X53129800Y-14835775D02*
|
||||
X53795200Y-15501175D01*
|
||||
X53449600Y-25109875D02*
|
||||
X53449600Y-30225675D01*
|
||||
X53129600Y-17405475D02*
|
||||
X53795200Y-16739875D01*
|
||||
X53129600Y-17405475D02*
|
||||
X53793200Y-18069075D01*
|
||||
X29182400Y-14835775D02*
|
||||
X28260000Y-15758175D01*
|
||||
X53793200Y-19519675D02*
|
||||
X51987200Y-21325675D01*
|
||||
X54912200Y-43972075D02*
|
||||
X54912200Y-43972075D01*
|
||||
X51987200Y-23647475D02*
|
||||
X53449600Y-25109875D01*
|
||||
X51987100Y-21325675D02*
|
||||
X51987100Y-23647475D01*
|
||||
D28*
|
||||
X26990000Y-18671775D02*
|
||||
X28260000Y-17401775D01*
|
||||
D29*
|
||||
X29197200Y-14835775D02*
|
||||
X29182400Y-14835775D01*
|
||||
X54912200Y-34666975D02*
|
||||
X54912200Y-34666975D01*
|
||||
X53795200Y-16444475D02*
|
||||
X53795200Y-15501175D01*
|
||||
%TO.N,Net 7*%
|
||||
X23432200Y-33216975D02*
|
||||
X28260000Y-33216975D01*
|
||||
X16807200Y-22629575D02*
|
||||
X16593600Y-22629575D01*
|
||||
X12289600Y-34120275D02*
|
||||
X14725400Y-36556075D01*
|
||||
X16593600Y-22629575D02*
|
||||
X16082200Y-23140975D01*
|
||||
X17193000Y-36556175D02*
|
||||
X19082200Y-34666975D01*
|
||||
X12289700Y-28773375D02*
|
||||
X12289700Y-34120375D01*
|
||||
X29872200Y-31604775D02*
|
||||
X29872200Y-30773375D01*
|
||||
X17582200Y-20841775D02*
|
||||
X17582200Y-22629575D01*
|
||||
X17582200Y-22629575D02*
|
||||
X16807200Y-22629575D01*
|
||||
X21982200Y-34666975D02*
|
||||
X23432200Y-33216975D01*
|
||||
X18097500Y-17401775D02*
|
||||
X18097500Y-20326375D01*
|
||||
X18097400Y-20326475D02*
|
||||
X17582200Y-20841675D01*
|
||||
X28260000Y-33216975D02*
|
||||
X29872200Y-31604775D01*
|
||||
X14725300Y-36556075D02*
|
||||
X17193100Y-36556075D01*
|
||||
X16082200Y-23140875D02*
|
||||
X16082200Y-24980875D01*
|
||||
X16082200Y-24980775D02*
|
||||
X12289600Y-28773375D01*
|
||||
X16807200Y-22629575D02*
|
||||
X16807200Y-22629575D01*
|
||||
D28*
|
||||
X21892200Y-18671775D02*
|
||||
X21777200Y-18671775D01*
|
||||
D29*
|
||||
X19082200Y-34666975D02*
|
||||
X21982200Y-34666975D01*
|
||||
X20507200Y-17401775D02*
|
||||
X18097400Y-17401775D01*
|
||||
D28*
|
||||
X21777200Y-18671775D02*
|
||||
X20507200Y-17401775D01*
|
||||
D29*
|
||||
%TO.N,Net 6*%
|
||||
X50524600Y-20545375D02*
|
||||
X50524600Y-21692875D01*
|
||||
X50524600Y-25109875D02*
|
||||
X50395500Y-24980775D01*
|
||||
X49587800Y-24173075D02*
|
||||
X50524600Y-25109875D01*
|
||||
X39672200Y-20823175D02*
|
||||
X38457600Y-22037775D01*
|
||||
X50395500Y-17429175D02*
|
||||
X50395500Y-17429175D01*
|
||||
X50524600Y-20545375D02*
|
||||
X51147500Y-19922475D01*
|
||||
X51164000Y-18197675D02*
|
||||
X50395500Y-17429175D01*
|
||||
X49587900Y-22629575D02*
|
||||
X49587900Y-24173175D01*
|
||||
X51164000Y-18197675D02*
|
||||
X51164000Y-19905975D01*
|
||||
X50524600Y-27539175D02*
|
||||
X51987200Y-29001775D01*
|
||||
X26106600Y-29773375D02*
|
||||
X26972200Y-29773375D01*
|
||||
X41237800Y-17429175D02*
|
||||
X50395400Y-17429175D01*
|
||||
X26485400Y-25931975D02*
|
||||
X27647200Y-25931975D01*
|
||||
X50524600Y-25109875D02*
|
||||
X50524600Y-27539275D01*
|
||||
X25351200Y-27066175D02*
|
||||
X25351200Y-29017975D01*
|
||||
X31541500Y-22037675D02*
|
||||
X27647300Y-25931875D01*
|
||||
X39995200Y-18671775D02*
|
||||
X41237800Y-17429175D01*
|
||||
X51164100Y-19905875D02*
|
||||
X51147500Y-19922475D01*
|
||||
X38457700Y-22037675D02*
|
||||
X31541500Y-22037675D01*
|
||||
X39672200Y-18671775D02*
|
||||
X39672200Y-20823175D01*
|
||||
X39672200Y-18671775D02*
|
||||
X39995200Y-18671775D01*
|
||||
X25351200Y-29017975D02*
|
||||
X26106600Y-29773375D01*
|
||||
X26485400Y-25931975D02*
|
||||
X25351200Y-27066175D01*
|
||||
X50524600Y-21692775D02*
|
||||
X49587800Y-22629575D01*
|
||||
D28*
|
||||
%TO.N,Net 8*%
|
||||
X63894500Y-54546175D02*
|
||||
X66438900Y-54546175D01*
|
||||
D29*
|
||||
%TO.N,Net 5*%
|
||||
X54912200Y-20463175D02*
|
||||
X57078600Y-22629575D01*
|
||||
X54912100Y-31150575D02*
|
||||
X55472100Y-31710575D01*
|
||||
X57078700Y-26835175D02*
|
||||
X54912100Y-29001775D01*
|
||||
X57078700Y-22629575D02*
|
||||
X57078700Y-26835175D01*
|
||||
X55472200Y-31710575D02*
|
||||
X56339400Y-31710575D01*
|
||||
X54912200Y-18671775D02*
|
||||
X54912200Y-20463175D01*
|
||||
X54912100Y-29001775D02*
|
||||
X54912100Y-31150575D01*
|
||||
X56339400Y-31710575D02*
|
||||
X56339400Y-31710575D01*
|
||||
%TO.N,GND*%
|
||||
X20507200Y-29361675D02*
|
||||
X20620000Y-29248875D01*
|
||||
X61888700Y-25033075D02*
|
||||
X56311300Y-19455675D01*
|
||||
X31541400Y-29773375D02*
|
||||
X35082700Y-29773375D01*
|
||||
X61888700Y-25176375D02*
|
||||
X61888700Y-25033175D01*
|
||||
X61888700Y-25554375D02*
|
||||
X61888700Y-25176375D01*
|
||||
X37465600Y-29773375D02*
|
||||
X35082700Y-29773375D01*
|
||||
X46693600Y-20545375D02*
|
||||
X47958600Y-20545375D01*
|
||||
X61888800Y-31150575D02*
|
||||
X61888800Y-31150575D01*
|
||||
X24432200Y-16131775D02*
|
||||
X24425000Y-16131775D01*
|
||||
X21892200Y-21474575D02*
|
||||
X21892200Y-27863975D01*
|
||||
X30827200Y-25931975D02*
|
||||
X33624200Y-25931975D01*
|
||||
X61888700Y-31150575D02*
|
||||
X61888700Y-31150575D01*
|
||||
X55002200Y-16968275D02*
|
||||
X56311200Y-18277275D01*
|
||||
X37465600Y-29773375D02*
|
||||
X46693600Y-20545375D01*
|
||||
X33624200Y-25931975D02*
|
||||
X37465600Y-29773375D01*
|
||||
X21892200Y-27863975D02*
|
||||
X21892200Y-27976575D01*
|
||||
X23155000Y-20211775D02*
|
||||
X21892200Y-21474575D01*
|
||||
X54912200Y-16131775D02*
|
||||
X55069400Y-16131775D01*
|
||||
X55002200Y-16131775D02*
|
||||
X55002200Y-16968375D01*
|
||||
X56311200Y-18277275D02*
|
||||
X56311200Y-19455675D01*
|
||||
D28*
|
||||
X24425000Y-16131775D02*
|
||||
X23155000Y-17401775D01*
|
||||
D29*
|
||||
X20507200Y-31791975D02*
|
||||
X19082200Y-33216975D01*
|
||||
X23155000Y-17401775D02*
|
||||
X23155000Y-20211775D01*
|
||||
X29872200Y-29773375D02*
|
||||
X31541400Y-29773375D01*
|
||||
X21892200Y-27976475D02*
|
||||
X20620000Y-29248875D01*
|
||||
X59992200Y-61785375D02*
|
||||
X59992200Y-61785375D01*
|
||||
X47958600Y-20545375D02*
|
||||
X49832200Y-18671775D01*
|
||||
X61888700Y-25554375D02*
|
||||
X61888700Y-31150575D01*
|
||||
X20507200Y-31791875D02*
|
||||
X20507200Y-29361675D01*
|
||||
%TO.N,Net 2*%
|
||||
X23432200Y-28413575D02*
|
||||
X25792000Y-30773375D01*
|
||||
X23432200Y-28413575D02*
|
||||
X23432200Y-30181775D01*
|
||||
X25792000Y-30773375D02*
|
||||
X26972200Y-30773375D01*
|
||||
X23432200Y-30181875D02*
|
||||
X19632800Y-33981275D01*
|
||||
X25792000Y-21325775D02*
|
||||
X25792000Y-23572175D01*
|
||||
X23432200Y-25931975D02*
|
||||
X23432200Y-28413575D01*
|
||||
X18267900Y-33981275D02*
|
||||
X17582200Y-34666975D01*
|
||||
D28*
|
||||
X24432200Y-18671775D02*
|
||||
X24432200Y-19965975D01*
|
||||
D29*
|
||||
X25792000Y-23572175D02*
|
||||
X23432200Y-25931975D01*
|
||||
X24432200Y-19965875D02*
|
||||
X25792000Y-21325675D01*
|
||||
D30*
|
||||
X18267900Y-33981275D02*
|
||||
X19632800Y-33981275D01*
|
||||
%TD*%
|
||||
M02*
|
||||
@ -0,0 +1,215 @@
|
||||
%TF.GenerationSoftware,Flux,Pcbnew,9.0.9-9.0.9~ubuntu22.04.1*%
|
||||
%TF.CreationDate,2026-08-02T17:48:19+00:00*%
|
||||
%TF.ProjectId,input,696e7075-742e-46b6-9963-61645f706362,rev?*%
|
||||
%TF.SameCoordinates,Original*%
|
||||
%TF.FileFunction,Soldermask,Top*%
|
||||
%TF.FilePolarity,Negative*%
|
||||
%FSLAX46Y46*%
|
||||
G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)*
|
||||
G04 Filename: rpi4-air-quality-b7dcy*
|
||||
G04 Build it with Flux! Visit our site at: https://www.flux.ai (PCBNEW 9.0.9-9.0.9~ubuntu22.04.1) date 2026-08-02 17:48:19*
|
||||
%MOMM*%
|
||||
%LPD*%
|
||||
G01*
|
||||
G04 APERTURE LIST*
|
||||
G04 Aperture macros list*
|
||||
%AMRoundRect*
|
||||
0 Rectangle with rounded corners*
|
||||
0 $1 Rounding radius*
|
||||
0 $2 $3 $4 $5 $6 $7 $8 $9 X,Y pos of 4 corners*
|
||||
0 Add a 4 corners polygon primitive as box body*
|
||||
4,1,4,$2,$3,$4,$5,$6,$7,$8,$9,$2,$3,0*
|
||||
0 Add four circle primitives for the rounded corners*
|
||||
1,1,$1+$1,$2,$3*
|
||||
1,1,$1+$1,$4,$5*
|
||||
1,1,$1+$1,$6,$7*
|
||||
1,1,$1+$1,$8,$9*
|
||||
0 Add four rect primitives between the rounded corners*
|
||||
20,1,$1+$1,$2,$3,$4,$5,0*
|
||||
20,1,$1+$1,$4,$5,$6,$7,0*
|
||||
20,1,$1+$1,$6,$7,$8,$9,0*
|
||||
20,1,$1+$1,$8,$9,$2,$3,0*%
|
||||
G04 Aperture macros list end*
|
||||
%ADD10C,1.700000*%
|
||||
%ADD11R,1.700000X1.700000*%
|
||||
%ADD12RoundRect,0.131300X0.431200X0.743700X-0.431200X0.743700X-0.431200X-0.743700X0.431200X-0.743700X0*%
|
||||
%ADD13R,1.490000X1.730000*%
|
||||
%ADD14R,1.700000X1.250000*%
|
||||
%ADD15C,2.700000*%
|
||||
%ADD16O,2.250000X4.500000*%
|
||||
%ADD17O,5.000000X2.500000*%
|
||||
%ADD18O,4.500000X2.250000*%
|
||||
%ADD19R,0.800000X0.450000*%
|
||||
%ADD20R,1.600000X2.500000*%
|
||||
%ADD21C,1.524000*%
|
||||
%ADD22R,1.524000X1.524000*%
|
||||
%ADD23C,6.200000*%
|
||||
%ADD24R,0.700000X0.600000*%
|
||||
%ADD25R,0.500000X0.600000*%
|
||||
%ADD26RoundRect,0.131300X-0.431200X-0.743700X0.431200X-0.743700X0.431200X0.743700X-0.431200X0.743700X0*%
|
||||
G04 APERTURE END LIST*
|
||||
D10*
|
||||
%TO.C,J3*%
|
||||
X62532286Y-43972389D03*
|
||||
X59992286Y-43972408D03*
|
||||
X57452286Y-43972426D03*
|
||||
D11*
|
||||
X54912286Y-43972445D03*
|
||||
%TD*%
|
||||
D12*
|
||||
%TO.C,R4*%
|
||||
X54912100Y-29001783D03*
|
||||
X51987100Y-29001767D03*
|
||||
%TD*%
|
||||
D13*
|
||||
%TO.C,C2*%
|
||||
X17439900Y-29248875D03*
|
||||
X20619900Y-29248875D03*
|
||||
%TD*%
|
||||
D10*
|
||||
%TO.C,J4*%
|
||||
X62532286Y-39422489D03*
|
||||
X59992286Y-39422508D03*
|
||||
X57452286Y-39422526D03*
|
||||
D11*
|
||||
X54912286Y-39422545D03*
|
||||
%TD*%
|
||||
D14*
|
||||
%TO.C,D1*%
|
||||
X66438816Y-54546175D03*
|
||||
X66438784Y-50146175D03*
|
||||
%TD*%
|
||||
D13*
|
||||
%TO.C,C1*%
|
||||
X30827200Y-25931983D03*
|
||||
X27647200Y-25931967D03*
|
||||
%TD*%
|
||||
D10*
|
||||
%TO.C,J5*%
|
||||
X62532286Y-34667289D03*
|
||||
X59992286Y-34667308D03*
|
||||
X57452286Y-34667326D03*
|
||||
D11*
|
||||
X54912286Y-34667345D03*
|
||||
%TD*%
|
||||
D12*
|
||||
%TO.C,R3*%
|
||||
X53449600Y-25109883D03*
|
||||
X50524600Y-25109867D03*
|
||||
%TD*%
|
||||
D15*
|
||||
%TO.C,H4*%
|
||||
X14500000Y-17401775D03*
|
||||
%TD*%
|
||||
D16*
|
||||
%TO.C,J1*%
|
||||
X64692206Y-58785365D03*
|
||||
D17*
|
||||
X59992200Y-55785375D03*
|
||||
D18*
|
||||
X59992212Y-61785375D03*
|
||||
%TD*%
|
||||
D15*
|
||||
%TO.C,H3*%
|
||||
X72500000Y-66401775D03*
|
||||
%TD*%
|
||||
D10*
|
||||
%TO.C,J2*%
|
||||
X62532286Y-49136889D03*
|
||||
X59992286Y-49136908D03*
|
||||
X57452286Y-49136926D03*
|
||||
D11*
|
||||
X54912286Y-49136945D03*
|
||||
%TD*%
|
||||
D19*
|
||||
%TO.C,U1*%
|
||||
X29872205Y-28773383D03*
|
||||
X26972200Y-29773367D03*
|
||||
X26972195Y-30773367D03*
|
||||
X29872195Y-30773383D03*
|
||||
X29872200Y-29773383D03*
|
||||
D20*
|
||||
X28422200Y-29773375D03*
|
||||
D19*
|
||||
X26972205Y-28773367D03*
|
||||
%TD*%
|
||||
D15*
|
||||
%TO.C,H1*%
|
||||
X14500000Y-66401775D03*
|
||||
%TD*%
|
||||
D21*
|
||||
%TO.C,RPi1*%
|
||||
X39690000Y-18671775D03*
|
||||
X42230000Y-18671775D03*
|
||||
X65090000Y-16131775D03*
|
||||
X60010000Y-16131775D03*
|
||||
X60010000Y-18671775D03*
|
||||
X24450000Y-18671775D03*
|
||||
X62550000Y-16131775D03*
|
||||
X44770000Y-16131775D03*
|
||||
X32070000Y-16131775D03*
|
||||
X21910000Y-16131775D03*
|
||||
X65090000Y-18671775D03*
|
||||
X24450000Y-16131775D03*
|
||||
X47310000Y-18671775D03*
|
||||
X52390000Y-16131775D03*
|
||||
X29530000Y-18671775D03*
|
||||
X39690000Y-16131775D03*
|
||||
X54930000Y-16131775D03*
|
||||
X49850000Y-18671775D03*
|
||||
X62550000Y-18671775D03*
|
||||
X44770000Y-18671775D03*
|
||||
X37150000Y-18671775D03*
|
||||
X34610000Y-16131775D03*
|
||||
X67630000Y-16131775D03*
|
||||
X32070000Y-18671775D03*
|
||||
X29530000Y-16131775D03*
|
||||
X34610000Y-18671775D03*
|
||||
X42230000Y-16131775D03*
|
||||
X54930000Y-18671775D03*
|
||||
X26990000Y-16131775D03*
|
||||
X52390000Y-18671775D03*
|
||||
X37150000Y-16131775D03*
|
||||
X57470000Y-18671775D03*
|
||||
X47310000Y-16131775D03*
|
||||
X19370000Y-16131775D03*
|
||||
X67630000Y-18671775D03*
|
||||
X21910000Y-18671775D03*
|
||||
D22*
|
||||
X19370000Y-18671775D03*
|
||||
D21*
|
||||
X49850000Y-16131775D03*
|
||||
X26990000Y-18671775D03*
|
||||
X57470000Y-16131775D03*
|
||||
D23*
|
||||
X14500000Y-17401775D03*
|
||||
X72500000Y-17401775D03*
|
||||
X72500000Y-66401775D03*
|
||||
X14500000Y-66401775D03*
|
||||
%TD*%
|
||||
D24*
|
||||
%TO.C,U2*%
|
||||
X19082203Y-34666972D03*
|
||||
X17582197Y-31766975D03*
|
||||
X17582203Y-34666975D03*
|
||||
X16082203Y-34666978D03*
|
||||
X16082197Y-31766978D03*
|
||||
X19082197Y-31766972D03*
|
||||
D25*
|
||||
X19082200Y-33216972D03*
|
||||
%TD*%
|
||||
D15*
|
||||
%TO.C,H2*%
|
||||
X72500000Y-17401775D03*
|
||||
%TD*%
|
||||
D26*
|
||||
%TO.C,R1*%
|
||||
X17582200Y-22629575D03*
|
||||
X20507200Y-22629575D03*
|
||||
%TD*%
|
||||
D12*
|
||||
%TO.C,R2*%
|
||||
X23432200Y-25931983D03*
|
||||
X20507200Y-25931967D03*
|
||||
%TD*%
|
||||
M02*
|
||||
@ -0,0 +1,215 @@
|
||||
%TF.GenerationSoftware,Flux,Pcbnew,9.0.9-9.0.9~ubuntu22.04.1*%
|
||||
%TF.CreationDate,2026-08-02T17:48:19+00:00*%
|
||||
%TF.ProjectId,input,696e7075-742e-46b6-9963-61645f706362,rev?*%
|
||||
%TF.SameCoordinates,Original*%
|
||||
%TF.FileFunction,Paste,Top*%
|
||||
%TF.FilePolarity,Positive*%
|
||||
%FSLAX46Y46*%
|
||||
G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)*
|
||||
G04 Filename: rpi4-air-quality-b7dcy*
|
||||
G04 Build it with Flux! Visit our site at: https://www.flux.ai (PCBNEW 9.0.9-9.0.9~ubuntu22.04.1) date 2026-08-02 17:48:19*
|
||||
%MOMM*%
|
||||
%LPD*%
|
||||
G01*
|
||||
G04 APERTURE LIST*
|
||||
G04 Aperture macros list*
|
||||
%AMRoundRect*
|
||||
0 Rectangle with rounded corners*
|
||||
0 $1 Rounding radius*
|
||||
0 $2 $3 $4 $5 $6 $7 $8 $9 X,Y pos of 4 corners*
|
||||
0 Add a 4 corners polygon primitive as box body*
|
||||
4,1,4,$2,$3,$4,$5,$6,$7,$8,$9,$2,$3,0*
|
||||
0 Add four circle primitives for the rounded corners*
|
||||
1,1,$1+$1,$2,$3*
|
||||
1,1,$1+$1,$4,$5*
|
||||
1,1,$1+$1,$6,$7*
|
||||
1,1,$1+$1,$8,$9*
|
||||
0 Add four rect primitives between the rounded corners*
|
||||
20,1,$1+$1,$2,$3,$4,$5,0*
|
||||
20,1,$1+$1,$4,$5,$6,$7,0*
|
||||
20,1,$1+$1,$6,$7,$8,$9,0*
|
||||
20,1,$1+$1,$8,$9,$2,$3,0*%
|
||||
G04 Aperture macros list end*
|
||||
%ADD10C,1.700000*%
|
||||
%ADD11R,1.700000X1.700000*%
|
||||
%ADD12RoundRect,0.131300X0.431200X0.743700X-0.431200X0.743700X-0.431200X-0.743700X0.431200X-0.743700X0*%
|
||||
%ADD13R,1.490000X1.730000*%
|
||||
%ADD14R,1.700000X1.250000*%
|
||||
%ADD15C,2.700000*%
|
||||
%ADD16O,2.250000X4.500000*%
|
||||
%ADD17O,5.000000X2.500000*%
|
||||
%ADD18O,4.500000X2.250000*%
|
||||
%ADD19R,0.800000X0.450000*%
|
||||
%ADD20R,1.600000X2.500000*%
|
||||
%ADD21C,1.524000*%
|
||||
%ADD22R,1.524000X1.524000*%
|
||||
%ADD23C,6.200000*%
|
||||
%ADD24R,0.700000X0.600000*%
|
||||
%ADD25R,0.500000X0.600000*%
|
||||
%ADD26RoundRect,0.131300X-0.431200X-0.743700X0.431200X-0.743700X0.431200X0.743700X-0.431200X0.743700X0*%
|
||||
G04 APERTURE END LIST*
|
||||
D10*
|
||||
%TO.C,J3*%
|
||||
X62532286Y-43972389D03*
|
||||
X59992286Y-43972408D03*
|
||||
X57452286Y-43972426D03*
|
||||
D11*
|
||||
X54912286Y-43972445D03*
|
||||
%TD*%
|
||||
D12*
|
||||
%TO.C,R4*%
|
||||
X54912100Y-29001783D03*
|
||||
X51987100Y-29001767D03*
|
||||
%TD*%
|
||||
D13*
|
||||
%TO.C,C2*%
|
||||
X17439900Y-29248875D03*
|
||||
X20619900Y-29248875D03*
|
||||
%TD*%
|
||||
D10*
|
||||
%TO.C,J4*%
|
||||
X62532286Y-39422489D03*
|
||||
X59992286Y-39422508D03*
|
||||
X57452286Y-39422526D03*
|
||||
D11*
|
||||
X54912286Y-39422545D03*
|
||||
%TD*%
|
||||
D14*
|
||||
%TO.C,D1*%
|
||||
X66438816Y-54546175D03*
|
||||
X66438784Y-50146175D03*
|
||||
%TD*%
|
||||
D13*
|
||||
%TO.C,C1*%
|
||||
X30827200Y-25931983D03*
|
||||
X27647200Y-25931967D03*
|
||||
%TD*%
|
||||
D10*
|
||||
%TO.C,J5*%
|
||||
X62532286Y-34667289D03*
|
||||
X59992286Y-34667308D03*
|
||||
X57452286Y-34667326D03*
|
||||
D11*
|
||||
X54912286Y-34667345D03*
|
||||
%TD*%
|
||||
D12*
|
||||
%TO.C,R3*%
|
||||
X53449600Y-25109883D03*
|
||||
X50524600Y-25109867D03*
|
||||
%TD*%
|
||||
D15*
|
||||
%TO.C,H4*%
|
||||
X14500000Y-17401775D03*
|
||||
%TD*%
|
||||
D16*
|
||||
%TO.C,J1*%
|
||||
X64692206Y-58785365D03*
|
||||
D17*
|
||||
X59992200Y-55785375D03*
|
||||
D18*
|
||||
X59992212Y-61785375D03*
|
||||
%TD*%
|
||||
D15*
|
||||
%TO.C,H3*%
|
||||
X72500000Y-66401775D03*
|
||||
%TD*%
|
||||
D10*
|
||||
%TO.C,J2*%
|
||||
X62532286Y-49136889D03*
|
||||
X59992286Y-49136908D03*
|
||||
X57452286Y-49136926D03*
|
||||
D11*
|
||||
X54912286Y-49136945D03*
|
||||
%TD*%
|
||||
D19*
|
||||
%TO.C,U1*%
|
||||
X29872205Y-28773383D03*
|
||||
X26972200Y-29773367D03*
|
||||
X26972195Y-30773367D03*
|
||||
X29872195Y-30773383D03*
|
||||
X29872200Y-29773383D03*
|
||||
D20*
|
||||
X28422200Y-29773375D03*
|
||||
D19*
|
||||
X26972205Y-28773367D03*
|
||||
%TD*%
|
||||
D15*
|
||||
%TO.C,H1*%
|
||||
X14500000Y-66401775D03*
|
||||
%TD*%
|
||||
D21*
|
||||
%TO.C,RPi1*%
|
||||
X39690000Y-18671775D03*
|
||||
X42230000Y-18671775D03*
|
||||
X65090000Y-16131775D03*
|
||||
X60010000Y-16131775D03*
|
||||
X60010000Y-18671775D03*
|
||||
X24450000Y-18671775D03*
|
||||
X62550000Y-16131775D03*
|
||||
X44770000Y-16131775D03*
|
||||
X32070000Y-16131775D03*
|
||||
X21910000Y-16131775D03*
|
||||
X65090000Y-18671775D03*
|
||||
X24450000Y-16131775D03*
|
||||
X47310000Y-18671775D03*
|
||||
X52390000Y-16131775D03*
|
||||
X29530000Y-18671775D03*
|
||||
X39690000Y-16131775D03*
|
||||
X54930000Y-16131775D03*
|
||||
X49850000Y-18671775D03*
|
||||
X62550000Y-18671775D03*
|
||||
X44770000Y-18671775D03*
|
||||
X37150000Y-18671775D03*
|
||||
X34610000Y-16131775D03*
|
||||
X67630000Y-16131775D03*
|
||||
X32070000Y-18671775D03*
|
||||
X29530000Y-16131775D03*
|
||||
X34610000Y-18671775D03*
|
||||
X42230000Y-16131775D03*
|
||||
X54930000Y-18671775D03*
|
||||
X26990000Y-16131775D03*
|
||||
X52390000Y-18671775D03*
|
||||
X37150000Y-16131775D03*
|
||||
X57470000Y-18671775D03*
|
||||
X47310000Y-16131775D03*
|
||||
X19370000Y-16131775D03*
|
||||
X67630000Y-18671775D03*
|
||||
X21910000Y-18671775D03*
|
||||
D22*
|
||||
X19370000Y-18671775D03*
|
||||
D21*
|
||||
X49850000Y-16131775D03*
|
||||
X26990000Y-18671775D03*
|
||||
X57470000Y-16131775D03*
|
||||
D23*
|
||||
X14500000Y-17401775D03*
|
||||
X72500000Y-17401775D03*
|
||||
X72500000Y-66401775D03*
|
||||
X14500000Y-66401775D03*
|
||||
%TD*%
|
||||
D24*
|
||||
%TO.C,U2*%
|
||||
X19082203Y-34666972D03*
|
||||
X17582197Y-31766975D03*
|
||||
X17582203Y-34666975D03*
|
||||
X16082203Y-34666978D03*
|
||||
X16082197Y-31766978D03*
|
||||
X19082197Y-31766972D03*
|
||||
D25*
|
||||
X19082200Y-33216972D03*
|
||||
%TD*%
|
||||
D15*
|
||||
%TO.C,H2*%
|
||||
X72500000Y-17401775D03*
|
||||
%TD*%
|
||||
D26*
|
||||
%TO.C,R1*%
|
||||
X17582200Y-22629575D03*
|
||||
X20507200Y-22629575D03*
|
||||
%TD*%
|
||||
D12*
|
||||
%TO.C,R2*%
|
||||
X23432200Y-25931983D03*
|
||||
X20507200Y-25931967D03*
|
||||
%TD*%
|
||||
M02*
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,206 @@
|
||||
%TF.GenerationSoftware,Flux,Pcbnew,9.0.9-9.0.9~ubuntu22.04.1*%
|
||||
%TF.CreationDate,2026-08-02T17:48:20+00:00*%
|
||||
%TF.ProjectId,input,696e7075-742e-46b6-9963-61645f706362,rev?*%
|
||||
%TF.SameCoordinates,Original*%
|
||||
%TF.FileFunction,Copper,L2,Inr*%
|
||||
%TF.FilePolarity,Positive*%
|
||||
%FSLAX46Y46*%
|
||||
G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)*
|
||||
G04 Filename: rpi4-air-quality-b7dcy*
|
||||
G04 Build it with Flux! Visit our site at: https://www.flux.ai (PCBNEW 9.0.9-9.0.9~ubuntu22.04.1) date 2026-08-02 17:48:20*
|
||||
%MOMM*%
|
||||
%LPD*%
|
||||
G01*
|
||||
G04 APERTURE LIST*
|
||||
%TA.AperFunction,ComponentPad*%
|
||||
%ADD10C,0.600000*%
|
||||
%TD*%
|
||||
%TA.AperFunction,ComponentPad*%
|
||||
%ADD11C,1.700000*%
|
||||
%TD*%
|
||||
%TA.AperFunction,ComponentPad*%
|
||||
%ADD12R,1.700000X1.700000*%
|
||||
%TD*%
|
||||
%TA.AperFunction,ComponentPad*%
|
||||
%ADD13C,2.700000*%
|
||||
%TD*%
|
||||
%TA.AperFunction,ComponentPad*%
|
||||
%ADD14O,2.250000X4.500000*%
|
||||
%TD*%
|
||||
%TA.AperFunction,ComponentPad*%
|
||||
%ADD15O,5.000000X2.500000*%
|
||||
%TD*%
|
||||
%TA.AperFunction,ComponentPad*%
|
||||
%ADD16O,4.500000X2.250000*%
|
||||
%TD*%
|
||||
%TA.AperFunction,ComponentPad*%
|
||||
%ADD17C,1.524000*%
|
||||
%TD*%
|
||||
%TA.AperFunction,ComponentPad*%
|
||||
%ADD18R,1.524000X1.524000*%
|
||||
%TD*%
|
||||
%TA.AperFunction,ComponentPad*%
|
||||
%ADD19C,6.200000*%
|
||||
%TD*%
|
||||
G04 APERTURE END LIST*
|
||||
D10*
|
||||
%TO.N,Net 3*%
|
||||
%TO.C,*%
|
||||
X64456000Y-50146175D03*
|
||||
%TO.N,Net 4*%
|
||||
X52617600Y-32372375D03*
|
||||
X54912200Y-43972075D03*
|
||||
X54912200Y-34666975D03*
|
||||
%TO.N,Net 8*%
|
||||
X63894500Y-54546175D03*
|
||||
%TO.N,Net 5*%
|
||||
X56339400Y-31710575D03*
|
||||
%TO.N,GND*%
|
||||
X59992200Y-61785375D03*
|
||||
X61888700Y-31150575D03*
|
||||
%TD*%
|
||||
D11*
|
||||
%TO.N,Net 3*%
|
||||
%TO.C,J3*%
|
||||
X62532286Y-43972389D03*
|
||||
%TO.N,GND*%
|
||||
X59992286Y-43972408D03*
|
||||
%TO.N,Net 5*%
|
||||
X57452286Y-43972426D03*
|
||||
D12*
|
||||
%TO.N,Net 4*%
|
||||
X54912286Y-43972445D03*
|
||||
%TD*%
|
||||
D11*
|
||||
%TO.N,Net 3*%
|
||||
%TO.C,J4*%
|
||||
X62532286Y-39422489D03*
|
||||
%TO.N,GND*%
|
||||
X59992286Y-39422508D03*
|
||||
%TO.N,Net 5*%
|
||||
X57452286Y-39422526D03*
|
||||
D12*
|
||||
%TO.N,Net 4*%
|
||||
X54912286Y-39422545D03*
|
||||
%TD*%
|
||||
D11*
|
||||
%TO.N,Net 3*%
|
||||
%TO.C,J5*%
|
||||
X62532286Y-34667289D03*
|
||||
%TO.N,GND*%
|
||||
X59992286Y-34667308D03*
|
||||
%TO.N,Net 5*%
|
||||
X57452286Y-34667326D03*
|
||||
D12*
|
||||
%TO.N,Net 4*%
|
||||
X54912286Y-34667345D03*
|
||||
%TD*%
|
||||
D13*
|
||||
%TO.N,N/C*%
|
||||
%TO.C,H4*%
|
||||
X14500000Y-17401775D03*
|
||||
%TD*%
|
||||
D14*
|
||||
%TO.N,GND*%
|
||||
%TO.C,J1*%
|
||||
X64692206Y-58785365D03*
|
||||
D15*
|
||||
%TO.N,Net 8*%
|
||||
X59992200Y-55785375D03*
|
||||
D16*
|
||||
%TO.N,GND*%
|
||||
X59992212Y-61785375D03*
|
||||
%TD*%
|
||||
D13*
|
||||
%TO.N,N/C*%
|
||||
%TO.C,H3*%
|
||||
X72500000Y-66401775D03*
|
||||
%TD*%
|
||||
D11*
|
||||
%TO.N,Net 3*%
|
||||
%TO.C,J2*%
|
||||
X62532286Y-49136889D03*
|
||||
%TO.N,GND*%
|
||||
X59992286Y-49136908D03*
|
||||
%TO.N,Net 5*%
|
||||
X57452286Y-49136926D03*
|
||||
D12*
|
||||
%TO.N,Net 4*%
|
||||
X54912286Y-49136945D03*
|
||||
%TD*%
|
||||
D13*
|
||||
%TO.N,N/C*%
|
||||
%TO.C,H1*%
|
||||
X14500000Y-66401775D03*
|
||||
%TD*%
|
||||
D17*
|
||||
%TO.N,Net 6*%
|
||||
%TO.C,RPi1*%
|
||||
X39690000Y-18671775D03*
|
||||
%TO.N,N/C*%
|
||||
X42230000Y-18671775D03*
|
||||
X65090000Y-16131775D03*
|
||||
X60010000Y-16131775D03*
|
||||
X60010000Y-18671775D03*
|
||||
%TO.N,Net 2*%
|
||||
X24450000Y-18671775D03*
|
||||
%TO.N,N/C*%
|
||||
X62550000Y-16131775D03*
|
||||
X44770000Y-16131775D03*
|
||||
X32070000Y-16131775D03*
|
||||
X21910000Y-16131775D03*
|
||||
X65090000Y-18671775D03*
|
||||
%TO.N,GND*%
|
||||
X24450000Y-16131775D03*
|
||||
%TO.N,N/C*%
|
||||
X47310000Y-18671775D03*
|
||||
X52390000Y-16131775D03*
|
||||
X29530000Y-18671775D03*
|
||||
X39690000Y-16131775D03*
|
||||
%TO.N,GND*%
|
||||
X54930000Y-16131775D03*
|
||||
X49850000Y-18671775D03*
|
||||
%TO.N,N/C*%
|
||||
X62550000Y-18671775D03*
|
||||
X44770000Y-18671775D03*
|
||||
X37150000Y-18671775D03*
|
||||
X34610000Y-16131775D03*
|
||||
X67630000Y-16131775D03*
|
||||
X32070000Y-18671775D03*
|
||||
X29530000Y-16131775D03*
|
||||
X34610000Y-18671775D03*
|
||||
X42230000Y-16131775D03*
|
||||
%TO.N,Net 5*%
|
||||
X54930000Y-18671775D03*
|
||||
%TO.N,N/C*%
|
||||
X26990000Y-16131775D03*
|
||||
X52390000Y-18671775D03*
|
||||
X37150000Y-16131775D03*
|
||||
X57470000Y-18671775D03*
|
||||
X47310000Y-16131775D03*
|
||||
X19370000Y-16131775D03*
|
||||
X67630000Y-18671775D03*
|
||||
%TO.N,Net 7*%
|
||||
X21910000Y-18671775D03*
|
||||
D18*
|
||||
%TO.N,Net 1*%
|
||||
X19370000Y-18671775D03*
|
||||
D17*
|
||||
%TO.N,N/C*%
|
||||
X49850000Y-16131775D03*
|
||||
%TO.N,Net 4*%
|
||||
X26990000Y-18671775D03*
|
||||
%TO.N,N/C*%
|
||||
X57470000Y-16131775D03*
|
||||
D19*
|
||||
X14500000Y-17401775D03*
|
||||
X72500000Y-17401775D03*
|
||||
X72500000Y-66401775D03*
|
||||
X14500000Y-66401775D03*
|
||||
%TD*%
|
||||
D13*
|
||||
%TO.N,N/C*%
|
||||
%TO.C,H2*%
|
||||
X72500000Y-17401775D03*
|
||||
%TD*%
|
||||
M02*
|
||||
@ -0,0 +1,206 @@
|
||||
%TF.GenerationSoftware,Flux,Pcbnew,9.0.9-9.0.9~ubuntu22.04.1*%
|
||||
%TF.CreationDate,2026-08-02T17:48:21+00:00*%
|
||||
%TF.ProjectId,input,696e7075-742e-46b6-9963-61645f706362,rev?*%
|
||||
%TF.SameCoordinates,Original*%
|
||||
%TF.FileFunction,Copper,L3,Inr*%
|
||||
%TF.FilePolarity,Positive*%
|
||||
%FSLAX46Y46*%
|
||||
G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)*
|
||||
G04 Filename: rpi4-air-quality-b7dcy*
|
||||
G04 Build it with Flux! Visit our site at: https://www.flux.ai (PCBNEW 9.0.9-9.0.9~ubuntu22.04.1) date 2026-08-02 17:48:21*
|
||||
%MOMM*%
|
||||
%LPD*%
|
||||
G01*
|
||||
G04 APERTURE LIST*
|
||||
%TA.AperFunction,ComponentPad*%
|
||||
%ADD10C,0.600000*%
|
||||
%TD*%
|
||||
%TA.AperFunction,ComponentPad*%
|
||||
%ADD11C,1.700000*%
|
||||
%TD*%
|
||||
%TA.AperFunction,ComponentPad*%
|
||||
%ADD12R,1.700000X1.700000*%
|
||||
%TD*%
|
||||
%TA.AperFunction,ComponentPad*%
|
||||
%ADD13C,2.700000*%
|
||||
%TD*%
|
||||
%TA.AperFunction,ComponentPad*%
|
||||
%ADD14O,2.250000X4.500000*%
|
||||
%TD*%
|
||||
%TA.AperFunction,ComponentPad*%
|
||||
%ADD15O,5.000000X2.500000*%
|
||||
%TD*%
|
||||
%TA.AperFunction,ComponentPad*%
|
||||
%ADD16O,4.500000X2.250000*%
|
||||
%TD*%
|
||||
%TA.AperFunction,ComponentPad*%
|
||||
%ADD17C,1.524000*%
|
||||
%TD*%
|
||||
%TA.AperFunction,ComponentPad*%
|
||||
%ADD18R,1.524000X1.524000*%
|
||||
%TD*%
|
||||
%TA.AperFunction,ComponentPad*%
|
||||
%ADD19C,6.200000*%
|
||||
%TD*%
|
||||
G04 APERTURE END LIST*
|
||||
D10*
|
||||
%TO.N,Net 3*%
|
||||
%TO.C,*%
|
||||
X64456000Y-50146175D03*
|
||||
%TO.N,Net 4*%
|
||||
X52617600Y-32372375D03*
|
||||
X54912200Y-43972075D03*
|
||||
X54912200Y-34666975D03*
|
||||
%TO.N,Net 8*%
|
||||
X63894500Y-54546175D03*
|
||||
%TO.N,Net 5*%
|
||||
X56339400Y-31710575D03*
|
||||
%TO.N,GND*%
|
||||
X59992200Y-61785375D03*
|
||||
X61888700Y-31150575D03*
|
||||
%TD*%
|
||||
D11*
|
||||
%TO.N,Net 3*%
|
||||
%TO.C,J3*%
|
||||
X62532286Y-43972389D03*
|
||||
%TO.N,GND*%
|
||||
X59992286Y-43972408D03*
|
||||
%TO.N,Net 5*%
|
||||
X57452286Y-43972426D03*
|
||||
D12*
|
||||
%TO.N,Net 4*%
|
||||
X54912286Y-43972445D03*
|
||||
%TD*%
|
||||
D11*
|
||||
%TO.N,Net 3*%
|
||||
%TO.C,J4*%
|
||||
X62532286Y-39422489D03*
|
||||
%TO.N,GND*%
|
||||
X59992286Y-39422508D03*
|
||||
%TO.N,Net 5*%
|
||||
X57452286Y-39422526D03*
|
||||
D12*
|
||||
%TO.N,Net 4*%
|
||||
X54912286Y-39422545D03*
|
||||
%TD*%
|
||||
D11*
|
||||
%TO.N,Net 3*%
|
||||
%TO.C,J5*%
|
||||
X62532286Y-34667289D03*
|
||||
%TO.N,GND*%
|
||||
X59992286Y-34667308D03*
|
||||
%TO.N,Net 5*%
|
||||
X57452286Y-34667326D03*
|
||||
D12*
|
||||
%TO.N,Net 4*%
|
||||
X54912286Y-34667345D03*
|
||||
%TD*%
|
||||
D13*
|
||||
%TO.N,N/C*%
|
||||
%TO.C,H4*%
|
||||
X14500000Y-17401775D03*
|
||||
%TD*%
|
||||
D14*
|
||||
%TO.N,GND*%
|
||||
%TO.C,J1*%
|
||||
X64692206Y-58785365D03*
|
||||
D15*
|
||||
%TO.N,Net 8*%
|
||||
X59992200Y-55785375D03*
|
||||
D16*
|
||||
%TO.N,GND*%
|
||||
X59992212Y-61785375D03*
|
||||
%TD*%
|
||||
D13*
|
||||
%TO.N,N/C*%
|
||||
%TO.C,H3*%
|
||||
X72500000Y-66401775D03*
|
||||
%TD*%
|
||||
D11*
|
||||
%TO.N,Net 3*%
|
||||
%TO.C,J2*%
|
||||
X62532286Y-49136889D03*
|
||||
%TO.N,GND*%
|
||||
X59992286Y-49136908D03*
|
||||
%TO.N,Net 5*%
|
||||
X57452286Y-49136926D03*
|
||||
D12*
|
||||
%TO.N,Net 4*%
|
||||
X54912286Y-49136945D03*
|
||||
%TD*%
|
||||
D13*
|
||||
%TO.N,N/C*%
|
||||
%TO.C,H1*%
|
||||
X14500000Y-66401775D03*
|
||||
%TD*%
|
||||
D17*
|
||||
%TO.N,Net 6*%
|
||||
%TO.C,RPi1*%
|
||||
X39690000Y-18671775D03*
|
||||
%TO.N,N/C*%
|
||||
X42230000Y-18671775D03*
|
||||
X65090000Y-16131775D03*
|
||||
X60010000Y-16131775D03*
|
||||
X60010000Y-18671775D03*
|
||||
%TO.N,Net 2*%
|
||||
X24450000Y-18671775D03*
|
||||
%TO.N,N/C*%
|
||||
X62550000Y-16131775D03*
|
||||
X44770000Y-16131775D03*
|
||||
X32070000Y-16131775D03*
|
||||
X21910000Y-16131775D03*
|
||||
X65090000Y-18671775D03*
|
||||
%TO.N,GND*%
|
||||
X24450000Y-16131775D03*
|
||||
%TO.N,N/C*%
|
||||
X47310000Y-18671775D03*
|
||||
X52390000Y-16131775D03*
|
||||
X29530000Y-18671775D03*
|
||||
X39690000Y-16131775D03*
|
||||
%TO.N,GND*%
|
||||
X54930000Y-16131775D03*
|
||||
X49850000Y-18671775D03*
|
||||
%TO.N,N/C*%
|
||||
X62550000Y-18671775D03*
|
||||
X44770000Y-18671775D03*
|
||||
X37150000Y-18671775D03*
|
||||
X34610000Y-16131775D03*
|
||||
X67630000Y-16131775D03*
|
||||
X32070000Y-18671775D03*
|
||||
X29530000Y-16131775D03*
|
||||
X34610000Y-18671775D03*
|
||||
X42230000Y-16131775D03*
|
||||
%TO.N,Net 5*%
|
||||
X54930000Y-18671775D03*
|
||||
%TO.N,N/C*%
|
||||
X26990000Y-16131775D03*
|
||||
X52390000Y-18671775D03*
|
||||
X37150000Y-16131775D03*
|
||||
X57470000Y-18671775D03*
|
||||
X47310000Y-16131775D03*
|
||||
X19370000Y-16131775D03*
|
||||
X67630000Y-18671775D03*
|
||||
%TO.N,Net 7*%
|
||||
X21910000Y-18671775D03*
|
||||
D18*
|
||||
%TO.N,Net 1*%
|
||||
X19370000Y-18671775D03*
|
||||
D17*
|
||||
%TO.N,N/C*%
|
||||
X49850000Y-16131775D03*
|
||||
%TO.N,Net 4*%
|
||||
X26990000Y-18671775D03*
|
||||
%TO.N,N/C*%
|
||||
X57470000Y-16131775D03*
|
||||
D19*
|
||||
X14500000Y-17401775D03*
|
||||
X72500000Y-17401775D03*
|
||||
X72500000Y-66401775D03*
|
||||
X14500000Y-66401775D03*
|
||||
%TD*%
|
||||
D13*
|
||||
%TO.N,N/C*%
|
||||
%TO.C,H2*%
|
||||
X72500000Y-17401775D03*
|
||||
%TD*%
|
||||
M02*
|
||||
@ -0,0 +1,107 @@
|
||||
P CODE 00
|
||||
P UNITS CUST 0
|
||||
P arrayDim N
|
||||
317NET?3 -c324 D0118PA00X-028954Y-003798X0236Y0000R000S3
|
||||
317NET?4 -3aa9 D0118PA00X-033615Y+003200X0236Y0000R000S3
|
||||
317NET?4 -7147 D0118PA00X-032712Y-001367X0236Y0000R000S3
|
||||
317NET?4 -f6df D0118PA00X-032712Y+002296X0236Y0000R000S3
|
||||
317NET?8 -3515 D0118PA00X-029175Y-005530X0236Y0000R000S3
|
||||
317NET?5 -aeea D0118PA00X-032150Y+003460X0236Y0000R000S3
|
||||
317GND -2a33 D0118PA00X-030712Y-008380X0236Y0000R000S3
|
||||
317GND -3587 D0118PA00X-029965Y+003681X0236Y0000R000S3
|
||||
317NET?3 J3 -Pin_ D0394PA00X-029712Y-001367X0669Y0000R270S0
|
||||
317GND J3 -Pin_ D0394PA00X-030712Y-001367X0669Y0000R270S0
|
||||
317NET?5 J3 -Pin_ D0394PA00X-031712Y-001367X0669Y0000R270S0
|
||||
317NET?4 J3 -Pin_ D0394PA00X-032712Y-001367X0669Y0669R270S0
|
||||
327NET?5 R4 -P1 A01X-032712Y+004527X0443Y0689R180S2
|
||||
327NET?6 R4 -P2 A01X-033863Y+004527X0443Y0689R180S2
|
||||
327NET?1 C2 -1 A01X-047465Y+004430X0587Y0681R000S2
|
||||
327GND C2 -2 A01X-046213Y+004430X0587Y0681R000S2
|
||||
317NET?3 J4 -Pin_ D0394PA00X-029712Y+000424X0669Y0000R270S0
|
||||
317GND J4 -Pin_ D0394PA00X-030712Y+000424X0669Y0000R270S0
|
||||
317NET?5 J4 -Pin_ D0394PA00X-031712Y+000424X0669Y0000R270S0
|
||||
317NET?4 J4 -Pin_ D0394PA00X-032712Y+000424X0669Y0669R270S0
|
||||
327NET?8 D1 -1 A01X-028174Y-005530X0492Y0669R090S2
|
||||
327NET?3 D1 -2 A01X-028174Y-003798X0492Y0669R090S2
|
||||
327GND C1 -1 A01X-042194Y+005735X0587Y0681R180S2
|
||||
327NET?6 C1 -2 A01X-043446Y+005735X0587Y0681R180S2
|
||||
317NET?3 J5 -Pin_ D0394PA00X-029712Y+002296X0669Y0000R270S0
|
||||
317GND J5 -Pin_ D0394PA00X-030712Y+002296X0669Y0000R270S0
|
||||
317NET?5 J5 -Pin_ D0394PA00X-031712Y+002296X0669Y0000R270S0
|
||||
317NET?4 J5 -Pin_ D0394PA00X-032712Y+002296X0669Y0669R270S0
|
||||
327NET?4 R3 -P1 A01X-033288Y+006059X0443Y0689R180S2
|
||||
327NET?6 R3 -P2 A01X-034439Y+006059X0443Y0689R180S2
|
||||
317N/C H4 -P1 D1063PA00X-048622Y+009094X1063Y0000R000S0
|
||||
317GND J1 -~ D0394PA00X-028861Y-007199X1772Y0886R090S0
|
||||
317NET?8 J1 -~ D0315PA00X-030712Y-006018X0984Y1969R090S0
|
||||
317GND J1 -~ D0394PA00X-030712Y-008380X0886Y1772R090S0
|
||||
317N/C H3 -P1 D1063PA00X-025787Y-010198X1063Y0000R000S0
|
||||
317NET?3 J2 -Pin_ D0394PA00X-029712Y-003400X0669Y0000R270S0
|
||||
317GND J2 -Pin_ D0394PA00X-030712Y-003400X0669Y0000R270S0
|
||||
317NET?5 J2 -Pin_ D0394PA00X-031712Y-003400X0669Y0000R270S0
|
||||
317NET?4 J2 -Pin_ D0394PA00X-032712Y-003400X0669Y0669R270S0
|
||||
327N/C U1 -NC_1 A01X-042570Y+004617X0177Y0315R090S2
|
||||
327NET?6 U1 -VDD A01X-043712Y+004223X0177Y0315R090S2
|
||||
327NET?2 U1 -SCK A01X-043712Y+003829X0177Y0315R090S2
|
||||
327NET?7 U1 -DATA A01X-042570Y+003829X0177Y0315R090S2
|
||||
327GND U1 -GND A01X-042570Y+004223X0177Y0315R090S2
|
||||
327N/C U1 -EP A01X-043141Y+004223X0630Y0984R180S2
|
||||
327N/C U1 -NC_2 A01X-043712Y+004617X0177Y0315R090S2
|
||||
317N/C H1 -P1 D1063PA00X-048622Y-010198X1063Y0000R000S0
|
||||
317NET?6 RPi1 -3V3 D0400PA00X-038705Y+008594X0600Y0000R000S0
|
||||
317N/C RPi1 -MOSI D0400PA00X-037705Y+008594X0600Y0000R000S0
|
||||
317N/C RPi1 -GPIO D0400PA00X-028705Y+009594X0600Y0000R000S0
|
||||
317N/C RPi1 -GND D0400PA00X-030705Y+009594X0600Y0000R000S0
|
||||
317N/C RPi1 -PWM1 D0400PA00X-030705Y+008594X0600Y0000R000S0
|
||||
317NET?2 RPi1 -SCL/ D0400PA00X-044705Y+008594X0600Y0000R000S0
|
||||
317N/C RPi1 -GPIO D0400PA00X-029705Y+009594X0600Y0000R000S0
|
||||
317N/C RPi1 -GPIO D0400PA00X-036705Y+009594X0600Y0000R000S0
|
||||
317N/C RPi1 -GPIO D0400PA00X-041705Y+009594X0600Y0000R000S0
|
||||
317N/C RPi1 -5V D0400PA00X-045705Y+009594X0600Y0000R000S0
|
||||
317N/C RPi1 -GPIO D0400PA00X-028705Y+008594X0600Y0000R000S0
|
||||
317GND RPi1 -GND D0400PA00X-044705Y+009594X0600Y0000R000S0
|
||||
317N/C RPi1 -SCLK D0400PA00X-035705Y+008594X0600Y0000R000S0
|
||||
317N/C RPi1 -ID_S D0400PA00X-033705Y+009594X0600Y0000R000S0
|
||||
317N/C RPi1 -GND D0400PA00X-042705Y+008594X0600Y0000R000S0
|
||||
317N/C RPi1 -GPIO D0400PA00X-038705Y+009594X0600Y0000R000S0
|
||||
317GND RPi1 -GND D0400PA00X-032705Y+009594X0600Y0000R000S0
|
||||
317GND RPi1 -GND D0400PA00X-034705Y+008594X0600Y0000R000S0
|
||||
317N/C RPi1 -GPIO D0400PA00X-029705Y+008594X0600Y0000R000S0
|
||||
317N/C RPi1 -MISO D0400PA00X-036705Y+008594X0600Y0000R000S0
|
||||
317N/C RPi1 -GPIO D0400PA00X-039705Y+008594X0600Y0000R000S0
|
||||
317N/C RPi1 -GND D0400PA00X-040705Y+009594X0600Y0000R000S0
|
||||
317N/C RPi1 -GPIO D0400PA00X-027705Y+009594X0600Y0000R000S0
|
||||
317N/C RPi1 -GPIO D0400PA00X-041705Y+008594X0600Y0000R000S0
|
||||
317N/C RPi1 -GPIO D0400PA00X-042705Y+009594X0600Y0000R000S0
|
||||
317N/C RPi1 -GPIO D0400PA00X-040705Y+008594X0600Y0000R000S0
|
||||
317N/C RPi1 -GND D0400PA00X-037705Y+009594X0600Y0000R000S0
|
||||
317NET?5 RPi1 -GCLK D0400PA00X-032705Y+008594X0600Y0000R000S0
|
||||
317N/C RPi1 -GPIO D0400PA00X-043705Y+009594X0600Y0000R000S0
|
||||
317N/C RPi1 -ID_S D0400PA00X-033705Y+008594X0600Y0000R000S0
|
||||
317N/C RPi1 -GPIO D0400PA00X-039705Y+009594X0600Y0000R000S0
|
||||
317N/C RPi1 -GCLK D0400PA00X-031705Y+008594X0600Y0000R000S0
|
||||
317N/C RPi1 -~CE0 D0400PA00X-035705Y+009594X0600Y0000R000S0
|
||||
317N/C RPi1 -5V D0400PA00X-046705Y+009594X0600Y0000R000S0
|
||||
317N/C RPi1 -GND D0400PA00X-027705Y+008594X0600Y0000R000S0
|
||||
317NET?7 RPi1 -SDA/ D0400PA00X-045705Y+008594X0600Y0000R000S0
|
||||
317NET?1 RPi1 -3V3 D0400PA00X-046705Y+008594X0600Y0600R000S0
|
||||
317N/C RPi1 -~CE1 D0400PA00X-034705Y+009594X0600Y0000R000S0
|
||||
317NET?4 RPi1 -GCLK D0400PA00X-043705Y+008594X0600Y0000R000S0
|
||||
317N/C RPi1 -PWM0 D0400PA00X-031705Y+009594X0600Y0000R000S0
|
||||
317N/C RPi1 -S1 D1083PA00X-048622Y+009094X2441Y0000R000S0
|
||||
317N/C RPi1 -S2 D1083PA00X-025787Y+009094X2441Y0000R000S0
|
||||
317N/C RPi1 -S3 D1083PA00X-025787Y-010198X2441Y0000R000S0
|
||||
317N/C RPi1 -S4 D1083PA00X-048622Y-010198X2441Y0000R000S0
|
||||
327NET?7 U2 -SDA A01X-046818Y+002296X0236Y0276R090S2
|
||||
327NET?1 U2 -VDD A01X-047409Y+003438X0236Y0276R090S2
|
||||
327NET?2 U2 -SCL A01X-047409Y+002296X0236Y0276R090S2
|
||||
327NET?1 U2 -SDO A01X-047999Y+002296X0236Y0276R090S2
|
||||
327NET?1 U2 -VDDI A01X-047999Y+003438X0236Y0276R090S2
|
||||
327NET?1 U2 -CSB A01X-046818Y+003438X0236Y0276R090S2
|
||||
327GND U2 -GND A01X-046818Y+002867X0197Y0236R000S2
|
||||
317N/C H2 -P1 D1063PA00X-025787Y+009094X1063Y0000R000S0
|
||||
327NET?7 R1 -P1 A01X-047409Y+007036X0443Y0689R000S2
|
||||
327NET?1 R1 -P2 A01X-046257Y+007036X0443Y0689R000S2
|
||||
327NET?2 R2 -P1 A01X-045105Y+005735X0443Y0689R180S2
|
||||
327NET?1 R2 -P2 A01X-046257Y+005735X0443Y0689R180S2
|
||||
999
|
||||
@ -0,0 +1,109 @@
|
||||
M48
|
||||
; DRILL file {Flux 9.0.9-9.0.9~ubuntu22.04.1} date 2026-08-02T17:48:21+0000
|
||||
; FORMAT={-:-/ absolute / metric / decimal}
|
||||
; #@! TF.CreationDate,2026-08-02T17:48:21+00:00
|
||||
; #@! TF.GenerationSoftware,Kicad,Pcbnew,9.0.9-9.0.9~ubuntu22.04.1
|
||||
; #@! TF.FileFunction,MixedPlating,1,4
|
||||
FMAT,2
|
||||
METRIC
|
||||
; #@! TA.AperFunction,Plated,PTH,ComponentDrill
|
||||
T1C0.300
|
||||
; #@! TA.AperFunction,Plated,PTH,ComponentDrill
|
||||
T2C0.800
|
||||
; #@! TA.AperFunction,Plated,PTH,ComponentDrill
|
||||
T3C1.000
|
||||
; #@! TA.AperFunction,Plated,PTH,ComponentDrill
|
||||
T4C1.016
|
||||
; #@! TA.AperFunction,Plated,PTH,ComponentDrill
|
||||
T5C2.700
|
||||
; #@! TA.AperFunction,Plated,PTH,ComponentDrill
|
||||
T6C2.750
|
||||
%
|
||||
G90
|
||||
G05
|
||||
T1
|
||||
X52.618Y-32.372
|
||||
X54.912Y-34.667
|
||||
X54.912Y-43.972
|
||||
X56.339Y-31.711
|
||||
X59.992Y-61.785
|
||||
X61.889Y-31.151
|
||||
X63.894Y-54.546
|
||||
X64.456Y-50.146
|
||||
T3
|
||||
X54.912Y-34.667
|
||||
X54.912Y-39.423
|
||||
X54.912Y-43.972
|
||||
X54.912Y-49.137
|
||||
X57.452Y-34.667
|
||||
X57.452Y-39.423
|
||||
X57.452Y-43.972
|
||||
X57.452Y-49.137
|
||||
X59.992Y-34.667
|
||||
X59.992Y-39.423
|
||||
X59.992Y-43.972
|
||||
X59.992Y-49.137
|
||||
X62.532Y-34.667
|
||||
X62.532Y-39.422
|
||||
X62.532Y-43.972
|
||||
X62.532Y-49.137
|
||||
T4
|
||||
X19.37Y-16.132
|
||||
X19.37Y-18.672
|
||||
X21.91Y-16.132
|
||||
X21.91Y-18.672
|
||||
X24.45Y-16.132
|
||||
X24.45Y-18.672
|
||||
X26.99Y-16.132
|
||||
X26.99Y-18.672
|
||||
X29.53Y-16.132
|
||||
X29.53Y-18.672
|
||||
X32.07Y-16.132
|
||||
X32.07Y-18.672
|
||||
X34.61Y-16.132
|
||||
X34.61Y-18.672
|
||||
X37.15Y-16.132
|
||||
X37.15Y-18.672
|
||||
X39.69Y-16.132
|
||||
X39.69Y-18.672
|
||||
X42.23Y-16.132
|
||||
X42.23Y-18.672
|
||||
X44.77Y-16.132
|
||||
X44.77Y-18.672
|
||||
X47.31Y-16.132
|
||||
X47.31Y-18.672
|
||||
X49.85Y-16.132
|
||||
X49.85Y-18.672
|
||||
X52.39Y-16.132
|
||||
X52.39Y-18.672
|
||||
X54.93Y-16.132
|
||||
X54.93Y-18.672
|
||||
X57.47Y-16.132
|
||||
X57.47Y-18.672
|
||||
X60.01Y-16.132
|
||||
X60.01Y-18.672
|
||||
X62.55Y-16.132
|
||||
X62.55Y-18.672
|
||||
X65.09Y-16.132
|
||||
X65.09Y-18.672
|
||||
X67.63Y-16.132
|
||||
X67.63Y-18.672
|
||||
T5
|
||||
X14.5Y-17.402
|
||||
X14.5Y-66.402
|
||||
X72.5Y-17.402
|
||||
X72.5Y-66.402
|
||||
T6
|
||||
X14.5Y-17.402
|
||||
X14.5Y-66.402
|
||||
X72.5Y-17.402
|
||||
X72.5Y-66.402
|
||||
T2
|
||||
X61.092Y-55.785G85X58.892Y-55.785
|
||||
G05
|
||||
T3
|
||||
X60.992Y-61.785G85X58.992Y-61.785
|
||||
G05
|
||||
X64.692Y-57.785G85X64.692Y-59.785
|
||||
G05
|
||||
M30
|
||||
Binary file not shown.
@ -0,0 +1,158 @@
|
||||
# Diseño de una Arquitectura de Sistemas Embebidos Basada en Drivers para la Adquisición, Transformación y Análisis de Datos de Micro Estaciones de Calidad del Aire
|
||||
|
||||
## Descripción del Proyecto
|
||||
|
||||
Este proyecto fue desarrollado en el marco de la **Estancia en el Verano de la Investigación Científica y Tecnológica del Programa Delfín 2026** en el Instituto Tecnológico de Morelia, bajo la asesoría del Dr. Gerardo Marx Chávez Campos. Desarrollado por Fernando Martínez Valenzuela.
|
||||
|
||||
El proyecto consiste en la evaluación experimental del comportamiento de sensores de bajo costo para la creación de redes de monitoreo de calidad del aire en contextos urbanos. Su enfoque principal radica en el diseño de una plataforma de hardware embebido altamente eficiente que gestione la recolección, el procesamiento, el almacenamiento y la visualización de los datos ambientales en tiempo real, operando bajo un entorno de Linux.
|
||||
|
||||
## Objetivo
|
||||
|
||||
Analizar el comportamiento de sensores de bajo costo mediante el diseño y desarrollo de una plataforma de hardware embebido basada en Raspberry Pi 4, con el fin de cuantificar la deriva instrumental y el error sistemático en la adquisición de datos de calidad del aire bajo condiciones controladas.
|
||||
|
||||
## Arquitectura del Sistema
|
||||
|
||||
El sistema está construido sobre una arquitectura integral operando en **Raspbian OS Lite**, estructurada en las siguientes capas (basado en el flujo de datos del proyecto):
|
||||
|
||||
1. **Adquisición de Hardware:** Lectura de sensores ambientales a través del protocolo **I2C**, utilizando buses separados para evitar latencia y conflictos de dirección.
|
||||
2. **Procesamiento Embebido (C):**
|
||||
- Un programa principal (orquestador) actúa como driver en espacio de usuario (*User space*).
|
||||
- Realiza validación de *checksum* sobre las lecturas de los sensores.
|
||||
- **Gestión a corto plazo:** Escribe los datos crudos en un disco RAM (`/dev/shm/aql_actual.txt`) cada **10 segundos** para proteger la vida útil de la memoria SD frente al desgaste por ciclos continuos de escritura.
|
||||
- **Gestión a largo plazo:** Acumula la información por lotes (`lote_bd.csv`) y la guarda en la memoria SD/SQLite cada **5 minutos**.
|
||||
3. **Procesamiento de Python y Datos:** Un motor desarrollado en Python que lee los datos crudos desde la RAM, calcula el Índice de Calidad del Aire (ICA) basándose estrictamente en la normativa oficial **NOM-172-SEMARNAT-2019**, y genera archivos JSON.
|
||||
4. **Capa de Despliegue (Front-end):** Utiliza **Nginx** como servidor web local. La interfaz de usuario (IU Estilo Apple) ofrece:
|
||||
- Panel de control en tiempo real con detección asíncrona de errores de I2C.
|
||||
- Semáforo ambiental visual para la interpretación del ICA.
|
||||
- Visualización dinámica de tendencias históricas utilizando la librería *Chart.js*.
|
||||
- Exportación estándar de datos completos en formato CSV.
|
||||
|
||||
## Materiales
|
||||
|
||||
- **Raspberry Pi 4B** (Unidad central de procesamiento).
|
||||
- **Sensores de Gas Gravity DFRobot** para medir gases nocivos (CO, NO2, SO2, O3).
|
||||
- **Sensores de Clima** (HTU21D y BMP180) para medir temperatura, humedad y presión atmosférica.
|
||||
- Componentes para la Placa de Circuito Impreso (PCB) a medida diseñada en **Flux**.
|
||||
|
||||
## Conexiones de Hardware
|
||||
|
||||
El hardware cuenta con un diseño de **2 capas** implementando planos de Tierra (GND) y Alimentación (VCC) para mitigar la Interferencia Electromagnética (EMI). Es de importancia crítica la integración de resistencias Pull-Up (4.7kΩ a 10kΩ) en las líneas SDA y SCL para mantener el estado lógico ALTO y evitar pérdida de paquetes.
|
||||
|
||||
| Sensor / Módulo | Pin RPi 4B (Físico) | Pin RPi 4B (GPIO) | Función / Bus |
|
||||
|-----------------|---------------------|-------------------|---------------|
|
||||
| **VCC** (Todos) | Pin 2 o 4 | 5V | Alimentación |
|
||||
| **GND** (Común) | Pin 6, 9, 14... | GND | Tierra común |
|
||||
| **SDA Clima** | Pin 3 | GPIO 2 | I2C-1 (Datos) |
|
||||
| **SCL Clima** | Pin 5 | GPIO 3 | I2C-1 (Reloj) |
|
||||
| **SDA Gases** | Pin 7 | GPIO 4 | I2C-3 (Datos) |
|
||||
| **SCL Gases** | Pin 29 | GPIO 5 | I2C-3 (Reloj) |
|
||||
|
||||
*(Nota: Asegúrate de habilitar el bus i2c-3 modificando el archivo `/boot/firmware/config.txt` si es necesario).*
|
||||
|
||||
## Guía de Implementación
|
||||
|
||||
Sigue estas instrucciones paso a paso para poner en marcha el sistema desde cualquier instalación limpia de Raspbian OS Lite.
|
||||
|
||||
### 1. Activar los buses I2C
|
||||
El primer bus (`i2c-1`) se activa desde la herramienta de configuración de la Raspberry Pi:
|
||||
```bash
|
||||
sudo raspi-config
|
||||
```
|
||||
> Ve a **Interface Options** -> **I2C** -> Selecciona **Yes** -> Sal de la herramienta.
|
||||
|
||||
Para activar el segundo bus (`i2c-3`) que utilizarán los sensores de gases, debes editar el archivo de configuración de arranque:
|
||||
```bash
|
||||
sudo nano /boot/firmware/config.txt
|
||||
```
|
||||
> Agrega al final del archivo la siguiente línea:
|
||||
> `dtoverlay=i2c3,pins_4_5`
|
||||
>
|
||||
> Guarda el archivo (`Ctrl+O`, `Enter`, `Ctrl+X`) y reinicia la Raspberry Pi ejecutando `sudo reboot`.
|
||||
|
||||
### 2. Instalar dependencias del sistema
|
||||
Instala los compiladores, herramientas I2C y el servidor web:
|
||||
```bash
|
||||
sudo apt update
|
||||
sudo apt install -y build-essential gcc i2c-tools nginx python3 python3-pip python3-flask sqlite3 libi2c-dev
|
||||
```
|
||||
|
||||
### 3. Clonar el repositorio
|
||||
```bash
|
||||
git clone https://gitea.itmorelia.com/Verano-Delfin-2026/AirQualityMicrostation.git
|
||||
cd AirQualityMicrostation
|
||||
```
|
||||
|
||||
### 4. Verificar los sensores conectados
|
||||
Verifica la comunicación en los buses separados:
|
||||
```bash
|
||||
i2cdetect -y 1
|
||||
i2cdetect -y 3
|
||||
```
|
||||
|
||||
### 5. Compilar y Ejecutar el Controlador Principal en C
|
||||
El controlador principal (orquestador) se encuentra en el archivo `main.c`. Para compilarlo vinculando la librería I2C, ejecuta:
|
||||
```bash
|
||||
gcc src/main.c -o orquestador_main -li2c
|
||||
```
|
||||
Una vez compilado, debes ejecutarlo en segundo plano (agregando `&`) para que inicie la recolección de datos continua:
|
||||
```bash
|
||||
./orquestador_main &
|
||||
```
|
||||
|
||||
### 6. Ejecutar el Motor de Python y Configurar Nginx
|
||||
Los archivos de Python se encargan de calcular el ICA (NOM-172) y generar los JSON. Ejecuta el script principal de la API de la siguiente manera:
|
||||
```bash
|
||||
python3 api/app.py &
|
||||
```
|
||||
|
||||
Finalmente, copia los archivos del front-end a la ruta pública de Nginx y reinicia el servicio web:
|
||||
```bash
|
||||
sudo cp -r web/* /var/www/html/
|
||||
sudo systemctl restart nginx
|
||||
```
|
||||
*(Puedes acceder al panel interactivo ingresando la IP de la Raspberry Pi en tu navegador).*
|
||||
|
||||
### 7. Configuración y Uso de la Herramienta CLI
|
||||
|
||||
Para consultar los datos de los sensores directamente desde la terminal, necesitas agregar el script `comandos.bash` a la Raspberry Pi.
|
||||
|
||||
**Paso A: Agregar o crear el archivo**
|
||||
Si el archivo no está incluido en el repositorio clonado, puedes crearlo directamente:
|
||||
```bash
|
||||
nano comandos.bash
|
||||
```
|
||||
*(Pega allí el código del script proporcionado, guarda con `Ctrl+O`, presiona `Enter`, y sal con `Ctrl+X`). Alternativamente, si tienes el archivo en tu PC, puedes transferirlo a la Raspberry Pi mediante SCP o un cliente SFTP como FileZilla.*
|
||||
|
||||
**Paso B: Instalar globalmente el comando**
|
||||
Una vez que el archivo `comandos.bash` esté listo en tu Raspberry, instálalo en el sistema con permisos de ejecución:
|
||||
|
||||
```bash
|
||||
sudo cp comandos.bash /usr/local/bin/aql
|
||||
sudo chmod +x /usr/local/bin/aql
|
||||
```
|
||||
|
||||
**Funcionamiento:**
|
||||
El script es muy eficiente porque no consulta la base de datos, sino que lee la información en tiempo real directamente desde el disco RAM (`/dev/shm/aql_actual.txt`).
|
||||
|
||||
**Modo de Uso:**
|
||||
- `aql clima` (Muestra Temperatura, Humedad y Presión).
|
||||
- `aql values` (Muestra un resumen de todos los gases en ppm).
|
||||
- `aql CO`, `aql O3`, `aql NO2`, `aql SO2` (Consultas individuales por gas).
|
||||
|
||||
**Nota de Solución de problemas:** Si recibes el error *"La microestación no está ejecutándose o aún no hay datos"*, significa que el archivo temporal en RAM no existe y debes verificar que el programa orquestador en C esté funcionando.
|
||||
|
||||
## Conclusiones
|
||||
|
||||
La microestación de calidad del aire demuestra la viabilidad técnica de implementar redes densas de monitoreo urbano mediante componentes de bajo costo. La arquitectura desarrollada prioriza la adaptabilidad y la alta disponibilidad. Al decidir integrar los controladores en el espacio de usuario (y no en el núcleo) en conjunto con un modelo híbrido de escritura de memoria (RAM Disk y SQLite), se ha logrado un sistema resistente frente al estrés informático continuo, que previene colapsos operativos del núcleo (Kernel Panic) y que disminuye drásticamente el desgaste del almacenamiento físico.
|
||||
|
||||
## Limitaciones
|
||||
|
||||
Para mantener el rigor académico, el alcance del estudio excluye los siguientes aspectos (limitaciones técnicas actuales de la plataforma):
|
||||
|
||||
1. **Calibración robusta y validación en campo:** No se realizan campañas de medición en exteriores a largo plazo, ni contrastación contra equipos meteorológicos oficiales para corregir deriva de calibración (*drift*) o sensibilidades climáticas.
|
||||
2. **Diseño mecánico y aislamiento:** El proyecto no contempla el diseño o fabricación de una carcasa protectora con grado de protección IP contra la intemperie (lluvia/polvo).
|
||||
3. **Análisis predictivo de datos:** No se implementan algoritmos de Machine Learning ni almacenamiento masivo en la nube para análisis a gran escala.
|
||||
4. **Drivers en el Espacio de Usuario (User space):** Los drivers en C se ejecutan en el espacio de usuario en lugar del núcleo (Kernel space) para evitar bloqueos críticos (*Kernel Panic*) ante fallos de hardware intermitentes en los sensores.
|
||||
|
||||
---
|
||||
*Documentación basada en la Metodología del Protocolo Oficial. Programa Delfín 2026.*
|
||||
@ -0,0 +1,38 @@
|
||||
#!/bin/bash
|
||||
# Guardar en sudo nano /usr/local/bin/aql
|
||||
|
||||
# Verificamos si el archivo existe en la memoria
|
||||
if [ ! -f "/dev/shm/aql_actual.txt" ]; then
|
||||
echo "Error: La microestación no está ejecutándose o aún no hay datos."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Cargamos las variables directamente desde el archivo
|
||||
source /dev/shm/aql_actual.txt
|
||||
|
||||
case "$1" in
|
||||
"CO")
|
||||
echo "CO: $CO ppm (Actualizado: $FECHA)"
|
||||
;;
|
||||
"O3")
|
||||
echo "O3: $O3 ppm (Actualizado: $FECHA)"
|
||||
;;
|
||||
"SO2")
|
||||
echo "SO2: $SO2 ppm (Actualizado: $FECHA)"
|
||||
;;
|
||||
"NO2")
|
||||
echo "NO2: $NO2 ppm (Actualizado: $FECHA)"
|
||||
;;
|
||||
"clima")
|
||||
echo "Temperatura: $TEMP C -- Humedad: $HUM % -- Presión: $PRES hPa"
|
||||
echo "Última lectura: $FECHA"
|
||||
;;
|
||||
"values")
|
||||
echo "CO: $CO ppm -- SO2: $SO2 ppm -- O3: $O3 ppm -- NO2: $NO2 ppm"
|
||||
echo "Última lectura: $FECHA"
|
||||
;;
|
||||
*)
|
||||
echo "Comando no reconocido. Opciones válidas:"
|
||||
echo " aql CO, aql O3, aql SO2, aql NO2, aql clima, aql values"
|
||||
;;
|
||||
esac
|
||||
@ -0,0 +1,705 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="es">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Micro Air Quality Station</title>
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.18.5/xlsx.full.min.js"></script>
|
||||
<style>
|
||||
/* Estilo general con gradiente sutil de fondo */
|
||||
body {
|
||||
background: linear-gradient(135deg, #f5f5f7 0%, #e8e8ed 100%);
|
||||
font-family: -apple-system, BlinkMacSystemFont, "SF Pro Display", "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
|
||||
color: #1d1d1f;
|
||||
margin: 0;
|
||||
padding: 40px 20px;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-weight: 700;
|
||||
letter-spacing: -1px;
|
||||
font-size: 2.5rem;
|
||||
margin-bottom: 5px;
|
||||
background: linear-gradient(90deg, #1d1d1f, #434344);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-weight: 600;
|
||||
letter-spacing: -0.5px;
|
||||
color: #1d1d1f;
|
||||
}
|
||||
|
||||
.contenedor {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
/* Franja de Color NOM-172 con efecto premium */
|
||||
#franja-ica {
|
||||
padding: 24px;
|
||||
border-radius: 24px;
|
||||
margin-bottom: 40px;
|
||||
text-align: center;
|
||||
color: white;
|
||||
font-weight: 700;
|
||||
font-size: 24px;
|
||||
background: linear-gradient(135deg, #86868b, #6e6e73);
|
||||
transition: background 0.5s ease, box-shadow 0.3s ease;
|
||||
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.15);
|
||||
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
|
||||
/* Diseño de las Tarjetas (Cards) con profundidad multicapa */
|
||||
.grid-tarjetas {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
|
||||
gap: 24px;
|
||||
margin-bottom: 50px;
|
||||
}
|
||||
|
||||
.grid-graficas {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
gap: 40px;
|
||||
margin-bottom: 50px;
|
||||
}
|
||||
|
||||
.tarjeta, .tarjeta-grafica {
|
||||
background: linear-gradient(145deg, #ffffff, #fdfdfd);
|
||||
border-radius: 24px;
|
||||
padding: 28px;
|
||||
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.04), 0 1px 3px rgba(0, 0, 0, 0.02);
|
||||
border: 1px solid rgba(255, 255, 255, 0.8);
|
||||
transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.tarjeta:hover {
|
||||
transform: translateY(-6px);
|
||||
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.08), 0 2px 5px rgba(0, 0, 0, 0.03);
|
||||
}
|
||||
|
||||
/* Acento decorativo sutil en las tarjetas */
|
||||
.tarjeta::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 4px;
|
||||
background: linear-gradient(90deg, transparent, rgba(0, 113, 227, 0.1), transparent);
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s;
|
||||
}
|
||||
.tarjeta:hover::before { opacity: 1; }
|
||||
|
||||
.titulo-tarjeta {
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
color: #86868b;
|
||||
margin-bottom: 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.valor-tarjeta {
|
||||
font-size: 46px;
|
||||
font-weight: 700;
|
||||
color: #1d1d1f;
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
gap: 8px;
|
||||
letter-spacing: -1.5px;
|
||||
}
|
||||
|
||||
.unidad {
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
color: #a1a1a6;
|
||||
letter-spacing: normal;
|
||||
}
|
||||
|
||||
.error-desconectado {
|
||||
font-size: 16px;
|
||||
color: #ff3b30;
|
||||
font-weight: 600;
|
||||
background: rgba(255, 59, 48, 0.1);
|
||||
padding: 8px 12px;
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
/* Elementos de formulario y botones modernizados */
|
||||
.controles-superiores {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 24px;
|
||||
flex-wrap: wrap;
|
||||
gap: 15px;
|
||||
background: rgba(255, 255, 255, 0.6);
|
||||
padding: 15px 25px;
|
||||
border-radius: 20px;
|
||||
backdrop-filter: blur(10px);
|
||||
border: 1px solid rgba(255, 255, 255, 0.3);
|
||||
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.02);
|
||||
}
|
||||
|
||||
select, input[type="date"] {
|
||||
padding: 10px 16px;
|
||||
border-radius: 12px;
|
||||
border: 1px solid #d2d2d7;
|
||||
background-color: #ffffff;
|
||||
font-family: inherit;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
outline: none;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s;
|
||||
box-shadow: inset 0 1px 2px rgba(0,0,0,0.02);
|
||||
}
|
||||
|
||||
select:focus, input[type="date"]:focus {
|
||||
border-color: #0071e3;
|
||||
box-shadow: 0 0 0 3px rgba(0, 113, 227, 0.2);
|
||||
}
|
||||
|
||||
button {
|
||||
padding: 10px 20px;
|
||||
border-radius: 20px;
|
||||
border: none;
|
||||
font-family: inherit;
|
||||
font-size: 14px;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 6px 15px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
.btn-buscar { background: linear-gradient(135deg, #0071e3, #005bb5); color: white; font-weight: 600; }
|
||||
.btn-csv { background: linear-gradient(135deg, #34c759, #28a745); color: white; font-weight: 600; }
|
||||
.btn-excel { background: linear-gradient(135deg, #107c41, #0c5e31); color: white; font-weight: 600; }
|
||||
|
||||
/* Estilos de la Miniterminal estilo macOS */
|
||||
.tarjeta-terminal {
|
||||
background-color: #1e1e1e;
|
||||
border-radius: 12px;
|
||||
padding: 0;
|
||||
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.3), 0 5px 15px rgba(0, 0, 0, 0.2);
|
||||
margin-bottom: 50px;
|
||||
font-family: 'SF Mono', 'Menlo', 'Monaco', 'Courier New', Courier, monospace;
|
||||
overflow: hidden;
|
||||
border: 1px solid #333;
|
||||
}
|
||||
|
||||
.terminal-header {
|
||||
background: linear-gradient(180deg, #3a3a3a 0%, #2a2a2a 100%);
|
||||
padding: 10px 15px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border-bottom: 1px solid #111;
|
||||
}
|
||||
|
||||
.terminal-dots {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.dot {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
.dot.red { background-color: #ff5f56; box-shadow: inset 0 0 4px rgba(0,0,0,0.2); }
|
||||
.dot.yellow { background-color: #ffbd2e; box-shadow: inset 0 0 4px rgba(0,0,0,0.2); }
|
||||
.dot.green { background-color: #27c93f; box-shadow: inset 0 0 4px rgba(0,0,0,0.2); }
|
||||
|
||||
.terminal-title {
|
||||
color: #999;
|
||||
font-size: 13px;
|
||||
margin: 0 auto;
|
||||
font-weight: 500;
|
||||
transform: translateX(-20px); /* Ajuste visual por los puntos */
|
||||
}
|
||||
|
||||
.terminal-cuerpo { padding: 20px; }
|
||||
|
||||
.terminal-salida {
|
||||
height: 250px;
|
||||
overflow-y: auto;
|
||||
color: #4af626;
|
||||
margin-bottom: 15px;
|
||||
white-space: pre-wrap;
|
||||
font-size: 14px;
|
||||
line-height: 1.5;
|
||||
text-shadow: 0 0 2px rgba(74, 246, 38, 0.4);
|
||||
}
|
||||
.terminal-salida::-webkit-scrollbar { width: 8px; }
|
||||
.terminal-salida::-webkit-scrollbar-thumb { background-color: #444; border-radius: 4px; }
|
||||
|
||||
.terminal-input-container {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
align-items: center;
|
||||
background: rgba(255, 255, 255, 0.05);
|
||||
padding: 10px 15px;
|
||||
border-radius: 8px;
|
||||
border: 1px solid #333;
|
||||
}
|
||||
|
||||
.terminal-input {
|
||||
flex-grow: 1;
|
||||
background-color: transparent;
|
||||
color: #fff;
|
||||
border: none;
|
||||
font-family: inherit;
|
||||
font-size: 14px;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.terminal-btn {
|
||||
background: #333;
|
||||
color: white;
|
||||
padding: 8px 16px;
|
||||
border-radius: 6px;
|
||||
box-shadow: none;
|
||||
}
|
||||
.terminal-btn:hover { background: #555; transform: none; box-shadow: none; }
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="contenedor">
|
||||
<h1>CENTRO DE MONITOREO DE CALIDAD DEL AIRE</h1>
|
||||
<p style="color: #86868b; margin-bottom: 30px; font-size: 1.1rem; font-weight: 500;">Adquisición de Datos de Calidad del Aire en Tiempo Real</p>
|
||||
|
||||
<!-- FRANJA NOM-172 -->
|
||||
<div id="franja-ica">Calculando Índice de Calidad del Aire (ICA)...</div>
|
||||
|
||||
<!-- TARJETAS DE LECTURA EN TIEMPO REAL -->
|
||||
<div class="grid-tarjetas">
|
||||
<div class="tarjeta">
|
||||
<div class="titulo-tarjeta"><span>☁️</span> Monóxido de Carbono (CO)</div>
|
||||
<div class="valor-tarjeta" id="valor-co">--</div>
|
||||
</div>
|
||||
<div class="tarjeta">
|
||||
<div class="titulo-tarjeta"><span>🛡️</span> Ozono (O3)</div>
|
||||
<div class="valor-tarjeta" id="valor-o3">--</div>
|
||||
</div>
|
||||
<div class="tarjeta">
|
||||
<div class="titulo-tarjeta"><span>🚗</span> Dióxido de Nitrógeno (NO2)</div>
|
||||
<div class="valor-tarjeta" id="valor-no2">--</div>
|
||||
</div>
|
||||
<div class="tarjeta">
|
||||
<div class="titulo-tarjeta"><span>🏭</span> Dióxido de Azufre (SO2)</div>
|
||||
<div class="valor-tarjeta" id="valor-so2">--</div>
|
||||
</div>
|
||||
<div class="tarjeta">
|
||||
<div class="titulo-tarjeta"><span>🌡️</span> Temperatura</div>
|
||||
<div class="valor-tarjeta" id="valor-temp">--</div>
|
||||
</div>
|
||||
<div class="tarjeta">
|
||||
<div class="titulo-tarjeta"><span>💧</span> Humedad</div>
|
||||
<div class="valor-tarjeta" id="valor-hum">--</div>
|
||||
</div>
|
||||
<div class="tarjeta">
|
||||
<div class="titulo-tarjeta"><span>🧭</span> Presión Atmosférica</div>
|
||||
<div class="valor-tarjeta" id="valor-pres">--</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- GRÁFICA COMPARATIVA ICA -->
|
||||
<div class="tarjeta-grafica" style="margin-bottom: 50px;">
|
||||
<h2>Comparativa de Índices de Calidad (ICA)</h2>
|
||||
<canvas id="graficaComparativaICA" height="80"></canvas>
|
||||
</div>
|
||||
|
||||
<!-- SECCIÓN DE GRÁFICAS INDIVIDUALES -->
|
||||
<div class="controles-superiores">
|
||||
<h2 style="margin: 0;">Tendencias Históricas Individuales</h2>
|
||||
|
||||
<div style="display: flex; gap: 12px; align-items: center; flex-wrap: wrap;">
|
||||
<select id="selector-rango" onchange="gestionarSelector()">
|
||||
<option value="1_mes">Último Mes</option>
|
||||
<option value="2_meses">Últimos 2 Meses</option>
|
||||
<option value="1_anio">Último Año</option>
|
||||
<option value="personalizado">Personalizado...</option>
|
||||
</select>
|
||||
|
||||
<div id="rango-personalizado" style="display: none; gap: 10px; align-items: center;">
|
||||
<input type="date" id="fecha-inicio">
|
||||
<span style="font-weight: 600; color: #86868b;">a</span>
|
||||
<input type="date" id="fecha-fin">
|
||||
<button class="btn-buscar" onclick="actualizarGrafica()">🔍 Buscar</button>
|
||||
</div>
|
||||
|
||||
<button class="btn-csv" onclick="exportarCSV()">📄 Exportar CSV</button>
|
||||
<button class="btn-excel" onclick="exportarExcel()">📊 Exportar Excel</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="grid-graficas">
|
||||
<div class="tarjeta-grafica">
|
||||
<h2>Gráfica de Monóxido de Carbono (CO)</h2>
|
||||
<canvas id="graficaCO"></canvas>
|
||||
</div>
|
||||
<div class="tarjeta-grafica">
|
||||
<h2>Gráfica de Ozono (O3)</h2>
|
||||
<canvas id="graficaO3"></canvas>
|
||||
</div>
|
||||
<div class="tarjeta-grafica">
|
||||
<h2>Gráfica de Dióxido de Nitrógeno (NO2)</h2>
|
||||
<canvas id="graficaNO2"></canvas>
|
||||
</div>
|
||||
<div class="tarjeta-grafica">
|
||||
<h2>Gráfica de Dióxido de Azufre (SO2)</h2>
|
||||
<canvas id="graficaSO2"></canvas>
|
||||
</div>
|
||||
<div class="tarjeta-grafica">
|
||||
<h2>Gráfica de Temperatura</h2>
|
||||
<canvas id="graficaTemp"></canvas>
|
||||
</div>
|
||||
<div class="tarjeta-grafica">
|
||||
<h2>Gráfica de Humedad</h2>
|
||||
<canvas id="graficaHum"></canvas>
|
||||
</div>
|
||||
<div class="tarjeta-grafica">
|
||||
<h2>Gráfica de Presión Atmosférica</h2>
|
||||
<canvas id="graficaPres"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- MINITERMINAL REMOTA ESTILO MACOS -->
|
||||
<div class="tarjeta-terminal">
|
||||
<div class="terminal-header">
|
||||
<div class="terminal-dots">
|
||||
<div class="dot red"></div>
|
||||
<div class="dot yellow"></div>
|
||||
<div class="dot green"></div>
|
||||
</div>
|
||||
<div class="terminal-title">pi@microestacion:~ (Bash)</div>
|
||||
</div>
|
||||
<div class="terminal-cuerpo">
|
||||
<div class="terminal-salida" id="terminal-salida">Bienvenido a la Raspberry Pi. Sistema listo.
|
||||
Para consultar parámetros manuales utilice los comandos locales (ej. aql clima, aql CO, aql values)...
|
||||
</div>
|
||||
<div class="terminal-input-container">
|
||||
<span style="color: #4af626; font-weight: bold;">$</span>
|
||||
<input type="text" id="terminal-input" class="terminal-input" placeholder="Escribe un comando..." onkeypress="manejarEnterTerminal(event)">
|
||||
<button class="terminal-btn" onclick="ejecutarComando()">Enviar</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<script>
|
||||
let datosGlobalesParaExportar = [];
|
||||
|
||||
// --- 1. LÓGICA NOM-172 ---
|
||||
function calcularICA(cp, gas) {
|
||||
const breakpoints = {
|
||||
"O3": [[0.0, 0.051, 0, 50], [0.052, 0.070, 51, 100], [0.071, 0.092, 101, 150], [0.093, 0.114, 151, 200], [0.115, 10.0, 201, 500]],
|
||||
"CO": [[0.0, 8.74, 0, 50], [8.75, 11.00, 51, 100], [11.01, 13.30, 101, 150], [13.31, 15.50, 151, 200], [15.51, 100.0, 201, 500]],
|
||||
"SO2": [[0.0, 0.008, 0, 50], [0.009, 0.110, 51, 100], [0.111, 0.165, 101, 150], [0.166, 0.220, 151, 200], [0.221, 10.0, 201, 500]],
|
||||
"NO2": [[0.0, 0.107, 0, 50], [0.108, 0.210, 51, 100], [0.211, 0.230, 101, 150], [0.231, 0.250, 151, 200], [0.251, 10.0, 201, 500]]
|
||||
};
|
||||
if (!breakpoints[gas]) return 0;
|
||||
for (let bp of breakpoints[gas]) {
|
||||
if (cp >= bp[0] && cp <= bp[1]) {
|
||||
return Math.round(((bp[3] - bp[2]) / (bp[1] - bp[0])) * (cp - bp[0]) + bp[2]);
|
||||
}
|
||||
}
|
||||
return 500;
|
||||
}
|
||||
|
||||
// Modificado para usar gradientes modernos en la franja
|
||||
function obtenerColorBanda(ica) {
|
||||
if (ica <= 50) return { texto: "Buena", color: "linear-gradient(135deg, #34c759, #28a745)" };
|
||||
if (ica <= 100) return { texto: "Aceptable", color: "linear-gradient(135deg, #ffcc00, #e5b700)" };
|
||||
if (ica <= 150) return { texto: "Mala", color: "linear-gradient(135deg, #ff9500, #e58600)" };
|
||||
if (ica <= 200) return { texto: "Muy Mala", color: "linear-gradient(135deg, #ff3b30, #d93128)" };
|
||||
return { texto: "Extremadamente Mala", color: "linear-gradient(135deg, #af52de, #9948c2)" };
|
||||
}
|
||||
|
||||
let graficaComparativa;
|
||||
|
||||
// --- 2. TIEMPO REAL ---
|
||||
async function obtenerDatosActuales() {
|
||||
try {
|
||||
const respuesta = await fetch('/api/actual');
|
||||
const datos = await respuesta.json();
|
||||
|
||||
if (datos.estado === "desconectado" || datos.estado === "error") {
|
||||
const mensajeError = `<span class="error-desconectado">⚠️ Desconectado</span>`;
|
||||
document.querySelectorAll('.valor-tarjeta').forEach(el => el.innerHTML = mensajeError);
|
||||
document.getElementById('franja-ica').innerText = "Error: Sensores Desconectados";
|
||||
document.getElementById('franja-ica').style.background = "linear-gradient(135deg, #86868b, #6e6e73)";
|
||||
return;
|
||||
}
|
||||
|
||||
document.getElementById('valor-co').innerHTML = `${datos.CO} <span class="unidad">ppm</span>`;
|
||||
document.getElementById('valor-o3').innerHTML = `${datos.O3} <span class="unidad">ppm</span>`;
|
||||
document.getElementById('valor-no2').innerHTML = `${datos.NO2} <span class="unidad">ppm</span>`;
|
||||
document.getElementById('valor-so2').innerHTML = `${datos.SO2} <span class="unidad">ppm</span>`;
|
||||
document.getElementById('valor-temp').innerHTML = `${datos.TEMP} <span class="unidad">°C</span>`;
|
||||
document.getElementById('valor-hum').innerHTML = `${datos.HUM} <span class="unidad">%</span>`;
|
||||
document.getElementById('valor-pres').innerHTML = `${datos.PRES} <span class="unidad">hPa</span>`;
|
||||
|
||||
let icaCO = calcularICA(parseFloat(datos.CO), "CO");
|
||||
let icaO3 = calcularICA(parseFloat(datos.O3), "O3");
|
||||
let icaNO2 = calcularICA(parseFloat(datos.NO2), "NO2");
|
||||
let icaSO2 = calcularICA(parseFloat(datos.SO2), "SO2");
|
||||
|
||||
let icaMaximo = Math.max(icaCO, icaO3, icaNO2, icaSO2);
|
||||
let banda = obtenerColorBanda(icaMaximo);
|
||||
|
||||
let franja = document.getElementById('franja-ica');
|
||||
franja.style.background = banda.color;
|
||||
franja.innerText = `Calidad del Aire: ${banda.texto} (ICA: ${icaMaximo})`;
|
||||
|
||||
if(graficaComparativa) graficaComparativa.destroy();
|
||||
const ctxComp = document.getElementById('graficaComparativaICA').getContext('2d');
|
||||
graficaComparativa = new Chart(ctxComp, {
|
||||
type: 'bar',
|
||||
data: {
|
||||
labels: ['Monóxido de Carbono', 'Ozono', 'Dióxido de Nitrógeno', 'Dióxido de Azufre'],
|
||||
datasets: [{
|
||||
label: 'Índice ICA Individual',
|
||||
data: [icaCO, icaO3, icaNO2, icaSO2],
|
||||
backgroundColor: ['#0071e3', '#34c759', '#ff9500', '#ff3b30'],
|
||||
borderRadius: 12, // Bordes más redondeados
|
||||
borderSkipped: false
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
plugins: { legend: { display: false } },
|
||||
scales: {
|
||||
y: { beginAtZero: true, suggestedMax: 150, grid: { color: '#f0f0f5' } },
|
||||
x: { grid: { display: false } }
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
} catch (error) { console.error("Error de conexión:", error); }
|
||||
}
|
||||
|
||||
setInterval(obtenerDatosActuales, 10000);
|
||||
obtenerDatosActuales();
|
||||
|
||||
// --- 3. GRÁFICAS HISTÓRICAS INDIVIDUALES ---
|
||||
let historicas = {};
|
||||
|
||||
function renderizarGraficaIndividual(idCanvas, etiquetas, datos, label, colorHex) {
|
||||
if (historicas[idCanvas]) { historicas[idCanvas].destroy(); }
|
||||
const ctx = document.getElementById(idCanvas).getContext('2d');
|
||||
|
||||
// Crear gradiente para el relleno debajo de la línea
|
||||
let gradient = ctx.createLinearGradient(0, 0, 0, 400);
|
||||
gradient.addColorStop(0, colorHex + '66'); // 40% opacidad
|
||||
gradient.addColorStop(1, colorHex + '00'); // Transparente
|
||||
|
||||
historicas[idCanvas] = new Chart(ctx, {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: etiquetas.length > 0 ? etiquetas : ['Sin datos'],
|
||||
datasets: [{
|
||||
label: label,
|
||||
data: datos.length > 0 ? datos : [0],
|
||||
borderColor: colorHex,
|
||||
backgroundColor: gradient, // Relleno degradado moderno
|
||||
borderWidth: 3, // Línea un poco más gruesa
|
||||
tension: 0.4,
|
||||
fill: true,
|
||||
pointBackgroundColor: '#ffffff',
|
||||
pointBorderColor: colorHex,
|
||||
pointBorderWidth: 2
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
aspectRatio: 2.5,
|
||||
plugins: {
|
||||
legend: { display: false },
|
||||
title: { display: false },
|
||||
tooltip: {
|
||||
backgroundColor: 'rgba(255, 255, 255, 0.9)',
|
||||
titleColor: '#1d1d1f',
|
||||
bodyColor: '#1d1d1f',
|
||||
borderColor: 'rgba(0,0,0,0.1)',
|
||||
borderWidth: 1,
|
||||
padding: 12,
|
||||
boxPadding: 6,
|
||||
usePointStyle: true
|
||||
}
|
||||
},
|
||||
scales: {
|
||||
x: {
|
||||
display: true,
|
||||
title: { display: true, text: 'Fecha y Hora', color: '#86868b', font: { weight: '600', size: 13 } },
|
||||
grid: { display: false }, // Limpieza visual en eje X
|
||||
border: { display: true, color: '#e5e5ea', width: 2 },
|
||||
ticks: { display: true, color: '#86868b', maxTicksLimit: 10, maxRotation: 45, minRotation: 45, font: {size: 11} }
|
||||
},
|
||||
y: {
|
||||
display: true,
|
||||
title: { display: true, text: label, color: '#86868b', font: { weight: '600', size: 13 } },
|
||||
grid: { display: true, color: '#f0f0f5', drawOnChartArea: true, drawTicks: false },
|
||||
border: { display: false }, // Ocultar borde Y para un look más abierto
|
||||
ticks: { display: true, color: '#86868b', font: {size: 11}, padding: 10 },
|
||||
beginAtZero: true
|
||||
}
|
||||
},
|
||||
elements: { point: { radius: 0, hitRadius: 15, hoverRadius: 6 } }, // Puntos invisibles hasta hacer hover
|
||||
interaction: { mode: 'index', intersect: false }
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function gestionarSelector() {
|
||||
const rango = document.getElementById('selector-rango').value;
|
||||
const divPersonalizado = document.getElementById('rango-personalizado');
|
||||
|
||||
if (rango === 'personalizado') {
|
||||
divPersonalizado.style.display = 'flex';
|
||||
} else {
|
||||
divPersonalizado.style.display = 'none';
|
||||
actualizarGrafica();
|
||||
}
|
||||
}
|
||||
|
||||
async function actualizarGrafica() {
|
||||
const rango = document.getElementById('selector-rango').value;
|
||||
let urlAPI = `/api/historial?rango=${rango}`;
|
||||
|
||||
if (rango === 'personalizado') {
|
||||
const inicio = document.getElementById('fecha-inicio').value;
|
||||
const fin = document.getElementById('fecha-fin').value;
|
||||
if (!inicio || !fin) {
|
||||
alert("Por favor, selecciona una fecha de inicio y una de fin.");
|
||||
return;
|
||||
}
|
||||
urlAPI += `&inicio=${inicio}&fin=${fin}`;
|
||||
}
|
||||
|
||||
const respuesta = await fetch(urlAPI);
|
||||
const datosHistorial = await respuesta.json();
|
||||
|
||||
datosGlobalesParaExportar = datosHistorial;
|
||||
|
||||
if (datosHistorial.length === 0) {
|
||||
alert("La base de datos no tiene registros para este rango de fechas.");
|
||||
}
|
||||
|
||||
const fechas = datosHistorial.map(f => f.fecha_hora);
|
||||
|
||||
renderizarGraficaIndividual('graficaCO', fechas, datosHistorial.map(f => f.co), 'Monóxido de Carbono (ppm)', '#0071e3');
|
||||
renderizarGraficaIndividual('graficaO3', fechas, datosHistorial.map(f => f.ozono), 'Ozono (ppm)', '#34c759');
|
||||
renderizarGraficaIndividual('graficaNO2', fechas, datosHistorial.map(f => f.no2), 'Dióxido de Nitrógeno (ppm)', '#ff9500');
|
||||
renderizarGraficaIndividual('graficaSO2', fechas, datosHistorial.map(f => f.so2), 'Dióxido de Azufre (ppm)', '#ff3b30');
|
||||
renderizarGraficaIndividual('graficaTemp', fechas, datosHistorial.map(f => f.temperatura), 'Temperatura (°C)', '#ffcc00');
|
||||
renderizarGraficaIndividual('graficaHum', fechas, datosHistorial.map(f => f.humedad), 'Humedad (%)', '#5ac8fa');
|
||||
renderizarGraficaIndividual('graficaPres', fechas, datosHistorial.map(f => f.presion), 'Presión Atmosférica (hPa)', '#5856d6');
|
||||
}
|
||||
|
||||
// --- 4. FUNCIÓN PARA EXPORTAR A CSV (EXCEL) ---
|
||||
function exportarCSV() {
|
||||
if (datosGlobalesParaExportar.length === 0) {
|
||||
alert("No hay datos disponibles para exportar en este rango.");
|
||||
return;
|
||||
}
|
||||
let contenidoCSV = "Fecha y Hora,CO (ppm),O3 (ppm),NO2 (ppm),SO2 (ppm),Temperatura (C),Humedad (%),Presion Atmosferica (hPa)\n";
|
||||
datosGlobalesParaExportar.forEach(fila => {
|
||||
contenidoCSV += `${fila.fecha_hora},${fila.co},${fila.ozono},${fila.no2},${fila.so2},${fila.temperatura},${fila.humedad},${fila.presion}\n`;
|
||||
});
|
||||
const blob = new Blob([contenidoCSV], { type: 'text/csv;charset=utf-8;' });
|
||||
const url = URL.createObjectURL(blob);
|
||||
const enlaceVirtual = document.createElement("a");
|
||||
enlaceVirtual.setAttribute("href", url);
|
||||
enlaceVirtual.setAttribute("download", "Historial_Calidad_Aire.csv");
|
||||
document.body.appendChild(enlaceVirtual);
|
||||
enlaceVirtual.click();
|
||||
document.body.removeChild(enlaceVirtual);
|
||||
}
|
||||
|
||||
// --- 5. FUNCIÓN PARA EXPORTAR A EXCEL (.XLSX) ---
|
||||
function exportarExcel() {
|
||||
if (datosGlobalesParaExportar.length === 0) {
|
||||
alert("No hay datos disponibles para exportar en este rango.");
|
||||
return;
|
||||
}
|
||||
const datosFormateados = datosGlobalesParaExportar.map(fila => ({
|
||||
"Fecha y Hora": fila.fecha_hora,
|
||||
"CO (ppm)": fila.co,
|
||||
"Ozono - O3 (ppm)": fila.ozono,
|
||||
"Dióxido de Nitrógeno - NO2 (ppm)": fila.no2,
|
||||
"Dióxido de Azufre - SO2 (ppm)": fila.so2,
|
||||
"Temperatura (°C)": fila.temperatura,
|
||||
"Humedad (%)": fila.humedad,
|
||||
"Presión Atmosférica (hPa)": fila.presion
|
||||
}));
|
||||
const hoja = XLSX.utils.json_to_sheet(datosFormateados);
|
||||
const libro = XLSX.utils.book_new();
|
||||
XLSX.utils.book_append_sheet(libro, hoja, "Calidad del Aire");
|
||||
XLSX.writeFile(libro, "Historial_Calidad_Aire.xlsx");
|
||||
}
|
||||
|
||||
// --- 6. LÓGICA DE LA MINITERMINAL ---
|
||||
function manejarEnterTerminal(event) {
|
||||
if (event.key === "Enter") {
|
||||
ejecutarComando();
|
||||
}
|
||||
}
|
||||
|
||||
async function ejecutarComando() {
|
||||
const inputElement = document.getElementById('terminal-input');
|
||||
const salidaElement = document.getElementById('terminal-salida');
|
||||
const comando = inputElement.value.trim();
|
||||
|
||||
if (!comando) return;
|
||||
|
||||
salidaElement.innerHTML += `\n<span style="color: #ffffff;">$ ${comando}</span>\n`;
|
||||
inputElement.value = "";
|
||||
salidaElement.scrollTop = salidaElement.scrollHeight;
|
||||
|
||||
try {
|
||||
const respuesta = await fetch('/api/ejecutar', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ comando: comando })
|
||||
});
|
||||
|
||||
const datos = await respuesta.json();
|
||||
|
||||
if (datos.error && datos.error !== "") {
|
||||
salidaElement.innerHTML += `<span style="color: #ff5f56;">${datos.error}</span>`;
|
||||
} else if (datos.salida && datos.salida !== "") {
|
||||
salidaElement.innerHTML += `${datos.salida}`;
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
salidaElement.innerHTML += `<span style="color: #ff5f56;">Error de comunicación con el servidor.</span>\n`;
|
||||
}
|
||||
|
||||
salidaElement.scrollTop = salidaElement.scrollHeight;
|
||||
}
|
||||
|
||||
actualizarGrafica();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@ -0,0 +1,152 @@
|
||||
from flask import Flask, jsonify, request
|
||||
from flask_cors import CORS
|
||||
import sqlite3
|
||||
import os
|
||||
import time
|
||||
import threading
|
||||
|
||||
app = Flask(__name__)
|
||||
CORS(app) # Permite que la página web consulte este servidor
|
||||
|
||||
RUTA_ACTUAL = "/dev/shm/aql_actual.txt"
|
||||
RUTA_BD = "/home/pi/microestacion.db"
|
||||
|
||||
|
||||
# --- LÓGICA DE LA NOM-172-SEMARNAT-2019 ---
|
||||
|
||||
def calcular_ica_individual(cp, gas):
|
||||
# Tablas de cortes (Breakpoints) según la NOM-172
|
||||
# Estructura: [BP_low, BP_high, Index_low, Index_high]
|
||||
breakpoints = {
|
||||
"O3": [(0.0, 0.051, 0, 50), (0.052, 0.070, 51, 100), (0.071, 0.092, 101, 150), (0.093, 0.114, 151, 200), (0.115, 10.0, 201, 500)],
|
||||
"CO": [(0.0, 8.74, 0, 50), (8.75, 11.00, 51, 100), (11.01, 13.30, 101, 150), (13.31, 15.50, 151, 200), (15.51, 100.0, 201, 500)],
|
||||
"SO2": [(0.0, 0.008, 0, 50), (0.009, 0.110, 51, 100), (0.111, 0.165, 101, 150), (0.166, 0.220, 151, 200), (0.221, 10.0, 201, 500)],
|
||||
"NO2": [(0.0, 0.107, 0, 50), (0.108, 0.210, 51, 100), (0.211, 0.230, 101, 150), (0.231, 0.250, 151, 200), (0.251, 10.0, 201, 500)]
|
||||
}
|
||||
|
||||
if gas not in breakpoints:
|
||||
return 0
|
||||
|
||||
for bp in breakpoints[gas]:
|
||||
bp_lo, bp_hi, i_lo, i_hi = bp
|
||||
if bp_lo <= cp <= bp_hi:
|
||||
# Fórmula de interpolación lineal oficial
|
||||
ica = ((i_hi - i_lo) / (bp_hi - bp_lo)) * (cp - bp_lo) + i_lo
|
||||
return round(ica)
|
||||
|
||||
# Si sobrepasa el límite máximo establecido (Caso extremo)
|
||||
return 500
|
||||
|
||||
def obtener_banda_ica(ica):
|
||||
if ica <= 50: return "Buena"
|
||||
elif ica <= 100: return "Aceptable"
|
||||
elif ica <= 150: return "Mala"
|
||||
elif ica <= 200: return "Muy Mala"
|
||||
else: return "Extremadamente Mala"
|
||||
|
||||
def procesador_ica_background():
|
||||
"""Hilo que corre en segundo plano calculando el ICA de los nuevos registros"""
|
||||
while True:
|
||||
try:
|
||||
conexion = sqlite3.connect(RUTA_BD)
|
||||
cursor = conexion.cursor()
|
||||
|
||||
# Buscamos todas las filas que el programa C acaba de insertar (ica es NULL)
|
||||
cursor.execute("SELECT id, ozono, no2, co, so2 FROM mediciones WHERE ica IS NULL")
|
||||
filas_pendientes = cursor.fetchall()
|
||||
|
||||
for fila in filas_pendientes:
|
||||
id_fila = fila[0]
|
||||
|
||||
# Calculamos el ICA de cada contaminante por separado
|
||||
ica_o3 = calcular_ica_individual(fila[1], "O3")
|
||||
ica_no2 = calcular_ica_individual(fila[2], "NO2")
|
||||
ica_co = calcular_ica_individual(fila[3], "CO")
|
||||
ica_so2 = calcular_ica_individual(fila[4], "SO2")
|
||||
|
||||
# La norma dicta que el ICA global es el valor máximo encontrado
|
||||
ica_global = max(ica_o3, ica_no2, ica_co, ica_so2)
|
||||
banda = obtener_banda_ica(ica_global)
|
||||
|
||||
# Actualizamos la fila en la base de datos con el cálculo final
|
||||
cursor.execute("UPDATE mediciones SET ica = ?, banda_ica = ? WHERE id = ?", (ica_global, banda, id_fila))
|
||||
|
||||
conexion.commit()
|
||||
conexion.close()
|
||||
except Exception as e:
|
||||
print(f"Error procesando ICA: {e}")
|
||||
|
||||
# Esperamos 30 segundos antes de volver a revisar la base de datos
|
||||
time.sleep(30)
|
||||
|
||||
# Función 1: Obtener datos en tiempo real
|
||||
@app.route('/api/actual')
|
||||
def obtener_actual():
|
||||
datos = {"estado": "ok"}
|
||||
|
||||
# Validamos si el archivo existe
|
||||
if not os.path.exists(RUTA_ACTUAL):
|
||||
return jsonify({"estado": "error", "mensaje": "Archivo no encontrado"})
|
||||
|
||||
# Validamos si el programa en C se detuvo (Si el archivo tiene más de 20 segundos sin modificarse)
|
||||
tiempo_modificacion = os.path.getmtime(RUTA_ACTUAL)
|
||||
if (time.time() - tiempo_modificacion) > 20:
|
||||
return jsonify({"estado": "desconectado"}) # Esto activará el mensaje de "Desconectado" en la web
|
||||
|
||||
# Leemos el archivo línea por línea
|
||||
with open(RUTA_ACTUAL, 'r') as f:
|
||||
for linea in f:
|
||||
if '=' in linea:
|
||||
clave, valor = linea.strip().split('=', 1)
|
||||
datos[clave] = valor.replace('"', '') # Limpiamos comillas de la fecha
|
||||
|
||||
return jsonify(datos)
|
||||
|
||||
# Función 2: Obtener historial para las gráficas
|
||||
@app.route('/api/historial')
|
||||
def obtener_historial():
|
||||
rango = request.args.get('rango', '1_mes') # Por defecto lee el último mes
|
||||
|
||||
conexion = sqlite3.connect(RUTA_BD)
|
||||
conexion.row_factory = sqlite3.Row # Permite acceder a las columnas por nombre
|
||||
cursor = conexion.cursor()
|
||||
|
||||
# Si el usuario eligió fechas personalizadas
|
||||
if rango == 'personalizado':
|
||||
inicio = request.args.get('inicio')
|
||||
fin = request.args.get('fin')
|
||||
|
||||
# Usamos ? para inyectar las variables de forma segura
|
||||
consulta = "SELECT fecha_hora, presion, temperatura, humedad, ozono, no2, co, so2 FROM mediciones WHERE fecha_hora BETWEEN ? AND ? ORDER BY fecha_hora ASC"
|
||||
# Agregamos las horas al inicio y al fin para abarcar los días completos
|
||||
cursor.execute(consulta, (f"{inicio} 00:00:00", f"{fin} 23:59:59"))
|
||||
|
||||
# Si eligió los rangos predefinidos
|
||||
else:
|
||||
filtro_fecha = ""
|
||||
if rango == '1_mes':
|
||||
filtro_fecha = "date('now', '-1 month')"
|
||||
elif rango == '2_meses':
|
||||
filtro_fecha = "date('now', '-2 months')"
|
||||
elif rango == '1_anio':
|
||||
filtro_fecha = "date('now', '-1 year')"
|
||||
|
||||
consulta = f"SELECT fecha_hora, presion, temperatura, humedad, ozono, no2, co, so2 FROM mediciones WHERE fecha_hora >= {filtro_fecha} ORDER BY fecha_hora ASC"
|
||||
cursor.execute(consulta)
|
||||
|
||||
filas = cursor.fetchall()
|
||||
conexion.close()
|
||||
|
||||
# Convertimos los resultados de SQLite a una lista de diccionarios (JSON)
|
||||
resultado = [dict(fila) for fila in filas]
|
||||
return jsonify(resultado)
|
||||
|
||||
|
||||
|
||||
# --- ARRANQUE DEL SERVIDOR Y EL HILO ---
|
||||
if __name__ == '__main__':
|
||||
# Iniciamos el procesador de ICA en un hilo paralelo para que no bloquee el servidor web
|
||||
hilo_ica = threading.Thread(target=procesador_ica_background, daemon=True)
|
||||
hilo_ica.start()
|
||||
|
||||
app.run(host='0.0.0.0', port=5000)
|
||||
@ -0,0 +1,179 @@
|
||||
from flask import Flask, jsonify, request
|
||||
from flask_cors import CORS
|
||||
import sqlite3
|
||||
import os
|
||||
import time
|
||||
import threading
|
||||
import subprocess # NUEVO: Librería para ejecutar comandos en la terminal
|
||||
|
||||
app = Flask(__name__)
|
||||
CORS(app) # Permite que la página web consulte este servidor
|
||||
|
||||
RUTA_ACTUAL = "/dev/shm/aql_actual.txt"
|
||||
RUTA_BD = "/home/pi/microestacion.db"
|
||||
|
||||
|
||||
# --- LÓGICA DE LA NOM-172-SEMARNAT-2019 ---
|
||||
|
||||
def calcular_ica_individual(cp, gas):
|
||||
# Tablas de cortes (Breakpoints) según la NOM-172
|
||||
# Estructura: [BP_low, BP_high, Index_low, Index_high]
|
||||
breakpoints = {
|
||||
"O3": [(0.0, 0.051, 0, 50), (0.052, 0.070, 51, 100), (0.071, 0.092, 101, 150), (0.093, 0.114, 151, 200), (0.115, 10.0, 201, 500)],
|
||||
"CO": [(0.0, 8.74, 0, 50), (8.75, 11.00, 51, 100), (11.01, 13.30, 101, 150), (13.31, 15.50, 151, 200), (15.51, 100.0, 201, 500)],
|
||||
"SO2": [(0.0, 0.008, 0, 50), (0.009, 0.110, 51, 100), (0.111, 0.165, 101, 150), (0.166, 0.220, 151, 200), (0.221, 10.0, 201, 500)],
|
||||
"NO2": [(0.0, 0.107, 0, 50), (0.108, 0.210, 51, 100), (0.211, 0.230, 101, 150), (0.231, 0.250, 151, 200), (0.251, 10.0, 201, 500)]
|
||||
}
|
||||
|
||||
if gas not in breakpoints:
|
||||
return 0
|
||||
|
||||
for bp in breakpoints[gas]:
|
||||
bp_lo, bp_hi, i_lo, i_hi = bp
|
||||
if bp_lo <= cp <= bp_hi:
|
||||
# Fórmula de interpolación lineal oficial
|
||||
ica = ((i_hi - i_lo) / (bp_hi - bp_lo)) * (cp - bp_lo) + i_lo
|
||||
return round(ica)
|
||||
|
||||
# Si sobrepasa el límite máximo establecido (Caso extremo)
|
||||
return 500
|
||||
|
||||
def obtener_banda_ica(ica):
|
||||
if ica <= 50: return "Buena"
|
||||
elif ica <= 100: return "Aceptable"
|
||||
elif ica <= 150: return "Mala"
|
||||
elif ica <= 200: return "Muy Mala"
|
||||
else: return "Extremadamente Mala"
|
||||
|
||||
def procesador_ica_background():
|
||||
"""Hilo que corre en segundo plano calculando el ICA de los nuevos registros"""
|
||||
while True:
|
||||
try:
|
||||
conexion = sqlite3.connect(RUTA_BD)
|
||||
cursor = conexion.cursor()
|
||||
|
||||
# Buscamos todas las filas que el programa C acaba de insertar (ica es NULL)
|
||||
cursor.execute("SELECT id, ozono, no2, co, so2 FROM mediciones WHERE ica IS NULL")
|
||||
filas_pendientes = cursor.fetchall()
|
||||
|
||||
for fila in filas_pendientes:
|
||||
id_fila = fila[0]
|
||||
|
||||
# Calculamos el ICA de cada contaminante por separado
|
||||
ica_o3 = calcular_ica_individual(fila[1], "O3")
|
||||
ica_no2 = calcular_ica_individual(fila[2], "NO2")
|
||||
ica_co = calcular_ica_individual(fila[3], "CO")
|
||||
ica_so2 = calcular_ica_individual(fila[4], "SO2")
|
||||
|
||||
# La norma dicta que el ICA global es el valor máximo encontrado
|
||||
ica_global = max(ica_o3, ica_no2, ica_co, ica_so2)
|
||||
banda = obtener_banda_ica(ica_global)
|
||||
|
||||
# Actualizamos la fila en la base de datos con el cálculo final
|
||||
cursor.execute("UPDATE mediciones SET ica = ?, banda_ica = ? WHERE id = ?", (ica_global, banda, id_fila))
|
||||
|
||||
conexion.commit()
|
||||
conexion.close()
|
||||
except Exception as e:
|
||||
print(f"Error procesando ICA: {e}")
|
||||
|
||||
# Esperamos 30 segundos antes de volver a revisar la base de datos
|
||||
time.sleep(30)
|
||||
|
||||
# Función 1: Obtener datos en tiempo real
|
||||
@app.route('/api/actual')
|
||||
def obtener_actual():
|
||||
datos = {"estado": "ok"}
|
||||
|
||||
# Validamos si el archivo existe
|
||||
if not os.path.exists(RUTA_ACTUAL):
|
||||
return jsonify({"estado": "error", "mensaje": "Archivo no encontrado"})
|
||||
|
||||
# Validamos si el programa en C se detuvo (Si el archivo tiene más de 20 segundos sin modificarse)
|
||||
tiempo_modificacion = os.path.getmtime(RUTA_ACTUAL)
|
||||
if (time.time() - tiempo_modificacion) > 20:
|
||||
return jsonify({"estado": "desconectado"}) # Esto activará el mensaje de "Desconectado" en la web
|
||||
|
||||
# Leemos el archivo línea por línea
|
||||
with open(RUTA_ACTUAL, 'r') as f:
|
||||
for linea in f:
|
||||
if '=' in linea:
|
||||
clave, valor = linea.strip().split('=', 1)
|
||||
datos[clave] = valor.replace('"', '') # Limpiamos comillas de la fecha
|
||||
|
||||
return jsonify(datos)
|
||||
|
||||
# Función 2: Obtener historial para las gráficas
|
||||
@app.route('/api/historial')
|
||||
def obtener_historial():
|
||||
rango = request.args.get('rango', '1_mes') # Por defecto lee el último mes
|
||||
|
||||
conexion = sqlite3.connect(RUTA_BD)
|
||||
conexion.row_factory = sqlite3.Row # Permite acceder a las columnas por nombre
|
||||
cursor = conexion.cursor()
|
||||
|
||||
# Si el usuario eligió fechas personalizadas
|
||||
if rango == 'personalizado':
|
||||
inicio = request.args.get('inicio')
|
||||
fin = request.args.get('fin')
|
||||
|
||||
# Usamos ? para inyectar las variables de forma segura
|
||||
consulta = "SELECT fecha_hora, presion, temperatura, humedad, ozono, no2, co, so2 FROM mediciones WHERE fecha_hora BETWEEN ? AND ? ORDER BY fecha_hora ASC"
|
||||
# Agregamos las horas al inicio y al fin para abarcar los días completos
|
||||
cursor.execute(consulta, (f"{inicio} 00:00:00", f"{fin} 23:59:59"))
|
||||
|
||||
# Si eligió los rangos predefinidos
|
||||
else:
|
||||
filtro_fecha = ""
|
||||
if rango == '1_mes':
|
||||
filtro_fecha = "date('now', '-1 month')"
|
||||
elif rango == '2_meses':
|
||||
filtro_fecha = "date('now', '-2 months')"
|
||||
elif rango == '1_anio':
|
||||
filtro_fecha = "date('now', '-1 year')"
|
||||
|
||||
consulta = f"SELECT fecha_hora, presion, temperatura, humedad, ozono, no2, co, so2 FROM mediciones WHERE fecha_hora >= {filtro_fecha} ORDER BY fecha_hora ASC"
|
||||
cursor.execute(consulta)
|
||||
|
||||
filas = cursor.fetchall()
|
||||
conexion.close()
|
||||
|
||||
# Convertimos los resultados de SQLite a una lista de diccionarios (JSON)
|
||||
resultado = [dict(fila) for fila in filas]
|
||||
return jsonify(resultado)
|
||||
|
||||
# Función 3: Terminal Remota (Ejecutar comandos)
|
||||
@app.route('/api/ejecutar', methods=['POST'])
|
||||
def ejecutar_comando():
|
||||
datos = request.get_json()
|
||||
comando = datos.get('comando', '')
|
||||
|
||||
if not comando:
|
||||
return jsonify({'salida': '', 'error': 'No se proporcionó ningún comando.'})
|
||||
|
||||
try:
|
||||
# Ejecutar el comando en el shell de la Raspberry Pi
|
||||
# Se captura la salida normal (stdout) y los errores (stderr)
|
||||
resultado = subprocess.run(comando, shell=True, capture_output=True, text=True, timeout=10)
|
||||
|
||||
salida = resultado.stdout
|
||||
error = resultado.stderr
|
||||
|
||||
# Combinar salida y error (Priorizar mostrar el error si existe)
|
||||
respuesta = error if error else salida
|
||||
|
||||
return jsonify({'salida': respuesta, 'error': ''})
|
||||
except subprocess.TimeoutExpired:
|
||||
return jsonify({'salida': '', 'error': 'El comando tardó demasiado en ejecutarse (Timeout).'})
|
||||
except Exception as e:
|
||||
return jsonify({'salida': '', 'error': str(e)})
|
||||
|
||||
|
||||
|
||||
# --- ARRANQUE DEL SERVIDOR Y EL HILO ---
|
||||
if __name__ == '__main__':
|
||||
# Iniciamos el procesador de ICA en un hilo paralelo para que no bloquee el servidor web
|
||||
hilo_ica = threading.Thread(target=procesador_ica_background, daemon=True)
|
||||
hilo_ica.start()
|
||||
|
||||
app.run(host='0.0.0.0', port=5000)
|
||||
Loading…
Reference in New Issue