#include <OneWire.h>
#include <DallasTemperature.h>
#include <LiquidCrystal_I2C.h>

const byte I2C_ADDR = 0x27;
const byte LCD_COLUMNS = 20;
const byte LCD_LINES= 4;

LiquidCrystal_I2C lcd(I2C_ADDR, LCD_COLUMNS, LCD_LINES);

// Connect DS18B29 to Arduino pin D12.
const byte ONE_WIRE_BUS = 12;

// Setup a OneWire instance to communicate with any OneWire devices.
OneWire oneWire(ONE_WIRE_BUS);

// Pass our OneWire reference to Dallas Temperature sensor.
DallasTemperature sensors(&oneWire);

 byte numDevices = 0;

// Initialization of sensor and serial communication.
void setup()
{
  Serial.begin(115200);

  lcd.init();
  lcd.backlight();
  lcd.setCursor(0, 0);
  lcd.print("Temperatures:");
  sensors.begin();

  byte address[8];

  while (oneWire.search(address))
  {
    Serial.print("Bus index=");
    Serial.print(numDevices);
    Serial.print(";  Device address=");
    for(byte i = 0; i < 8; i++)
    {
      Serial.print(address[i], HEX);
      Serial.print(" ");
    }
    Serial.println();
    numDevices++;
  }
}

const byte LCD_BUFFER_LENGTH = 20;
char lcdBuffer[LCD_BUFFER_LENGTH + 1];  // One extra for NULL terminator.
const char LCD_BUFFER_FORMAT[] = "  %d: %s\xDF\x43            ";  // Escape the two characters for °C because DF merges in to C as a valid hex number.

void loop()
{
  if (numDevices > 0)
  {
    sensors.requestTemperatures();

    for (byte i = 0; i < numDevices; i++)
    {
      float temperatureCelsius = sensors.getTempCByIndex(i);

      Serial.print("Bus index=");
      Serial.print(i);
      Serial.print(";  Temperature=");
      Serial.print(temperatureCelsius);
      Serial.println("°C");

      char floatBuffer[20];
      snprintf(lcdBuffer, LCD_BUFFER_LENGTH, LCD_BUFFER_FORMAT, i, dtostrf(temperatureCelsius, 8, 3, floatBuffer));
      lcd.setCursor(0, i + 1);
      lcd.print(lcdBuffer);
    }
  }

  delay(1000);
}