#include <DHT.h>
// =================================================
// PINS
// =================================================
#define SDA_PIN D4
#define SCL_PIN D5
#define DHT_PIN A0
#define DHTTYPE DHT22
#define OLED_ADDR 0x3C
#define BMP_ADDR 0x77
DHT dht(DHT_PIN, DHTTYPE);
// =================================================
// SOFTWARE I2C
// =================================================
void i2cDelay()
{
delayMicroseconds(4);
}
void i2cStart()
{
pinMode(SDA_PIN, OUTPUT);
pinMode(SCL_PIN, OUTPUT);
digitalWrite(SDA_PIN, HIGH);
digitalWrite(SCL_PIN, HIGH);
i2cDelay();
digitalWrite(SDA_PIN, LOW);
i2cDelay();
digitalWrite(SCL_PIN, LOW);
}
void i2cStop()
{
digitalWrite(SDA_PIN, LOW);
digitalWrite(SCL_PIN, HIGH);
i2cDelay();
digitalWrite(SDA_PIN, HIGH);
}
bool i2cWrite(byte data)
{
for (byte i = 0; i < 8; i++)
{
digitalWrite(SDA_PIN, data & 0x80);
data <<= 1;
digitalWrite(SCL_PIN, HIGH);
i2cDelay();
digitalWrite(SCL_PIN, LOW);
i2cDelay();
}
pinMode(SDA_PIN, INPUT_PULLUP);
digitalWrite(SCL_PIN, HIGH);
i2cDelay();
bool ack = !digitalRead(SDA_PIN);
digitalWrite(SCL_PIN, LOW);
pinMode(SDA_PIN, OUTPUT);
return ack;
}
byte i2cRead(bool ack)
{
byte data = 0;
pinMode(SDA_PIN, INPUT_PULLUP);
for (byte i = 0; i < 8; i++)
{
data <<= 1;
digitalWrite(SCL_PIN, HIGH);
i2cDelay();
if (digitalRead(SDA_PIN))
data |= 1;
digitalWrite(SCL_PIN, LOW);
i2cDelay();
}
pinMode(SDA_PIN, OUTPUT);
digitalWrite(SDA_PIN, ack ? LOW : HIGH);
digitalWrite(SCL_PIN, HIGH);
i2cDelay();
digitalWrite(SCL_PIN, LOW);
return data;
}
// =================================================
// OLED
// =================================================
void oledCmd(byte c)
{
i2cStart();
i2cWrite(OLED_ADDR << 1);
i2cWrite(0x00);
i2cWrite(c);
i2cStop();
}
void oledData(byte d)
{
i2cStart();
i2cWrite(OLED_ADDR << 1);
i2cWrite(0x40);
i2cWrite(d);
i2cStop();
}
void oledInit()
{
delay(100);
oledCmd(0xAE);
oledCmd(0xD5);
oledCmd(0x80);
oledCmd(0xA8);
oledCmd(0x3F);
oledCmd(0xD3);
oledCmd(0x00);
oledCmd(0x40);
oledCmd(0x8D);
oledCmd(0x14);
oledCmd(0x20);
oledCmd(0x00);
oledCmd(0xA1);
oledCmd(0xC8);
oledCmd(0xDA);
oledCmd(0x12);
oledCmd(0x81);
oledCmd(0x7F);
oledCmd(0xD9);
oledCmd(0xF1);
oledCmd(0xDB);
oledCmd(0x40);
oledCmd(0xA4);
oledCmd(0xA6);
oledCmd(0xAF);
}
void oledPos(byte x, byte page)
{
oledCmd(0xB0 + page);
oledCmd(x & 0x0F);
oledCmd(0x10 | (x >> 4));
}
// =================================================
// 5x7 FONT
// =================================================
void oledChar(char c)
{
byte a = 0;
byte b = 0;
byte d = 0;
byte e = 0;
byte f = 0;
switch(c)
{
case '0':
a=0x3E; b=0x51; d=0x49; e=0x45; f=0x3E;
break;
case '1':
a=0x00; b=0x42; d=0x7F; e=0x40; f=0x00;
break;
case '2':
a=0x42; b=0x61; d=0x51; e=0x49; f=0x46;
break;
case '3':
a=0x21; b=0x41; d=0x45; e=0x4B; f=0x31;
break;
case '4':
a=0x18; b=0x14; d=0x12; e=0x7F; f=0x10;
break;
case '5':
a=0x27; b=0x45; d=0x45; e=0x45; f=0x39;
break;
case '6':
a=0x3C; b=0x4A; d=0x49; e=0x49; f=0x30;
break;
case '7':
a=0x01; b=0x71; d=0x09; e=0x05; f=0x03;
break;
case '8':
a=0x36; b=0x49; d=0x49; e=0x49; f=0x36;
break;
case '9':
a=0x06; b=0x49; d=0x49; e=0x29; f=0x1E;
break;
case 'T':
a=0x01; b=0x01; d=0x7F; e=0x01; f=0x01;
break;
case 'H':
a=0x7F; b=0x08; d=0x08; e=0x08; f=0x7F;
break;
case 'P':
a=0x7F; b=0x09; d=0x09; e=0x09; f=0x06;
break;
case 'C':
a=0x3E; b=0x41; d=0x41; e=0x41; f=0x22;
break;
case ':':
a=0x00; b=0x36; d=0x36;
break;
case '%':
a=0x63; b=0x13; d=0x08; e=0x64; f=0x63;
break;
case '-':
a=0x08; b=0x08; d=0x08; e=0x08; f=0x08;
break;
case '.':
d=0x60;
break;
case ' ':
break;
}
oledData(a);
oledData(b);
oledData(d);
oledData(e);
oledData(f);
oledData(0);
}
void oledText(byte x, byte page, const char *s)
{
oledPos(x, page);
while(*s)
oledChar(*s++);
}
// =================================================
// CLEAR OLED LINE
// =================================================
void oledClearLine(byte page)
{
oledPos(0, page);
for(int i = 0; i < 20; i++)
{
oledChar(' ');
}
}
// =================================================
// BMP180
// =================================================
int16_t AC1;
int16_t AC2;
int16_t AC3;
uint16_t AC4;
uint16_t AC5;
uint16_t AC6;
int16_t B1c;
int16_t B2c;
int16_t MCc;
int16_t MDc;
uint16_t bmpRead16(byte reg)
{
i2cStart();
i2cWrite(BMP_ADDR << 1);
i2cWrite(reg);
i2cStart();
i2cWrite((BMP_ADDR << 1) | 1);
byte h = i2cRead(true);
byte l = i2cRead(false);
i2cStop();
return ((uint16_t)h << 8) | l;
}
void bmpWrite(byte reg, byte value)
{
i2cStart();
i2cWrite(BMP_ADDR << 1);
i2cWrite(reg);
i2cWrite(value);
i2cStop();
}
void bmpInit()
{
AC1 = (int16_t)bmpRead16(0xAA);
AC2 = (int16_t)bmpRead16(0xAC);
AC3 = (int16_t)bmpRead16(0xAE);
AC4 = bmpRead16(0xB0);
AC5 = bmpRead16(0xB2);
AC6 = bmpRead16(0xB4);
B1c = (int16_t)bmpRead16(0xB6);
B2c = (int16_t)bmpRead16(0xB8);
MCc = (int16_t)bmpRead16(0xBC);
MDc = (int16_t)bmpRead16(0xBE);
}
long bmpPressure()
{
bmpWrite(0xF4, 0x2E);
delay(5);
int32_t UT = bmpRead16(0xF6);
bmpWrite(0xF4, 0x34);
delay(5);
int32_t UP = bmpRead16(0xF6);
int32_t X1 = ((UT - AC6) * AC5) >> 15;
int32_t X2 = ((int32_t)MCc << 11) / (X1 + MDc);
int32_t B5 = X1 + X2;
int32_t B6 = B5 - 4000;
X1 = (B2c * ((B6 * B6) >> 12)) >> 11;
X2 = (AC2 * B6) >> 11;
int32_t X3 = X1 + X2;
int32_t B3 = (((int32_t)AC1 * 4 + X3) + 2) / 4;
X1 = (AC3 * B6) >> 13;
X2 = (B1c * ((B6 * B6) >> 12)) >> 16;
X3 = (X1 + X2 + 2) >> 2;
uint32_t B4 =
(AC4 * (uint32_t)(X3 + 32768)) >> 15;
uint32_t B7 =
((uint32_t)UP - B3) * 50000UL;
long p;
if(B7 < 0x80000000UL)
p = (B7 * 2) / B4;
else
p = (B7 / B4) * 2;
X1 = (p >> 8) * (p >> 8);
X1 = (X1 * 3038) >> 16;
X2 = (-7357 * p) >> 16;
return p + ((X1 + X2 + 3791) >> 4);
}
// =================================================
// SETUP
// =================================================
void setup()
{
Serial.begin(115200);
pinMode(SDA_PIN, OUTPUT);
pinMode(SCL_PIN, OUTPUT);
digitalWrite(SDA_PIN, HIGH);
digitalWrite(SCL_PIN, HIGH);
dht.begin();
delay(2000);
oledInit();
oledClearLine(0);
oledClearLine(2);
oledClearLine(4);
oledText(0, 0, "WEATHER");
delay(1000);
bmpInit();
Serial.println("WEATHER MONITORING STATION");
}
// =================================================
// LOOP
// =================================================
void loop()
{
float temperature = dht.readTemperature();
float humidity = dht.readHumidity();
if (isnan(temperature) || isnan(humidity))
{
delay(2000);
temperature = dht.readTemperature();
humidity = dht.readHumidity();
}
long pressure = bmpPressure();
bool dhtOK =
!isnan(temperature) &&
!isnan(humidity);
// -----------------------------------------------
// SERIAL MONITOR
// -----------------------------------------------
Serial.println();
if(dhtOK)
{
Serial.print("Temperature: ");
Serial.print(temperature);
Serial.println(" C");
Serial.print("Humidity: ");
Serial.print(humidity);
Serial.println(" %");
}
else
{
Serial.println("DHT22 ERROR");
}
Serial.print("Pressure: ");
Serial.print(pressure / 100.0);
Serial.println(" hPa");
// -----------------------------------------------
// CLEAR OLD OLED DATA
// -----------------------------------------------
oledClearLine(0);
oledClearLine(2);
oledClearLine(4);
// -----------------------------------------------
// TEMPERATURE
// -----------------------------------------------
oledText(0, 0, "T:");
if(dhtOK)
{
int t = (int)temperature;
if(t < 0)
{
oledChar('-');
t = -t;
}
if(t >= 10)
{
oledChar('0' + (t / 10));
oledChar('0' + (t % 10));
}
else
{
oledChar('0' + t);
}
oledChar('C');
}
else
{
oledText(12, 0, "ERR");
}
// -----------------------------------------------
// HUMIDITY
// -----------------------------------------------
oledText(0, 2, "H:");
if(dhtOK)
{
int h = (int)humidity;
if(h >= 10)
{
oledChar('0' + (h / 10));
oledChar('0' + (h % 10));
}
else
{
oledChar('0' + h);
}
oledChar('%');
}
else
{
oledText(12, 2, "ERR");
}
// -----------------------------------------------
// PRESSURE
// -----------------------------------------------
oledText(0, 4, "P:");
int p = pressure / 100;
if(p >= 1000)
{
oledChar('0' + (p / 1000));
p %= 1000;
oledChar('0' + (p / 100));
p %= 100;
oledChar('0' + (p / 10));
oledChar('0' + (p % 10));
}
else if(p >= 100)
{
oledChar('0' + (p / 100));
p %= 100;
oledChar('0' + (p / 10));
oledChar('0' + (p % 10));
}
else if(p >= 10)
{
oledChar('0' + (p / 10));
oledChar('0' + (p % 10));
}
else
{
oledChar('0' + p);
}
delay(2000);
}