viorelracoviteanu
Published © GPL3+

Big Characters Weather Clock (int/ext temp, hum, press)

A weather clock with RTC DS3231, 2 x weather sensor BME280, 20x4 LCD and brightness auto-adjust.

IntermediateFull instructions provided5,734
Big Characters Weather Clock (int/ext temp, hum, press)

Things used in this project

Hardware components

Arduino Nano R3
Arduino Nano R3
×1
Alphanumeric LCD, 20 x 4
Alphanumeric LCD, 20 x 4
×1
High Accuracy Pi RTC (DS3231)
Seeed Studio High Accuracy Pi RTC (DS3231)
×1
Gravity: I2C BME280 Environmental Sensor
DFRobot Gravity: I2C BME280 Environmental Sensor
×2
Photo resistor
Photo resistor
×1
Rotary Encoder with Push-Button
Rotary Encoder with Push-Button
×1

Software apps and online services

Arduino IDE
Arduino IDE

Story

Read more

Custom parts and enclosures

Big Characters Map

Custom characters for big font

Schematics

Electric Diagram

Electric diagram - modules connection

Code

Big Font Weather Clock

Arduino
20x4 LCD Big Font Clock, interior/exterior weather information
/*
 * Racov feb.2021
 -- 20x4 LCD (paralel) display 
 -- clock with big numbers and I2C-DS3231 Real Time clock
 -- temperature and hunidity interior/exterior with I2C-BMP280
 -- rotary encoder for TIME set
 
 The circuit:
 * LCD RS     - D12
 * LCD Enable - D11
 * LCD D4     - D8
 * LCD D5     - D7
 * LCD D6     - D6
 * LCD D7     - D5
 * LCD R/W    - GND
 * LED A      - D9
 * 10K resistor-ends to +5V and GND
 * wiper to LCD VO(pin 3)

 Encoder:
 * A        - D2
 * B        - D3
 * Push1    - D4
 * Push2, C - GND
 
 racov.ro

*/

// include the library code:
#include <LiquidCrystal.h>      //LCD
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>    //BME280 temp-hum-pres sensor,
#include <RTClib.h>             //DS3231 Real Time Clock
RTC_DS3231 rtc;                 //declare RTC                
Adafruit_BME280 bme1;           //declare BME interior
Adafruit_BME280 bme2;           //declare BME exterior

// initialize the library by associating any needed LCD interface pin
// with the arduino pin number it is connected to
const int rs = 12, en = 11, d4 = 8, d5 = 7, d6 = 6, d7 = 5, LED = 9;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

// usually the rotary encoders three pins have the ground pin in the middle
int encoderPinA = 2;  // encoder right
int encoderPinB = 3;  // encoder left
int clearButton = 4;  // encoder push

// variables for automatic brightness
int light;

// interior environment variables
int intemp = 0;
int inhum = 0;
int pres = 0;
// exterior environment variables
int hum = 0;
int temp = 0;

int h,m,s,yr,mt,dt,dy,olds;   // hous, minutes, seconds, year, month, date of the month, day, previous second
char *DOW[]={"MAR","MIE","JOI","VIN","SAM","DUM","LUN"};  //define day of the week
char *MTH[]={"ian","feb","mar","apr","mai","iun","iul","aug","sep","oct","nov","dec"};  //define month
int EncoderMax;   // varialbe for h, m, s, ... max value

int encoderPos = 0;  		    // a counter for the dial
unsigned int lastReportedPos = 1;   // change management
static boolean rotating = false;    // debounce management

// interrupt service routine vars
boolean A_set = false;
boolean B_set = false;

// varialbe to know if we are in time setting mode
boolean set_h = false;     //hours
boolean set_m = false;     //minutes
boolean set_s = false;     //seconds
boolean set_yr = false;    //year
boolean set_mt = false;    //month
boolean set_dt = false;    //date of the month

boolean intbme = true;
boolean extbme = true;
/////////////////////////////////////////////////////

void setup() {
 Serial.begin(9600);
 // set up the LCD's number of columns and rows:
  lcd.begin(20, 4);
  lcd.clear();
 // set up the encoder
 pinMode(encoderPinA, INPUT);
 pinMode(encoderPinB, INPUT);
 pinMode(clearButton, INPUT);
 // encoder pin on interrupt 0 (pin 2)
 attachInterrupt(0, doEncoderA, CHANGE);
 // encoder pin on interrupt 1 (pin 3)
 attachInterrupt(1, doEncoderB, CHANGE);

 // *******DEFINE CUSTOM CHARACTERS FOR BIG FONT*****************
  byte A[8] =
  {
  B00011,
  B00111,
  B01111,
  B01111,
  B01111,
  B01111,
  B01111,
  B01111
  };
  byte B[8] =
  {
  B11111,
  B11111,
  B00000,
  B00000,
  B00000,
  B00000,
  B00000,
  B11111
  };
  byte C[8] =
  {
  B11000,
  B11100,
  B11110,
  B11110,
  B11110,
  B11110,
  B11110,
  B11110
  };
  byte D[8] =
  {
  B01111,
  B01111,
  B01111,
  B01111,
  B01111,
  B01111,
  B00111,
  B00011
  };
  byte E[8] =
  {
  B11111,
  B00000,
  B00000,
  B00000,
  B00000,
  B00000,
  B11111,
  B11111
  };
  byte F[8] =
  {
  B11110,
  B11110,
  B11110,
  B11110,
  B11110,
  B11110,
  B11100,
  B11000
  };
  byte G[8] =
  {
  B11111,
  B11111,
  B11111,
  B00000,
  B00000,
  B00000,
  B00000,
  B00000
  };
  byte H[8] =
  {
  B00000,
  B00000,
  B00000,
  B00000,
  B00000,
  B11111,
  B11111,
  B11111
  };
  
  lcd.createChar(8,A);
  lcd.createChar(6,B);
  lcd.createChar(2,C);
  lcd.createChar(3,D);
  lcd.createChar(7,E);
  lcd.createChar(5,F);
  lcd.createChar(1,G);
  lcd.createChar(4,H);
 
  // Print a message to the LCD.
  // lcd.setCursor(col, row);
  // lcd.print("text");
  lcd.setCursor(6, 0);
  lcd.print("WEATHER");
  lcd.setCursor(7, 1);
  lcd.print("CLOCK");
  lcd.setCursor(5, 2);
  lcd.print("**RACOV**");
  lcd.setCursor(6, 3);
  lcd.print("Feb.2021");
  // slowly increase display backlighting brightness 
  for (int i = 0; i <= 4; i++) {
    analogWrite(LED, (i*50));
    delay(500);
    }
  delay(1000);
  
  // initializing the modules
  analogWrite(LED, 50);
  lcd.setCursor(0, 0);
  lcd.print("CHECKING MODULES....");
  delay(100);
  
  analogWrite(LED, 100);
  lcd.setCursor(0, 1);
  lcd.print("1.REAL CLOCK......OK");
  if (! rtc.begin()) {
    lcd.setCursor(16, 1);
    lcd.print("FAIL");
    delay(5000);
  }
  delay(500);
  
  analogWrite(LED, 150);
  lcd.setCursor(0, 2);
  lcd.print("2.INSIDE TEMP.....OK");
  if (!bme1.begin(0x76)) {
    lcd.setCursor(16, 2);
    lcd.print("FAIL");
    intbme = false;
  }
  delay(500);
  
  analogWrite(LED, 200);
  lcd.setCursor(0, 3);
  lcd.print("3.OUTSIDE TEMP....OK");
  if (!bme2.begin(0x77)) {
    lcd.setCursor(16, 3);
    lcd.print("FAIL");
    extbme = false;
  }
  delay(2000);
  
  // print all the fix text - never changes
  lcd.setCursor(0, 0);
  lcd.print(" __ __"+String(char(165))+" __ __"+(char(165))+" __ __");  // char(165) is big point symbol
  lcd.setCursor(0, 1);
  lcd.print("      "+String(char(165))+"      "+(char(165))+"      ");
  lcd.setCursor(0, 2);
  lcd.print("LUN-01-ian [--"+String(char(223))+" --%]");  // char(223) is degree symbol
  lcd.setCursor(0, 3);
  lcd.print("  ----hPa   --"+String(char(223))+" --% ");

// set a particular date and time if you want (yyyy,mm,dd,hh,mm,ss)
//   rtc.adjust(DateTime(2021, 2, 16, 11, 00, 00));
  
// read all time and date and display
  DateTime now = rtc.now();
  h  = now.hour();
  m  = now.minute();
  s  = now.second();
  yr = now.year();
  mt = now.month();
  dt = now.day();
  dy = now.dayOfTheWeek();
  olds = s;

// fill the display with all the data
  printbig((h%10),3);
  printbig((h/10),0);
  printbig((m%10),10);
  printbig((m/10),7);
  printbig((s%10),17);
  printbig((s/10),14);

  lcd.setCursor(0, 2);
  lcd.print(DOW[dy]);
  lcd.setCursor(4, 2);
  lcd.print(dt/10);
  lcd.print(dt%10);
  lcd.setCursor(7, 2);
  lcd.print(MTH[mt]);

}

void loop() {
  DateTime now = rtc.now();
  s  = now.second();                        // read seconds
  if (olds != s) {                          // if seconds changed
/*    Serial.println(dy);
    Serial.println(mt);
    Serial.println(dt);
    Serial.println(yr); */
      printbig((s%10),17);                  // display seconds
      printbig((s/10),14);
      olds = s;
      timeset();              		    // verify if user wants to set time
      if ( s == 0 ) {                       // minutes change
          m  = now.minute();                // read minutes
          printbig((m%10),10);              // display minutes
          printbig((m/10),7);
          if (m == 0) {                     // hours change
            h  = now.hour();                // read hours
            printbig((h%10),3);             // dislay hours
            printbig((h/10),0);
            if (h == 0) {                   // day change
              dt = now.day();               // read day
              dy = now.dayOfTheWeek();
              mt = now.month();             // read month
              yr = now.year();              // read year
              lcd.setCursor(0, 2);          // display date full
              lcd.print(DOW[dy]);
              lcd.setCursor(4, 2);
              lcd.print(dt/10);
              lcd.print(dt%10);
              lcd.setCursor(7, 2);
              lcd.print(MTH[mt]);
          }
      }
    }
        // set screen brightness
        light = (analogRead(A6));
        analogWrite(LED, 2+(light/4.2));
                
        // interior temperature/humidity/pression
        if (intbme){
          intemp = round(bme1.readTemperature() - 1);
          inhum = round(bme1.readHumidity());
          pres = round(bme1.readPressure() / 100.0F);
          lcd.setCursor(11,2);
        if (intemp>=0) {
          lcd.print("[");
          if (intemp<10) {lcd.print(" ");}
          }
          else {
            if (intemp>(-10)) {lcd.print("[");}
          }
        lcd.print(intemp);
        lcd.setCursor(15,2);
        if (inhum<100) {lcd.print(" ");}
        lcd.print(inhum);
        lcd.setCursor(2,3);
        if (pres < 1000) {lcd.print(" ");
          if (pres < 100) {lcd.print("  ");}
          }
        lcd.print(pres);
        }
      // exterior temperature/humidity
        if (extbme){
            temp = round(bme2.readTemperature());
            lcd.setCursor(11,3);
          if (temp>=0) {
          lcd.print(" ");
          if (temp<10) {lcd.print(" ");}
          }
          else {
            if (temp>(-10)) {lcd.print(" ");}
            }
         lcd.print(temp);
        hum = round(bme2.readHumidity());
        lcd.setCursor(15,3);
              if (hum<100) {lcd.print(" ");}
              if (hum<10) {lcd.print(" ");}
              lcd.print(hum);
        }
    // do other things every second
  }
  delay (100);
}

void timeset() 
{
  // set year
   if (digitalRead(clearButton) == LOW )  {
    delay (10);
    analogWrite(LED, 150);             
    if (digitalRead(clearButton) == LOW )  {  // debounce switch set year
      set_yr = true;                             // set year
      set_mt = false;
      set_dt = false;
      set_h = false;
      set_m = false;
      set_s = false;
      encoderPos = yr;
  // blanks the time munbers
        lcd.setCursor(0, 0);
        lcd.print(" __ __"+String(char(165))+" __ __"+(char(165))+" __ __");  // char(165) is big point symbol
        lcd.setCursor(0, 1);
        lcd.print("      "+String(char(165))+"      "+(char(165))+"      ");
        lcd.setCursor(0, 2);
        lcd.print("Year: ");
      delay (500);
      while (digitalRead(clearButton) == HIGH ) {
        yr = encoderPos;
        lcd.setCursor(6, 2);
        lcd.print(yr);
        rotating = true;  // reset the debouncer
        if (lastReportedPos != encoderPos) {
          lastReportedPos = encoderPos;
        }
        delay (100);                              // debounce again
      }
    rtc.adjust(DateTime(yr, mt, dt, h, m, s));    //write the RTC memory (YYYY, M, D, H, M, s)
    analogWrite(LED, 0);                          // blink screen
    delay(200);
    analogWrite(LED, 150);
    }
   }

  // set month
   if (digitalRead(clearButton) == LOW )  {
    delay (10);                               
    if (digitalRead(clearButton) == LOW )  {  // debounce switch set month
      set_yr = false;                             // set month
      set_mt = true;
      set_dt = false;
      set_h = false;
      set_m = false;
      set_s = false;
      lcd.setCursor(0, 2);
      lcd.print("___-__-___");
      encoderPos = mt;
      delay (500);
      while (digitalRead(clearButton) == HIGH ) {
        mt = encoderPos;
        lcd.setCursor(7, 2);
        lcd.print(MTH[mt]);
        rotating = true;  // reset the debouncer
        if (lastReportedPos != encoderPos) {
          lastReportedPos = encoderPos;
        }
        delay (100);                              // debounce again
      }
    rtc.adjust(DateTime(yr, mt, dt, h, m, s));
    analogWrite(LED, 0);
    delay(200);
    analogWrite(LED, 150);
    }
   }

   // set day of month
   if (digitalRead(clearButton) == LOW )  {
    delay (10);                               
    if (digitalRead(clearButton) == LOW )  {  // debounce switch set day of month
      set_yr = false;                             // set day of month
      set_mt = false;
      set_dt = true;
      set_h = false;
      set_m = false;
      set_s = false;
      encoderPos = dt;        
      lcd.setCursor(0, 2);
      lcd.print("___-__-___");
      delay (500);
      while (digitalRead(clearButton) == HIGH ) {
        dt = encoderPos+1;
        lcd.setCursor(4, 2);
        lcd.print(dt/10);
        lcd.print(dt%10);
        rotating = true;  // reset the debouncer
        if (lastReportedPos != encoderPos) {
          lastReportedPos = encoderPos;
        }
        delay (100);                              // debounce again
      }
    rtc.adjust(DateTime(yr, mt, dt, h, m, s));
    analogWrite(LED, 0);
    delay(200);
    // fill the date
    analogWrite(LED, 150);
    lcd.setCursor(0, 2);
    lcd.print(DOW[dy]);
    lcd.setCursor(4, 2);
    lcd.print(dt/10);
    lcd.print(dt%10);
    lcd.setCursor(7, 2);
    lcd.print(MTH[mt]);
    }
   }
   
  // set hours
  if (digitalRead(clearButton) == LOW )  {
    delay (10);                               
    if (digitalRead(clearButton) == LOW )  {  // debounce switch set hours
      set_h = true;                             // set hours
      set_m = false;
      set_s = false;
      encoderPos = h;
      delay (500);
      while (digitalRead(clearButton) == HIGH ) {
        h = encoderPos;
        lcd.setCursor(0, 0);
        lcd.print(" __ __"+String(char(165))+" __ __"+(char(165))+" __ __");  // char(165) is big point symbol
        lcd.setCursor(0, 1);
        lcd.print("      "+String(char(165))+"      "+(char(165))+"      ");
         printbig((h/10),0);
         printbig((h%10),3);
        rotating = true;  // reset the debouncer
        if (lastReportedPos != encoderPos) {
          lastReportedPos = encoderPos;
        }
        delay (100);                              // debounce again
      }
    rtc.adjust(DateTime(yr, mt, dt, h, m, s));
    analogWrite(LED, 0);
    delay(200);
    analogWrite(LED, 150);
    }
  }

  // set minutes
  if (digitalRead(clearButton) == LOW )  {
    delay (10);                               
    if (digitalRead(clearButton) == LOW )  {  // debounce switch set minutes
      set_h = false;                             // set minutes
      set_m = true;
      set_s = false;
      encoderPos = m;
      delay (500);
      while (digitalRead(clearButton) == HIGH ) {
        m = encoderPos;
        lcd.setCursor(0, 0);
        lcd.print(" __ __"+String(char(165))+" __ __"+(char(165))+" __ __");  // char(165) is big point symbol
        lcd.setCursor(0, 1);
        lcd.print("      "+String(char(165))+"      "+(char(165))+"      ");
        printbig(m/10,7);
        printbig(m%10,10);
        rotating = true;  // reset the debouncer
        if (lastReportedPos != encoderPos) {
          lastReportedPos = encoderPos;
        }
        delay (100);                              // debounce again
      }
    rtc.adjust(DateTime(yr, mt, dt, h, m, s));
    analogWrite(LED, 0);
    delay(200);
    analogWrite(LED, 150);
    }
  }
  
  // set seconds
  if (digitalRead(clearButton) == LOW )  {
    delay (10);                               
    if (digitalRead(clearButton) == LOW )  {  // debounce switch set seconds
      set_h = false;                             // set seconds
      set_m = false;
      set_s = true;
      encoderPos = s;
      delay (500);
      while (digitalRead(clearButton) == HIGH ) {
        s = encoderPos;
        lcd.setCursor(0, 0);
        lcd.print(" __ __"+String(char(165))+" __ __"+(char(165))+" __ __");  // char(165) is big point symbol
        lcd.setCursor(0, 1);
        lcd.print("      "+String(char(165))+"      "+(char(165))+"      ");
        printbig(s/10,14);
        printbig(s%10,17);
        rotating = true;  // reset the debouncer
        if (lastReportedPos != encoderPos) {
          lastReportedPos = encoderPos;
        }
        delay (100);                              // debounce again
      }
    rtc.adjust(DateTime(yr, mt, dt, h, m, s));
    analogWrite(LED, 0);
    delay(200);
    analogWrite(LED, 150);
    }
  }
  
  //fill in the clock numbers
  printbig((h%10),3);
  printbig((h/10),0);
  printbig((m%10),10);
  printbig((m/10),7);
  printbig((s%10),17);
  printbig((s/10),14);

  // fill in the date
  lcd.setCursor(0, 2);
  lcd.print(DOW[dy]);
  lcd.setCursor(4, 2);
  lcd.print(dt/10);
  lcd.print(dt%10);
  lcd.setCursor(7, 2);
  lcd.print(MTH[mt]);

  DateTime now = rtc.now();   // read again the time
}

// Interrupt on A changing state
void doEncoderA() {
  // debounce
  if (set_h) EncoderMax = 24;
    else if (set_m) EncoderMax = 60;
    else if (set_s) EncoderMax = 60;
    else if (set_yr) EncoderMax = 3000;
    else if (set_mt) EncoderMax = 12;
    else if (set_dt) EncoderMax = 31;
  if ( rotating ) delay (1);  // wait a little until the bouncing is done
  // Test transition, did things really change?
  if ( digitalRead(encoderPinA) != A_set ) { // debounce once more
    A_set = !A_set;
    // adjust counter + if A leads B
    if ( A_set && !B_set )
      encoderPos += 1;
      encoderPos = (EncoderMax+encoderPos) % EncoderMax;
    rotating = false;  // no more debouncing until loop() hits again
  }
}

// Interrupt on B changing state, same as A above
void doEncoderB() {
  if (set_h) EncoderMax = 24;
    else if (set_m) EncoderMax = 60;
    else if (set_s) EncoderMax = 60;
    else if (set_yr) EncoderMax = 3000;
    else if (set_mt) EncoderMax = 12;
    else if (set_dt) EncoderMax = 31;
  if ( rotating ) delay (1);
  if ( digitalRead(encoderPinB) != B_set ) {
    B_set = !B_set;
    //  adjust counter - 1 if B leads A
    if ( B_set && !A_set )
      encoderPos -= 1;
      encoderPos = (EncoderMax+encoderPos) % EncoderMax;
    rotating = false;
  }
}


void printbig(int i, int x)
{
  //  prints each segment of the big numbers

  if (i == 0) {
      lcd.setCursor(x,0);
      lcd.write(8);  
      lcd.write(1); 
      lcd.write(2);
      lcd.setCursor(x, 1);
      lcd.write(3);  
      lcd.write(4);  
      lcd.write(5);
  }
    else if  (i == 1) {
      lcd.setCursor(x,0);
      lcd.write(8);
      lcd.write(255);
      lcd.print(" ");
      lcd.setCursor(x, 1);
      lcd.print(" ");
      lcd.write(255);
      lcd.print(" ");
    }

    else if  (i == 2) {
      lcd.setCursor(x,0);
      lcd.write(1);
      lcd.write(6);
      lcd.write(2);
      lcd.setCursor(x, 1);
      lcd.write(3);
      lcd.write(7);
      lcd.write(4);
    }

    else if (i == 3) {
      lcd.setCursor(x,0);
      lcd.write(1);
      lcd.write(6);
      lcd.write(2);
      lcd.setCursor(x, 1);
      lcd.write(4);
      lcd.write(7);
      lcd.write(5); 
    }

    else if (i == 4) {
      lcd.setCursor(x,0);
      lcd.write(3);
      lcd.write(4);
      lcd.write(2);
      lcd.setCursor(x, 1);
      lcd.print("  ");
      lcd.write(5);
    }

    else if (i == 5) {
      lcd.setCursor(x,0);
      lcd.write(255);
      lcd.write(6);
      lcd.write(1);
      lcd.setCursor(x, 1);
      lcd.write(7);
      lcd.write(7);
      lcd.write(5);
    }

    else if (i == 6) {
      lcd.setCursor(x,0);
      lcd.write(8);
      lcd.write(6);
      lcd.print(" ");
      lcd.setCursor(x, 1);
      lcd.write(3);
      lcd.write(7);
      lcd.write(5);
    }

    else if (i == 7) {
      lcd.setCursor(x,0);
      lcd.write(1);
      lcd.write(1);
      lcd.write(5);
      lcd.setCursor(x, 1);
      lcd.print(" ");
      lcd.write(8);
      lcd.print(" ");
    }
    
    else if (i == 8) {
      lcd.setCursor(x,0);
      lcd.write(8);
      lcd.write(6);
      lcd.write(2);
      lcd.setCursor(x, 1);
      lcd.write(3);
      lcd.write(7);
      lcd.write(5);
    }

    else if (i == 9) {
      lcd.setCursor(x,0);
      lcd.write(8);
      lcd.write(6);
      lcd.write(2);
      lcd.setCursor(x, 1);
      lcd.print(" ");
      lcd.write(4);
      lcd.write(5);
    }

  } 

Credits

viorelracoviteanu
5 projects • 59 followers

Comments