In the last Arduino project I built a simple real time clock using DS1307 RTC and NOKIA 5110 LCD (link is below) and in this project I’m going to show how to build a real time clock with temperature monitor using Arduino, DS3231 RTC chip and the same LCD display (Nokia 5110).
The DS3231 is more accurate than the DS1307 due to its built-in temperature sensor. It also (the DS3231) keeps time running if the main power source is down. It also uses I2C interface to communicate with the master device which is in this case the Arduino.
To see how to interface Arduino with Nokia 5110 LCD, visit the following post:
Interfacing Arduino with Nokia 5110 LCD
And to see how to interface Arduino with DS3231 for the first time, take a look at this post:
Arduino and DS3231 real time clock
The link below shows how to interface Arduino with DS1307 RTC and Nokia 5110 LCD:
Arduino clock with NOKIA 5110 LCD and DS1307 RTC
Hardware Required:
- Arduino board
- Nokia 5110 LCD screen
- DS3231 board —-> DS3231 RTC datasheet
- 5 x 3.3k ohm resistor
- 5 x 2.2k ohm resistor
- 2 x push button
- 3V coin cell battery
- Breadboard
- Jumper wires
Arduino with DS3231 and Nokia 5110 LCD circuit:
The following image shows project circuit schematic diagram.
The two push buttons B1 and B2 are for setting time and date. The two buttons are connected to Arduino pin 9 and pin 8 respectively for B1 and B2.
The Nokia 5110 LCD which is shown in the circuit diagram has 8 pins (from left to right): RST (reset), CE (chip enable), DC (or D/C: data/command), Din (data in), Clk (clock), VCC (3.3V), BL (back light) and Gnd (ground).
This LCD works with 3.3V only (power supply and control lines). The LCD module is supplied with 3.3V which comes from the Arduino board (VCC pin of the LCD is connected to Arduino 3.3V pin), BL pin is also connected to 3.3V.
All Arduino UNO board output pins are 5V, connecting a 5V pin to the Nokia 5110 LCD could damage its controller circuit.
To connect the Arduino to the LCD module and for the LCD safety, I used voltage divider for each line which means there are 5 voltage dividers. Each voltage divider consists of 2.2k and 3.3k resistors, this drops the 5V into 3V which is sufficient.
Nokia 5110 LCD pins are connected to Arduino UNO board as follows (each one through voltage divider):
RST (reset) pin is connected to Arduino digital pin 3
CE (chip enable) pin is connected to Arduino digital pin 4
DC (data/command) pin is connected to Arduino digital pin 5
DIN (data in) pin is connected to Arduino digital pin 6
CLK (clock) pin is connected to Arduino digital pin 7
Arduino with DS3231 and Nokia 5110 LCD code:
The Arduino code below doesn’t use any library for the DS3231 RTC chip.
The following Arduino code requires 2 libraries from Adafruit Industries:
The first library is a driver for the Nokia 5110 LCD (PCD8544 controller) which can be installed from Arduino IDE library manager (Sketch —> Include Library —> Manage Libraries …, in the search box write “nokia” and install the one from Adafruit).
The second library is Adafruit graphics library which can be installed also from Arduino IDE library manager.
The previous 2 libraries can also be installed manually, download links are below:
Adafruit Nokia 5110 LCD library —-> direct link
Adafruit graphics library —-> direct link
After the download, go to Arduino IDE —> Sketch —> Include Library —> Add .ZIP Library … and browse for the .zip file (previously downloaded).
The same thing for the other library file.
In the code there are total of 4 libraries, they’re included in the code as follows:
1 2 3 4 | #include <Wire.h> // include Wire library (required for I2C devices) #include <SPI.h> // include SPI library #include <Adafruit_GFX.h> // include adafruit graphics library #include <Adafruit_PCD8544.h> // include adafruit PCD8544 (Nokia 5110) library |
And the two push buttons are defined in the code as shown below:
1 2 3 | // button definitions #define button1 9 // button B1 is connected to Arduino pin 9 #define button2 8 // button B2 is connected to Arduino pin 8 |
Full Arduino code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 | /* * Arduino real time clock with Nokia 5110 LCD and DS3231. * This code works also with DS3232. * This is a free software with NO WARRANTY. * http://simple-circuit.com/ */ #include <Wire.h> // include Wire library (required for I2C devices) #include <SPI.h> // include SPI library #include <Adafruit_GFX.h> // include adafruit graphics library #include <Adafruit_PCD8544.h> // include adafruit PCD8544 (Nokia 5110) library // Nokia 5110 LCD module connections (CLK, DIN, D/C, CS, RST) Adafruit_PCD8544 display = Adafruit_PCD8544(7, 6, 5, 4, 3); // button definitions #define button1 9 // button B1 is connected to Arduino pin 9 #define button2 8 // button B2 is connected to Arduino pin 8 void setup() { pinMode(button1, INPUT_PULLUP); pinMode(button2, INPUT_PULLUP); delay(1000); // wait 1 second Wire.begin(); // join I2C bus // initialize the display display.begin(); // you can change the contrast around to adapt the display // for the best viewing! display.setContrast(50); display.clearDisplay(); // clear the screen and buffer display.display(); display.setTextSize(1); display.setTextColor(BLACK, WHITE); display.setCursor(28, 16); display.print("TIME:"); display.setCursor(13, 32); display.print("CHIP TEMP:"); display.display(); } // variable declarations char Time[] = " : : "; char Date[] = " / /20 "; char Temp[] = "000.00"; char temperature_msb; byte i, second, minute, hour, w_day, day, month, year, temperature_lsb; // a small function for button1 (B1) debounce bool debounce () { byte count = 0; for(byte i = 0; i < 5; i++) { if ( !digitalRead(button1) ) count++; delay(10); } if(count > 2) return 1; else return 0; } // function for display day of the week void day_display() { switch(w_day) { case 1: draw_text(12, 0, " SUNDAY "); break; case 2: draw_text(12, 0, " MONDAY "); break; case 3: draw_text(15, 0, " TUESDAY "); break; case 4: draw_text(15, 0, "WEDNESDAY"); break; case 5: draw_text(12, 0, " THURSDAY "); break; case 6: draw_text(12, 0, " FRIDAY "); break; default: draw_text(12, 0, " SATURDAY "); } } void RTC_display() { // convert BCD to decimal second = (second >> 4) * 10 + (second & 0x0F); minute = (minute >> 4) * 10 + (minute & 0x0F); hour = (hour >> 4) * 10 + (hour & 0x0F); day = (day >> 4) * 10 + (day & 0x0F); month = (month >> 4) * 10 + (month & 0x0F); year = (year >> 4) * 10 + (year & 0x0F); // end conversion // update time array Time[7] = second % 10 + '0'; Time[6] = second / 10 + '0'; Time[4] = minute % 10 + '0'; Time[3] = minute / 10 + '0'; Time[1] = hour % 10 + '0'; Time[0] = hour / 10 + '0'; // update date array Date[9] = year % 10 + '0'; Date[8] = year / 10 + '0'; Date[4] = month % 10 + '0'; Date[3] = month / 10 + '0'; Date[1] = day % 10 + '0'; Date[0] = day / 10 + '0'; int chip_temp = temperature_msb << 2 | temperature_lsb >> 6; if (chip_temp < 0) { // if temperature is negative chip_temp = abs(chip_temp); // absolute value Temp[0] = '-'; // put minus sign } else Temp[0] = ' '; // put space Temp[1] = chip_temp / 40 + '0'; // chip_temp/40 = (chip_temp/4)/10 --> get tens Temp[2] = (chip_temp / 4) % 10 + '0'; // --> get ones Temp[4] = (chip_temp * 5) / 2 % 10 + '0'; // chip_temp*5/2 = (chip_temp/4)*10 --> get tenths Temp[5] = (chip_temp * 25) % 10 + '0'; // chip_temp*25 = (chip_temp/4)*100 --> get hundredths draw_text(12, 8, Date); // print date draw_text(18, 24, Time); // print time draw_text(15, 40, Temp); // print chip temperature display.drawRect(53, 40, 3, 3, BLACK); // print degree symbol ( ° ) draw_text(58, 40, "C"); // print 'C' } void blink_parameter() { byte j = 0; while(j < 100 && digitalRead(button1) && digitalRead(button2)) { j++; delay(5); } } byte edit(byte x_pos, byte y_pos, byte parameter) { char text[3]; sprintf(text,"%02u", parameter); while(debounce()); // call debounce function (wait for B1 to be released) while(1) { while(!digitalRead(button2)) { parameter++; if(i == 0 && parameter > 31) // if date > 31 ==> date = 1 parameter = 1; if(i == 1 && parameter > 12) // if month > 12 ==> month = 1 parameter = 1; if(i == 2 && parameter > 99) // if year > 99 ==> year = 0 parameter = 0; if(i == 3 && parameter > 23) // if hours > 23 ==> hours = 0 parameter = 0; if(i == 4 && parameter > 59) // if minutes > 59 ==> minutes = 0 parameter = 0; sprintf(text,"%02u", parameter); draw_text(x_pos, y_pos, text); delay(200); // wait 200ms } draw_text(x_pos, y_pos, " "); blink_parameter(); draw_text(x_pos, y_pos, text); blink_parameter(); if(!digitalRead(button1)) // if button B1 is pressed if(debounce()) // call debounce function (make sure if B1 is pressed) { i++; // increment 'i' for the next parameter return parameter; // return parameter value and exit } } } // print text on the LCD void draw_text(byte x_pos, byte y_pos, char *text) { display.setCursor(x_pos, y_pos); display.print(text); display.display(); } // main loop void loop() { if(!digitalRead(button1)) // if button B1 is pressed if(debounce()) // call debounce function (make sure if B1 is pressed) { i = 0; while(debounce()); // call debounce function (wait for button B1 to be released) while(1) { while( !digitalRead(button2) ) // while button B2 pressed { w_day++; // increment w_day if(w_day > 7) w_day = 1; day_display(); // call day_display function delay(500); // wait 500 ms } draw_text(15, 0, " "); blink_parameter(); // call blink_parameter function day_display(); // call day_display function blink_parameter(); // call blink_parameter function if( !digitalRead(button1) ) // if button B1 is pressed break; } day = edit(12, 8, day); // edit date month = edit(30, 8, month); // edit month year = edit(60, 8, year); // edit year hour = edit(18, 24, hour); // edit hours minute = edit(36, 24, minute); // edit minutes // convert decimal to BCD minute = ((minute / 10) << 4) + (minute % 10); hour = ((hour / 10) << 4) + (hour % 10); day = ((day / 10) << 4) + (day % 10); month = ((month / 10) << 4) + (month % 10); year = ((year / 10) << 4) + (year % 10); // end conversion while(debounce()); // call debounce function (wait for button B1 to be released) // write data to DS1307 RTC Wire.beginTransmission(0x68); // start I2C protocol with DS1307 address Wire.write(0); // send register address Wire.write(0); // reset sesonds and start oscillator Wire.write(minute); // write minute Wire.write(hour); // write hour Wire.write(w_day); // write day Wire.write(day); // write date Wire.write(month); // write month Wire.write(year); // write year Wire.endTransmission(); // stop transmission and release the I2C bus delay(200); // wait 200ms } // read time and date Wire.beginTransmission(0x68); // start I2C protocol with DS1307 address Wire.write(0); // send register address Wire.endTransmission(false); // I2C restart Wire.requestFrom(0x68, 7); // request 7 bytes from DS1307 and release I2C bus at end of reading second = Wire.read(); // read seconds from register 0 minute = Wire.read(); // read minuts from register 1 hour = Wire.read(); // read hour from register 2 w_day = Wire.read(); // read day from register 3 day = Wire.read(); // read date from register 4 month = Wire.read(); // read month from register 5 year = Wire.read(); // read year from register 6 // read chip temperature Wire.beginTransmission(0x68); // start I2C protocol with DS3231 address Wire.write(0x11); // send register address Wire.endTransmission(false); // I2C restart Wire.requestFrom(0x68, 2); // request 2 bytes from DS3231 and release I2C bus at end of reading temperature_msb = Wire.read(); // read temperature MSB temperature_lsb = Wire.read(); // read temperature LSB day_display(); // print day of the week RTC_display(); // print time & date delay(100); // wait 100 ms } // end of code. |
The following video shows a simple hardware circuit of this project:
and the one below shows Proteus simulation (note that simulation circuit is not the same as real hardware circuit, hardware circuit diagram is shown above):
Proteus simulation file download link is below, use version 8.6 or later to open it:
Arduino with Nokia 5110 LCD and DS3231 RTC
Discover more from Simple Circuit
Subscribe to get the latest posts sent to your email.
I want to make the real time clock with the Nokia display, but wish it had an alarm as this would make a good bedside clock, thanks for sharing your circuits and software, very nice