I created a BAROGRAPH with the 2,2" TFT Adafruit display and Pressure sensor BMP180.
After spending quite some time the project is now finished and I would like to share it with people possibly
interested since I have not found many identical projects on the web.
At the beginning of the sketch you find the details of what the project does.
I also join a picture of the finished product.
Good luck to everybody wanting to make his own barograph.
Code: Select all
/*
ELECTRONIC BAROGRAPH
This sketch measures Temperature and Atmospheric Pressure,
saves the data on SD card and brings the following data to the TFT screen:
atmospheric pressure
temperature
pressure trend over one hour
graph of atmospheric pressure over the past 48 hours
If pressure drops more than 140 Pa/H an alarm sounds and LED flashes.(valuable for sailors)
Pressure is calibrated and compensated with the sensor's constants to sea level
using the sketch from Lindblom
Components used: Arduino pro mini 5V 328
Adafruit TFT 2,2" with SD card ILI9340
Adafruit Barometric Pressure sensor BMP180 5V
A regulated 5V power source with LM2574 for
installation on a yacht accepting 12V or 24V
Sketch based on ideas and work from Paul Torruella and Lindblom.
*/
#include <Adafruit_GFX.h>
#include <Adafruit_ILI9340.h>
#include <SPI.h>
#include <Wire.h>
#include <SD.h>
#define BMP085_ADDRESS 0x77 // I2C address of BMP085
#define _sclk 13
#define _miso 12
#define _mosi 11
#define _cs 10
#define _dc 9
#define _rst 8
#define sd_cs 4
#define FREQBUZ 2500
#define BUZ 7
int led =6;
Adafruit_ILI9340 tft = Adafruit_ILI9340( _cs, _dc, _rst);
const unsigned char OSS = 0; // Oversampling Setting
unsigned long lastMeasurementTime =0;
unsigned long lastRefreshDisplay =0;
byte heightsToDisplay[320];
// Calibration values
int ac1;
int ac2;
int ac3;
unsigned int ac4;
unsigned int ac5;
unsigned int ac6;
int b1;
int b2;
int mb;
int mc;
int md;
// b5 is calculated in bmp085GetTemperature(...), this variable is also used in bmp085GetPressure(...)
// so ...Temperature(...) must be called before ...Pressure(...).
long b5;
File historicFile;
void setup(){
pinMode (6,OUTPUT);
pinMode (7,OUTPUT);
pinMode(10, OUTPUT);
tft.begin();
tft.fillScreen(ILI9340_BLUE);
tft.setRotation(1);
//Drawing frames
tft.fillScreen(ILI9340_BLUE);
tft.drawRect(1,1,318,238,ILI9340_WHITE); // white rectangle at display border
tft.drawFastVLine(317, 1, 238,ILI9340_WHITE);
tft.drawFastVLine(316, 1, 238,ILI9340_WHITE);
tft.drawRect(10,50, tft.width()-70, 150, ILI9340_WHITE); // frame for the graph
tft.drawFastHLine(10,125,tft.width()-70, ILI9340_WHITE); //HL in the middle of the graph at 1007
// hPa scale indication
tft.setCursor(tft.width()-55, tft.height()-45);
tft.setTextColor(ILI9340_WHITE); tft.setTextSize(2);
tft.println("980");
tft.setCursor(tft.width()-55, tft.height()-120);
tft.println("1007");
tft.setCursor(tft.width()-55, 50);
tft.println("1035");
// Value units indication
tft.setTextColor(ILI9340_WHITE); tft.setTextSize(2);
tft.setCursor(88, tft.height()-214);
tft.println("hPa");
tft.setCursor(197, tft.height()-214);
tft.println("Pa/H");
tft.setCursor(10, tft.height()-25);
tft.println("48H");
tft.setCursor(120, tft.height()-25);
tft.println("24H");
tft.setCursor(tft.width()-85, tft.height()-25);
tft.println("0H");
// puts °C on the screen
tft.fillRect(140,4,50,43,ILI9340_BLUE);
tft.setTextColor(ILI9340_WHITE); tft.setTextSize(2);
tft.setCursor(tft.width()-25, 10);
tft.println("C");
tft.drawCircle(tft.width()-35,12,3,ILI9340_WHITE);
Serial.begin(9600);
Wire.begin();
bmp085Calibration();
if (!SD.begin(4)) {
Serial.println("initialization failed!");
return;
}
Serial.println("initialization done.");
}
void loop()
{
unsigned long gap = millis() - lastMeasurementTime;
if (gap>=5000){
lastMeasurementTime +=gap;
float temperature = bmp085GetTemperature(bmp085ReadUT()); //MUST be called first
long pressure1 = bmp085GetPressure(bmp085ReadUP());
long pressure = pressure1 + 3000;//correction I had to apply
tft.fillRect(10,4,75,43, ILI9340_BLUE);//clear rectangle pressure value
tft.setCursor(10,tft.height()-220);
tft.setTextColor(ILI9340_WHITE); tft.setTextSize(3);
tft.print(pressure/100);// clear rectangle trend value
tft.fillRect(tft.width()-54,25,50,20,ILI9340_BLUE);//clear rectangle temperature value
tft.setCursor(tft.width()-54, tft.height()-210);
tft.setTextColor(ILI9340_WHITE); tft.setTextSize(2);
tft.println(temperature,1);
computePressureTrend();
appendPressureInHistoric();
gap = millis() - lastRefreshDisplay;//refresh graph every minute
if (gap>60000){
lastRefreshDisplay += gap;
updateDataToDisplay();
}
}
}
// read calibration values from sensor
void bmp085Calibration()
{
ac1 = bmp085ReadInt(0xAA);
ac2 = bmp085ReadInt(0xAC);
ac3 = bmp085ReadInt(0xAE);
ac4 = bmp085ReadInt(0xB0);
ac5 = bmp085ReadInt(0xB2);
ac6 = bmp085ReadInt(0xB4);
b1 = bmp085ReadInt(0xB6);
b2 = bmp085ReadInt(0xB8);
mb = bmp085ReadInt(0xBA);
mc = bmp085ReadInt(0xBC);
md = bmp085ReadInt(0xBE);
}
// Calculate temperature in deg C
float bmp085GetTemperature(unsigned int ut){
long x1, x2;
x1 = (((long)ut - (long)ac6)*(long)ac5) >> 15;
x2 = ((long)mc << 11)/(x1 + md);
b5 = x1 + x2;
float temp = ((b5 + 8)>>4);
temp = temp /10;
return temp;
}
// Calculate pressure given up
// calibration values must be known
// b5 is also required so bmp085GetTemperature(...) must be called first.
// Value returned will be pressure in units of Pa.
long bmp085GetPressure(unsigned long up){
long x1, x2, x3, b3, b6, p;
unsigned long b4, b7;
b6 = b5 - 4000;
// Calculate B3
x1 = (b2 * (b6 * b6)>>12)>>11;
x2 = (ac2 * b6)>>11;
x3 = x1 + x2;
b3 = (((((long)ac1)*4 + x3)<<OSS) + 2)>>2;
// Calculate B4
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;
long temp = p;
return temp;
}
// Read 1 byte from the BMP085 at 'address'
char bmp085Read(unsigned char address)
{
unsigned char data;
Wire.beginTransmission(BMP085_ADDRESS);
Wire.write(address);
Wire.endTransmission();
Wire.requestFrom(BMP085_ADDRESS, 1);
while(!Wire.available())
;
return Wire.read();
}
// Read 2 bytes from the BMP085
// First byte will be from 'address'
// Second byte will be from 'address'+1
int bmp085ReadInt(unsigned char address)
{
unsigned char msb, lsb;
Wire.beginTransmission(BMP085_ADDRESS);
Wire.write(address);
Wire.endTransmission();
Wire.requestFrom(BMP085_ADDRESS, 2);
while(Wire.available()<2);
msb = Wire.read();
lsb = Wire.read();
return (int) msb<<8 | lsb;
}
// Read the uncompensated temperature value
unsigned int bmp085ReadUT(){
unsigned int ut;
// Write 0x2E into Register 0xF4
// This requests a temperature reading
Wire.beginTransmission(BMP085_ADDRESS);
Wire.write(0xF4);
Wire.write(0x2E);
Wire.endTransmission();
// Wait at least 4.5ms
delay(5);
// Read two bytes from registers 0xF6 and 0xF7
ut = bmp085ReadInt(0xF6);
return ut;
}
// Read the uncompensated pressure value
unsigned long bmp085ReadUP(){
unsigned char msb, lsb, xlsb;
unsigned long up = 0;
// Write 0x34+(OSS<<6) into register 0xF4
// Request a pressure reading w/ oversampling setting
Wire.beginTransmission(BMP085_ADDRESS);
Wire.write(0xF4);
Wire.write(0x34 + (OSS<<6));
Wire.endTransmission();
// Wait for conversion, delay time dependent on OSS
delay(2 + (3<<OSS));
// Read register 0xF6 (MSB), 0xF7 (LSB), and 0xF8 (XLSB)
msb = bmp085Read(0xF6);
lsb = bmp085Read(0xF7);
xlsb = bmp085Read(0xF8);
up = (((unsigned long) msb << 16) | ((unsigned long) lsb << 8) | (unsigned long) xlsb) >> (8-OSS);
return up;
}
void writeRegister(int deviceAddress, byte address, byte val) {
Wire.beginTransmission(deviceAddress); // start transmission to device
Wire.write(address); // send register address
Wire.write(val); // send value to write
Wire.endTransmission(); // end transmission
}
int readRegister(int deviceAddress, byte address){
int v;
Wire.beginTransmission(deviceAddress);
Wire.write(address); // register to read
Wire.endTransmission();
Wire.requestFrom(deviceAddress, 1); // read a byte
while(!Wire.available()) {
// waiting
}
v = Wire.read();
return v;
}
void updateDataToDisplay(){
tft.fillRect(11,51, 248, 74, ILI9340_BLUE);//clear screen graph rectangles
tft.fillRect(11, 126, 248, 73, ILI9340_BLUE);
int i=0;
File historicFile = SD.open("test15.txt");//data saved in file test15
if(!historicFile){
return;
}
long fileSize = historicFile.size();
long pos = ( fileSize - 276480);// 12 records /min* 60 min/h*48h * 8 bits /record
char pressureArray[7];
while(i<248 && pos < 4000000000 ){
historicFile.seek(pos);
for(int j = 0; j < 6; j++){ // reads the record bytes one by one
pressureArray[j] = historicFile.read();
if(pressureArray[j]==' '){
pressureArray[j] =0;
}
}
pressureArray[6]=0;
long pressureValue1 = atol(pressureArray);
long pressureValue = pressureValue1 + 3000;
// Graph boarder limits
if(pressureValue<98000){
pressureValue = 98000;
}
if(pressureValue>103500){
pressureValue=103500;
}
heightsToDisplay[i] = map(pressureValue, 98000, 103500,tft.height()-42,tft.height()-189 );
tft.drawPixel(tft.width()-310 +i, heightsToDisplay[i], ILI9340_WHITE);
tft.drawPixel(tft.width()-310 +i, heightsToDisplay[i]-1, ILI9340_WHITE);// to increase thikness of the graph
i++;
pos = pos+1112; // 276480 bits spread over 248 observations
}
historicFile.close();
}
void appendPressureInHistoric(){
long pressure = bmp085GetPressure(bmp085ReadUP());
char pressureArray[7];
String pressureStr = String (pressure);
pressureStr.toCharArray(pressureArray,7);
if (pressure<100000){
pressureArray[5] =' ';
}
pressureArray[6]=0;
historicFile = SD.open("test15.txt", FILE_WRITE);
if(!historicFile){
return;
}
historicFile.println(pressureArray);
historicFile.close();
}
//compute the 1 h pressure change
void computePressureTrend(){
long pressure = bmp085GetPressure(bmp085ReadUP());
File historicFile = SD.open("test15.txt");
if(!historicFile){
return;
}
long fileSize = historicFile.size();
long pos = ( fileSize - 8*12*60); //record(8)*records per min(12)*min/h(60)
char pressureArray[7];
historicFile.seek(pos);
for(int j = 0; j < 6; j++){
pressureArray[j] = historicFile.read();
if(pressureArray[j]==' '){
pressureArray[j] =0;
}
}
pressureArray[6]=0;
long pressure1HValue = atol(pressureArray);
int OneHourTrend = int( pressure - pressure1HValue);
if(OneHourTrend < -140){ // sound buzzer if pressure drop < -140 Pa/h
tone ( 6, 4000,500);
delay(500);
tone (6, 4500, 500);
delay(500);
digitalWrite(7,HIGH);//flash LED
delay(500);
digitalWrite(7,LOW);
}
noTone(6);
digitalWrite(led,LOW);
tft.fillRect(140,4,47,43,ILI9340_BLUE);
tft.setCursor(140 ,tft.height()-214);
tft.setTextColor(ILI9340_WHITE); tft.setTextSize(2);
tft.println(OneHourTrend);
historicFile.close();
}