raspberry pi 3でC言語による環境センサー「BME280」の接続

raspberry pi 3に「BME280を用いたPro Microの温湿度・気圧測定 プログラム」で使用した環境センサー「BME280」を接続し、C言語により温湿度・気圧データを入力してみました。また、固定IPアドレスを割り付けたraspberry pi 3の無線LANを使った場合、apt-get updateがエラーになる場合があり、この解決方法を示します。

raspberry pi 3への環境センサー「BME280」の接続

raspberry pi 3とBME280間で、I2CのSDAとSCLのそれぞれに接続します。BME280のVINにはraspberry piの3.3Vを入力します。pinの配置と接続した図を次に示します。

pinの配置pin配置
環境センサー「BME280」の接続

raspberry pi 3でのBME280の接続確認

raspberry pi 3でBME280を認識しているかを確認します。
まず、次のコマンドを入力し、メニュー画面から「8 Advanced Options」を選択して、I2Cを有効にします。

$ sudo raspi-config

次のコマンドで再起動します。

$ sudo reboot

次のコマンドでi2c-toolsをインストールします。

pi@raspberrypi:~ $ sudo apt-get install i2c-tools
Reading package lists… Done
Building dependency tree
Reading state information… Done
i2c-tools is already the newest version.
0 upgraded, 0 newly installed, 0 to remove and 79 not upgraded.
pi@raspberrypi:~ $

BME280の接続を確認するため次のコマンドを入力します。DIYmall BME280のI2Cのポートは0x76になっています。

pi@raspberrypi:~ $ i2cdetect -y 1
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- 76 --

環境センサー「BME280」プログラムの作成

Raspberry PIで、Cライブラリ「WiringPi」を用いて、環境センサー「BME280」を動作させました。WiringPiのインストール方法は、Raspberry PIでRTC-8564NBの時計プログラムの作成に示します。「BME280を用いたPro Microの温湿度・気圧測定 プログラム」で使用したArduinoのプログラムを、WiringPiで実行できるように移植しました。
プログラムのソースコード「bme280.c」を次に示します。

bme280.c

#include <stdio.h>
 
#include <wiringPi.h>
#include <wiringPiI2C.h>

#define BME280_ADDRESS 0x76
unsigned long int hum_raw,temp_raw,pres_raw;
signed long int t_fine;

unsigned int dig_T1;
int dig_T2;
int dig_T3;
unsigned int dig_P1;
int dig_P2;
int dig_P3;
int dig_P4;
int dig_P5;
int dig_P6;
int dig_P7;
int dig_P8;
int dig_P9;
char  dig_H1;
int dig_H2;
char  dig_H3;
int dig_H4;
int dig_H5;
char  dig_H6;
 
static int dev;

static int init_dev(void)
{
  if ((dev = wiringPiI2CSetup(BME280_ADDRESS)) == -1)
  {
     return 1 ;
  }
    return 0;
}
void getRegisters(char address, int numData, unsigned char *data) {
  char adr;
  int i;
     
  adr = address;
  for (i = 0; i < numData; i++) {
    *data = wiringPiI2CReadReg8 (dev, adr);
//  	printf("adr:%x data:%x\n",adr, *data);
    adr ++;
    data ++;
  }
}

void readTrim()
{
    unsigned char data[32],i=0;
	
	getRegisters(0x88, 24, &data[0]);
	i+=24;
    
	getRegisters(0xA1, 1, &data[i]);
	i+=1;

	getRegisters(0xE1, 7, &data[i]);
	i+=7;
    
    dig_T1 = (data[1] << 8) | data[0];
    dig_T2 = (data[3] << 8) | data[2];
    dig_T3 = (data[5] << 8) | data[4];
    dig_P1 = (data[7] << 8) | data[6];
    dig_P2 = (data[9] << 8) | data[8];
    dig_P3 = (data[11]<< 8) | data[10];
    dig_P4 = (data[13]<< 8) | data[12];
    dig_P5 = (data[15]<< 8) | data[14];
    dig_P6 = (data[17]<< 8) | data[16];
    dig_P7 = (data[19]<< 8) | data[18];
    dig_P8 = (data[21]<< 8) | data[20];
    dig_P9 = (data[23]<< 8) | data[22];
    dig_H1 = data[24];
    dig_H2 = (data[26]<< 8) | data[25];
    dig_H3 = data[27];
    dig_H4 = (data[28]<< 4) | (0x0F & data[29]);
    dig_H5 = (data[30] << 4) | ((data[29] >> 4) & 0x0F);
    dig_H6 = data[31];   
}

void writeReg(unsigned char address, unsigned char data) {
  char adr;
  int i;
     
  adr = address;
  wiringPiI2CWriteReg8 (dev, adr, data);
//  printf("adr:%x data:%x\n",adr, data);
}
 
void readData()
{
    int i = 0;
    unsigned char data[8];
	
	getRegisters(0xF7, 8, &data[0]);

	pres_raw = data[0];
	pres_raw = (pres_raw<<8) | data[1];
	pres_raw = (pres_raw<<4) | (data[2] >> 4);
	
	temp_raw = data[3];
	temp_raw = (temp_raw<<8) | data[4];
	temp_raw = (temp_raw<<4) | (data[5] >> 4);
	
    hum_raw  = data[6];
    hum_raw  = (hum_raw << 8) | data[7];
//    printf("TEMP :%x  DegC  PRESS :%x  hPa  HUM :%x \n",temp_raw,pres_raw,hum_raw);
}


signed long int calibration_T(signed long int adc_T)
{
    
    signed long int var1, var2, T;
    var1 = ((((adc_T >> 3) - ((signed long int)dig_T1<<1))) * ((signed long int)dig_T2)) >> 11;
    var2 = (((((adc_T >> 4) - ((signed long int)dig_T1)) * ((adc_T>>4) - ((signed long int)dig_T1))) >> 12) * ((signed long int)dig_T3)) >> 14;
    
    t_fine = var1 + var2;
    T = (t_fine * 5 + 128) >> 8;
    return T; 
}

unsigned long int calibration_P(signed long int adc_P)
{
    signed long int var1, var2;
    unsigned long int P;
    var1 = (((signed long int)t_fine)>>1) - (signed long int)64000;
    var2 = (((var1>>2) * (var1>>2)) >> 11) * ((signed long int)dig_P6);
    var2 = var2 + ((var1*((signed long int)dig_P5))<<1);
    var2 = (var2>>2)+(((signed long int)dig_P4)<<16);
    var1 = (((dig_P3 * (((var1>>2)*(var1>>2)) >> 13)) >>3) + ((((signed long int)dig_P2) * var1)>>1))>>18;
    var1 = ((((32768+var1))*((signed long int)dig_P1))>>15);
    if (var1 == 0)
    {
        return 0;
    }    
    P = (((unsigned long int)(((signed long int)1048576)-adc_P)-(var2>>12)))*3125;
    if(P<0x80000000)
    {
       P = (P << 1) / ((unsigned long int) var1);   
    }
    else
    {
        P = (P / (unsigned long int)var1) * 2;    
    }
    var1 = (((signed long int)dig_P9) * ((signed long int)(((P>>3) * (P>>3))>>13)))>>12;
    var2 = (((signed long int)(P>>2)) * ((signed long int)dig_P8))>>13;
    P = (unsigned long int)((signed long int)P + ((var1 + var2 + dig_P7) >> 4));
    return P;
}

unsigned long int calibration_H(signed long int adc_H)
{
    signed long int v_x1;
    
    v_x1 = (t_fine - ((signed long int)76800));
    v_x1 = (((((adc_H << 14) -(((signed long int)dig_H4) << 20) - (((signed long int)dig_H5) * v_x1)) + 
              ((signed long int)16384)) >> 15) * (((((((v_x1 * ((signed long int)dig_H6)) >> 10) * 
              (((v_x1 * ((signed long int)dig_H3)) >> 11) + ((signed long int) 32768))) >> 10) + (( signed long int)2097152)) * 
              ((signed long int) dig_H2) + 8192) >> 14));
   v_x1 = (v_x1 - (((((v_x1 >> 15) * (v_x1 >> 15)) >> 7) * ((signed long int)dig_H1)) >> 4));
   v_x1 = (v_x1 < 0 ? 0 : v_x1);
   v_x1 = (v_x1 > 419430400 ? 419430400 : v_x1);
   return (unsigned long int)(v_x1 >> 12);   
}

void main(int argc, char **argv)
{
    unsigned char osrs_t = 1;             //Temperature oversampling x 1
    unsigned char osrs_p = 1;             //Pressure oversampling x 1
    unsigned char osrs_h = 1;             //Humidity oversampling x 1
    unsigned char mode = 3;               //Normal mode
    unsigned char t_sb = 5;               //Tstandby 1000ms
    unsigned char filter = 0;             //Filter off 
    unsigned char spi3w_en = 0;           //3-wire SPI Disable
    
    unsigned char ctrl_meas_reg = (osrs_t << 5) | (osrs_p << 2) | mode;
    unsigned char config_reg    = (t_sb << 5) | (filter << 2) | spi3w_en;
    unsigned char ctrl_hum_reg  = osrs_h;
 
	
    double temp_act = 0.0, press_act = 0.0,hum_act=0.0;
    signed long int temp_cal;
    unsigned long int press_cal,hum_cal;
	
	
    if(init_dev()==1)  return; 
    
    writeReg(0xF2,ctrl_hum_reg);
    writeReg(0xF4,ctrl_meas_reg);
    writeReg(0xF5,config_reg);
    readTrim();                    //

	while(1)
	{
	    delay(1000);
	    readData();
	    
	    temp_cal = calibration_T(temp_raw);
	    press_cal = calibration_P(pres_raw);
	    hum_cal = calibration_H(hum_raw);
	    temp_act = (double)temp_cal / 100.0;
	    press_act = (double)press_cal / 100.0;
	    hum_act = (double)hum_cal / 1024.0;
	    printf("TEMP :%f  DegC  PRESS :%f  hPa  HUM :%f \n",temp_act,press_act,hum_act);
    
	}
}

コンパイル・リンクは次のコマンドで実行します。

# gcc -o bme280 bme280.c -lwiringPi

作成したプログラムを次のコマンドで実行します。

# sudo ./bme280

次のように温湿度・気圧データが1秒ごとに表示されます。

root@raspberrypi:~/iotHub3gpi# gcc -o bme280 bme280.c -lwiringPi
root@raspberrypi:~/iotHub3gpi# ./bme280
TEMP :24.640000 DegC PRESS :1142.670000 hPa HUM :64.587891
TEMP :24.640000 DegC PRESS :1142.730000 hPa HUM :64.587891
TEMP :24.630000 DegC PRESS :1143.040000 hPa HUM :64.598633
TEMP :24.630000 DegC PRESS :1143.070000 hPa HUM :64.598633
TEMP :24.640000 DegC PRESS :1142.790000 hPa HUM :64.587891
TEMP :24.650000 DegC PRESS :1142.280000 hPa HUM :64.610352
TEMP :24.650000 DegC PRESS :1142.320000 hPa HUM :64.610352
TEMP :24.630000 DegC PRESS :1143.330000 hPa HUM :64.608398
TEMP :24.640000 DegC PRESS :1142.880000 hPa HUM :64.598633
TEMP :24.640000 DegC PRESS :1142.880000 hPa HUM :64.609375
TEMP :24.650000 DegC PRESS :1142.350000 hPa HUM :64.599609
TEMP :24.640000 DegC PRESS :1142.510000 hPa HUM :64.587891
TEMP :24.640000 DegC PRESS :1142.550000 hPa HUM :64.565430
^Z
[8]+ Stopped ./bme280

apt-get updateがエラーになる

「apt-get update」でraspberry piをアップデートすると、次のようなエラーが出る場合があります。これは、無線LANを使用していると、内部の機器にはネットワークアクセスが可能でも、設定によっては、インターネットには接続できない場合があります。この場合、起動スクリプトを書き換える必要があります。

pi@raspberrypi:~ $ sudo apt-get update
Err http://mirrordirector.raspbian.org jessie InRelease

Err http://archive.raspberrypi.org jessie InRelease

Err http://mirrordirector.raspbian.org jessie Release.gpg
Could not resolve ‘mirrordirector.raspbian.org’
Err http://archive.raspberrypi.org jessie Release.gpg
Could not resolve ‘archive.raspberrypi.org’
Reading package lists… Done
W: Failed to fetch http://mirrordirector.raspbian.org/raspbian/dists/jessie/InRe lease

W: Failed to fetch http://archive.raspberrypi.org/debian/dists/jessie/InRelease

W: Failed to fetch http://mirrordirector.raspbian.org/raspbian/dists/jessie/Rele ase.gpg Could not resolve ‘mirrordirector.raspbian.org’

W: Failed to fetch http://archive.raspberrypi.org/debian/dists/jessie/Release.gp g Could not resolve ‘archive.raspberrypi.org’

W: Some index files failed to download. They have been ignored, or old ones used instead.

/etc/rc.localの起動スクリプトの末尾のexit 0の手前に、3行追加します。それぞれの役割は

  • wlanにipアドレス割り当て
  • dhcpd立ち上げ
  • hostapd立ち上げ

/etc/rc.localを次のように編集します。IPアドレスは「192.168.0.50」とします。

$ sudo vi /etc/rc.local

ifconfig wlan0 192.168.0.50 netmask 255.255.255.0 up
/etc/init.d/isc-dhcp-server start
/etc/init.d/hostapd start

exit 0