本文已参与「新人创作礼」活动,一起开启掘金创作之路。
1.0 简介
- BMP180气压计:气压传感器是用于测量气体的绝对压强的仪器。
- 有机发光二极管(OrganicLight-Emitting Diode,OLED),又称为有机电激光显示、有机发光半导体(OrganicElectroluminesence Display,OLED),是指有机半导体材料和发光材料在电场驱动下,通过载流子注入和复合导致发光的现象。本篇通过Arduino 01==BMP180==IIC采样得到气压和温度,再通过串口交互给Arduino 02,顺便 02的IIC通讯==0.98寸OLED==将气压和温度数据打印显示。
数字气压传感器的学习 高精度气压传感器一般是利用MEMS技术在单晶硅片上加工出真空腔体和惠斯登电桥,==惠斯登电桥桥臂两端的输出电压与施加的压力成正比==,经过温度补偿和校准后具有体积小,精度高,响应速度快,不受温度变化影响的特点。输出方式一般为模拟电压输出和数字信号输出两种,其中数字信号输出方式由于和单片机连接方便,是市场上的主流。
-
工作原理: 当被测气体的压力降低或升高时,这个薄膜变形带动顶针,同时该电阻器的阻值将会改变。电阻器的阻值发生变化。从传感元件取得0-5V的信号电压,经过A/D转换由数据采集器接受,然后数据采集器以适当的形式把结果传送给计算机。
-
BMP180相关参数如下: 压力范围:300hPa - -1100hPa(海拔9000m - - 500m)电源电压:1.8v - - 3.6v (VIN), 1.62v3.6v(VDDD)LCC8封装:无铅陶瓷载体封装(LCC) 尺寸: 3.6mmx3.8x0.93mm 低功耗:5uA,在标准模式 高精度:低功耗模式下,分辨率为0.06hPa (0.5米)高线性模式下,分辨率为0.03hPa (0.25米) 含温度输出 I2C接口温度补偿 无铅,符合RoHs规范MSL 1反应时间:7.5ms待机电流:0.1uA无需外部时钟电路
2.0 实验材料
- Arduino Uno R3开发板两块
- BMP180气压计传感器
- 0.98寸OLED
- 八根公母线
- USB数据线
- 一台安装Arduino开发环境的电脑
3.0 实验步骤
3.1 根据原理图搭建电路
BMP180传感器为3.3V供电,采用IIC通讯其中信号输出端连接到Arduino 01弟弟的信号线SDA(uno 的A4也可以)和一根时钟线SCL(uno 的A5也可以)引脚上;==Arduino 01弟弟与Arduino 02哥哥通过软串口9号和10号通讯,需对调==,Arduino 02哥哥通过IIC与OLED显示器通讯,因此除了5V供电的两根线外,只需要一根信号线SDA(uno 的A4也可以)和一根时钟线SCL(uno 的A5也可以)就可以。
实验原理图:
实验接线图:
3.2 新建sketch,分别拷贝如下代码并进行保存编译上传
Arduino IDE代码所需U8g2lib库
Arduino 01弟弟代码:
/**************************************************************************************/
/**********************DFRobot.com*****************************/
/***write by Tom Riddler Jun.16.14***/
/***if you got any progream,please contact me terminaterfxy@hotmail.com***/
#include <SoftwareSerial.h>
SoftwareSerial mySerial(9, 10); // RX, TX
#include <Wire.h>
#define BMP180ADD 0x77 // I2C address of BMP180
//write is (0xEE) read is (0xEF)
unsigned char OSS;
/**********************MSB LSB******/
int ac1; // 0xAA 0xAB
int ac2; // 0xAC 0xAD
int ac3; // 0xAE 0xAE
unsigned int ac4; // 0xB0 0xB1
unsigned int ac5; // 0xB2 0xB3
unsigned int ac6; // 0xB4 0xB5
int b1; // 0xB6 0xB7
int b2; // 0xB8 0xB9
int mb; // 0xBA 0xBB
int mc; // 0xBC 0xBD
int md; // 0xBE 0xBF
float temperature;
int Temperature;
double pressure;
int Pressure;
double pressure2;
long b5;
double altitude;
int Altitude;
int sensorA0 = 0;
int sensorA1 = 0;
int sensorA2 = 0;
int sensorA3 = 0;
int sensorA4 = 0;
int sensorA5 = 0;
void setup()
{
mySerial.begin(9600);
Serial.begin(9600);
Wire.begin();
OSS = 2; // Oversampling Setting 0: single 1: 2 times 2: 4 times 3: 8 times
BMP180start();
}
void loop()
{
calculate();//BMP180计算
delay(500);
Temperature=temperature/1,Pressure=pressure/1,Altitude=altitude/1;//双精度浮点数转为整形输出
sensorA0 = analogRead(A0);
sensorA1 = analogRead(A1);
sensorA2 = analogRead(A2);
sensorA3 = analogRead(A3);
sensorA4 = analogRead(A4);
sensorA5 = analogRead(A5);
Serial.println("A0:" + String(Temperature) + ";A1:" + String(Pressure) + ";A2:" + String(Altitude) + ";A3:" + String(sensorA3) + ";A4:" + String(sensorA4) + ";A5:" + String(sensorA5));
mySerial.println("A0:" + String(Temperature) + ";A1:" + String(Pressure) + ";A2:" + String(Altitude) + ";A3:" + String(sensorA3) + ";A4:" + String(sensorA4) + ";A5:" + String(sensorA5));
show();
delay(1000);
}
/** calculate centure **/
void calculate()
{
temperature = bmp180GetTemperature(bmp180ReadUT());
temperature = temperature * 0.1;
pressure = bmp180GetPressure(bmp180ReadUP())/1000;
pressure2 = 1000*pressure / 101325;
pressure2 = pow(pressure2, 0.19029496);
altitude = 44330 * (1 - pressure2); //altitude = 44330*(1-(pressure/101325)^0.19029496);
}
/** print reslut **/
void show()
{
Serial.print("Temperature: ");
Serial.print(temperature, 1); //10 hexadecimal
Serial.println(" C");
Serial.print("Pressure: ");
Serial.print(pressure, 0); //10 hexadecimal
Serial.println(" Pa");
Serial.print("altitude:");
Serial.print(altitude);
Serial.println("m");
}
/**BMP180 satrt program**/
void BMP180start()
{ /*MSB*/
ac1 = bmp180ReadDate(0xAA); //get full data
ac2 = bmp180ReadDate(0xAC);
ac3 = bmp180ReadDate(0xAE);
ac4 = bmp180ReadDate(0xB0);
ac5 = bmp180ReadDate(0xB2);
ac6 = bmp180ReadDate(0xB4);
b1 = bmp180ReadDate(0xB6);
b2 = bmp180ReadDate(0xB8);
mb = bmp180ReadDate(0xBA);
mc = bmp180ReadDate(0xBC);
md = bmp180ReadDate(0xBE);
}
/***BMP180 temperature Calculate***/
short bmp180GetTemperature(unsigned int ut)
{
long x1, x2;
x1 = (((long)ut - (long)ac6) * (long)ac5) >> 15; //x1=((ut-ac6)*ac5)/(2^15)
x2 = ((long)mc << 11) / (x1 + md); //x2=(mc*2^11)/(x1+md)
b5 = x1 + x2; //b5=x1+x2
return ((b5 + 8) >> 4); //t=(b5+8)/(2^4)
}
/***BMP180 pressure Calculate***/
long bmp180GetPressure(unsigned long up)
{
long x1, x2, x3, b3, b6, p;
unsigned long b4, b7;
b6 = b5 - 4000;
x1 = (b2 * (b6 * b6) >> 12) >> 11;
x2 = (ac2 * b6) >> 11;
x3 = x1 + x2;
b3 = (((((long)ac1) * 4 + x3) << OSS) + 2) >> 2;
x1 = (ac3 * b6) >> 13;
x2 = (b1 * ((b6 * b6) >> 12)) >> 16;
x3 = ((x1 + x2) + 2) >> 2;
b4 = (ac4 * (unsigned long)(x3 + 32768)) >> 15;
b7 = ((unsigned long)(up - b3) * (50000 >> OSS));
if (b7 < 0x80000000)
p = (b7 << 1) / b4;
else
p = (b7 / b4) << 1;
x1 = (p >> 8) * (p >> 8);
x1 = (x1 * 3038) >> 16;
x2 = (-7357 * p) >> 16;
p += (x1 + x2 + 3791) >> 4;
return p;
}
/*** Read 1 bytes from the BMP180 ***/
int bmp180Read(unsigned char address)
{
unsigned char data;
Wire.beginTransmission(BMP180ADD);
Wire.write(address);
Wire.endTransmission();
Wire.requestFrom(BMP180ADD, 1);
while (!Wire.available());
return Wire.read();
}
/*** Read 2 bytes from the BMP180 ***/
int bmp180ReadDate(unsigned char address)
{
unsigned char msb, lsb;
Wire.beginTransmission(BMP180ADD);
Wire.write(address);
Wire.endTransmission();
Wire.requestFrom(BMP180ADD, 2);
while (Wire.available() < 2);
msb = Wire.read();
lsb = Wire.read();
return (int) msb << 8 | lsb;
}
/*** read uncompensated temperature value ***/
unsigned int bmp180ReadUT()
{
unsigned int ut;
Wire.beginTransmission(BMP180ADD);
Wire.write(0xF4); // Write 0x2E into Register 0xF4
Wire.write(0x2E); // This requests a temperature reading
Wire.endTransmission();
delay(5); // Wait at least 4.5ms
ut = bmp180ReadDate(0xF6); // read MSB from 0xF6 read LSB from (16 bit)
return ut;
}
/*** Read uncompensated pressure value from BMP180 ***/
unsigned long bmp180ReadUP()
{
unsigned char msb, lsb, xlsb;
unsigned long up = 0;
Wire.beginTransmission(BMP180ADD);
Wire.write(0xF4); // Write 0x34+(OSS<<6) into register 0xF4
Wire.write(0x34 + (OSS << 6)); // 0x34+oss*64
Wire.endTransmission();
delay(2 + (3 << OSS)); // Wait for conversion, delay time dependent on OSS
Wire.beginTransmission(BMP180ADD);
Wire.write(0xF6); // Read register 0xF6 (MSB), 0xF7 (LSB), and 0xF8 (XLSB)
Wire.endTransmission();
Wire.requestFrom(BMP180ADD, 3);
while (Wire.available() < 3); // Wait for data to become available
msb = Wire.read();
lsb = Wire.read();
xlsb = Wire.read();
up = (((unsigned long) msb << 16) | ((unsigned long) lsb << 8) | (unsigned long) xlsb) >> (8 - OSS); //16 to 19 bit
return up;
}
Arduino 02哥哥代码:
#include <U8g2lib.h>
#include <Wire.h>
U8G2_SSD1306_128X64_NONAME_1_HW_I2C u8g2(U8G2_R0, U8X8_PIN_NONE);
#include <SoftwareSerial.h>
SoftwareSerial mySerial(9, 10); // RX, TX
String message_c;
const char* message;
int sensorA0;
int sensorA1;
int sensorA2;
int sensorA3;
int sensorA4;
int sensorA5;
void setup()
{
Serial.begin(9600);
while (Serial.read() >= 0) {} //清空串口0缓存
mySerial.begin(9600);
mySerial.listen();
u8g2.begin();
u8g2.enableUTF8Print();
}
void loop()
{
if (mySerial.available())
{
String message_c = mySerial.readString(); //串口1接收字符串
// Serial.print(message_c); //串口0打印串口1接收的字符串
// Serial.println(message_c.length()); //串口0打印串口1接收的字符串长度
message = message_c.c_str(); //由于sscanf只能识别const char*类型字符串,将String类型字符串转成const char*类型
sscanf(message, "A0:%d;A1:%d;A2:%d;A3:%d;A4:%d;A5:%d", &sensorA0, &sensorA1, &sensorA2, &sensorA3, &sensorA4, &sensorA5); //串口1接收字符串格式为435;25.25
Serial.print("sensorA0=");
Serial.print(sensorA0);
Serial.print(", sensorA1=");
Serial.print(sensorA1);
Serial.print(", sensorA2=");
Serial.print(sensorA2);
Serial.print(", sensorA3=");
Serial.print(sensorA3);
Serial.print(", sensorA4=");
Serial.print(sensorA4);
Serial.print(", sensorA5=");
Serial.println(sensorA5);
// while (mySerial.read() >= 0) {}; //清空串口1缓存,保证字符串的长度稳定
}
u8g2.firstPage();
do
{
page1();
} while (u8g2.nextPage());
delay(100);
}
void page1() {
u8g2.setFont(u8g2_font_timB10_tf);
u8g2.setFontPosTop();
u8g2.setCursor(2, 10);
u8g2.print("A0:");
u8g2.setCursor(25, 10);
u8g2.print(sensorA0);
u8g2.setCursor(45, 10);
u8g2.print("°C");
u8g2.setCursor(2, 30);
u8g2.print("A1:");
u8g2.setCursor(25, 30);
u8g2.print(sensorA1);
u8g2.setCursor(45, 30);
u8g2.print("Kpa");
u8g2.setCursor(2, 50);
u8g2.print("A2:");
u8g2.setCursor(25, 50);
u8g2.print(sensorA2);
u8g2.setCursor(45, 50);
u8g2.print("m");
u8g2.setCursor(77, 10);
u8g2.print("A3:");
u8g2.setCursor(100, 10);
u8g2.print(sensorA3);
u8g2.setCursor(77, 30);
u8g2.print("A4:");
u8g2.setCursor(100, 30);
u8g2.print(sensorA4);
u8g2.setCursor(77, 50);
u8g2.print("A5:");
u8g2.setCursor(100, 50);
u8g2.print(sensorA5);
u8g2.drawVLine(75, 4, 60);
u8g2.drawHLine(1, 25, 127);
u8g2.drawHLine(1, 45, 127);
u8g2.drawFrame(1, 1, 127, 63);
}
3.3 实验现象
打开窗口监视,观察OLED显示屏和串口的数据是否一致 ,然后手动捂热BPM180 ,观察其两者动态变化 😃😃😃 视频演示
[video(video-DJrX9AKF-1614057948091)(type-youku)(url-player.youku.com/embed/XNTEw…)]
4.0 总结
- ==本篇通过Arduino 01弟弟通过IIC与BMP180通讯采样得到气压和温度,再通过串口交互给Arduino 02哥哥,顺便 Arduino 02哥哥的IIC通讯0.98寸OLED将气压和温度数据打印显示。==。难度综合性强,值得新手一试!!!😃😃😃
- 在以后的博文中我们将学会用arduino==常用传感器和执行器==,从而实现对外部世界进行感知,充分认识这个有机与无机的环境,科学地合理地进行创作和发挥效益,然后为人类社会发展贡献一点微薄之力。