In the following example, in addition to using the Atmega644p microcontroller, I have also added the following functions:

  • signaling - using an LED;
  • commands - using a button;
  • displaying information - using a 16x2 graphic LCD;
  • real-time clock - RTC - using the PCF8583 circuit;
  • temperature sensor - using the DS18B20 circuit;
  • measuring analog signals - using the ADC capabilities.

The electrical schematic used in the simulation with Proteus is presented in the image below:

The source code (this time I used comments in English) used is as follows:

/*
Connection LCD to Sanguino
 * LCD RS to digital pin 22
 * LCD Enable to digital pin 23
 * LCD D4 to digital pin 24
 * LCD D5 to digital pin 25
 * LCD D6 to digital pin 26
 * LCD D7 to digital pin 28
 * LCD R/W to GND
Connection RED LED to Sanguino
* LED K to digital 13
* LED A to +5V in serie with 1k resistor
Connection DS18B20 - temperature sensor - case TO92 to Sanguino
* DS18B20 DQ to digital 2
* DS18B20 Vdd to +5V
* DS18B20 GND to GND
* DS18B20 use an pull-up resistor with value 4k7 between Vdd and DQ pin
Connection RTC - PCF8583 to Sanguino
* RTC A0 to +V for hardware address 0xA2
* RTC SCL to pin D16/SCL
* RTC SDA to pin D17/SDA
* RTC OSC1 to 32678Hz crystal
* RTC OSC0 to 32678HZ crystal
* RTC GND to GND
* RTC OSC1 to +V using 22pF capacitor
*/

// Library used
#include <Arduino.h>
#include <LiquidCrystalIO.h> // load LCD library
#include <OneWireNg_CurrentPlatform.h> // load 1-Wire communication library (DS18B20)
#include <PCF8583.h> // load library necessary to RTC sensor
#include <stdio.h> // load library necessary to build a string with sprintf function

// variable with constant value
const int ledPin =  13; // digital pin number where LED is connected
const long intervalBlink = 500; // time interval to blink the LED (in milliseconds)
const int runButton = 12; // digital pin number  where RUN button is connected

char date[50]; // buffer where we store the date info
char time[50]; // buffer where we store the time info
char times[50]; // buffer where we store the date and time info
char day[5], month[5], year[5]; // buffers used store the date
char hour[5], minute[5], second[6]; // buffers used to store the time
char potbuf1[50]; // buffer where we store the ADC info for P1-P2
char potbuf2[50]; // buffer where we store the ADC info for P3-P4

// variable with value changed
int ledState = HIGH;  // ledState used to set LED-ul ON or OFF (HiGH => LED=OFF)
unsigned long previousMillisBlink = 0; // variable used to store the previous time when the LED was upgraded
int runButtonState = HIGH; // variable used to store the state for the button Run
int pot1, pot2, pot3, pot4; // value of ADC

// pins used to connect LCD to Sanguino
const int rs = 22, en = 23, d4 = 24, d5 = 25, d6 = 26, d7 = 27;
// construct object lcd
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

// -----------------------Declaration used to set sensor DS18B20---------------
#define OW_PIN  2 // pin where the DS18 sensor is connected
// #define PARASITE_POWER // delete the comment for parasite support

#ifdef PARASITE_POWER
// # define PWR_CTRL_PIN   9 // delete the comment to power the transistor through pin 9
#endif

// commands for DS sensors
#define CMD_CONVERT_T           0x44
#define CMD_COPY_SCRATCHPAD     0x48
#define CMD_WRITE_SCRATCHPAD    0x4e
#define CMD_RECALL_EEPROM       0xb8
#define CMD_READ_POW_SUPPLY     0xb4
#define CMD_READ_SCRATCHPAD     0xbe

// DS sensors supported
#define DS18S20     0x10
#define DS1822      0x22
#define DS18B20     0x28
#define DS1825      0x3b
#define DS28EA00    0x42

#define ARRSZ(t) (sizeof(t)/sizeof((t)[0]))

static struct {
  uint8_t code;
  const char *name;
  }
  DSTH_CODES[] = {
    { DS18S20, "DS18S20" },
    { DS1822, "DS1822" },
    { DS18B20, "DS18B20" },
    { DS1825, "DS1825" },
    { DS28EA00,"DS28EA00" }
    };

static OneWireNg *ow = NULL;

// return NULL if is not supported
//static const char *dsthName(const OneWireNg::Id& id) {
//  for (size_t i=0; i < ARRSZ(DSTH_CODES); i++) {
//    if (id[0] == DSTH_CODES[i].code)
//    return DSTH_CODES[i].name;
//    }
//    return NULL;
//}
// ---------------------------end declarations for DS18B20-------------------------------

// construct an p object
//   PCF8583 p(0xA0); // hardware address for A0 connected to GND
   PCF8583 rtc(0xA2); // hardware address for A0 connected to +V

// declare used functions
void blinkLed();         // function used to blink the LED
long getTemp();          // function used to read the temperature
void printLcdTemp();     // function used to display the temperature to LCD
void printLcdTime();     // function used to display the time to LCD
void setDateTime();      // function used to setting the date and the time
void clear_row_1();      // function used to clean the row 1 and to put the cursor at the begging line
void clear_row_2();      // function used to clean the row 2 and to put the cursor at the begging line
void printAllADCtoLCD(); // function used to print all ADC values to LCD
void printLCDTimeADC();  // function used to print all ADC or Date, Time and Temp values at LCD 

// this function is run only once when the atmega is power/reset
void setup() {

    // ----------------- start to configure DS18B20------------------------------------
    #ifdef PWR_CTRL_PIN
    ow = new OneWireNg_CurrentPlatform(OW_PIN, PWR_CTRL_PIN, false);
    #else
    ow = new OneWireNg_CurrentPlatform(OW_PIN, false);
    #endif

    delay(500);

    #if (CONFIG_MAX_SRCH_FILTERS > 0)
    // if filtering is enabled - filter to supported devices only;
    //CONFIG_MAX_SRCH_FILTERS must be large enough to embrace all code ids
    for (size_t i=0; i < ARRSZ(DSTH_CODES); i++)
        ow->searchFilterAdd(DSTH_CODES[i].code);
    #endif
    // ---------------------end to configure DS18B20----------------------

    Serial.begin(9600); // begin serial communication

    lcd.begin(16, 2); // set the columns number and rows number at used LCD
    lcd.print("Load..."); // send message to LCD
    Serial.print("Load..."); // send message to serial console
    Serial.println(" OK");
    delay(1000); // wait to read the message

    pinMode(ledPin, OUTPUT); // setting digital pin ledPin to be output
    pinMode(runButton, INPUT_PULLUP); // setting digital pin for Run button to be input with pull-up resistor

    setDateTime(); // call the function to setting the date and time
    lcd.clear(); // clean all lines from LCD

}

//this functions is run in continue loop
void loop() {

    blinkLed(); // call the function to blink the LED
    printLCDTimeADC();
//  printAllADCtoLCD(); // call the function to print the ADC values to LCD
//  printLcdTime(); // call the function to print the date and time to LCD
//  printLcdTemp(); // call the function to print the temperature to LCD

}

// function what blink the LED
void blinkLed() {

    // check if time was gone to change the LED state (ON or OFF)
    // if the difference from currentMillis and previosMillis is bigger by intervalBlink
    unsigned long currentMillisBlink = millis(); // put current time in variable curentMillis

    if (currentMillisBlink - previousMillisBlink >= intervalBlink) {
        // check if time wishes was gone
        // if yes, then
        previousMillisBlink = currentMillisBlink; // save current time
        if (ledState == HIGH) {
            // if the LED is OFF/ON then I change the state to ON/OFF
            ledState = LOW;
        }
        else {
            ledState = HIGH;
        }

        digitalWrite(ledPin, ledState); // set the pin state with value 0/1 given by ledState

    }

}

// function used to read the temperature
long getTemp() {

    OneWireNg::Id id;
    OneWireNg::ErrorCode ec;

    ow->searchReset();
//  do {
        ec = ow->search(id);
        if (!(ec == OneWireNg::EC_MORE || ec == OneWireNg::EC_DONE))
//          break;
        // start temperature conversion
        ow->addressSingle(id);
        ow->writeByte(CMD_CONVERT_T);

        #ifdef PARASITE_POWER
        ow->powerBus(true); // power the bus
        #endif

        delay(750); // wait for conversion

        uint8_t touchScrpd[] = {
                CMD_READ_SCRATCHPAD,
                0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
        };

        ow->addressSingle(id);
        ow->touchBytes(touchScrpd, sizeof(touchScrpd));

        uint8_t *scrpd = &touchScrpd[1];  // scratchpad date

        if (OneWireNg::crc8(scrpd, 8) != scrpd[8]) {
            Serial.println("  Invalid CRC!");
//          continue;
        }

        long temp = ((long)(int8_t)scrpd[1] << 8) | scrpd[0];
        if (id[0] != DS18S20) {
            unsigned res = (scrpd[4] >> 5) & 3;
            temp = (temp >> (3-res)) << (3-res);
            temp = (temp*1000)/16;
        }

        else if (scrpd[7]) {
            temp = 1000*(temp >> 1) - 250;
            temp += 1000*(scrpd[7] - scrpd[6]) / scrpd[7];
        }
        else {
            temp = (temp*1000)/2;
            Serial.println("  Zeroed COUNT_PER_C detected!");
        }

        return temp;

//  } while (ec == OneWireNg::EC_MORE);

}

// function to print temperature information at LCD
void printLcdTemp() {

    long temperatura = getTemp();

    // print the temperature using cast function from long to float
    lcd.setCursor(8,1); // put the cursor to print information at line 2 and column 9
    lcd.print("        "); // delete last temperature info

    if (temperatura < 0) { // print negative sign if the temperature is below 0
        temperatura = -temperatura;
        lcd.setCursor(9,1);
        lcd.print('-');
    }

    lcd.setCursor(10,1); // put the cursor to print information at line 2 and column 11
    lcd.print((float)temperatura / 1000); // print temperature information
    lcd.print('C'); // print C sign for Celsius degree

/*
// print teperature information using long variable
   lcd.setCursor(9,1); // put the cursor to print information at line 2 and column 10
   lcd.print("       "); // delete last temperature info

   if (temperatura < 0) { // print negative sign if the temperature is below 0
   temperatura = -temperatura;
   lcd.setCursor(9,1);
   lcd.print('-');
   }

   lcd.setCursor(10,1); // put the cursor to print information at line 2 and column 11
   lcd.print(temperatura / 1000);
   lcd.print('.'); // print comma
   lcd.print(temperatura % 1000);
   //lcd.print('C');
*/

}

// function to setup the date and time, send: DDMMYYYYhhmmss;
void setDateTime() {

    Serial.println("You can set the time using format: DDMMYYYYhhmmss; ");
    Serial.println("and then press RUN button.");

    while (runButtonState == HIGH) {

        sprintf(date, "%02d/%02d/%04d",
                rtc.getDay(), rtc.getMonth(), rtc.getYear()); // put the date info from RTC in buffer
        sprintf(time, "%02d:%02d:%02d",
                rtc.getHour(), rtc.getMinute(), rtc.getSecond()); // put the time info from RTC in buffer

        lcd.setCursor(0,0);
        lcd.print(date);
        lcd.print("  SET");
        lcd.setCursor(0,1);
        lcd.print(time);
        lcd.print("   CLOCK");

    if(Serial.available() > 0) { // if exist serial communication, then I read the data send by user
        Serial.println("Receiving...");
        uint8_t day = (int) ((Serial.read() - 48) *10 +  (Serial.read() - 48));
        uint8_t month = (int) ((Serial.read() - 48) *10 +  (Serial.read() - 48));
        uint8_t year = (int) ((Serial.read() - 48) *1000 +  (Serial.read() - 48) *100 + (Serial.read() - 48) *10 + (Serial.read() - 48)) ;
        uint8_t hour  = (int) ((Serial.read() - 48) *10 +  (Serial.read() - 48));
        uint8_t min = (int) ((Serial.read() - 48) *10 +  (Serial.read() - 48));
        uint8_t sec = (int) ((Serial.read() - 48) * 10 + (Serial.read() - 48));

        if(Serial.read() == ';') { // if the last character is ; this mean the end on data
            Serial.println("and the clock was setting..."); // the time was setting
            rtc.setDateTime(sec, min, hour, day, month, year); // set the time and date
            lcd.clear(); // clear LCD
            // read the time
            sprintf(times, "%02d/%02d/%04d %02d:%02d:%02d",
                    rtc.getDay(), rtc.getMonth(), rtc.getYear(), rtc.getHour(), rtc.getMinute(), rtc.getSecond());
            Serial.println(times); // print at serial console the setting time

        }
    }
    runButtonState = digitalRead(runButton);
    delay(100);
    }
}

// function to print date and time information at LCD, DD/MM/YYYY and hh:mm:ss
void printLcdTime() {

//  sprintf(date, "%02d/%02d/%04d",
//          rtc.getDay(), rtc.getMonth(), rtc.getYear()); // put the date info from RTC in buffer
//  sprintf(time, "%02d:%02d:%02d",
//          rtc.getHour(), rtc.getMinute(), rtc.getSecond()); // put the time info from RTC in buffer

    lcd.setCursor(0,0);
//  lcd.print(date);
    // put the date info from RTC in buffers
    sprintf(day, "%02d", rtc.getDay());
    sprintf(month, "%02d", rtc.getMonth());
    sprintf(year, "%4d", rtc.getYear());

    // put the time info from RTC in buffer
    sprintf(hour, "%02d", rtc.getHour());
    sprintf(minute, "%02d", rtc.getMinute());
    sprintf(second, "%02d", rtc.getSecond());

    lcd.print(day);
    lcd.print("/");
    lcd.print(month);
    lcd.print("/");
    lcd.print(year);
    lcd.print("      ");

    lcd.setCursor(0,1);
//  lcd.print(time);
    lcd.print(hour);
    lcd.print(":");
    lcd.print(minute);
    lcd.print(":");
    lcd.print(second);

}

// function clean the line 1 from LCD and put the cursor at the begging line
void clear_row_1() {

    lcd.setCursor(0, 0);
    lcd.print("                ");
    lcd.setCursor(0, 0);

}

// function clean the line 2 from LCD and put the cursor at the begging line
void clear_row_2() {

    lcd.setCursor(0, 1);
    lcd.print("                ");
    lcd.setCursor(0, 1);

}

//function to read ADC value
void printAllADCtoLCD() {

    //read potentiometers   
    pot1 = analogRead(A0);
    pot2 = analogRead(A1);
    pot3 = analogRead(A2);
    pot4 = analogRead(A3);
    sprintf(potbuf1, "P1=%04d P2=%04d", pot1, pot2); // put in buffer info with ADC values
    clear_row_1(); // clear line 1 from LCD
    lcd.print(potbuf1); // print to LCD the information with ADC values
    sprintf(potbuf2, "P3=%04d P4=%04d", pot3, pot4); // put in buffer info with ADC values
    clear_row_2(); // clear line 1 from LCD
    lcd.print(potbuf2); // print to LCD the information with ADC values
    delay(250);
}

// function to print all ADC or Date, Time and Temp values at LCD 
void printLCDTimeADC() {

    if (runButtonState == HIGH)
    {

        printAllADCtoLCD();
        runButtonState = digitalRead(runButton);
    }
    else
    {

        printLcdTime();
        printLcdTemp();
        runButtonState = digitalRead(runButton);
    }

    delay(250);
}

Operation:
Upon the first power-up of the assembly or when resetting the microcontroller, we will be greeted on the LCD screen with the following message:

and the message received via serial communication at the console is as follows:

At this moment, we can set the date and time in the real-time clock implemented with PCF8583.
The sequence that needs to be transmitted from the serial console for setting the date and time is in the form ZZLLAAAAhhmmss;, for example:

16042020094600;

as shown in the image below:

after transmitting the string of characters to the serial console, we will receive a notification that the message has been received along with the current date and time, as shown in the image below:

After setting the date and time or if we are satisfied with the displayed date and time, for example, we have previously set the date and time and it is being maintained by the 3V battery, we will press the RUN button which will allow the setup to continue running in order to display the information received from the 4 potentiometers connected to the ADC inputs (A0-A3), as shown in the image below:

To obtain information related to the date, time, and temperature, we will need to press the RUN button. This information will be displayed as long as the button is pressed, and the message will be in the form:

The operation of the assembly in the simulation environment Proteus can be viewed in the following video:

The entire project (source code and the file in Proteus) can be downloaded from here LCD_Blink_LED_DS18B20_PCF8583_ADC.zip

The new libraries used and added in the source code are: