Подключение датчика BME280 к Orange Pi

BME280 — это интегрированный датчик окружающей среды давления, влажности и температуры, сочетающий высокую линейность, высокую точность и низкое энергопотребление. Датчик влажности имеет чрезвычайно быстрое время отклика. Датчик давления является абсолютным барометрическим датчиком давления с функциями исключительно высокой точности и разрешения при очень низком уровне шума. Встроенный датчик температуры оптимизирован для очень низкого уровня шума и высокого разрешения. Он в основном используется для температурной компенсации датчиков давления и влажности, а также может использоваться для оценки температуры окружающей среды.

Подключение датчика

BME280 поддерживает цифровые интерфейсы I²C и SPI;

Интерфейс I²C поддерживает стандартные, быстрые и высокоскоростные режимы. Интерфейс SPI поддерживает режим SPI ’00’ (CPOL = CPHA = ‘0’) и режим ’11’ (CPOL = CPHA = ‘1’) в 4-проводной и 3-проводной конфигурации.

Интерфейс I²C использует следующие контакты:

  • SCK: serial clock (SCL)
  • SDI: data (SDA)
  • SDO: Slave address LSB (GND = ‘0’, VDDIO = ‘1’)

Подключение SDO к GND приводит к ведомому адресу 1110110 (0x76); подключение его к VDDIO приводит к ведомому адресу 1110111 (0x77), который совпадает с адресом I²C BMP280. Штырь SDO не может оставаться плавающим; если он оставлен плавающим, адрес I²C будет не определен.

Исходник bme280_p.c

// Distributed with a free-will license.
// Use it any way you want, profit or free, provided it fits in the licenses of its associated works.
// BME280
// This code is designed to work with the BME280 sensor with I2C Interface

#include <stdio.h>
#include <stdlib.h>
#include <linux/i2c-dev.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <getopt.h>
#include <unistd.h>

//void main()
//{

void print_usage() {
    printf("Usage: bme280_p -[ahCFH] -P[factor]\n");
    printf("Usage: bme280_p -a all parms verbose\n");
    printf("Usage: bme280_p -C Temp value in Celsius\n");
    printf("Usage: bme280_p -F Temp value in Fahrenheit\n");
    printf("Usage: bme280_p -H Humidity value in %%RH\n");
    printf("Usage: bme280_p -P[factor] Pressure value in hPa * factor\n");
}

int main(int argc, char *argv[]) {
    int option = 0;
      float fact = 1.0;
      float fpressure;

        // Create I2C bus
        int file;
        char *bus = "/dev/i2c-1";
        if((file = open(bus, O_RDWR)) < 0) 
        {
                printf("Failed to open the bus. \n");
                exit(1);
        }
        // Get I2C device, BME280 I2C address is 0x76(136)
        ioctl(file, I2C_SLAVE, 0x76);

        // Read 24 bytes of data from register(0x88)
        char reg[1] = {0x88};
        write(file, reg, 1);
        char b1[24] = {0};
        if(read(file, b1, 24) != 24)
        {
                printf("Error : Input/Output error \n");
                exit(1);
        }

        // Convert the data
        // temp coefficents
        int dig_T1 = (b1[0] + b1[1] * 256);
        int dig_T2 = (b1[2] + b1[3] * 256);
        if(dig_T2 > 32767)
        {
                dig_T2 -= 65536;
        }
        int dig_T3 = (b1[4] + b1[5] * 256);
        if(dig_T3 > 32767)
        {
                dig_T3 -= 65536;
        }

        // pressure coefficents
        int dig_P1 = (b1[6] + b1[7] * 256);
        int dig_P2 = (b1[8] + b1[9] * 256);
        if(dig_P2 > 32767)
        {
                dig_P2 -= 65536;
        }
        int dig_P3 = (b1[10] + b1[11] * 256);
        if(dig_P3 > 32767)
        {
                dig_P3 -= 65536;
        }
        int dig_P4 = (b1[12] + b1[13] * 256);
        if(dig_P4 > 32767)
        {
                dig_P4 -= 65536;
        }
        int dig_P5 = (b1[14] + b1[15] * 256);
        if(dig_P5 > 32767)
        {
        dig_P5 -= 65536;
        }
        int dig_P6 = (b1[16] + b1[17] * 256);
        if(dig_P6 > 32767)
        {
                dig_P6 -= 65536;
        }
        int dig_P7 = (b1[18] + b1[19] * 256);
        if(dig_P7 > 32767)
        {
                dig_P7 -= 65536;
        }
        int dig_P8 = (b1[20] + b1[21] * 256);
        if(dig_P8 > 32767)
        {
        dig_P8 -= 65536;
        }
        int dig_P9 = (b1[22] + b1[23] * 256);
        if(dig_P9 > 32767)
        {
                dig_P9 -= 65536;
        }

        // Read 1 byte of data from register(0xA1)
        reg[0] = 0xA1;
        write(file, reg, 1);
        char data[8] = {0};
        read(file, data, 1);
        int dig_H1 = data[0];

        // Read 7 bytes of data from register(0xE1)
        reg[0] = 0xE1;
        write(file, reg, 1);
        read(file, b1, 7);

        // Convert the data
        // humidity coefficents
        int dig_H2 = (b1[0] + b1[1] * 256);
        if(dig_H2 > 32767)
        {
                dig_H2 -= 65536;
        }
        int dig_H3 = b1[2] & 0xFF ;
        int dig_H4 = (b1[3] * 16 + (b1[4] & 0xF));
        if(dig_H4 > 32767)
        {
                dig_H4 -= 65536;
        }
        int dig_H5 = (b1[4] / 16) + (b1[5] * 16);
        if(dig_H5 > 32767)
        {
                dig_H5 -= 65536;
        }
        int dig_H6 = b1[6];
        if(dig_H6 > 127)
        {
                dig_H6 -= 256;
        }

        // Select control humidity register(0xF2)
        // Humidity over sampling rate = 1(0x01)
        char config[2] = {0};
        config[0] = 0xF2;
        config[1] = 0x01;
        write(file, config, 2);
        // Select control measurement register(0xF4)
        // Normal mode, temp and pressure over sampling rate = 1(0x27)
        config[0] = 0xF4;
        config[1] = 0x27;
        write(file, config, 2);
        // Select config register(0xF5)
        // Stand_by time = 1000 ms(0xA0)
        config[0] = 0xF5;
        config[1] = 0xA0;
        write(file, config, 2);

        // Read 8 bytes of data from register(0xF7)
        // pressure msb1, pressure msb, pressure lsb, temp msb1, temp msb, temp lsb, humidity lsb, humidity msb
        reg[0] = 0xF7;
        write(file, reg, 1);
        read(file, data, 8);

        // Convert pressure and temperature data to 19-bits
        long adc_p = ((long)(data[0] * 65536 + ((long)(data[1] * 256) + (long)(data[2] & 0xF0)))) / 16;
        long adc_t = ((long)(data[3] * 65536 + ((long)(data[4] * 256) + (long)(data[5] & 0xF0)))) / 16;
        // Convert the humidity data
        long adc_h = (data[6] * 256 + data[7]);

        // Temperature offset calculations
        float var1 = (((float)adc_t) / 16384.0 - ((float)dig_T1) / 1024.0) * ((float)dig_T2);
        float var2 = ((((float)adc_t) / 131072.0 - ((float)dig_T1) / 8192.0) *
                                        (((float)adc_t)/131072.0 - ((float)dig_T1)/8192.0)) * ((float)dig_T3);
        float t_fine = (long)(var1 + var2);
        float cTemp = (var1 + var2) / 5120.0;
        float fTemp = cTemp * 1.8 + 32;

        // Pressure offset calculations
        var1 = ((float)t_fine / 2.0) - 64000.0;
        var2 = var1 * var1 * ((float)dig_P6) / 32768.0;
        var2 = var2 + var1 * ((float)dig_P5) * 2.0;
        var2 = (var2 / 4.0) + (((float)dig_P4) * 65536.0);
        var1 = (((float) dig_P3) * var1 * var1 / 524288.0 + ((float) dig_P2) * var1) / 524288.0;
        var1 = (1.0 + var1 / 32768.0) * ((float)dig_P1);
        float p = 1048576.0 - (float)adc_p;
        p = (p - (var2 / 4096.0)) * 6250.0 / var1;
        var1 = ((float) dig_P9) * p * p / 2147483648.0;
        var2 = p * ((float) dig_P8) / 32768.0;
        float pressure = (p + (var1 + var2 + ((float)dig_P7)) / 16.0) / 100;

        // Humidity offset calculations
        float var_H = (((float)t_fine) - 76800.0);
        var_H = (adc_h - (dig_H4 * 64.0 + dig_H5 / 16384.0 * var_H)) * (dig_H2 / 65536.0 * (1.0 + dig_H6 / 67108864.0 * var_H * (1.0 + dig_H3 / 67108864.0 * var_H)));
        float humidity = var_H * (1.0 -  dig_H1 * var_H / 524288.0);
        if(humidity > 100.0)
        {
                humidity = 100.0;
        }else
        if(humidity < 0.0) 
        {
                humidity = 0.0;
        }

    while ((option = getopt(argc, argv,"ahCFHP::")) != -1) {
        switch (option) {
             case 'a' : 
                 printf("Temperature in Celsius : %.2f C \n", cTemp);
                 printf("Temperature in Fahrenheit : %.2f F \n", fTemp);
                 printf("Pressure : %.2f hPa \n", pressure);
                 printf("Relative Humidity : %.2f %%RH \n", humidity);
                 close(file);
                 exit(0);

             case 'C' : 
                 printf("%.2f \n", cTemp);
                 close(file);
                 exit(0);

             case 'P' :
                 if (optarg != NULL )
                 fact = atof(optarg);
                 else
                 fact = 1;
                 fpressure = fact * pressure;
                 if (fact < 1)
                   printf("%.4f \n", fpressure);
                  else
                   printf("%.2f \n", fpressure);
                 close(file);
                 exit(0);

             case 'H' : 
                 printf("%.2f \n", humidity);
                 close(file);
                 exit(0);

             case 'F' : 
                 printf("%.2f \n", fTemp);
                 close(file);
                 exit(0);

             case 'h' : 
                 print_usage();
                 close(file);
                 exit(0);

             case '?' :
             case ':' :
             default: print_usage(); 
                 exit(EXIT_FAILURE);
        }
    }
        print_usage();
        close(file);
}

Компиляция

gcc  -g -Wall -Wextra -pedantic -std=c11 -o bme280_p bme280_p.c

Запуск программы

./bme280_p 
Usage: bme280_p -[ahCFH] -P[factor]
Usage: bme280_p -a all parms verbose
Usage: bme280_p -C Temp value in Celsius
Usage: bme280_p -F Temp value in Fahrenheit
Usage: bme280_p -H Humidity value in %RH
Usage: bme280_p -P[factor] Pressure value in hPa * factor

./bme280_p -a
Temperature in Celsius : 22.29 C 
Temperature in Fahrenheit : 72.13 F 
Pressure : 1009.53 hPa 
Relative Humidity : 43.52 %RH 

./bme280_p -C
22.30 

 ./bme280_p -F
72.14 

./bme280_p -H
43.53

./bme280_p -P
1009.52

./bme280_p -P1
1009.55

./bme280_p -P10
10095.85

./bme280_p -P0.01
10.0960

На этом всё !

Оставьте комментарий