А как управлять 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 - сам сегодня о ней узнал, очень нужнаю.

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

1int red=map(значение температуры, -30, 30, 0, 255);
2int 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 и будет вам и три цвета, и четыре

01const int sensorMin = 0;      // sensor minimum, discovered through experiment
02const int sensorMax = 600;    // sensor maximum, discovered through experiment
03 
04 
05void setup() {
06  // initialize serial communication:
07  Serial.begin(9600); 
08}
09 
10void loop() {
11  // read the sensor:
12  int sensorReading = analogRead(A0);
13  // map the sensor range to a range of four options:
14  int range = map(sensorReading, sensorMin, sensorMax, 0, 3);
15 
16  // do something different depending on the
17  // range value:
18  switch (range) {
19  case 0:    // your hand is on the sensor
20    Serial.println("dark");
21    digitalWrite(blueLed,HIGH);
22    break;
23  case 1:    // your hand is close to the sensor
24    Serial.println("dim");
25    digitalWrite(greenLed,HIGH);
26    break;
27  case 2:    // your hand is a few inches from the sensor
28    Serial.println("medium");
29    digitalWrite(redLed,HIGH);
30    break;
31  case 3:    // your hand is nowhere near the sensor
32    Serial.println("bright");
33    digitalWrite(whiteLed,HIGH);
34    break;
35  }
36  delay(1);        // delay in between reads for stability
37}

 

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
001#include <EEPROM.h> // подключение библиотеки внутренней памяти
002#include <Wire.h> // библиотека подключения дисплея по I2C
003//ВАЖНО : при использовании I2C устройств - в скетче, библиотека Wire - должна быть объявлена первой,
004//иначе - будут ошибки компиляции.
005#include <LiquidCrystal_I2C.h> // библиотека управления дисплеем по I2C
006#include <OneWire.h> // библиотека управления по однопроводной шине датчиком температуры
007#include <DallasTemperature.h> //библиотека управления датчиком DS18B20
008#define ONE_WIRE_BUS 12 //датчик DS18B20 подключен на pin 12
009 
010OneWire oneWire(ONE_WIRE_BUS);// Настройка протокола 1-Wire для общения с датчиками в том числе и с DS18B20
011DallasTemperature sensors(&oneWire); // Передача данных с DS18B20
012LiquidCrystal_I2C lcd(0x27,16,2);  // Настройки LCD дисплея: адрес 0x27, 16 символов, 2 строки
013  
014uint8_t gradus[8] = {0x0C,0x12,0x12,0x0C,0x0,0x0,0x0}; //создаем символ "градус"
015uint8_t line[8] = {0x4,0x0,0x4,0x0,0x4,0x0,0x4}; //создаем символ разделительной черты
016 
017#define OUT1 A4 // устанавливаем выход для реле нижнего порогового значения на pin А4
018#define OUT2 A5 // устанавливаем выход для реле верхнего порогового значения на pin А5
019#define OUT3 A3 // устанавливаем выход на реле термостата на pin А3
020 
021int tempMin, tempMax; // задаем переменные для установки нижнего и верхнего пороговых значений температуры
022int tempMin_mem, tempMax_mem; // задаем переменные для записи в ЕЕРRОМ данных о пороговых температурах
023 
024int red = 9;    // определяем пин 9 (ШИМ) для красной линии RGB LED 
025int green = 10; // определяем пин 10 (ШИМ) для зеленой линии RGB LED  
026int blue = 11;  // определяем пин 11 (ШИМ) для синей линии RGB LED    
027 
028float tempMin_led, tempMax_led; // задаем переменные для пороговых значений управления RGB LED
029float temperature; // задаем переменную для измерения температуры
030float delta; // задаем переменную разницы (гистерезиса) пороговых значений температуры
031 
032byte key() // задаем возвращаемые значения для переменной KEY - сигнала от кнопок управления
033   {
034    int val = analogRead(0);       // значение сигнала от кнопок получаем с pin А0
035    if (val < 50) return 5;        // при нажатии кнопки RIGHT возвращаем значение 5
036    else if (val < 150) return 3;  // при нажатии кнопки UP возвращаем значение 3
037    else if (val < 350) return 4;  // при нажатии кнопки DOWN возвращаем значение 4
038    else if (val < 500) return 2;  // при нажатии кнопки LEFT возвращаем значение 2
039    else if (val < 800) return 1;  // при нажатии кнопки SELECT возвращаем значение 1
040    else return 0;                 // если кнопки не нажаты - возвращаемое значение 0
041   }
042 
043/************* Подпрограмма меню установок значений температуры **********************/
044void SetupMenu()
045{
046 byte position; // задаем переменную для определения позиции меню установок значений температуры
047 digitalWrite(OUT1, LOW); // при входе в режим установок температуры выключаем все реле
048 digitalWrite(OUT2, LOW);
049 digitalWrite(OUT3, LOW);
050 
051  lcd.clear(); // очищаем экран дисплея
052  lcd.setCursor(0, 0); // курсор на позицию 0 строки 1
053  lcd.print("Min ");
054  lcd.setCursor(0, 1); // курсор на позицию 0 строки 2
055  lcd.print("Max ");
056  lcd.blink(); // курсор в мигающем режиме
057   
058  while(1) // Цикл 1. Условия выхода не установлены. Выход из цикла при перезагрузке контроллера нажатием кнопки RESET
059 {
060  byte KEY = key(); // переменная KEY принимает значение key возвращаемое при нажатии кнопок - читаем значение кнопок
061     
062  lcd.setCursor(4, 0); // курсор на позицию 4 строки 1
063   // Если нижнее пороговое значение температуры представлено положительным числом от 0 и выше,
064   // пишем значение, добавляя знак "+", например, +36
065    if (tempMin > 0)
066     {
067      lcd.setCursor(4, 0); // курсор на 4 позицию 1 строки
068      lcd.print("+");
069      lcd.print(tempMin); // пишем нижнее пороговое значение температуры
070      lcd.write(1);       // рисуем символ "градус"
071     }
072      
073  // Если нижнее пороговое значение температуры имеет отрицательное значение от 0 и ниже,
074  // пишем значение, со знаком "-", который присваивается программно, например, -3
075   else if (tempMin <= 0)
076     {
077      lcd.setCursor(4, 0);        // курсор на 4 позицию 1 строки
078      lcd.print(tempMin);         // пишем нижнее пороговое значение температуры
079      lcd.write(1);               // рисуем символ "градус"
080     }
081    lcd.print("C  ");
082  
083  lcd.setCursor(4, 1); // курсор на позицию 4 строки 2
084  
085   // Если верхнее пороговое значение температуры представлено положительным числом от 0 и выше,
086   // пишем значение, добавляя знак "+", например, +36
087    if (tempMax > 0)
088     {
089      lcd.setCursor(4, 1); // курсор на 4 позицию 1 строки
090      lcd.print("+");
091      lcd.print(tempMax); // пишем верхнее пороговое значение температуры
092      lcd.write(1);       // рисуем символ "градус"
093     }
094      
095  // Если верхнее пороговое значение температуры имеет отрицательное значение от 0 и ниже,
096  // пишем значение, со знаком "-", который присваивается программно, например, -3
097   else if (tempMax <= 0)
098     {
099      lcd.setCursor(4, 1);        // курсор на 4 позицию 1 строки
100      lcd.print(tempMax);         // пишем верхнее пороговое значение температуры
101      lcd.write(1);               // рисуем символ "градус"
102     }
103   lcd.print("C  ");
104 
105/***** Обработка команд кнопок, установка и запись в EEPROM пороговых значений температуры ******/
106   if (position == 0) // в режиме установки нижнего порогового значения температуры
107    
108      lcd.setCursor(3, 0); // курсор на позицию 3 строки 1
109      if (KEY == 2) // если нажата кнопка 2 "LEFT"
110       {
111        tempMin--; // уменьшаем на единицу нижнее пороговое значение температуры
112        tempMin_mem = map (tempMin,-50,205,0,255); // изменяем значение в формат 0-255 для записи в EEPROM (не запоминает отрицательных значений)
113        EEPROM.write(1, tempMin_mem); // нижнее пороговое значение температуры сохраняем в ячейке 1 EEPROM
114       }
115      else if (KEY == 5) // если нажата кнопка 5 "RIGHT"
116         {
117          tempMin++; // увеличиваем на единицу нижнее пороговое значение температуры
118          tempMin_mem = map (tempMin,-50,205,0,255); // изменяем к положительным значениям
119          EEPROM.write(1, tempMin_mem);     // сохраняем в ячейке 1 EEPROM
120         }   
121    }
122     
123    if (position == 1) // в режиме установки верзнего порогового значения температуры
124     {
125      lcd.setCursor(3, 1); // курсор на позицию 3 строки 2
126      if (KEY == 2) // если нажата кнопка 2 "LEFT"
127       {
128        tempMax--; // уменьшаем на единицу верхнее пороговое значение температуры
129        tempMax_mem = map (tempMax,-50,205,0,255); // изменяем значение в формат 0-255 для записи в EEPROM
130        EEPROM.write(2, tempMax_mem); // верхнее пороговое значение температуры сохраняем в ячейке 2 EEPROM
131       }
132      else if (KEY == 5) // если нажата кнопка 5 "RIGHT"
133         {
134          tempMax++; // увеличиваем на единицу верхнеее пороговое значение температуры
135          tempMax_mem = map (tempMax,-50,205,0,255); // изменяем к положительным значениям
136          EEPROM.write(2, tempMax_mem);    // сохраняем в ячейке 2 EEPROM
137         }   
138    }
139    /*
140    Кнопками 3 "UP" и 4 "DOWN" изменяем режим установок
141    нижнего и верхнего пороговых значений температуры
142    */
143    if (KEY == 3) // если нажата кнопка 3 "UP"
144     {
145      position--; // значение режимов меню уменьшаем на 1
146     }
147    else if (KEY == 4) // если нажата кнопка 4 "DOWN"
148       {
149        position++; // значение режимов меню увеличиваем на 1
150       
151    if (position > 1) // при значении позиции больше 1
152     {
153      position = 0; // значение позиции приобретает значение 0
154     }
155    delay(200);
156  }
157} // закрываем подпрограмму void SetupMenu
158/*****************************************************/
159 
160void setup()
161{
162  lcd.init(); // инициализация дисплея
163  lcd.backlight(); // Включаем подсветку дисплея
164  lcd.createChar(1, gradus); // записываем в память дисплея символ "градус"
165  lcd.createChar(2, line); // записываем в память дисплея символ "разделительная линия"
166 
167  sensors.begin(); // инициализируем датчик температуры
168 
169  pinMode(OUT1, OUTPUT);   // определяем pin реле нижнего порогового значения в качестве выхода
170  pinMode(OUT2, OUTPUT);   // определяем pin реле верхнего порогового значения в качестве выхода
171  pinMode(OUT3, OUTPUT);   // определяем pin реле 3 термостата в качестве выхода
172  pinMode(red, OUTPUT);    // определяем красную линию LED в качестве выхода
173  pinMode(green, OUTPUT);  // определяем зеленую линию LED в качестве выхода
174  pinMode(blue, OUTPUT);   // определяем синюю линию LED в качестве выхода
175 
176tempMin_mem = EEPROM.read(1); // читаем из EEPROM записанное нижнее пороговое значение температуры
177tempMax_mem = EEPROM.read(2); // читаем из EEPROM записанное верхнее пороговое значение температуры
178 
179tempMin = map (tempMin_mem, 0,255,-50,205); // значение из EEPROM переводим в нижнее пороговое значение температуры
180tempMax = map (tempMax_mem, 0,255,-50,205); // значение из EEPROM переводим в верхнее пороговое значение температуры
181 
182/*******/ Serial.begin(9600);
183 
184} // завершаем цикл void setup
185/*****************************************************/
186 
187void loop()
188 
189  if (key() == 1) // если нажата кнопка 1 "SELECT"
190   {
191    SetupMenu(); // запускаем подпрограмму SetupMenu установок пороговых значений температуры
192   }
193  else if (key() == 4) // при нажатии кнопки 4 "DOWN"
194      {
195      lcd.noBacklight(); // выключаем подсветку дисплея
196      }
197  else if (key() == 3) // при  нажатии кнопки 3 "UP"
198      {
199      lcd.backlight(); // включаем подсветку дисплея
200      }
201 
202 sensors.requestTemperatures(); // датчик регистрирует температуру
203 // переменной temperature присваивается значение, полученное с датчика температуры
204 float temperature = sensors.getTempCByIndex(0); 
205  
206/**************** Управление реле термостата *******************/
207 
208 if (temperature <= tempMin)  // если температура ниже нижнего порогового значения
209  {
210  digitalWrite(OUT1, HIGH);     // включаем Реле 1
211  }
212 else
213    {
214     digitalWrite(OUT1, LOW); // если нет, выключаем Реле 1
215    }
216 if (temperature <= tempMax)  // если температура ниже верхнего порогового значения
217   {
218    digitalWrite(OUT2, HIGH);     // включаем Реле 2
219   }
220 else
221    {
222     digitalWrite(OUT2, LOW); // если нет, выключаем Реле 2
223    }
224/* Реле 3 термостата включено до достижения верхнего порогового значения.
225После достижения верхнего порогового значения, реле 3 отключается
226и включается при падении температуры ниже нижнего порогового значения.
227Температура поддерживается в диапазоне от нижнего до верхнегоо пороговых значений.
228*/
229 
230if ((digitalRead(OUT1)) && (digitalRead(OUT2))) // если получаем значение с выходов OUT1 и OUT2
231     {
232      digitalWrite(OUT3, HIGH); // включаем реле 3 термостата
233     }   
234else if (!digitalRead(OUT2)) // если игнорируем значение с выхода OUT2
235     {
236     digitalWrite(OUT3, LOW); // выключаем реле 3 термостата
237     
238 
239/***** Пишем первую строку дисплея *******************/
240 
241  lcd.setCursor(0, 0); // курсор на 0 позицию 1 строки
242  lcd.print("Min");
243  lcd.setCursor(4, 0); // курсор на 4 позицию 1 строки
244     
245   // Если нижнее пороговое значение температуры представлено двухзначным числом от 10 до 99,
246   // пишем значение, добавляя знак "+", например, +36
247    if ((tempMin >= 10)&&(tempMin < 100))
248     {
249      lcd.setCursor(4, 0); // курсор на 4 позицию 1 строки
250      lcd.print("+");
251      lcd.print(tempMin); // пишем нижнее пороговое значение температуры
252      lcd.write(1);       // рисуем символ "градус"
253     }
254      
255  // Если нижнее пороговое значение температуры имеет отрицательное однозначное значение от -10 до 0,
256  // пишем значение, со знаком "-", который присваивается программно, например, -3
257   else if ((tempMin > -10)&&(tempMin <= 0))
258     {
259      lcd.setCursor(4, 0);        // курсор на 4 позицию 1 строки
260      lcd.print(tempMin);         // пишем нижнее пороговое значение температуры
261      lcd.write(1);               // рисуем символ "градус"
262     }
263  
264 // Если нижнее пороговое значение температуры имеет положительное однозначное значение от 0 до 10,
265 // пишем значение, добавляя знак "+", например, +6 
266  else if ((tempMin < 10)&&(tempMin >= 0))
267    {
268     lcd.setCursor(4, 0);      // курсор на 4 позицию 1 строки
269     lcd.print("+");
270     lcd.print(tempMin);        // выводим нижнее пороговое значение температуры
271     lcd.write(1);              // рисуем символ "градус"
272    }
273 
274 // во всех остальных случаях, когда выводится 3-х символьное значение:
275 // если нижнее пороговое значение температуры положительное трехзначное, например, 102 (знак "+" не добавляется)
276 // если нижнее пороговое значение температуры отрицательное двухзначное, например, -18
277  else
278    {
279    lcd.setCursor(4, 0);       // курсор на 4 позицию 1 строки
280    lcd.print(tempMin);        // выводим нижнее пороговое значение температуры
281    lcd.write(1);              // рисуем символ "градус"
282    }
283 
284  lcd.setCursor(8, 0); // курсор на 8 позицию 1 строки
285  lcd.write(2);        // рисуем разделительную линию
286 
287  lcd.setCursor(9, 0); // курсор на 9 позицию 1 строки 
288 
289/* Выводим значение текущей температуры и сносим лишние символы при переходе разряда показаний.
290   Должно быть пять символов отображения текущей температуры, с учетом того, что датчик сам
291   присваивает знак "-" отрицательным значениям
292*/
293  // Если температура имеет двухзначное значение до запятой, от 10 до 99,
294  // пишем ее, добавляя знак "+", например, +36,6
295    if ((temperature >= 10)&&(temperature < 100))
296     {
297      lcd.setCursor(9, 0);      // курсор на 9 позицию 1 строки
298      lcd.print("+");
299      lcd.print(temperature, 1); // выводим текущее значение температуры, (значение 1 - два знака после запятой)
300      lcd.setCursor(14, 0);       // курсор на 14 позицию 1 строки
301      lcd.write(1);               // рисуем символ "градус"
302      lcd.setCursor(15, 0);       // курсор на 15 позицию 1 строки
303      lcd.print("C"); 
304     }
305      
306  // Если температура имеет отрицательное однозначное значение до запятой, от -10 до 0,
307  // пишем ее, со знаком "-", который напишет сам датчик например, -3,6
308   else if ((temperature > -10)&&(temperature <= 0))
309     {
310      lcd.setCursor(10, 0);       // курсор на 10 позицию 1 строки
311      lcd.print(temperature, 1);  // выводим текущее значение температуры
312      lcd.setCursor(14, 0);       // курсор на 14 позицию 1 строки
313      lcd.write(1);               // рисуем символ "градус"
314      lcd.setCursor(15, 0);       // курсор на 15 позицию 1 строки
315      lcd.print("C"); 
316     }
317  
318 // Если температура имеет положительное однозначное значение до запятой, от 0 до 10,
319 // пишем ее, со знаком "+", например, +3,6 
320  else if ((temperature < 10)&&(temperature >= 0))
321    {
322     lcd.setCursor(10, 0);      // курсор на 12 позицию 1 строки
323     lcd.print("+");
324     lcd.print(temperature, 1); // выводим текущее значение температуры
325     lcd.setCursor(14, 0);      // курсор на 14 позицию 1 строки
326     lcd.write(1);              // рисуем символ "градус"
327     lcd.setCursor(15, 0);      // курсор на 15 позицию 1 строки
328     lcd.print("C"); 
329    }
330 
331 // во всех остальных случаях, когда выводится пяти символьное значение:
332 // если значение температуры положительное трехзначное, например, 102,5 (знак "+" не добавляется)
333 // если значение температуры отрицательное двухзначное, например, -18,4
334  else
335    {
336    lcd.setCursor(9, 0);       // курсор на 9 позицию 1 строки
337    lcd.print(temperature, 1); // выводим текущее значение температуры
338    lcd.setCursor(14, 0);      // курсор на 14 позицию 1 строки
339    lcd.write(1);              // рисуем символ "градус"
340    lcd.setCursor(15, 0);      // курсор на 15 позицию 1 строки
341    lcd.print("C"); 
342    }
343 
344/****** Пишем вторую строку дисплея ********************/
345  lcd.setCursor(0, 1); // курсор на 0 позицию 2 строки
346  lcd.print("Max");
347  lcd.setCursor(4, 1); // курсор на 4 позицию 2 строки
348  
349   // Если верхнее пороговое значение температуры представлено двухзначным числом от 10 до 99,
350   // пишем значение, добавляя знак "+", например, +36
351    if ((tempMax >= 10)&&(tempMax < 100))
352     {
353      lcd.setCursor(4, 1); // курсор на 4 позицию 1 строки
354      lcd.print("+");
355      lcd.print(tempMax); // пишем верхнее пороговое значение температуры
356      lcd.write(1);       // рисуем символ "градус"
357     }
358      
359  // Если верхнее пороговое значение температуры имеет отрицательное однозначное значение от -10 до 0,
360  // пишем значение, со знаком "-", который присваивается программно, например, -3
361   else if ((tempMax > -10)&&(tempMax <= 0))
362     {
363      lcd.setCursor(4, 1);        // курсор на 4 позицию 1 строки
364      lcd.print(tempMax);         // пишем верхнее пороговое значение температуры
365      lcd.write(1);               // рисуем символ "градус"
366     }
367  
368 // Если верхнее пороговое значение температуры имеет положительное однозначное значение от 0 до 10,
369 // пишем значение, добавляя знак "+", например, +6 
370  else if ((tempMax < 10)&&(tempMax >= 0))
371    {
372     lcd.setCursor(4, 1);      // курсор на 4 позицию 1 строки
373     lcd.print("+");
374     lcd.print(tempMax);        // выводим верхнее пороговое значение температуры
375     lcd.write(1);              // рисуем символ "градус"
376    }
377 
378 // во всех остальных случаях, когда выводится 3-х символьное значение:
379 // если верхнее пороговое значение температуры положительное трехзначное, например, 102 (знак "+" не добавляется)
380 // если верхнее пороговое значение температуры отрицательное двухзначное, например, -18
381  else
382    {
383    lcd.setCursor(4, 1);       // курсор на 4 позицию 1 строки
384    lcd.print(tempMax);        // выводим верхнее пороговое значение температуры
385    lcd.write(1);              // рисуем символ "градус"
386    }
387   
388  lcd.setCursor(8, 1); // курсор на 8 позицию 1 строки
389  lcd.write(2); // рисуем разделительную линию
390 
391  lcd.setCursor(9,1);  // курсор на 8 позицию 2 строки
392  lcd.print("OUT");
393  lcd.setCursor(13,1);  // курсор на 8 позицию 2 строки
394 
395    if (digitalRead(OUT3))  // если получаем значение с выхода 3
396     {
397     lcd.print("ON ");      // пишем состояние реле 3 "ON"
398     }
399    else // в противном случае
400      {
401       lcd.print("OFF");    // пишем состояние реле 3 "OFF"
402      }
403  delay(100); // пауза 0.1 секунда
404 
405 
406/************* Управление  R G B   L E D   ********************************/
407  /* устанавливаем тип переменных tempMin_led и tempMax_led для вычислений с плавающей запятой
408     и определяем их значение равное установленным пороговым значениям температур */
409  tempMin_led = (float)tempMin / 1.0;
410  tempMax_led = (float)tempMax / 1.0;
411   
412  /* значение переменной delta вычисляем как положительное значение разницы пороговых температур
413     разделенное на 25 оттенков цветового спектра, подлежащего отображению RGB LED в зависимости
414     от температуры и в пределах значений заданных параметрами tempMin и tempMax
415     (с учетом того, что всегда tempMin < tempMax) */
416  delta = ((tempMax_led - tempMin_led) / 25); // разницу температур / 25 оттенков
417 
418/* Устанавливаем уровень ШИМ сигнала на красной, зеленой и синей линиях RGB
419   в зависимости от температуры и в пределах значений заданных параметрами tempMin и tempMax
420   путем поэтапного прибавления к значению нижнего уровня температуры кратного значения delta
421*/
422 
423if (temperature < tempMin_led) // при значении температуры ниже нижнего заданного значения
424{
425analogWrite (red, 0);    // отображается синий
426analogWrite (green, 0);
427analogWrite (blue, 255);
428}
429 
430/* Четыре основных этапа изменение цвета:
431  1. От синего к голубому                     
432  2. От голубого к зеленому
433  3. От зеленого к желтому
434  4. От желтого к красному
435  Каждый этап состоит из 6 частей.
436  Значение ШИМ = 255 / 6 = 42.5. Округленно 42 = шаг изменения значения функции analogWrite
437*/
438 
439// от синего к голубому
440else if (temperature >= tempMin_led && temperature <= (tempMin_led + delta))
441{
442analogWrite (red, 0);   
443analogWrite (green, 0);
444analogWrite (blue, 255);
445}
446else if (temperature > (tempMin_led + delta) && temperature <= (tempMin_led + (2*delta)))
447{
448analogWrite (red, 0);   
449analogWrite (green, 42);
450analogWrite (blue, 255);
451}
452else if (temperature >(tempMin_led+(2*delta)) && temperature <= (tempMin_led + (3*delta)))
453{
454analogWrite (red, 0);   
455analogWrite (green, 85);
456analogWrite (blue, 255);
457}
458else if (temperature > (tempMin_led + (3*delta)) && temperature <= (tempMin_led + (4*delta)))
459{
460analogWrite (red, 0);   
461analogWrite (green, 127);
462analogWrite (blue, 255);
463}
464else if (temperature > (tempMin_led + (4*delta)) && temperature <= (tempMin_led + (5*delta)))
465{
466analogWrite (red, 0);
467analogWrite (green, 170);
468analogWrite (blue, 255);
469}
470else if (temperature > (tempMin_led + (5*delta)) && temperature <= (tempMin_led + (6*delta)))
471{
472analogWrite (red, 0);
473analogWrite (green, 212);
474analogWrite (blue, 255);
475}
476else if (temperature > (tempMin_led + (6*delta)) && temperature <= (tempMin_led + (7*delta)))
477{
478analogWrite (red, 0);   
479analogWrite (green, 255);
480analogWrite (blue, 255);
481}
482 
483// от голубого к зеленому
484else if (temperature > (tempMin_led + (7*delta)) && temperature <= (tempMin_led + (8*delta)))
485{
486analogWrite (red, 0);   
487analogWrite (green, 255);
488analogWrite (blue, 212);
489}
490else if (temperature > (tempMin_led + (8*delta)) && temperature <= (tempMin_led + (9*delta)))
491{
492analogWrite (red, 0);   
493analogWrite (green, 255);
494analogWrite (blue, 170);
495}
496else if (temperature > (tempMin_led + (9*delta)) && temperature <= (tempMin_led + (10*delta)))
497{
498analogWrite (red, 0);
499analogWrite (green, 255);
500analogWrite (blue, 127);
501}
502else if (temperature > (tempMin_led + (10*delta)) && temperature <= (tempMin_led + (11*delta)))
503{
504analogWrite (red, 0);
505analogWrite (green, 255);
506analogWrite (blue, 85);
507}
508else if (temperature > (tempMin_led + (11*delta)) && temperature <= (tempMin_led + (12*delta)))
509{
510analogWrite (red, 0);
511analogWrite (green, 255);
512analogWrite (blue, 42);
513}
514else if (temperature > (tempMin_led + (12*delta)) && temperature <= (tempMin_led + (13*delta)))
515{
516analogWrite (red, 0); 
517analogWrite (green, 255);
518analogWrite (blue, 0);
519}
520 
521// от зеленого к желтому
522else if (temperature > (tempMin_led + (13*delta)) && temperature <= (tempMin_led + (14*delta)))
523{
524analogWrite (red, 42);   
525analogWrite (green, 255);
526analogWrite (blue, 0);
527}
528else if (temperature > (tempMin_led + (14*delta)) && temperature <= (tempMin_led + (15*delta)))
529{
530analogWrite (red, 85);   
531analogWrite (green, 255);
532analogWrite (blue, 0);
533}
534else if (temperature > (tempMin_led + (15*delta)) && temperature <= (tempMin_led + (16*delta)))
535{
536analogWrite (red, 127);
537analogWrite (green, 255);
538analogWrite (blue, 0);
539}
540else if (temperature > (tempMin_led + (16*delta)) && temperature <= (tempMin_led + (17*delta)))
541{
542analogWrite (red, 170); 
543analogWrite (green, 255);
544analogWrite (blue, 0);
545}
546else if (temperature > (tempMin_led + (17*delta)) && temperature <= (tempMin_led + (18*delta)))
547{
548analogWrite (red, 212);
549analogWrite (green, 255);
550analogWrite (blue, 0);
551}
552else if (temperature > (tempMin_led + (18*delta)) && temperature <= (tempMin_led + (19*delta)))
553{
554analogWrite (red, 255);
555analogWrite (green, 255);
556analogWrite (blue, 0);
557}
558 
559// от желтого к красному
560else if (temperature > (tempMin_led + (19*delta)) && temperature <= (tempMin_led + (20*delta)))
561{
562analogWrite (red, 255);
563analogWrite (green, 212);
564analogWrite (blue, 0);
565}
566else if (temperature > (tempMin_led + (20*delta)) && temperature <= (tempMin_led + (21*delta)))
567{
568analogWrite (red, 255);
569analogWrite (green, 170);
570analogWrite (blue, 0);
571}
572else if (temperature > (tempMin_led + (21*delta)) && temperature <= (tempMin_led + (22*delta)))
573{
574analogWrite (red, 255);
575analogWrite (green, 127);
576analogWrite (blue, 0);
577}
578else if (temperature > (tempMin_led + (22*delta)) && temperature <= (tempMin_led + (23*delta)))
579{
580analogWrite (red, 255);
581analogWrite (green, 85);
582analogWrite (blue, 0);
583}
584else if (temperature > (tempMin_led + (23*delta)) && temperature <= (tempMin_led + (24*delta)))
585{
586analogWrite (red, 255);
587analogWrite (green, 42);
588analogWrite (blue, 0);
589}
590else if (temperature > (tempMin_led + (24*delta)) && temperature <= (tempMin_led + (25*delta)))
591{
592analogWrite (red, 255);
593analogWrite (green, 0);
594analogWrite (blue, 0);
595}
596 
597else if (temperature >= tempMax_led) // при значении температуры выше высшего заданного значения
598{
599analogWrite (red, 255); // отображается красный
600analogWrite (green, 0);
601analogWrite (blue, 0);
602}
603 
604/******/ Serial.print("temperature ");
605/******/ Serial.println(temperature);
606/******/ Serial.print("Min ");
607/******/ Serial.println(tempMin);
608/******/ Serial.print("Max ");
609/******/ Serial.println(tempMax);
610/******/ Serial.print("OUT ");
611/******/ if (digitalRead(OUT3)) {Serial.println("ON");}
612/******/ else {Serial.println("OFF");}
613     
614} // закрываем цикл 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

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

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