// https://wokwi.com/projects/411353543794137089

// modified from https://wokwi.com/projects/395145162627749889
// Datasheet: https://www.analog.com/media/en/technical-documentation/data-sheets/DS18B20.pdf
// Comparison: https://www.analog.com/en/resources/design-notes/1wire-protocol-pdf-of-ds18s20-vs-ds18b20-digital-themormeters.html
// DallasTemperature.h https://github.com/milesburton/Arduino-Temperature-Control-Library
// WokwiChip: https://github.com/bonnyr/wokwi-ds1820-custom-chip
/*
  PROGRAM:
  Name         Add_tempsensor.ino
  Version:     02d
  Author:      C.W.A. Baltus
  Created:     8-12-2021
  Edited by:   C.W.A. Baltus
  Modified:    22-12-2021

  WHAT DOES THIS PROGRAM:
  Stores the adresses of 4 pieces of temperaturesensors DS18b20 in an EEPROM (on board of Arduino) in the same order as the sensors step by step are added.
  It takes 4 *  8 bytes = 32 bytes; the Nano can contain 512 bytes.

  Afterwords the addresses can be read out and assigned to byte arrays:
  adrTcvForth[8] (uint8_t)
  adrTcvBack[8]
  adrTvvForth[8]
  adrTvvBack[8]

  HARDWARE:
  - Arduino Nano V3
  - LCD 2004 with I2C-interface (SDA pin A4, SCL pin A5)
  - 4 pieces 1 wire temperature sensors Dallas DS1620b20 (pin D12, with pullup resistor 4k7)

  TESTED ON:
  IDE 1.8.16 and Arduino Nano

  Tutorials:
  http://www.hacktronics.com/Tutorials/arduino-1-wire-address-finder.html
  https://www.pjrc.com/teensy/td_libs_OneWire.html
*/

//========================================================================
//Libraries
#include <DallasTemperature.h> // https://github.com/milesburton/Arduino-Temperature-Control-Library
#include <EEPROM.h>
//#include <LCD.h>
//#include <LiquidCrystal_I2C.h>   // Source: LiquidCrystal_V1.2.1.zip
#include <OneWire.h>
#include <Wire.h>
#include <hd44780.h> // #include <hd44780ioClass/hd44780_I2Cexp.h> // i2c LCD i/o class header
#include <hd44780ioClass/hd44780_I2Cexp.h> // i2c LCD i/o class header

hd44780_I2Cexp lcd;

// Data wire is plugged into port 2 on the Arduino
#define ONE_WIRE_BUS 2

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

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

// variable to hold device addresses
DeviceAddress Thermometer;

int deviceCount = 0;


//Define global parameters
byte i;    //position within arraybye
byte j = 0; //Number of ds passed

uint8_t adrTcvForward[8];
uint8_t adrTcvBack[8];
uint8_t adrTvvForward[8];
uint8_t adrTvvBack[8];
String myString;

const byte invordering[] = {7, 3, 1, 5, 0, 4, 2, 6};
const byte ordering[] = {4, 2, 6, 1, 5, 3, 7, 0};

int status;

//========================================================================
void setup(void) {
  Serial.begin(11520);

  status = lcd.begin(20, 4);
  if (status) // non zero status means it was unsuccesful
  {
    // hd44780 has a fatalError() routine that blinks an led if possible
    // begin() failed so blink error code using the onboard LED if possible
    hd44780::fatalError(status); // does not return
  }
  setupDallas(); // from https://lastminuteengineers.com/multiple-ds18b20-arduino-tutorial/

}  //End setup

//========================================================================
void loop(void) {
  //Nothing to do
  uint32_t t0 = micros();
  if(loopDallasRead()){
    uint32_t t1 = micros();
    Serial.println(t1-t0);
  }
} //End loop


// void setupOtherDS() {
//   //This call has to be moved to a control menu (so it will be executed once)
//   Identify_1WireDevices();
//   delay (1000);

//   //Assign a bytearray once to adrTcvForth
//   for (int i = 0; i < 8; i++) {
//     adrTcvForward[i] = EEPROM.read(100 + i);
//   }
//   for (int i = 0; i < 8; i++) {
//     adrTcvBack[i] =   EEPROM.read(108 + i);
//   }
//   for (int i = 0; i < 8; i++) {
//     adrTvvForward[i] = EEPROM.read(116 + i);
//   }
//   for (int i = 0; i < 8; i++) {
//     adrTvvBack[i] =   EEPROM.read(124 + i);
//   }


//   //Check addresses on serial monitor
//   Serial.println("");
//   Serial.print("Adres sensor1 = "); printAddress(adrTcvForward);
//   Serial.print("Adres sensor2 = "); printAddress(adrTcvBack);
//   Serial.print("Adres sensor3 = "); printAddress(adrTvvForward);
//   Serial.print("Adres sensor4 = "); printAddress(adrTvvBack);
// }

// //========================================================================
// void Identify_1WireDevices(void) {
//   boolean blnExists;
//   byte addr[8];
//   byte addr1[8];
//   byte addr2[8];
//   byte addr3[8];
//   byte addr4[8];
//   int intSensorsPassed = 0;

//   Serial.print("Looking for 1-Wire devices...\n\r");
//   lcd.clear(); lcd.print ("Connect sensor 1");

//   do   {   //Should be done 4 times
//     while (ds.search(addr))
//     {
//       //printAddress(addr);
//       if ( OneWire::crc8( addr, 7) != addr[7]) {
//         Serial.print("CRC is not valid!\n");
//         delay (100);
//         break;
//       }

//       if (addr[0] != 0x10) {
//         Serial.print(addr[0], HEX);
//         Serial.println (" Not a DS18b20");  //The least significant byte of the DS18b20 should be 0x28
//         break;
//       }


//       switch (intSensorsPassed) {
//         case 0:
//           memcpy (addr1, addr, 8);  //Store the first addres in addr1
//           intSensorsPassed++;
//           Serial.print ("Assigned to " + String(intSensorsPassed) + ": "); printAddress(addr1); cr();
//           Serial.println ("Sensors passed = " + String(intSensorsPassed) + "\n");
//           lcd.setCursor(0, intSensorsPassed); lcd.print ("Add sensor " + String(intSensorsPassed + 1));
//           break;
//         case 1:
//           //check if the address was earlier identified
//           //Serial.println("\nIncoming address = "); printAddress(addr);
//           if (memcmp(addr1, addr, 8) != 0) {
//             //Serial.println("Unknown sensor found");   //Seems to be another (new) address
//             memcpy (addr2, addr, 8);    //Store the addess in addr2
//             intSensorsPassed++;
//             Serial.print ("Assigned to " + String(intSensorsPassed) + ": "); printAddress(addr2); cr();
//             Serial.println ("Sensors passed = " + String(intSensorsPassed) + "\n");
//             lcd.setCursor(0, intSensorsPassed); lcd.print ("Add sensor " + String(intSensorsPassed + 1));
//           }  //End if
//           break;
//         case 2:
//           //check if the address was earlier identified
//           if ((memcmp(addr, addr1, 8) != 0)  && (memcmp(addr, addr2, 8) != 0)) {
//             //Serial.println("Unknown sensor found");   //Seems to be another (new) address
//             memcpy (addr3, addr, 8); //Copy the addess to addr3
//             intSensorsPassed++;
//             Serial.print ("Assigned to " + String(intSensorsPassed) + ": "); printAddress(addr3); cr();
//             Serial.println ("Sensors passed = " + String(intSensorsPassed) + "\n");
//             lcd.setCursor(0, intSensorsPassed); lcd.print ("Add sensor " + String(intSensorsPassed + 1));
//           }  //End if
//           break;
//         case 3:
//           //check if the address was earlier identified
//           if ((memcmp(addr, addr1, 8) != 0)  && (memcmp(addr, addr2, 8) != 0)  && (memcmp(addr, addr3, 8) != 0) ) {
//             //Serial.println("Unknown sensor found");   //Seems to be another (new) address
//             memcpy (addr4, addr, 8);  //Copy the addess to addr4
//             //printAddress(addr); Serial.print("\n");
//             intSensorsPassed++;
//             Serial.print ("Assigned to " + String(intSensorsPassed) + ": "); printAddress(addr4); cr();
//             Serial.println ("Sensors passed = " + String(intSensorsPassed) + "\n");
//           }  //End if
//           break;
//       } //End switch

//     }    //End while sensors Passed
//     delay (500);
//   } while (intSensorsPassed < 4);

//   //Store the detected addresses in EEPROM
//   for ( i = 0; i < 8; i++)
//   {
//     EEPROM.write( (100 + i), addr1[i] );
//     EEPROM.write( (108 + i), addr2[i] );
//     EEPROM.write( (116 + i), addr3[i] );
//     EEPROM.write( (124 + i), addr4[i] );
//   }

//   Serial.print("\n\nThat's it.");

// } //End function


// //================================================================================================================
// void printAddress(uint8_t temp2[]) {
//   int i;
//   for ( i = 0; i < 8; i++) {
//     Serial.print("0x");  //Starting with the least significant byte

//     if (temp2[i] < 16) {
//       Serial.print('0'); //print a prevealing zero if necessary
//     }
//     Serial.print(temp2[i], HEX); ;
//     if (i < 7)
//     {
//       Serial.print(", "); //print a separator between all bytes
//     }
//   }   //End for loop
//   Serial.print("\n");
// }  //End subroutine

// //================================================================================================================
// void cr()
// {
//   Serial.println("\n");
// }




void setupDallas(void)
{
  // from https://lastminuteengineers.com/multiple-ds18b20-arduino-tutorial/
  // Start up the library
  sensors.begin();

  // locate devices on the bus
  Serial.println("Locating devices...");
  Serial.print("Found ");
  deviceCount = sensors.getDeviceCount();
  Serial.print(deviceCount, DEC);
  Serial.println(" devices.");
  Serial.println("");

  Serial.println("Printing addresses...");
  for (int i = 0;  i < deviceCount;  i++)
  {
    Serial.print("Sensor ");
    Serial.print(i + 1);
    Serial.print(" : ");
    sensors.getAddress(Thermometer, i);
    printAddress(Thermometer);
  }
}

// void loop(void)
// {}

void printAddress(DeviceAddress deviceAddress)
{
  for (uint8_t i = 0; i < 8; i++)
  {
    Serial.print("0x");
    if (deviceAddress[i] < 0x10) Serial.print("0");
    Serial.print(deviceAddress[i], HEX);
    if (i < 7) Serial.print(", ");
  }
  Serial.println("");
}

bool loopDallasRead(void)
{
  bool retval = false;
  const uint32_t interval = 1000;
  static uint32_t last = -interval;
  uint32_t now = millis();
  if (now - last >= interval) {
    last+= interval;
    // Send command to all the sensors for temperature conversion
    sensors.requestTemperatures();

    // Display temperature from each sensor
    for (int i = 0;  i < deviceCount/4;  i++)
    {
      byte jj = ordering[i]; // lookup logical sensor(physpos)
      float tempC;
      Serial.print("S");
      Serial.print(i + 1);
      Serial.print(":");
      tempC = sensors.getTempCByIndex(jj);
      Serial.print(tempC);
      Serial.print(" ");
      //lcd.setCursor(10 * (i & 1 ), i / 2);
      //lcd.print(i + 1); lcd.print(':'); lcd.print(tempC, 3);
      //lcd.print(" ");
    }
    Serial.println();
    retval = true;
  }
  return retval;
}
1-5 are diagram.json waveForm controlled || 6-8 click-to-adjust.