반응형
라즈베리파이 BMP180 대기압 측정센서 실습 : BMP180 : 고도센서, 기압센서, 온도센서 라즈베리파이 실습코드
라즈베리파이 I2C 핀 사용법
라즈베리파이와 BMP180 대기압 측정센서 연결도
라즈베리파이에서 $i2cdetect -y 1 명령으로 센서의 주소를 확인한다.
파이선 코드와 C코드를 모두 아래에 나타내었다.
Python 코드는 아래를 참고한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 | #!/usr/bin/env python import smbus import time MODE_ULTRALOWPOWER = 0 MODE_STANDARD = 1 MODE_HIGHRES = 2 MODE_ULTRAHIGHRES = 3 # BMP180의 레지스터 REGISTER_AC1 = 0xAA REGISTER_AC2 = 0xAC REGISTER_AC3 = 0xAE REGISTER_AC4 = 0xB0 REGISTER_AC5 = 0xB2 REGISTER_AC6 = 0xB4 REGISTER_B1 = 0xB6 REGISTER_B2 = 0xB8 REGISTER_MB = 0xBA REGISTER_MC = 0xBC REGISTER_MD = 0xBE REGISTER_CONTROL = 0xF4 REGISTER_TEMPDATA = 0xF6 REGISTER_PRESSUREDATA = 0xF6 COMMAND_READTEMP = 0x2E COMMAND_READPRESSURE = 0x34 mode = MODE_STANDARD # 보정 데이터 11개 AC1 = 0 AC2 = 0 AC3 = 0 AC4 = 0 AC5 = 0 AC6 = 0 B1 = 0 B2 = 0 MB = 0 MC = 0 MD = 0 #BMP180의 I2C 통신 주소 address = 0x77 #레지스터에서 1바이트를 읽음 def read_byte(adr): return bus.read_byte_data(address, adr) #레지스터에서 2바이트를 읽음 def read_word(adr): high = bus.read_byte_data(address, adr) low = bus.read_byte_data(address, adr+1) val = (high << 8) + low return val #레지스터에서 2바이트를 읽은 후 보정함 def read_word_2c(adr): val = read_word(adr) if (val >= 0x8000): return -((65535 - val) + 1) else: return val #레지스터에서 보정 데이터를 읽어서 저장해 둠 def init_Calibration_Data(): global AC1, AC2, AC3, AC4, AC5, AC6, B1, B2, MB, MC, MD AC1 = read_word_2c(REGISTER_AC1) AC2 = read_word_2c(REGISTER_AC2) AC3 = read_word_2c(REGISTER_AC3) AC4 = read_word_2c(REGISTER_AC4) AC5 = read_word_2c(REGISTER_AC5) AC6 = read_word_2c(REGISTER_AC6) B1 = read_word_2c(REGISTER_B1) B2 = read_word_2c(REGISTER_B2) MB = read_word_2c(REGISTER_MB) MC = read_word_2c(REGISTER_MC) MD = read_word_2c(REGISTER_MD) print " AC1:", AC1," AC2:", AC2," AC3:", AC3," AC4:", AC4," AC5:", AC5," AC6:", AC6 print " B1:", B1," B2:", B2," MB:", MB," MC:", MC," MD:", MD #BMP180에서 보정전 온도 데이터를 읽음 def read_raw_Temperature(): bus.write_byte_data(address, REGISTER_CONTROL, COMMAND_READTEMP) time.sleep(0.0045) # Sleep 4.5ms raw = read_word_2c(REGISTER_TEMPDATA) print "Raw Temperature: 0x%04X (%d)" % (raw & 0xFFFF, raw) return raw #BMP180에서 보정전 기압 데이터를 읽음 def read_raw_Pressure(): bus.write_byte_data(address, REGISTER_CONTROL, COMMAND_READPRESSURE + (mode << 6)) time.sleep(0.03) # Sleep 30ms msb = read_byte(REGISTER_PRESSUREDATA) lsb = read_byte(REGISTER_PRESSUREDATA + 1) nxt = read_byte(REGISTER_PRESSUREDATA + 2) raw = ((msb << 16) + (lsb << 8) + nxt) >> (8 - mode) print "Raw Pressure: 0x%04X (%d)" % (raw & 0xFFFF, raw) return raw #온도를 보정함 def calibrate_Temp(raw): UT = 0 X1 = 0 X2 = 0 B5 = 0 temp = 0.0 X1 = ((raw - AC6) * AC5) >> 15 X2 = (MC << 11) / (X1 + MD) B5 = X1 + X2 temp = ((B5 + 8) >> 4) / 10.0 print "Calibrated temperature = %f C" % temp return temp #기압을 보정함 def calibrate_Pressure(raw): UT = 0 UP = 0 B3 = 0 B5 = 0 B6 = 0 X1 = 0 X2 = 0 X3 = 0 p = 0 B4 = 0 B7 = 0 UT = read_raw_Temperature() UP = raw # True Temperature Calculations X1 = ((UT - AC6) * AC5) >> 15 X2 = (MC << 11) / (X1 + MD) B5 = X1 + X2 # Pressure Calculations B6 = B5 - 4000 X1 = (B2 * (B6 * B6) >> 12) >> 11 X2 = (AC2 * B6) >> 11 X3 = X1 + X2 B3 = (((AC1 * 4 + X3) << mode) + 2) / 4 X1 = (AC3 * B6) >> 13 X2 = (B1 * ((B6 * B6) >> 12)) >> 16 X3 = ((X1 + X2) + 2) >> 2 B4 = (AC4 * (X3 + 32768)) >> 15 B7 = (UP - B3) * (50000 >> mode) 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) print "Pressure = ", p return p #기압을 읽은 후 보정함 def read_Pressure(): raw = read_raw_Pressure() p = calibrate_Pressure(raw) return p #온도를 읽은 후 보정함 def read_Temperature(): raw = read_raw_Temperature() t = calibrate_Temp(raw) return t #고도를 구함. 해수면 대기압은 값이 주어지지 않으면 표준값 사용 def read_Altitude(seaLevelPressure=101325): altitude = 0.0 pressure = float(read_Pressure()) altitude = 44330.0 * (1.0 - pow(pressure / seaLevelPressure, 0.1903)) print "Altitude = ", altitude return altitude # smbus 초기화 함수. Revision2에서는 파라미터 1을 사용 bus = smbus.SMBus(1) init_Calibration_Data() temp = read_Temperature() pressure = read_Pressure() altitude = read_Altitude() print "======== Result =======" print "Temperature : ", temp, " C" print "Pressure = ", pressure, "(", pressure / 100, " hPa)" print "Altitude : ", altitude, " Meter" |
C 코드는 아래를 참고한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 | #include <stdio.h> #include <stdbool.h> #include <signal.h> #include <math.h> #include <wiringPi.h> #define MODE_ULTRALOWPOWER 0 #define MODE_STANDARD 1 #define MODE_HIGHRES 2 #define MODE_ULTRAHIGHRES 3 // BMP180 Registers #define REGISTER_AC1 0xAA #define REGISTER_AC2 0xAC #define REGISTER_AC3 0xAE #define REGISTER_AC4 0xB0 #define REGISTER_AC5 0xB2 #define REGISTER_AC6 0xB4 #define REGISTER_B1 0xB6 #define REGISTER_B2 0xB8 #define REGISTER_MB 0xBA #define REGISTER_MC 0xBC #define REGISTER_MD 0xBE #define REGISTER_CONTROL 0xF4 #define REGISTER_TEMPDATA 0xF6 #define REGISTER_PRESSUREDATA 0xF6 #define COMMAND_READTEMP 0x2E #define COMMAND_READPRESSURE 0x34 int mode = MODE_STANDARD; // Calibration data int AC1 = 0; int AC2 = 0; int AC3 = 0; int AC4 = 0; int AC5 = 0; int AC6 = 0; int B1 = 0; int B2 = 0; int MB = 0; int MC = 0; int MD = 0; int dID = 0x77; // BMP180 device address int fd = 0; // i2c device handle bool loop = true; void my_ctrl_c_handler(int sig){ // can be called asynchronously close(fd); exit(0); } short read_word_2c(int addr) { char low, high; short val; high = (char)wiringPiI2CReadReg8(fd, addr) ; low = (char)wiringPiI2CReadReg8(fd, addr + 1) ; val = (high << 8) + low; if (val >= 0x8000) return -((65535 - val) + 1); else return val; } void init_Calibration_Data() { AC1 = (int)read_word_2c(REGISTER_AC1); AC2 = (int)read_word_2c(REGISTER_AC2); AC3 = (int)read_word_2c(REGISTER_AC3); AC4 = (int)read_word_2c(REGISTER_AC4); AC5 = (int)read_word_2c(REGISTER_AC5); AC6 = (int)read_word_2c(REGISTER_AC6); B1 = (int)read_word_2c(REGISTER_B1); B2 = (int)read_word_2c(REGISTER_B2); MB = (int)read_word_2c(REGISTER_MB); MC = (int)read_word_2c(REGISTER_MC); MD = (int)read_word_2c(REGISTER_MD); printf (" AC1:%d AC2:%d AC3:%d AC4:%d AC5:%d AC6:%d \n", AC1, AC2, AC3, AC4, AC5, AC6); printf (" B1:%d B2:%d MB:%d MC:%d MD:%d\n", B1,B2, MB, MC, MD); } int read_raw_Temperature() { int raw; wiringPiI2CWriteReg8(fd, REGISTER_CONTROL, COMMAND_READTEMP); delay(5); // Sleep 4.5ms raw = read_word_2c(REGISTER_TEMPDATA); printf ("Raw Temperature: 0x%04X (%d)\n" ,raw & 0xFFFF, raw); return raw; } int read_raw_Pressure() { int msb, lsb, nxt; int raw; wiringPiI2CWriteReg8(fd, REGISTER_CONTROL, COMMAND_READPRESSURE + (mode << 6)); delay(30); // Sleep 30ms msb = (char)wiringPiI2CReadReg8(fd, REGISTER_PRESSUREDATA); lsb = (char)wiringPiI2CReadReg8(fd, REGISTER_PRESSUREDATA + 1); nxt = (char)wiringPiI2CReadReg8(fd, REGISTER_PRESSUREDATA + 2); raw = ((msb << 16) + (lsb << 8) + nxt) >> (8 - mode); printf( "Raw Pressure: 0x%04X (%d)\n" , raw & 0xFFFF, raw); return raw ; } float calibrate_Temp(int raw) { int UT = 0; int X1 = 0; int X2 = 0; int B5 = 0; float temp = 0.0; X1 = ((raw - AC6) * AC5) >> 15; X2 = (MC << 11) / (X1 + MD); B5 = X1 + X2; temp = ((B5 + 8) >> 4) / 10.0; printf ("Calibrated temperature = %f C\n", temp); return temp; } int calibrate_Pressure(int raw) { int UT = 0; int UP = 0; int B3 = 0; int B5 = 0; int B6 = 0; int X1 = 0; int X2 = 0; int X3 = 0; int P = 0; int B4 = 0; int B7 = 0; UT = read_raw_Temperature(); UP = raw; // True Temperature Calculations X1 = ((UT - AC6) * AC5) >> 15; X2 = (MC << 11) / (X1 + MD); B5 = X1 + X2; // Pressure Calculations B6 = B5 - 4000; X1 = (B2 * (B6 * B6) >> 12) >> 11; X2 = (AC2 * B6) >> 11; X3 = X1 + X2; B3 = (((AC1 * 4 + X3) << mode) + 2) / 4; X1 = (AC3 * B6) >> 13; X2 = (B1 * ((B6 * B6) >> 12)) >> 16; X3 = ((X1 + X2) + 2) >> 2; B4 = (AC4 * (X3 + 32768)) >> 15; B7 = (UP - B3) * (50000 >> mode); P = (B7 / B4) * 2; X1 = (P >> 8) * (P >> 8); X1 = (X1 * 3038) >> 16; X2 = (-7357 * P) >> 16; P = P + (float)((X1 + X2 + 3791) >> 4); printf( "Pressure = %f\n ", P); return P; } int read_Pressure() { int raw; int p; raw = read_raw_Pressure(); p = calibrate_Pressure(raw); return p; } float read_Temperature() { int raw; float t; raw = read_raw_Temperature(); t = calibrate_Temp(raw); return t; } float read_Altitude(int Level) { float altitude = 0.0, pressure, seaLevelPressure; if(0 == Level) seaLevelPressure=101325.0; else seaLevelPressure = (float)Level; pressure = read_Pressure(); altitude = 44330.0 * (1.0 - pow(pressure / seaLevelPressure, 0.1903)); printf( "Altitude = %f\n", altitude); return altitude; } int main() { float temp, altitude; int pressure; signal(SIGINT, my_ctrl_c_handler); //Ctrl + C Handler if((fd=wiringPiI2CSetup(dID))<0){ printf("error opening i2c channel\n\r"); return 0; } init_Calibration_Data(); temp = read_Temperature(); pressure = read_Pressure(); altitude = read_Altitude(0); printf( "======== Result =======\n"); printf ("Temperature : %f C \n", temp); printf ("Pressure : %d Pa(%f hPa) \n", pressure, (float)pressure / 100.); printf ("Altitude : %f Meter \n", altitude); return 0; } |
반응형
'라즈베리파이' 카테고리의 다른 글
라즈베리파이 카메라 사용법 상세한 자료 파이선 코드 [링크] (0) | 2019.04.01 |
---|---|
FSR402센서, FSR (Force Sensing Resistors) 힘 감지 센서 라즈베리파이 파이선 코드 (0) | 2019.03.27 |
모든 센서종류, 센서타입 리스트 (0) | 2019.03.26 |
라즈베리파이 2대를 사용한 UART 채팅 프로그램 C, Python 사용 (0) | 2019.03.22 |
라즈베리파이 UART loopback 테스트 - C, Python 구현 (0) | 2019.03.22 |