#include <LiquidCrystal_I2C.h>          // подключение библиотеки для работы с дисплеем по шине I2C 

#define a_data    A0                    // константа с номером пина для получения данных с термистора   
#define rOut      11                    // константа с номером пина отвечающего за красный цвет светодиода RGB (ШИМ)1500
#define gOut      10                    // константа с номером пина отвечающего за зеленый цвет светодиода RGB (ШИМ)
#define bOut      9                     // константа с номером пина отвечающего за синий цвет светодиода RGB (ШИМ)

#define lcd1_i2c  0x27                                 // константа с адресом первого дисплея   
#define lcd2_i2c  0x3F                                 // константа с адресом второго дисплея 
#define lcd1_col  20                                   // константа с длиной строки первого дисплея 
#define lcd1_lin  4                                    // константа с числом строк первого дисплея 
#define lcd2_col  20                                   // константа с длиной строки второго дисплея 
#define lcd2_lin  4                                    // константа с числом строк второго дисплея 

LiquidCrystal_I2C lcd1(lcd1_i2c, lcd1_col, lcd1_lin);  // объявление объекта lcd1 с передачей параметров 
LiquidCrystal_I2C lcd2(lcd2_i2c, lcd2_col, lcd2_lin);  // объявление объекта lcd2 с передачей параметров 

const float betac = 3950;                              // B-коэффициент термистора
byte rS = 0;                                           // значение ШИМ красного цвета
byte gS = 0;                                           // значение ШИМ зеленого цвета
byte bS = 0;                                           // значение ШИМ синего цвета 

void setup() {
 
  pinMode(a_data, INPUT);                              // определение режима для пина термистора как входа 
  pinMode(rS, OUTPUT);                                 // определение режима работы пина rS как выхода
  pinMode(gS, OUTPUT);                                 // определение режима работы пина gS как выхода
  pinMode(bS, OUTPUT);                                 // определение режима работы пина bS как выхода

  lcd1.init();                                         // инициализация работы с дисплеем №1 (lcd1)   
  lcd1.backlight();                                    // включение подсветки дисплея №1 (lcd1)  

  lcd2.init();                                         // инициализация работы с дисплеем №2 (lcd2)  
  lcd2.backlight();                                    // включение подсветки дисплея №2 (lcd2)  

}

void loop() {

  int a_value = analogRead(a_data);                   // чтение аналоговых данных с пина термистора
  float c_temp = 1 / (log(1 / (1023. / a_value - 1)) / betac + 1.0 / 298.15) - 273.15; //пересчет значения ацп в градусы цельсия
  
  if (a_value <= 315) {                               //задаем диапазон уровня сигнала с датчика для синего цвета
      byte c_vl = map(a_value, 115, 315, 255, 0);     //пересчет уровня сигнала ДТ в диапазон значений ШИМ  
      rS = 255;                                       //
      gS = 255 - c_vl;                                //запись уровня сигнала ШИМ в переменные задания цвета
      bS = 0;                                         //
                                                                           
    } else if (a_value > 315 && a_value <= 530) {     //задаем диапазон уровня сигнала с датчика для зеленого цвета
      byte c_vl = map(a_value, 315, 530, 255, 0);     //пересчет уровня сигнала ДТ в диапазон значений ШИМ  
      rS = c_vl;                                      //
      gS = 255;                                       //запись уровня сигнала ШИМ в переменные задания цвета
      bS = 0;                                         //

    } else if (a_value > 530 && a_value <= 745) {     //задаем диапазон уровня сигнала с датчика для желтого цвета
      byte c_vl = map(a_value, 530, 745, 255, 0);     //пересчет уровня сигнала ДТ в диапазон значений ШИМ
      rS = 0;                                         //
      gS = 255;                                       //запись уровня сигнала ШИМ в переменные задания цвета
      bS = 255 - c_vl;                                //

    } else if (a_value > 745 && a_value <= 953) {     //задаем диапазон уровня сигнала с датчика для красного цвета
      byte c_vl = map(a_value, 745, 953, 255, 0);     //пересчет уровня сигнала ДТ в диапазон значений ШИМ  
      rS = 0;                                         //
      gS = c_vl;                                      //запись уровня сигнала ШИМ в переменные задания цвета
      bS = 255;                                       //
    }
  
  analogWrite(rOut, rS);                              //  
  analogWrite(gOut, gS);                              //передача сигнала ШИМ на пины светодиода RGB
  analogWrite(bOut, bS);                              //

  lcd1.setCursor(8,0);                                // установка курсора на определённую позицию (lcd1)
  lcd1.print("lcd1");                                 // вывод сообщения на первой (0) строке (lcd1)    
  lcd1.setCursor(1,2);                                // установка курсора на определённую позицию (lcd1)
  lcd1.print("lcd1 adress:  0x");                     // вывод сообщения на третьей (2) строке (lcd1)  
  lcd1.print(lcd1_i2c, HEX);                          // вывод содержимого lcd1_i2c в HEX-формате
  lcd1.setCursor(1,3);                                // установка курсора на определённую позицию (lcd1)
  lcd1.print("lcd2 adress:  0x");                     // вывод сообщения на четвертой (3) строке (lcd1)  
  lcd1.print(lcd2_i2c, HEX);                          // вывод содержимого lcd2_i2c в HEX-формате

  lcd2.setCursor(8,0);                                // установка курсора на определённую позицию (lcd2)
  lcd2.print("lcd2");                                 // вывод сообщения на первой (0) строке (lcd2)
  lcd2.setCursor(3,1);                                // установка курсора на определённую позицию (lcd2)
  lcd2.print("Temp: ");                               // вывод сообщения на второй (1) строке (lcd2)

  int tempPos = 8;                                    // переменная для начальной позиции вывода температуры

  if (c_temp >= 10) {                                 //  
    lcd2.setCursor(tempPos,1);                        // вывод сообщения с показаниями термистора   
    lcd2.print("  ");                                 // в градусах цельсия 
  }                                                   // условия проверяют значение c_temp в 4 дипазонах
  else if (c_temp < 10 && c_temp >= 0) {              // 1. больше или равно 10
    lcd2.setCursor(tempPos,1);                        // 2. меньше 10 и больше или равно 0
    lcd2.print("   ");                                // 3. меньше 0 и больше -10
  }                                                   // 4. меньше -10 
  else if (c_temp < 0 && c_temp > -10) {              // в зависимости от выполнения условия 
    lcd2.setCursor(tempPos,1);                        // меняется количество пробелов перед выводом c_temp
    lcd2.print("  ");                                 // сделано это в попытке зафиксировать выравнивание  
  }                                                   // вывода температуры к правому краю  
  else{                                               // вроде работает) 
    lcd2.setCursor(tempPos,1);                        // 
    lcd2.print(" ");                                  // 
  }

  lcd2.print(c_temp);                                 // вывод содержимого c_temp 
  lcd2.print(char(223));                              // вывод символа градус  
  lcd2.print("C");                                    //

  lcd2.setCursor(1,2);                                // установка курсора на определённую позицию (lcd2)
  lcd2.print("HEX Color: ");                          // вывод сообщения на третьей (2) строке (lcd2)
  lcd2.print(hcConvert(rS, gS, bS));                  // вывод кода текущего цвета светодиода RGB в HEX Color Code (#FFFFFF)

  lcd2.setCursor(0,3);                                // установка курсора на определённую позицию (lcd2)
  lcd2.print(rgbStr(rS, gS, bS));                     // вывод сообщения на четвертой (3) строке (lcd2)
  //                                                  // с кодом текущего цвета светодиода в формате RGB
}

String hcConvert(byte Rd, byte Gn, byte Bl){          // функция преобразования переменных сигнала ШИМ (светодиод RGB)
  char hxValue[] = {};                                // в строку вида "#FFFFFF"
  sprintf(hxValue, "#%02X%02X%02X", Rd, Gn, Bl);      // в основе лежит функция sprint, которая возвращает отформатированную   
  return String(hxValue);                             // строку из переменных в виде массива
}

String rgbStr(byte Rd, byte Gn, byte Bl){                       // функция преобразования переменных сигнала ШИМ 
  char colValue[] = {};                                         // (светодиод RGB) в строку вида "R:255  G:255  B:255"
  sprintf(colValue, "R:%003u  G:%003u  B:%003u", Rd, Gn, Bl);   // в основе лежит функция sprint, которая возвращает 
  return String(colValue);                                      // отформатированную строку из переменных в виде массива
}