/*За основу взят скетч из этого видео
https://www.youtube.com/watch?v=FPLtQ8g_5qAhttps://www.youtube.com/watch?v=FPLtQ8g_5qAhttps://www.youtube.com/watch?v=FPLtQ8g_5qA
*/
#include "TimerOne.h"
//#include "Encod_er.h"
#include "EncButton.h"
#include "iarduino_OLED.h"
//#include "GyverEncoder.h"
//Encoder enc(DT, CLK, SW);
// EncButton eb(2, 3, 4, INPUT, INPUT_PULLUP); // + режим пинов кнопки
EncButton eb(5, 6, 3, INPUT, INPUT_PULLUP); // + режим пинов кнопки
#define pin_Relay 13
#define pin_Relay1 7
#define pin_Speaker 10
#define spr_gnd_Pin 11
#define NotPush 0
#define ShortPush 1
#define LongPush 2
#define DurationOfLongPush 2000
//будет вызываться каждые 250 при вызове в прерывнаиях
//#define interval 250//интервал указан 250 миллисек.
iarduino_OLED myOLED(0x3C);
//extern uint8_t MediumFont[];
//extern uint8_t RusFont[];
//extern uint8_t SmallFont[];
//extern uint8_t MediumFont[];
//extern uint8_t MediumNumbers[];
extern uint8_t MediumFontRus[];
uint32_t i;
int h, m, s;
byte data[] = { 0, 0, 0, 0 };
byte mask = 15, Hour = 0, Minut = 0, flsvet, zn, Signal = 0, SEC = 0;
unsigned long TimeOfPush, tempu, TimerSec = 0, mycounter = 0, temp1, temp2;
bool dvoet, myfl = false, ModeArbeiten = false, UkazHM = true, flEND = false;
int8_t VAL;
struct myMerz
{
word freq;
unsigned long temp;
bool flsvet;
};
myMerz trig[] =
{
{ 500, 0, false },
{ 200, 0, false },
{ 1000, 0, false }
};
void isr() {
eb.tickISR();
}
void setup()
{
myOLED.begin();
myOLED.setFont(MediumFontRus);
myOLED.setCursor(0, 15);
myOLED.print("Часы");
myOLED.setCursor(53, 15);
myOLED.print("Мин");
myOLED.setCursor(92, 15);
myOLED.print("Сек");
// инициализация таймера 1, период interval мкс
//Timer1.initialize(interval);
// задаем обработчик прерываний
//Timer1.attachInterrupt(timerInterrupt, interval);
//задаем пины спикера как выходы,один из них как земля
pinMode(pin_Speaker, OUTPUT);
pinMode(spr_gnd_Pin, OUTPUT);
pinMode(pin_Relay, OUTPUT);
pinMode(pin_Relay1, OUTPUT);
digitalWrite(pin_Relay, HIGH);
digitalWrite(pin_Relay1, LOW);
eb.setEncType(EB_STEP4_LOW);
//digitalWrite(pin_SW, HIGH); // подтягиваем к 5V
TimeOfPush = 0;
delay(100);
//encoder.timeLeft= 0;//byte timeLeft; // время/признак вращения влево (* 8 периодов)
// encoder.timeRight= 0;//byte timeRight; // время/признак вращения вправо (* 8 периодов)
attachInterrupt(0, isr, CHANGE);
attachInterrupt(1, isr, CHANGE);
eb.setEncISR(true);
}
//------------------------------------------------------------
// обработчик прерывания 250 мкс
void timerInterrupt() //относится к библиотеке Encod_er.h
{
eb.tick();
//encoder.scanState(); // метод проверки состояния энкодера
//относится к библиотеке Encod_er.h
//у гайвера похоже на eb.tick();
if (ModeArbeiten)
{
tempu++;
if (tempu == 4000)
{
tempu = 0;
mycounter++;
}
}
}
//------------------------------------------------------------
bool procmerz(byte num)
{
unsigned long tempmillis = millis(); // триггер переключается с периодом из trig
if (tempmillis - trig[num].temp > trig[num].freq)
{
trig[num].temp = tempmillis;
trig[num].flsvet = !trig[num].flsvet;
}
return (trig[num].flsvet);
}
//------------------------------------------------------------
byte mypush()
// возвращает длинное-2, короткое-1 или осутствие нажатия-0
{
unsigned long tpr = millis();
byte res = NotPush;
//if (!digitalRead(pin_SW))
if (!eb.click())
{
if (TimeOfPush == 0) TimeOfPush = tpr;
else
if (tpr - TimeOfPush > DurationOfLongPush && !myfl)
{
TimeOfPush = 0;
myfl = true;
return (LongPush);
}
}
else
{
if (TimeOfPush > 0 && !myfl) res = ShortPush;
TimeOfPush = 0;
myfl = false;
}
return (res);
}
//------------------------------------------------------------
int8_t norm(int8_t aa, byte dob, byte mf) // делаем аа в пределах mf, начиная от dob
{
if (aa > mf) return (dob);
if (aa < dob) return (mf);
return (aa);
}
//------------------------------------------------------------
void Sec2HourMin()
{
Hour = (TimerSec - mycounter) / 3600;
Minut = (TimerSec - mycounter) % 3600 / 60;
SEC = (TimerSec - mycounter) % 60;
}
//------------------------------------------------------------
void loop()
{
eb.tick();
dvoet = true;
zn = procmerz(1);
mask = 15;
unsigned long tempx = millis();
if (procmerz(2) && flEND && tempx - temp2 < 10000L) analogWrite(pin_Speaker, 150); // издаем звук
else
analogWrite(pin_Speaker, 0);
byte rrr = mypush();
if (rrr != NotPush) // произошло нажатие
{
flEND = false;
if (rrr == ShortPush) UkazHM = !UkazHM; // короткое
if (rrr == LongPush)
{
ModeArbeiten = !ModeArbeiten; // длинное
if (ModeArbeiten)
{
mycounter = 0; // запуск таймера
TimerSec = Hour * 3600L + Minut * 60L;
if (TimerSec == 0) ModeArbeiten = false;
else digitalWrite(pin_Relay, LOW);
digitalWrite(pin_Relay1, HIGH);
}
else
{
digitalWrite(pin_Relay, HIGH);
digitalWrite(pin_Relay1, LOW); //отключаем реле принудительно
Hour = 0;
Minut = 0;
}
}
}
if (ModeArbeiten) // режим работы
{
dvoet = procmerz(0);
if (TimerSec == mycounter)
{
ModeArbeiten = false; // отключаем реле по времени
digitalWrite(pin_Relay, HIGH);
digitalWrite(pin_Relay1, LOW);
temp2 = tempx;
flEND = true;
}
// if(pin_Relay,HIGH)myOLED.update(); myOLED.setCursor(0,64);
//myOLED.print("Стоп Реле1",0,64);
Sec2HourMin();
}
else
// режим установки времени
{
if (UkazHM)
{
if (zn) //mask=B0011;
myOLED.update();
myOLED.invText(true);
myOLED.setCursor(0, 15);
myOLED.print("Часы");
myOLED.invText(false);
delay(250);
myOLED.setCursor(0, 15);
myOLED.print("Часы");
delay(250);
myOLED.update();
//myOLED.invText(true);
Hour = norm(Hour + VAL, 0, 99);
}
else
{
//if (zn) //mask=B1100;
myOLED.update();
myOLED.invText(true);
myOLED.setCursor(53, 15);
myOLED.print("Мин");
myOLED.invText(false);
delay(250);
myOLED.setCursor(53, 15);
myOLED.print("Мин");
delay(250);
myOLED.update();
//myOLED.invText(true);
Minut = norm(Minut + VAL, 0, 59);
}
if (tempx - temp1 < 500) mask = 15; // не моргать при вращении энкодера
}
VAL = 0;
//if (encoder.timeRight!=0) //byte timeRight; // время/признак вращения вправо (* 8 периодов)
//признаки поворота энкодера соответственно вправо и влево. Если равны 0,
// то поворота не было. Если не равны 0,
//то содержат время поворота на один шаг. Время вычисляется, как
if (eb.right())
{
VAL = 1;
eb.right(); //byte timeRight; // время/признак вращения вправо (* 8 периодов)
goto m1;
}
else
if (eb.left()); //byte timeLeft; // время/признак вращения влево (* 8 периодов)
//Т.е. единица значения timeRight или timeLeft это период вызова scanState(),
// умноженный на 8. В моей программе это 250 мкс * 8 = 2 мс. На 8 я умножил,
// чтобы использовать один байт.
//Значение переменных timeRight или timeLeft ограничиваются на уровне 255.
//Если признаки используются, то должны сбрасываться в основном цикле.
{
VAL = -1;
eb.left(); //byte timeLeft; // время/признак вращения влево (* 8 периодов)
m1:
temp1 = tempx;
flEND = false; // при любом повороте отключаем сигнал
//if (!digitalRead(pin_SW)) VAL = 0;//неравенство (a != b)
if (!digitalRead(3)) VAL = 0;//неравенство (a != b)
//Функция считывает значение с заданного входа - HIGH или LOW.
}
myOLED.setCursor(16, 39);
if (Hour < 10) {
myOLED.print(0);
}
myOLED.print(Hour);
myOLED.print(":");
if (Minut < 10)
{
myOLED.print(0);
}
myOLED.print(Minut);
myOLED.print(":");
if (SEC < 10) {
myOLED.print(0);
}
myOLED.print(SEC);
}