antiElectron
Published © CC BY-NC-ND

Arduino Based Portable Altimeter & Weather Station

Arduino based portable altimeter & weather station.

IntermediateFull instructions provided24 hours2,139
Arduino Based Portable Altimeter & Weather Station

Things used in this project

Hardware components

OSRAM PICTIVA OS288048PQ33MY0C11
ams OSRAM OSRAM PICTIVA OS288048PQ33MY0C11
×1
BOSCH BME280
×1
MS5611
×1
SHT31
×1
Microchip ATMEGA 328P-PU
×1

Software apps and online services

Arduino IDE
Arduino IDE

Story

Read more

Schematics

Portable altimeter & weather station PCB

Schematics and PCB

Code

OSRAM PICTIVA portable altimeter and wether station

Arduino
// MODIFICATIONS
// 14/12/2015   Added humidex limits (display "----" under 26.7°C)
// 17/01/2016   Added measurement calibration coefficients
// 14/02/2016   Fixed self test procedure failed to recognise failure conditions
// 14/02/2016   Added non volatile memory storage for altimeter reference altitude


/*
 * LCD Pins
 * 
 * 1=Vss    GND
 * 2=NC
 * 3=Vdd    +3.3v
 * 4=BS1    GND
 * 5=IREF   820K resistor to GND
 * 6=#CS    Pin 10
 * 7=#RES   Pin 8 (plus  reset circuit resistor 27k + cond 10uF)
 * 8=D/#C   Pin 9
 * 9=R/#W   GND
 * 10=E#    GND
 * 11=CLK   Pin 13
 * 12=DIN   Pin 11
 * 13=DOUT  n.c.
 * 14=NC
 * 15=VCOMH 100nF to GND
 * 16=VCL   GND
 * 17=VCC   +12v
 * 18=NC
 * 19=NC
 * 20=NC
 * 
 */
#include <EasyScheduler.h>
#include <OLED_pictivaWide.h>
#include <Average.h>
#include <Wire.h>
#include <SPI.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
#include <EEPROM.h>                      //include EEPROM library

#include "_fonts/samsung_x2.c"//check the _font folder for more fonts!


#define RST_PIN   8
#define DC_PIN    9
#define CS_PIN    10

OLED_pictivaWide oled = OLED_pictivaWide(CS_PIN, DC_PIN, RST_PIN);;
Adafruit_BME280 bme; // I2C

#define LED 2

float Temp = 0;
float tempK = 0;
float tempF = 0;
float tempavg = 0;
float hum = 0;
float humavg = 0;
float Press = 1013.25;
float pressavg = 0;
float altr = 10000;
float dp = 0;
float vp = 0;
float vpe = 0;
float ah = 0;
float ad = 0;
float addry = 0;
float adwet = 0;
float heat = 0;
float referencePressure = 1013.25;
float altPressure = 1013.25;
char tempf[9];
char rhf[9];
char pressf[9];
char altrf[8];
char dpf[8];
char ahf[8];
char adf[8];
char heatf[8];
char rpf[9];

int zero;
int qnh_inc;
int qnh_dec;
int qne;
int stat = 1;
long address = 0;                        //set EEPROM memory start address location


//Calibration coefficients
float temp_o = -2.0;
float temp_s = 1.0;
float temp_lin;
float hum_o = 4.5;
float hum_s = 1.0;
float hum_lin;
float press_o = 0.0;
float press_s = 1.0;
float press_lin;

// CONSTANTS FOR SATURATED VAPOR PRESSURE CALCULATION
float a0 = 6.107799961;
float a1 = 0.4436518521;
float a2 = 0.01428945805;
float a3 = 0.0002650648471;
float a4 = 0.000003031240396;
float a5 = 0.00000002034080948;
float a6 = 0.00000000006136820929;

// CONSTANTS FOR HEAT INDEX CALCULATION
float c1 = -42.379;
float c2 = 2.04901523;
float c3 = 10.14333127;
float c4 = -0.22475541;
float c5 = -0.00683783;
float c6 = -0.05481717;
float c7 = 0.00122874;
float c8 = 0.00085282;
float c9 = -0.00000199;


Average<float> avepress(10);
Average<float> avetemp(10);
Average<float> avehum(10);

Schedular Task1;
Schedular Task2;
Schedular Task3;

/*
void Wait() {
  delay(100);
  digitalWrite(LED, HIGH);
  delay(50);
  digitalWrite(LED, LOW);
  delay(50);
}
*/

void setup() {
  Task1.start();
  Task2.start();
  Task3.start();
  pinMode(6, INPUT_PULLUP);
  pinMode(5, INPUT_PULLUP);
  pinMode(4, INPUT_PULLUP);
  pinMode(3, INPUT_PULLUP); 

  referencePressure = (EEPROMreadlong(address));       //read calibration factor from EEPROM

  oled.begin();
  oled.setFont(&Font);//easy!


 oled.setCursor(0, 0);
 oled.print("------------------------------------------------");
 oled.setCursor(0, 2);
 oled.print("    OLED ADVANCED ALTIMETER & WEATHER STATION   ");
  oled.setCursor(0, 4);
 oled.print("                     rev. 1.1"); 
 oled.setCursor(0, 5);
 oled.print("--------------------------------- by mAnU 2016 -");
 
  delay(2000);
  
 oled.setCursor(0, 4);
 oled.print("                             "); 
 oled.setCursor(0, 2);
 oled.print("SELF TEST:                                      ");

if (!bme.begin(0x76)) {
 oled.setCursor(12, 2);
   delay(500);
 oled.print("BME 280 FAILED");
 while (1);  
  }
   delay(500); 
 oled.setCursor(12, 2);
 oled.print("BME 280 PASSED"); 


  delay(2000);

  oled.clearScreen(); 
  oled.setCursor(0, 0);
  oled.print("T");
  oled.setCursor(4, 0);
  oled.print("C");
  oled.setCursor(0, 1);  
  oled.print("H");
  oled.setCursor(4, 1);
  oled.print("%");
  oled.setCursor(0, 2);
  oled.print("P"); 
  oled.setCursor(4, 2);
  oled.print("hPa");
  /*
  oled.setCursor(16, 1);
  oled.print("Dew");
  oled.setCursor(28, 1);
  oled.print("C");
  oled.setCursor(16, 3);  
  oled.print("Hidx");
  oled.setCursor(28, 3);
  oled.print("C");
  oled.setCursor(16, 5);  
  oled.print("Alt");
  oled.setCursor(28, 5);
  oled.print("m");

  oled.setCursor(31, 1);  
  oled.print("AD");
  oled.setCursor(43, 1);
  oled.print("kg/m3"); 

  oled.setCursor(31, 3);  
  oled.print("AH");
  oled.setCursor(43, 3);
  oled.print("g/m3");

  oled.setCursor(43, 5);
  oled.print("hPa"); 
  */
/*
  oled.setCursor(14, 0);  
  oled.print("|");
  oled.setCursor(14, 1);  
  oled.print("|"); 
  oled.setCursor(14, 2);  
  oled.print("|"); 
  oled.setCursor(14, 3);  
  oled.print("|");     
  oled.setCursor(14, 4);  
  oled.print("|");   
  oled.setCursor(14, 5);  
  oled.print("|"); 

  oled.setCursor(29, 0);  
  oled.print("|");
  oled.setCursor(29, 1);  
  oled.print("|"); 
  oled.setCursor(29, 2);  
  oled.print("|"); 
  oled.setCursor(29, 3);  
  oled.print("|");     
  oled.setCursor(29, 4);  
  oled.print("|");   
  oled.setCursor(29, 5);  
  oled.print("|");
  */
}

void loop() {
    Task1.check(acq1,500);
    Task2.check(acq2,50);
    Task3.check(acq3,3); 
}

  void acq1(){  
   Temp = bme.readTemperature();
   hum = bme.readHumidity();

 // CALCULATIONS
   tempK = tempavg + 273.15;
   tempF = tempavg / 5 * 9 + 32.000;
  vp = a0 + tempavg * (a1 + tempavg * ( a2 + tempavg * (a3 + tempavg * ( a4 + tempavg * (a5 + a6 * tempavg)))));
  vpe = (humavg * vp) / 100.00; 
  dp = (-430.22 + 237.70 * log(vpe)) / (-log(vpe) + 19.08) ;            // Dew point
  addry = (((pressavg * 100) - (vpe * 100)) / (287.04597 * (tempK)));         // Dry air fraction density
  adwet = (vpe * 100) / (461.495 * (tempK));                            // Water fraction density
  ad = addry + adwet; 
  ah = 2.16679 * vpe * 100 / tempK;
  heat = ((c1 + c2 * tempF+ c3 * humavg + c4 * tempF * humavg + c5 * square(tempF) + c6 * square(humavg) + c7 * square(tempF) * humavg + c8 * tempF * square(humavg) + c9 * square(tempF) * square(humavg))-32) / 9 * 5;


   avetemp.push(Temp);
   tempavg = avetemp.mean();
   avehum.push(hum);
   humavg = avehum.mean();

 // DATA LINEARISATION
   temp_lin = tempavg * temp_s + temp_o;
   hum_lin = humavg * hum_s + hum_o;

// DATA FORMATTING
  dtostrf(temp_lin,2, 2, tempf);
  dtostrf(hum_lin,2, 2, rhf);
  dtostrf(dp,2, 2, dpf);
  dtostrf(heat,2, 2, heatf);
  dtostrf(ah,1, 3, ahf);
  dtostrf(ad,1, 4, adf);
    
  oled.setCursor(2, 0);
  oled.print(tempf);
  oled.setCursor(2, 1);
  oled.print(rhf);
  /*
  oled.setCursor(5, 1);
  oled.print(dpf);
  oled.setCursor(5, 2);
  if (tempavg < 26.7){
  oled.print("    ---");  
  }
  else{
  oled.print(heatf);
} 
  oled.setCursor(10, 0);
  oled.print(adf);
  oled.setCursor(10, 1);
  oled.print(ahf); 
  */  
}

  
void acq2(){  
//   Press = bme.readPressure() / 100.000;
   altr = bme.readAltitude(referencePressure);
   avepress.push(Press);
   pressavg = avepress.mean();

// DATA LINEARISATION 
   press_lin = pressavg * press_s + press_o;

// DATA FORMATTING 
   dtostrf(press_lin,3, 2, pressf);
   dtostrf(altr,4, 0, altrf);
   dtostrf(referencePressure,4, 2, rpf);
   
   oled.setCursor(1, 2);
   oled.print(pressf);
   /*
   oled.setCursor(10, 3);
   oled.println(altrf);
   oled.setCursor(5, 3);
   oled.println(rpf); 

   oled.setCursor(31, 5);  
if (stat == 0){ 
  oled.print("QFE");
}
if (stat == 1){ 
  oled.print("QNH");
}
if (stat == 2){ 
  oled.print("QNE");
}     
*/
}


void acq3(){
   zero = digitalRead(6);
   qnh_inc = digitalRead(5);
   qnh_dec = digitalRead(4);
   qne = digitalRead(3);

  if (zero == LOW){
    referencePressure = pressavg;
    stat = 0;
  }

  if (qnh_inc == LOW){
    stat = 1;
    referencePressure = altPressure;   
    referencePressure = referencePressure + 0.01;
    altPressure = referencePressure;
    EEPROMwritelong(address,altPressure);          //store calibration factor in EEPROM
  }
  
  if (qnh_dec == LOW){ 
    stat = 1;
    referencePressure = altPressure;      
    referencePressure = referencePressure - 0.01;
    altPressure = referencePressure;
    EEPROMwritelong(address,altPressure);          //store calibration factor in EEPROM
  }

  if (qne == LOW){
    referencePressure = 1013.25;
    stat = 2;
  }
  
}

//Routine to write a 4 byte (32 bit) long to EEPROM at specified addresses
void EEPROMwritelong(int address, long value)    
    {
    byte four = (value & 0xFF);            //four = least significant byte
    byte three = ((value>>8) & 0xFF);
    byte two = ((value>>16) & 0xFF);
    byte one = ((value>>24) & 0xFF);       //one = most significant byte
    
    EEPROM.write(address, four);           //write the four bytes into EEPROM
    EEPROM.write(address +1, three);
    EEPROM.write(address +2, two);
    EEPROM.write(address +3, one);
    }

//routine to read back 4 bytes and return with (32 bit) long as value
long EEPROMreadlong(long address)
    {
      long four = EEPROM.read(address);    //read the 4 bytes from EEPROM
      long three = EEPROM.read(address + 1);
      long two = EEPROM.read(address + 2);
      long one = EEPROM.read(address + 3);
      return (four)+(three << 8)+(two << 16)+(one << 24);
    }

Credits

antiElectron
20 projects • 119 followers
Contact

Comments

Please log in or sign up to comment.