А как управлять RGB светодиодом при помощи датчика температуры? То есть менять цвета от зависимости температуры.

folv
Offline
Зарегистрирован: 11.12.2012

Подскажите как управлять RGB светодиодом при помощи датчика температуры? То есть менять цвета от зависимости температуры.

axill
Offline
Зарегистрирован: 05.09.2011

сначала сделать три канала с силовыми ключами управляемые с аналоговых выходов (PWM). Затем сделать замер температуры и последним шагом настроить формулу или таблицу связи температуры с тремя числами от 0 до 255 - значениями яркости каждого из каналов RGB

leshak
Offline
Зарегистрирован: 29.09.2011

axill пишет:

сначала сделать три канала с силовыми ключами управляемые с аналоговых выходов (PWM). Затем сделать замер температуры и последним шагом настроить формулу или таблицу связи температуры с тремя числами от 0 до 255 - значениями яркости каждого из каналов RGB

А я думаю, это нужно делать в таком порядке:

1. Подключить датчик температуры. И на базовых примерах научится с ним работать (получать температуру, отправлять в Serial, зажигать встроенный светодиод при достижении определенной температуры).
2. Отложить в сторону предыдущий скетч и датчик, взять обычный светик (или опять-таки встроенный) и научится управлять его яркостью.
3. Добавить еще два светка, и научится "рулить яркостью" стразу троих, для начала выставлять их в какие-то предопределенные значения.
4. Выкинуть два светика, и научится менять яркость одного в зависимости от температуры. Вначале линейно (чем выше температура - тем ярче светик)
5. То же самое, но зависимость уже не линейная, а по какой-то "формуле" (экспонента, по квадратичному закону и т.п.) или по "табличным значениям".
6. То же самое, но уже для трех светиков. Но табличка связей "температру-яркость" - для каждого светодиода своя.
7. Смотрим на свой RGB светодиод. Если каждый его канал ждерт больше 40-ма, то делаем развязку силовыми ключами или ULN-кой  (вообщем гуглим "ардуина управление мощьной нагрузкой"). Если <=40ma, то пропускаем этот пункт
8. Заменяем три светика на свой RGB диод.
9. Радуемся.

В процессе всех этих разбирательств, не нужно пытатся найти пример "вот в точности такой как у меня". Скажем "научится менять яркость одного в зависимости от температуры". В точности такого примера можно и не найти. Зато можно найти пример, где яркость меняют в зависимости от положения аналогового резистора (кстати этот пример - тоже можно попрбовать). Разобратся с ним, и потом заменить в нем "чтение аналогового входа", на "чтение температуры со своего датчика" (к этому моменту вы уже должны уметь это, если шли по пунктам).

То же самое с "менять по табличному значению". Примера "температура-яркость" - может и не быть. Но может быть пример "температура --> угло сервы". Или "аналоговый вход -->угол сервы".

Точно так же с "силовыми развязками". Смотрим все примеры где ардуина рулит "чем-то мощьным". Разбираемся по каким принципам это делается...

P.S. На самом деле, я не сказал что-то "противоположное" тому что предолжил axill. Иток - тот же самый. Я дал просто "разбивку" как прийти к этому итогу. Разрезал слона на куссочки которые легче прожевать.

 

axill
Offline
Зарегистрирован: 05.09.2011

leshak полностью поддерживаю) у меня просто столько буков не нашлось)

leshak
Offline
Зарегистрирован: 29.09.2011

axill пишет:

leshak полностью поддерживаю) у меня просто столько буков не нашлось)

Ну тогда можно было проще: начните с blink и ПОСТЕПЕННО превращайте его в блекдежк со шлюхами ;)

А вообще меня всегда умиляют попытки построить сразу "вот что-то этакое" (хотя, в данном случае, нужно признать размер "хотелок" довольно скромен и близок к здравому смыслу). Иногда встречаются "я хочу сделать автопилот для боинга, только в програмировании слаб. помогите новичку" :)

Я, с 10-ти летним опытом программинга, и то не возмусь писать что-то больше 10-ти строк "сразу целиком". Только что-то минимальное, и постепенно усложнять. Опять-таки "минимальными шагами". Добавляя только "что-то одно за раз".

axill
Offline
Зарегистрирован: 05.09.2011

Опять согласен) я сам два года газад загорелся идеей сделать свой контроллер приточной вентиляции, чтобы интегрировать его с умным домом. Не самая простая задача чтобы с нее начинать) однако постепенно шаг за шагом я уже очень близок к тому, чтобы сделать ее в один присест. За это время много чего освоил, и про пайку вспомнил и про програмирование и сделал работающие устройства интегрированные с умным домом. В общем большая цель сама по себе это не плохо. Но достичь ее сходу - не разумно. А во. Держа в голове большую цель подбираться к ней шаг за шагом - самое то

vvadim
Offline
Зарегистрирован: 23.05.2012

Полностью солидарен. Я сам по сути новичёк и не программист, но шаг за шагом, по пути читая и вникая в новые для меня темы, получается сделать какие то работающие устройства. Приходится тратить время, задавать вопросы на форуме, но если это интересно и хочется получить результат, то это единственный ПРАВИЛЬНЫЙ подход.

Sergey_Ch
Offline
Зарегистрирован: 15.01.2015

Респект участникам данного форума. Приглашаю единомышленникам объединить усилия в разрезании и поедании слона.

Моя задумка - отображение определенного (задаваемого) диапазона температуры с помощью спектра свечения RGB LED. Сама температура отражается на LCD дисплее, кнопками либо энкодером задаем диапазон температур, подлежащий контролю путем изменения спектра свечения RGB LED.

Применение, например, подсветека парной в бане плавно изменяет свой цвет от холодного - синего до горячего - красного в зависимости от температуры в диапазоне 70-120 градусов. Или светильник изменяет свой цвет зимой в диапазоне от -30(холодно) до -10(жарко). Летом задаем диапазон от +20 до +35, визуальный контроль за температурой в парнике (красиво подсвеченная теплица на участке, чем ни проект?)

Большое отдельное спасибо участнику Leshak за систематизацию задачи.

Для начала, хочу предложить к обсуждению проект приведенный в ссылке http://www.seeedstudio.com/wiki/Grove_-_Chainable_RGB_LED

правда, не все мне здесь нравится, и именно, использование самого RGB LED модуля.

Что касается управления мощными нагрузками, эта задача уже решена многократно. Наример http://habrahabr.ru/post/224621/ или http://cxem.net/beginner/beginner61.php

Но давайте пойдем шаг за шагом, как завещал великий Leshak

Жду идей и предложений, и сам готов по мере возможности публиковать свои наработки.

 

 

 

 

verhmax
Offline
Зарегистрирован: 21.12.2014

используйте функцию map - сам сегодня о ней узнал, очень нужнаю.

примерно так можно реализовать

int red=map(значение температуры, -30, 30, 0, 255);
int green=map(значение температуры, -30, 30, 255, 0);

при температуре -30 светится только зеленый, при +30 только красный, а все промежуточные ардуинка сама вычисляет пропорционально.

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

нужно решать по пунктам, но уже не так как говорил лешак, точнее не совсем. допустим это уже сделали и мы не полные нубы

1. нужно постоить таблицу или график зависимости цвета от температуры (по идее дожно быть уже готово)

2. далее поигравшись со RGB добится нужных цветов и узнать как сделать переходы между ними (аналогично)

3. самое "простое" оформить в виде кода (буйство ума и фантазии. вот тут как раз и можно будет помочь. без исходных данных этот пункт почти бесполезен)

nikolaki
nikolaki аватар
Offline
Зарегистрирован: 14.02.2013

переделайте  стандартный пример из ИДЕ Ардуино switchCase и будет вам и три цвета, и четыре


const int sensorMin = 0;      // sensor minimum, discovered through experiment
const int sensorMax = 600;    // sensor maximum, discovered through experiment


void setup() {
  // initialize serial communication:
  Serial.begin(9600);  
}

void loop() {
  // read the sensor:
  int sensorReading = analogRead(A0);
  // map the sensor range to a range of four options:
  int range = map(sensorReading, sensorMin, sensorMax, 0, 3);

  // do something different depending on the 
  // range value:
  switch (range) {
  case 0:    // your hand is on the sensor
    Serial.println("dark");
    digitalWrite(blueLed,HIGH);
    break;
  case 1:    // your hand is close to the sensor
    Serial.println("dim");
    digitalWrite(greenLed,HIGH);
    break;
  case 2:    // your hand is a few inches from the sensor
    Serial.println("medium");
    digitalWrite(redLed,HIGH);
    break;
  case 3:    // your hand is nowhere near the sensor
    Serial.println("bright");
    digitalWrite(whiteLed,HIGH);
    break;
  } 
  delay(1);        // delay in between reads for stability
}

 

Sergey_Ch
Offline
Зарегистрирован: 15.01.2015

Коллеги, я решил эту задачу. Если интерес не пропал, пишите на форум.

Термостат, работающий в диапазоне температур от -40 до +125, с установлением гистерезиса температур,

спектр свечения RGB LED в зависимости от температуры в заданный max и min значениях.

 

folv
Offline
Зарегистрирован: 11.12.2012

Интерес не пропал!

Sergey_Ch
Offline
Зарегистрирован: 15.01.2015

Уважаемые коллеги,
представляю на ваш суд свой проект. Он вполне рабочий.
Заранее признаю, что код далек от совершенства и свидетельствует о слабом владении языком программирования. Решения искал самостоятельно, кроме Интернета помочь было не кому, а сам я не программист и не электронщик. Поэтому прошу всех любителей и профессионалов присылать свои замечания и предложения. Именно в этом мне и представляется задача данного форума. Не оставайтесь равнодушными, потратьте 3-5 минут своего компьютерного времени, ведь именно это позволит довести проект до возможности его реализации.

Проект выполнен на основе Arduino Leonardo. В основе проекта – термостат, работающий в диапазоне от -50 до +205, оснащенный LCD дисплеем 16х2. Термостат запоминает в EEPROM значения устанавливаемых Max и Min температур. Реле включается при достижении нижнего порога температур и выключается при достижении верхнего порога. Это позволяет без нужды не «дергать» котел отопления за счет времени падения температуры от установленного верхнего предела до нижнего. Возможность установки отрицательных пороговых значений температур добавлена для универсальности данного устройства и расширения возможности его применения. В связи с тем, что EEPROM не сохраняет отрицательных значений, диапазон значений для записи в память изменен. После извлечения из памяти приводится опять в первоначальное состояние.
На дисплее отражаются данные о текущей температуре, измеряемой датчиком DS18B20, состояние выхода реле (OFF, ON), минимальное и максимальное пороговые значения температур.

Если температура, получаемая с датчика находится в пределах температур, заданных в качестве минимальной и максимальной, подключенный к выходам 9,10,11 RGB светодиод меняет свой цвет от синего, при нижнем пороговом уровне, до красного, при верхнем пороговом уровне.

Вот предлагаемый код, который я постарался прокомментировать как можно подробнее.

/***************************************************************************/
#include // подключение библиотеки внутренней памяти
#include // библиотека подключения дисплея по I2C
//ВАЖНО : при использовании I2C устройств - в скетче, библиотека Wire - должна быть объявлена первой,
//иначе - будут ошибки компиляции.
#include // библиотека управления дисплеем по I2C
#include // библиотека управления по однопроводной шине датчиком температуры
#include //библиотека управления датчиком DS18B20
#define ONE_WIRE_BUS 12 //датчик DS18B20 подключен на pin 12

OneWire oneWire(ONE_WIRE_BUS);// Настройка протокола 1-Wire для общения с датчиками в том числе и с DS18B20
DallasTemperature sensors(&oneWire); // Передача данных с DS18B20
LiquidCrystal_I2C lcd(0x27,16,2); // Настройки LCD дисплея: адрес 0x27, 16 символов, 2 строки

uint8_t gradus[8] = {0x0C,0x12,0x12,0x0C,0x0,0x0,0x0}; //создаем символ "градус"
uint8_t line[8] = {0x4,0x0,0x4,0x0,0x4,0x0,0x4}; //создаем символ разделительной черты

#define OUT1 A4 // устанавливаем выход для реле нижнего порогового значения на pin А4
#define OUT2 A5 // устанавливаем выход для реле верхнего порогового значения на pin А5
#define OUT3 A3 // устанавливаем выход на реле термостата на pin А3

int tempMin, tempMax; // задаем переменные для установки нижнего и верхнего пороговых значений температуры
int tempMin_mem, tempMax_mem; // задаем переменные для записи в ЕЕРRОМ данных о пороговых температурах

int red = 9; // определяем пин 9 (ШИМ) для красной линии RGB LED
int green = 10; // определяем пин 10 (ШИМ) для зеленой линии RGB LED
int blue = 11; // определяем пин 11 (ШИМ) для синей линии RGB LED

float tempMin_led, tempMax_led; // задаем переменные для пороговых значений управления RGB LED
float temperature; // задаем переменную для измерения температуры
float delta; // задаем переменную разницы (гистерезиса) пороговых значений температуры

byte key() // задаем возвращаемые значения для переменной KEY - сигнала от кнопок управления
{
int val = analogRead(0); // значение сигнала от кнопок получаем с pin А0
if (val < 50) return 5; // при нажатии кнопки RIGHT возвращаем значение 5
else if (val < 150) return 3; // при нажатии кнопки UP возвращаем значение 3
else if (val < 350) return 4; // при нажатии кнопки DOWN возвращаем значение 4
else if (val < 500) return 2; // при нажатии кнопки LEFT возвращаем значение 2
else if (val < 800) return 1; // при нажатии кнопки SELECT возвращаем значение 1
else return 0; // если кнопки не нажаты - возвращаемое значение 0
}

/************* Подпрограмма меню установок значений температуры **********************/
void SetupMenu()
{
byte position; // задаем переменную для определения позиции меню установок значений температуры
digitalWrite(OUT1, LOW); // при входе в режим установок температуры выключаем все реле
digitalWrite(OUT2, LOW);
digitalWrite(OUT3, LOW);

lcd.clear(); // очищаем экран дисплея
lcd.setCursor(0, 0); // курсор на позицию 0 строки 1
lcd.print("Min ");
lcd.setCursor(0, 1); // курсор на позицию 0 строки 2
lcd.print("Max ");
lcd.blink(); // курсор в мигающем режиме

while(1) // Цикл 1. Условия выхода не установлены. Выход из цикла при перезагрузке контроллера нажатием кнопки RESET
{
byte KEY = key(); // переменная KEY принимает значение key возвращаемое при нажатии кнопок - читаем значение кнопок

lcd.setCursor(4, 0); // курсор на позицию 4 строки 1
// Если нижнее пороговое значение температуры представлено положительным числом от 0 и выше,
// пишем значение, добавляя знак "+", например, +36
if (tempMin > 0)
{
lcd.setCursor(4, 0); // курсор на 4 позицию 1 строки
lcd.print("+");
lcd.print(tempMin); // пишем нижнее пороговое значение температуры
lcd.write(1); // рисуем символ "градус"
}

// Если нижнее пороговое значение температуры имеет отрицательное значение от 0 и ниже,
// пишем значение, со знаком "-", который присваивается программно, например, -3
else if (tempMin <= 0)
{
lcd.setCursor(4, 0); // курсор на 4 позицию 1 строки
lcd.print(tempMin); // пишем нижнее пороговое значение температуры
lcd.write(1); // рисуем символ "градус"
}
lcd.print("C ");

lcd.setCursor(4, 1); // курсор на позицию 4 строки 2

// Если верхнее пороговое значение температуры представлено положительным числом от 0 и выше,
// пишем значение, добавляя знак "+", например, +36
if (tempMax > 0)
{
lcd.setCursor(4, 1); // курсор на 4 позицию 1 строки
lcd.print("+");
lcd.print(tempMax); // пишем верхнее пороговое значение температуры
lcd.write(1); // рисуем символ "градус"
}

// Если верхнее пороговое значение температуры имеет отрицательное значение от 0 и ниже,
// пишем значение, со знаком "-", который присваивается программно, например, -3
else if (tempMax <= 0)
{
lcd.setCursor(4, 1); // курсор на 4 позицию 1 строки
lcd.print(tempMax); // пишем верхнее пороговое значение температуры
lcd.write(1); // рисуем символ "градус"
}
lcd.print("C ");

/***** Обработка команд кнопок, установка и запись в EEPROM пороговых значений температуры ******/
if (position == 0) // в режиме установки нижнего порогового значения температуры
{
lcd.setCursor(3, 0); // курсор на позицию 3 строки 1
if (KEY == 2) // если нажата кнопка 2 "LEFT"
{
tempMin--; // уменьшаем на единицу нижнее пороговое значение температуры
tempMin_mem = map (tempMin,-50,205,0,255); // изменяем значение в формат 0-255 для записи в EEPROM (не запоминает отрицательных значений)
EEPROM.write(1, tempMin_mem); // нижнее пороговое значение температуры сохраняем в ячейке 1 EEPROM
}
else if (KEY == 5) // если нажата кнопка 5 "RIGHT"
{
tempMin++; // увеличиваем на единицу нижнее пороговое значение температуры
tempMin_mem = map (tempMin,-50,205,0,255); // изменяем к положительным значениям
EEPROM.write(1, tempMin_mem); // сохраняем в ячейке 1 EEPROM
}
}

if (position == 1) // в режиме установки верзнего порогового значения температуры
{
lcd.setCursor(3, 1); // курсор на позицию 3 строки 2
if (KEY == 2) // если нажата кнопка 2 "LEFT"
{
tempMax--; // уменьшаем на единицу верхнее пороговое значение температуры
tempMax_mem = map (tempMax,-50,205,0,255); // изменяем значение в формат 0-255 для записи в EEPROM
EEPROM.write(2, tempMax_mem); // верхнее пороговое значение температуры сохраняем в ячейке 2 EEPROM
}
else if (KEY == 5) // если нажата кнопка 5 "RIGHT"
{
tempMax++; // увеличиваем на единицу верхнеее пороговое значение температуры
tempMax_mem = map (tempMax,-50,205,0,255); // изменяем к положительным значениям
EEPROM.write(2, tempMax_mem); // сохраняем в ячейке 2 EEPROM
}
}
/*
Кнопками 3 "UP" и 4 "DOWN" изменяем режим установок
нижнего и верхнего пороговых значений температуры
*/
if (KEY == 3) // если нажата кнопка 3 "UP"
{
position--; // значение режимов меню уменьшаем на 1
}
else if (KEY == 4) // если нажата кнопка 4 "DOWN"
{
position++; // значение режимов меню увеличиваем на 1
}
if (position > 1) // при значении позиции больше 1
{
position = 0; // значение позиции приобретает значение 0
}
delay(200);
}
} // закрываем подпрограмму void SetupMenu
/*****************************************************/

void setup()
{
lcd.init(); // инициализация дисплея
lcd.backlight(); // Включаем подсветку дисплея
lcd.createChar(1, gradus); // записываем в память дисплея символ "градус"
lcd.createChar(2, line); // записываем в память дисплея символ "разделительная линия"

sensors.begin(); // инициализируем датчик температуры

pinMode(OUT1, OUTPUT); // определяем pin реле нижнего порогового значения в качестве выхода
pinMode(OUT2, OUTPUT); // определяем pin реле верхнего порогового значения в качестве выхода
pinMode(OUT3, OUTPUT); // определяем pin реле 3 термостата в качестве выхода
pinMode(red, OUTPUT); // определяем красную линию LED в качестве выхода
pinMode(green, OUTPUT); // определяем зеленую линию LED в качестве выхода
pinMode(blue, OUTPUT); // определяем синюю линию LED в качестве выхода

tempMin_mem = EEPROM.read(1); // читаем из EEPROM записанное нижнее пороговое значение температуры
tempMax_mem = EEPROM.read(2); // читаем из EEPROM записанное верхнее пороговое значение температуры

tempMin = map (tempMin_mem, 0,255,-50,205); // значение из EEPROM переводим в нижнее пороговое значение температуры
tempMax = map (tempMax_mem, 0,255,-50,205); // значение из EEPROM переводим в верхнее пороговое значение температуры

/*******/ Serial.begin(9600);

} // завершаем цикл void setup
/*****************************************************/

void loop()
{
if (key() == 1) // если нажата кнопка 1 "SELECT"
{
SetupMenu(); // запускаем подпрограмму SetupMenu установок пороговых значений температуры
}
else if (key() == 4) // при нажатии кнопки 4 "DOWN"
{
lcd.noBacklight(); // выключаем подсветку дисплея
}
else if (key() == 3) // при нажатии кнопки 3 "UP"
{
lcd.backlight(); // включаем подсветку дисплея
}

sensors.requestTemperatures(); // датчик регистрирует температуру
// переменной temperature присваивается значение, полученное с датчика температуры
float temperature = sensors.getTempCByIndex(0);

/**************** Управление реле термостата *******************/

if (temperature <= tempMin) // если температура ниже нижнего порогового значения
{
digitalWrite(OUT1, HIGH); // включаем Реле 1
}
else
{
digitalWrite(OUT1, LOW); // если нет, выключаем Реле 1
}
if (temperature <= tempMax) // если температура ниже верхнего порогового значения
{
digitalWrite(OUT2, HIGH); // включаем Реле 2
}
else
{
digitalWrite(OUT2, LOW); // если нет, выключаем Реле 2
}
/* Реле 3 термостата включено до достижения верхнего порогового значения.
После достижения верхнего порогового значения, реле 3 отключается
и включается при падении температуры ниже нижнего порогового значения.
Температура поддерживается в диапазоне от нижнего до верхнегоо пороговых значений.
*/

if ((digitalRead(OUT1)) && (digitalRead(OUT2))) // если получаем значение с выходов OUT1 и OUT2
{
digitalWrite(OUT3, HIGH); // включаем реле 3 термостата
}
else if (!digitalRead(OUT2)) // если игнорируем значение с выхода OUT2
{
digitalWrite(OUT3, LOW); // выключаем реле 3 термостата
}

/***** Пишем первую строку дисплея *******************/

lcd.setCursor(0, 0); // курсор на 0 позицию 1 строки
lcd.print("Min");
lcd.setCursor(4, 0); // курсор на 4 позицию 1 строки

// Если нижнее пороговое значение температуры представлено двухзначным числом от 10 до 99,
// пишем значение, добавляя знак "+", например, +36
if ((tempMin >= 10)&&(tempMin < 100))
{
lcd.setCursor(4, 0); // курсор на 4 позицию 1 строки
lcd.print("+");
lcd.print(tempMin); // пишем нижнее пороговое значение температуры
lcd.write(1); // рисуем символ "градус"
}

// Если нижнее пороговое значение температуры имеет отрицательное однозначное значение от -10 до 0,
// пишем значение, со знаком "-", который присваивается программно, например, -3
else if ((tempMin > -10)&&(tempMin <= 0))
{
lcd.setCursor(4, 0); // курсор на 4 позицию 1 строки
lcd.print(tempMin); // пишем нижнее пороговое значение температуры
lcd.write(1); // рисуем символ "градус"
}

// Если нижнее пороговое значение температуры имеет положительное однозначное значение от 0 до 10,
// пишем значение, добавляя знак "+", например, +6
else if ((tempMin < 10)&&(tempMin >= 0))
{
lcd.setCursor(4, 0); // курсор на 4 позицию 1 строки
lcd.print("+");
lcd.print(tempMin); // выводим нижнее пороговое значение температуры
lcd.write(1); // рисуем символ "градус"
}

// во всех остальных случаях, когда выводится 3-х символьное значение:
// если нижнее пороговое значение температуры положительное трехзначное, например, 102 (знак "+" не добавляется)
// если нижнее пороговое значение температуры отрицательное двухзначное, например, -18
else
{
lcd.setCursor(4, 0); // курсор на 4 позицию 1 строки
lcd.print(tempMin); // выводим нижнее пороговое значение температуры
lcd.write(1); // рисуем символ "градус"
}

lcd.setCursor(8, 0); // курсор на 8 позицию 1 строки
lcd.write(2); // рисуем разделительную линию

lcd.setCursor(9, 0); // курсор на 9 позицию 1 строки

/* Выводим значение текущей температуры и сносим лишние символы при переходе разряда показаний.
Должно быть пять символов отображения текущей температуры, с учетом того, что датчик сам
присваивает знак "-" отрицательным значениям
*/
// Если температура имеет двухзначное значение до запятой, от 10 до 99,
// пишем ее, добавляя знак "+", например, +36,6
if ((temperature >= 10)&&(temperature < 100))
{
lcd.setCursor(9, 0); // курсор на 9 позицию 1 строки
lcd.print("+");
lcd.print(temperature, 1); // выводим текущее значение температуры, (значение 1 - два знака после запятой)
lcd.setCursor(14, 0); // курсор на 14 позицию 1 строки
lcd.write(1); // рисуем символ "градус"
lcd.setCursor(15, 0); // курсор на 15 позицию 1 строки
lcd.print("C");
}

// Если температура имеет отрицательное однозначное значение до запятой, от -10 до 0,
// пишем ее, со знаком "-", который напишет сам датчик например, -3,6
else if ((temperature > -10)&&(temperature <= 0))
{
lcd.setCursor(10, 0); // курсор на 10 позицию 1 строки
lcd.print(temperature, 1); // выводим текущее значение температуры
lcd.setCursor(14, 0); // курсор на 14 позицию 1 строки
lcd.write(1); // рисуем символ "градус"
lcd.setCursor(15, 0); // курсор на 15 позицию 1 строки
lcd.print("C");
}

// Если температура имеет положительное однозначное значение до запятой, от 0 до 10,
// пишем ее, со знаком "+", например, +3,6
else if ((temperature < 10)&&(temperature >= 0))
{
lcd.setCursor(10, 0); // курсор на 12 позицию 1 строки
lcd.print("+");
lcd.print(temperature, 1); // выводим текущее значение температуры
lcd.setCursor(14, 0); // курсор на 14 позицию 1 строки
lcd.write(1); // рисуем символ "градус"
lcd.setCursor(15, 0); // курсор на 15 позицию 1 строки
lcd.print("C");
}

// во всех остальных случаях, когда выводится пяти символьное значение:
// если значение температуры положительное трехзначное, например, 102,5 (знак "+" не добавляется)
// если значение температуры отрицательное двухзначное, например, -18,4
else
{
lcd.setCursor(9, 0); // курсор на 9 позицию 1 строки
lcd.print(temperature, 1); // выводим текущее значение температуры
lcd.setCursor(14, 0); // курсор на 14 позицию 1 строки
lcd.write(1); // рисуем символ "градус"
lcd.setCursor(15, 0); // курсор на 15 позицию 1 строки
lcd.print("C");
}

/****** Пишем вторую строку дисплея ********************/
lcd.setCursor(0, 1); // курсор на 0 позицию 2 строки
lcd.print("Max");
lcd.setCursor(4, 1); // курсор на 4 позицию 2 строки

// Если верхнее пороговое значение температуры представлено двухзначным числом от 10 до 99,
// пишем значение, добавляя знак "+", например, +36
if ((tempMax >= 10)&&(tempMax < 100))
{
lcd.setCursor(4, 1); // курсор на 4 позицию 1 строки
lcd.print("+");
lcd.print(tempMax); // пишем верхнее пороговое значение температуры
lcd.write(1); // рисуем символ "градус"
}

// Если верхнее пороговое значение температуры имеет отрицательное однозначное значение от -10 до 0,
// пишем значение, со знаком "-", который присваивается программно, например, -3
else if ((tempMax > -10)&&(tempMax <= 0))
{
lcd.setCursor(4, 1); // курсор на 4 позицию 1 строки
lcd.print(tempMax); // пишем верхнее пороговое значение температуры
lcd.write(1); // рисуем символ "градус"
}

// Если верхнее пороговое значение температуры имеет положительное однозначное значение от 0 до 10,
// пишем значение, добавляя знак "+", например, +6
else if ((tempMax < 10)&&(tempMax >= 0))
{
lcd.setCursor(4, 1); // курсор на 4 позицию 1 строки
lcd.print("+");
lcd.print(tempMax); // выводим верхнее пороговое значение температуры
lcd.write(1); // рисуем символ "градус"
}

// во всех остальных случаях, когда выводится 3-х символьное значение:
// если верхнее пороговое значение температуры положительное трехзначное, например, 102 (знак "+" не добавляется)
// если верхнее пороговое значение температуры отрицательное двухзначное, например, -18
else
{
lcd.setCursor(4, 1); // курсор на 4 позицию 1 строки
lcd.print(tempMax); // выводим верхнее пороговое значение температуры
lcd.write(1); // рисуем символ "градус"
}

lcd.setCursor(8, 1); // курсор на 8 позицию 1 строки
lcd.write(2); // рисуем разделительную линию

lcd.setCursor(9,1); // курсор на 8 позицию 2 строки
lcd.print("OUT");
lcd.setCursor(13,1); // курсор на 8 позицию 2 строки

if (digitalRead(OUT3)) // если получаем значение с выхода 3
{
lcd.print("ON "); // пишем состояние реле 3 "ON"
}
else // в противном случае
{
lcd.print("OFF"); // пишем состояние реле 3 "OFF"
}
delay(100); // пауза 0.1 секунда

/************* Управление R G B L E D ********************************/
/* устанавливаем тип переменных tempMin_led и tempMax_led для вычислений с плавающей запятой
и определяем их значение равное установленным пороговым значениям температур */
tempMin_led = (float)tempMin / 1.0;
tempMax_led = (float)tempMax / 1.0;

/* значение переменной delta вычисляем как положительное значение разницы пороговых температур
разделенное на 25 оттенков цветового спектра, подлежащего отображению RGB LED в зависимости
от температуры и в пределах значений заданных параметрами tempMin и tempMax
(с учетом того, что всегда tempMin < tempMax) */
delta = ((tempMax_led - tempMin_led) / 25); // разницу температур / 25 оттенков

/* Устанавливаем уровень ШИМ сигнала на красной, зеленой и синей линиях RGB
в зависимости от температуры и в пределах значений заданных параметрами tempMin и tempMax
путем поэтапного прибавления к значению нижнего уровня температуры кратного значения delta
*/

if (temperature < tempMin_led) // при значении температуры ниже нижнего заданного значения
{
analogWrite (red, 0); // отображается синий
analogWrite (green, 0);
analogWrite (blue, 255);
}

/* Четыре основных этапа изменение цвета:
1. От синего к голубому
2. От голубого к зеленому
3. От зеленого к желтому
4. От желтого к красному
Каждый этап состоит из 6 частей.
Значение ШИМ = 255 / 6 = 42.5. Округленно 42 = шаг изменения значения функции analogWrite
*/

// от синего к голубому
else if (temperature >= tempMin_led && temperature <= (tempMin_led + delta))
{
analogWrite (red, 0);
analogWrite (green, 0);
analogWrite (blue, 255);
}
else if (temperature > (tempMin_led + delta) && temperature <= (tempMin_led + (2*delta)))
{
analogWrite (red, 0);
analogWrite (green, 42);
analogWrite (blue, 255);
}
else if (temperature >(tempMin_led+(2*delta)) && temperature <= (tempMin_led + (3*delta)))
{
analogWrite (red, 0);
analogWrite (green, 85);
analogWrite (blue, 255);
}
else if (temperature > (tempMin_led + (3*delta)) && temperature <= (tempMin_led + (4*delta)))
{
analogWrite (red, 0);
analogWrite (green, 127);
analogWrite (blue, 255);
}
else if (temperature > (tempMin_led + (4*delta)) && temperature <= (tempMin_led + (5*delta)))
{
analogWrite (red, 0);
analogWrite (green, 170);
analogWrite (blue, 255);
}
else if (temperature > (tempMin_led + (5*delta)) && temperature <= (tempMin_led + (6*delta)))
{
analogWrite (red, 0);
analogWrite (green, 212);
analogWrite (blue, 255);
}
else if (temperature > (tempMin_led + (6*delta)) && temperature <= (tempMin_led + (7*delta)))
{
analogWrite (red, 0);
analogWrite (green, 255);
analogWrite (blue, 255);
}

// от голубого к зеленому
else if (temperature > (tempMin_led + (7*delta)) && temperature <= (tempMin_led + (8*delta)))
{
analogWrite (red, 0);
analogWrite (green, 255);
analogWrite (blue, 212);
}
else if (temperature > (tempMin_led + (8*delta)) && temperature <= (tempMin_led + (9*delta)))
{
analogWrite (red, 0);
analogWrite (green, 255);
analogWrite (blue, 170);
}
else if (temperature > (tempMin_led + (9*delta)) && temperature <= (tempMin_led + (10*delta)))
{
analogWrite (red, 0);
analogWrite (green, 255);
analogWrite (blue, 127);
}
else if (temperature > (tempMin_led + (10*delta)) && temperature <= (tempMin_led + (11*delta)))
{
analogWrite (red, 0);
analogWrite (green, 255);
analogWrite (blue, 85);
}
else if (temperature > (tempMin_led + (11*delta)) && temperature <= (tempMin_led + (12*delta)))
{
analogWrite (red, 0);
analogWrite (green, 255);
analogWrite (blue, 42);
}
else if (temperature > (tempMin_led + (12*delta)) && temperature <= (tempMin_led + (13*delta)))
{
analogWrite (red, 0);
analogWrite (green, 255);
analogWrite (blue, 0);
}

// от зеленого к желтому
else if (temperature > (tempMin_led + (13*delta)) && temperature <= (tempMin_led + (14*delta)))
{
analogWrite (red, 42);
analogWrite (green, 255);
analogWrite (blue, 0);
}
else if (temperature > (tempMin_led + (14*delta)) && temperature <= (tempMin_led + (15*delta)))
{
analogWrite (red, 85);
analogWrite (green, 255);
analogWrite (blue, 0);
}
else if (temperature > (tempMin_led + (15*delta)) && temperature <= (tempMin_led + (16*delta)))
{
analogWrite (red, 127);
analogWrite (green, 255);
analogWrite (blue, 0);
}
else if (temperature > (tempMin_led + (16*delta)) && temperature <= (tempMin_led + (17*delta)))
{
analogWrite (red, 170);
analogWrite (green, 255);
analogWrite (blue, 0);
}
else if (temperature > (tempMin_led + (17*delta)) && temperature <= (tempMin_led + (18*delta)))
{
analogWrite (red, 212);
analogWrite (green, 255);
analogWrite (blue, 0);
}
else if (temperature > (tempMin_led + (18*delta)) && temperature <= (tempMin_led + (19*delta)))
{
analogWrite (red, 255);
analogWrite (green, 255);
analogWrite (blue, 0);
}

// от желтого к красному
else if (temperature > (tempMin_led + (19*delta)) && temperature <= (tempMin_led + (20*delta)))
{
analogWrite (red, 255);
analogWrite (green, 212);
analogWrite (blue, 0);
}
else if (temperature > (tempMin_led + (20*delta)) && temperature <= (tempMin_led + (21*delta)))
{
analogWrite (red, 255);
analogWrite (green, 170);
analogWrite (blue, 0);
}
else if (temperature > (tempMin_led + (21*delta)) && temperature <= (tempMin_led + (22*delta)))
{
analogWrite (red, 255);
analogWrite (green, 127);
analogWrite (blue, 0);
}
else if (temperature > (tempMin_led + (22*delta)) && temperature <= (tempMin_led + (23*delta)))
{
analogWrite (red, 255);
analogWrite (green, 85);
analogWrite (blue, 0);
}
else if (temperature > (tempMin_led + (23*delta)) && temperature <= (tempMin_led + (24*delta)))
{
analogWrite (red, 255);
analogWrite (green, 42);
analogWrite (blue, 0);
}
else if (temperature > (tempMin_led + (24*delta)) && temperature <= (tempMin_led + (25*delta)))
{
analogWrite (red, 255);
analogWrite (green, 0);
analogWrite (blue, 0);
}

else if (temperature >= tempMax_led) // при значении температуры выше высшего заданного значения
{
analogWrite (red, 255); // отображается красный
analogWrite (green, 0);
analogWrite (blue, 0);
}

/******/ Serial.print("temperature ");
/******/ Serial.println(temperature);
/******/ Serial.print("Min ");
/******/ Serial.println(tempMin);
/******/ Serial.print("Max ");
/******/ Serial.println(tempMax);
/******/ Serial.print("OUT ");
/******/ if (digitalRead(OUT3)) {Serial.println("ON");}
/******/ else {Serial.println("OFF");}

} // закрываем цикл void loop
/**************************************************************************/

В данном сообщении, я не стал вдаваться в технические подробности устройства и подробные описания его компонентов.
Если кому интересно, пишите на личную почту (адрес s-chuprin@mail.ru ), пришлю схемы, описание, фото и все остальное.

Удачи всем, жду Ваших замечаний и правок.

Кстати, вот проект,
http://ergoz.ru/electronics/arduino/rgb-led-strip-upravlyaemyiy-arduino....
в котором светодиод изменяет цвет в зависимости от диапазона температур, задаваемых в программном коде. Я этот проект повторил на макетной плате. Работает, в том числе в диапазоне отрицательных значений (у меня в морозильной камере -16 гр.). Цвет RGB диода изменяется плавно без скачков. Красиво, но RGB диоды в этом проекте горят слабо, в пол силы. Интересно, почему? А так проект совсем не плох и мог бы быть основой для разработки собственных устройств. Тем более, что аналогичных проектов не так много на российских и зарубежных сайтах.

Вот теперь все. Жду комментариев.

Sergey_Ch
Offline
Зарегистрирован: 15.01.2015

#include <EEPROM.h> // подключение библиотеки внутренней памяти
#include <Wire.h> // библиотека подключения дисплея по I2C 
//ВАЖНО : при использовании I2C устройств - в скетче, библиотека Wire - должна быть объявлена первой,
//иначе - будут ошибки компиляции. 
#include <LiquidCrystal_I2C.h> // библиотека управления дисплеем по I2C
#include <OneWire.h> // библиотека управления по однопроводной шине датчиком температуры
#include <DallasTemperature.h> //библиотека управления датчиком DS18B20
#define ONE_WIRE_BUS 12 //датчик DS18B20 подключен на pin 12

OneWire oneWire(ONE_WIRE_BUS);// Настройка протокола 1-Wire для общения с датчиками в том числе и с DS18B20
DallasTemperature sensors(&oneWire); // Передача данных с DS18B20
LiquidCrystal_I2C lcd(0x27,16,2);  // Настройки LCD дисплея: адрес 0x27, 16 символов, 2 строки
 
uint8_t gradus[8] = {0x0C,0x12,0x12,0x0C,0x0,0x0,0x0}; //создаем символ "градус"
uint8_t line[8] = {0x4,0x0,0x4,0x0,0x4,0x0,0x4}; //создаем символ разделительной черты

#define OUT1 A4 // устанавливаем выход для реле нижнего порогового значения на pin А4
#define OUT2 A5 // устанавливаем выход для реле верхнего порогового значения на pin А5
#define OUT3 A3 // устанавливаем выход на реле термостата на pin А3

int tempMin, tempMax; // задаем переменные для установки нижнего и верхнего пороговых значений температуры
int tempMin_mem, tempMax_mem; // задаем переменные для записи в ЕЕРRОМ данных о пороговых температурах

int red = 9;    // определяем пин 9 (ШИМ) для красной линии RGB LED  
int green = 10; // определяем пин 10 (ШИМ) для зеленой линии RGB LED   
int blue = 11;  // определяем пин 11 (ШИМ) для синей линии RGB LED     

float tempMin_led, tempMax_led; // задаем переменные для пороговых значений управления RGB LED
float temperature; // задаем переменную для измерения температуры
float delta; // задаем переменную разницы (гистерезиса) пороговых значений температуры

byte key() // задаем возвращаемые значения для переменной KEY - сигнала от кнопок управления 
   { 
    int val = analogRead(0);       // значение сигнала от кнопок получаем с pin А0
    if (val < 50) return 5;        // при нажатии кнопки RIGHT возвращаем значение 5
    else if (val < 150) return 3;  // при нажатии кнопки UP возвращаем значение 3
    else if (val < 350) return 4;  // при нажатии кнопки DOWN возвращаем значение 4
    else if (val < 500) return 2;  // при нажатии кнопки LEFT возвращаем значение 2
    else if (val < 800) return 1;  // при нажатии кнопки SELECT возвращаем значение 1
    else return 0;                 // если кнопки не нажаты - возвращаемое значение 0
   }

/************* Подпрограмма меню установок значений температуры **********************/
void SetupMenu()
{ 
 byte position; // задаем переменную для определения позиции меню установок значений температуры
 digitalWrite(OUT1, LOW); // при входе в режим установок температуры выключаем все реле
 digitalWrite(OUT2, LOW);
 digitalWrite(OUT3, LOW);

  lcd.clear(); // очищаем экран дисплея
  lcd.setCursor(0, 0); // курсор на позицию 0 строки 1 
  lcd.print("Min ");
  lcd.setCursor(0, 1); // курсор на позицию 0 строки 2
  lcd.print("Max ");
  lcd.blink(); // курсор в мигающем режиме
  
  while(1) // Цикл 1. Условия выхода не установлены. Выход из цикла при перезагрузке контроллера нажатием кнопки RESET
 {
  byte KEY = key(); // переменная KEY принимает значение key возвращаемое при нажатии кнопок - читаем значение кнопок
    
  lcd.setCursor(4, 0); // курсор на позицию 4 строки 1
   // Если нижнее пороговое значение температуры представлено положительным числом от 0 и выше,
   // пишем значение, добавляя знак "+", например, +36 
    if (tempMin > 0) 
     {
      lcd.setCursor(4, 0); // курсор на 4 позицию 1 строки
      lcd.print("+");
      lcd.print(tempMin); // пишем нижнее пороговое значение температуры
      lcd.write(1);       // рисуем символ "градус"
     }
     
  // Если нижнее пороговое значение температуры имеет отрицательное значение от 0 и ниже,
  // пишем значение, со знаком "-", который присваивается программно, например, -3 
   else if (tempMin <= 0)
     {
      lcd.setCursor(4, 0);        // курсор на 4 позицию 1 строки
      lcd.print(tempMin);         // пишем нижнее пороговое значение температуры
      lcd.write(1);               // рисуем символ "градус"
     }
    lcd.print("C  ");
 
  lcd.setCursor(4, 1); // курсор на позицию 4 строки 2
 
   // Если верхнее пороговое значение температуры представлено положительным числом от 0 и выше,
   // пишем значение, добавляя знак "+", например, +36 
    if (tempMax > 0) 
     {
      lcd.setCursor(4, 1); // курсор на 4 позицию 1 строки
      lcd.print("+");
      lcd.print(tempMax); // пишем верхнее пороговое значение температуры
      lcd.write(1);       // рисуем символ "градус"
     }
     
  // Если верхнее пороговое значение температуры имеет отрицательное значение от 0 и ниже,
  // пишем значение, со знаком "-", который присваивается программно, например, -3 
   else if (tempMax <= 0)
     {
      lcd.setCursor(4, 1);        // курсор на 4 позицию 1 строки
      lcd.print(tempMax);         // пишем верхнее пороговое значение температуры
      lcd.write(1);               // рисуем символ "градус"
     }
   lcd.print("C  ");

/***** Обработка команд кнопок, установка и запись в EEPROM пороговых значений температуры ******/ 
   if (position == 0) // в режиме установки нижнего порогового значения температуры
    {  
      lcd.setCursor(3, 0); // курсор на позицию 3 строки 1
      if (KEY == 2) // если нажата кнопка 2 "LEFT"
       {
        tempMin--; // уменьшаем на единицу нижнее пороговое значение температуры
        tempMin_mem = map (tempMin,-50,205,0,255); // изменяем значение в формат 0-255 для записи в EEPROM (не запоминает отрицательных значений)
        EEPROM.write(1, tempMin_mem); // нижнее пороговое значение температуры сохраняем в ячейке 1 EEPROM
       }
      else if (KEY == 5) // если нажата кнопка 5 "RIGHT"
         {
          tempMin++; // увеличиваем на единицу нижнее пороговое значение температуры
          tempMin_mem = map (tempMin,-50,205,0,255); // изменяем к положительным значениям 
          EEPROM.write(1, tempMin_mem);     // сохраняем в ячейке 1 EEPROM
         }    
    }
    
    if (position == 1) // в режиме установки верзнего порогового значения температуры 
     { 
      lcd.setCursor(3, 1); // курсор на позицию 3 строки 2
      if (KEY == 2) // если нажата кнопка 2 "LEFT"
       {
        tempMax--; // уменьшаем на единицу верхнее пороговое значение температуры
        tempMax_mem = map (tempMax,-50,205,0,255); // изменяем значение в формат 0-255 для записи в EEPROM
        EEPROM.write(2, tempMax_mem); // верхнее пороговое значение температуры сохраняем в ячейке 2 EEPROM
       }
      else if (KEY == 5) // если нажата кнопка 5 "RIGHT"
         {
          tempMax++; // увеличиваем на единицу верхнеее пороговое значение температуры
          tempMax_mem = map (tempMax,-50,205,0,255); // изменяем к положительным значениям 
          EEPROM.write(2, tempMax_mem);    // сохраняем в ячейке 2 EEPROM 
         }    
    }
    /*
    Кнопками 3 "UP" и 4 "DOWN" изменяем режим установок 
    нижнего и верхнего пороговых значений температуры
    */
    if (KEY == 3) // если нажата кнопка 3 "UP" 
     {
      position--; // значение режимов меню уменьшаем на 1
     } 
    else if (KEY == 4) // если нажата кнопка 4 "DOWN"
       {
        position++; // значение режимов меню увеличиваем на 1
       }  
    if (position > 1) // при значении позиции больше 1
     {
      position = 0; // значение позиции приобретает значение 0
     } 
    delay(200);
  }
} // закрываем подпрограмму void SetupMenu
/*****************************************************/

void setup()
{
  lcd.init(); // инициализация дисплея
  lcd.backlight(); // Включаем подсветку дисплея
  lcd.createChar(1, gradus); // записываем в память дисплея символ "градус"
  lcd.createChar(2, line); // записываем в память дисплея символ "разделительная линия"

  sensors.begin(); // инициализируем датчик температуры

  pinMode(OUT1, OUTPUT);   // определяем pin реле нижнего порогового значения в качестве выхода 
  pinMode(OUT2, OUTPUT);   // определяем pin реле верхнего порогового значения в качестве выхода 
  pinMode(OUT3, OUTPUT);   // определяем pin реле 3 термостата в качестве выхода 
  pinMode(red, OUTPUT);    // определяем красную линию LED в качестве выхода
  pinMode(green, OUTPUT);  // определяем зеленую линию LED в качестве выхода
  pinMode(blue, OUTPUT);   // определяем синюю линию LED в качестве выхода

tempMin_mem = EEPROM.read(1); // читаем из EEPROM записанное нижнее пороговое значение температуры 
tempMax_mem = EEPROM.read(2); // читаем из EEPROM записанное верхнее пороговое значение температуры

tempMin = map (tempMin_mem, 0,255,-50,205); // значение из EEPROM переводим в нижнее пороговое значение температуры
tempMax = map (tempMax_mem, 0,255,-50,205); // значение из EEPROM переводим в верхнее пороговое значение температуры

/*******/ Serial.begin(9600);

} // завершаем цикл void setup
/*****************************************************/

void loop()
 {  
  if (key() == 1) // если нажата кнопка 1 "SELECT"
   {
    SetupMenu(); // запускаем подпрограмму SetupMenu установок пороговых значений температуры
   } 
  else if (key() == 4) // при нажатии кнопки 4 "DOWN"
      {
      lcd.noBacklight(); // выключаем подсветку дисплея
      }
  else if (key() == 3) // при  нажатии кнопки 3 "UP"
      {
      lcd.backlight(); // включаем подсветку дисплея
      }

 sensors.requestTemperatures(); // датчик регистрирует температуру
 // переменной temperature присваивается значение, полученное с датчика температуры 
 float temperature = sensors.getTempCByIndex(0);  
 
/**************** Управление реле термостата *******************/

 if (temperature <= tempMin)  // если температура ниже нижнего порогового значения
  { 
  digitalWrite(OUT1, HIGH);     // включаем Реле 1 
  }
 else
    {
     digitalWrite(OUT1, LOW); // если нет, выключаем Реле 1
    }
 if (temperature <= tempMax)  // если температура ниже верхнего порогового значения
   {
    digitalWrite(OUT2, HIGH);     // включаем Реле 2
   }
 else
    {
     digitalWrite(OUT2, LOW); // если нет, выключаем Реле 2
    } 
/* Реле 3 термостата включено до достижения верхнего порогового значения.
После достижения верхнего порогового значения, реле 3 отключается
и включается при падении температуры ниже нижнего порогового значения.
Температура поддерживается в диапазоне от нижнего до верхнегоо пороговых значений.
*/

if ((digitalRead(OUT1)) && (digitalRead(OUT2))) // если получаем значение с выходов OUT1 и OUT2
     {
      digitalWrite(OUT3, HIGH); // включаем реле 3 термостата
     }    
else if (!digitalRead(OUT2)) // если игнорируем значение с выхода OUT2
     {
     digitalWrite(OUT3, LOW); // выключаем реле 3 термостата
     }  

/***** Пишем первую строку дисплея *******************/

  lcd.setCursor(0, 0); // курсор на 0 позицию 1 строки
  lcd.print("Min"); 
  lcd.setCursor(4, 0); // курсор на 4 позицию 1 строки
    
   // Если нижнее пороговое значение температуры представлено двухзначным числом от 10 до 99,
   // пишем значение, добавляя знак "+", например, +36 
    if ((tempMin >= 10)&&(tempMin < 100)) 
     {
      lcd.setCursor(4, 0); // курсор на 4 позицию 1 строки
      lcd.print("+");
      lcd.print(tempMin); // пишем нижнее пороговое значение температуры
      lcd.write(1);       // рисуем символ "градус"
     }
     
  // Если нижнее пороговое значение температуры имеет отрицательное однозначное значение от -10 до 0,
  // пишем значение, со знаком "-", который присваивается программно, например, -3 
   else if ((tempMin > -10)&&(tempMin <= 0))
     {
      lcd.setCursor(4, 0);        // курсор на 4 позицию 1 строки
      lcd.print(tempMin);         // пишем нижнее пороговое значение температуры
      lcd.write(1);               // рисуем символ "градус"
     }
 
 // Если нижнее пороговое значение температуры имеет положительное однозначное значение от 0 до 10,
 // пишем значение, добавляя знак "+", например, +6  
  else if ((tempMin < 10)&&(tempMin >= 0))
    {
     lcd.setCursor(4, 0);      // курсор на 4 позицию 1 строки
     lcd.print("+");
     lcd.print(tempMin);        // выводим нижнее пороговое значение температуры
     lcd.write(1);              // рисуем символ "градус"
    }

 // во всех остальных случаях, когда выводится 3-х символьное значение:
 // если нижнее пороговое значение температуры положительное трехзначное, например, 102 (знак "+" не добавляется)
 // если нижнее пороговое значение температуры отрицательное двухзначное, например, -18 
  else
    {
    lcd.setCursor(4, 0);       // курсор на 4 позицию 1 строки
    lcd.print(tempMin);        // выводим нижнее пороговое значение температуры
    lcd.write(1);              // рисуем символ "градус"
    }

  lcd.setCursor(8, 0); // курсор на 8 позицию 1 строки 
  lcd.write(2);        // рисуем разделительную линию 

  lcd.setCursor(9, 0); // курсор на 9 позицию 1 строки  

/* Выводим значение текущей температуры и сносим лишние символы при переходе разряда показаний.
   Должно быть пять символов отображения текущей температуры, с учетом того, что датчик сам 
   присваивает знак "-" отрицательным значениям
*/
  // Если температура имеет двухзначное значение до запятой, от 10 до 99,
  // пишем ее, добавляя знак "+", например, +36,6 
    if ((temperature >= 10)&&(temperature < 100)) 
     {
      lcd.setCursor(9, 0);      // курсор на 9 позицию 1 строки
      lcd.print("+");
      lcd.print(temperature, 1); // выводим текущее значение температуры, (значение 1 - два знака после запятой)
      lcd.setCursor(14, 0);       // курсор на 14 позицию 1 строки
      lcd.write(1);               // рисуем символ "градус"
      lcd.setCursor(15, 0);       // курсор на 15 позицию 1 строки
      lcd.print("C");  
     }
     
  // Если температура имеет отрицательное однозначное значение до запятой, от -10 до 0,
  // пишем ее, со знаком "-", который напишет сам датчик например, -3,6 
   else if ((temperature > -10)&&(temperature <= 0))
     {
      lcd.setCursor(10, 0);       // курсор на 10 позицию 1 строки
      lcd.print(temperature, 1);  // выводим текущее значение температуры
      lcd.setCursor(14, 0);       // курсор на 14 позицию 1 строки
      lcd.write(1);               // рисуем символ "градус"
      lcd.setCursor(15, 0);       // курсор на 15 позицию 1 строки
      lcd.print("C");  
     }
 
 // Если температура имеет положительное однозначное значение до запятой, от 0 до 10,
 // пишем ее, со знаком "+", например, +3,6  
  else if ((temperature < 10)&&(temperature >= 0))
    {
     lcd.setCursor(10, 0);      // курсор на 12 позицию 1 строки
     lcd.print("+");
     lcd.print(temperature, 1); // выводим текущее значение температуры
     lcd.setCursor(14, 0);      // курсор на 14 позицию 1 строки
     lcd.write(1);              // рисуем символ "градус"
     lcd.setCursor(15, 0);      // курсор на 15 позицию 1 строки
     lcd.print("C");  
    }

 // во всех остальных случаях, когда выводится пяти символьное значение:
 // если значение температуры положительное трехзначное, например, 102,5 (знак "+" не добавляется)
 // если значение температуры отрицательное двухзначное, например, -18,4 
  else
    {
    lcd.setCursor(9, 0);       // курсор на 9 позицию 1 строки
    lcd.print(temperature, 1); // выводим текущее значение температуры
    lcd.setCursor(14, 0);      // курсор на 14 позицию 1 строки
    lcd.write(1);              // рисуем символ "градус"
    lcd.setCursor(15, 0);      // курсор на 15 позицию 1 строки
    lcd.print("C");  
    }

/****** Пишем вторую строку дисплея ********************/
  lcd.setCursor(0, 1); // курсор на 0 позицию 2 строки
  lcd.print("Max");
  lcd.setCursor(4, 1); // курсор на 4 позицию 2 строки
 
   // Если верхнее пороговое значение температуры представлено двухзначным числом от 10 до 99,
   // пишем значение, добавляя знак "+", например, +36 
    if ((tempMax >= 10)&&(tempMax < 100)) 
     {
      lcd.setCursor(4, 1); // курсор на 4 позицию 1 строки
      lcd.print("+");
      lcd.print(tempMax); // пишем верхнее пороговое значение температуры
      lcd.write(1);       // рисуем символ "градус"
     }
     
  // Если верхнее пороговое значение температуры имеет отрицательное однозначное значение от -10 до 0,
  // пишем значение, со знаком "-", который присваивается программно, например, -3 
   else if ((tempMax > -10)&&(tempMax <= 0))
     {
      lcd.setCursor(4, 1);        // курсор на 4 позицию 1 строки
      lcd.print(tempMax);         // пишем верхнее пороговое значение температуры
      lcd.write(1);               // рисуем символ "градус"
     }
 
 // Если верхнее пороговое значение температуры имеет положительное однозначное значение от 0 до 10,
 // пишем значение, добавляя знак "+", например, +6  
  else if ((tempMax < 10)&&(tempMax >= 0))
    {
     lcd.setCursor(4, 1);      // курсор на 4 позицию 1 строки
     lcd.print("+");
     lcd.print(tempMax);        // выводим верхнее пороговое значение температуры
     lcd.write(1);              // рисуем символ "градус"
    }

 // во всех остальных случаях, когда выводится 3-х символьное значение:
 // если верхнее пороговое значение температуры положительное трехзначное, например, 102 (знак "+" не добавляется)
 // если верхнее пороговое значение температуры отрицательное двухзначное, например, -18 
  else
    {
    lcd.setCursor(4, 1);       // курсор на 4 позицию 1 строки
    lcd.print(tempMax);        // выводим верхнее пороговое значение температуры
    lcd.write(1);              // рисуем символ "градус"
    }
  
  lcd.setCursor(8, 1); // курсор на 8 позицию 1 строки 
  lcd.write(2); // рисуем разделительную линию 

  lcd.setCursor(9,1);  // курсор на 8 позицию 2 строки 
  lcd.print("OUT");
  lcd.setCursor(13,1);  // курсор на 8 позицию 2 строки

    if (digitalRead(OUT3))  // если получаем значение с выхода 3
     {
     lcd.print("ON ");      // пишем состояние реле 3 "ON"
     }
    else // в противном случае
      {
       lcd.print("OFF");    // пишем состояние реле 3 "OFF"
      }
  delay(100); // пауза 0.1 секунда


/************* Управление  R G B   L E D   ********************************/
  /* устанавливаем тип переменных tempMin_led и tempMax_led для вычислений с плавающей запятой
     и определяем их значение равное установленным пороговым значениям температур */
  tempMin_led = (float)tempMin / 1.0; 
  tempMax_led = (float)tempMax / 1.0;
  
  /* значение переменной delta вычисляем как положительное значение разницы пороговых температур
     разделенное на 25 оттенков цветового спектра, подлежащего отображению RGB LED в зависимости
     от температуры и в пределах значений заданных параметрами tempMin и tempMax
     (с учетом того, что всегда tempMin < tempMax) */
  delta = ((tempMax_led - tempMin_led) / 25); // разницу температур / 25 оттенков

/* Устанавливаем уровень ШИМ сигнала на красной, зеленой и синей линиях RGB 
   в зависимости от температуры и в пределах значений заданных параметрами tempMin и tempMax
   путем поэтапного прибавления к значению нижнего уровня температуры кратного значения delta
*/

if (temperature < tempMin_led) // при значении температуры ниже нижнего заданного значения
{
analogWrite (red, 0);    // отображается синий
analogWrite (green, 0);
analogWrite (blue, 255);
}

/* Четыре основных этапа изменение цвета:
  1. От синего к голубому                      
  2. От голубого к зеленому
  3. От зеленого к желтому
  4. От желтого к красному
  Каждый этап состоит из 6 частей.
  Значение ШИМ = 255 / 6 = 42.5. Округленно 42 = шаг изменения значения функции analogWrite 
*/

// от синего к голубому
else if (temperature >= tempMin_led && temperature <= (tempMin_led + delta))
{
analogWrite (red, 0);    
analogWrite (green, 0);
analogWrite (blue, 255);
}
else if (temperature > (tempMin_led + delta) && temperature <= (tempMin_led + (2*delta)))
{
analogWrite (red, 0);    
analogWrite (green, 42);
analogWrite (blue, 255);
}
else if (temperature >(tempMin_led+(2*delta)) && temperature <= (tempMin_led + (3*delta)))
{
analogWrite (red, 0);    
analogWrite (green, 85);
analogWrite (blue, 255);
}
else if (temperature > (tempMin_led + (3*delta)) && temperature <= (tempMin_led + (4*delta)))
{
analogWrite (red, 0);    
analogWrite (green, 127);
analogWrite (blue, 255);
}
else if (temperature > (tempMin_led + (4*delta)) && temperature <= (tempMin_led + (5*delta)))
{
analogWrite (red, 0);
analogWrite (green, 170);
analogWrite (blue, 255);
}
else if (temperature > (tempMin_led + (5*delta)) && temperature <= (tempMin_led + (6*delta)))
{
analogWrite (red, 0); 
analogWrite (green, 212);
analogWrite (blue, 255);
}
else if (temperature > (tempMin_led + (6*delta)) && temperature <= (tempMin_led + (7*delta)))
{
analogWrite (red, 0);    
analogWrite (green, 255);
analogWrite (blue, 255);
}

// от голубого к зеленому
else if (temperature > (tempMin_led + (7*delta)) && temperature <= (tempMin_led + (8*delta)))
{
analogWrite (red, 0);    
analogWrite (green, 255);
analogWrite (blue, 212);
}
else if (temperature > (tempMin_led + (8*delta)) && temperature <= (tempMin_led + (9*delta)))
{
analogWrite (red, 0);    
analogWrite (green, 255);
analogWrite (blue, 170);
}
else if (temperature > (tempMin_led + (9*delta)) && temperature <= (tempMin_led + (10*delta)))
{
analogWrite (red, 0);
analogWrite (green, 255);
analogWrite (blue, 127);
}
else if (temperature > (tempMin_led + (10*delta)) && temperature <= (tempMin_led + (11*delta)))
{
analogWrite (red, 0); 
analogWrite (green, 255);
analogWrite (blue, 85);
}
else if (temperature > (tempMin_led + (11*delta)) && temperature <= (tempMin_led + (12*delta)))
{
analogWrite (red, 0); 
analogWrite (green, 255);
analogWrite (blue, 42);
}
else if (temperature > (tempMin_led + (12*delta)) && temperature <= (tempMin_led + (13*delta)))
{
analogWrite (red, 0);  
analogWrite (green, 255);
analogWrite (blue, 0);
}

// от зеленого к желтому
else if (temperature > (tempMin_led + (13*delta)) && temperature <= (tempMin_led + (14*delta)))
{
analogWrite (red, 42);    
analogWrite (green, 255);
analogWrite (blue, 0);
}
else if (temperature > (tempMin_led + (14*delta)) && temperature <= (tempMin_led + (15*delta)))
{
analogWrite (red, 85);    
analogWrite (green, 255);
analogWrite (blue, 0);
}
else if (temperature > (tempMin_led + (15*delta)) && temperature <= (tempMin_led + (16*delta)))
{
analogWrite (red, 127); 
analogWrite (green, 255);
analogWrite (blue, 0);
}
else if (temperature > (tempMin_led + (16*delta)) && temperature <= (tempMin_led + (17*delta)))
{
analogWrite (red, 170);  
analogWrite (green, 255);
analogWrite (blue, 0);
}
else if (temperature > (tempMin_led + (17*delta)) && temperature <= (tempMin_led + (18*delta)))
{
analogWrite (red, 212);
analogWrite (green, 255);
analogWrite (blue, 0);
}
else if (temperature > (tempMin_led + (18*delta)) && temperature <= (tempMin_led + (19*delta)))
{
analogWrite (red, 255);
analogWrite (green, 255);
analogWrite (blue, 0);
}

// от желтого к красному
else if (temperature > (tempMin_led + (19*delta)) && temperature <= (tempMin_led + (20*delta)))
{
analogWrite (red, 255);
analogWrite (green, 212);
analogWrite (blue, 0);
}
else if (temperature > (tempMin_led + (20*delta)) && temperature <= (tempMin_led + (21*delta)))
{
analogWrite (red, 255);
analogWrite (green, 170);
analogWrite (blue, 0);
}
else if (temperature > (tempMin_led + (21*delta)) && temperature <= (tempMin_led + (22*delta)))
{
analogWrite (red, 255);
analogWrite (green, 127);
analogWrite (blue, 0);
}
else if (temperature > (tempMin_led + (22*delta)) && temperature <= (tempMin_led + (23*delta)))
{
analogWrite (red, 255);
analogWrite (green, 85);
analogWrite (blue, 0);
}
else if (temperature > (tempMin_led + (23*delta)) && temperature <= (tempMin_led + (24*delta)))
{
analogWrite (red, 255);
analogWrite (green, 42);
analogWrite (blue, 0);
}
else if (temperature > (tempMin_led + (24*delta)) && temperature <= (tempMin_led + (25*delta)))
{
analogWrite (red, 255);
analogWrite (green, 0);
analogWrite (blue, 0);
}

else if (temperature >= tempMax_led) // при значении температуры выше высшего заданного значения
{
analogWrite (red, 255); // отображается красный
analogWrite (green, 0);
analogWrite (blue, 0);
}

/******/ Serial.print("temperature ");
/******/ Serial.println(temperature);
/******/ Serial.print("Min ");
/******/ Serial.println(tempMin);
/******/ Serial.print("Max ");
/******/ Serial.println(tempMax);
/******/ Serial.print("OUT ");
/******/ if (digitalRead(OUT3)) {Serial.println("ON");}
/******/ else {Serial.println("OFF");}
    
} // закрываем цикл void loop

Вот теперь нормально.

bwn
Offline
Зарегистрирован: 25.08.2014

Самый первый коммент, код лучше вставлять правильно , иначе очень не читабельно.
Как вы умудрились получить 205гр/С с Далласом? С EEPROM кажется намудрили, оставьте целочисленные значения и старший знаковый бит, будет -127 до 127. Если хочется больше, то двухбайтовое int. Ну и перебор значений наверно в For будет изящнее.

А так, интересненько, сам хочу нечто подобное замутить, только в виде ночника с погодной станцией.

Пока писал, уже исправились, еще сворачивать научится))))

Sergey_Ch
Offline
Зарегистрирован: 15.01.2015

Спасибо за первый комментарий.

Конечно, получить с Далласа 205 гр не получится, я и не пытался. Грел зажигалкой до 110. Как в бане.

С EEPROM  буду дальше думать. В коде написал первое, что пришло в голову. Хотя еще не вижу пути иного решения.

А вот за идею о применении цикла for - для перебора цветов, отдельное спасибо. Если я правильно понимаю, циклов for будет четыре, аналгичо как у меня четыре блока перебора цветов от син. к гол., от гол. к зел., от зел. к желт., от желт. к красн. Если датите подсказку, тоже огромное спасибо. 

В описании, я не стал вдаваться в технические подробности устройства и подробные описания его компонентов. Если кому интересно, пишите на личную почту (адрес: s-chuprin@mail.ru ), пришлю схемы, описание, фото и все остальное.

Интересно Ваше мнение по решению аналогичных задач в проекте http://ergoz.ru/electronics/arduino/rgb-led-strip-upravlyaemyiy-arduino.... в котором светодиод изменяет цвет в зависимости от диапазона температур, задаваемых в программном коде. Не понимаю, как в этом проекте происходит перебор цветов и что намудрил этот мастер. Я этот проект повторил на макетной плате. Работает, в том числе в диапазоне отрицательных значений (у меня в морозильной камере -16 гр.). Цвет RGB диода изменяется плавно без скачков. Красиво, но RGB диоды в этом проекте горят слабо, в пол силы. Тоже интересно, почему?

bwn
Offline
Зарегистрирован: 25.08.2014

С епромом для однобайтовых целочисленных так:

#include <EEPROM.h> // подключение библиотеки внутренней памяти

float a=-100.35;
char b;

void setup(){
  
  Serial.begin(9600);
}

void loop(){
  b=a;
  Serial.println(b,DEC);
  EEPROM.write(101,b);
  delay(2000);
  b=EEPROM.read(101);
  Serial.println(b,DEC);
  delay(1000000);
}

Ключевое слово "char".