// 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);
}
Comments
Please log in or sign up to comment.