#include <OneWire.h>
#include <DallasTemperature.h>
#include <Servo.h>
#include <EEPROM.h>
//#include <SoftwareServo.h>
//SoftwareServo servo;
Servo servo;//Подключаем библиотеку для управления сервоприводом
// Data wire is plugged into port 2 on the Arduino
#define ONE_WIRE_BUS A0 //Определям вход для термометра
// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h> // Скачанная библиотека для дисплея.
#include <Adafruit_SSD1306.h> // Скачанная библиотека для дисплея.
#define OLED_RESET 4
//#define STEP_DEGREE 9
Adafruit_SSD1306 display(OLED_RESET); //Создаем объект дисплей
OneWire oneWire(ONE_WIRE_BUS); //Создаем объект oneWire
int CurrTemp, SetTemp,PrevTemp=0,Mode=1,posReg=9,RememberPos=9,Delta=0,CountPress=0,Pause=25;//Текущая температура,установленная,предыдущая,режим 1-manual 0-auto,позиция регулятора,разница температур
byte inv=1,minPos=1,maxPos=17; //Инверсия - для зеркального крепления привода, мин. позиция регулятора, макс позиция
// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);//Создаем объект термометра
void setup(void)
{
//servo.attach(2,350,2480);//Привязываем серво на второй пин
display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // initialize with the I2C addr 0x3C (for the 0.96" 128X64 OLED LCD Display)I2C АДРЕС.
display.clearDisplay(); // Clear the buffer. / Очистить буфер.
display.setTextColor(WHITE); // Цвет текста.
display.setTextSize(2); // Размер текста (1).
display.setCursor(0,0); // Устанавливаем курсор в 0 0
Serial.begin(9600);
//Определяем режим пинов 5,4,3
pinMode(5,INPUT);
pinMode(4,INPUT);
pinMode(3,INPUT);
//pinMode(2,OUTPUT);
sensors.begin(); //Стартуем термометр
delay(100);
SetTemp=EEPROM.read(0);//Читаем сохраненную температуру в EEPROM
if(SetTemp<0 || SetTemp>30) SetTemp=18; //Если вне диапазона 0..30 тогда устанавливаем 18
Mode=EEPROM.read(4);//Читаем режим
Pause=EEPROM.read(12);//Считываем значение паузы
if(Pause==255) Pause=25;//При первом запуске значение в ячейке будет 255, тогда устанавливаем значение по умолчанию
//posReg=EEPROM.read(8);//Читаем позицию регулятора
//RememberPos=posReg;
//if(posReg<(minPos) || posReg>maxPos) posReg=9;//Если вне диапазона minPos..maxPos тогда устанавливаем 9
setPos(posReg); //Устанавливаем позицию регулятора
ReadKeyTemp(); //Основная функция опроса клавиш
printTemp(); //Вывод на дисплей
}
void loop(void)
{
/* Serial.println(abs(Delta));
Serial.println(abs(CurrTemp-SetTemp));
Serial.println(CurrTemp);
Serial.println(SetTemp);
*/
if(!Mode ){//Если режим авто
//Без инверсии
// Serial.println("Set");
Delta=CurrTemp-SetTemp;//Вычисляем разницу температур
if((Delta<=3) && (Delta>=-3) && !inv) setPos(posReg-Delta);//Если дельта в диапазоне -3..3 устанавливаем регулятор posReg-Delta
if(Delta>3 && !inv) setPos(minPos);//Если дельта больше 3 устанавливаем регулятор в крайнее положение мин
if(Delta<-3 && !inv) setPos(maxPos);//Если дельта меньше 3 устанавливаем регулятор в крайнее положение макс
//Тоже самое но с инверсией
if((Delta<=3) && (Delta>=-3) && inv) setPos(posReg+Delta);//Если дельта в диапазоне -3..3 устанавливаем регулятор posReg+Delta
if(Delta>3 && inv) setPos(maxPos);//Если дельта больше 3 устанавливаем регулятор в крайнее положение макс
if(Delta<-3 && inv) setPos(minPos);//Если дельта меньше 3 устанавливаем регулятор в крайнее положение мин
}
MyDelay(30); //Задержка на 30с в которой идет постоянный опрос клавиатуры и термометра
}
void printTemp()
{
sensors.requestTemperatures();//Делаем опрос термометров
CurrTemp=sensors.getTempCByIndex(0);//Считываем температуру
display.clearDisplay();//Очищаем буфер дисплея
display.setCursor(0,0);//Устанавливаем курсор в позицию 0 0
CurrTemp>=0?display.print("+"):display.print(" ");//Если температура положительная печатаем +, если нет то пробел
display.print(CurrTemp);//Выводим температуру
display.setCursor(64,0);//Устанавливаем курсор в позицию 64 0
SetTemp>=0?display.print("+"):display.print(" ");//Если температура положительная печатаем +, если нет то пробел
display.print(SetTemp);//Выводим температуру
display.setCursor(0,44);//Устанавливаем курсор в позицию 0 44
Mode?display.print("manual"):display.print("auto");//Выводим режим
display.setCursor(104,44);//Устанавливаем курсор в позицию 104 44
inv==0?display.print(posReg):display.print(18-posReg);//Печатаем позицию регулятора с учетом инверсии
display.drawRect(0, 20, 128, 20,WHITE);//Отображаем бегунок (прямоугольник)
inv==0?display.fillRect((posReg-1)*7.53, 20, 8, 20,WHITE):display.fillRect((18-posReg-1)*7.53, 20, 8, 20,WHITE);//Отображаем позицию в бегуноке с учетом инверсии
display.display(); //Выводим информацию из буфера на дисплей
return; //Возврат
}
void ReadKeyTemp()//Опрос клавиатуры
{
//Считываем состояние клавишь
byte ButtonL=digitalRead(5);
byte ButtonC=digitalRead(4);
byte ButtonR=digitalRead(3);
delay(100);
if(ButtonC==HIGH) CountPress++; else CountPress=0;
//Serial.println(CountPress);
if(CountPress>=5) setDelay();
if(!Mode)//Если автоматический режим
{
//sensors.requestTemperatures();
if(ButtonL==HIGH && SetTemp>0)//Если нажата левая клавиша температура больше 0
{
SetTemp--;//убавляем на единицу
EEPROM.write(0, SetTemp);//Сохраняем значение в EEPROM
return;
}
if(ButtonR==HIGH && SetTemp<30)//Если нажата правая клавиша температура меньше 30
{
SetTemp++;//Прибавляем на единицу
EEPROM.write(0, SetTemp);//Сохраняем значение в EEPROM
return;
}
} else
{
//Если ручной режим
if(ButtonL==HIGH && posReg>minPos && !inv) //Если нажата левая клавиша и позиция регулятора больше мин без инверсии
{
posReg--;//Убавляем на единицу
setPos(posReg);//Устанавливае позицию
return;
}
if(ButtonR==HIGH && posReg<maxPos && !inv ) //Если нажата правая клавиша и позиция регулятора меньше макс без инверсии
{
posReg++;//Прибавляем на единицу
setPos(posReg);//Устанавливае позицию
return;
}
if(ButtonR==HIGH && posReg>minPos && inv) //Если нажата левая клавиша и позиция регулятора больше мин с учетом инверсии
{
posReg--;//Убавляем на единицу
setPos(posReg);//Устанавливае позицию
return;
}
if(ButtonL==HIGH && posReg<maxPos && inv ) //Если нажата правая клавиша и позиция регулятора меньше макс с учетом инверсии
{
posReg++;//Прибавляем на единицу
setPos(posReg);//Устанавливае позицию
return;
}
}
if((ButtonC==HIGH) && Mode) //Если нажата центральная клавиша и режим ручной
{
Mode=0;//Меняем режим
EEPROM.write(4, Mode);//Сохраняем
return;
}
else if((ButtonC==HIGH) && !Mode) //Если нажата центральная клавиша и автоматический ручной
{
Mode=1;//Меняем режим
EEPROM.write(4, Mode);//Сохраняем
return;
}
return;
}
void setPos(int Pos)//Устанавливаем позицию
{
if(Pos<=0 ) Pos=minPos;//Если позиция меньше минимальной тогда устанавливаем минимальную
if(Pos>17 ) Pos=maxPos;//Если позиция больше максимальной тогда устанавливаем максимальную
if(RememberPos==Pos) return;//Проверяем не пытаемся ли мы установить туже позицию что уже установлена
/*
Serial.println("-----------");
Serial.println(Pos);
Serial.println(posReg);
Serial.println(RememberPos);
*/
//delay(1000);
servo.attach(2,340,2600);
delay(10);
posReg=Pos;//Устанавливаем глобальную переменную
RememberPos=Pos;
//EEPROM.write(8,posReg);//Сохраняем позицию
//Serial.println(posReg);
switch(posReg)//Установка регулятора по заранее отградуированную позицию
{
case 1: servo.writeMicroseconds(2550); break;
case 2: servo.writeMicroseconds(2350); break;
case 3: servo.writeMicroseconds(2190); break;
case 4: servo.writeMicroseconds(2060); break;
case 5: servo.writeMicroseconds(1910); break;
case 6: servo.writeMicroseconds(1770); break;
case 7: servo.writeMicroseconds(1630); break;
case 8: servo.writeMicroseconds(1520); break;
case 9: servo.writeMicroseconds(1350); break;
case 10: servo.writeMicroseconds(1120); break;
case 11: servo.writeMicroseconds(1000); break;
case 12: servo.writeMicroseconds(870); break;
case 13: servo.writeMicroseconds(740); break;
case 14: servo.writeMicroseconds(630); break;
case 15: servo.writeMicroseconds(540); break;
case 16: servo.writeMicroseconds(450); break;
case 17: servo.writeMicroseconds(350); break;
}
delay(200);
servo.detach();
return;
}
void MyDelay(int Sec)//Функция задержки между опросами температуры
{
for(int j=1;j<=Sec;j++)
{
for(int i=1;i<=3;i++)
{
printTemp();//Выводим информацию на дисплей
ReadKeyTemp();//Делаем опрос клавиатуры
/*Serial.println("------------");
Serial.println(Delta);
Serial.println((CurrTemp-SetTemp));*/
if(!Mode)
{
if((Delta>=0)&&((CurrTemp-SetTemp)<0))
{
Serial.println("+ -");
if(posReg==minPos || posReg==maxPos) setPos(9); else inv==0?setPos(posReg+3):setPos(posReg-3);
return;//Если вдруг дельта сменила знак с + на - прерываем для пересчета позиций
}
if((Delta<=0)&&((CurrTemp-SetTemp)>0))
{
Serial.println("- +");
if(posReg==minPos || posReg==maxPos) setPos(9); else inv==0?setPos(posReg-3):setPos(posReg+3);
return;//Если вдруг дельта сменила знак с - на + прерываем для пересчета позиций
}
if(abs(Delta)<abs(CurrTemp-SetTemp)) return;
/*
if((CurrTemp!=PrevTemp))
{
PrevTemp=CurrTemp;
return;
}*/
}
}
//Delta=CurrTemp-SetTemp;
}
}
void setDelay(){
display.clearDisplay();//Очищаем буфер дисплея
display.setCursor(10,24);//Устанавливаем курсор в позицию 10 24
display.print("Pause: ");
display.print(Pause);//Выводим паузу
display.display(); //Выводим текст из буфера
delay(1000);// Делаем задержку в секунду что бы не пролететь держа кнопку
while(1){ //Бесконечный цикл опроса
byte ButtonL=digitalRead(5);//Считываем положение кнопок
byte ButtonC=digitalRead(4);
byte ButtonR=digitalRead(3);
display.clearDisplay(); //Очищаем буфер дисплея
display.setCursor(10,24);//Устанавливаем курсор в позицию 10 24
display.print("Pause: ");
display.print(Pause);//Выводим паузу
display.display();//Выводим текст из буфера
delay(150);//Компенсируем дребезг
if(ButtonR==HIGH ) //Если нажата клавиша вправо
{
Pause++; //Увеличиваем паузу
}
if(ButtonL==HIGH ) //Если нажата клавиша влево
{
Pause--; //Уменьшаем паузу
}
if((ButtonC==HIGH) ) //Если нажата центральная Сохраняем позицию и выходим
{
EEPROM.write(12, Pause);//Сохраняем
return;//Возврат из функции
}
}
}