LED - LCD - Temperature

In our previous project, we will add, in addition to the character display, the LED that blinks intermittently, a temperature sensor DS18B20 that uses 1-Wire communication.
This sensor is usually found in a TO-92 package or in a protective sheath.
We will increase the difficulty level by transmitting the temperature information read from the DS18B20 sensor via serial communication.

I connected the sensor to digital pin 2 of the Sanguino board, as shown in the image below.
The 4.7k pull-up resistor is mandatory.
The temperature will be displayed on the serial communication in a terminal.
Thus, I introduced the serial communication mode.

The code used is as follows:

/*
Conectarea LCD la Sanguino
 * LCD RS la pinul digital pin 22
 * LCD Enable la pinul digital pin 23
 * LCD D4 la pinul digital pin 24
 * LCD D5 la pinul digital pin 25
 * LCD D6 la pinul digital pin 26
 * LCD D7 la pinul digital pin 28
 * LCD R/W la masa
Conectare LED
* LED K la pinul digital 13
* LED A la +5V printr-o rezistenta de 1k
Conectare DS18B20 - senzor de temperatura capsula TO92
* DS18B20 DQ la pinul digital 2
* DS18B20 Vdd la +5V
* DS18B20 GND la masa
* DS18B20 o rezistenta pull-up de 4k7 intre Vdd si pinul DQ  
*/
#include <Arduino.h>
#include <LiquidCrystal.h> // load the library for the LCD display
#include "OneWireNg_CurrentPlatform.h"

 // constantele sunt variabile cu valoare fixa
const int ledPin =  13; // pinul unde este conectat LED-ul
const long intervalBlink = 500; // intervalul de timp in care se va aprinde ledul (in milisecunde)
boolean started = false;

// variabile a caror valoare se va modifica
int ledState = HIGH;  // ledState utilzat pentru a seta LED-ul ON sau OFF (HiGH => LED=OFF)
unsigned long previousMillisBlink = 0; // variabila care va stoca timpul când starea LED-ului a fost actualizata

// intializez libraria si asociez pinii Sanguino la LCD
const int rs = 22, en = 23, d4 = 24, d5 = 25, d6 = 26, d7 = 27;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

// Declaratiile necesare pentru senzorul DS18

#define OW_PIN  2 // the pin where the DS18 sensor is connected 
// #define PARASITE_POWER // uncomment for parasite power support 

#ifdef PARASITE_POWER
/* sterge comentarea pentru alimentarea tranzistorului
si controlul acestuia prin pinul 9 sau altul */
// # define PWR_CTRL_PIN   9
#endif

/* Comenzile pentru circuitele DS */
#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

/* Tipurile de circuite DS suportate */
#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;

/* returneaza NULL daca nu este suportat */
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;
}

// sfarsitul declaratiilor necesare pentru circuitele DS

// declar functiile utilizate
void blinkLed(); // fuctia care aprinde un LED
void printSerialTemp(); // functia care va afisa temperatura la portul serial

// aceasta functie va fi rulata o data
void setup() { 
  #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

  Serial.begin(9600); // intializez comunicatia seriala
  lcd.begin(16, 2); // setez nr. de coloane si de linii ale LCD-ului
  lcd.print("salut, lume!"); // Afisez un mesaj la LCD
  pinMode(ledPin, OUTPUT); // setez pinul digital aferent ledPin ca iesire

}

//acesta functie va fi rulata la infinit
void loop() { 

  lcd.setCursor(0, 1); // setez cursorul la coloana 0, linia 1 (pe randul 2)
  lcd.print(millis()/1000);  // afisez nr. de secunde de la ultimul reset
  blinkLed(); // apelez functia ce aprinde LED-ul
  printSerialTemp(); // apelez functia care afiseaza la portul serial temperatura

}

// acesta functie va aprinde un led
void blinkLed() { 
  // verifica daca e trecut timpul pentru a schimba satrea LED-ului (ON sau OFF)
  // daca diferenta dintre timpul curent (currentMillis) si ultimul timp (previosMillis) salvat
  // este mai mare decat timpul impus prin variabila (intervalBlink) 
  unsigned long currentMillisBlink = millis(); // stochez in curentMillis timpul curent
  if (currentMillisBlink - previousMillisBlink >= intervalBlink) {
    // verific daca s-a scurs intervalul de timp dorit
    // daca da, atunci,
    previousMillisBlink = currentMillisBlink; //salvez timpul current
    if (ledState == HIGH) {
      // daca LED-ul este OFF atunci schimb starea lui in ON si invers
      ledState = LOW;
      }
      else {
        ledState = HIGH;
        }
  digitalWrite(ledPin, ledState); // setez starea pinului cu variabila ledState stabilita anterior
  }

}

//afisare la portul serial a temperaturii
void printSerialTemp() {
  OneWireNg::Id id;
  OneWireNg::ErrorCode ec;

  ow->searchReset();
  do {
    ec = ow->search(id);
    if (!(ec == OneWireNg::EC_MORE || ec == OneWireNg::EC_DONE))
    break;

    /* porneste conversia temperaturii */
    ow->addressSingle(id);
    ow->writeByte(CMD_CONVERT_T);

    #ifdef PARASITE_POWER
    /* alimenteaza magistrala */
    ow->powerBus(true);
    #endif

    delay(500); // asteptam pentru realizarea conversiei

    uint8_t touchScrpd[] = {
      CMD_READ_SCRATCHPAD,
      /* datele citite scratchpad sunt plasate aici (9 bytes) */
      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
      };

    ow->addressSingle(id);
    ow->touchBytes(touchScrpd, sizeof(touchScrpd));
    uint8_t *scrpd = &touchScrpd[1];  /* datele scratchpad */

    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);  /* bitii nedefiniti devin zero */
      temp = (temp*1000)/16;
      }

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

  Serial.print("  Temperatura: ");
  if (temp < 0) {
    temp = -temp;
    Serial.print('-');
    }

  Serial.print(temp / 1000);
  Serial.print('.');
  Serial.print(temp % 1000);
  Serial.println(" C");
  } while (ec == OneWireNg::EC_MORE);

}

The libraries used are:

I also tried the DallasTemperature library, but it often had conversion/temperature measurement errors.

The operation of the assembly in Proteus can be seen in the video below:

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