Если не против.
Редактируемые переменные (уставки) и их мин. и макс. значения можно не хранить в ОЗУ, а только в еепром и загружать в локальные по необходимости. Это на случай если уставок десятки-сотни.
При работе с еепром удобно пользоваться атрибутом ЕЕМЕМ. Ненадо помнить где какая переменная лежит.
А теперь подключим lcd I2C с меню . джойстик вверх вкл подсветку, вниз выключить . вправо-влево бегаем по экранам меню . если ничего не делаем 10сек возврат на главный экран. Подобный скетч выше но на трех кнопках.
//---кнопкa-----------------------------
typedef void (*pDo)();
class Cl_btn {
protected:
byte pin;
bool state;
unsigned long past;
void set(bool s) {
state = s;
past = millis();
switch (s) {
case false:
break;
case true:
Do();
break;
}
}
public:
Cl_btn(byte p): pin(p) {}
pDo Do = [] {};
void init() {
pinMode(pin, INPUT_PULLUP);
set(false);
}
void run() {
if (millis() - past >= 100)
switch (state) {
case false:
if (!digitalRead(pin))set(true);
break;
case true:
if (digitalRead(pin))set(false);
if (millis() - past >= 300)set(false);
break;
}
}
};
Cl_btn Btn(/*пин*/A0);
//-------------------------------------------
const byte st1 = 0;
const byte st0 = 1;
const byte st2 = 2;
class Cl_joystic {
protected:
byte pin;
byte state;
unsigned long past;
void set(byte s) {
state = s;
past = millis();
switch (s) {
case st0:
break;
case st1:
Do1();
break;
case st2:
Do2();
break;
}
}
public:
Cl_joystic(byte p): pin(p) {}
pDo Do1 = [] {};
pDo Do2 = [] {};
void init() {
set(st0);
}
void run() {
if (millis() - past >= 100) {
int tmp = analogRead(pin);
switch (state) {
case st1:
if (tmp > 450)set(st0);
if (millis() - past >= 300)set(st0);
break;
case st0:
if (tmp < 400)set(st1);
else if (tmp > 600)set(st2);
break;
case st2:
if (tmp < 550)set(st0);
if (millis() - past >= 300)set(st0);
break;
}
}
}
};
Cl_joystic JoyLR(/*пин*/A1);
Cl_joystic JoyUD(/*пин*/A2);
//---------------lcd---------------------------------------------
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);
//--------------- меню---------------------------------------------
template <typename T> inline Print & operator << (Print &s, T n) {
s.print(n);
return s;
}
const byte sMain = 0;// главный экран
const byte ss1 = 1;// 1-экран
const byte ss2 = 2;// 2-экран
const byte ss3 = 3;// 3-экран
const byte ss4 = 4;// 4-экран
const byte ss5 = 5;// 5-экран
byte pos;
unsigned long past;
void setPos(byte p) {
pos = p;
past = millis();
lcd.clear();
switch (p) {
case sMain:
lcd << F("Main screen");
JoyUD.Do1 = [] { };
JoyUD.Do2 = [] {setPos(ss1); };
break;
case ss1:
lcd << F("1 screen");
JoyUD.Do1 = [] {setPos(sMain); };
JoyUD.Do2 = [] {setPos(ss2); };
break;
case ss2:
lcd << F("2 screen");
JoyUD.Do1 = [] {setPos(ss1); };
JoyUD.Do2 = [] {setPos(ss3); };
break;
case ss3:
lcd << F("3 screen");
JoyUD.Do1 = [] {setPos(ss2); };
JoyUD.Do2 = [] {setPos(ss4); };
break;
case ss4:
lcd << F("4 screen");
JoyUD.Do1 = [] {setPos(ss3); };
JoyUD.Do2 = [] {setPos(ss5); };
break;
case ss5:
lcd << F("5 screen");
JoyUD.Do1 = [] {setPos(ss4); };
JoyUD.Do2 = [] {};
break;
}
}
void menuInit() {
lcd.begin(16, 2);
setPos(sMain);
}
void menuRun() {
if (pos != sMain && millis() - past >= 10000)setPos(sMain);
if (pos == sMain && millis() - past >= 1000)setPos(sMain);
}
//----------------------------------
void setup() {
lcd.init();
Btn.init();
JoyLR.init();
JoyUD.init();
menuInit();
Btn.Do = [] {};
JoyLR.Do1 = [] {lcd.backlight();};
JoyLR.Do2 = [] {lcd.noBacklight();};
}
void loop() {
Btn.run();
JoyLR.run();
JoyUD.run();
menuRun();
}
/**/
И вот с этой библиотекой код. И да если вы будете ее использовать,то не забывайте использовать команды clear() -очистка буфера и show()- отправка этого буфера в память дисплея
А откуда мне знать. Этот код пришлось брать из стандартных библиотек, да и комментарий оттуда же. Так-что все притензии к автору :) И да там написано не меньше 4.1ms , а 4.5ms это побольше будет так что все Ок
ПС: Похоже передыдущий скетч не был избавлен от ошибок. Так что новый вариант.
/* часы с ручной установкой времени на DS3231*/
// Оборудование
// Ардуино Нано
// lcd1602_i2c -- I2C
// модуль DS3231 -- I2C
// ардуино джойстик кнопка A0 потенциометры A1,A2
// модуль реле 2,3,4,5
//---------------lcd---------------------------------------------
template <typename T> inline Print & operator << (Print &s, T n) {
s.print(n);
return s;
}
//------дисплей lcd1602_i2c-----------------------------
// даташит https://www.sparkfun.com/datasheets/LCD/ADM1602K-NSW-FBS-3.3v.pdf
// на русском http://www.melt.aha.ru/pdf/mt-16s2h.pdf
#include <Wire.h>
// команды
#define LCD_CLEARDISPLAY 0x01
#define LCD_RETURNHOME 0x02
#define LCD_ENTRYMODESET 0x04
#define LCD_DISPLAYCONTROL 0x08
#define LCD_CURSORSHIFT 0x10
#define LCD_FUNCTIONSET 0x20
#define LCD_SETCGRAMADDR 0x40
#define LCD_SETDDRAMADDR 0x80
// флаги для режима ввода дисплея
#define LCD_ENTRYRIGHT 0x00
#define LCD_ENTRYLEFT 0x02
#define LCD_ENTRYSHIFTINCREMENT 0x01
#define LCD_ENTRYSHIFTDECREMENT 0x00
// флаги для управления включением / выключением дисплея
#define LCD_DISPLAYON 0x04
#define LCD_DISPLAYOFF 0x00
#define LCD_CURSORON 0x02
#define LCD_CURSOROFF 0x00
#define LCD_BLINKON 0x01
#define LCD_BLINKOFF 0x00
// флаги для отображения / сдвига курсора
#define LCD_DISPLAYMOVE 0x08
#define LCD_CURSORMOVE 0x00
#define LCD_MOVERIGHT 0x04
#define LCD_MOVELEFT 0x00
// флаги для набора функций
#define LCD_8BITMODE 0x10
#define LCD_4BITMODE 0x00
#define LCD_2LINE 0x08
#define LCD_1LINE 0x00
#define LCD_5x10DOTS 0x04
#define LCD_5x8DOTS 0x00
// флаги для управления подсветкой
#define LCD_lightON 0x08
#define LCD_lightOFF 0x00
#define En B00000100 // Бит разрешения
#define Rw B00000010 // Чтение / запись бит
#define Rs B00000001 // Бит выбора регистра
class Cl_lcd1602_i2c : public Print {
protected:
uint8_t adr, posX, posY;
uint8_t _lightONval;
uint8_t _displayfunction;
uint8_t _displaycontrol;
uint8_t _displaymode;
byte buffer[32];
public:
Cl_lcd1602_i2c(uint8_t a): adr(a) {}
void init() {
Wire.begin();
write4bits(0x03 << 4);
delayMicroseconds(4500); // wait min 4.1ms
write4bits(0x03 << 4);
delayMicroseconds(4500); // wait min 4.1ms
write4bits(0x03 << 4);
delayMicroseconds(150);
write4bits(0x02 << 4);
delay(50);
_lightONval = LCD_lightOFF;
expanderWrite(_lightONval); // сбросить расширение и выключить подсветку (бит 8 = 1)
// режим работы дисплея 4-х битный интерфейс ,две строки,5х8 точек
_displayfunction = LCD_4BITMODE | LCD_2LINE | LCD_5x8DOTS;
command(LCD_FUNCTIONSET | _displayfunction);
// режим контроля дисплей вкл, курсор не мигает,дисплей не мигает
_displaycontrol = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF;
command(LCD_DISPLAYCONTROL | _displaycontrol);
// режим ввода текста в память-начинать слева с движением в право
_displaymode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT;
command(LCD_ENTRYMODESET | _displaymode);
clear();
}
// подсветку вкл/выкл
void lightON(void) {
_lightONval = LCD_lightON;
expanderWrite(0);
}
void lightOFF(void) {
_lightONval = LCD_lightOFF;
expanderWrite(0);
}
// очистить буфер
void clear() {
for (byte i = 0; i < 32; i++ )buffer[i] = 0x20;
posX = 0; posY = 0;
}
// отправить информацию из буфера на экран
void show() {
line(0);
for (byte i = 0; i < 16; i++ )out(buffer[i]);
line(1);
for (byte i = 16; i < 32; i++ )out(buffer[i]);
}
void setCursor(byte x, byte y) {
if (x > 16) x = 16;
else posX = x;
if (y > 2) x = 2;
else posY = y;
}
private:
/*внутрение функции*/
void line(byte l) {
if (l == 0) command(LCD_SETDDRAMADDR | 0x00);
else command(LCD_SETDDRAMADDR | 0x40);
}
inline void out(uint8_t value) {
send(value, Rs);
}
inline size_t write(uint8_t value) {
if (posX < 16 && posY < 2) {
buffer[posY * 16 + posX] = value;
posX++;
}
return 1;
}
/*команды низкоуровневого управления*/
inline void command(uint8_t value) {
send(value, 0);
}
void send(uint8_t value, uint8_t mode) {
uint8_t highnib = value & 0xf0;
write4bits((highnib) | mode);
uint8_t lownib = (value << 4) & 0xf0;
write4bits((lownib) | mode);
}
void write4bits(uint8_t value) {
expanderWrite(value);
pulseEnable(value);
}
void expanderWrite(uint8_t _data) {
Wire.beginTransmission(adr);
Wire.write((int)(_data) | _lightONval);
Wire.endTransmission();
}
void pulseEnable(uint8_t _data) {
expanderWrite(_data | En); // En high
delayMicroseconds(1); // enable pulse must be >450ns
expanderWrite(_data & ~En); // En low
delayMicroseconds(50); // commands need > 37us to settle
}
};
Cl_lcd1602_i2c lcd(0x27);//0x3F
//-----часы-----------------------
uint8_t conv2d(const char* p) {
uint8_t v = 0;
if ('0' <= *p && *p <= '9')
v = *p - '0';
return 10 * v + *++p - '0';
}
class dTime {
protected:
public:
byte hh, mm, ss;
unsigned long time() {
return ((hh * 24 + mm) * 60 + ss);
}
dTime(unsigned long t = 0)
: hh(t / 60 / 60 % 24), mm(t / 60 % 60), ss(t % 60) {}
dTime(byte h, byte m, byte s)
: hh(h), mm(m), ss(s) {}
dTime(const dTime& t)// : hh(copy.hh), mm(copy.mm), ss(copy.ss)
{
hh = t.hh;
mm = t.mm;
ss = t.ss;
}
dTime(const char* time) {
hh = conv2d(time);
mm = conv2d(time + 3);
ss = conv2d(time + 6);
}
dTime(const __FlashStringHelper* time) {
char buff[8];
memcpy_P(buff, time, 8);
hh = conv2d(buff);
mm = conv2d(buff + 3);
ss = conv2d(buff + 6);
}
dTime& operator=(const dTime& t) {
if (this == &t)
return *this;
hh = t.hh;
mm = t.mm;
ss = t.ss;
return *this;
}
};
#define DS3231_ADDRESS 0x68
#define DS3231_CONTROL 0x0E
#define DS3231_STATUSREG 0x0F
#include <Wire.h>
uint8_t read_i2c_register(uint8_t addr, uint8_t reg) {
Wire.beginTransmission(addr);
Wire.write((byte)reg);
Wire.endTransmission();
Wire.requestFrom(addr, (byte)1);
return Wire.read();
}
void write_i2c_register(uint8_t addr, uint8_t reg, uint8_t val) {
Wire.beginTransmission(addr);
Wire.write((byte)reg);
Wire.write((byte)val);
Wire.endTransmission();
}
uint8_t bcd2bin (uint8_t val) {
return val - 6 * (val >> 4);
}
uint8_t bin2bcd (uint8_t val) {
return val + 6 * (val / 10);
}
class RTC_DS3231 {
public:
void write(dTime t) {
Wire.beginTransmission(DS3231_ADDRESS);
Wire.write((byte)0); // start at location 0
Wire.write(bin2bcd(t.ss));
Wire.write(bin2bcd(t.mm));
Wire.write(bin2bcd(t.hh));
Wire.endTransmission();
uint8_t statreg = read_i2c_register(DS3231_ADDRESS, DS3231_STATUSREG);
statreg &= ~0x80; // flip OSF bit
write_i2c_register(DS3231_ADDRESS, DS3231_STATUSREG, statreg);
}
dTime read() {
Wire.beginTransmission(DS3231_ADDRESS);
Wire.write((byte)0);
Wire.endTransmission();
Wire.requestFrom(DS3231_ADDRESS, 7);
uint8_t s = bcd2bin(Wire.read() & 0x7F);
uint8_t m = bcd2bin(Wire.read());
uint8_t h = bcd2bin(Wire.read());
return dTime(h, m, s);
}
};
RTC_DS3231 rtc;// часы
dTime now, now_; //текущее время
//--------------Реле------------------------------------------------
typedef struct {
byte hour;
byte minute;
byte second;
} timer_t;
class cl_timer {
protected:
timer_t *adr;
public:
cl_timer(timer_t *a): adr(a) {}
void save(unsigned long t = 0) {
setHour(t / 60 / 60 % 24);
setMinute(t / 60 % 60);
setSecond(t % 60);
}
void save(const char* time) {
setHour(conv2d(time));
setMinute(conv2d(time + 3));
setSecond(conv2d(time + 6));
}
void save(const __FlashStringHelper* time) {
char buff[8];
memcpy_P(buff, time, 8);
setHour(conv2d(buff));
setMinute(conv2d(buff + 3));
setSecond(conv2d(buff + 6));
}
byte hour() {
return eeprom_read_byte(&(adr->hour));
};
byte minute() {
return eeprom_read_byte(&(adr->minute));
};
byte second() {
return eeprom_read_byte(&(adr->second));
};
byte time() {
return ((hour() * 24 + minute()) * 60 + second());
};
void setHour(byte h) {
eeprom_write_byte(&adr->hour, h);
}
void setMinute(byte m) {
eeprom_write_byte(&adr->minute, m);
}
void setSecond(byte s) {
eeprom_write_byte(&adr->second, s);
}
};
/*состояния таймера*/
const byte sOFF = 0;
const byte sON = 1;
const byte sEND = 2;
class Cl_Relay {
protected:
byte pin;
byte state;
void set(byte s) {
state = s;
switch (s) {
case sOFF:
digitalWrite(pin, HIGH);
break;
case sON:
digitalWrite(pin, LOW);
break;
case sEND:
digitalWrite(pin, HIGH);
break;
}
}
public:
cl_timer timeON, timeOFF;
Cl_Relay(byte p, cl_timer t1, cl_timer t2)
: pin(p), timeON(t1), timeOFF(t2) {}
void init() {
pinMode(pin, OUTPUT);
set(sOFF) ;
}
void run() {
switch (state) {
case sOFF:
if (now.time() >= timeON.time())set(sON);
break;
case sON:
if (now.time() >= timeOFF.time())set(sEND);
break;
case sEND: break;
}
}
void reset() {
set(sOFF) ;
}
void viev() {
switch (state) {
case sOFF:
lcd << F("OFF");
break;
case sON:
lcd << F("ON ");
break;
case sEND:
lcd << F("END");
break;
}
}
};
const byte RelayNum = 4; //кол-во реле
timer_t EEMEM adr[RelayNum * 2];
Cl_Relay Relay[RelayNum] = {
Cl_Relay(/*пин*/2, &adr[0], &adr[1]),// 1-е реле
Cl_Relay(/*пин*/3, &adr[2], &adr[3]),// 2-е реле
Cl_Relay(/*пин*/4, &adr[4], &adr[5]),// 3-е реле
Cl_Relay(/*пин*/5, &adr[6], &adr[7]) // 4-е реле
};
// первичные настройки в EEPROM
void setZero() {
Relay[0].timeON.save(F("00:00:30")); Relay[0].timeOFF.save(F("00:02:30"));// 1-е реле
Relay[1].timeON.save(F("00:01:00")); Relay[1].timeOFF.save(F("00:03:00"));// 2-е реле
Relay[2].timeON.save(F("00:01:30")); Relay[2].timeOFF.save(F("00:03:30"));// 3-е реле
Relay[3].timeON.save(F("00:02:00")); Relay[3].timeOFF.save(F("00:04:00"));// 4-е реле
}
//---кнопкa-----------------------------
typedef void (*pDo)();
class Cl_btn {
protected:
byte pin;
bool state;
unsigned long past;
void set(bool s) {
state = s;
past = millis();
switch (s) {
case false:
break;
case true:
Do();
break;
}
}
public:
Cl_btn(byte p): pin(p) {}
pDo Do = [] {};
void init() {
pinMode(pin, INPUT_PULLUP);
set(false);
}
void run() {
if (millis() - past >= 100)
switch (state) {
case false:
if (!digitalRead(pin))set(true);
break;
case true:
if (digitalRead(pin))set(false);
if (millis() - past >= 300)set(false);
break;
}
}
};
Cl_btn Btn(/*пин*/A0);
//-------------------------------------------
const byte st1 = 0;
const byte st0 = 1;
const byte st2 = 2;
class Cl_joystic {
protected:
byte pin;
byte state;
unsigned long past;
void set(byte s) {
state = s;
past = millis();
switch (s) {
case st0:
break;
case st1:
Do1();
break;
case st2:
Do2();
break;
}
}
public:
Cl_joystic(byte p): pin(p) {}
pDo Do1 = [] {};
pDo Do2 = [] {};
void init() {
set(st0);
}
void run() {
if (millis() - past >= 100) {
int tmp = analogRead(pin);
switch (state) {
case st1:
if (tmp > 450)set(st0);
if (millis() - past >= 300)set(st0);
break;
case st0:
if (tmp < 400)set(st1);
else if (tmp > 600)set(st2);
break;
case st2:
if (tmp < 550)set(st0);
if (millis() - past >= 300)set(st0);
break;
}
}
}
};
Cl_joystic JoyLR(/*пин*/A1);
Cl_joystic JoyUD(/*пин*/A2);
//---------меню----------------
const byte scr0 = 0; // показ времени
const byte scr1 = 10; // показ времени реле1 вкл/выкл
const byte scr1_hour1 = 11; // установка часов реле1 вкл
const byte scr1_min1 = 12; // установка минут реле1 вкл
const byte scr1_sec1 = 13; // установка секунд реле1 вкл
const byte scr1_hour2 = 14; // установка часов реле1 выкл
const byte scr1_min2 = 15; // установка минут реле1 выкл
const byte scr1_sec2 = 16; // установка секунд реле1 выкл
const byte scr2 = 20; // показ времени реле2 вкл/выкл
const byte scr2_hour1 = 21; // установка часов реле2 вкл
const byte scr2_min1 = 22; // установка минут реле2 вкл
const byte scr2_sec1 = 23; // установка секунд реле2 вкл
const byte scr2_hour2 = 24; // установка часов реле2 выкл
const byte scr2_min2 = 25; // установка минут реле2 выкл
const byte scr2_sec2 = 26; // установка секунд реле2 выкл
const byte scr3 = 30; // показ времени реле3 вкл/выкл
const byte scr3_hour1 = 31; // установка часов реле3 вкл
const byte scr3_min1 = 32; // установка минут реле3 вкл
const byte scr3_sec1 = 33; // установка секунд реле3 вкл
const byte scr3_hour2 = 34; // установка часов реле3 выкл
const byte scr3_min2 = 35; // установка минут реле3 выкл
const byte scr3_sec2 = 36; // установка секунд реле3 выкл
const byte scr4 = 40; // показ времени реле4 вкл/выкл
const byte scr4_hour1 = 41; // установка часов реле4 вкл
const byte scr4_min1 = 42; // установка минут реле4 вкл
const byte scr4_sec1 = 43; // установка секунд реле4 вкл
const byte scr4_hour2 = 44; // установка часов реле4 выкл
const byte scr4_min2 = 45; // установка минут реле4 выкл
const byte scr4_sec2 = 46; // установка секунд реле4 выкл
const byte scr5 = 50;
const byte scr5_hour = 51; // установка времени часы
const byte scr5_min = 52; // установка времени минуты
const byte scr5_sec = 53; // установка времени секунд
const byte scr5_res = 54; // установка времени секунд
byte scr; // номер экрана
unsigned long past;// фик времени в этом экране
byte var;// переменная для редактирования
dTime Time;// переменая времени
void go(byte s) {
scr = s;
past = millis();
lcd.clear();
switch (s) {
case scr0: { // 0- экран
lcd << now.hh << F(":") << now.mm << F(":") << now.ss ;
lcd.setCursor(9, 0);
Relay[0].viev(); lcd << F(" ");
Relay[1].viev(); lcd << F(" ");
lcd.setCursor(9, 1);
Relay[2].viev(); lcd << F(" ");
Relay[3].viev(); lcd << F(" ");
lcd.show();
}
Btn.Do = [] {};
JoyLR.Do1 = [] {};
JoyLR.Do2 = [] {go(scr1);};
break;
case scr1: { // ------------------------------1- экран
lcd << F("Re1 ") << Relay[0].timeON.hour() << F(":") << Relay[0].timeON.minute() << F(":") << Relay[0].timeON.second();
lcd.setCursor(4, 1);
lcd << Relay[0].timeOFF.hour() << F(":") << Relay[0].timeOFF.minute() << F(":") << Relay[0].timeOFF.second();
lcd.show();
}
Btn.Do = [] {
var = Relay[0].timeON.hour();
go(scr1_hour1);
};
JoyLR.Do1 = [] {go(scr0);};
JoyLR.Do2 = [] {go(scr2);};
break;
case scr1_hour1: { // установка часов реле1 вкл
lcd << F("Re1>") << var << F(":") << Relay[0].timeON.minute() << F(":") << Relay[0].timeON.second();
lcd.setCursor(4, 1);
lcd << Relay[0].timeOFF.hour() << F(":") << Relay[0].timeOFF.minute() << F(":") << Relay[0].timeOFF.second();
lcd.show();
}
Btn.Do = [] {
Relay[0].timeON.setHour(var);
var = Relay[0].timeON.minute();
go(scr1_min1);
};
JoyLR.Do1 = [] {
if (var < 23)var++;
go(scr1_hour1);
};
JoyLR.Do2 = [] {
if (var > 0)var--;
go(scr1_hour1);
};
break;
case scr1_min1: { // установка минут реле1 вкл
lcd << F("Re1 ") << Relay[0].timeON.hour() << F(">") << var << F(":") << Relay[0].timeON.second();
lcd.setCursor(4, 1);
lcd << Relay[0].timeOFF.hour() << F(":") << Relay[0].timeOFF.minute() << F(":") << Relay[0].timeOFF.second();
lcd.show();
}
Btn.Do = [] {
Relay[0].timeON.setMinute(var);
var = Relay[0].timeON.second();
go(scr1_sec1);
};
JoyLR.Do1 = [] {
if (var < 59)var++;
go(scr1_min1);
};
JoyLR.Do2 = [] {
if (var > 0)var--;
go(scr1_min1);
};
break;
case scr1_sec1: { // установка секунд реле1 вкл
lcd << F("Re1 ") << Relay[0].timeON.hour() << F(":") << Relay[0].timeON.minute() << F(">") << var;
lcd.setCursor(4, 1);
lcd << Relay[0].timeOFF.hour() << F(":") << Relay[0].timeOFF.minute() << F(":") << Relay[0].timeOFF.second();
lcd.show();
}
Btn.Do = [] {
Relay[0].timeON.setSecond(var);
var = Relay[0].timeOFF.hour();
go(scr1_hour2);
};
JoyLR.Do1 = [] {
if (var < 59)var++;
go(scr1_sec1);
};
JoyLR.Do2 = [] {
if (var > 0)var--;
go(scr1_sec1);
};
break;
case scr1_hour2: { // установка часов реле1 выкл
lcd << F("Re1 ") << Relay[0].timeON.hour() << F(":") << Relay[0].timeON.minute() << F(":") << Relay[0].timeON.second();
lcd.setCursor(3, 1);
lcd << F(">") << var << F(":") << Relay[0].timeOFF.minute() << F(":") << Relay[0].timeOFF.second();
lcd.show();
}
Btn.Do = [] {
Relay[0].timeOFF.setHour(var);
var = Relay[0].timeOFF.minute();
go(scr1_min2);
};
JoyLR.Do1 = [] {
if (var < 23)var++;
go(scr1_hour2);
};
JoyLR.Do2 = [] {
if (var > 0)var--;
go(scr1_hour2);
};
break;
case scr1_min2: { // установка минут реле1 выкл
lcd << F("Re1 ") << Relay[0].timeON.hour() << F(":") << Relay[0].timeON.minute() << F(":") << Relay[0].timeON.second();
lcd.setCursor(4, 1);
lcd << Relay[0].timeOFF.hour() << F(">") << var << F(":") << Relay[0].timeOFF.second();
lcd.show();
}
Btn.Do = [] {
Relay[0].timeOFF.setMinute(var);
var = Relay[0].timeOFF.second();
go(scr1_sec2);
};
JoyLR.Do1 = [] {
if (var < 59)var++;
go(scr1_min2);
};
JoyLR.Do2 = [] {
if (var > 0)var--;
go(scr1_min2);
};
break;
case scr1_sec2: { // установка секунд реле1 выкл
lcd << F("Re1 ") << Relay[0].timeON.hour() << F(":") << Relay[0].timeON.minute() << F(":") << Relay[0].timeON.second();
lcd.setCursor(4, 1);
lcd << Relay[0].timeOFF.hour() << F(":") << Relay[0].timeOFF.minute() << F(">") << var;
lcd.show();
}
Btn.Do = [] {
Relay[0].timeOFF.setSecond(var);
go(scr1);
};
JoyLR.Do1 = [] {
if (var < 59)var++;
go(scr1_sec2);
};
JoyLR.Do2 = [] {
if (var > 0)var--;
go(scr1_sec2);
};
break;
case scr2: { //------------------------------------------------ 2- экран
lcd << F("Re2 ") << Relay[1].timeON.hour() << F(":") << Relay[1].timeON.minute() << F(":") << Relay[1].timeON.second();
lcd.setCursor(4, 1);
lcd << Relay[1].timeOFF.hour() << F(":") << Relay[1].timeOFF.minute() << F(":") << Relay[1].timeOFF.second();
lcd.show();
}
Btn.Do = [] {
var = Relay[1].timeON.hour();
go(scr2_hour1);
};
JoyLR.Do1 = [] {go(scr1);};
JoyLR.Do2 = [] {go(scr3);};
break;
case scr2_hour1: { // установка часов реле2 вкл
lcd << F("Re2>") << var << F(":") << Relay[1].timeON.minute() << F(":") << Relay[1].timeON.second();
lcd.setCursor(4, 1);
lcd << Relay[1].timeOFF.hour() << F(":") << Relay[1].timeOFF.minute() << F(":") << Relay[1].timeOFF.second();
lcd.show();
}
Btn.Do = [] {
Relay[1].timeON.setHour(var);
var = Relay[1].timeON.minute();
go(scr2_min1);
};
JoyLR.Do1 = [] {
if (var < 23)var++;
go(scr2_hour1);
};
JoyLR.Do2 = [] {
if (var > 0)var--;
go(scr2_hour1);
};
break;
case scr2_min1: { // установка минут реле2 вкл
lcd << F("Re2 ") << Relay[1].timeON.hour() << F(">") << var << F(":") << Relay[1].timeON.second();
lcd.setCursor(4, 1);
lcd << Relay[1].timeOFF.hour() << F(":") << Relay[1].timeOFF.minute() << F(":") << Relay[1].timeOFF.second();
lcd.show();
}
Btn.Do = [] {
Relay[1].timeON.setMinute(var);
var = Relay[1].timeON.second();
go(scr2_sec1);
};
JoyLR.Do1 = [] {
if (var < 59)var++;
go(scr2_min1);
};
JoyLR.Do2 = [] {
if (var > 0)var--;
go(scr2_min1);
};
break;
case scr2_sec1: { // установка секунд реле2 вкл
lcd << F("Re2 ") << Relay[1].timeON.hour() << F(":") << Relay[1].timeON.minute() << F(">") << var;
lcd.setCursor(4, 1);
lcd << Relay[1].timeOFF.hour() << F(":") << Relay[1].timeOFF.minute() << F(":") << Relay[1].timeOFF.second();
lcd.show();
}
Btn.Do = [] {
Relay[1].timeON.setSecond(var);
var = Relay[1].timeOFF.hour();
go(scr2_hour2);
};
JoyLR.Do1 = [] {
if (var < 59)var++;
go(scr2_sec1);
};
JoyLR.Do2 = [] {
if (var > 0)var--;
go(scr2_sec1);
};
break;
case scr2_hour2: { // установка часов реле2 выкл
lcd << F("Re2 ") << Relay[1].timeON.hour() << F(":") << Relay[1].timeON.minute() << F(":") << Relay[1].timeON.second();
lcd.setCursor(3, 1);
lcd << F(">") << var << F(":") << Relay[1].timeOFF.minute() << F(":") << Relay[1].timeOFF.second();
lcd.show();
}
Btn.Do = [] {
Relay[1].timeOFF.setHour(var);
var = Relay[1].timeOFF.minute();
go(scr2_min2);
};
JoyLR.Do1 = [] {
if (var < 23)var++;
go(scr2_hour2);
};
JoyLR.Do2 = [] {
if (var > 0)var--;
go(scr2_hour2);
};
break;
case scr2_min2: { // установка минут реле2 выкл
lcd << F("Re2 ") << Relay[1].timeON.hour() << F(":") << Relay[1].timeON.minute() << F(":") << Relay[1].timeON.second();
lcd.setCursor(4, 1);
lcd << Relay[1].timeOFF.hour() << F(">") << var << F(":") << Relay[1].timeOFF.second();
lcd.show();
}
Btn.Do = [] {
Relay[1].timeOFF.setMinute(var);
var = Relay[1].timeOFF.second();
go(scr2_sec2);
};
JoyLR.Do1 = [] {
if (var < 59)var++;
go(scr2_min2);
};
JoyLR.Do2 = [] {
if (var > 0)var--;
go(scr2_min2);
};
break;
case scr2_sec2: { // установка секунд реле2 выкл
lcd << F("Re2 ") << Relay[1].timeON.hour() << F(":") << Relay[1].timeON.minute() << F(":") << Relay[1].timeON.second();
lcd.setCursor(4, 1);
lcd << Relay[1].timeOFF.hour() << F(":") << Relay[1].timeOFF.minute() << F(">") << var;
lcd.show();
}
Btn.Do = [] {
Relay[1].timeOFF.setSecond(var);
go(scr2);
};
JoyLR.Do1 = [] {
if (var < 59)var++;
go(scr2_sec2);
};
JoyLR.Do2 = [] {
if (var > 0)var--;
go(scr2_sec2);
};
break;
case scr3: { //---------------------------------- 3- экран
lcd << F("Re3 ") << Relay[2].timeON.hour() << F(":") << Relay[2].timeON.minute() << F(":") << Relay[2].timeON.second();
lcd.setCursor(4, 1);
lcd << Relay[2].timeOFF.hour() << F(":") << Relay[2].timeOFF.minute() << F(":") << Relay[2].timeOFF.second();
lcd.show();
}
Btn.Do = [] {
var = Relay[2].timeON.hour();
go(scr3_hour1);
};
JoyLR.Do1 = [] {go(scr2);};
JoyLR.Do2 = [] {go(scr4);};
break;
case scr3_hour1: { // установка часов реле3 вкл
lcd << F("Re3>") << var << F(":") << Relay[2].timeON.minute() << F(":") << Relay[2].timeON.second();
lcd.setCursor(4, 1);
lcd << Relay[2].timeOFF.hour() << F(":") << Relay[2].timeOFF.minute() << F(":") << Relay[2].timeOFF.second();
lcd.show();
}
Btn.Do = [] {
Relay[2].timeON.setHour(var);
var = Relay[2].timeON.minute();
go(scr3_min1);
};
JoyLR.Do1 = [] {
if (var < 23)var++;
go(scr3_hour1);
};
JoyLR.Do2 = [] {
if (var > 0)var--;
go(scr3_hour1);
};
break;
case scr3_min1: { // установка минут реле1 вкл
lcd << F("Re3 ") << Relay[2].timeON.hour() << F(">") << var << F(":") << Relay[2].timeON.second();
lcd.setCursor(4, 1);
lcd << Relay[2].timeOFF.hour() << F(":") << Relay[2].timeOFF.minute() << F(":") << Relay[2].timeOFF.second();
lcd.show();
}
Btn.Do = [] {
Relay[2].timeON.setMinute(var);
var = Relay[2].timeON.second();
go(scr3_sec1);
};
JoyLR.Do1 = [] {
if (var < 59)var++;
go(scr3_min1);
};
JoyLR.Do2 = [] {
if (var > 0)var--;
go(scr3_min1);
};
break;
case scr3_sec1: { // установка секунд реле3 вкл
lcd << F("Re3 ") << Relay[2].timeON.hour() << F(":") << Relay[2].timeON.minute() << F(">") << var;
lcd.setCursor(4, 1);
lcd << Relay[2].timeOFF.hour() << F(":") << Relay[2].timeOFF.minute() << F(":") << Relay[2].timeOFF.second();
lcd.show();
}
Btn.Do = [] {
Relay[2].timeON.setSecond(var);
var = Relay[2].timeOFF.hour();
go(scr3_hour2);
};
JoyLR.Do1 = [] {
if (var < 59)var++;
go(scr3_sec1);
};
JoyLR.Do2 = [] {
if (var > 0)var--;
go(scr3_sec1);
};
break;
case scr3_hour2: { // установка часов реле3 выкл
lcd << F("Re3 ") << Relay[2].timeON.hour() << F(":") << Relay[2].timeON.minute() << F(":") << Relay[2].timeON.second();
lcd.setCursor(3, 1);
lcd << F(">") << var << F(":") << Relay[2].timeOFF.minute() << F(":") << Relay[2].timeOFF.second();
lcd.show();
}
Btn.Do = [] {
Relay[2].timeOFF.setHour(var);
var = Relay[2].timeOFF.minute();
go(scr3_min2);
};
JoyLR.Do1 = [] {
if (var < 23)var++;
go(scr3_hour2);
};
JoyLR.Do2 = [] {
if (var > 0)var--;
go(scr3_hour2);
};
break;
case scr3_min2: { // установка минут реле3 выкл
lcd << F("Re3 ") << Relay[2].timeON.hour() << F(":") << Relay[2].timeON.minute() << F(":") << Relay[2].timeON.second();
lcd.setCursor(4, 1);
lcd << Relay[2].timeOFF.hour() << F(">") << var << F(":") << Relay[2].timeOFF.second();
lcd.show();
}
Btn.Do = [] {
Relay[0].timeOFF.setMinute(var);
var = Relay[0].timeOFF.second();
go(scr3_sec2);
};
JoyLR.Do1 = [] {
if (var < 59)var++;
go(scr3_min2);
};
JoyLR.Do2 = [] {
if (var > 0)var--;
go(scr3_min2);
};
break;
case scr3_sec2: { // установка секунд реле3 выкл
lcd << F("Re3 ") << Relay[2].timeON.hour() << F(":") << Relay[2].timeON.minute() << F(":") << Relay[2].timeON.second();
lcd.setCursor(4, 1);
lcd << Relay[2].timeOFF.hour() << F(":") << Relay[2].timeOFF.minute() << F(">") << var;
lcd.show();
}
Btn.Do = [] {
Relay[3].timeOFF.setSecond(var);
go(scr3);
};
JoyLR.Do1 = [] {
if (var < 59)var++;
go(scr3_sec2);
};
JoyLR.Do2 = [] {
if (var > 0)var--;
go(scr3_sec2);
};
break;
case scr4: { // 4- экран
lcd << F("Re4 ") << Relay[3].timeON.hour() << F(":") << Relay[3].timeON.minute() << F(":") << Relay[3].timeON.second();
lcd.setCursor(4, 1);
lcd << Relay[3].timeOFF.hour() << F(":") << Relay[3].timeOFF.minute() << F(":") << Relay[3].timeOFF.second();
lcd.show();
}
Btn.Do = [] {
var = Relay[3].timeON.hour();
go(scr4_hour1);
};
JoyLR.Do1 = [] {go(scr3);};
JoyLR.Do2 = [] {go(scr5);};
break;
case scr4_hour1: { // установка часов реле4 вкл
lcd << F("Re4>") << var << F(":") << Relay[3].timeON.minute() << F(":") << Relay[3].timeON.second();
lcd.setCursor(4, 1);
lcd << Relay[3].timeOFF.hour() << F(":") << Relay[3].timeOFF.minute() << F(":") << Relay[3].timeOFF.second();
lcd.show();
}
Btn.Do = [] {
Relay[3].timeON.setHour(var);
var = Relay[3].timeON.minute();
go(scr4_min1);
};
JoyLR.Do1 = [] {
if (var < 23)var++;
go(scr4_hour1);
};
JoyLR.Do2 = [] {
if (var > 0)var--;
go(scr4_hour1);
};
break;
case scr4_min1: { // установка минут реле4 вкл
lcd << F("Re4 ") << Relay[3].timeON.hour() << F(">") << var << F(":") << Relay[3].timeON.second();
lcd.setCursor(4, 1);
lcd << Relay[3].timeOFF.hour() << F(":") << Relay[3].timeOFF.minute() << F(":") << Relay[3].timeOFF.second();
lcd.show();
}
Btn.Do = [] {
Relay[0].timeON.setMinute(var);
var = Relay[0].timeON.second();
go(scr4_sec1);
};
JoyLR.Do1 = [] {
if (var < 59)var++;
go(scr4_min1);
};
JoyLR.Do2 = [] {
if (var > 0)var--;
go(scr4_min1);
};
break;
case scr4_sec1: { // установка секунд реле4 вкл
lcd << F("Re4 ") << Relay[3].timeON.hour() << F(":") << Relay[3].timeON.minute() << F(">") << var;
lcd.setCursor(4, 1);
lcd << Relay[3].timeOFF.hour() << F(":") << Relay[3].timeOFF.minute() << F(":") << Relay[3].timeOFF.second();
lcd.show();
}
Btn.Do = [] {
Relay[0].timeON.setSecond(var);
var = Relay[3].timeOFF.hour();
go(scr4_hour2);
};
JoyLR.Do1 = [] {
if (var < 59)var++;
go(scr4_sec1);
};
JoyLR.Do2 = [] {
if (var > 0)var--;
go(scr4_sec1);
};
break;
case scr4_hour2: { // установка часов реле4 выкл
lcd << F("Re4 ") << Relay[3].timeON.hour() << F(":") << Relay[3].timeON.minute() << F(":") << Relay[3].timeON.second();
lcd.setCursor(3, 1);
lcd << F(">") << var << F(":") << Relay[3].timeOFF.minute() << F(":") << Relay[3].timeOFF.second();
lcd.show();
}
Btn.Do = [] {
Relay[3].timeOFF.setHour(var);
var = Relay[3].timeOFF.minute();
go(scr4_min2);
};
JoyLR.Do1 = [] {
if (var < 23)var++;
go(scr4_hour2);
};
JoyLR.Do2 = [] {
if (var > 0)var--;
go(scr4_hour2);
};
break;
case scr4_min2: { // установка минут реле4 выкл
lcd << F("Re4 ") << Relay[3].timeON.hour() << F(":") << Relay[3].timeON.minute() << F(":") << Relay[3].timeON.second();
lcd.setCursor(4, 1);
lcd << Relay[3].timeOFF.hour() << F(">") << var << F(":") << Relay[3].timeOFF.second();
lcd.show();
}
Btn.Do = [] {
Relay[3].timeOFF.setMinute(var);
var = Relay[3].timeOFF.second();
go(scr4_sec2);
};
JoyLR.Do1 = [] {
if (var < 59)var++;
go(scr4_min2);
};
JoyLR.Do2 = [] {
if (var > 0)var--;
go(scr4_min2);
};
break;
case scr4_sec2: { // установка секунд реле4 выкл
lcd << F("Re4 ") << Relay[3].timeON.hour() << F(":") << Relay[3].timeON.minute() << F(":") << Relay[3].timeON.second();
lcd.setCursor(4, 1);
lcd << Relay[3].timeOFF.hour() << F(":") << Relay[3].timeOFF.minute() << F(">") << var;
lcd.show();
}
Btn.Do = [] {
Relay[3].timeOFF.setSecond(var);
go(scr4);
};
JoyLR.Do1 = [] {
if (var < 59)var++;
go(scr4_sec2);
};
JoyLR.Do2 = [] {
if (var > 0)var--;
go(scr4_sec2);
};
break;
case scr5: { // 5- экран
lcd << F("SetTime:") << now.hh << F(":") << now.mm << F(":") << now.ss ;
lcd.show();
}
Btn.Do = [] {
Time = now;
go(scr5_hour);
};
JoyLR.Do1 = [] {go(scr4);};
JoyLR.Do2 = [] {go(scr0);};
break;
case scr5_hour: {
lcd << F("SetTime>") << Time.hh << F(":") << Time.mm << F(":") << Time.ss;
lcd.show();
}
Btn.Do = [] {go(scr5_min);};
JoyLR.Do1 = [] {
if (Time.hh > 0)Time.hh--;
go(scr5_hour);
};
JoyLR.Do2 = [] {
if (Time.hh < 23)Time.hh++;
go(scr5_hour);
};
break;
case scr5_min: {
lcd << F("SetTime:") << Time.hh << F(">") << Time.mm << F(":") << Time.ss ;
lcd.show();
}
Btn.Do = [] {go(scr5_sec);};
JoyLR.Do1 = [] {
if (Time.mm > 0)Time.mm--;
go(scr5_min);
};
JoyLR.Do2 = [] {
if (Time.mm < 59)Time.mm++;
go(scr5_min);
};
break;
case scr5_sec: {
lcd << F("SetTime:") << Time.hh << F(":") << Time.mm << F(">") << Time.ss;
lcd.show();
}
Btn.Do = [] {
rtc.write(Time);
now = Time;
for (int i = 0; i < RelayNum; i++)Relay[i].reset();
go(scr5);
};
JoyLR.Do1 = [] {
if (Time.ss > 0)Time.ss--;
go(scr5_sec);
};
JoyLR.Do2 = [] {
if (Time.ss < 59)Time.ss++;
go(scr5_sec);
};
break;
}
}
void menuInit() {
lcd.lightON();
now = rtc.read();
JoyUD.Do1 = [] {lcd.lightON();};
JoyUD.Do2 = [] {lcd.lightOFF();};
go(scr0);
}
void menuRun() {
if (scr != scr0 && millis() - past >= 3000)go(scr0);
if (scr == scr0 && millis() - past >= 500)go(scr0);
}
//-----------------------------
void setup() {
lcd.init();
//rtc.write(F("00:00:00"));
rtc.write(F(__TIME__));//(для первичной настройки часов)
now = rtc.read();
setZero();////(для первичной настройки устройства)
for (int i = 0; i < RelayNum; i++)Relay[i].init();
Btn.init();
JoyLR.init();
JoyUD.init();
menuInit();
}
void loop() {
now_ = now;
now = rtc.read();
if (now_.hh == 23 && now.hh == 0)
for (int i = 0; i < RelayNum; i++)Relay[i].reset();
for (int i = 0; i < RelayNum; i++)Relay[i].run();
Btn.run();
JoyLR.run();
JoyUD.run();
menuRun();
}
/**/
До меня дошли слухи, что до народа дошли слухи, что я использую лямда функции не правильно. Сообщаю. Они не правдивы. Лямда-функции это очень простой иструмент и не надо носится с ним как с чемоданом без ручки. Отказаться жалко, а использовать страшно.
Возьмем этот скетч
typedef int num_t; //<-- создаем тип
num_t aaa=5; // создаем переменную этого типа
//---------------------------------------
void setup() {
Serial.begin(9600);
Serial.print(aaa); //<- используем эту переменую для вывода
}
void loop() {
}
Вам страшно использовать переменные. Нет. А чего здесь у Вас комплексы полезли.
typedef void(*pDo)(); //<-- создаем тип указатель на функцию
pDo Do = []{}; // создаем переменую указатель на функцию и присваиваем ей значение лемдафункция
void setup() {
Do();//< - используем уже эту переменную как функцию
}
void loop() {
}
А так
typedef int(*pDo)(); //<-- создаем тип указатель на функцию
pDo Do = [] { return 5;}; // создаем переменую указатель на функцию и присваиваем ей значение лемдафункция
//-----------------------------------
void setup() {
Serial.begin(9600);
Serial.print(Do());
}
void loop() {
}
Теперь сделаем вывод на экран LCD1602 I2C
Если не против.
Редактируемые переменные (уставки) и их мин. и макс. значения можно не хранить в ОЗУ, а только в еепром и загружать в локальные по необходимости. Это на случай если уставок десятки-сотни.
При работе с еепром удобно пользоваться атрибутом ЕЕМЕМ. Ненадо помнить где какая переменная лежит.
http://robocraft.ru/blog/3043.html
Ну где-то так
/**/ //--переменые--------------------- #include <avr/eeprom.h> typedef struct { uint8_t value; uint8_t minimum; uint8_t maximum; } byte_t ; const byte numVar = 4; byte_t EEMEM adr[numVar]; void saveZeroSettings() { byte_t data[numVar] = { // начальные настройки {10, 10, 50}, // 1-я переменная {20, 10, 50}, // 2-я переменная {30, 10, 50}, // 3-я переменная {40, 10, 50} // 4-я переменная }; for (int i = 0; i < numVar; ++i) { eeprom_write_byte(&adr[i].value , data[i].value); eeprom_write_byte(&adr[i].minimum, data[i].minimum); eeprom_write_byte(&adr[i].maximum, data[i].maximum); } } byte var[4]; void initVar() { for (int i = 0; i < numVar; ++i) { var[i] = eeprom_read_byte(&adr[i].value); } } //---------------------------------------------- template <typename T> inline Print & operator << (Print & s, T n) { s.print(n); return s; } //----------------------------------------------- void setup() { Serial.begin(9600); saveZeroSettings(); initVar(); for (int i = 0; i < numVar; ++i) { var[i] = eeprom_read_byte(&adr[i].value); Serial << i << "=" << var[i] << "\n"; } } void loop() { }Поправил скетч #50 Понятно что скеч стал сложнее для понимания.Но проверил - работает
//--переменые--------------------- #include <avr/eeprom.h> typedef struct { uint8_t value; uint8_t minimum; uint8_t maximum; } byte_t ; const byte numVar = 4; byte_t EEMEM adr[numVar]; void saveZeroSettings() { byte_t data[numVar] = { // начальные настройки {10, 10, 50}, // 1-я переменная {20, 10, 50}, // 2-я переменная {30, 10, 50}, // 3-я переменная {40, 10, 50} // 4-я переменная }; for (int i = 0; i < numVar; ++i) { eeprom_write_byte(&adr[i].value , data[i].value ); eeprom_write_byte(&adr[i].minimum, data[i].minimum); eeprom_write_byte(&adr[i].maximum, data[i].maximum); } } byte var[4]; void initVar() { for (int i = 0; i < numVar; ++i) { var[i] = eeprom_read_byte(&adr[i].value); } } //---------сенсор---------------------------- class Cl_sens { protected: const byte pin; byte val; unsigned long past; public: Cl_sens(byte p): pin(p) {} void init() { pinMode(pin, INPUT); val = analogRead(pin) / 16; past = millis(); } void run() { if (millis() - past >= 500) { val = analogRead(pin) / 16; past = millis(); } } byte read() { return val; } }; const int numSens = 2; Cl_sens Sens[numSens] = { Cl_sens(/*пин*/A0), //сенсор 1 Cl_sens(/*пин*/A1), //сенсор 2 }; //---кнопки----------------------------- typedef void (*pDo)(); class Cl_btn { protected: byte pin; bool state; unsigned long past; void set(bool s) { state = s; past = millis(); switch (s) { case false: break; case true: Do(); break; } } public: Cl_btn(byte p): pin(p) {} pDo Do = [] {}; void init() { pinMode(pin, INPUT_PULLUP); set(false); } void run() { if (millis() - past >= 100) switch (state) { case false: if (!digitalRead(pin))set(true); break; case true: if (digitalRead(pin))set(false); if (millis() - past >= 300)set(false); break; } } }; const int numBtn = 3; Cl_btn Btn[numBtn] = { Cl_btn(/*пин*/2), //кнопка верх Cl_btn(/*пин*/3), //кнопка вниз Cl_btn(/*пин*/4) //кнопка Select }; //--LCD1602----------------------------- #include <Wire.h> #include <LiquidCrystal_I2C.h> LiquidCrystal_I2C lcd(0x27, 16, 2); bool backlightState = 0; void invertBL() { if (!backlightState) { backlightState = 1; lcd.backlight();// Включаем подсветку дисплея } else { backlightState = 0; lcd.noBacklight();// Выключаем подсветку дисплея } } //--меню-------------------------- template <typename T> inline Print & operator << (Print &s, T n) { s.print(n); return s; } const byte strMain = 0; // главный экран const byte str1 = 1; // 1-й экран const byte Estr1 = 2; // 1-й экран(редактирование) const byte str2 = 3; // 2-й экран const byte Estr2 = 4; // 2-й экран(редактирование) const byte str3 = 5; // 3-й экран const byte Estr3 = 6; // 3-й экран(редактирование) const byte str4 = 7; // 4-й экран const byte Estr4 = 8; // 4-й экран(редактирование) byte pos; byte editVar; unsigned long pastMenu; void setPos(byte p) { pastMenu = millis(); pos = p; switch (p) { case strMain: lcd.clear(); lcd << F("T1:") << Sens[0].read() << F(" "); lcd.setCursor(0, 1); lcd << F("T2:") << Sens[1].read() << F(" "); Btn[0].Do = [] {}; //кнопка верх Btn[1].Do = [] {setPos(str1);}; //кнопка вниз Btn[2].Do = [] {invertBL();}; //кнопка Select break; case str1: lcd.clear(); lcd << F("var1=") << var[0] << F(" "); Btn[0].Do = [] {setPos(strMain);}; //кнопка верх Btn[1].Do = [] {setPos(str2);}; //кнопка вниз Btn[2].Do = [] { //кнопка Select editVar = var[0]; setPos(Estr1); }; break; case Estr1: lcd.clear(); lcd << F("var1-") << editVar << F(" "); Btn[0].Do = [] { //кнопка верх byte maximum = eeprom_read_byte(&adr[0].maximum); if (editVar < maximum) editVar++; setPos(Estr1); }; Btn[1].Do = [] { //кнопка вниз byte minimum = eeprom_read_byte(&adr[0].minimum); if (editVar > minimum) editVar--; setPos(Estr1); }; Btn[2].Do = [] { //кнопка Select eeprom_write_byte(&adr[0].value, editVar); var[0] = editVar; setPos(str1); }; break; case str2: lcd.clear(); lcd << F("var2=") << var[1] << F(" "); Btn[0].Do = [] {setPos(str1);}; //кнопка верх Btn[1].Do = [] {setPos(str3);}; //кнопка вниз Btn[2].Do = [] { //кнопка Select editVar = var[1]; setPos(Estr2); }; break; case Estr2: lcd.clear(); lcd << F("var2-") << editVar << F(" "); Btn[0].Do = [] { byte maximum = eeprom_read_byte(&adr[1].maximum); if (editVar < maximum) editVar++; setPos(Estr2); }; //кнопка верх Btn[1].Do = [] { byte minimum = eeprom_read_byte(&adr[1].minimum); if (editVar > minimum) editVar--; setPos(Estr2); }; //кнопка вниз Btn[2].Do = [] { //кнопка Select eeprom_write_byte(&adr[1].value, editVar); var[1] = editVar; setPos(str2); }; break; case str3: lcd.clear(); lcd << F("var3=") << var[2] << F(" "); Btn[0].Do = [] {setPos(str2);}; //кнопка верх Btn[1].Do = [] {setPos(str4);}; //кнопка вниз Btn[2].Do = [] { //кнопка Select editVar = var[2]; setPos(Estr3); }; break; case Estr3: lcd.clear(); lcd << F("var3-") << editVar << F(" "); Btn[0].Do = [] { //кнопка верх byte maximum = eeprom_read_byte(&adr[2].maximum); if (editVar < maximum) editVar++; setPos(Estr3); }; Btn[1].Do = [] { //кнопка вниз byte minimum = eeprom_read_byte(&adr[2].minimum); if (editVar > minimum) editVar--; setPos(Estr3); }; Btn[2].Do = [] { //кнопка Select eeprom_write_byte(&adr[2].value, editVar); var[2] = editVar; setPos(str3); }; break; case str4: lcd.clear(); lcd << F("var4=") << var[3] << F(" "); Btn[0].Do = [] {setPos(str3);}; //кнопка верх Btn[1].Do = [] {}; //кнопка вниз Btn[2].Do = [] { //кнопка Select editVar = var[3]; setPos(Estr4); }; break; case Estr4: lcd.clear(); lcd << F("var4-") << editVar << F(" "); Btn[0].Do = [] { //кнопка верх byte maximum = eeprom_read_byte(&adr[3].maximum); if (editVar < maximum) editVar++; setPos(Estr3); }; Btn[1].Do = [] { //кнопка вниз byte minimum = eeprom_read_byte(&adr[3].minimum); if (editVar > minimum) editVar--; setPos(Estr4); }; Btn[2].Do = [] { //кнопка Select eeprom_write_byte(&adr[3].value, editVar); var[3] = editVar; setPos(str4); }; break; } } void runMenu() { switch (pos) { case strMain: // если находимся на главном экране то обновлять каждую секунду if (millis() - pastMenu >= 1000) setPos(strMain); break; default: // если пользователь не нажимает на кнопки, то вернуться на главный экран if (millis() - pastMenu >= 10000) setPos(strMain); } } //--main------------------------------ void setup() { //saveZeroSettings(); раскоментировать только для загрузки EEPROM initVar(); for (int i = 0; i < numSens; i++)Sens[i].init(); for (int i = 0; i < numBtn; i++)Btn[i].init(); lcd.init(); invertBL(); setPos(strMain); } void loop() { for (int i = 0; i < numSens; i++)Sens[i].run(); for (int i = 0; i < numBtn; i++)Btn[i].run(); runMenu(); }Ну а теперь подключим ... реле
//--переменые--------------------- #include <avr/eeprom.h> typedef struct { uint8_t value; uint8_t minimum; uint8_t maximum; } byte_t ; const byte numVar = 4; byte_t EEMEM adr[numVar]; void saveZeroSettings() { byte_t data[numVar] = { // начальные настройки {20, 10, 50}, // 1-я переменная {30, 10, 50}, // 2-я переменная {20, 10, 50}, // 3-я переменная {30, 10, 50} // 4-я переменная }; for (int i = 0; i < numVar; ++i) { eeprom_write_byte(&adr[i].value , data[i].value ); eeprom_write_byte(&adr[i].minimum, data[i].minimum); eeprom_write_byte(&adr[i].maximum, data[i].maximum); } } byte var[4]; void initVar() { for (int i = 0; i < numVar; ++i) { var[i] = eeprom_read_byte(&adr[i].value); } } //---------сенсор---------------------------- class Cl_sens { protected: const byte pin; byte val; unsigned long past; public: Cl_sens(byte p): pin(p) {} void init() { pinMode(pin, INPUT); val = analogRead(pin) / 16; past = millis(); } void run() { if (millis() - past >= 500) { val = analogRead(pin) / 16; past = millis(); } } byte read() { return val; } }; const int numSens = 2; Cl_sens Sens[numSens] = { Cl_sens(/*пин*/A0), //сенсор 1 Cl_sens(/*пин*/A1), //сенсор 2 }; //---кнопки----------------------------- typedef void (*pDo)(); class Cl_btn { protected: byte pin; bool state; unsigned long past; void set(bool s) { state = s; past = millis(); switch (s) { case false: break; case true: Do(); break; } } public: Cl_btn(byte p): pin(p) {} pDo Do = [] {}; void init() { pinMode(pin, INPUT_PULLUP); set(false); } void run() { if (millis() - past >= 100) switch (state) { case false: if (!digitalRead(pin))set(true); break; case true: if (digitalRead(pin))set(false); if (millis() - past >= 300)set(false); break; } } }; const int numBtn = 3; Cl_btn Btn[numBtn] = { Cl_btn(/*пин*/2), //кнопка верх Cl_btn(/*пин*/3), //кнопка вниз Cl_btn(/*пин*/4) //кнопка Select }; //--LCD1602----------------------------- #include <Wire.h> #include <LiquidCrystal_I2C.h> LiquidCrystal_I2C lcd(0x27, 16, 2); bool backlightState = 0; void invertBL() { if (!backlightState) { backlightState = 1; lcd.backlight();// Включаем подсветку дисплея } else { backlightState = 0; lcd.noBacklight();// Выключаем подсветку дисплея } } //---реле------------------------------- typedef byte (*pRetByte)(); class Cl_relay { protected: byte pin; pRetByte RetByte1 = [] {return (byte)0;}; pRetByte RetByte2 = [] {return (byte)0;}; bool state; unsigned long past; void set(bool s) { past = millis(); state = s; switch (s) { case false: digitalWrite(pin, HIGH); break; case true: digitalWrite(pin, LOW); break; } } public: Cl_relay(byte p, pRetByte pRB1, pRetByte pRB2) : pin(p), RetByte1(pRB1), RetByte2(pRB2) {} void init() { pinMode(pin, OUTPUT); set(false); } void run() { if (millis() - past > 200) { switch (state) { case false: if (RetByte1() >= RetByte2() + 1)set(true); break; case true: if (RetByte2() >= RetByte1() + 1)set(false); break; } } } void viev() { switch (state) { case false: lcd << F("OFF"); break; case true: lcd << F(" ON"); break; } } }; const int numRly = 4; Cl_relay Rly[numRly] = { // пин 1 выражением сравнивается с 2 выражением Cl_relay(/*пин*/5, [] {return var[0];}, [] {return Sens[0].read();}), //реле 1 Cl_relay(/*пин*/6, [] {return var[1];}, [] {return Sens[0].read();}), //реле 2 Cl_relay(/*пин*/7, [] {return var[2];}, [] {return Sens[1].read();}), //реле 4 Cl_relay(/*пин*/8, [] {return var[3];}, [] {return Sens[1].read();}) //реле 3 }; //--меню-------------------------- template <typename T> inline Print & operator << (Print &s, T n) { s.print(n); return s; } const byte strMain = 0; // главный экран const byte str1 = 1; // 1-й экран const byte Estr1 = 2; // 1-й экран(редактирование) const byte str2 = 3; // 2-й экран const byte Estr2 = 4; // 2-й экран(редактирование) const byte str3 = 5; // 3-й экран const byte Estr3 = 6; // 3-й экран(редактирование) const byte str4 = 7; // 4-й экран const byte Estr4 = 8; // 4-й экран(редактирование) byte pos; byte editVar; unsigned long pastMenu; void setPos(byte p) { pastMenu = millis(); pos = p; switch (p) { case strMain: lcd.clear(); lcd << F("T1:") << Sens[0].read() << F(" "); lcd.setCursor(6, 0); Rly[0].viev(); lcd.setCursor(10, 0); Rly[1].viev(); lcd.setCursor(0, 1); lcd << F("T2:") << Sens[1].read() << F(" "); lcd.setCursor(6, 1); Rly[2].viev(); lcd.setCursor(10, 1); Rly[3].viev(); Btn[0].Do = [] {}; //кнопка верх Btn[1].Do = [] {setPos(str1);}; //кнопка вниз Btn[2].Do = [] {invertBL();}; //кнопка Select break; case str1: lcd.clear(); lcd << F("var1=") << var[0] << F(" "); Btn[0].Do = [] {setPos(strMain);}; //кнопка верх Btn[1].Do = [] {setPos(str2);}; //кнопка вниз Btn[2].Do = [] { //кнопка Select editVar = var[0]; setPos(Estr1); }; break; case Estr1: lcd.clear(); lcd << F("var1-") << editVar << F(" "); Btn[0].Do = [] { //кнопка верх byte maximum = eeprom_read_byte(&adr[0].maximum); if (editVar < maximum) editVar++; setPos(Estr1); }; Btn[1].Do = [] { //кнопка вниз byte minimum = eeprom_read_byte(&adr[0].minimum); if (editVar > minimum) editVar--; setPos(Estr1); }; Btn[2].Do = [] { //кнопка Select eeprom_write_byte(&adr[0].value, editVar); var[0] = editVar; setPos(str1); }; break; case str2: lcd.clear(); lcd << F("var2=") << var[1] << F(" "); Btn[0].Do = [] {setPos(str1);}; //кнопка верх Btn[1].Do = [] {setPos(str3);}; //кнопка вниз Btn[2].Do = [] { //кнопка Select editVar = var[1]; setPos(Estr2); }; break; case Estr2: lcd.clear(); lcd << F("var2-") << editVar << F(" "); Btn[0].Do = [] { byte maximum = eeprom_read_byte(&adr[1].maximum); if (editVar < maximum) editVar++; setPos(Estr2); }; //кнопка верх Btn[1].Do = [] { byte minimum = eeprom_read_byte(&adr[1].minimum); if (editVar > minimum) editVar--; setPos(Estr2); }; //кнопка вниз Btn[2].Do = [] { //кнопка Select eeprom_write_byte(&adr[1].value, editVar); var[1] = editVar; setPos(str2); }; break; case str3: lcd.clear(); lcd << F("var3=") << var[2] << F(" "); Btn[0].Do = [] {setPos(str2);}; //кнопка верх Btn[1].Do = [] {setPos(str4);}; //кнопка вниз Btn[2].Do = [] { //кнопка Select editVar = var[2]; setPos(Estr3); }; break; case Estr3: lcd.clear(); lcd << F("var3-") << editVar << F(" "); Btn[0].Do = [] { //кнопка верх byte maximum = eeprom_read_byte(&adr[2].maximum); if (editVar < maximum) editVar++; setPos(Estr3); }; Btn[1].Do = [] { //кнопка вниз byte minimum = eeprom_read_byte(&adr[2].minimum); if (editVar > minimum) editVar--; setPos(Estr3); }; Btn[2].Do = [] { //кнопка Select eeprom_write_byte(&adr[2].value, editVar); var[2] = editVar; setPos(str3); }; break; case str4: lcd.clear(); lcd << F("var4=") << var[3] << F(" "); Btn[0].Do = [] {setPos(str3);}; //кнопка верх Btn[1].Do = [] {}; //кнопка вниз Btn[2].Do = [] { //кнопка Select editVar = var[3]; setPos(Estr4); }; break; case Estr4: lcd.clear(); lcd << F("var4-") << editVar << F(" "); Btn[0].Do = [] { //кнопка верх byte maximum = eeprom_read_byte(&adr[3].maximum); if (editVar < maximum) editVar++; setPos(Estr3); }; Btn[1].Do = [] { //кнопка вниз byte minimum = eeprom_read_byte(&adr[3].minimum); if (editVar > minimum) editVar--; setPos(Estr4); }; Btn[2].Do = [] { //кнопка Select eeprom_write_byte(&adr[3].value, editVar); var[3] = editVar; setPos(str4); }; break; } } void runMenu() { switch (pos) { case strMain: // если находимся на главном экране то обновлять каждую секунду if (millis() - pastMenu >= 1000) setPos(strMain); break; default: // если пользователь не нажимает на кнопки, то вернуться на главный экран if (millis() - pastMenu >= 10000) setPos(strMain); } } //--main------------------------------ void setup() { saveZeroSettings();// раскоментировать только для загрузки EEPROM initVar(); for (int i = 0; i < numSens; i++)Sens[i].init(); for (int i = 0; i < numRly ; i++)Rly [i].init(); for (int i = 0; i < numBtn; i++)Btn[i].init(); lcd.init(); invertBL(); setPos(strMain); } void loop() { for (int i = 0; i < numSens; i++)Sens[i].run(); for (int i = 0; i < numRly ; i++) Rly[i].run(); for (int i = 0; i < numBtn; i++)Btn[i].run(); runMenu(); }Так на будущее на подумать.
/**/ //--так оценочный класс byte ---- typedef struct { byte data; } byte_t; class Cl_byte { protected : byte_t adr; byte data; public: Cl_byte(byte_t a): adr(a) { data = read(); } byte read() { return eeprom_read_byte(&adr.data); } void write(byte d) { data = d; if (read() != d) eeprom_write_byte(&adr.data, d); } void zeroSetting() { byte_t tmp = {0xFF}; eeprom_write_byte(&adr.data, tmp.data); } }; const byte num = 5; byte_t EEMEM adr[num]; Cl_byte Byte[num] = { Cl_byte(adr[0]), Cl_byte(adr[1]), Cl_byte(adr[2]), Cl_byte(adr[3]), Cl_byte(adr[4]) }; void setup() { //for (int i = 0; i < num; i++)Byte[i].zeroSetting(); // для первичной настройки в EEPROM for (int i = 0; i < num; i++)Byte[i].read(); for (int i = 0; i < num; i++)Byte[i].write(10); } void loop() { }Переписал программу #11 под теперешний стиль
/*LCD Key Shield*/ unsigned long mill; //--------------------Cl_aKeyboard-------------------------------- typedef void (*pDo)(); /*состояние-нет нажатий/правая/левая/вверх/вниз/влево/выбор*/ const byte skNone = 0; const byte skRight = 1; const byte skUp = 2; const byte skDown = 3; const byte skLeft = 4; const byte skSelect = 5; class Cl_aKeyboard { public: // обработчики кнопок pDo DoRight = [] {}; pDo DoUp = [] {}; pDo DoDown = [] {}; pDo DoLeft = [] {}; pDo DoSelect = [] {}; protected: const byte pin; byte state; unsigned long past; byte read() { int tmp = analogRead(pin); if (tmp < 80) return skRight; else if (tmp < 200) return skUp; else if (tmp < 400) return skDown; else if (tmp < 600) return skLeft; else if (tmp < 800) return skSelect; else return skNone; } void set(byte s) { state = s; past = millis(); switch (s) { case skNone: break; case skRight: DoRight(); break; case skUp: DoUp(); break; case skDown: DoDown(); break; case skLeft: DoLeft(); break; case skSelect: DoSelect(); break; } } public: Cl_aKeyboard(byte p) : pin(p) {} void init() { set(read()); } void run() { if (millis() - past >= 100) { switch (state) { case skNone: { byte tmp = read(); if (tmp != skNone)set(tmp); break; } default: if (millis() - past >= 300)set(skNone); } } } }; Cl_aKeyboard Keyboard(/*пин*/A0); //---------------lcd и меню--------------------------------------------- template <typename T> inline Print & operator << (Print &s, T n) { s.print(n); return s; } #include <LiquidCrystal.h> LiquidCrystal lcd(/*RS*/8,/*Enable*/9,/*DB4*/4,/*DB5*/5,/*DB6*/6,/*DB7*/7); const byte sNone = 0;// 1-экран const byte sRight = 1;// 2-экран const byte sUp = 2;// 3-экран const byte sDown = 3;// 4-экран const byte sLeft = 4;// 5-экран const byte sSelect = 5;// 6-экран byte pos; unsigned long past; void setPos(byte p) { pos = p; past = millis(); switch (p) { case sNone: lcd.clear(); lcd << F("LCD Key Shield"); lcd.setCursor(0, 1); lcd << F("Press Key:None"); break; case sRight: lcd.clear(); lcd << F("LCD Key Shield"); lcd.setCursor(0, 1); lcd << F("Press Key:Right"); break; case sUp: lcd.clear(); lcd << F("LCD Key Shield"); lcd.setCursor(0, 1); lcd << F("Press Key:Up"); break; case sDown: lcd.clear(); lcd << F("LCD Key Shield"); lcd.setCursor(0, 1); lcd << F("Press Key:Down"); break; case sLeft: lcd.clear(); lcd << F("LCD Key Shield"); lcd.setCursor(0, 1); lcd << F("Press Key:Left"); break; case sSelect: lcd.clear(); lcd << F("LCD Key Shield"); lcd.setCursor(0, 1); lcd << F("Press Key:Select"); break; } } void menuInit() { lcd.begin(16, 2); setPos(sNone); Keyboard.DoRight = [] {setPos(sRight); }; Keyboard.DoUp = [] {setPos(sUp); }; Keyboard.DoDown = [] {setPos(sDown); }; Keyboard.DoLeft = [] {setPos(sLeft); }; Keyboard.DoSelect = [] {setPos(sSelect);}; } void menuRun() { if (pos != sNone && millis() - past >= 10000)setPos(sNone); } //---------------------------------------- void setup() { Keyboard.init(); menuInit(); } void loop() { Keyboard.run(); menuRun(); } /**//*LCD Key Shield*/ unsigned long mill; //--------------------Cl_aKeyboard-------------------------------- typedef void (*pDo)(); /*состояние-нет нажатий/правая/левая/вверх/вниз/влево/выбор*/ const byte skNone = 0; const byte skRight = 1; const byte skUp = 2; const byte skDown = 3; const byte skLeft = 4; const byte skSelect = 5; class Cl_aKeyboard { public: // обработчики кнопок pDo DoRight = [] {}; pDo DoUp = [] {}; pDo DoDown = [] {}; pDo DoLeft = [] {}; pDo DoSelect = [] {}; protected: const byte pin; byte state; unsigned long past; byte read() { int tmp = analogRead(pin); if (tmp < 100) return skRight; else if (tmp < 200) return skUp; else if (tmp < 400) return skDown; else if (tmp < 600) return skLeft; else if (tmp < 800) return skSelect; else return skNone; } void set(byte s) { state = s; past = millis(); switch (s) { case skNone: break; case skRight: DoRight(); break; case skUp: DoUp(); break; case skDown: DoDown(); break; case skLeft: DoLeft(); break; case skSelect: DoSelect(); break; } } public: Cl_aKeyboard(byte p) : pin(p) {} void init() { set(read()); } void run() { if (millis() - past >= 100) { switch (state) { case skNone: { byte tmp = read(); if (tmp != skNone)set(tmp); break; } default: if (millis() - past >= 300)set(skNone); } } } }; Cl_aKeyboard Keyboard(/*пин*/A0); //---------------lcd и меню--------------------------------------------- template <typename T> inline Print & operator << (Print &s, T n) { s.print(n); return s; } #include <LiquidCrystal.h> LiquidCrystal lcd(/*RS*/8,/*Enable*/9,/*DB4*/4,/*DB5*/5,/*DB6*/6,/*DB7*/7); const byte sMain = 0;// главный экран const byte ss1 = 1;// 1-экран const byte ss2 = 2;// 2-экран const byte ss3 = 3;// 3-экран const byte ss4 = 4;// 4-экран const byte ss5 = 5;// 5-экран byte pos; unsigned long past; void setPos(byte p) { pos = p; past = millis(); switch (p) { case sMain: lcd.clear(); lcd << F("Main screen"); Keyboard.DoUp = [] { }; Keyboard.DoDown = [] {setPos(ss1); }; break; case ss1: lcd.clear(); lcd << F("1 screen"); Keyboard.DoUp = [] {setPos(sMain); }; Keyboard.DoDown = [] {setPos(ss2); }; break; case ss2: lcd.clear(); lcd << F("2 screen"); Keyboard.DoUp = [] {setPos(ss1); }; Keyboard.DoDown = [] {setPos(ss3); }; break; case ss3: lcd.clear(); lcd << F("3 screen"); Keyboard.DoUp = [] {setPos(ss2); }; Keyboard.DoDown = [] {setPos(ss4); }; break; case ss4: lcd.clear(); lcd << F("4 screen"); Keyboard.DoUp = [] {setPos(ss3); }; Keyboard.DoDown = [] {setPos(ss5); }; break; case ss5: lcd.clear(); lcd << F("5 screen"); Keyboard.DoUp = [] {setPos(ss4); }; Keyboard.DoDown = [] { }; break; } } void menuInit() { lcd.begin(16, 2); setPos(sMain); } void menuRun() { if (pos != sMain && millis() - past >= 10000)setPos(sMain); if (pos == sMain && millis() - past >= 1000)setPos(sMain); } //---------------------------------------- void setup() { Keyboard.init(); menuInit(); } void loop() { Keyboard.run(); menuRun(); } /**/Скетч для использования Ардуино-джойстика для меню, работает .
//---кнопкa----------------------------- typedef void (*pDo)(); class Cl_btn { protected: byte pin; bool state; unsigned long past; void set(bool s) { state = s; past = millis(); switch (s) { case false: break; case true: Do(); break; } } public: Cl_btn(byte p): pin(p) {} pDo Do = [] {}; void init() { pinMode(pin, INPUT_PULLUP); set(false); } void run() { if (millis() - past >= 100) switch (state) { case false: if (!digitalRead(pin))set(true); break; case true: if (digitalRead(pin))set(false); if (millis() - past >= 300)set(false); break; } } }; Cl_btn Btn(/*пин*/A0); //------------------------------------------- const byte st1 = 0; const byte st0 = 1; const byte st2 = 2; class Cl_joystic { protected: byte pin; byte state; unsigned long past; void set(byte s) { state = s; past = millis(); switch (s) { case st0: break; case st1: Do1(); break; case st2: Do2(); break; } } public: Cl_joystic(byte p): pin(p) {} pDo Do1 = [] {}; pDo Do2 = [] {}; void init() { set(st0); } void run() { if (millis() - past >= 100) { int tmp = analogRead(pin); switch (state) { case st1: if (tmp > 450)set(st0); if (millis() - past >= 300)set(st0); break; case st0: if (tmp < 400)set(st1); else if (tmp > 600)set(st2); break; case st2: if (tmp < 550)set(st0); if (millis() - past >= 300)set(st0); break; } } } }; Cl_joystic JoyLR(/*пин*/A1); Cl_joystic JoyUD(/*пин*/A2); //--меню-------------------------- template <typename T> inline Print & operator << (Print &s, T n) { s.print(n); return s; } //---------------------------------- void setup() { Serial.begin(9600); Btn.init(); JoyLR.init(); JoyUD.init(); Btn.Do = [] {Serial << F("Btn\n");}; JoyLR.Do1 = [] {Serial << F("Right\n");}; JoyLR.Do2 = [] {Serial << F("Left\n");}; JoyUD.Do1 = [] {Serial << F("Up\n");}; JoyUD.Do2 = [] {Serial << F("Down\n");}; } void loop() { Btn.run(); JoyLR.run(); JoyUD.run(); } /**/А теперь подключим lcd I2C с меню . джойстик вверх вкл подсветку, вниз выключить . вправо-влево бегаем по экранам меню . если ничего не делаем 10сек возврат на главный экран. Подобный скетч выше но на трех кнопках.
//---кнопкa----------------------------- typedef void (*pDo)(); class Cl_btn { protected: byte pin; bool state; unsigned long past; void set(bool s) { state = s; past = millis(); switch (s) { case false: break; case true: Do(); break; } } public: Cl_btn(byte p): pin(p) {} pDo Do = [] {}; void init() { pinMode(pin, INPUT_PULLUP); set(false); } void run() { if (millis() - past >= 100) switch (state) { case false: if (!digitalRead(pin))set(true); break; case true: if (digitalRead(pin))set(false); if (millis() - past >= 300)set(false); break; } } }; Cl_btn Btn(/*пин*/A0); //------------------------------------------- const byte st1 = 0; const byte st0 = 1; const byte st2 = 2; class Cl_joystic { protected: byte pin; byte state; unsigned long past; void set(byte s) { state = s; past = millis(); switch (s) { case st0: break; case st1: Do1(); break; case st2: Do2(); break; } } public: Cl_joystic(byte p): pin(p) {} pDo Do1 = [] {}; pDo Do2 = [] {}; void init() { set(st0); } void run() { if (millis() - past >= 100) { int tmp = analogRead(pin); switch (state) { case st1: if (tmp > 450)set(st0); if (millis() - past >= 300)set(st0); break; case st0: if (tmp < 400)set(st1); else if (tmp > 600)set(st2); break; case st2: if (tmp < 550)set(st0); if (millis() - past >= 300)set(st0); break; } } } }; Cl_joystic JoyLR(/*пин*/A1); Cl_joystic JoyUD(/*пин*/A2); //---------------lcd--------------------------------------------- #include <Wire.h> #include <LiquidCrystal_I2C.h> LiquidCrystal_I2C lcd(0x27, 16, 2); //--------------- меню--------------------------------------------- template <typename T> inline Print & operator << (Print &s, T n) { s.print(n); return s; } const byte sMain = 0;// главный экран const byte ss1 = 1;// 1-экран const byte ss2 = 2;// 2-экран const byte ss3 = 3;// 3-экран const byte ss4 = 4;// 4-экран const byte ss5 = 5;// 5-экран byte pos; unsigned long past; void setPos(byte p) { pos = p; past = millis(); lcd.clear(); switch (p) { case sMain: lcd << F("Main screen"); JoyUD.Do1 = [] { }; JoyUD.Do2 = [] {setPos(ss1); }; break; case ss1: lcd << F("1 screen"); JoyUD.Do1 = [] {setPos(sMain); }; JoyUD.Do2 = [] {setPos(ss2); }; break; case ss2: lcd << F("2 screen"); JoyUD.Do1 = [] {setPos(ss1); }; JoyUD.Do2 = [] {setPos(ss3); }; break; case ss3: lcd << F("3 screen"); JoyUD.Do1 = [] {setPos(ss2); }; JoyUD.Do2 = [] {setPos(ss4); }; break; case ss4: lcd << F("4 screen"); JoyUD.Do1 = [] {setPos(ss3); }; JoyUD.Do2 = [] {setPos(ss5); }; break; case ss5: lcd << F("5 screen"); JoyUD.Do1 = [] {setPos(ss4); }; JoyUD.Do2 = [] {}; break; } } void menuInit() { lcd.begin(16, 2); setPos(sMain); } void menuRun() { if (pos != sMain && millis() - past >= 10000)setPos(sMain); if (pos == sMain && millis() - past >= 1000)setPos(sMain); } //---------------------------------- void setup() { lcd.init(); Btn.init(); JoyLR.init(); JoyUD.init(); menuInit(); Btn.Do = [] {}; JoyLR.Do1 = [] {lcd.backlight();}; JoyLR.Do2 = [] {lcd.noBacklight();}; } void loop() { Btn.run(); JoyLR.run(); JoyUD.run(); menuRun(); } /**/Добавил таймер на millis
//---кнопкa----------------------------- typedef void (*pDo)(); class Cl_btn { protected: byte pin; bool state; unsigned long past; void set(bool s) { state = s; past = millis(); switch (s) { case false: break; case true: Do(); break; } } public: Cl_btn(byte p): pin(p) {} pDo Do = [] {}; void init() { pinMode(pin, INPUT_PULLUP); set(false); } void run() { if (millis() - past >= 100) switch (state) { case false: if (!digitalRead(pin))set(true); break; case true: if (digitalRead(pin))set(false); if (millis() - past >= 300)set(false); break; } } }; Cl_btn Btn(/*пин*/A0); //------------------------------------------- const byte st1 = 0; const byte st0 = 1; const byte st2 = 2; class Cl_joystic { protected: byte pin; byte state; unsigned long past; void set(byte s) { state = s; past = millis(); switch (s) { case st0: break; case st1: Do1(); break; case st2: Do2(); break; } } public: Cl_joystic(byte p): pin(p) {} pDo Do1 = [] {}; pDo Do2 = [] {}; void init() { set(st0); } void run() { if (millis() - past >= 100) { int tmp = analogRead(pin); switch (state) { case st1: if (tmp > 450)set(st0); if (millis() - past >= 300)set(st0); break; case st0: if (tmp < 400)set(st1); else if (tmp > 600)set(st2); break; case st2: if (tmp < 550)set(st0); if (millis() - past >= 300)set(st0); break; } } } }; Cl_joystic JoyLR(/*пин*/A1); Cl_joystic JoyUD(/*пин*/A2); //---------------lcd--------------------------------------------- #include <Wire.h> #include <LiquidCrystal_I2C.h> LiquidCrystal_I2C lcd(0x27, 16, 2); //--------------- меню--------------------------------------------- template <typename T> inline Print & operator << (Print &s, T n) { s.print(n); return s; } const byte sMain = 0;// главный экран const byte ss1 = 1;// 1-экран const byte ss2 = 2;// 2-экран const byte ss3 = 3;// 3-экран const byte ss4 = 4;// 4-экран const byte ss5 = 5;// 5-экран byte pos; unsigned long past; void setPos(byte p) { pos = p; past = millis(); lcd.clear(); switch (p) { case sMain: { unsigned long now = millis() / 1000; int hour = now / 60 / 60 % 24 ; int minute = now / 60 % 60; int second = now % 60; lcd << F("Time:") << hour << F(":") << minute << F(":") << second; } JoyUD.Do1 = [] { }; JoyUD.Do2 = [] {setPos(ss1); }; break; case ss1: lcd << F("1 screen"); JoyUD.Do1 = [] {setPos(sMain); }; JoyUD.Do2 = [] {setPos(ss2); }; break; case ss2: lcd << F("2 screen"); JoyUD.Do1 = [] {setPos(ss1); }; JoyUD.Do2 = [] {setPos(ss3); }; break; case ss3: lcd << F("3 screen"); JoyUD.Do1 = [] {setPos(ss2); }; JoyUD.Do2 = [] {setPos(ss4); }; break; case ss4: lcd << F("4 screen"); JoyUD.Do1 = [] {setPos(ss3); }; JoyUD.Do2 = [] {setPos(ss5); }; break; case ss5: lcd << F("5 screen"); JoyUD.Do1 = [] {setPos(ss4); }; JoyUD.Do2 = [] {}; break; } } void menuInit() { lcd.begin(16, 2); setPos(sMain); } void menuRun() { if (pos != sMain && millis() - past >= 10000)setPos(sMain); if (pos == sMain && millis() - past >= 1000)setPos(sMain); } //---------------------------------- void setup() { lcd.init(); Btn.init(); JoyLR.init(); JoyUD.init(); menuInit(); Btn.Do = [] {}; JoyLR.Do1 = [] {lcd.backlight();}; JoyLR.Do2 = [] {lcd.noBacklight();}; } void loop() { Btn.run(); JoyLR.run(); JoyUD.run(); menuRun(); } /**///---кнопкa----------------------------- typedef void (*pDo)(); class Cl_btn { protected: byte pin; bool state; unsigned long past; void set(bool s) { state = s; past = millis(); switch (s) { case false: break; case true: Do(); break; } } public: Cl_btn(byte p): pin(p) {} pDo Do = [] {}; void init() { pinMode(pin, INPUT_PULLUP); set(false); } void run() { if (millis() - past >= 100) switch (state) { case false: if (!digitalRead(pin))set(true); break; case true: if (digitalRead(pin))set(false); if (millis() - past >= 300)set(false); break; } } }; Cl_btn Btn(/*пин*/A0); //------------------------------------------- const byte st1 = 0; const byte st0 = 1; const byte st2 = 2; class Cl_joystic { protected: byte pin; byte state; unsigned long past; void set(byte s) { state = s; past = millis(); switch (s) { case st0: break; case st1: Do1(); break; case st2: Do2(); break; } } public: Cl_joystic(byte p): pin(p) {} pDo Do1 = [] {}; pDo Do2 = [] {}; void init() { set(st0); } void run() { if (millis() - past >= 100) { int tmp = analogRead(pin); switch (state) { case st1: if (tmp > 450)set(st0); if (millis() - past >= 300)set(st0); break; case st0: if (tmp < 400)set(st1); else if (tmp > 600)set(st2); break; case st2: if (tmp < 550)set(st0); if (millis() - past >= 300)set(st0); break; } } } }; Cl_joystic JoyLR(/*пин*/A1); Cl_joystic JoyUD(/*пин*/A2); // -------------таймеры------------------------------------------------ typedef struct { byte hour; byte minute; byte second; } timer_t; const timer_t Timer[] = { {0, 0, 0},// 1-й таймер {0, 0, 0},// 2-й таймер {0, 0, 0},// 3-й таймер {0, 0, 0},// 4-й таймер {0, 0, 0} // 5-й таймер }; //---------------lcd--------------------------------------------- #include <Wire.h> #include <LiquidCrystal_I2C.h> LiquidCrystal_I2C lcd(0x27, 16, 2); //--------------- меню--------------------------------------------- template <typename T> inline Print & operator << (Print &s, T n) { s.print(n); return s; } const byte sMain = 0;// главный экран const byte ss1 = 1;// 1-экран const byte ss2 = 2;// 2-экран const byte ss3 = 3;// 3-экран const byte ss4 = 4;// 4-экран const byte ss5 = 5;// 5-экран byte pos; unsigned long past; void setPos(byte p) { pos = p; past = millis(); lcd.clear(); switch (p) { case sMain: { unsigned long now = millis() / 1000; int hour = now / 60 / 60 % 24 ; int minute = now / 60 % 60; int second = now % 60; lcd << F("Time:") << hour << F(":") << minute << F(":") << second; } JoyUD.Do1 = [] { }; JoyUD.Do2 = [] {setPos(ss1); }; break; case ss1: { lcd << F("Timer1:") << Timer[0].hour << F(":") << Timer[0].minute << F(":") << Timer[0].second; } JoyUD.Do1 = [] {setPos(sMain); }; JoyUD.Do2 = [] {setPos(ss2); }; break; case ss2: { lcd << F("Timer2:") << Timer[1].hour << F(":") << Timer[1].minute << F(":") << Timer[1].second; } JoyUD.Do1 = [] {setPos(ss1); }; JoyUD.Do2 = [] {setPos(ss3); }; break; case ss3: { lcd << F("Timer3:") << Timer[2].hour << F(":") << Timer[2].minute << F(":") << Timer[2].second; } JoyUD.Do1 = [] {setPos(ss2); }; JoyUD.Do2 = [] {setPos(ss4); }; break; case ss4: { lcd << F("Timer4:") << Timer[3].hour << F(":") << Timer[3].minute << F(":") << Timer[3].second; } JoyUD.Do1 = [] {setPos(ss3); }; JoyUD.Do2 = [] {setPos(ss5); }; break; case ss5: { lcd << F("Timer5:") << Timer[4].hour << F(":") << Timer[4].minute << F(":") << Timer[4].second; } JoyUD.Do1 = [] {setPos(ss4); }; JoyUD.Do2 = [] {}; break; } } void menuInit() { lcd.begin(16, 2); setPos(sMain); } void menuRun() { if (pos != sMain && millis() - past >= 10000)setPos(sMain); if (pos == sMain && millis() - past >= 1000)setPos(sMain); } //---------------------------------- void setup() { lcd.init(); Btn.init(); JoyLR.init(); JoyUD.init(); menuInit(); Btn.Do = [] {}; JoyLR.Do1 = [] {lcd.backlight();}; JoyLR.Do2 = [] {lcd.noBacklight();}; } void loop() { Btn.run(); JoyLR.run(); JoyUD.run(); menuRun(); } /**///---кнопкa----------------------------- typedef void (*pDo)(); class Cl_btn { protected: byte pin; bool state; unsigned long past; void set(bool s) { state = s; past = millis(); switch (s) { case false: break; case true: Do(); break; } } public: Cl_btn(byte p): pin(p) {} pDo Do = [] {}; void init() { pinMode(pin, INPUT_PULLUP); set(false); } void run() { if (millis() - past >= 100) switch (state) { case false: if (!digitalRead(pin))set(true); break; case true: if (digitalRead(pin))set(false); if (millis() - past >= 300)set(false); break; } } }; Cl_btn Btn(/*пин*/A0); //------------------------------------------- const byte st1 = 0; const byte st0 = 1; const byte st2 = 2; class Cl_joystic { protected: byte pin; byte state; unsigned long past; void set(byte s) { state = s; past = millis(); switch (s) { case st0: break; case st1: Do1(); break; case st2: Do2(); break; } } public: Cl_joystic(byte p): pin(p) {} pDo Do1 = [] {}; pDo Do2 = [] {}; void init() { set(st0); } void run() { if (millis() - past >= 100) { int tmp = analogRead(pin); switch (state) { case st1: if (tmp > 450)set(st0); if (millis() - past >= 300)set(st0); break; case st0: if (tmp < 400)set(st1); else if (tmp > 600)set(st2); break; case st2: if (tmp < 550)set(st0); if (millis() - past >= 300)set(st0); break; } } } }; Cl_joystic JoyLR(/*пин*/A1); Cl_joystic JoyUD(/*пин*/A2); // -------------таймеры------------------------------------------------ typedef struct { byte hour; byte minute; byte second; } timer_t; timer_t Timer[] = { {1, 10, 11},// 1-й таймер {2, 20, 22},// 2-й таймер {3, 30, 33},// 3-й таймер {4, 40, 44},// 4-й таймер {5, 50, 55} // 5-й таймер }; //---------------lcd--------------------------------------------- #include <Wire.h> #include <LiquidCrystal_I2C.h> LiquidCrystal_I2C lcd(0x27, 16, 2); //--------------- меню--------------------------------------------- template <typename T> inline Print & operator << (Print &s, T n) { s.print(n); return s; } const byte sMain = 0;// главный экран const byte ss1 = 1;// 1-экран const byte ss1e1 = 2;// редактирование 1 const byte ss1e2 = 3;// редактирование 2 const byte ss1e3 = 4;// редактирование 3 const byte ss2 = 5;// 2-экран const byte ss2e1 = 6;// редактирование 1 const byte ss2e2 = 7;// редактирование 2 const byte ss2e3 = 8;// редактирование 3 const byte ss3 = 9;// 3-экран const byte ss3e1 = 10;// редактирование 1 const byte ss3e2 = 11;// редактирование 2 const byte ss3e3 = 12;// редактирование 3 const byte ss4 = 13;// 4-экран const byte ss4e1 = 14;// редактирование 1 const byte ss4e2 = 15;// редактирование 2 const byte ss4e3 = 16;// редактирование 3 const byte ss5 = 17;// 5-экран const byte ss5e1 = 18;// редактирование 1 const byte ss5e2 = 19;// редактирование 2 const byte ss5e3 = 20;// редактирование 3 byte pos; unsigned long past; void setPos(byte p) { pos = p; past = millis(); lcd.clear(); switch (p) { case sMain:// главный экран { unsigned long now = millis() / 1000; int hour = now / 60 / 60 % 24 ; int minute = now / 60 % 60; int second = now % 60; lcd << F("Time:") << hour << F(":") << minute << F(":") << second; } Btn.Do = [] {}; JoyUD.Do1 = [] { }; JoyUD.Do2 = [] {setPos(ss1); }; break; case ss1: // 1-экран { lcd << F("Timer1:") << Timer[0].hour << F(":") << Timer[0].minute << F(":") << Timer[0].second; } Btn.Do = [] {setPos(ss1e1); }; JoyUD.Do1 = [] {setPos(sMain); }; JoyUD.Do2 = [] {setPos(ss2); }; break; case ss1e1:// редактирование 1 { lcd << F("Timer1:") << Timer[0].hour << F(":") << Timer[0].minute << F(">") << Timer[0].second; } Btn.Do = [] {setPos(ss1e2);}; JoyUD.Do1 = [] { if (Timer[0].second < 59)Timer[0].second++; setPos(ss1e1); }; JoyUD.Do2 = [] { if (Timer[0].second > 0)Timer[0].second--; setPos(ss1e1); }; break; case ss1e2:// редактирование 2 { lcd << F("Timer1:") << Timer[0].hour << F(">") << Timer[0].minute << F(":") << Timer[0].second; } Btn.Do = [] {setPos(ss1e3);}; JoyUD.Do1 = [] { if (Timer[0].minute < 59)Timer[0].minute++; setPos(ss1e2); }; JoyUD.Do2 = [] { if (Timer[0].minute > 0)Timer[0].minute--; setPos(ss1e2); }; break; case ss1e3:// редактирование 3 { lcd << F("Timer1>") << Timer[0].hour << F(":") << Timer[0].minute << F(":") << Timer[0].second; } Btn.Do = [] {setPos(ss1);}; JoyUD.Do1 = [] { if (Timer[0].hour < 23)Timer[0].hour++; setPos(ss1e3); }; JoyUD.Do2 = [] { if (Timer[0].hour > 0)Timer[0].hour--; setPos(ss1e3); }; break; case ss2: // 2-экран { lcd << F("Timer2:") << Timer[1].hour << F(":") << Timer[1].minute << F(":") << Timer[1].second; } Btn.Do = [] {setPos(ss2e1); }; JoyUD.Do1 = [] {setPos(ss1); }; JoyUD.Do2 = [] {setPos(ss3); }; break; case ss2e1: { lcd << F("Timer2:") << Timer[1].hour << F(":") << Timer[1].minute << F(">") << Timer[1].second; } Btn.Do = [] {setPos(ss2e2);}; JoyUD.Do1 = [] { if (Timer[1].second < 59)Timer[1].second++; setPos(ss2e1); }; JoyUD.Do2 = [] { if (Timer[1].second > 0)Timer[1].second--; setPos(ss2e1); }; break; case ss2e2: { lcd << F("Timer2:") << Timer[1].hour << F(">") << Timer[1].minute << F(":") << Timer[1].second; } Btn.Do = [] {setPos(ss2e3);}; JoyUD.Do1 = [] { if (Timer[1].minute < 59)Timer[1].minute++; setPos(ss2e2); }; JoyUD.Do2 = [] { if (Timer[1].minute > 0)Timer[1].minute--; setPos(ss2e2); }; break; case ss2e3: { lcd << F("Timer2>") << Timer[1].hour << F(":") << Timer[1].minute << F(":") << Timer[1].second; } Btn.Do = [] {setPos(ss2);}; JoyUD.Do1 = [] { if (Timer[1].hour < 23)Timer[1].hour++; setPos(ss2e3); }; JoyUD.Do2 = [] { if (Timer[1].hour > 0)Timer[1].hour--; setPos(ss2e3); }; break; case ss3: // 3-экран { lcd << F("Timer3:") << Timer[2].hour << F(":") << Timer[2].minute << F(":") << Timer[2].second; } Btn.Do = [] {setPos(ss3e1); }; JoyUD.Do1 = [] {setPos(ss2); }; JoyUD.Do2 = [] {setPos(ss4); }; break; case ss3e1: { lcd << F("Timer3:") << Timer[2].hour << F(":") << Timer[2].minute << F(">") << Timer[2].second; } Btn.Do = [] {setPos(ss3e2);}; JoyUD.Do1 = [] { if (Timer[2].second < 59)Timer[2].second++; setPos(ss3e1); }; JoyUD.Do2 = [] { if (Timer[2].second > 0)Timer[2].second--; setPos(ss3e1); }; break; case ss3e2: { lcd << F("Timer3:") << Timer[2].hour << F(">") << Timer[2].minute << F(":") << Timer[2].second; } Btn.Do = [] {setPos(ss3e3);}; JoyUD.Do1 = [] { if (Timer[2].minute < 59)Timer[2].minute++; setPos(ss3e2); }; JoyUD.Do2 = [] { if (Timer[2].minute > 0)Timer[2].minute--; setPos(ss3e2); }; break; break; case ss3e3: { lcd << F("Timer3>") << Timer[2].hour << F(":") << Timer[2].minute << F(":") << Timer[2].second; } Btn.Do = [] {setPos(ss3);}; JoyUD.Do1 = [] { if (Timer[2].hour < 23)Timer[2].hour++; setPos(ss3e3); }; JoyUD.Do2 = [] { if (Timer[2].hour > 0)Timer[2].hour--; setPos(ss3e3); }; break; case ss4: // 4-экран { lcd << F("Timer4:") << Timer[3].hour << F(":") << Timer[3].minute << F(":") << Timer[3].second; } Btn.Do = [] {setPos(ss4e1); }; JoyUD.Do1 = [] {setPos(ss3); }; JoyUD.Do2 = [] {setPos(ss5); }; break; case ss4e1: { lcd << F("Timer4:") << Timer[3].hour << F(":") << Timer[3].minute << F(">") << Timer[3].second; } Btn.Do = [] {setPos(ss4e2);}; JoyUD.Do1 = [] { if (Timer[3].second < 59)Timer[3].second++; setPos(ss4e1); }; JoyUD.Do2 = [] { if (Timer[3].second > 0)Timer[3].second--; setPos(ss4e1); }; break; case ss4e2: { lcd << F("Timer4:") << Timer[3].hour << F(">") << Timer[3].minute << F(":") << Timer[3].second; } Btn.Do = [] {setPos(ss4e3);}; JoyUD.Do1 = [] { if (Timer[3].minute < 59)Timer[3].minute++; setPos(ss4e2); }; JoyUD.Do2 = [] { if (Timer[3].minute > 0)Timer[3].minute--; setPos(ss4e2); }; break; case ss4e3: { lcd << F("Timer4>") << Timer[3].hour << F(":") << Timer[3].minute << F(":") << Timer[3].second; } Btn.Do = [] {setPos(ss4);}; JoyUD.Do1 = [] { if (Timer[3].hour < 23)Timer[3].hour++; setPos(ss4e3); }; JoyUD.Do2 = [] { if (Timer[3].hour > 0)Timer[3].hour--; setPos(ss4e3); }; break; case ss5: // 5-экран { lcd << F("Timer5:") << Timer[4].hour << F(":") << Timer[4].minute << F(":") << Timer[4].second; } Btn.Do = [] {setPos(ss5e1); }; JoyUD.Do1 = [] {setPos(ss4);}; JoyUD.Do2 = [] {}; break; case ss5e1: { lcd << F("Timer5:") << Timer[4].hour << F(":") << Timer[4].minute << F(">") << Timer[4].second; } Btn.Do = [] {setPos(ss5e2);}; JoyUD.Do1 = [] { if (Timer[4].second < 59)Timer[4].second++; setPos(ss5e1); }; JoyUD.Do2 = [] { if (Timer[4].second > 0)Timer[4].second--; setPos(ss5e1); }; break; case ss5e2: { lcd << F("Timer5:") << Timer[4].hour << F(">") << Timer[4].minute << F(":") << Timer[4].second; } Btn.Do = [] {setPos(ss5e3);}; JoyUD.Do1 = [] { if (Timer[4].minute < 59)Timer[4].minute++; setPos(ss5e2); }; JoyUD.Do2 = [] { if (Timer[4].minute > 0)Timer[4].minute--; setPos(ss5e2); }; break; case ss5e3: { lcd << F("Timer5>") << Timer[4].hour << F(":") << Timer[4].minute << F(":") << Timer[4].second; } Btn.Do = [] {setPos(ss5);}; JoyUD.Do1 = [] { if (Timer[4].hour < 23)Timer[4].hour++; setPos(ss5e3); }; JoyUD.Do2 = [] { if (Timer[4].hour > 0)Timer[4].hour--; setPos(ss5e3); }; break; } } void menuInit() { lcd.begin(16, 2); setPos(sMain); } void menuRun() { if (pos != sMain && millis() - past >= 10000)setPos(sMain); if (pos == sMain && millis() - past >= 1000)setPos(sMain); } //---------------------------------- void setup() { lcd.init(); Btn.init(); JoyLR.init(); JoyUD.init(); menuInit(); JoyLR.Do1 = [] {lcd.backlight();}; JoyLR.Do2 = [] {lcd.noBacklight();}; } void loop() { Btn.run(); JoyLR.run(); JoyUD.run(); menuRun(); } /**/Немного громоздко.Но похоже надо еще думать как упростить.
//---кнопкa----------------------------- typedef void (*pDo)(); class Cl_btn { protected: byte pin; bool state; unsigned long past; void set(bool s) { state = s; past = millis(); switch (s) { case false: break; case true: Do(); break; } } public: Cl_btn(byte p): pin(p) {} pDo Do = [] {}; void init() { pinMode(pin, INPUT_PULLUP); set(false); } void run() { if (millis() - past >= 100) switch (state) { case false: if (!digitalRead(pin))set(true); break; case true: if (digitalRead(pin))set(false); if (millis() - past >= 300)set(false); break; } } }; Cl_btn Btn(/*пин*/A0); //------------------------------------------- const byte st1 = 0; const byte st0 = 1; const byte st2 = 2; class Cl_joystic { protected: byte pin; byte state; unsigned long past; void set(byte s) { state = s; past = millis(); switch (s) { case st0: break; case st1: Do1(); break; case st2: Do2(); break; } } public: Cl_joystic(byte p): pin(p) {} pDo Do1 = [] {}; pDo Do2 = [] {}; void init() { set(st0); } void run() { if (millis() - past >= 100) { int tmp = analogRead(pin); switch (state) { case st1: if (tmp > 450)set(st0); if (millis() - past >= 300)set(st0); break; case st0: if (tmp < 400)set(st1); else if (tmp > 600)set(st2); break; case st2: if (tmp < 550)set(st0); if (millis() - past >= 300)set(st0); break; } } } }; Cl_joystic JoyLR(/*пин*/A1); Cl_joystic JoyUD(/*пин*/A2); // -------------таймеры------------------------------------------------ typedef struct { byte hour; byte minute; byte second; } timer_t; const byte numTimer = 5; timer_t EEMEM adr[numTimer]; // первичные настройки в EEPROM void saveZeroSettings() { timer_t data[numTimer] = { // начальные настройки {1, 10, 11},// 1-й таймер {2, 20, 22},// 2-й таймер {3, 30, 33},// 3-й таймер {4, 40, 44},// 4-й таймер {5, 50, 55} // 5-й таймер }; for (int i = 0; i < numTimer; ++i) { eeprom_write_byte(&adr[i].hour , data[i].hour); eeprom_write_byte(&adr[i].minute, data[i].minute); eeprom_write_byte(&adr[i].second, data[i].second); } } //---------------lcd--------------------------------------------- #include <Wire.h> #include <LiquidCrystal_I2C.h> LiquidCrystal_I2C lcd(0x27, 16, 2); //--------------- меню--------------------------------------------- byte var; // некая вспомогательная переменная template <typename T> inline Print & operator << (Print &s, T n) { s.print(n); return s; } const byte sMain = 0;// главный экран const byte ss1 = 1;// 1-экран const byte ss1e1 = 2;// редактирование 1 const byte ss1e2 = 3;// редактирование 2 const byte ss1e3 = 4;// редактирование 3 const byte ss2 = 5;// 2-экран const byte ss2e1 = 6;// редактирование 1 const byte ss2e2 = 7;// редактирование 2 const byte ss2e3 = 8;// редактирование 3 const byte ss3 = 9;// 3-экран const byte ss3e1 = 10;// редактирование 1 const byte ss3e2 = 11;// редактирование 2 const byte ss3e3 = 12;// редактирование 3 const byte ss4 = 13;// 4-экран const byte ss4e1 = 14;// редактирование 1 const byte ss4e2 = 15;// редактирование 2 const byte ss4e3 = 16;// редактирование 3 const byte ss5 = 17;// 5-экран const byte ss5e1 = 18;// редактирование 1 const byte ss5e2 = 19;// редактирование 2 const byte ss5e3 = 20;// редактирование 3 byte pos; unsigned long past; void setPos(byte p) { pos = p; past = millis(); lcd.clear(); switch (p) { case sMain:// главный экран { unsigned long now = millis() / 1000; int hour = now / 60 / 60 % 24 ; int minute = now / 60 % 60; int second = now % 60; lcd << F("Time:") << hour << F(":") << minute << F(":") << second; } Btn.Do = [] {}; JoyUD.Do1 = [] { }; JoyUD.Do2 = [] {setPos(ss1); }; break; case ss1: // 1-экран { lcd << F("Timer1:") << eeprom_read_byte(&adr[0].hour) << F(":") << eeprom_read_byte(&adr[0].minute) << F(":") << eeprom_read_byte(&adr[0].second); } Btn.Do = [] { var = eeprom_read_byte(&adr[0].second); setPos(ss1e1); }; JoyUD.Do1 = [] {setPos(sMain); }; JoyUD.Do2 = [] {setPos(ss2); }; break; case ss1e1:// редактирование секунд { lcd << F("Timer1:") << eeprom_read_byte(&adr[0].hour) << F(":") << eeprom_read_byte(&adr[0].minute) << F(">") << var; } Btn.Do = [] { eeprom_write_byte(&adr[0].second, var); var = eeprom_read_byte(&adr[0].minute); setPos(ss1e2); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss1e1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss1e1); }; break; case ss1e2:// редактирование минут { lcd << F("Timer1:") << eeprom_read_byte(&adr[0].hour) << F(">") << var << F(":") << eeprom_read_byte(&adr[0].second); } Btn.Do = [] { eeprom_write_byte(&adr[0].minute, var); var = eeprom_read_byte(&adr[0].hour); setPos(ss1e3); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss1e2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss1e2); }; break; case ss1e3:// редактирование часов { lcd << F("Timer1>") << var << F(":") << eeprom_read_byte(&adr[0].minute) << F(":") << eeprom_read_byte(&adr[0].second); } Btn.Do = [] { eeprom_write_byte(&adr[0].hour, var); setPos(ss1); }; JoyUD.Do1 = [] { if (var < 23)var++; setPos(ss1e3); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss1e3); }; break; case ss2: // 2-экран { lcd << F("Timer2:") << eeprom_read_byte(&adr[1].hour) << F(":") << eeprom_read_byte(&adr[1].minute) << F(":") << eeprom_read_byte(&adr[1].second); } Btn.Do = [] { var = eeprom_read_byte(&adr[1].second); setPos(ss2e1); }; JoyUD.Do1 = [] {setPos(ss1); }; JoyUD.Do2 = [] {setPos(ss3); }; break; case ss2e1: { lcd << F("Timer2:") << eeprom_read_byte(&adr[1].hour) << F(":") << eeprom_read_byte(&adr[1].minute) << F(">") << var; } Btn.Do = [] { eeprom_write_byte(&adr[1].second, var); var = eeprom_read_byte(&adr[1].minute); setPos(ss2e2); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss2e1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss2e1); }; break; case ss2e2: { lcd << F("Timer2:") << eeprom_read_byte(&adr[1].hour) << F(">") << var << F(":") << eeprom_read_byte(&adr[1].second); } Btn.Do = [] { eeprom_write_byte(&adr[1].minute, var); var = eeprom_read_byte(&adr[1].hour); setPos(ss2e3); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss2e2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss2e2); }; break; case ss2e3: { lcd << F("Timer2>") << var << F(":") << eeprom_read_byte(&adr[1].minute) << F(":") << eeprom_read_byte(&adr[1].second); } Btn.Do = [] { eeprom_write_byte(&adr[1].hour, var); setPos(ss2); }; JoyUD.Do1 = [] { if (var < 23)var++; setPos(ss2e3); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss2e3); }; break; case ss3: // 3-экран { lcd << F("Timer3:") << eeprom_read_byte(&adr[2].hour) << F(":") << eeprom_read_byte(&adr[2].minute) << F(":") << eeprom_read_byte(&adr[2].second); } Btn.Do = [] { var = eeprom_read_byte(&adr[2].second); setPos(ss3e1); }; JoyUD.Do1 = [] {setPos(ss2); }; JoyUD.Do2 = [] {setPos(ss4); }; break; case ss3e1:// редакт секунд { lcd << F("Timer3:") << eeprom_read_byte(&adr[2].hour) << F(":") << eeprom_read_byte(&adr[2].minute) << F(">") << var; } Btn.Do = [] { eeprom_write_byte(&adr[2].second, var); var = eeprom_read_byte(&adr[2].minute); setPos(ss3e2); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss3e1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss3e1); }; break; case ss3e2:// редакт минут { lcd << F("Timer3:") << eeprom_read_byte(&adr[2].hour) << F(">") << var << F(":") << eeprom_read_byte(&adr[2].second); } Btn.Do = [] { eeprom_write_byte(&adr[2].minute, var); var = eeprom_read_byte(&adr[2].hour); setPos(ss3e3); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss3e2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss3e2); }; break; case ss3e3:// редакт часов { lcd << F("Timer3>") << var << F(":") << eeprom_read_byte(&adr[2].minute) << F(":") << eeprom_read_byte(&adr[2].second); } Btn.Do = [] { eeprom_write_byte(&adr[2].hour, var); setPos(ss3); }; JoyUD.Do1 = [] { if (var < 23)var++; setPos(ss3e3); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss3e3); }; break; case ss4: // 4-экран { lcd << F("Timer4:") << eeprom_read_byte(&adr[3].hour) << F(":") << eeprom_read_byte(&adr[3].minute) << F(":") << eeprom_read_byte(&adr[3].second); } Btn.Do = [] { var = eeprom_read_byte(&adr[3].second); setPos(ss4e1); }; JoyUD.Do1 = [] {setPos(ss3); }; JoyUD.Do2 = [] {setPos(ss5); }; break; case ss4e1: { lcd << F("Timer4:") << eeprom_read_byte(&adr[3].hour) << F(":") << eeprom_read_byte(&adr[3].minute) << F(">") << var; } Btn.Do = [] { eeprom_write_byte(&adr[3].second, var); var = eeprom_read_byte(&adr[3].minute); setPos(ss4e2); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss4e1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss4e1); }; break; case ss4e2: { lcd << F("Timer4:") << eeprom_read_byte(&adr[3].hour) << F(">") << var << F(":") << eeprom_read_byte(&adr[3].second); } Btn.Do = [] { eeprom_write_byte(&adr[3].minute, var); var = eeprom_read_byte(&adr[3].hour); setPos(ss4e3); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss4e2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss4e2); }; break; case ss4e3: { lcd << F("Timer4>") << var << F(":") << eeprom_read_byte(&adr[3].minute) << F(":") << eeprom_read_byte(&adr[3].second); } Btn.Do = [] { eeprom_write_byte(&adr[3].hour, var); setPos(ss4); }; JoyUD.Do1 = [] { if (var < 23)var++; setPos(ss4e3); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss4e3); }; break; case ss5: // 5-экран { lcd << F("Timer5:") << eeprom_read_byte(&adr[4].hour) << F(":") << eeprom_read_byte(&adr[4].minute) << F(":") << eeprom_read_byte(&adr[4].second); } Btn.Do = [] { var = eeprom_read_byte(&adr[4].second); setPos(ss5e1); }; JoyUD.Do1 = [] { setPos(ss4); }; JoyUD.Do2 = [] {}; break; case ss5e1: { lcd << F("Timer5:") << eeprom_read_byte(&adr[4].hour) << F(":") << eeprom_read_byte(&adr[4].minute) << F(">") << var; } Btn.Do = [] { eeprom_write_byte(&adr[4].second, var); var = eeprom_read_byte(&adr[4].minute); setPos(ss5e2); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss5e1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss5e1); }; break; case ss5e2: { lcd << F("Timer5:") << eeprom_read_byte(&adr[4].hour) << F(">") << var << F(":") << eeprom_read_byte(&adr[4].second); } Btn.Do = [] { eeprom_write_byte(&adr[4].minute, var); var = eeprom_read_byte(&adr[4].hour); setPos(ss5e3); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss5e2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss5e2); }; break; case ss5e3: { lcd << F("Timer5>") << var << F(":") << eeprom_read_byte(&adr[4].minute) << F(":") << eeprom_read_byte(&adr[4].second); } Btn.Do = [] { eeprom_write_byte(&adr[4].hour, var); setPos(ss5); }; JoyUD.Do1 = [] { if (var < 23)var++; setPos(ss5e3); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss5e3); }; break; } } void menuInit() { lcd.begin(16, 2); setPos(sMain); } void menuRun() { if (pos != sMain && millis() - past >= 10000)setPos(sMain); if (pos == sMain && millis() - past >= 1000)setPos(sMain); } //---------------------------------- void setup() { saveZeroSettings(); lcd.init(); Btn.init(); JoyLR.init(); JoyUD.init(); menuInit(); JoyLR.Do1 = [] {lcd.backlight();}; JoyLR.Do2 = [] {lcd.noBacklight();}; } void loop() { Btn.run(); JoyLR.run(); JoyUD.run(); menuRun(); } /**/Тоже самое но чуть попроще в чтении скетча
/**/ // -------------таймеры------------------------------------------------ typedef struct { byte hour; byte minute; byte second; } timer_t; const byte numTimer = 5; timer_t EEMEM adr[numTimer]; // первичные настройки в EEPROM void saveZeroSettings() { timer_t data[numTimer] = { // начальные настройки {1, 10, 11},// 1-й таймер {2, 20, 22},// 2-й таймер {3, 30, 33},// 3-й таймер {4, 40, 44},// 4-й таймер {5, 50, 55} // 5-й таймер }; for (int i = 0; i < numTimer; ++i) { eeprom_write_byte(&adr[i].hour , data[i].hour); eeprom_write_byte(&adr[i].minute, data[i].minute); eeprom_write_byte(&adr[i].second, data[i].second); } } class Cl_Timer { private: timer_t * adr; public: Cl_Timer(timer_t * a): adr(a) {} void init() {} void run() {} byte hour() { return eeprom_read_byte(&(adr->hour)); } byte minute() { return eeprom_read_byte(&(adr->minute)); } byte second() { return eeprom_read_byte(&(adr->second)); } void writeHour(byte data) { eeprom_write_byte(&(adr->hour), data); } void writeMinute(byte data) { eeprom_write_byte(&(adr->minute), data); } void writeSecond(byte data) { eeprom_write_byte(&(adr->second), data); } }; Cl_Timer Timer[numTimer] = { Cl_Timer(&adr[0]), // 1-й таймер Cl_Timer(&adr[1]), // 2-й таймер Cl_Timer(&adr[2]), // 3-й таймер Cl_Timer(&adr[3]), // 4-й таймер Cl_Timer(&adr[4]) // 5-й таймер }; //---кнопкa----------------------------- typedef void (*pDo)(); class Cl_btn { protected: byte pin; bool state; unsigned long past; void set(bool s) { state = s; past = millis(); switch (s) { case false: break; case true: Do(); break; } } public: Cl_btn(byte p): pin(p) {} pDo Do = [] {}; void init() { pinMode(pin, INPUT_PULLUP); set(false); } void run() { if (millis() - past >= 100) switch (state) { case false: if (!digitalRead(pin))set(true); break; case true: if (digitalRead(pin))set(false); if (millis() - past >= 300)set(false); break; } } }; Cl_btn Btn(/*пин*/A0); //------------------------------------------- const byte st1 = 0; const byte st0 = 1; const byte st2 = 2; class Cl_joystic { protected: byte pin; byte state; unsigned long past; void set(byte s) { state = s; past = millis(); switch (s) { case st0: break; case st1: Do1(); break; case st2: Do2(); break; } } public: Cl_joystic(byte p): pin(p) {} pDo Do1 = [] {}; pDo Do2 = [] {}; void init() { set(st0); } void run() { if (millis() - past >= 100) { int tmp = analogRead(pin); switch (state) { case st1: if (tmp > 450)set(st0); if (millis() - past >= 300)set(st0); break; case st0: if (tmp < 400)set(st1); else if (tmp > 600)set(st2); break; case st2: if (tmp < 550)set(st0); if (millis() - past >= 300)set(st0); break; } } } }; Cl_joystic JoyLR(/*пин*/A1); Cl_joystic JoyUD(/*пин*/A2); //---------------lcd--------------------------------------------- #include <Wire.h> #include <LiquidCrystal_I2C.h> LiquidCrystal_I2C lcd(0x27, 16, 2); //--------------- меню--------------------------------------------- byte var; // некая вспомогательная переменная template <typename T> inline Print & operator << (Print &s, T n) { s.print(n); return s; } const byte sMain = 0;// главный экран const byte ss1 = 1;// 1-экран const byte ss1e1 = 2;// редактирование 1 const byte ss1e2 = 3;// редактирование 2 const byte ss1e3 = 4;// редактирование 3 const byte ss2 = 5;// 2-экран const byte ss2e1 = 6;// редактирование 1 const byte ss2e2 = 7;// редактирование 2 const byte ss2e3 = 8;// редактирование 3 const byte ss3 = 9;// 3-экран const byte ss3e1 = 10;// редактирование 1 const byte ss3e2 = 11;// редактирование 2 const byte ss3e3 = 12;// редактирование 3 const byte ss4 = 13;// 4-экран const byte ss4e1 = 14;// редактирование 1 const byte ss4e2 = 15;// редактирование 2 const byte ss4e3 = 16;// редактирование 3 const byte ss5 = 17;// 5-экран const byte ss5e1 = 18;// редактирование 1 const byte ss5e2 = 19;// редактирование 2 const byte ss5e3 = 20;// редактирование 3 byte pos; unsigned long past; void setPos(byte p) { pos = p; past = millis(); lcd.clear(); switch (p) { case sMain:// главный экран { unsigned long now = millis() / 1000; int hour = now / 60 / 60 % 24 ; int minute = now / 60 % 60; int second = now % 60; lcd << F("Time:") << hour << F(":") << minute << F(":") << second; } Btn.Do = [] {}; JoyUD.Do1 = [] { }; JoyUD.Do2 = [] {setPos(ss1); }; break; case ss1: // 1-экран { lcd << F("Timer1:") << Timer[0].hour() << F(":") << Timer[0].minute() << F(":") << Timer[0].second(); } Btn.Do = [] { var = Timer[0].second(); setPos(ss1e1); }; JoyUD.Do1 = [] {setPos(sMain); }; JoyUD.Do2 = [] {setPos(ss2); }; break; case ss1e1:// редактирование секунд { lcd << F("Timer1:") << Timer[0].hour() << F(":") << Timer[0].minute() << F(">") << var; } Btn.Do = [] { Timer[0].writeSecond(var); var = Timer[0].minute(); setPos(ss1e2); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss1e1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss1e1); }; break; case ss1e2:// редактирование минут { lcd << F("Timer1:") << Timer[0].hour() << F(">") << var << F(":") << Timer[0].second(); } Btn.Do = [] { Timer[0].writeMinute(var); var = Timer[0].hour(); setPos(ss1e3); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss1e2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss1e2); }; break; case ss1e3:// редактирование часов { lcd << F("Timer1>") << var << F(":") << Timer[0].minute() << F(":") << Timer[0].second(); } Btn.Do = [] { Timer[0].writeHour(var); setPos(ss1); }; JoyUD.Do1 = [] { if (var < 23)var++; setPos(ss1e3); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss1e3); }; break; case ss2: // 2-экран { lcd << F("Timer2:") << Timer[1].hour() << F(":") << Timer[1].minute() << F(":") << Timer[1].second(); } Btn.Do = [] { var = Timer[1].second(); setPos(ss2e1); }; JoyUD.Do1 = [] {setPos(ss1); }; JoyUD.Do2 = [] {setPos(ss3); }; break; case ss2e1: { lcd << F("Timer2:") << Timer[1].hour() << F(":") << Timer[1].minute() << F(">") << var; } Btn.Do = [] { Timer[1].writeSecond(var); var = Timer[1].minute(); setPos(ss2e2); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss2e1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss2e1); }; break; case ss2e2: { lcd << F("Timer2:") << Timer[1].hour() << F(">") << var << F(":") << Timer[1].second(); } Btn.Do = [] { Timer[1].writeMinute(var); var = Timer[1].hour(); setPos(ss2e3); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss2e2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss2e2); }; break; case ss2e3: { lcd << F("Timer2>") << var << F(":") << Timer[1].minute() << F(":") << Timer[1].second(); } Btn.Do = [] { Timer[1].writeHour(var); setPos(ss2); }; JoyUD.Do1 = [] { if (var < 23)var++; setPos(ss2e3); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss2e3); }; break; case ss3: // 3-экран { lcd << F("Timer3:") << Timer[2].hour() << F(":") << Timer[2].minute() << F(":") << Timer[2].second(); } Btn.Do = [] { var = Timer[2].second(); setPos(ss3e1); }; JoyUD.Do1 = [] {setPos(ss2); }; JoyUD.Do2 = [] {setPos(ss4); }; break; case ss3e1:// редакт секунд { lcd << F("Timer3:") << Timer[2].hour() << F(":") << Timer[2].minute() << F(">") << var; } Btn.Do = [] { Timer[2].writeSecond(var); var = Timer[2].minute(); setPos(ss3e2); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss3e1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss3e1); }; break; case ss3e2:// редакт минут { lcd << F("Timer3:") << Timer[2].hour() << F(">") << var << F(":") << Timer[2].second(); } Btn.Do = [] { Timer[2].writeMinute(var); var = Timer[2].hour(); setPos(ss3e3); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss3e2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss3e2); }; break; case ss3e3:// редакт часов { lcd << F("Timer3>") << var << F(":") << Timer[2].minute() << F(":") << Timer[2].second(); } Btn.Do = [] { Timer[2].writeHour(var); setPos(ss3); }; JoyUD.Do1 = [] { if (var < 23)var++; setPos(ss3e3); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss3e3); }; break; case ss4: // 4-экран { lcd << F("Timer4:") << Timer[3].hour() << F(":") << Timer[3].minute() << F(":") << Timer[3].second(); } Btn.Do = [] { var = Timer[3].second(); setPos(ss4e1); }; JoyUD.Do1 = [] {setPos(ss3); }; JoyUD.Do2 = [] {setPos(ss5); }; break; case ss4e1: { lcd << F("Timer4:") << Timer[3].hour() << F(":") << Timer[3].minute() << F(">") << var; } Btn.Do = [] { Timer[3].writeSecond(var); var = Timer[3].minute(); setPos(ss4e2); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss4e1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss4e1); }; break; case ss4e2: { lcd << F("Timer4:") << Timer[3].hour() << F(">") << var << F(":") << Timer[3].second(); } Btn.Do = [] { Timer[3].writeMinute(var); var = Timer[3].hour(); setPos(ss4e3); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss4e2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss4e2); }; break; case ss4e3: { lcd << F("Timer4>") << var << F(":") << Timer[3].minute() << F(":") << Timer[3].second(); } Btn.Do = [] { Timer[3].writeHour(var); setPos(ss4); }; JoyUD.Do1 = [] { if (var < 23)var++; setPos(ss4e3); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss4e3); }; break; case ss5: // 5-экран { lcd << F("Timer5:") << Timer[4].hour() << F(":") << Timer[4].minute() << F(":") << Timer[4].second(); } Btn.Do = [] { var = Timer[4].second(); setPos(ss5e1); }; JoyUD.Do1 = [] { setPos(ss4); }; JoyUD.Do2 = [] {}; break; case ss5e1: { lcd << F("Timer5:") << Timer[4].hour() << F(":") << Timer[4].minute() << F(">") << var; } Btn.Do = [] { Timer[4].writeSecond(var); var = Timer[4].minute(); setPos(ss5e2); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss5e1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss5e1); }; break; case ss5e2: { lcd << F("Timer5:") << Timer[4].hour() << F(">") << var << F(":") << Timer[4].second(); } Btn.Do = [] { Timer[4].writeMinute(var); var = Timer[4].hour(); setPos(ss5e3); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss5e2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss5e2); }; break; case ss5e3: { lcd << F("Timer5>") << var << F(":") << Timer[4].minute() << F(":") << Timer[4].second(); } Btn.Do = [] { Timer[4].writeHour(var); setPos(ss5); }; JoyUD.Do1 = [] { if (var < 23)var++; setPos(ss5e3); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss5e3); }; break; } } void menuInit() { lcd.begin(16, 2); setPos(sMain); } void menuRun() { if (pos != sMain && millis() - past >= 10000)setPos(sMain); if (pos == sMain && millis() - past >= 1000)setPos(sMain); } //---------------------------------- void setup() { saveZeroSettings(); for (int i = 0; i < numTimer; i++) Timer[i].init(); lcd.init(); Btn.init(); JoyLR.init(); JoyUD.init(); menuInit(); JoyLR.Do1 = [] {lcd.backlight();}; JoyLR.Do2 = [] {lcd.noBacklight();}; } void loop() { for (int i = 0; i < numTimer; i++) Timer[i].run(); Btn.run(); JoyLR.run(); JoyUD.run(); menuRun(); } /**//**/ unsigned long now ;// количество секунд прошедшее после вкл //---------------lcd--------------------------------------------- template <typename T> inline Print & operator << (Print &s, T n) { s.print(n); return s; } #include <Wire.h> #include <LiquidCrystal_I2C.h> LiquidCrystal_I2C lcd(0x27, 16, 2); // -------------таймеры------------------------------------------------ typedef struct { byte hour; byte minute; byte second; } timer_t; const byte numTimer = 5; timer_t EEMEM adr[numTimer]; // первичные настройки в EEPROM void saveZeroSettings() { timer_t data[numTimer] = { // начальные настройки {0, 0, 30},// 1-й таймер {0, 1, 00},// 2-й таймер {0, 1, 30},// 3-й таймер {0, 2, 00},// 4-й таймер {0, 2, 30} // 5-й таймер }; for (int i = 0; i < numTimer; ++i) { eeprom_write_byte(&adr[i].hour , data[i].hour); eeprom_write_byte(&adr[i].minute, data[i].minute); eeprom_write_byte(&adr[i].second, data[i].second); } } /*состояния таймера*/ const byte sOFF = 0; const byte sON = 1; const byte sEND = 2; class Cl_Timer { private: timer_t * adr; byte stat;// состояние unsigned long past; void setStat(byte s) { stat = s; past = millis(); switch (s) { case sOFF: break; case sON: break; case sEND: break; } } public: Cl_Timer(timer_t * a): adr(a) {} void init() { setStat(sOFF); } void run() { if (millis() - past >= 100) { switch (stat) { case sOFF: if (now >= ((unsigned long)hour() * 24 + minute()) * 60 + second())setStat(sON); break; case sON: setStat(sON); break; case sEND: setStat(sEND); break; } } } void state() { switch (stat) { case sOFF: lcd << F("OFF"); break; case sON: lcd << F("ON "); break; case sEND: lcd << F("END"); break; } } byte hour() { return eeprom_read_byte(&(adr->hour)); } byte minute() { return eeprom_read_byte(&(adr->minute)); } byte second() { return eeprom_read_byte(&(adr->second)); } void writeHour(byte data) { eeprom_write_byte(&(adr->hour), data); } void writeMinute(byte data) { eeprom_write_byte(&(adr->minute), data); } void writeSecond(byte data) { eeprom_write_byte(&(adr->second), data); } }; Cl_Timer Timer[numTimer] = { Cl_Timer(&adr[0]), // 1-й таймер Cl_Timer(&adr[1]), // 2-й таймер Cl_Timer(&adr[2]), // 3-й таймер Cl_Timer(&adr[3]), // 4-й таймер Cl_Timer(&adr[4]) // 5-й таймер }; //---кнопкa----------------------------- typedef void (*pDo)(); class Cl_btn { protected: byte pin; bool state; unsigned long past; void set(bool s) { state = s; past = millis(); switch (s) { case false: break; case true: Do(); break; } } public: Cl_btn(byte p): pin(p) {} pDo Do = [] {}; void init() { pinMode(pin, INPUT_PULLUP); set(false); } void run() { if (millis() - past >= 100) switch (state) { case false: if (!digitalRead(pin))set(true); break; case true: if (digitalRead(pin))set(false); if (millis() - past >= 300)set(false); break; } } }; Cl_btn Btn(/*пин*/A0); //------------------------------------------- const byte st1 = 0; const byte st0 = 1; const byte st2 = 2; class Cl_joystic { protected: byte pin; byte state; unsigned long past; void set(byte s) { state = s; past = millis(); switch (s) { case st0: break; case st1: Do1(); break; case st2: Do2(); break; } } public: Cl_joystic(byte p): pin(p) {} pDo Do1 = [] {}; pDo Do2 = [] {}; void init() { set(st0); } void run() { if (millis() - past >= 100) { int tmp = analogRead(pin); switch (state) { case st1: if (tmp > 450)set(st0); if (millis() - past >= 300)set(st0); break; case st0: if (tmp < 400)set(st1); else if (tmp > 600)set(st2); break; case st2: if (tmp < 550)set(st0); if (millis() - past >= 300)set(st0); break; } } } }; Cl_joystic JoyLR(/*пин*/A1); Cl_joystic JoyUD(/*пин*/A2); //--------------- меню--------------------------------------------- byte var; // некая вспомогательная переменная const byte sMain = 0;// главный экран const byte ss1 = 1;// 1-экран const byte ss1e1 = 2;// редактирование 1 const byte ss1e2 = 3;// редактирование 2 const byte ss1e3 = 4;// редактирование 3 const byte ss2 = 5;// 2-экран const byte ss2e1 = 6;// редактирование 1 const byte ss2e2 = 7;// редактирование 2 const byte ss2e3 = 8;// редактирование 3 const byte ss3 = 9;// 3-экран const byte ss3e1 = 10;// редактирование 1 const byte ss3e2 = 11;// редактирование 2 const byte ss3e3 = 12;// редактирование 3 const byte ss4 = 13;// 4-экран const byte ss4e1 = 14;// редактирование 1 const byte ss4e2 = 15;// редактирование 2 const byte ss4e3 = 16;// редактирование 3 const byte ss5 = 17;// 5-экран const byte ss5e1 = 18;// редактирование 1 const byte ss5e2 = 19;// редактирование 2 const byte ss5e3 = 20;// редактирование 3 byte pos; unsigned long past; void setPos(byte p) { pos = p; past = millis(); lcd.clear(); switch (p) { case sMain:// главный экран { now = millis() / 1000; int hour = now / 60 / 60 % 24 ; int minute = now / 60 % 60; int second = now % 60; lcd << hour << F(":") << minute << F(":") << second; lcd.setCursor(9, 0); Timer[0].state(); lcd << F(" "); Timer[1].state(); lcd << F(" "); lcd.setCursor(5, 1); Timer[2].state(); lcd << F(" "); Timer[3].state(); lcd << F(" "); Timer[4].state(); lcd << F(" "); } Btn.Do = [] {}; JoyUD.Do1 = [] { }; JoyUD.Do2 = [] {setPos(ss1); }; break; case ss1: // 1-экран { lcd << F("Timer1:") << Timer[0].hour() << F(":") << Timer[0].minute() << F(":") << Timer[0].second(); } Btn.Do = [] { var = Timer[0].second(); setPos(ss1e1); }; JoyUD.Do1 = [] {setPos(sMain); }; JoyUD.Do2 = [] {setPos(ss2); }; break; case ss1e1:// редактирование секунд { lcd << F("Timer1:") << Timer[0].hour() << F(":") << Timer[0].minute() << F(">") << var; } Btn.Do = [] { Timer[0].writeSecond(var); var = Timer[0].minute(); setPos(ss1e2); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss1e1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss1e1); }; break; case ss1e2:// редактирование минут { lcd << F("Timer1:") << Timer[0].hour() << F(">") << var << F(":") << Timer[0].second(); } Btn.Do = [] { Timer[0].writeMinute(var); var = Timer[0].hour(); setPos(ss1e3); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss1e2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss1e2); }; break; case ss1e3:// редактирование часов { lcd << F("Timer1>") << var << F(":") << Timer[0].minute() << F(":") << Timer[0].second(); } Btn.Do = [] { Timer[0].writeHour(var); setPos(ss1); }; JoyUD.Do1 = [] { if (var < 23)var++; setPos(ss1e3); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss1e3); }; break; case ss2: // 2-экран { lcd << F("Timer2:") << Timer[1].hour() << F(":") << Timer[1].minute() << F(":") << Timer[1].second(); } Btn.Do = [] { var = Timer[1].second(); setPos(ss2e1); }; JoyUD.Do1 = [] {setPos(ss1); }; JoyUD.Do2 = [] {setPos(ss3); }; break; case ss2e1: { lcd << F("Timer2:") << Timer[1].hour() << F(":") << Timer[1].minute() << F(">") << var; } Btn.Do = [] { Timer[1].writeSecond(var); var = Timer[1].minute(); setPos(ss2e2); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss2e1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss2e1); }; break; case ss2e2: { lcd << F("Timer2:") << Timer[1].hour() << F(">") << var << F(":") << Timer[1].second(); } Btn.Do = [] { Timer[1].writeMinute(var); var = Timer[1].hour(); setPos(ss2e3); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss2e2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss2e2); }; break; case ss2e3: { lcd << F("Timer2>") << var << F(":") << Timer[1].minute() << F(":") << Timer[1].second(); } Btn.Do = [] { Timer[1].writeHour(var); setPos(ss2); }; JoyUD.Do1 = [] { if (var < 23)var++; setPos(ss2e3); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss2e3); }; break; case ss3: // 3-экран { lcd << F("Timer3:") << Timer[2].hour() << F(":") << Timer[2].minute() << F(":") << Timer[2].second(); } Btn.Do = [] { var = Timer[2].second(); setPos(ss3e1); }; JoyUD.Do1 = [] {setPos(ss2); }; JoyUD.Do2 = [] {setPos(ss4); }; break; case ss3e1:// редакт секунд { lcd << F("Timer3:") << Timer[2].hour() << F(":") << Timer[2].minute() << F(">") << var; } Btn.Do = [] { Timer[2].writeSecond(var); var = Timer[2].minute(); setPos(ss3e2); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss3e1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss3e1); }; break; case ss3e2:// редакт минут { lcd << F("Timer3:") << Timer[2].hour() << F(">") << var << F(":") << Timer[2].second(); } Btn.Do = [] { Timer[2].writeMinute(var); var = Timer[2].hour(); setPos(ss3e3); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss3e2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss3e2); }; break; case ss3e3:// редакт часов { lcd << F("Timer3>") << var << F(":") << Timer[2].minute() << F(":") << Timer[2].second(); } Btn.Do = [] { Timer[2].writeHour(var); setPos(ss3); }; JoyUD.Do1 = [] { if (var < 23)var++; setPos(ss3e3); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss3e3); }; break; case ss4: // 4-экран { lcd << F("Timer4:") << Timer[3].hour() << F(":") << Timer[3].minute() << F(":") << Timer[3].second(); } Btn.Do = [] { var = Timer[3].second(); setPos(ss4e1); }; JoyUD.Do1 = [] {setPos(ss3); }; JoyUD.Do2 = [] {setPos(ss5); }; break; case ss4e1: { lcd << F("Timer4:") << Timer[3].hour() << F(":") << Timer[3].minute() << F(">") << var; } Btn.Do = [] { Timer[3].writeSecond(var); var = Timer[3].minute(); setPos(ss4e2); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss4e1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss4e1); }; break; case ss4e2: { lcd << F("Timer4:") << Timer[3].hour() << F(">") << var << F(":") << Timer[3].second(); } Btn.Do = [] { Timer[3].writeMinute(var); var = Timer[3].hour(); setPos(ss4e3); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss4e2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss4e2); }; break; case ss4e3: { lcd << F("Timer4>") << var << F(":") << Timer[3].minute() << F(":") << Timer[3].second(); } Btn.Do = [] { Timer[3].writeHour(var); setPos(ss4); }; JoyUD.Do1 = [] { if (var < 23)var++; setPos(ss4e3); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss4e3); }; break; case ss5: // 5-экран { lcd << F("Timer5:") << Timer[4].hour() << F(":") << Timer[4].minute() << F(":") << Timer[4].second(); } Btn.Do = [] { var = Timer[4].second(); setPos(ss5e1); }; JoyUD.Do1 = [] { setPos(ss4); }; JoyUD.Do2 = [] {}; break; case ss5e1: { lcd << F("Timer5:") << Timer[4].hour() << F(":") << Timer[4].minute() << F(">") << var; } Btn.Do = [] { Timer[4].writeSecond(var); var = Timer[4].minute(); setPos(ss5e2); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss5e1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss5e1); }; break; case ss5e2: { lcd << F("Timer5:") << Timer[4].hour() << F(">") << var << F(":") << Timer[4].second(); } Btn.Do = [] { Timer[4].writeMinute(var); var = Timer[4].hour(); setPos(ss5e3); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss5e2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss5e2); }; break; case ss5e3: { lcd << F("Timer5>") << var << F(":") << Timer[4].minute() << F(":") << Timer[4].second(); } Btn.Do = [] { Timer[4].writeHour(var); setPos(ss5); }; JoyUD.Do1 = [] { if (var < 23)var++; setPos(ss5e3); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss5e3); }; break; } } void menuInit() { lcd.begin(16, 2); setPos(sMain); } void menuRun() { if (pos != sMain && millis() - past >= 10000)setPos(sMain); if (pos == sMain && millis() - past >= 1000)setPos(sMain); } //---------------------------------- void setup() { saveZeroSettings(); for (int i = 0; i < numTimer; i++) Timer[i].init(); lcd.init(); Btn.init(); JoyLR.init(); JoyUD.init(); menuInit(); JoyLR.Do1 = [] {lcd.backlight();}; JoyLR.Do2 = [] {lcd.noBacklight();}; } void loop() { for (int i = 0; i < numTimer; i++) Timer[i].run(); Btn.run(); JoyLR.run(); JoyUD.run(); menuRun(); } /**//**/ unsigned long now ;// количество секунд прошедшее после вкл //---------------lcd--------------------------------------------- template <typename T> inline Print & operator << (Print &s, T n) { s.print(n); return s; } #include <Wire.h> #include <LiquidCrystal_I2C.h> LiquidCrystal_I2C lcd(0x27, 16, 2); // -------------таймеры------------------------------------------------ typedef struct { byte hour; byte minute; byte second; } timer_t; const byte numTimer = 5; timer_t EEMEM adr1[numTimer]; // первичные настройки в EEPROM void saveZeroSettings() { timer_t data[numTimer * 2] = { // начальные настройки {0, 0, 30}, {0, 3, 00}, // 1-й таймер {0, 1, 00}, {0, 3, 30}, // 2-й таймер {0, 1, 30}, {0, 4, 00}, // 3-й таймер {0, 2, 00}, {0, 4, 30}, // 4-й таймер {0, 2, 30}, {0, 5, 00} // 5-й таймер }; for (int i = 0; i < numTimer * 2; ++i) { eeprom_write_byte(&adr1[i].hour , data[i].hour); eeprom_write_byte(&adr1[i].minute, data[i].minute); eeprom_write_byte(&adr1[i].second, data[i].second); } } /*состояния таймера*/ const byte sOFF = 0; const byte sON = 1; const byte sEND = 2; class Cl_Timer { private: timer_t *adr1, *adr2; byte stat;// состояние unsigned long past; void setStat(byte s) { stat = s; past = millis(); switch (s) { case sOFF: break; case sON: break; case sEND: break; } } public: Cl_Timer(timer_t * a1, timer_t * a2): adr1(a1), adr2(a2) {} void init() { setStat(sOFF); } void run() { if (millis() - past >= 100) { switch (stat) { case sOFF: if (now >= ((unsigned long)hour1() * 24 + minute1()) * 60 + second1())setStat(sON); break; case sON: setStat(sON); break; case sEND: setStat(sEND); break; } } } void state() { switch (stat) { case sOFF: lcd << F("OFF"); break; case sON: lcd << F("ON "); break; case sEND: lcd << F("END"); break; } } byte hour1() { return eeprom_read_byte(&(adr1->hour)); } byte minute1() { return eeprom_read_byte(&(adr1->minute)); } byte second1() { return eeprom_read_byte(&(adr1->second)); } void writeHour1(byte data) { eeprom_write_byte(&(adr1->hour), data); } void writeMinute1(byte data) { eeprom_write_byte(&(adr1->minute), data); } void writeSecond1(byte data) { eeprom_write_byte(&(adr1->second), data); } byte hour2() { return eeprom_read_byte(&(adr2->hour)); } byte minute2() { return eeprom_read_byte(&(adr2->minute)); } byte second2() { return eeprom_read_byte(&(adr2->second)); } void writeHour2(byte data) { eeprom_write_byte(&(adr2->hour), data); } void writeMinute2(byte data) { eeprom_write_byte(&(adr2->minute), data); } void writeSecond2(byte data) { eeprom_write_byte(&(adr2->second), data); } }; Cl_Timer Timer[numTimer] = { Cl_Timer(&adr1[0], &adr1[1]), // 1-й таймер Cl_Timer(&adr1[2], &adr1[3]), // 2-й таймер Cl_Timer(&adr1[4], &adr1[5]), // 3-й таймер Cl_Timer(&adr1[6], &adr1[7]), // 4-й таймер Cl_Timer(&adr1[8], &adr1[9]) // 5-й таймер }; //---кнопкa----------------------------- typedef void (*pDo)(); class Cl_btn { protected: byte pin; bool state; unsigned long past; void set(bool s) { state = s; past = millis(); switch (s) { case false: break; case true: Do(); break; } } public: Cl_btn(byte p): pin(p) {} pDo Do = [] {}; void init() { pinMode(pin, INPUT_PULLUP); set(false); } void run() { if (millis() - past >= 100) switch (state) { case false: if (!digitalRead(pin))set(true); break; case true: if (digitalRead(pin))set(false); if (millis() - past >= 300)set(false); break; } } }; Cl_btn Btn(/*пин*/A0); //------------------------------------------- const byte st1 = 0; const byte st0 = 1; const byte st2 = 2; class Cl_joystic { protected: byte pin; byte state; unsigned long past; void set(byte s) { state = s; past = millis(); switch (s) { case st0: break; case st1: Do1(); break; case st2: Do2(); break; } } public: Cl_joystic(byte p): pin(p) {} pDo Do1 = [] {}; pDo Do2 = [] {}; void init() { set(st0); } void run() { if (millis() - past >= 100) { int tmp = analogRead(pin); switch (state) { case st1: if (tmp > 450)set(st0); if (millis() - past >= 300)set(st0); break; case st0: if (tmp < 400)set(st1); else if (tmp > 600)set(st2); break; case st2: if (tmp < 550)set(st0); if (millis() - past >= 300)set(st0); break; } } } }; Cl_joystic JoyLR(/*пин*/A1); Cl_joystic JoyUD(/*пин*/A2); //--------------- меню--------------------------------------------- byte var; // некая вспомогательная переменная const byte sMain = 0;// главный экран const byte ss1 = 1;// 1-экран const byte ss1sec1 = 2;// редактирование 1 const byte ss1min1 = 3;// редактирование 2 const byte ss1hour1 = 4;// редактирование 3 const byte ss1sec2 = 5;// редактирование 1 const byte ss1min2 = 6;// редактирование 2 const byte ss1hour2 = 7;// редактирование 3 const byte ss2 = 11;// 2-экран const byte ss2sec1 = 12;// редактирование 1 const byte ss2min1 = 13;// редактирование 2 const byte ss2hour1 = 14;// редактирование 3 const byte ss2sec2 = 15;// редактирование 1 const byte ss2min2 = 16;// редактирование 2 const byte ss2hour2 = 17;// редактирование 3 const byte ss3 = 21;// 3-экран const byte ss3sec1 = 22;// редактирование 1 const byte ss3min1 = 23;// редактирование 2 const byte ss3hour1 = 24;// редактирование 3 const byte ss3sec2 = 25;// редактирование 1 const byte ss3min2 = 26;// редактирование 2 const byte ss3hour2 = 27;// редактирование 3 const byte ss4 = 31;// 4-экран const byte ss4sec1 = 32;// редактирование 1 const byte ss4min1 = 33;// редактирование 2 const byte ss4hour1 = 34;// редактирование 3 const byte ss4sec2 = 35;// редактирование 1 const byte ss4min2 = 36;// редактирование 2 const byte ss4hour2 = 37;// редактирование 3 const byte ss5 = 41;// 5-экран const byte ss5sec1 = 42;// редактирование 1 const byte ss5min1 = 43;// редактирование 2 const byte ss5hour1 = 44;// редактирование 3 const byte ss5sec2 = 45;// редактирование 1 const byte ss5min2 = 46;// редактирование 2 const byte ss5hour2 = 47;// редактирование 3 byte pos; unsigned long past; void setPos(byte p) { pos = p; past = millis(); lcd.clear(); switch (p) { case sMain:// главный экран { now = millis() / 1000; int hour = now / 60 / 60 % 24 ; int minute = now / 60 % 60; int second = now % 60; lcd << hour << F(":") << minute << F(":") << second; lcd.setCursor(9, 0); Timer[0].state(); lcd << F(" "); Timer[1].state(); lcd << F(" "); lcd.setCursor(5, 1); Timer[2].state(); lcd << F(" "); Timer[3].state(); lcd << F(" "); Timer[4].state(); lcd << F(" "); } Btn.Do = [] {}; JoyUD.Do1 = [] { }; JoyUD.Do2 = [] {setPos(ss1); }; break; case ss1: // 1-экран { lcd << F("Timer1:") << Timer[0].hour1() << F(":") << Timer[0].minute1() << F(":") << Timer[0].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[0].hour2() << F(":") << Timer[0].minute2() << F(":") << Timer[0].second2(); } Btn.Do = [] { var = Timer[0].second1(); setPos(ss1sec1); }; JoyUD.Do1 = [] {setPos(sMain); }; JoyUD.Do2 = [] {setPos(ss2); }; break; case ss1sec1:// редактирование секунд { lcd << F("Timer1:") << Timer[0].hour1() << F(":") << Timer[0].minute1() << F(">") << var; lcd.setCursor(0, 1); lcd << F(" ") << Timer[0].hour2() << F(":") << Timer[0].minute2() << F(":") << Timer[0].second2(); } Btn.Do = [] { Timer[0].writeSecond1(var); var = Timer[0].minute1(); setPos(ss1min1); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss1sec1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss1sec1); }; break; case ss1min1:// редактирование минут { lcd << F("Timer1:") << Timer[0].hour1() << F(">") << var << F(":") << Timer[0].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[0].hour2() << F(":") << Timer[0].minute2() << F(":") << Timer[0].second2(); } Btn.Do = [] { Timer[0].writeMinute1(var); var = Timer[0].hour1(); setPos(ss1hour1); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss1min1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss1min1); }; break; case ss1hour1:// редактирование часов { lcd << F("Timer1>") << var << F(":") << Timer[0].minute1() << F(":") << Timer[0].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[0].hour2() << F(":") << Timer[0].minute2() << F(":") << Timer[0].second2(); } Btn.Do = [] { Timer[0].writeHour1(var); setPos(ss1sec2); }; JoyUD.Do1 = [] { if (var < 23)var++; setPos(ss1hour1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss1hour1); }; break; case ss1sec2:// редактирование секунд { lcd << F("Timer1:") << Timer[0].hour1() << F(":") << Timer[0].minute1() << F(":") << Timer[0].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[0].hour2() << F(":") << Timer[0].minute2() << F(">") << var; } Btn.Do = [] { Timer[0].writeSecond2(var); var = Timer[0].minute2(); setPos(ss1min2); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss1sec2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss1sec2); }; break; case ss1min2:// редактирование минут { lcd << F("Timer1:") << Timer[0].hour1() << F(":") << Timer[0].minute1() << F(":") << Timer[0].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[0].hour2() << F(">") << var << F(":") << Timer[0].second2(); } Btn.Do = [] { Timer[0].writeMinute2(var); var = Timer[0].hour2(); setPos(ss1hour2); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss1min2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss1min2); }; break; case ss1hour2:// редактирование часов { lcd << F("Timer1:") << Timer[0].hour1() << F(":") << Timer[0].minute1() << F(":") << Timer[0].second1(); lcd.setCursor(0, 1); lcd << F(" >") << var << F(":") << Timer[0].minute2() << F(":") << Timer[0].second2(); } Btn.Do = [] { Timer[0].writeHour2(var); setPos(ss1); }; JoyUD.Do1 = [] { if (var < 23)var++; setPos(ss1hour2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss1hour2); }; break; //--------------------------------------------------------------------- case ss2: // 2-экран { lcd << F("Timer2:") << Timer[1].hour1() << F(":") << Timer[1].minute1() << F(":") << Timer[1].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[1].hour2() << F(":") << Timer[1].minute2() << F(":") << Timer[1].second2(); } Btn.Do = [] { var = Timer[1].second1(); setPos(ss2sec1); }; JoyUD.Do1 = [] {setPos(ss1); }; JoyUD.Do2 = [] {setPos(ss3); }; break; case ss2sec1: { lcd << F("Timer2:") << Timer[1].hour1() << F(":") << Timer[1].minute1() << F(">") << var; lcd.setCursor(0, 1); lcd << F(" ") << Timer[1].hour2() << F(":") << Timer[1].minute2() << F(":") << Timer[1].second2(); } Btn.Do = [] { Timer[1].writeSecond1(var); var = Timer[1].minute1(); setPos(ss2min1); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss2sec1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss2sec1); }; break; case ss2min1: { lcd << F("Timer2:") << Timer[1].hour1() << F(">") << var << F(":") << Timer[1].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[1].hour2() << F(":") << Timer[1].minute2() << F(":") << Timer[1].second2(); } Btn.Do = [] { Timer[1].writeMinute1(var); var = Timer[1].hour1(); setPos(ss2hour1); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss2min1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss2min1); }; break; case ss2hour1: { lcd << F("Timer2>") << var << F(":") << Timer[1].minute1() << F(":") << Timer[1].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[1].hour2() << F(":") << Timer[1].minute2() << F(":") << Timer[1].second2(); } Btn.Do = [] { Timer[1].writeHour1(var); var = Timer[1].second2(); setPos(ss2sec2); }; JoyUD.Do1 = [] { if (var < 23)var++; setPos(ss2hour1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss2hour1); }; break; case ss2sec2: { lcd << F("Timer2:") << Timer[1].hour1() << F(":") << Timer[1].minute1() << F(":") << Timer[1].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[1].hour2() << F(":") << Timer[1].minute2() << F(">") << var; } Btn.Do = [] { Timer[1].writeSecond2(var); var = Timer[1].minute2(); setPos(ss2min2); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss2sec2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss2sec2); }; break; case ss2min2: { lcd << F("Timer2:") << Timer[1].hour1() << F(":") << Timer[1].minute1() << F(":") << Timer[1].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[1].hour2() << F(">") << var << F(":") << Timer[1].second2(); } Btn.Do = [] { Timer[1].writeMinute2(var); var = Timer[1].hour2(); setPos(ss2hour2); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss2min2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss2min2); }; break; case ss2hour2: { lcd << F("Timer2:") << Timer[1].hour1() << F(":") << Timer[1].minute1() << F(":") << Timer[1].second1(); lcd.setCursor(0, 1); lcd << F(" >") << var << F(":") << Timer[1].minute2() << F(":") << Timer[1].second2(); } Btn.Do = [] { Timer[1].writeHour2(var); setPos(ss2); }; JoyUD.Do1 = [] { if (var < 23)var++; setPos(ss2hour2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss2hour2); }; break; //--------------------------------------------------------------------- case ss3: // 3-экран { lcd << F("Timer3:") << Timer[2].hour1() << F(":") << Timer[2].minute1() << F(":") << Timer[2].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[2].hour2() << F(":") << Timer[2].minute2() << F(":") << Timer[2].second2(); } Btn.Do = [] { var = Timer[2].second1(); setPos(ss3sec1); }; JoyUD.Do1 = [] {setPos(ss2); }; JoyUD.Do2 = [] {setPos(ss4); }; break; case ss3sec1:// редакт секунд { lcd << F("Timer3:") << Timer[2].hour1() << F(":") << Timer[2].minute1() << F(">") << var; lcd.setCursor(0, 1); lcd << F(" ") << Timer[2].hour2() << F(":") << Timer[2].minute2() << F(":") << Timer[2].second2(); } Btn.Do = [] { Timer[2].writeSecond1(var); var = Timer[2].minute1(); setPos(ss3min1); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss3sec1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss3sec1); }; break; case ss3min1:// редакт минут { lcd << F("Timer3:") << Timer[2].hour1() << F(">") << var << F(":") << Timer[2].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[2].hour2() << F(":") << Timer[2].minute2() << F(":") << Timer[2].second2(); } Btn.Do = [] { Timer[2].writeMinute1(var); var = Timer[2].hour1(); setPos(ss3hour1); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss3min1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss3min1); }; break; case ss3hour1:// редакт часов { lcd << F("Timer3>") << var << F(":") << Timer[2].minute1() << F(":") << Timer[2].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[2].hour2() << F(":") << Timer[2].minute2() << F(":") << Timer[2].second2(); } Btn.Do = [] { Timer[2].writeHour1(var); var = Timer[2].second2(); setPos(ss3sec2); }; JoyUD.Do1 = [] { if (var < 23)var++; setPos(ss3hour1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss3hour1); }; break; case ss3sec2:// редакт секунд { lcd << F("Timer3:") << Timer[2].hour1() << F(":") << Timer[2].minute1() << F(":") << Timer[2].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[2].hour2() << F(":") << Timer[2].minute2() << F(">") << var; } Btn.Do = [] { Timer[2].writeSecond2(var); var = Timer[2].minute2(); setPos(ss3min2); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss3sec2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss3sec2); }; break; case ss3min2:// редакт минут { lcd << F("Timer3:") << Timer[2].hour1() << F(":") << Timer[2].minute1() << F(":") << Timer[2].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[2].hour2() << F(">") << var << F(":") << Timer[2].second2(); } Btn.Do = [] { Timer[2].writeMinute2(var); var = Timer[2].hour2(); setPos(ss3hour2); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss3min2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss3min2); }; break; case ss3hour2:// редакт часов { lcd << F("Timer3:") << Timer[2].hour1() << F(":") << Timer[2].minute1() << F(":") << Timer[2].second1(); lcd.setCursor(0, 1); lcd << F(" >") << var << F(":") << Timer[2].minute2() << F(":") << Timer[2].second2(); } Btn.Do = [] { Timer[2].writeHour2(var); setPos(ss3); }; JoyUD.Do1 = [] { if (var < 23)var++; setPos(ss3hour2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss3hour2); }; break; //--------------------------------------------------------------------- case ss4: // 4-экран { lcd << F("Timer4:") << Timer[3].hour1() << F(":") << Timer[3].minute1() << F(":") << Timer[3].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[3].hour2() << F(":") << Timer[3].minute2() << F(":") << Timer[3].second2(); } Btn.Do = [] { var = Timer[3].second1(); setPos(ss4sec1); }; JoyUD.Do1 = [] {setPos(ss3); }; JoyUD.Do2 = [] {setPos(ss5); }; break; case ss4sec1: { lcd << F("Timer4:") << Timer[3].hour1() << F(":") << Timer[3].minute1() << F(">") << var; lcd.setCursor(0, 1); lcd << F(" ") << Timer[3].hour2() << F(":") << Timer[3].minute2() << F(":") << Timer[3].second2(); } Btn.Do = [] { Timer[3].writeSecond1(var); var = Timer[3].minute1(); setPos(ss4min1); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss4sec1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss4sec1); }; break; case ss4min1: { lcd << F("Timer4:") << Timer[3].hour1() << F(">") << var << F(":") << Timer[3].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[3].hour2() << F(":") << Timer[3].minute2() << F(":") << Timer[3].second2(); } Btn.Do = [] { Timer[3].writeMinute1(var); var = Timer[3].hour1(); setPos(ss4hour1); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss4min1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss4min1); }; break; case ss4hour1: { lcd << F("Timer4>") << var << F(":") << Timer[3].minute1() << F(":") << Timer[3].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[3].hour2() << F(":") << Timer[3].minute2() << F(":") << Timer[3].second2(); } Btn.Do = [] { Timer[3].writeHour1(var); var = Timer[3].second2(); setPos(ss4sec2); }; JoyUD.Do1 = [] { if (var < 23)var++; setPos(ss4hour1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss4hour1); }; break; case ss4sec2: { lcd << F("Timer4:") << Timer[3].hour1() << F(":") << Timer[3].minute1() << F(":") << Timer[3].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[3].hour2() << F(":") << Timer[3].minute2() << F(">") << var; } Btn.Do = [] { Timer[3].writeSecond2(var); var = Timer[3].minute2(); setPos(ss4min2); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss4sec2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss4sec2); }; break; case ss4min2: { lcd << F("Timer4:") << Timer[3].hour1() << F(":") << Timer[3].minute1() << F(":") << Timer[3].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[3].hour2() << F(">") << var << F(":") << Timer[3].second2(); } Btn.Do = [] { Timer[3].writeMinute2(var); var = Timer[3].hour2(); setPos(ss4hour2); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss4min2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss4min2); }; break; case ss4hour2: { lcd << F("Timer4:") << Timer[3].hour1() << F(":") << Timer[3].minute1() << F(":") << Timer[3].second1(); lcd.setCursor(0, 1); lcd << F(" >") << var << F(":") << Timer[3].minute2() << F(":") << Timer[3].second2(); } Btn.Do = [] { Timer[3].writeHour2(var); setPos(ss4); }; JoyUD.Do1 = [] { if (var < 23)var++; setPos(ss4hour2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss4hour2); }; break; //--------------------------------------------------------------------- case ss5: // 5-экран { lcd << F("Timer5:") << Timer[4].hour1() << F(":") << Timer[4].minute1() << F(":") << Timer[4].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[4].hour2() << F(":") << Timer[4].minute2() << F(":") << Timer[4].second2(); } Btn.Do = [] { var = Timer[4].second1(); setPos(ss5sec1); }; JoyUD.Do1 = [] { setPos(ss4); }; JoyUD.Do2 = [] {}; break; case ss5sec1: { lcd << F("Timer5:") << Timer[4].hour1() << F(":") << Timer[4].minute1() << F(">") << var; lcd.setCursor(0, 1); lcd << F(" ") << Timer[4].hour2() << F(":") << Timer[4].minute2() << F(":") << Timer[4].second2(); } Btn.Do = [] { Timer[4].writeSecond1(var); var = Timer[4].minute1(); setPos(ss5min1); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss5sec1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss5sec1); }; break; case ss5min1: { lcd << F("Timer5:") << Timer[4].hour1() << F(">") << var << F(":") << Timer[4].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[4].hour2() << F(":") << Timer[4].minute2() << F(":") << Timer[4].second2(); } Btn.Do = [] { Timer[4].writeMinute1(var); var = Timer[4].hour1(); setPos(ss5hour1); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss5min1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss5min1); }; break; case ss5hour1: { lcd << F("Timer5>") << var << F(":") << Timer[4].minute1() << F(":") << Timer[4].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[4].hour2() << F(":") << Timer[4].minute2() << F(":") << Timer[4].second2(); } Btn.Do = [] { Timer[4].writeHour1(var); var = Timer[4].second2(); setPos(ss5sec2); }; JoyUD.Do1 = [] { if (var < 23)var++; setPos(ss5hour1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss5hour1); }; break; case ss5sec2: { lcd << F("Timer5:") << Timer[4].hour1() << F(":") << Timer[4].minute1() << F(":") << Timer[4].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[4].hour2() << F(":") << Timer[4].minute2() << F(">") << var; } Btn.Do = [] { Timer[4].writeSecond2(var); var = Timer[4].minute2(); setPos(ss5min2); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss5sec2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss5sec2); }; break; case ss5min2: { lcd << F("Timer5:") << Timer[4].hour1() << F(":") << Timer[4].minute1() << F(":") << Timer[4].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[4].hour2() << F(">") << var << F(":") << Timer[4].second2(); } Btn.Do = [] { Timer[4].writeMinute2(var); var = Timer[4].hour2(); setPos(ss5hour2); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss5min2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss5min2); }; break; case ss5hour2: { lcd << F("Timer5:") << Timer[4].hour1() << F(":") << Timer[4].minute1() << F(":") << Timer[4].second1(); lcd.setCursor(0, 1); lcd << F(" >") << var << F(":") << Timer[4].minute2() << F(":") << Timer[4].second2(); } Btn.Do = [] { Timer[4].writeHour2(var); setPos(ss5); }; JoyUD.Do1 = [] { if (var < 23)var++; setPos(ss5hour2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss5hour2); }; break; } } void menuInit() { lcd.begin(16, 2); setPos(sMain); } void menuRun() { if (pos != sMain && millis() - past >= 10000)setPos(sMain); if (pos == sMain && millis() - past >= 1000)setPos(sMain); } //---------------------------------- void setup() { saveZeroSettings(); for (int i = 0; i < numTimer; i++) Timer[i].init(); lcd.init(); Btn.init(); JoyLR.init(); JoyUD.init(); menuInit(); JoyLR.Do1 = [] {lcd.backlight();}; JoyLR.Do2 = [] {lcd.noBacklight();}; } void loop() { for (int i = 0; i < numTimer; i++) Timer[i].run(); Btn.run(); JoyLR.run(); JoyUD.run(); menuRun(); } /**/Подключим 5 реле на таймеры и получим.
/**/ unsigned long now ;// количество секунд прошедшее после вкл //---------------lcd--------------------------------------------- template <typename T> inline Print & operator << (Print &s, T n) { s.print(n); return s; } #include <Wire.h> #include <LiquidCrystal_I2C.h> LiquidCrystal_I2C lcd(0x27, 16, 2); // -------------таймеры------------------------------------------------ typedef struct { byte hour; byte minute; byte second; } timer_t; const byte numTimer = 5; timer_t EEMEM adr1[numTimer]; // первичные настройки в EEPROM void saveZeroSettings() { timer_t data[numTimer * 2] = { // начальные настройки {0, 0, 30}, {0, 3, 00}, // 1-й таймер {0, 1, 00}, {0, 3, 30}, // 2-й таймер {0, 1, 30}, {0, 4, 00}, // 3-й таймер {0, 2, 00}, {0, 4, 30}, // 4-й таймер {0, 2, 30}, {0, 5, 00} // 5-й таймер }; for (int i = 0; i < numTimer * 2; ++i) { eeprom_write_byte(&adr1[i].hour , data[i].hour); eeprom_write_byte(&adr1[i].minute, data[i].minute); eeprom_write_byte(&adr1[i].second, data[i].second); } } /*состояния таймера*/ const byte sOFF = 0; const byte sON = 1; const byte sEND = 2; class Cl_Timer { private: timer_t *adr1, *adr2; byte pin; byte stat;// состояние unsigned long past; void setStat(byte s) { stat = s; past = millis(); switch (s) { case sOFF: digitalWrite(pin, HIGH); break; case sON: digitalWrite(pin, LOW); break; case sEND: digitalWrite(pin, HIGH); break; } } public: Cl_Timer(byte p, timer_t * a1, timer_t * a2) : adr1(a1), adr2(a2), pin(p) {} void init() { pinMode(pin, OUTPUT); setStat(sOFF); } void run() { if (millis() - past >= 100) { switch (stat) { case sOFF: if (now >= ((unsigned long)hour1() * 24 + minute1()) * 60 + second1())setStat(sON); else setStat(sOFF); break; case sON: if (now >= ((unsigned long)hour2() * 24 + minute2()) * 60 + second2())setStat(sEND); else setStat(sON); break; case sEND: setStat(sEND); break; } } } void state() { switch (stat) { case sOFF: lcd << F("OFF"); break; case sON: lcd << F("ON "); break; case sEND: lcd << F("END"); break; } } byte hour1() { return eeprom_read_byte(&(adr1->hour)); } byte minute1() { return eeprom_read_byte(&(adr1->minute)); } byte second1() { return eeprom_read_byte(&(adr1->second)); } void writeHour1(byte data) { eeprom_write_byte(&(adr1->hour), data); } void writeMinute1(byte data) { eeprom_write_byte(&(adr1->minute), data); } void writeSecond1(byte data) { eeprom_write_byte(&(adr1->second), data); } byte hour2() { return eeprom_read_byte(&(adr2->hour)); } byte minute2() { return eeprom_read_byte(&(adr2->minute)); } byte second2() { return eeprom_read_byte(&(adr2->second)); } void writeHour2(byte data) { eeprom_write_byte(&(adr2->hour), data); } void writeMinute2(byte data) { eeprom_write_byte(&(adr2->minute), data); } void writeSecond2(byte data) { eeprom_write_byte(&(adr2->second), data); } }; Cl_Timer Timer[numTimer] = { Cl_Timer(/*пин*/2, &adr1[0], &adr1[1]), // 1-й таймер Cl_Timer(/*пин*/3, &adr1[2], &adr1[3]), // 2-й таймер Cl_Timer(/*пин*/4, &adr1[4], &adr1[5]), // 3-й таймер Cl_Timer(/*пин*/5, &adr1[6], &adr1[7]), // 4-й таймер Cl_Timer(/*пин*/6, &adr1[8], &adr1[9]) // 5-й таймер }; //---кнопкa----------------------------- typedef void (*pDo)(); class Cl_btn { protected: byte pin; bool state; unsigned long past; void set(bool s) { state = s; past = millis(); switch (s) { case false: break; case true: Do(); break; } } public: Cl_btn(byte p): pin(p) {} pDo Do = [] {}; void init() { pinMode(pin, INPUT_PULLUP); set(false); } void run() { if (millis() - past >= 100) switch (state) { case false: if (!digitalRead(pin))set(true); break; case true: if (digitalRead(pin))set(false); if (millis() - past >= 300)set(false); break; } } }; Cl_btn Btn(/*пин*/A0); //------------------------------------------- const byte st1 = 0; const byte st0 = 1; const byte st2 = 2; class Cl_joystic { protected: byte pin; byte state; unsigned long past; void set(byte s) { state = s; past = millis(); switch (s) { case st0: break; case st1: Do1(); break; case st2: Do2(); break; } } public: Cl_joystic(byte p): pin(p) {} pDo Do1 = [] {}; pDo Do2 = [] {}; void init() { set(st0); } void run() { if (millis() - past >= 100) { int tmp = analogRead(pin); switch (state) { case st1: if (tmp > 450)set(st0); if (millis() - past >= 300)set(st0); break; case st0: if (tmp < 400)set(st1); else if (tmp > 600)set(st2); break; case st2: if (tmp < 550)set(st0); if (millis() - past >= 300)set(st0); break; } } } }; Cl_joystic JoyLR(/*пин*/A1); Cl_joystic JoyUD(/*пин*/A2); //--------------- меню--------------------------------------------- byte var; // некая вспомогательная переменная const byte sMain = 0;// главный экран const byte ss1 = 1;// 1-экран const byte ss1sec1 = 2;// редактирование 1 const byte ss1min1 = 3;// редактирование 2 const byte ss1hour1 = 4;// редактирование 3 const byte ss1sec2 = 5;// редактирование 1 const byte ss1min2 = 6;// редактирование 2 const byte ss1hour2 = 7;// редактирование 3 const byte ss2 = 11;// 2-экран const byte ss2sec1 = 12;// редактирование 1 const byte ss2min1 = 13;// редактирование 2 const byte ss2hour1 = 14;// редактирование 3 const byte ss2sec2 = 15;// редактирование 1 const byte ss2min2 = 16;// редактирование 2 const byte ss2hour2 = 17;// редактирование 3 const byte ss3 = 21;// 3-экран const byte ss3sec1 = 22;// редактирование 1 const byte ss3min1 = 23;// редактирование 2 const byte ss3hour1 = 24;// редактирование 3 const byte ss3sec2 = 25;// редактирование 1 const byte ss3min2 = 26;// редактирование 2 const byte ss3hour2 = 27;// редактирование 3 const byte ss4 = 31;// 4-экран const byte ss4sec1 = 32;// редактирование 1 const byte ss4min1 = 33;// редактирование 2 const byte ss4hour1 = 34;// редактирование 3 const byte ss4sec2 = 35;// редактирование 1 const byte ss4min2 = 36;// редактирование 2 const byte ss4hour2 = 37;// редактирование 3 const byte ss5 = 41;// 5-экран const byte ss5sec1 = 42;// редактирование 1 const byte ss5min1 = 43;// редактирование 2 const byte ss5hour1 = 44;// редактирование 3 const byte ss5sec2 = 45;// редактирование 1 const byte ss5min2 = 46;// редактирование 2 const byte ss5hour2 = 47;// редактирование 3 byte pos; unsigned long past; void setPos(byte p) { pos = p; past = millis(); lcd.clear(); switch (p) { case sMain:// главный экран { now = millis() / 1000; int hour = now / 60 / 60 % 24 ; int minute = now / 60 % 60; int second = now % 60; lcd << hour << F(":") << minute << F(":") << second; lcd.setCursor(9, 0); Timer[0].state(); lcd << F(" "); Timer[1].state(); lcd << F(" "); lcd.setCursor(5, 1); Timer[2].state(); lcd << F(" "); Timer[3].state(); lcd << F(" "); Timer[4].state(); lcd << F(" "); } Btn.Do = [] {}; JoyUD.Do1 = [] { }; JoyUD.Do2 = [] {setPos(ss1); }; break; case ss1: // 1-экран { lcd << F("Timer1:") << Timer[0].hour1() << F(":") << Timer[0].minute1() << F(":") << Timer[0].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[0].hour2() << F(":") << Timer[0].minute2() << F(":") << Timer[0].second2(); } Btn.Do = [] { var = Timer[0].second1(); setPos(ss1sec1); }; JoyUD.Do1 = [] {setPos(sMain); }; JoyUD.Do2 = [] {setPos(ss2); }; break; case ss1sec1:// редактирование секунд { lcd << F("Timer1:") << Timer[0].hour1() << F(":") << Timer[0].minute1() << F(">") << var; lcd.setCursor(0, 1); lcd << F(" ") << Timer[0].hour2() << F(":") << Timer[0].minute2() << F(":") << Timer[0].second2(); } Btn.Do = [] { Timer[0].writeSecond1(var); var = Timer[0].minute1(); setPos(ss1min1); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss1sec1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss1sec1); }; break; case ss1min1:// редактирование минут { lcd << F("Timer1:") << Timer[0].hour1() << F(">") << var << F(":") << Timer[0].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[0].hour2() << F(":") << Timer[0].minute2() << F(":") << Timer[0].second2(); } Btn.Do = [] { Timer[0].writeMinute1(var); var = Timer[0].hour1(); setPos(ss1hour1); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss1min1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss1min1); }; break; case ss1hour1:// редактирование часов { lcd << F("Timer1>") << var << F(":") << Timer[0].minute1() << F(":") << Timer[0].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[0].hour2() << F(":") << Timer[0].minute2() << F(":") << Timer[0].second2(); } Btn.Do = [] { Timer[0].writeHour1(var); setPos(ss1sec2); }; JoyUD.Do1 = [] { if (var < 23)var++; setPos(ss1hour1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss1hour1); }; break; case ss1sec2:// редактирование секунд { lcd << F("Timer1:") << Timer[0].hour1() << F(":") << Timer[0].minute1() << F(":") << Timer[0].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[0].hour2() << F(":") << Timer[0].minute2() << F(">") << var; } Btn.Do = [] { Timer[0].writeSecond2(var); var = Timer[0].minute2(); setPos(ss1min2); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss1sec2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss1sec2); }; break; case ss1min2:// редактирование минут { lcd << F("Timer1:") << Timer[0].hour1() << F(":") << Timer[0].minute1() << F(":") << Timer[0].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[0].hour2() << F(">") << var << F(":") << Timer[0].second2(); } Btn.Do = [] { Timer[0].writeMinute2(var); var = Timer[0].hour2(); setPos(ss1hour2); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss1min2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss1min2); }; break; case ss1hour2:// редактирование часов { lcd << F("Timer1:") << Timer[0].hour1() << F(":") << Timer[0].minute1() << F(":") << Timer[0].second1(); lcd.setCursor(0, 1); lcd << F(" >") << var << F(":") << Timer[0].minute2() << F(":") << Timer[0].second2(); } Btn.Do = [] { Timer[0].writeHour2(var); setPos(ss1); }; JoyUD.Do1 = [] { if (var < 23)var++; setPos(ss1hour2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss1hour2); }; break; //--------------------------------------------------------------------- case ss2: // 2-экран { lcd << F("Timer2:") << Timer[1].hour1() << F(":") << Timer[1].minute1() << F(":") << Timer[1].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[1].hour2() << F(":") << Timer[1].minute2() << F(":") << Timer[1].second2(); } Btn.Do = [] { var = Timer[1].second1(); setPos(ss2sec1); }; JoyUD.Do1 = [] {setPos(ss1); }; JoyUD.Do2 = [] {setPos(ss3); }; break; case ss2sec1: { lcd << F("Timer2:") << Timer[1].hour1() << F(":") << Timer[1].minute1() << F(">") << var; lcd.setCursor(0, 1); lcd << F(" ") << Timer[1].hour2() << F(":") << Timer[1].minute2() << F(":") << Timer[1].second2(); } Btn.Do = [] { Timer[1].writeSecond1(var); var = Timer[1].minute1(); setPos(ss2min1); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss2sec1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss2sec1); }; break; case ss2min1: { lcd << F("Timer2:") << Timer[1].hour1() << F(">") << var << F(":") << Timer[1].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[1].hour2() << F(":") << Timer[1].minute2() << F(":") << Timer[1].second2(); } Btn.Do = [] { Timer[1].writeMinute1(var); var = Timer[1].hour1(); setPos(ss2hour1); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss2min1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss2min1); }; break; case ss2hour1: { lcd << F("Timer2>") << var << F(":") << Timer[1].minute1() << F(":") << Timer[1].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[1].hour2() << F(":") << Timer[1].minute2() << F(":") << Timer[1].second2(); } Btn.Do = [] { Timer[1].writeHour1(var); var = Timer[1].second2(); setPos(ss2sec2); }; JoyUD.Do1 = [] { if (var < 23)var++; setPos(ss2hour1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss2hour1); }; break; case ss2sec2: { lcd << F("Timer2:") << Timer[1].hour1() << F(":") << Timer[1].minute1() << F(":") << Timer[1].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[1].hour2() << F(":") << Timer[1].minute2() << F(">") << var; } Btn.Do = [] { Timer[1].writeSecond2(var); var = Timer[1].minute2(); setPos(ss2min2); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss2sec2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss2sec2); }; break; case ss2min2: { lcd << F("Timer2:") << Timer[1].hour1() << F(":") << Timer[1].minute1() << F(":") << Timer[1].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[1].hour2() << F(">") << var << F(":") << Timer[1].second2(); } Btn.Do = [] { Timer[1].writeMinute2(var); var = Timer[1].hour2(); setPos(ss2hour2); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss2min2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss2min2); }; break; case ss2hour2: { lcd << F("Timer2:") << Timer[1].hour1() << F(":") << Timer[1].minute1() << F(":") << Timer[1].second1(); lcd.setCursor(0, 1); lcd << F(" >") << var << F(":") << Timer[1].minute2() << F(":") << Timer[1].second2(); } Btn.Do = [] { Timer[1].writeHour2(var); setPos(ss2); }; JoyUD.Do1 = [] { if (var < 23)var++; setPos(ss2hour2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss2hour2); }; break; //--------------------------------------------------------------------- case ss3: // 3-экран { lcd << F("Timer3:") << Timer[2].hour1() << F(":") << Timer[2].minute1() << F(":") << Timer[2].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[2].hour2() << F(":") << Timer[2].minute2() << F(":") << Timer[2].second2(); } Btn.Do = [] { var = Timer[2].second1(); setPos(ss3sec1); }; JoyUD.Do1 = [] {setPos(ss2); }; JoyUD.Do2 = [] {setPos(ss4); }; break; case ss3sec1:// редакт секунд { lcd << F("Timer3:") << Timer[2].hour1() << F(":") << Timer[2].minute1() << F(">") << var; lcd.setCursor(0, 1); lcd << F(" ") << Timer[2].hour2() << F(":") << Timer[2].minute2() << F(":") << Timer[2].second2(); } Btn.Do = [] { Timer[2].writeSecond1(var); var = Timer[2].minute1(); setPos(ss3min1); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss3sec1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss3sec1); }; break; case ss3min1:// редакт минут { lcd << F("Timer3:") << Timer[2].hour1() << F(">") << var << F(":") << Timer[2].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[2].hour2() << F(":") << Timer[2].minute2() << F(":") << Timer[2].second2(); } Btn.Do = [] { Timer[2].writeMinute1(var); var = Timer[2].hour1(); setPos(ss3hour1); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss3min1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss3min1); }; break; case ss3hour1:// редакт часов { lcd << F("Timer3>") << var << F(":") << Timer[2].minute1() << F(":") << Timer[2].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[2].hour2() << F(":") << Timer[2].minute2() << F(":") << Timer[2].second2(); } Btn.Do = [] { Timer[2].writeHour1(var); var = Timer[2].second2(); setPos(ss3sec2); }; JoyUD.Do1 = [] { if (var < 23)var++; setPos(ss3hour1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss3hour1); }; break; case ss3sec2:// редакт секунд { lcd << F("Timer3:") << Timer[2].hour1() << F(":") << Timer[2].minute1() << F(":") << Timer[2].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[2].hour2() << F(":") << Timer[2].minute2() << F(">") << var; } Btn.Do = [] { Timer[2].writeSecond2(var); var = Timer[2].minute2(); setPos(ss3min2); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss3sec2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss3sec2); }; break; case ss3min2:// редакт минут { lcd << F("Timer3:") << Timer[2].hour1() << F(":") << Timer[2].minute1() << F(":") << Timer[2].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[2].hour2() << F(">") << var << F(":") << Timer[2].second2(); } Btn.Do = [] { Timer[2].writeMinute2(var); var = Timer[2].hour2(); setPos(ss3hour2); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss3min2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss3min2); }; break; case ss3hour2:// редакт часов { lcd << F("Timer3:") << Timer[2].hour1() << F(":") << Timer[2].minute1() << F(":") << Timer[2].second1(); lcd.setCursor(0, 1); lcd << F(" >") << var << F(":") << Timer[2].minute2() << F(":") << Timer[2].second2(); } Btn.Do = [] { Timer[2].writeHour2(var); setPos(ss3); }; JoyUD.Do1 = [] { if (var < 23)var++; setPos(ss3hour2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss3hour2); }; break; //--------------------------------------------------------------------- case ss4: // 4-экран { lcd << F("Timer4:") << Timer[3].hour1() << F(":") << Timer[3].minute1() << F(":") << Timer[3].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[3].hour2() << F(":") << Timer[3].minute2() << F(":") << Timer[3].second2(); } Btn.Do = [] { var = Timer[3].second1(); setPos(ss4sec1); }; JoyUD.Do1 = [] {setPos(ss3); }; JoyUD.Do2 = [] {setPos(ss5); }; break; case ss4sec1: { lcd << F("Timer4:") << Timer[3].hour1() << F(":") << Timer[3].minute1() << F(">") << var; lcd.setCursor(0, 1); lcd << F(" ") << Timer[3].hour2() << F(":") << Timer[3].minute2() << F(":") << Timer[3].second2(); } Btn.Do = [] { Timer[3].writeSecond1(var); var = Timer[3].minute1(); setPos(ss4min1); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss4sec1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss4sec1); }; break; case ss4min1: { lcd << F("Timer4:") << Timer[3].hour1() << F(">") << var << F(":") << Timer[3].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[3].hour2() << F(":") << Timer[3].minute2() << F(":") << Timer[3].second2(); } Btn.Do = [] { Timer[3].writeMinute1(var); var = Timer[3].hour1(); setPos(ss4hour1); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss4min1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss4min1); }; break; case ss4hour1: { lcd << F("Timer4>") << var << F(":") << Timer[3].minute1() << F(":") << Timer[3].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[3].hour2() << F(":") << Timer[3].minute2() << F(":") << Timer[3].second2(); } Btn.Do = [] { Timer[3].writeHour1(var); var = Timer[3].second2(); setPos(ss4sec2); }; JoyUD.Do1 = [] { if (var < 23)var++; setPos(ss4hour1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss4hour1); }; break; case ss4sec2: { lcd << F("Timer4:") << Timer[3].hour1() << F(":") << Timer[3].minute1() << F(":") << Timer[3].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[3].hour2() << F(":") << Timer[3].minute2() << F(">") << var; } Btn.Do = [] { Timer[3].writeSecond2(var); var = Timer[3].minute2(); setPos(ss4min2); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss4sec2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss4sec2); }; break; case ss4min2: { lcd << F("Timer4:") << Timer[3].hour1() << F(":") << Timer[3].minute1() << F(":") << Timer[3].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[3].hour2() << F(">") << var << F(":") << Timer[3].second2(); } Btn.Do = [] { Timer[3].writeMinute2(var); var = Timer[3].hour2(); setPos(ss4hour2); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss4min2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss4min2); }; break; case ss4hour2: { lcd << F("Timer4:") << Timer[3].hour1() << F(":") << Timer[3].minute1() << F(":") << Timer[3].second1(); lcd.setCursor(0, 1); lcd << F(" >") << var << F(":") << Timer[3].minute2() << F(":") << Timer[3].second2(); } Btn.Do = [] { Timer[3].writeHour2(var); setPos(ss4); }; JoyUD.Do1 = [] { if (var < 23)var++; setPos(ss4hour2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss4hour2); }; break; //--------------------------------------------------------------------- case ss5: // 5-экран { lcd << F("Timer5:") << Timer[4].hour1() << F(":") << Timer[4].minute1() << F(":") << Timer[4].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[4].hour2() << F(":") << Timer[4].minute2() << F(":") << Timer[4].second2(); } Btn.Do = [] { var = Timer[4].second1(); setPos(ss5sec1); }; JoyUD.Do1 = [] { setPos(ss4); }; JoyUD.Do2 = [] {}; break; case ss5sec1: { lcd << F("Timer5:") << Timer[4].hour1() << F(":") << Timer[4].minute1() << F(">") << var; lcd.setCursor(0, 1); lcd << F(" ") << Timer[4].hour2() << F(":") << Timer[4].minute2() << F(":") << Timer[4].second2(); } Btn.Do = [] { Timer[4].writeSecond1(var); var = Timer[4].minute1(); setPos(ss5min1); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss5sec1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss5sec1); }; break; case ss5min1: { lcd << F("Timer5:") << Timer[4].hour1() << F(">") << var << F(":") << Timer[4].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[4].hour2() << F(":") << Timer[4].minute2() << F(":") << Timer[4].second2(); } Btn.Do = [] { Timer[4].writeMinute1(var); var = Timer[4].hour1(); setPos(ss5hour1); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss5min1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss5min1); }; break; case ss5hour1: { lcd << F("Timer5>") << var << F(":") << Timer[4].minute1() << F(":") << Timer[4].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[4].hour2() << F(":") << Timer[4].minute2() << F(":") << Timer[4].second2(); } Btn.Do = [] { Timer[4].writeHour1(var); var = Timer[4].second2(); setPos(ss5sec2); }; JoyUD.Do1 = [] { if (var < 23)var++; setPos(ss5hour1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss5hour1); }; break; case ss5sec2: { lcd << F("Timer5:") << Timer[4].hour1() << F(":") << Timer[4].minute1() << F(":") << Timer[4].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[4].hour2() << F(":") << Timer[4].minute2() << F(">") << var; } Btn.Do = [] { Timer[4].writeSecond2(var); var = Timer[4].minute2(); setPos(ss5min2); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss5sec2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss5sec2); }; break; case ss5min2: { lcd << F("Timer5:") << Timer[4].hour1() << F(":") << Timer[4].minute1() << F(":") << Timer[4].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[4].hour2() << F(">") << var << F(":") << Timer[4].second2(); } Btn.Do = [] { Timer[4].writeMinute2(var); var = Timer[4].hour2(); setPos(ss5hour2); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss5min2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss5min2); }; break; case ss5hour2: { lcd << F("Timer5:") << Timer[4].hour1() << F(":") << Timer[4].minute1() << F(":") << Timer[4].second1(); lcd.setCursor(0, 1); lcd << F(" >") << var << F(":") << Timer[4].minute2() << F(":") << Timer[4].second2(); } Btn.Do = [] { Timer[4].writeHour2(var); setPos(ss5); }; JoyUD.Do1 = [] { if (var < 23)var++; setPos(ss5hour2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss5hour2); }; break; } } void menuInit() { lcd.begin(16, 2); setPos(sMain); } void menuRun() { if (pos != sMain && millis() - past >= 10000)setPos(sMain); if (pos == sMain && millis() - past >= 1000)setPos(sMain); } //---------------------------------- void setup() { saveZeroSettings(); for (int i = 0; i < numTimer; i++) Timer[i].init(); lcd.init(); Btn.init(); JoyLR.init(); JoyUD.init(); menuInit(); JoyLR.Do1 = [] {lcd.backlight();}; JoyLR.Do2 = [] {lcd.noBacklight();}; } void loop() { for (int i = 0; i < numTimer; i++) Timer[i].run(); Btn.run(); JoyLR.run(); JoyUD.run(); menuRun(); } /**/Моя упрощенная библиотека для работы с lcd1602 i2c
/**/ template <typename T> inline Print & operator << (Print &s, T n) { s.print(n); return s; } //------дисплей lcd1602_i2c----------------------------- // даташит https://www.sparkfun.com/datasheets/LCD/ADM1602K-NSW-FBS-3.3v.pdf // на русском http://www.melt.aha.ru/pdf/mt-16s2h.pdf #include <Wire.h> // команды #define LCD_CLEARDISPLAY 0x01 #define LCD_RETURNHOME 0x02 #define LCD_ENTRYMODESET 0x04 #define LCD_DISPLAYCONTROL 0x08 #define LCD_CURSORSHIFT 0x10 #define LCD_FUNCTIONSET 0x20 #define LCD_SETCGRAMADDR 0x40 #define LCD_SETDDRAMADDR 0x80 // флаги для режима ввода дисплея #define LCD_ENTRYRIGHT 0x00 #define LCD_ENTRYLEFT 0x02 #define LCD_ENTRYSHIFTINCREMENT 0x01 #define LCD_ENTRYSHIFTDECREMENT 0x00 // флаги для управления включением / выключением дисплея #define LCD_DISPLAYON 0x04 #define LCD_DISPLAYOFF 0x00 #define LCD_CURSORON 0x02 #define LCD_CURSOROFF 0x00 #define LCD_BLINKON 0x01 #define LCD_BLINKOFF 0x00 // флаги для отображения / сдвига курсора #define LCD_DISPLAYMOVE 0x08 #define LCD_CURSORMOVE 0x00 #define LCD_MOVERIGHT 0x04 #define LCD_MOVELEFT 0x00 // флаги для набора функций #define LCD_8BITMODE 0x10 #define LCD_4BITMODE 0x00 #define LCD_2LINE 0x08 #define LCD_1LINE 0x00 #define LCD_5x10DOTS 0x04 #define LCD_5x8DOTS 0x00 // флаги для управления подсветкой #define LCD_BACKLIGHT 0x08 #define LCD_NOBACKLIGHT 0x00 #define En B00000100 // Бит разрешения #define Rw B00000010 // Чтение / запись бит #define Rs B00000001 // Бит выбора регистра class Cl_lcd1602_i2c : public Print { protected: uint8_t adr, posX, posY; uint8_t _backlightval; uint8_t _displayfunction; uint8_t _displaycontrol; uint8_t _displaymode; byte buffer[32]; public: Cl_lcd1602_i2c(uint8_t a): adr(a) {} void init() { Wire.begin(); write4bits(0x03 << 4); delayMicroseconds(4500); // wait min 4.1ms write4bits(0x03 << 4); delayMicroseconds(4500); // wait min 4.1ms write4bits(0x03 << 4); delayMicroseconds(150); write4bits(0x02 << 4); delay(50); _backlightval = LCD_NOBACKLIGHT; expanderWrite(_backlightval); // сбросить расширение и выключить подсветку (бит 8 = 1) // режим работы дисплея 4-х битный интерфейс ,две строки,5х8 точек _displayfunction = LCD_4BITMODE | LCD_2LINE | LCD_5x8DOTS; command(LCD_FUNCTIONSET | _displayfunction); // режим контроля дисплей вкл, курсор не мигает,дисплей не мигает _displaycontrol = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF; command(LCD_DISPLAYCONTROL | _displaycontrol); // режим ввода текста в память-начинать слева с движением в право _displaymode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT; command(LCD_ENTRYMODESET | _displaymode); clear(); } // подсветку вкл/выкл void backlight(void) { _backlightval = LCD_BACKLIGHT; expanderWrite(0); } void noBacklight(void) { _backlightval = LCD_NOBACKLIGHT; expanderWrite(0); } // очистить буфер void clear() { for (byte i = 0; i < 32; i++ )buffer[i] = 0x20; posX = 0; posY = 0; } // отправить информацию из буфера на экран void show() { line(0); for (byte i = 0; i < 16; i++ )out(buffer[i]); line(1); for (byte i = 16; i < 32; i++ )out(buffer[i]); } void setCursor(byte x, byte y) { if (x > 16) x = 16; else posX = x; if (y > 2) x = 2; else posY = y; } private: /*внутрение функции*/ void line(byte l) { if (l == 0) command(LCD_SETDDRAMADDR | 0x00); else command(LCD_SETDDRAMADDR | 0x40); } inline void out(uint8_t value) { send(value, Rs); } inline size_t write(uint8_t value) { if (posX < 16 && posY < 2) { buffer[posY * 16 + posX] = value; posX++; } return 1; } /*команды низкоуровневого управления*/ inline void command(uint8_t value) { send(value, 0); } void send(uint8_t value, uint8_t mode) { uint8_t highnib = value & 0xf0; write4bits((highnib) | mode); uint8_t lownib = (value << 4) & 0xf0; write4bits((lownib) | mode); } void write4bits(uint8_t value) { expanderWrite(value); pulseEnable(value); } void expanderWrite(uint8_t _data) { Wire.beginTransmission(adr); Wire.write((int)(_data) | _backlightval); Wire.endTransmission(); } void pulseEnable(uint8_t _data) { expanderWrite(_data | En); // En high delayMicroseconds(1); // enable pulse must be >450ns expanderWrite(_data & ~En); // En low delayMicroseconds(50); // commands need > 37us to settle } }; Cl_lcd1602_i2c lcd(0x27); //-------------------------------------------------- void setup() { lcd.init(); lcd.backlight(); lcd.clear(); lcd.setCursor(5, 0); lcd << F("ABCD"); lcd.setCursor(8, 1); lcd << F("EFGH"); lcd.show(); } void loop() { } /**/Я планирую позже использовать ее,так как она уменьшает мигание дисплея.
И вот с этой библиотекой код. И да если вы будете ее использовать,то не забывайте использовать команды clear() -очистка буфера и show()- отправка этого буфера в память дисплея
/**/ unsigned long now ;// количество секунд прошедшее после вкл //---------------lcd--------------------------------------------- template <typename T> inline Print & operator << (Print &s, T n) { s.print(n); return s; } //------дисплей lcd1602_i2c----------------------------- // даташит https://www.sparkfun.com/datasheets/LCD/ADM1602K-NSW-FBS-3.3v.pdf // на русском http://www.melt.aha.ru/pdf/mt-16s2h.pdf #include <Wire.h> // команды #define LCD_CLEARDISPLAY 0x01 #define LCD_RETURNHOME 0x02 #define LCD_ENTRYMODESET 0x04 #define LCD_DISPLAYCONTROL 0x08 #define LCD_CURSORSHIFT 0x10 #define LCD_FUNCTIONSET 0x20 #define LCD_SETCGRAMADDR 0x40 #define LCD_SETDDRAMADDR 0x80 // флаги для режима ввода дисплея #define LCD_ENTRYRIGHT 0x00 #define LCD_ENTRYLEFT 0x02 #define LCD_ENTRYSHIFTINCREMENT 0x01 #define LCD_ENTRYSHIFTDECREMENT 0x00 // флаги для управления включением / выключением дисплея #define LCD_DISPLAYON 0x04 #define LCD_DISPLAYOFF 0x00 #define LCD_CURSORON 0x02 #define LCD_CURSOROFF 0x00 #define LCD_BLINKON 0x01 #define LCD_BLINKOFF 0x00 // флаги для отображения / сдвига курсора #define LCD_DISPLAYMOVE 0x08 #define LCD_CURSORMOVE 0x00 #define LCD_MOVERIGHT 0x04 #define LCD_MOVELEFT 0x00 // флаги для набора функций #define LCD_8BITMODE 0x10 #define LCD_4BITMODE 0x00 #define LCD_2LINE 0x08 #define LCD_1LINE 0x00 #define LCD_5x10DOTS 0x04 #define LCD_5x8DOTS 0x00 // флаги для управления подсветкой #define LCD_BACKLIGHT 0x08 #define LCD_NOBACKLIGHT 0x00 #define En B00000100 // Бит разрешения #define Rw B00000010 // Чтение / запись бит #define Rs B00000001 // Бит выбора регистра class Cl_lcd1602_i2c : public Print { protected: uint8_t adr, posX, posY; uint8_t _backlightval; uint8_t _displayfunction; uint8_t _displaycontrol; uint8_t _displaymode; byte buffer[32]; public: Cl_lcd1602_i2c(uint8_t a): adr(a) {} void init() { Wire.begin(); write4bits(0x03 << 4); delayMicroseconds(4500); // wait min 4.1ms write4bits(0x03 << 4); delayMicroseconds(4500); // wait min 4.1ms write4bits(0x03 << 4); delayMicroseconds(150); write4bits(0x02 << 4); delay(50); _backlightval = LCD_NOBACKLIGHT; expanderWrite(_backlightval); // сбросить расширение и выключить подсветку (бит 8 = 1) // режим работы дисплея 4-х битный интерфейс ,две строки,5х8 точек _displayfunction = LCD_4BITMODE | LCD_2LINE | LCD_5x8DOTS; command(LCD_FUNCTIONSET | _displayfunction); // режим контроля дисплей вкл, курсор не мигает,дисплей не мигает _displaycontrol = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF; command(LCD_DISPLAYCONTROL | _displaycontrol); // режим ввода текста в память-начинать слева с движением в право _displaymode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT; command(LCD_ENTRYMODESET | _displaymode); clear(); } // подсветку вкл/выкл void backlight(void) { _backlightval = LCD_BACKLIGHT; expanderWrite(0); } void noBacklight(void) { _backlightval = LCD_NOBACKLIGHT; expanderWrite(0); } // очистить буфер void clear() { for (byte i = 0; i < 32; i++ )buffer[i] = 0x20; posX = 0; posY = 0; } // отправить информацию из буфера на экран void show() { line(0); for (byte i = 0; i < 16; i++ )out(buffer[i]); line(1); for (byte i = 16; i < 32; i++ )out(buffer[i]); } void setCursor(byte x, byte y) { if (x > 16) x = 16; else posX = x; if (y > 2) x = 2; else posY = y; } private: /*внутрение функции*/ void line(byte l) { if (l == 0) command(LCD_SETDDRAMADDR | 0x00); else command(LCD_SETDDRAMADDR | 0x40); } inline void out(uint8_t value) { send(value, Rs); } inline size_t write(uint8_t value) { if (posX < 16 && posY < 2) { buffer[posY * 16 + posX] = value; posX++; } return 1; } /*команды низкоуровневого управления*/ inline void command(uint8_t value) { send(value, 0); } void send(uint8_t value, uint8_t mode) { uint8_t highnib = value & 0xf0; write4bits((highnib) | mode); uint8_t lownib = (value << 4) & 0xf0; write4bits((lownib) | mode); } void write4bits(uint8_t value) { expanderWrite(value); pulseEnable(value); } void expanderWrite(uint8_t _data) { Wire.beginTransmission(adr); Wire.write((int)(_data) | _backlightval); Wire.endTransmission(); } void pulseEnable(uint8_t _data) { expanderWrite(_data | En); // En high delayMicroseconds(1); // enable pulse must be >450ns expanderWrite(_data & ~En); // En low delayMicroseconds(50); // commands need > 37us to settle } }; Cl_lcd1602_i2c lcd(0x27); // -------------таймеры------------------------------------------------ typedef struct { byte hour; byte minute; byte second; } timer_t; const byte numTimer = 5; timer_t EEMEM adr1[numTimer]; // первичные настройки в EEPROM void saveZeroSettings() { timer_t data[numTimer * 2] = { // начальные настройки {0, 0, 30}, {0, 3, 00}, // 1-й таймер {0, 1, 00}, {0, 3, 30}, // 2-й таймер {0, 1, 30}, {0, 4, 00}, // 3-й таймер {0, 2, 00}, {0, 4, 30}, // 4-й таймер {0, 2, 30}, {0, 5, 00} // 5-й таймер }; for (int i = 0; i < numTimer * 2; ++i) { eeprom_write_byte(&adr1[i].hour , data[i].hour); eeprom_write_byte(&adr1[i].minute, data[i].minute); eeprom_write_byte(&adr1[i].second, data[i].second); } } /*состояния таймера*/ const byte sOFF = 0; const byte sON = 1; const byte sEND = 2; class Cl_Timer { private: timer_t *adr1, *adr2; byte pin; byte stat;// состояние unsigned long past; void setStat(byte s) { stat = s; past = millis(); switch (s) { case sOFF: digitalWrite(pin, HIGH); break; case sON: digitalWrite(pin, LOW); break; case sEND: digitalWrite(pin, HIGH); break; } } public: Cl_Timer(byte p, timer_t * a1, timer_t * a2) : adr1(a1), adr2(a2), pin(p) {} void init() { pinMode(pin, OUTPUT); setStat(sOFF); } void run() { if (millis() - past >= 100) { switch (stat) { case sOFF: if (now >= ((unsigned long)hour1() * 24 + minute1()) * 60 + second1())setStat(sON); else setStat(sOFF); break; case sON: if (now >= ((unsigned long)hour2() * 24 + minute2()) * 60 + second2())setStat(sEND); else setStat(sON); break; case sEND: setStat(sEND); break; } } } void state() { switch (stat) { case sOFF: lcd << F("OFF"); break; case sON: lcd << F("ON "); break; case sEND: lcd << F("END"); break; } } byte hour1() { return eeprom_read_byte(&(adr1->hour)); } byte minute1() { return eeprom_read_byte(&(adr1->minute)); } byte second1() { return eeprom_read_byte(&(adr1->second)); } void writeHour1(byte data) { eeprom_write_byte(&(adr1->hour), data); } void writeMinute1(byte data) { eeprom_write_byte(&(adr1->minute), data); } void writeSecond1(byte data) { eeprom_write_byte(&(adr1->second), data); } byte hour2() { return eeprom_read_byte(&(adr2->hour)); } byte minute2() { return eeprom_read_byte(&(adr2->minute)); } byte second2() { return eeprom_read_byte(&(adr2->second)); } void writeHour2(byte data) { eeprom_write_byte(&(adr2->hour), data); } void writeMinute2(byte data) { eeprom_write_byte(&(adr2->minute), data); } void writeSecond2(byte data) { eeprom_write_byte(&(adr2->second), data); } }; Cl_Timer Timer[numTimer] = { Cl_Timer(/*пин*/2, &adr1[0], &adr1[1]), // 1-й таймер Cl_Timer(/*пин*/3, &adr1[2], &adr1[3]), // 2-й таймер Cl_Timer(/*пин*/4, &adr1[4], &adr1[5]), // 3-й таймер Cl_Timer(/*пин*/5, &adr1[6], &adr1[7]), // 4-й таймер Cl_Timer(/*пин*/6, &adr1[8], &adr1[9]) // 5-й таймер }; //---кнопкa----------------------------- typedef void (*pDo)(); class Cl_btn { protected: byte pin; bool state; unsigned long past; void set(bool s) { state = s; past = millis(); switch (s) { case false: break; case true: Do(); break; } } public: Cl_btn(byte p): pin(p) {} pDo Do = [] {}; void init() { pinMode(pin, INPUT_PULLUP); set(false); } void run() { if (millis() - past >= 100) switch (state) { case false: if (!digitalRead(pin))set(true); break; case true: if (digitalRead(pin))set(false); if (millis() - past >= 300)set(false); break; } } }; Cl_btn Btn(/*пин*/A0); //------------------------------------------- const byte st1 = 0; const byte st0 = 1; const byte st2 = 2; class Cl_joystic { protected: byte pin; byte state; unsigned long past; void set(byte s) { state = s; past = millis(); switch (s) { case st0: break; case st1: Do1(); break; case st2: Do2(); break; } } public: Cl_joystic(byte p): pin(p) {} pDo Do1 = [] {}; pDo Do2 = [] {}; void init() { set(st0); } void run() { if (millis() - past >= 100) { int tmp = analogRead(pin); switch (state) { case st1: if (tmp > 450)set(st0); if (millis() - past >= 300)set(st0); break; case st0: if (tmp < 400)set(st1); else if (tmp > 600)set(st2); break; case st2: if (tmp < 550)set(st0); if (millis() - past >= 300)set(st0); break; } } } }; Cl_joystic JoyLR(/*пин*/A1); Cl_joystic JoyUD(/*пин*/A2); //--------------- меню--------------------------------------------- byte var; // некая вспомогательная переменная const byte sMain = 0;// главный экран const byte ss1 = 1;// 1-экран const byte ss1sec1 = 2;// редактирование 1 const byte ss1min1 = 3;// редактирование 2 const byte ss1hour1 = 4;// редактирование 3 const byte ss1sec2 = 5;// редактирование 1 const byte ss1min2 = 6;// редактирование 2 const byte ss1hour2 = 7;// редактирование 3 const byte ss2 = 11;// 2-экран const byte ss2sec1 = 12;// редактирование 1 const byte ss2min1 = 13;// редактирование 2 const byte ss2hour1 = 14;// редактирование 3 const byte ss2sec2 = 15;// редактирование 1 const byte ss2min2 = 16;// редактирование 2 const byte ss2hour2 = 17;// редактирование 3 const byte ss3 = 21;// 3-экран const byte ss3sec1 = 22;// редактирование 1 const byte ss3min1 = 23;// редактирование 2 const byte ss3hour1 = 24;// редактирование 3 const byte ss3sec2 = 25;// редактирование 1 const byte ss3min2 = 26;// редактирование 2 const byte ss3hour2 = 27;// редактирование 3 const byte ss4 = 31;// 4-экран const byte ss4sec1 = 32;// редактирование 1 const byte ss4min1 = 33;// редактирование 2 const byte ss4hour1 = 34;// редактирование 3 const byte ss4sec2 = 35;// редактирование 1 const byte ss4min2 = 36;// редактирование 2 const byte ss4hour2 = 37;// редактирование 3 const byte ss5 = 41;// 5-экран const byte ss5sec1 = 42;// редактирование 1 const byte ss5min1 = 43;// редактирование 2 const byte ss5hour1 = 44;// редактирование 3 const byte ss5sec2 = 45;// редактирование 1 const byte ss5min2 = 46;// редактирование 2 const byte ss5hour2 = 47;// редактирование 3 byte pos; unsigned long past; void setPos(byte p) { pos = p; past = millis(); lcd.clear(); switch (p) { case sMain:// главный экран { now = millis() / 1000; int hour = now / 60 / 60 % 24 ; int minute = now / 60 % 60; int second = now % 60; lcd << hour << F(":") << minute << F(":") << second; lcd.setCursor(9, 0); Timer[0].state(); lcd << F(" "); Timer[1].state(); lcd << F(" "); lcd.setCursor(5, 1); Timer[2].state(); lcd << F(" "); Timer[3].state(); lcd << F(" "); Timer[4].state(); lcd << F(" "); lcd.show(); } Btn.Do = [] {}; JoyUD.Do1 = [] { }; JoyUD.Do2 = [] {setPos(ss1); }; break; case ss1: // 1-экран { lcd << F("Timer1:") << Timer[0].hour1() << F(":") << Timer[0].minute1() << F(":") << Timer[0].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[0].hour2() << F(":") << Timer[0].minute2() << F(":") << Timer[0].second2(); lcd.show(); } Btn.Do = [] { var = Timer[0].second1(); setPos(ss1sec1); }; JoyUD.Do1 = [] {setPos(sMain); }; JoyUD.Do2 = [] {setPos(ss2); }; break; case ss1sec1:// редактирование секунд { lcd << F("Timer1:") << Timer[0].hour1() << F(":") << Timer[0].minute1() << F(">") << var; lcd.setCursor(0, 1); lcd << F(" ") << Timer[0].hour2() << F(":") << Timer[0].minute2() << F(":") << Timer[0].second2(); lcd.show(); } Btn.Do = [] { Timer[0].writeSecond1(var); var = Timer[0].minute1(); setPos(ss1min1); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss1sec1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss1sec1); }; break; case ss1min1:// редактирование минут { lcd << F("Timer1:") << Timer[0].hour1() << F(">") << var << F(":") << Timer[0].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[0].hour2() << F(":") << Timer[0].minute2() << F(":") << Timer[0].second2(); lcd.show(); } Btn.Do = [] { Timer[0].writeMinute1(var); var = Timer[0].hour1(); setPos(ss1hour1); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss1min1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss1min1); }; break; case ss1hour1:// редактирование часов { lcd << F("Timer1>") << var << F(":") << Timer[0].minute1() << F(":") << Timer[0].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[0].hour2() << F(":") << Timer[0].minute2() << F(":") << Timer[0].second2(); lcd.show(); } Btn.Do = [] { Timer[0].writeHour1(var); setPos(ss1sec2); }; JoyUD.Do1 = [] { if (var < 23)var++; setPos(ss1hour1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss1hour1); }; break; case ss1sec2:// редактирование секунд { lcd << F("Timer1:") << Timer[0].hour1() << F(":") << Timer[0].minute1() << F(":") << Timer[0].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[0].hour2() << F(":") << Timer[0].minute2() << F(">") << var; lcd.show(); } Btn.Do = [] { Timer[0].writeSecond2(var); var = Timer[0].minute2(); setPos(ss1min2); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss1sec2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss1sec2); }; break; case ss1min2:// редактирование минут { lcd << F("Timer1:") << Timer[0].hour1() << F(":") << Timer[0].minute1() << F(":") << Timer[0].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[0].hour2() << F(">") << var << F(":") << Timer[0].second2(); lcd.show(); } Btn.Do = [] { Timer[0].writeMinute2(var); var = Timer[0].hour2(); setPos(ss1hour2); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss1min2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss1min2); }; break; case ss1hour2:// редактирование часов { lcd << F("Timer1:") << Timer[0].hour1() << F(":") << Timer[0].minute1() << F(":") << Timer[0].second1(); lcd.setCursor(0, 1); lcd << F(" >") << var << F(":") << Timer[0].minute2() << F(":") << Timer[0].second2(); lcd.show(); } Btn.Do = [] { Timer[0].writeHour2(var); setPos(ss1); }; JoyUD.Do1 = [] { if (var < 23)var++; setPos(ss1hour2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss1hour2); }; break; //--------------------------------------------------------------------- case ss2: // 2-экран { lcd << F("Timer2:") << Timer[1].hour1() << F(":") << Timer[1].minute1() << F(":") << Timer[1].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[1].hour2() << F(":") << Timer[1].minute2() << F(":") << Timer[1].second2(); lcd.show(); } Btn.Do = [] { var = Timer[1].second1(); setPos(ss2sec1); }; JoyUD.Do1 = [] {setPos(ss1); }; JoyUD.Do2 = [] {setPos(ss3); }; break; case ss2sec1: { lcd << F("Timer2:") << Timer[1].hour1() << F(":") << Timer[1].minute1() << F(">") << var; lcd.setCursor(0, 1); lcd << F(" ") << Timer[1].hour2() << F(":") << Timer[1].minute2() << F(":") << Timer[1].second2(); lcd.show(); } Btn.Do = [] { Timer[1].writeSecond1(var); var = Timer[1].minute1(); setPos(ss2min1); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss2sec1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss2sec1); }; break; case ss2min1: { lcd << F("Timer2:") << Timer[1].hour1() << F(">") << var << F(":") << Timer[1].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[1].hour2() << F(":") << Timer[1].minute2() << F(":") << Timer[1].second2(); lcd.show(); } Btn.Do = [] { Timer[1].writeMinute1(var); var = Timer[1].hour1(); setPos(ss2hour1); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss2min1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss2min1); }; break; case ss2hour1: { lcd << F("Timer2>") << var << F(":") << Timer[1].minute1() << F(":") << Timer[1].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[1].hour2() << F(":") << Timer[1].minute2() << F(":") << Timer[1].second2(); lcd.show(); } Btn.Do = [] { Timer[1].writeHour1(var); var = Timer[1].second2(); setPos(ss2sec2); }; JoyUD.Do1 = [] { if (var < 23)var++; setPos(ss2hour1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss2hour1); }; break; case ss2sec2: { lcd << F("Timer2:") << Timer[1].hour1() << F(":") << Timer[1].minute1() << F(":") << Timer[1].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[1].hour2() << F(":") << Timer[1].minute2() << F(">") << var; lcd.show(); } Btn.Do = [] { Timer[1].writeSecond2(var); var = Timer[1].minute2(); setPos(ss2min2); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss2sec2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss2sec2); }; break; case ss2min2: { lcd << F("Timer2:") << Timer[1].hour1() << F(":") << Timer[1].minute1() << F(":") << Timer[1].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[1].hour2() << F(">") << var << F(":") << Timer[1].second2(); lcd.show(); } Btn.Do = [] { Timer[1].writeMinute2(var); var = Timer[1].hour2(); setPos(ss2hour2); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss2min2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss2min2); }; break; case ss2hour2: { lcd << F("Timer2:") << Timer[1].hour1() << F(":") << Timer[1].minute1() << F(":") << Timer[1].second1(); lcd.setCursor(0, 1); lcd << F(" >") << var << F(":") << Timer[1].minute2() << F(":") << Timer[1].second2(); lcd.show(); } Btn.Do = [] { Timer[1].writeHour2(var); setPos(ss2); }; JoyUD.Do1 = [] { if (var < 23)var++; setPos(ss2hour2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss2hour2); }; break; //--------------------------------------------------------------------- case ss3: // 3-экран { lcd << F("Timer3:") << Timer[2].hour1() << F(":") << Timer[2].minute1() << F(":") << Timer[2].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[2].hour2() << F(":") << Timer[2].minute2() << F(":") << Timer[2].second2(); lcd.show(); } Btn.Do = [] { var = Timer[2].second1(); setPos(ss3sec1); }; JoyUD.Do1 = [] {setPos(ss2); }; JoyUD.Do2 = [] {setPos(ss4); }; break; case ss3sec1:// редакт секунд { lcd << F("Timer3:") << Timer[2].hour1() << F(":") << Timer[2].minute1() << F(">") << var; lcd.setCursor(0, 1); lcd << F(" ") << Timer[2].hour2() << F(":") << Timer[2].minute2() << F(":") << Timer[2].second2(); lcd.show(); } Btn.Do = [] { Timer[2].writeSecond1(var); var = Timer[2].minute1(); setPos(ss3min1); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss3sec1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss3sec1); }; break; case ss3min1:// редакт минут { lcd << F("Timer3:") << Timer[2].hour1() << F(">") << var << F(":") << Timer[2].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[2].hour2() << F(":") << Timer[2].minute2() << F(":") << Timer[2].second2(); lcd.show(); } Btn.Do = [] { Timer[2].writeMinute1(var); var = Timer[2].hour1(); setPos(ss3hour1); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss3min1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss3min1); }; break; case ss3hour1:// редакт часов { lcd << F("Timer3>") << var << F(":") << Timer[2].minute1() << F(":") << Timer[2].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[2].hour2() << F(":") << Timer[2].minute2() << F(":") << Timer[2].second2(); lcd.show(); } Btn.Do = [] { Timer[2].writeHour1(var); var = Timer[2].second2(); setPos(ss3sec2); }; JoyUD.Do1 = [] { if (var < 23)var++; setPos(ss3hour1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss3hour1); }; break; case ss3sec2:// редакт секунд { lcd << F("Timer3:") << Timer[2].hour1() << F(":") << Timer[2].minute1() << F(":") << Timer[2].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[2].hour2() << F(":") << Timer[2].minute2() << F(">") << var; lcd.show(); } Btn.Do = [] { Timer[2].writeSecond2(var); var = Timer[2].minute2(); setPos(ss3min2); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss3sec2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss3sec2); }; break; case ss3min2:// редакт минут { lcd << F("Timer3:") << Timer[2].hour1() << F(":") << Timer[2].minute1() << F(":") << Timer[2].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[2].hour2() << F(">") << var << F(":") << Timer[2].second2(); lcd.show(); } Btn.Do = [] { Timer[2].writeMinute2(var); var = Timer[2].hour2(); setPos(ss3hour2); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss3min2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss3min2); }; break; case ss3hour2:// редакт часов { lcd << F("Timer3:") << Timer[2].hour1() << F(":") << Timer[2].minute1() << F(":") << Timer[2].second1(); lcd.setCursor(0, 1); lcd << F(" >") << var << F(":") << Timer[2].minute2() << F(":") << Timer[2].second2(); lcd.show(); } Btn.Do = [] { Timer[2].writeHour2(var); setPos(ss3); }; JoyUD.Do1 = [] { if (var < 23)var++; setPos(ss3hour2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss3hour2); }; break; //--------------------------------------------------------------------- case ss4: // 4-экран { lcd << F("Timer4:") << Timer[3].hour1() << F(":") << Timer[3].minute1() << F(":") << Timer[3].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[3].hour2() << F(":") << Timer[3].minute2() << F(":") << Timer[3].second2(); lcd.show(); } Btn.Do = [] { var = Timer[3].second1(); setPos(ss4sec1); }; JoyUD.Do1 = [] {setPos(ss3); }; JoyUD.Do2 = [] {setPos(ss5); }; break; case ss4sec1: { lcd << F("Timer4:") << Timer[3].hour1() << F(":") << Timer[3].minute1() << F(">") << var; lcd.setCursor(0, 1); lcd << F(" ") << Timer[3].hour2() << F(":") << Timer[3].minute2() << F(":") << Timer[3].second2(); lcd.show(); } Btn.Do = [] { Timer[3].writeSecond1(var); var = Timer[3].minute1(); setPos(ss4min1); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss4sec1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss4sec1); }; break; case ss4min1: { lcd << F("Timer4:") << Timer[3].hour1() << F(">") << var << F(":") << Timer[3].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[3].hour2() << F(":") << Timer[3].minute2() << F(":") << Timer[3].second2(); lcd.show(); } Btn.Do = [] { Timer[3].writeMinute1(var); var = Timer[3].hour1(); setPos(ss4hour1); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss4min1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss4min1); }; break; case ss4hour1: { lcd << F("Timer4>") << var << F(":") << Timer[3].minute1() << F(":") << Timer[3].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[3].hour2() << F(":") << Timer[3].minute2() << F(":") << Timer[3].second2(); lcd.show(); } Btn.Do = [] { Timer[3].writeHour1(var); var = Timer[3].second2(); setPos(ss4sec2); }; JoyUD.Do1 = [] { if (var < 23)var++; setPos(ss4hour1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss4hour1); }; break; case ss4sec2: { lcd << F("Timer4:") << Timer[3].hour1() << F(":") << Timer[3].minute1() << F(":") << Timer[3].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[3].hour2() << F(":") << Timer[3].minute2() << F(">") << var; lcd.show(); } Btn.Do = [] { Timer[3].writeSecond2(var); var = Timer[3].minute2(); setPos(ss4min2); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss4sec2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss4sec2); }; break; case ss4min2: { lcd << F("Timer4:") << Timer[3].hour1() << F(":") << Timer[3].minute1() << F(":") << Timer[3].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[3].hour2() << F(">") << var << F(":") << Timer[3].second2(); lcd.show(); } Btn.Do = [] { Timer[3].writeMinute2(var); var = Timer[3].hour2(); setPos(ss4hour2); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss4min2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss4min2); }; break; case ss4hour2: { lcd << F("Timer4:") << Timer[3].hour1() << F(":") << Timer[3].minute1() << F(":") << Timer[3].second1(); lcd.setCursor(0, 1); lcd << F(" >") << var << F(":") << Timer[3].minute2() << F(":") << Timer[3].second2(); lcd.show(); } Btn.Do = [] { Timer[3].writeHour2(var); setPos(ss4); }; JoyUD.Do1 = [] { if (var < 23)var++; setPos(ss4hour2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss4hour2); }; break; //--------------------------------------------------------------------- case ss5: // 5-экран { lcd << F("Timer5:") << Timer[4].hour1() << F(":") << Timer[4].minute1() << F(":") << Timer[4].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[4].hour2() << F(":") << Timer[4].minute2() << F(":") << Timer[4].second2(); lcd.show(); } Btn.Do = [] { var = Timer[4].second1(); setPos(ss5sec1); }; JoyUD.Do1 = [] { setPos(ss4); }; JoyUD.Do2 = [] {}; break; case ss5sec1: { lcd << F("Timer5:") << Timer[4].hour1() << F(":") << Timer[4].minute1() << F(">") << var; lcd.setCursor(0, 1); lcd << F(" ") << Timer[4].hour2() << F(":") << Timer[4].minute2() << F(":") << Timer[4].second2(); lcd.show(); } Btn.Do = [] { Timer[4].writeSecond1(var); var = Timer[4].minute1(); setPos(ss5min1); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss5sec1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss5sec1); }; break; case ss5min1: { lcd << F("Timer5:") << Timer[4].hour1() << F(">") << var << F(":") << Timer[4].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[4].hour2() << F(":") << Timer[4].minute2() << F(":") << Timer[4].second2(); lcd.show(); } Btn.Do = [] { Timer[4].writeMinute1(var); var = Timer[4].hour1(); setPos(ss5hour1); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss5min1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss5min1); }; break; case ss5hour1: { lcd << F("Timer5>") << var << F(":") << Timer[4].minute1() << F(":") << Timer[4].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[4].hour2() << F(":") << Timer[4].minute2() << F(":") << Timer[4].second2(); lcd.show(); } Btn.Do = [] { Timer[4].writeHour1(var); var = Timer[4].second2(); setPos(ss5sec2); }; JoyUD.Do1 = [] { if (var < 23)var++; setPos(ss5hour1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss5hour1); }; break; case ss5sec2: { lcd << F("Timer5:") << Timer[4].hour1() << F(":") << Timer[4].minute1() << F(":") << Timer[4].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[4].hour2() << F(":") << Timer[4].minute2() << F(">") << var; lcd.show(); } Btn.Do = [] { Timer[4].writeSecond2(var); var = Timer[4].minute2(); setPos(ss5min2); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss5sec2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss5sec2); }; break; case ss5min2: { lcd << F("Timer5:") << Timer[4].hour1() << F(":") << Timer[4].minute1() << F(":") << Timer[4].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[4].hour2() << F(">") << var << F(":") << Timer[4].second2(); lcd.show(); } Btn.Do = [] { Timer[4].writeMinute2(var); var = Timer[4].hour2(); setPos(ss5hour2); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss5min2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss5min2); }; break; case ss5hour2: { lcd << F("Timer5:") << Timer[4].hour1() << F(":") << Timer[4].minute1() << F(":") << Timer[4].second1(); lcd.setCursor(0, 1); lcd << F(" >") << var << F(":") << Timer[4].minute2() << F(":") << Timer[4].second2(); lcd.show(); } Btn.Do = [] { Timer[4].writeHour2(var); setPos(ss5); }; JoyUD.Do1 = [] { if (var < 23)var++; setPos(ss5hour2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss5hour2); }; break; } } void menuInit() { setPos(sMain); } void menuRun() { if (pos != sMain && millis() - past >= 10000)setPos(sMain); if (pos == sMain && millis() - past >= 1000)setPos(sMain); } //---------------------------------- void setup() { saveZeroSettings(); for (int i = 0; i < numTimer; i++) Timer[i].init(); lcd.init(); Btn.init(); JoyLR.init(); JoyUD.init(); menuInit(); JoyLR.Do1 = [] {lcd.backlight();}; JoyLR.Do2 = [] {lcd.noBacklight();}; } void loop() { for (int i = 0; i < numTimer; i++) Timer[i].run(); Btn.run(); JoyLR.run(); JoyUD.run(); menuRun(); } /**/добавил класс- millis-часы(не полный)
/**/ //---------------lcd--------------------------------------------- template <typename T> inline Print & operator << (Print &s, T n) { s.print(n); return s; } //------дисплей lcd1602_i2c----------------------------- // даташит https://www.sparkfun.com/datasheets/LCD/ADM1602K-NSW-FBS-3.3v.pdf // на русском http://www.melt.aha.ru/pdf/mt-16s2h.pdf #include <Wire.h> // команды #define LCD_CLEARDISPLAY 0x01 #define LCD_RETURNHOME 0x02 #define LCD_ENTRYMODESET 0x04 #define LCD_DISPLAYCONTROL 0x08 #define LCD_CURSORSHIFT 0x10 #define LCD_FUNCTIONSET 0x20 #define LCD_SETCGRAMADDR 0x40 #define LCD_SETDDRAMADDR 0x80 // флаги для режима ввода дисплея #define LCD_ENTRYRIGHT 0x00 #define LCD_ENTRYLEFT 0x02 #define LCD_ENTRYSHIFTINCREMENT 0x01 #define LCD_ENTRYSHIFTDECREMENT 0x00 // флаги для управления включением / выключением дисплея #define LCD_DISPLAYON 0x04 #define LCD_DISPLAYOFF 0x00 #define LCD_CURSORON 0x02 #define LCD_CURSOROFF 0x00 #define LCD_BLINKON 0x01 #define LCD_BLINKOFF 0x00 // флаги для отображения / сдвига курсора #define LCD_DISPLAYMOVE 0x08 #define LCD_CURSORMOVE 0x00 #define LCD_MOVERIGHT 0x04 #define LCD_MOVELEFT 0x00 // флаги для набора функций #define LCD_8BITMODE 0x10 #define LCD_4BITMODE 0x00 #define LCD_2LINE 0x08 #define LCD_1LINE 0x00 #define LCD_5x10DOTS 0x04 #define LCD_5x8DOTS 0x00 // флаги для управления подсветкой #define LCD_BACKLIGHT 0x08 #define LCD_NOBACKLIGHT 0x00 #define En B00000100 // Бит разрешения #define Rw B00000010 // Чтение / запись бит #define Rs B00000001 // Бит выбора регистра class Cl_lcd1602_i2c : public Print { protected: uint8_t adr, posX, posY; uint8_t _backlightval; uint8_t _displayfunction; uint8_t _displaycontrol; uint8_t _displaymode; byte buffer[32]; public: Cl_lcd1602_i2c(uint8_t a): adr(a) {} void init() { Wire.begin(); write4bits(0x03 << 4); delayMicroseconds(4500); // wait min 4.1ms write4bits(0x03 << 4); delayMicroseconds(4500); // wait min 4.1ms write4bits(0x03 << 4); delayMicroseconds(150); write4bits(0x02 << 4); delay(50); _backlightval = LCD_NOBACKLIGHT; expanderWrite(_backlightval); // сбросить расширение и выключить подсветку (бит 8 = 1) // режим работы дисплея 4-х битный интерфейс ,две строки,5х8 точек _displayfunction = LCD_4BITMODE | LCD_2LINE | LCD_5x8DOTS; command(LCD_FUNCTIONSET | _displayfunction); // режим контроля дисплей вкл, курсор не мигает,дисплей не мигает _displaycontrol = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF; command(LCD_DISPLAYCONTROL | _displaycontrol); // режим ввода текста в память-начинать слева с движением в право _displaymode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT; command(LCD_ENTRYMODESET | _displaymode); clear(); } // подсветку вкл/выкл void backlight(void) { _backlightval = LCD_BACKLIGHT; expanderWrite(0); } void noBacklight(void) { _backlightval = LCD_NOBACKLIGHT; expanderWrite(0); } // очистить буфер void clear() { for (byte i = 0; i < 32; i++ )buffer[i] = 0x20; posX = 0; posY = 0; } // отправить информацию из буфера на экран void show() { line(0); for (byte i = 0; i < 16; i++ )out(buffer[i]); line(1); for (byte i = 16; i < 32; i++ )out(buffer[i]); } void setCursor(byte x, byte y) { if (x > 16) x = 16; else posX = x; if (y > 2) x = 2; else posY = y; } private: /*внутрение функции*/ void line(byte l) { if (l == 0) command(LCD_SETDDRAMADDR | 0x00); else command(LCD_SETDDRAMADDR | 0x40); } inline void out(uint8_t value) { send(value, Rs); } inline size_t write(uint8_t value) { if (posX < 16 && posY < 2) { buffer[posY * 16 + posX] = value; posX++; } return 1; } /*команды низкоуровневого управления*/ inline void command(uint8_t value) { send(value, 0); } void send(uint8_t value, uint8_t mode) { uint8_t highnib = value & 0xf0; write4bits((highnib) | mode); uint8_t lownib = (value << 4) & 0xf0; write4bits((lownib) | mode); } void write4bits(uint8_t value) { expanderWrite(value); pulseEnable(value); } void expanderWrite(uint8_t _data) { Wire.beginTransmission(adr); Wire.write((int)(_data) | _backlightval); Wire.endTransmission(); } void pulseEnable(uint8_t _data) { expanderWrite(_data | En); // En high delayMicroseconds(1); // enable pulse must be >450ns expanderWrite(_data & ~En); // En low delayMicroseconds(50); // commands need > 37us to settle } }; Cl_lcd1602_i2c lcd(0x27); //---------- millis часы ---------------------------------------------- class Cl_clock { protected: unsigned long time; unsigned long past; void set() { past = millis(); time = past / 1000; } public: void init() { set(); } void run() { if (millis() - past >= 100) set(); } unsigned long now() { return time; } byte hour() { return (time / 60 / 60 % 24); } byte minute() { return (time / 60 % 60); } byte second() { return (time % 60); } }; Cl_clock clock; // -------------таймеры------------------------------------------------ typedef struct { byte hour; byte minute; byte second; } timer_t; const byte numTimer = 5; timer_t EEMEM adr1[numTimer]; // первичные настройки в EEPROM void saveZeroSettings() { timer_t data[numTimer * 2] = { // начальные настройки {0, 0, 30}, {0, 3, 00}, // 1-й таймер {0, 1, 00}, {0, 3, 30}, // 2-й таймер {0, 1, 30}, {0, 4, 00}, // 3-й таймер {0, 2, 00}, {0, 4, 30}, // 4-й таймер {0, 2, 30}, {0, 5, 00} // 5-й таймер }; for (int i = 0; i < numTimer * 2; ++i) { eeprom_write_byte(&adr1[i].hour , data[i].hour); eeprom_write_byte(&adr1[i].minute, data[i].minute); eeprom_write_byte(&adr1[i].second, data[i].second); } } /*состояния таймера*/ const byte sOFF = 0; const byte sON = 1; const byte sEND = 2; class Cl_Timer { private: timer_t *adr1, *adr2; byte pin; byte stat;// состояние unsigned long past; void setStat(byte s) { stat = s; past = millis(); switch (s) { case sOFF: digitalWrite(pin, HIGH); break; case sON: digitalWrite(pin, LOW); break; case sEND: digitalWrite(pin, HIGH); break; } } public: Cl_Timer(byte p, timer_t * a1, timer_t * a2) : adr1(a1), adr2(a2), pin(p) {} void init() { pinMode(pin, OUTPUT); setStat(sOFF); } void run() { if (millis() - past >= 100) { switch (stat) { case sOFF: if (clock.now() >= ((unsigned long)hour1() * 24 + minute1()) * 60 + second1())setStat(sON); else setStat(sOFF); break; case sON: if (clock.now() >= ((unsigned long)hour2() * 24 + minute2()) * 60 + second2())setStat(sEND); else setStat(sON); break; case sEND: setStat(sEND); break; } } } void state() { switch (stat) { case sOFF: lcd << F("OFF"); break; case sON: lcd << F("ON "); break; case sEND: lcd << F("END"); break; } } byte hour1() { return eeprom_read_byte(&(adr1->hour)); } byte minute1() { return eeprom_read_byte(&(adr1->minute)); } byte second1() { return eeprom_read_byte(&(adr1->second)); } void writeHour1(byte data) { eeprom_write_byte(&(adr1->hour), data); } void writeMinute1(byte data) { eeprom_write_byte(&(adr1->minute), data); } void writeSecond1(byte data) { eeprom_write_byte(&(adr1->second), data); } byte hour2() { return eeprom_read_byte(&(adr2->hour)); } byte minute2() { return eeprom_read_byte(&(adr2->minute)); } byte second2() { return eeprom_read_byte(&(adr2->second)); } void writeHour2(byte data) { eeprom_write_byte(&(adr2->hour), data); } void writeMinute2(byte data) { eeprom_write_byte(&(adr2->minute), data); } void writeSecond2(byte data) { eeprom_write_byte(&(adr2->second), data); } }; Cl_Timer Timer[numTimer] = { Cl_Timer(/*пин*/2, &adr1[0], &adr1[1]), // 1-й таймер Cl_Timer(/*пин*/3, &adr1[2], &adr1[3]), // 2-й таймер Cl_Timer(/*пин*/4, &adr1[4], &adr1[5]), // 3-й таймер Cl_Timer(/*пин*/5, &adr1[6], &adr1[7]), // 4-й таймер Cl_Timer(/*пин*/6, &adr1[8], &adr1[9]) // 5-й таймер }; //---кнопкa----------------------------- typedef void (*pDo)(); class Cl_btn { protected: byte pin; bool state; unsigned long past; void set(bool s) { state = s; past = millis(); switch (s) { case false: break; case true: Do(); break; } } public: Cl_btn(byte p): pin(p) {} pDo Do = [] {}; void init() { pinMode(pin, INPUT_PULLUP); set(false); } void run() { if (millis() - past >= 100) switch (state) { case false: if (!digitalRead(pin))set(true); break; case true: if (digitalRead(pin))set(false); if (millis() - past >= 300)set(false); break; } } }; Cl_btn Btn(/*пин*/A0); //------------------------------------------- const byte st1 = 0; const byte st0 = 1; const byte st2 = 2; class Cl_joystic { protected: byte pin; byte state; unsigned long past; void set(byte s) { state = s; past = millis(); switch (s) { case st0: break; case st1: Do1(); break; case st2: Do2(); break; } } public: Cl_joystic(byte p): pin(p) {} pDo Do1 = [] {}; pDo Do2 = [] {}; void init() { set(st0); } void run() { if (millis() - past >= 100) { int tmp = analogRead(pin); switch (state) { case st1: if (tmp > 450)set(st0); if (millis() - past >= 300)set(st0); break; case st0: if (tmp < 400)set(st1); else if (tmp > 600)set(st2); break; case st2: if (tmp < 550)set(st0); if (millis() - past >= 300)set(st0); break; } } } }; Cl_joystic JoyLR(/*пин*/A1); Cl_joystic JoyUD(/*пин*/A2); //--------------- меню--------------------------------------------- byte var; // некая вспомогательная переменная const byte sMain = 0;// главный экран const byte ss1 = 1;// 1-экран const byte ss1sec1 = 2;// редактирование 1 const byte ss1min1 = 3;// редактирование 2 const byte ss1hour1 = 4;// редактирование 3 const byte ss1sec2 = 5;// редактирование 1 const byte ss1min2 = 6;// редактирование 2 const byte ss1hour2 = 7;// редактирование 3 const byte ss2 = 11;// 2-экран const byte ss2sec1 = 12;// редактирование 1 const byte ss2min1 = 13;// редактирование 2 const byte ss2hour1 = 14;// редактирование 3 const byte ss2sec2 = 15;// редактирование 1 const byte ss2min2 = 16;// редактирование 2 const byte ss2hour2 = 17;// редактирование 3 const byte ss3 = 21;// 3-экран const byte ss3sec1 = 22;// редактирование 1 const byte ss3min1 = 23;// редактирование 2 const byte ss3hour1 = 24;// редактирование 3 const byte ss3sec2 = 25;// редактирование 1 const byte ss3min2 = 26;// редактирование 2 const byte ss3hour2 = 27;// редактирование 3 const byte ss4 = 31;// 4-экран const byte ss4sec1 = 32;// редактирование 1 const byte ss4min1 = 33;// редактирование 2 const byte ss4hour1 = 34;// редактирование 3 const byte ss4sec2 = 35;// редактирование 1 const byte ss4min2 = 36;// редактирование 2 const byte ss4hour2 = 37;// редактирование 3 const byte ss5 = 41;// 5-экран const byte ss5sec1 = 42;// редактирование 1 const byte ss5min1 = 43;// редактирование 2 const byte ss5hour1 = 44;// редактирование 3 const byte ss5sec2 = 45;// редактирование 1 const byte ss5min2 = 46;// редактирование 2 const byte ss5hour2 = 47;// редактирование 3 byte pos; unsigned long past; void setPos(byte p) { pos = p; past = millis(); lcd.clear(); switch (p) { case sMain:// главный экран { lcd << clock.hour() << F(":") << clock.minute() << F(":") << clock.second(); lcd.setCursor(9, 0); Timer[0].state(); lcd << F(" "); Timer[1].state(); lcd << F(" "); lcd.setCursor(5, 1); Timer[2].state(); lcd << F(" "); Timer[3].state(); lcd << F(" "); Timer[4].state(); lcd << F(" "); lcd.show(); } Btn.Do = [] {}; JoyUD.Do1 = [] { }; JoyUD.Do2 = [] {setPos(ss1); }; break; case ss1: // 1-экран { lcd << F("Timer1:") << Timer[0].hour1() << F(":") << Timer[0].minute1() << F(":") << Timer[0].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[0].hour2() << F(":") << Timer[0].minute2() << F(":") << Timer[0].second2(); lcd.show(); } Btn.Do = [] { var = Timer[0].second1(); setPos(ss1sec1); }; JoyUD.Do1 = [] {setPos(sMain); }; JoyUD.Do2 = [] {setPos(ss2); }; break; case ss1sec1:// редактирование секунд { lcd << F("Timer1:") << Timer[0].hour1() << F(":") << Timer[0].minute1() << F(">") << var; lcd.setCursor(0, 1); lcd << F(" ") << Timer[0].hour2() << F(":") << Timer[0].minute2() << F(":") << Timer[0].second2(); lcd.show(); } Btn.Do = [] { Timer[0].writeSecond1(var); var = Timer[0].minute1(); setPos(ss1min1); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss1sec1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss1sec1); }; break; case ss1min1:// редактирование минут { lcd << F("Timer1:") << Timer[0].hour1() << F(">") << var << F(":") << Timer[0].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[0].hour2() << F(":") << Timer[0].minute2() << F(":") << Timer[0].second2(); lcd.show(); } Btn.Do = [] { Timer[0].writeMinute1(var); var = Timer[0].hour1(); setPos(ss1hour1); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss1min1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss1min1); }; break; case ss1hour1:// редактирование часов { lcd << F("Timer1>") << var << F(":") << Timer[0].minute1() << F(":") << Timer[0].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[0].hour2() << F(":") << Timer[0].minute2() << F(":") << Timer[0].second2(); lcd.show(); } Btn.Do = [] { Timer[0].writeHour1(var); setPos(ss1sec2); }; JoyUD.Do1 = [] { if (var < 23)var++; setPos(ss1hour1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss1hour1); }; break; case ss1sec2:// редактирование секунд { lcd << F("Timer1:") << Timer[0].hour1() << F(":") << Timer[0].minute1() << F(":") << Timer[0].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[0].hour2() << F(":") << Timer[0].minute2() << F(">") << var; lcd.show(); } Btn.Do = [] { Timer[0].writeSecond2(var); var = Timer[0].minute2(); setPos(ss1min2); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss1sec2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss1sec2); }; break; case ss1min2:// редактирование минут { lcd << F("Timer1:") << Timer[0].hour1() << F(":") << Timer[0].minute1() << F(":") << Timer[0].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[0].hour2() << F(">") << var << F(":") << Timer[0].second2(); lcd.show(); } Btn.Do = [] { Timer[0].writeMinute2(var); var = Timer[0].hour2(); setPos(ss1hour2); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss1min2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss1min2); }; break; case ss1hour2:// редактирование часов { lcd << F("Timer1:") << Timer[0].hour1() << F(":") << Timer[0].minute1() << F(":") << Timer[0].second1(); lcd.setCursor(0, 1); lcd << F(" >") << var << F(":") << Timer[0].minute2() << F(":") << Timer[0].second2(); lcd.show(); } Btn.Do = [] { Timer[0].writeHour2(var); setPos(ss1); }; JoyUD.Do1 = [] { if (var < 23)var++; setPos(ss1hour2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss1hour2); }; break; //--------------------------------------------------------------------- case ss2: // 2-экран { lcd << F("Timer2:") << Timer[1].hour1() << F(":") << Timer[1].minute1() << F(":") << Timer[1].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[1].hour2() << F(":") << Timer[1].minute2() << F(":") << Timer[1].second2(); lcd.show(); } Btn.Do = [] { var = Timer[1].second1(); setPos(ss2sec1); }; JoyUD.Do1 = [] {setPos(ss1); }; JoyUD.Do2 = [] {setPos(ss3); }; break; case ss2sec1: { lcd << F("Timer2:") << Timer[1].hour1() << F(":") << Timer[1].minute1() << F(">") << var; lcd.setCursor(0, 1); lcd << F(" ") << Timer[1].hour2() << F(":") << Timer[1].minute2() << F(":") << Timer[1].second2(); lcd.show(); } Btn.Do = [] { Timer[1].writeSecond1(var); var = Timer[1].minute1(); setPos(ss2min1); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss2sec1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss2sec1); }; break; case ss2min1: { lcd << F("Timer2:") << Timer[1].hour1() << F(">") << var << F(":") << Timer[1].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[1].hour2() << F(":") << Timer[1].minute2() << F(":") << Timer[1].second2(); lcd.show(); } Btn.Do = [] { Timer[1].writeMinute1(var); var = Timer[1].hour1(); setPos(ss2hour1); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss2min1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss2min1); }; break; case ss2hour1: { lcd << F("Timer2>") << var << F(":") << Timer[1].minute1() << F(":") << Timer[1].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[1].hour2() << F(":") << Timer[1].minute2() << F(":") << Timer[1].second2(); lcd.show(); } Btn.Do = [] { Timer[1].writeHour1(var); var = Timer[1].second2(); setPos(ss2sec2); }; JoyUD.Do1 = [] { if (var < 23)var++; setPos(ss2hour1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss2hour1); }; break; case ss2sec2: { lcd << F("Timer2:") << Timer[1].hour1() << F(":") << Timer[1].minute1() << F(":") << Timer[1].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[1].hour2() << F(":") << Timer[1].minute2() << F(">") << var; lcd.show(); } Btn.Do = [] { Timer[1].writeSecond2(var); var = Timer[1].minute2(); setPos(ss2min2); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss2sec2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss2sec2); }; break; case ss2min2: { lcd << F("Timer2:") << Timer[1].hour1() << F(":") << Timer[1].minute1() << F(":") << Timer[1].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[1].hour2() << F(">") << var << F(":") << Timer[1].second2(); lcd.show(); } Btn.Do = [] { Timer[1].writeMinute2(var); var = Timer[1].hour2(); setPos(ss2hour2); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss2min2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss2min2); }; break; case ss2hour2: { lcd << F("Timer2:") << Timer[1].hour1() << F(":") << Timer[1].minute1() << F(":") << Timer[1].second1(); lcd.setCursor(0, 1); lcd << F(" >") << var << F(":") << Timer[1].minute2() << F(":") << Timer[1].second2(); lcd.show(); } Btn.Do = [] { Timer[1].writeHour2(var); setPos(ss2); }; JoyUD.Do1 = [] { if (var < 23)var++; setPos(ss2hour2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss2hour2); }; break; //--------------------------------------------------------------------- case ss3: // 3-экран { lcd << F("Timer3:") << Timer[2].hour1() << F(":") << Timer[2].minute1() << F(":") << Timer[2].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[2].hour2() << F(":") << Timer[2].minute2() << F(":") << Timer[2].second2(); lcd.show(); } Btn.Do = [] { var = Timer[2].second1(); setPos(ss3sec1); }; JoyUD.Do1 = [] {setPos(ss2); }; JoyUD.Do2 = [] {setPos(ss4); }; break; case ss3sec1:// редакт секунд { lcd << F("Timer3:") << Timer[2].hour1() << F(":") << Timer[2].minute1() << F(">") << var; lcd.setCursor(0, 1); lcd << F(" ") << Timer[2].hour2() << F(":") << Timer[2].minute2() << F(":") << Timer[2].second2(); lcd.show(); } Btn.Do = [] { Timer[2].writeSecond1(var); var = Timer[2].minute1(); setPos(ss3min1); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss3sec1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss3sec1); }; break; case ss3min1:// редакт минут { lcd << F("Timer3:") << Timer[2].hour1() << F(">") << var << F(":") << Timer[2].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[2].hour2() << F(":") << Timer[2].minute2() << F(":") << Timer[2].second2(); lcd.show(); } Btn.Do = [] { Timer[2].writeMinute1(var); var = Timer[2].hour1(); setPos(ss3hour1); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss3min1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss3min1); }; break; case ss3hour1:// редакт часов { lcd << F("Timer3>") << var << F(":") << Timer[2].minute1() << F(":") << Timer[2].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[2].hour2() << F(":") << Timer[2].minute2() << F(":") << Timer[2].second2(); lcd.show(); } Btn.Do = [] { Timer[2].writeHour1(var); var = Timer[2].second2(); setPos(ss3sec2); }; JoyUD.Do1 = [] { if (var < 23)var++; setPos(ss3hour1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss3hour1); }; break; case ss3sec2:// редакт секунд { lcd << F("Timer3:") << Timer[2].hour1() << F(":") << Timer[2].minute1() << F(":") << Timer[2].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[2].hour2() << F(":") << Timer[2].minute2() << F(">") << var; lcd.show(); } Btn.Do = [] { Timer[2].writeSecond2(var); var = Timer[2].minute2(); setPos(ss3min2); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss3sec2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss3sec2); }; break; case ss3min2:// редакт минут { lcd << F("Timer3:") << Timer[2].hour1() << F(":") << Timer[2].minute1() << F(":") << Timer[2].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[2].hour2() << F(">") << var << F(":") << Timer[2].second2(); lcd.show(); } Btn.Do = [] { Timer[2].writeMinute2(var); var = Timer[2].hour2(); setPos(ss3hour2); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss3min2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss3min2); }; break; case ss3hour2:// редакт часов { lcd << F("Timer3:") << Timer[2].hour1() << F(":") << Timer[2].minute1() << F(":") << Timer[2].second1(); lcd.setCursor(0, 1); lcd << F(" >") << var << F(":") << Timer[2].minute2() << F(":") << Timer[2].second2(); lcd.show(); } Btn.Do = [] { Timer[2].writeHour2(var); setPos(ss3); }; JoyUD.Do1 = [] { if (var < 23)var++; setPos(ss3hour2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss3hour2); }; break; //--------------------------------------------------------------------- case ss4: // 4-экран { lcd << F("Timer4:") << Timer[3].hour1() << F(":") << Timer[3].minute1() << F(":") << Timer[3].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[3].hour2() << F(":") << Timer[3].minute2() << F(":") << Timer[3].second2(); lcd.show(); } Btn.Do = [] { var = Timer[3].second1(); setPos(ss4sec1); }; JoyUD.Do1 = [] {setPos(ss3); }; JoyUD.Do2 = [] {setPos(ss5); }; break; case ss4sec1: { lcd << F("Timer4:") << Timer[3].hour1() << F(":") << Timer[3].minute1() << F(">") << var; lcd.setCursor(0, 1); lcd << F(" ") << Timer[3].hour2() << F(":") << Timer[3].minute2() << F(":") << Timer[3].second2(); lcd.show(); } Btn.Do = [] { Timer[3].writeSecond1(var); var = Timer[3].minute1(); setPos(ss4min1); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss4sec1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss4sec1); }; break; case ss4min1: { lcd << F("Timer4:") << Timer[3].hour1() << F(">") << var << F(":") << Timer[3].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[3].hour2() << F(":") << Timer[3].minute2() << F(":") << Timer[3].second2(); lcd.show(); } Btn.Do = [] { Timer[3].writeMinute1(var); var = Timer[3].hour1(); setPos(ss4hour1); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss4min1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss4min1); }; break; case ss4hour1: { lcd << F("Timer4>") << var << F(":") << Timer[3].minute1() << F(":") << Timer[3].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[3].hour2() << F(":") << Timer[3].minute2() << F(":") << Timer[3].second2(); lcd.show(); } Btn.Do = [] { Timer[3].writeHour1(var); var = Timer[3].second2(); setPos(ss4sec2); }; JoyUD.Do1 = [] { if (var < 23)var++; setPos(ss4hour1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss4hour1); }; break; case ss4sec2: { lcd << F("Timer4:") << Timer[3].hour1() << F(":") << Timer[3].minute1() << F(":") << Timer[3].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[3].hour2() << F(":") << Timer[3].minute2() << F(">") << var; lcd.show(); } Btn.Do = [] { Timer[3].writeSecond2(var); var = Timer[3].minute2(); setPos(ss4min2); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss4sec2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss4sec2); }; break; case ss4min2: { lcd << F("Timer4:") << Timer[3].hour1() << F(":") << Timer[3].minute1() << F(":") << Timer[3].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[3].hour2() << F(">") << var << F(":") << Timer[3].second2(); lcd.show(); } Btn.Do = [] { Timer[3].writeMinute2(var); var = Timer[3].hour2(); setPos(ss4hour2); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss4min2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss4min2); }; break; case ss4hour2: { lcd << F("Timer4:") << Timer[3].hour1() << F(":") << Timer[3].minute1() << F(":") << Timer[3].second1(); lcd.setCursor(0, 1); lcd << F(" >") << var << F(":") << Timer[3].minute2() << F(":") << Timer[3].second2(); lcd.show(); } Btn.Do = [] { Timer[3].writeHour2(var); setPos(ss4); }; JoyUD.Do1 = [] { if (var < 23)var++; setPos(ss4hour2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss4hour2); }; break; //--------------------------------------------------------------------- case ss5: // 5-экран { lcd << F("Timer5:") << Timer[4].hour1() << F(":") << Timer[4].minute1() << F(":") << Timer[4].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[4].hour2() << F(":") << Timer[4].minute2() << F(":") << Timer[4].second2(); lcd.show(); } Btn.Do = [] { var = Timer[4].second1(); setPos(ss5sec1); }; JoyUD.Do1 = [] { setPos(ss4); }; JoyUD.Do2 = [] {}; break; case ss5sec1: { lcd << F("Timer5:") << Timer[4].hour1() << F(":") << Timer[4].minute1() << F(">") << var; lcd.setCursor(0, 1); lcd << F(" ") << Timer[4].hour2() << F(":") << Timer[4].minute2() << F(":") << Timer[4].second2(); lcd.show(); } Btn.Do = [] { Timer[4].writeSecond1(var); var = Timer[4].minute1(); setPos(ss5min1); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss5sec1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss5sec1); }; break; case ss5min1: { lcd << F("Timer5:") << Timer[4].hour1() << F(">") << var << F(":") << Timer[4].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[4].hour2() << F(":") << Timer[4].minute2() << F(":") << Timer[4].second2(); lcd.show(); } Btn.Do = [] { Timer[4].writeMinute1(var); var = Timer[4].hour1(); setPos(ss5hour1); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss5min1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss5min1); }; break; case ss5hour1: { lcd << F("Timer5>") << var << F(":") << Timer[4].minute1() << F(":") << Timer[4].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[4].hour2() << F(":") << Timer[4].minute2() << F(":") << Timer[4].second2(); lcd.show(); } Btn.Do = [] { Timer[4].writeHour1(var); var = Timer[4].second2(); setPos(ss5sec2); }; JoyUD.Do1 = [] { if (var < 23)var++; setPos(ss5hour1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss5hour1); }; break; case ss5sec2: { lcd << F("Timer5:") << Timer[4].hour1() << F(":") << Timer[4].minute1() << F(":") << Timer[4].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[4].hour2() << F(":") << Timer[4].minute2() << F(">") << var; lcd.show(); } Btn.Do = [] { Timer[4].writeSecond2(var); var = Timer[4].minute2(); setPos(ss5min2); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss5sec2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss5sec2); }; break; case ss5min2: { lcd << F("Timer5:") << Timer[4].hour1() << F(":") << Timer[4].minute1() << F(":") << Timer[4].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[4].hour2() << F(">") << var << F(":") << Timer[4].second2(); lcd.show(); } Btn.Do = [] { Timer[4].writeMinute2(var); var = Timer[4].hour2(); setPos(ss5hour2); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss5min2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss5min2); }; break; case ss5hour2: { lcd << F("Timer5:") << Timer[4].hour1() << F(":") << Timer[4].minute1() << F(":") << Timer[4].second1(); lcd.setCursor(0, 1); lcd << F(" >") << var << F(":") << Timer[4].minute2() << F(":") << Timer[4].second2(); lcd.show(); } Btn.Do = [] { Timer[4].writeHour2(var); setPos(ss5); }; JoyUD.Do1 = [] { if (var < 23)var++; setPos(ss5hour2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss5hour2); }; break; } } void menuInit() { setPos(sMain); } void menuRun() { if (pos != sMain && millis() - past >= 10000)setPos(sMain); if (pos == sMain && millis() - past >= 1000)setPos(sMain); } //---------------------------------- void setup() { lcd.init(); clock.init(); saveZeroSettings(); for (int i = 0; i < numTimer; i++) Timer[i].init(); Btn.init(); JoyLR.init(); JoyUD.init(); menuInit(); JoyLR.Do1 = [] {lcd.backlight();}; JoyLR.Do2 = [] {lcd.noBacklight();}; } void loop() { clock.run(); for (int i = 0; i < numTimer; i++) Timer[i].run(); Btn.run(); JoyLR.run(); JoyUD.run(); menuRun(); } /**/Модуль с DS3231 и тестовый скетч
/**/ #include <Wire.h> #include "DS3231.h" RTClib RTC; //----------------------- void setup () { Serial.begin(9600); Wire.begin(); } void loop () { delay(1000); DateTime now = RTC.now(); Serial.print(now.hour(), DEC); Serial.print(':'); Serial.print(now.minute(), DEC); Serial.print(':'); Serial.print(now.second(), DEC); Serial.println(); }С недостатками но работает уже с модулем
/**/ //---------------lcd--------------------------------------------- template <typename T> inline Print & operator << (Print &s, T n) { s.print(n); return s; } //------дисплей lcd1602_i2c----------------------------- // даташит https://www.sparkfun.com/datasheets/LCD/ADM1602K-NSW-FBS-3.3v.pdf // на русском http://www.melt.aha.ru/pdf/mt-16s2h.pdf #include <Wire.h> // команды #define LCD_CLEARDISPLAY 0x01 #define LCD_RETURNHOME 0x02 #define LCD_ENTRYMODESET 0x04 #define LCD_DISPLAYCONTROL 0x08 #define LCD_CURSORSHIFT 0x10 #define LCD_FUNCTIONSET 0x20 #define LCD_SETCGRAMADDR 0x40 #define LCD_SETDDRAMADDR 0x80 // флаги для режима ввода дисплея #define LCD_ENTRYRIGHT 0x00 #define LCD_ENTRYLEFT 0x02 #define LCD_ENTRYSHIFTINCREMENT 0x01 #define LCD_ENTRYSHIFTDECREMENT 0x00 // флаги для управления включением / выключением дисплея #define LCD_DISPLAYON 0x04 #define LCD_DISPLAYOFF 0x00 #define LCD_CURSORON 0x02 #define LCD_CURSOROFF 0x00 #define LCD_BLINKON 0x01 #define LCD_BLINKOFF 0x00 // флаги для отображения / сдвига курсора #define LCD_DISPLAYMOVE 0x08 #define LCD_CURSORMOVE 0x00 #define LCD_MOVERIGHT 0x04 #define LCD_MOVELEFT 0x00 // флаги для набора функций #define LCD_8BITMODE 0x10 #define LCD_4BITMODE 0x00 #define LCD_2LINE 0x08 #define LCD_1LINE 0x00 #define LCD_5x10DOTS 0x04 #define LCD_5x8DOTS 0x00 // флаги для управления подсветкой #define LCD_BACKLIGHT 0x08 #define LCD_NOBACKLIGHT 0x00 #define En B00000100 // Бит разрешения #define Rw B00000010 // Чтение / запись бит #define Rs B00000001 // Бит выбора регистра class Cl_lcd1602_i2c : public Print { protected: uint8_t adr, posX, posY; uint8_t _backlightval; uint8_t _displayfunction; uint8_t _displaycontrol; uint8_t _displaymode; byte buffer[32]; public: Cl_lcd1602_i2c(uint8_t a): adr(a) {} void init() { Wire.begin(); write4bits(0x03 << 4); delayMicroseconds(4500); // wait min 4.1ms write4bits(0x03 << 4); delayMicroseconds(4500); // wait min 4.1ms write4bits(0x03 << 4); delayMicroseconds(150); write4bits(0x02 << 4); delay(50); _backlightval = LCD_NOBACKLIGHT; expanderWrite(_backlightval); // сбросить расширение и выключить подсветку (бит 8 = 1) // режим работы дисплея 4-х битный интерфейс ,две строки,5х8 точек _displayfunction = LCD_4BITMODE | LCD_2LINE | LCD_5x8DOTS; command(LCD_FUNCTIONSET | _displayfunction); // режим контроля дисплей вкл, курсор не мигает,дисплей не мигает _displaycontrol = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF; command(LCD_DISPLAYCONTROL | _displaycontrol); // режим ввода текста в память-начинать слева с движением в право _displaymode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT; command(LCD_ENTRYMODESET | _displaymode); clear(); } // подсветку вкл/выкл void backlight(void) { _backlightval = LCD_BACKLIGHT; expanderWrite(0); } void noBacklight(void) { _backlightval = LCD_NOBACKLIGHT; expanderWrite(0); } // очистить буфер void clear() { for (byte i = 0; i < 32; i++ )buffer[i] = 0x20; posX = 0; posY = 0; } // отправить информацию из буфера на экран void show() { line(0); for (byte i = 0; i < 16; i++ )out(buffer[i]); line(1); for (byte i = 16; i < 32; i++ )out(buffer[i]); } void setCursor(byte x, byte y) { if (x > 16) x = 16; else posX = x; if (y > 2) x = 2; else posY = y; } private: /*внутрение функции*/ void line(byte l) { if (l == 0) command(LCD_SETDDRAMADDR | 0x00); else command(LCD_SETDDRAMADDR | 0x40); } inline void out(uint8_t value) { send(value, Rs); } inline size_t write(uint8_t value) { if (posX < 16 && posY < 2) { buffer[posY * 16 + posX] = value; posX++; } return 1; } /*команды низкоуровневого управления*/ inline void command(uint8_t value) { send(value, 0); } void send(uint8_t value, uint8_t mode) { uint8_t highnib = value & 0xf0; write4bits((highnib) | mode); uint8_t lownib = (value << 4) & 0xf0; write4bits((lownib) | mode); } void write4bits(uint8_t value) { expanderWrite(value); pulseEnable(value); } void expanderWrite(uint8_t _data) { Wire.beginTransmission(adr); Wire.write((int)(_data) | _backlightval); Wire.endTransmission(); } void pulseEnable(uint8_t _data) { expanderWrite(_data | En); // En high delayMicroseconds(1); // enable pulse must be >450ns expanderWrite(_data & ~En); // En low delayMicroseconds(50); // commands need > 37us to settle } }; Cl_lcd1602_i2c lcd(0x27); //---------- часы ---------------------------------------------- /**/ #include "DS3231.h" RTClib RTC; class Cl_clock { protected: DateTime _now; unsigned long past; unsigned long time; void set() { past = millis(); _now = RTC.now(); time = (_now.hour() * 24 + _now.minute()) * 60 + _now.second(); } public: void init() { set(); } void run() { if (millis() - past >= 1000) set(); } unsigned long now() { return time; } byte hour() { return _now.hour(); } byte minute() { return _now.minute(); } byte second() { return _now.second(); } }; Cl_clock clock; // -------------таймеры------------------------------------------------ typedef struct { byte hour; byte minute; byte second; } timer_t; const byte numTimer = 5; timer_t EEMEM adr1[numTimer]; // первичные настройки в EEPROM void saveZeroSettings() { timer_t data[numTimer * 2] = { // начальные настройки {0, 0, 30}, {0, 3, 00}, // 1-й таймер {0, 1, 00}, {0, 3, 30}, // 2-й таймер {0, 1, 30}, {0, 4, 00}, // 3-й таймер {0, 2, 00}, {0, 4, 30}, // 4-й таймер {0, 2, 30}, {0, 5, 00} // 5-й таймер }; for (int i = 0; i < numTimer * 2; ++i) { eeprom_write_byte(&adr1[i].hour , data[i].hour); eeprom_write_byte(&adr1[i].minute, data[i].minute); eeprom_write_byte(&adr1[i].second, data[i].second); } } /*состояния таймера*/ const byte sOFF = 0; const byte sON = 1; const byte sEND = 2; class Cl_Timer { private: timer_t *adr1, *adr2; byte pin; byte stat;// состояние unsigned long past; void setStat(byte s) { stat = s; past = millis(); switch (s) { case sOFF: digitalWrite(pin, HIGH); break; case sON: digitalWrite(pin, LOW); break; case sEND: digitalWrite(pin, HIGH); break; } } public: Cl_Timer(byte p, timer_t * a1, timer_t * a2) : adr1(a1), adr2(a2), pin(p) {} void init() { pinMode(pin, OUTPUT); setStat(sOFF); } void run() { if (millis() - past >= 100) { switch (stat) { case sOFF: if (clock.now() >= ((unsigned long)hour1() * 24 + minute1()) * 60 + second1())setStat(sON); else setStat(sOFF); break; case sON: if (clock.now() >= ((unsigned long)hour2() * 24 + minute2()) * 60 + second2())setStat(sEND); else setStat(sON); break; case sEND: setStat(sEND); break; } } } void state() { switch (stat) { case sOFF: lcd << F("OFF"); break; case sON: lcd << F("ON "); break; case sEND: lcd << F("END"); break; } } byte hour1() { return eeprom_read_byte(&(adr1->hour)); } byte minute1() { return eeprom_read_byte(&(adr1->minute)); } byte second1() { return eeprom_read_byte(&(adr1->second)); } void writeHour1(byte data) { eeprom_write_byte(&(adr1->hour), data); } void writeMinute1(byte data) { eeprom_write_byte(&(adr1->minute), data); } void writeSecond1(byte data) { eeprom_write_byte(&(adr1->second), data); } byte hour2() { return eeprom_read_byte(&(adr2->hour)); } byte minute2() { return eeprom_read_byte(&(adr2->minute)); } byte second2() { return eeprom_read_byte(&(adr2->second)); } void writeHour2(byte data) { eeprom_write_byte(&(adr2->hour), data); } void writeMinute2(byte data) { eeprom_write_byte(&(adr2->minute), data); } void writeSecond2(byte data) { eeprom_write_byte(&(adr2->second), data); } }; Cl_Timer Timer[numTimer] = { Cl_Timer(/*пин*/2, &adr1[0], &adr1[1]), // 1-й таймер Cl_Timer(/*пин*/3, &adr1[2], &adr1[3]), // 2-й таймер Cl_Timer(/*пин*/4, &adr1[4], &adr1[5]), // 3-й таймер Cl_Timer(/*пин*/5, &adr1[6], &adr1[7]), // 4-й таймер Cl_Timer(/*пин*/6, &adr1[8], &adr1[9]) // 5-й таймер }; //---кнопкa----------------------------- typedef void (*pDo)(); class Cl_btn { protected: byte pin; bool state; unsigned long past; void set(bool s) { state = s; past = millis(); switch (s) { case false: break; case true: Do(); break; } } public: Cl_btn(byte p): pin(p) {} pDo Do = [] {}; void init() { pinMode(pin, INPUT_PULLUP); set(false); } void run() { if (millis() - past >= 100) switch (state) { case false: if (!digitalRead(pin))set(true); break; case true: if (digitalRead(pin))set(false); if (millis() - past >= 300)set(false); break; } } }; Cl_btn Btn(/*пин*/A0); //------------------------------------------- const byte st1 = 0; const byte st0 = 1; const byte st2 = 2; class Cl_joystic { protected: byte pin; byte state; unsigned long past; void set(byte s) { state = s; past = millis(); switch (s) { case st0: break; case st1: Do1(); break; case st2: Do2(); break; } } public: Cl_joystic(byte p): pin(p) {} pDo Do1 = [] {}; pDo Do2 = [] {}; void init() { set(st0); } void run() { if (millis() - past >= 100) { int tmp = analogRead(pin); switch (state) { case st1: if (tmp > 450)set(st0); if (millis() - past >= 300)set(st0); break; case st0: if (tmp < 400)set(st1); else if (tmp > 600)set(st2); break; case st2: if (tmp < 550)set(st0); if (millis() - past >= 300)set(st0); break; } } } }; Cl_joystic JoyLR(/*пин*/A1); Cl_joystic JoyUD(/*пин*/A2); //--------------- меню--------------------------------------------- byte var; // некая вспомогательная переменная const byte sMain = 0;// главный экран const byte ss1 = 1;// 1-экран const byte ss1sec1 = 2;// редактирование 1 const byte ss1min1 = 3;// редактирование 2 const byte ss1hour1 = 4;// редактирование 3 const byte ss1sec2 = 5;// редактирование 1 const byte ss1min2 = 6;// редактирование 2 const byte ss1hour2 = 7;// редактирование 3 const byte ss2 = 11;// 2-экран const byte ss2sec1 = 12;// редактирование 1 const byte ss2min1 = 13;// редактирование 2 const byte ss2hour1 = 14;// редактирование 3 const byte ss2sec2 = 15;// редактирование 1 const byte ss2min2 = 16;// редактирование 2 const byte ss2hour2 = 17;// редактирование 3 const byte ss3 = 21;// 3-экран const byte ss3sec1 = 22;// редактирование 1 const byte ss3min1 = 23;// редактирование 2 const byte ss3hour1 = 24;// редактирование 3 const byte ss3sec2 = 25;// редактирование 1 const byte ss3min2 = 26;// редактирование 2 const byte ss3hour2 = 27;// редактирование 3 const byte ss4 = 31;// 4-экран const byte ss4sec1 = 32;// редактирование 1 const byte ss4min1 = 33;// редактирование 2 const byte ss4hour1 = 34;// редактирование 3 const byte ss4sec2 = 35;// редактирование 1 const byte ss4min2 = 36;// редактирование 2 const byte ss4hour2 = 37;// редактирование 3 const byte ss5 = 41;// 5-экран const byte ss5sec1 = 42;// редактирование 1 const byte ss5min1 = 43;// редактирование 2 const byte ss5hour1 = 44;// редактирование 3 const byte ss5sec2 = 45;// редактирование 1 const byte ss5min2 = 46;// редактирование 2 const byte ss5hour2 = 47;// редактирование 3 byte pos; unsigned long past; void setPos(byte p) { pos = p; past = millis(); lcd.clear(); switch (p) { case sMain:// главный экран { lcd << clock.hour() << F(":") << clock.minute() << F(":") << clock.second(); lcd.setCursor(9, 0); Timer[0].state(); lcd << F(" "); Timer[1].state(); lcd << F(" "); lcd.setCursor(5, 1); Timer[2].state(); lcd << F(" "); Timer[3].state(); lcd << F(" "); Timer[4].state(); lcd << F(" "); lcd.show(); } Btn.Do = [] {}; JoyUD.Do1 = [] { }; JoyUD.Do2 = [] {setPos(ss1); }; break; case ss1: // 1-экран { lcd << F("Timer1:") << Timer[0].hour1() << F(":") << Timer[0].minute1() << F(":") << Timer[0].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[0].hour2() << F(":") << Timer[0].minute2() << F(":") << Timer[0].second2(); lcd.show(); } Btn.Do = [] { var = Timer[0].second1(); setPos(ss1sec1); }; JoyUD.Do1 = [] {setPos(sMain); }; JoyUD.Do2 = [] {setPos(ss2); }; break; case ss1sec1:// редактирование секунд { lcd << F("Timer1:") << Timer[0].hour1() << F(":") << Timer[0].minute1() << F(">") << var; lcd.setCursor(0, 1); lcd << F(" ") << Timer[0].hour2() << F(":") << Timer[0].minute2() << F(":") << Timer[0].second2(); lcd.show(); } Btn.Do = [] { Timer[0].writeSecond1(var); var = Timer[0].minute1(); setPos(ss1min1); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss1sec1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss1sec1); }; break; case ss1min1:// редактирование минут { lcd << F("Timer1:") << Timer[0].hour1() << F(">") << var << F(":") << Timer[0].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[0].hour2() << F(":") << Timer[0].minute2() << F(":") << Timer[0].second2(); lcd.show(); } Btn.Do = [] { Timer[0].writeMinute1(var); var = Timer[0].hour1(); setPos(ss1hour1); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss1min1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss1min1); }; break; case ss1hour1:// редактирование часов { lcd << F("Timer1>") << var << F(":") << Timer[0].minute1() << F(":") << Timer[0].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[0].hour2() << F(":") << Timer[0].minute2() << F(":") << Timer[0].second2(); lcd.show(); } Btn.Do = [] { Timer[0].writeHour1(var); setPos(ss1sec2); }; JoyUD.Do1 = [] { if (var < 23)var++; setPos(ss1hour1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss1hour1); }; break; case ss1sec2:// редактирование секунд { lcd << F("Timer1:") << Timer[0].hour1() << F(":") << Timer[0].minute1() << F(":") << Timer[0].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[0].hour2() << F(":") << Timer[0].minute2() << F(">") << var; lcd.show(); } Btn.Do = [] { Timer[0].writeSecond2(var); var = Timer[0].minute2(); setPos(ss1min2); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss1sec2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss1sec2); }; break; case ss1min2:// редактирование минут { lcd << F("Timer1:") << Timer[0].hour1() << F(":") << Timer[0].minute1() << F(":") << Timer[0].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[0].hour2() << F(">") << var << F(":") << Timer[0].second2(); lcd.show(); } Btn.Do = [] { Timer[0].writeMinute2(var); var = Timer[0].hour2(); setPos(ss1hour2); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss1min2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss1min2); }; break; case ss1hour2:// редактирование часов { lcd << F("Timer1:") << Timer[0].hour1() << F(":") << Timer[0].minute1() << F(":") << Timer[0].second1(); lcd.setCursor(0, 1); lcd << F(" >") << var << F(":") << Timer[0].minute2() << F(":") << Timer[0].second2(); lcd.show(); } Btn.Do = [] { Timer[0].writeHour2(var); setPos(ss1); }; JoyUD.Do1 = [] { if (var < 23)var++; setPos(ss1hour2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss1hour2); }; break; //--------------------------------------------------------------------- case ss2: // 2-экран { lcd << F("Timer2:") << Timer[1].hour1() << F(":") << Timer[1].minute1() << F(":") << Timer[1].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[1].hour2() << F(":") << Timer[1].minute2() << F(":") << Timer[1].second2(); lcd.show(); } Btn.Do = [] { var = Timer[1].second1(); setPos(ss2sec1); }; JoyUD.Do1 = [] {setPos(ss1); }; JoyUD.Do2 = [] {setPos(ss3); }; break; case ss2sec1: { lcd << F("Timer2:") << Timer[1].hour1() << F(":") << Timer[1].minute1() << F(">") << var; lcd.setCursor(0, 1); lcd << F(" ") << Timer[1].hour2() << F(":") << Timer[1].minute2() << F(":") << Timer[1].second2(); lcd.show(); } Btn.Do = [] { Timer[1].writeSecond1(var); var = Timer[1].minute1(); setPos(ss2min1); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss2sec1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss2sec1); }; break; case ss2min1: { lcd << F("Timer2:") << Timer[1].hour1() << F(">") << var << F(":") << Timer[1].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[1].hour2() << F(":") << Timer[1].minute2() << F(":") << Timer[1].second2(); lcd.show(); } Btn.Do = [] { Timer[1].writeMinute1(var); var = Timer[1].hour1(); setPos(ss2hour1); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss2min1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss2min1); }; break; case ss2hour1: { lcd << F("Timer2>") << var << F(":") << Timer[1].minute1() << F(":") << Timer[1].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[1].hour2() << F(":") << Timer[1].minute2() << F(":") << Timer[1].second2(); lcd.show(); } Btn.Do = [] { Timer[1].writeHour1(var); var = Timer[1].second2(); setPos(ss2sec2); }; JoyUD.Do1 = [] { if (var < 23)var++; setPos(ss2hour1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss2hour1); }; break; case ss2sec2: { lcd << F("Timer2:") << Timer[1].hour1() << F(":") << Timer[1].minute1() << F(":") << Timer[1].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[1].hour2() << F(":") << Timer[1].minute2() << F(">") << var; lcd.show(); } Btn.Do = [] { Timer[1].writeSecond2(var); var = Timer[1].minute2(); setPos(ss2min2); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss2sec2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss2sec2); }; break; case ss2min2: { lcd << F("Timer2:") << Timer[1].hour1() << F(":") << Timer[1].minute1() << F(":") << Timer[1].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[1].hour2() << F(">") << var << F(":") << Timer[1].second2(); lcd.show(); } Btn.Do = [] { Timer[1].writeMinute2(var); var = Timer[1].hour2(); setPos(ss2hour2); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss2min2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss2min2); }; break; case ss2hour2: { lcd << F("Timer2:") << Timer[1].hour1() << F(":") << Timer[1].minute1() << F(":") << Timer[1].second1(); lcd.setCursor(0, 1); lcd << F(" >") << var << F(":") << Timer[1].minute2() << F(":") << Timer[1].second2(); lcd.show(); } Btn.Do = [] { Timer[1].writeHour2(var); setPos(ss2); }; JoyUD.Do1 = [] { if (var < 23)var++; setPos(ss2hour2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss2hour2); }; break; //--------------------------------------------------------------------- case ss3: // 3-экран { lcd << F("Timer3:") << Timer[2].hour1() << F(":") << Timer[2].minute1() << F(":") << Timer[2].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[2].hour2() << F(":") << Timer[2].minute2() << F(":") << Timer[2].second2(); lcd.show(); } Btn.Do = [] { var = Timer[2].second1(); setPos(ss3sec1); }; JoyUD.Do1 = [] {setPos(ss2); }; JoyUD.Do2 = [] {setPos(ss4); }; break; case ss3sec1:// редакт секунд { lcd << F("Timer3:") << Timer[2].hour1() << F(":") << Timer[2].minute1() << F(">") << var; lcd.setCursor(0, 1); lcd << F(" ") << Timer[2].hour2() << F(":") << Timer[2].minute2() << F(":") << Timer[2].second2(); lcd.show(); } Btn.Do = [] { Timer[2].writeSecond1(var); var = Timer[2].minute1(); setPos(ss3min1); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss3sec1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss3sec1); }; break; case ss3min1:// редакт минут { lcd << F("Timer3:") << Timer[2].hour1() << F(">") << var << F(":") << Timer[2].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[2].hour2() << F(":") << Timer[2].minute2() << F(":") << Timer[2].second2(); lcd.show(); } Btn.Do = [] { Timer[2].writeMinute1(var); var = Timer[2].hour1(); setPos(ss3hour1); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss3min1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss3min1); }; break; case ss3hour1:// редакт часов { lcd << F("Timer3>") << var << F(":") << Timer[2].minute1() << F(":") << Timer[2].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[2].hour2() << F(":") << Timer[2].minute2() << F(":") << Timer[2].second2(); lcd.show(); } Btn.Do = [] { Timer[2].writeHour1(var); var = Timer[2].second2(); setPos(ss3sec2); }; JoyUD.Do1 = [] { if (var < 23)var++; setPos(ss3hour1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss3hour1); }; break; case ss3sec2:// редакт секунд { lcd << F("Timer3:") << Timer[2].hour1() << F(":") << Timer[2].minute1() << F(":") << Timer[2].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[2].hour2() << F(":") << Timer[2].minute2() << F(">") << var; lcd.show(); } Btn.Do = [] { Timer[2].writeSecond2(var); var = Timer[2].minute2(); setPos(ss3min2); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss3sec2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss3sec2); }; break; case ss3min2:// редакт минут { lcd << F("Timer3:") << Timer[2].hour1() << F(":") << Timer[2].minute1() << F(":") << Timer[2].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[2].hour2() << F(">") << var << F(":") << Timer[2].second2(); lcd.show(); } Btn.Do = [] { Timer[2].writeMinute2(var); var = Timer[2].hour2(); setPos(ss3hour2); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss3min2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss3min2); }; break; case ss3hour2:// редакт часов { lcd << F("Timer3:") << Timer[2].hour1() << F(":") << Timer[2].minute1() << F(":") << Timer[2].second1(); lcd.setCursor(0, 1); lcd << F(" >") << var << F(":") << Timer[2].minute2() << F(":") << Timer[2].second2(); lcd.show(); } Btn.Do = [] { Timer[2].writeHour2(var); setPos(ss3); }; JoyUD.Do1 = [] { if (var < 23)var++; setPos(ss3hour2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss3hour2); }; break; //--------------------------------------------------------------------- case ss4: // 4-экран { lcd << F("Timer4:") << Timer[3].hour1() << F(":") << Timer[3].minute1() << F(":") << Timer[3].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[3].hour2() << F(":") << Timer[3].minute2() << F(":") << Timer[3].second2(); lcd.show(); } Btn.Do = [] { var = Timer[3].second1(); setPos(ss4sec1); }; JoyUD.Do1 = [] {setPos(ss3); }; JoyUD.Do2 = [] {setPos(ss5); }; break; case ss4sec1: { lcd << F("Timer4:") << Timer[3].hour1() << F(":") << Timer[3].minute1() << F(">") << var; lcd.setCursor(0, 1); lcd << F(" ") << Timer[3].hour2() << F(":") << Timer[3].minute2() << F(":") << Timer[3].second2(); lcd.show(); } Btn.Do = [] { Timer[3].writeSecond1(var); var = Timer[3].minute1(); setPos(ss4min1); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss4sec1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss4sec1); }; break; case ss4min1: { lcd << F("Timer4:") << Timer[3].hour1() << F(">") << var << F(":") << Timer[3].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[3].hour2() << F(":") << Timer[3].minute2() << F(":") << Timer[3].second2(); lcd.show(); } Btn.Do = [] { Timer[3].writeMinute1(var); var = Timer[3].hour1(); setPos(ss4hour1); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss4min1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss4min1); }; break; case ss4hour1: { lcd << F("Timer4>") << var << F(":") << Timer[3].minute1() << F(":") << Timer[3].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[3].hour2() << F(":") << Timer[3].minute2() << F(":") << Timer[3].second2(); lcd.show(); } Btn.Do = [] { Timer[3].writeHour1(var); var = Timer[3].second2(); setPos(ss4sec2); }; JoyUD.Do1 = [] { if (var < 23)var++; setPos(ss4hour1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss4hour1); }; break; case ss4sec2: { lcd << F("Timer4:") << Timer[3].hour1() << F(":") << Timer[3].minute1() << F(":") << Timer[3].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[3].hour2() << F(":") << Timer[3].minute2() << F(">") << var; lcd.show(); } Btn.Do = [] { Timer[3].writeSecond2(var); var = Timer[3].minute2(); setPos(ss4min2); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss4sec2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss4sec2); }; break; case ss4min2: { lcd << F("Timer4:") << Timer[3].hour1() << F(":") << Timer[3].minute1() << F(":") << Timer[3].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[3].hour2() << F(">") << var << F(":") << Timer[3].second2(); lcd.show(); } Btn.Do = [] { Timer[3].writeMinute2(var); var = Timer[3].hour2(); setPos(ss4hour2); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss4min2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss4min2); }; break; case ss4hour2: { lcd << F("Timer4:") << Timer[3].hour1() << F(":") << Timer[3].minute1() << F(":") << Timer[3].second1(); lcd.setCursor(0, 1); lcd << F(" >") << var << F(":") << Timer[3].minute2() << F(":") << Timer[3].second2(); lcd.show(); } Btn.Do = [] { Timer[3].writeHour2(var); setPos(ss4); }; JoyUD.Do1 = [] { if (var < 23)var++; setPos(ss4hour2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss4hour2); }; break; //--------------------------------------------------------------------- case ss5: // 5-экран { lcd << F("Timer5:") << Timer[4].hour1() << F(":") << Timer[4].minute1() << F(":") << Timer[4].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[4].hour2() << F(":") << Timer[4].minute2() << F(":") << Timer[4].second2(); lcd.show(); } Btn.Do = [] { var = Timer[4].second1(); setPos(ss5sec1); }; JoyUD.Do1 = [] { setPos(ss4); }; JoyUD.Do2 = [] {}; break; case ss5sec1: { lcd << F("Timer5:") << Timer[4].hour1() << F(":") << Timer[4].minute1() << F(">") << var; lcd.setCursor(0, 1); lcd << F(" ") << Timer[4].hour2() << F(":") << Timer[4].minute2() << F(":") << Timer[4].second2(); lcd.show(); } Btn.Do = [] { Timer[4].writeSecond1(var); var = Timer[4].minute1(); setPos(ss5min1); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss5sec1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss5sec1); }; break; case ss5min1: { lcd << F("Timer5:") << Timer[4].hour1() << F(">") << var << F(":") << Timer[4].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[4].hour2() << F(":") << Timer[4].minute2() << F(":") << Timer[4].second2(); lcd.show(); } Btn.Do = [] { Timer[4].writeMinute1(var); var = Timer[4].hour1(); setPos(ss5hour1); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss5min1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss5min1); }; break; case ss5hour1: { lcd << F("Timer5>") << var << F(":") << Timer[4].minute1() << F(":") << Timer[4].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[4].hour2() << F(":") << Timer[4].minute2() << F(":") << Timer[4].second2(); lcd.show(); } Btn.Do = [] { Timer[4].writeHour1(var); var = Timer[4].second2(); setPos(ss5sec2); }; JoyUD.Do1 = [] { if (var < 23)var++; setPos(ss5hour1); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss5hour1); }; break; case ss5sec2: { lcd << F("Timer5:") << Timer[4].hour1() << F(":") << Timer[4].minute1() << F(":") << Timer[4].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[4].hour2() << F(":") << Timer[4].minute2() << F(">") << var; lcd.show(); } Btn.Do = [] { Timer[4].writeSecond2(var); var = Timer[4].minute2(); setPos(ss5min2); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss5sec2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss5sec2); }; break; case ss5min2: { lcd << F("Timer5:") << Timer[4].hour1() << F(":") << Timer[4].minute1() << F(":") << Timer[4].second1(); lcd.setCursor(0, 1); lcd << F(" ") << Timer[4].hour2() << F(">") << var << F(":") << Timer[4].second2(); lcd.show(); } Btn.Do = [] { Timer[4].writeMinute2(var); var = Timer[4].hour2(); setPos(ss5hour2); }; JoyUD.Do1 = [] { if (var < 59)var++; setPos(ss5min2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss5min2); }; break; case ss5hour2: { lcd << F("Timer5:") << Timer[4].hour1() << F(":") << Timer[4].minute1() << F(":") << Timer[4].second1(); lcd.setCursor(0, 1); lcd << F(" >") << var << F(":") << Timer[4].minute2() << F(":") << Timer[4].second2(); lcd.show(); } Btn.Do = [] { Timer[4].writeHour2(var); setPos(ss5); }; JoyUD.Do1 = [] { if (var < 23)var++; setPos(ss5hour2); }; JoyUD.Do2 = [] { if (var > 0)var--; setPos(ss5hour2); }; break; } } void menuInit() { setPos(sMain); } void menuRun() { if (pos != sMain && millis() - past >= 10000)setPos(sMain); if (pos == sMain && millis() - past >= 1000)setPos(sMain); } //---------------------------------- void setup() { lcd.init(); clock.init(); saveZeroSettings(); for (int i = 0; i < numTimer; i++)Timer[i].init(); Btn.init(); JoyLR.init(); JoyUD.init(); menuInit(); JoyLR.Do1 = [] {lcd.backlight();}; JoyLR.Do2 = [] {lcd.noBacklight();}; } void loop() { clock.run(); for (int i = 0; i < numTimer; i++)Timer[i].run(); Btn.run(); JoyLR.run(); JoyUD.run(); menuRun(); } /**/Возможно это баян. Но вставив этот код в скетч вы всегда будете знать время последней зашивки кода
void setup() { Serial.begin(9600); Serial.print(F("data:")); Serial.println(F(__DATE__)); Serial.print(F("time:")); Serial.println(F(__TIME__)); } void loop() { }баян, еще какой.
тебе совсем там плохо ?
Может не NAME а всеже __FILE__? Да и VERSION - сугубо личное наверно.
Как бы расположение мне не особо нужно...
Да, и то и другое сугубо личное, но иногда полезное. С особо одарёнными заказчиками(.
Мой программный компонент для модуля DS3231
/**/ template <typename T> inline Print & operator << (Print &s, T n) { s.print(n); return s; } //-----часы----------------------- uint8_t conv2d(const char* p) { uint8_t v = 0; if ('0' <= *p && *p <= '9') v = *p - '0'; return 10 * v + *++p - '0'; } class dTime { protected: public: byte hh, mm, ss; dTime(unsigned long t = 0) : hh(t / 60 / 60 % 24), mm(t / 60 % 60), ss(t % 60) {} dTime(byte h, byte m, byte s) : hh(h), mm(m), ss(s) {} dTime(const dTime& t)// : hh(copy.hh), mm(copy.mm), ss(copy.ss) { hh = t.hh; mm = t.mm; ss = t.ss; } dTime(const char* time) { hh = conv2d(time); mm = conv2d(time + 3); ss = conv2d(time + 6); } dTime(const __FlashStringHelper* time) { char buff[8]; memcpy_P(buff, time, 8); hh = conv2d(buff); mm = conv2d(buff + 3); ss = conv2d(buff + 6); } dTime& operator=(const dTime& t) { if (this == &t) return *this; hh = t.hh; mm = t.mm; ss = t.ss; return *this; } }; #define DS3231_ADDRESS 0x68 #define DS3231_CONTROL 0x0E #define DS3231_STATUSREG 0x0F #include <Wire.h> uint8_t read_i2c_register(uint8_t addr, uint8_t reg) { Wire.beginTransmission(addr); Wire.write((byte)reg); Wire.endTransmission(); Wire.requestFrom(addr, (byte)1); return Wire.read(); } void write_i2c_register(uint8_t addr, uint8_t reg, uint8_t val) { Wire.beginTransmission(addr); Wire.write((byte)reg); Wire.write((byte)val); Wire.endTransmission(); } uint8_t bcd2bin (uint8_t val) { return val - 6 * (val >> 4); } uint8_t bin2bcd (uint8_t val) { return val + 6 * (val / 10); } class RTC_DS3231 { public: void write(dTime t) { Wire.beginTransmission(DS3231_ADDRESS); Wire.write((byte)0); // start at location 0 Wire.write(bin2bcd(t.ss)); Wire.write(bin2bcd(t.mm)); Wire.write(bin2bcd(t.hh)); Wire.endTransmission(); uint8_t statreg = read_i2c_register(DS3231_ADDRESS, DS3231_STATUSREG); statreg &= ~0x80; // flip OSF bit write_i2c_register(DS3231_ADDRESS, DS3231_STATUSREG, statreg); } dTime read() { Wire.beginTransmission(DS3231_ADDRESS); Wire.write((byte)0); Wire.endTransmission(); Wire.requestFrom(DS3231_ADDRESS, 7); uint8_t s = bcd2bin(Wire.read() & 0x7F); uint8_t m = bcd2bin(Wire.read()); uint8_t h = bcd2bin(Wire.read()); return dTime(h, m, s); } }; RTC_DS3231 rtc; //----------------------------- void setup() { Serial.begin(9600); Wire.begin(); rtc.write(F(__TIME__)); } void loop() { delay(1000); dTime now(rtc.read()); Serial << now.hh << F(":") << now.mm << F(":") << now.ss << F("\n"); } /**/Добавил к часам управление 4-мя реле . Удачно получилось.
/* часы с ручной установкой времени на DS3231*/ // Оборудование // Ардуино Нано // lcd1602_i2c -- I2C // модуль DS3231 -- I2C // ардуино джойстик кнопка A0 потенциометры A1,A2 // модуль реле 2,3,4,5 //---------------lcd--------------------------------------------- template <typename T> inline Print & operator << (Print &s, T n) { s.print(n); return s; } //------дисплей lcd1602_i2c----------------------------- // даташит https://www.sparkfun.com/datasheets/LCD/ADM1602K-NSW-FBS-3.3v.pdf // на русском http://www.melt.aha.ru/pdf/mt-16s2h.pdf #include <Wire.h> // команды #define LCD_CLEARDISPLAY 0x01 #define LCD_RETURNHOME 0x02 #define LCD_ENTRYMODESET 0x04 #define LCD_DISPLAYCONTROL 0x08 #define LCD_CURSORSHIFT 0x10 #define LCD_FUNCTIONSET 0x20 #define LCD_SETCGRAMADDR 0x40 #define LCD_SETDDRAMADDR 0x80 // флаги для режима ввода дисплея #define LCD_ENTRYRIGHT 0x00 #define LCD_ENTRYLEFT 0x02 #define LCD_ENTRYSHIFTINCREMENT 0x01 #define LCD_ENTRYSHIFTDECREMENT 0x00 // флаги для управления включением / выключением дисплея #define LCD_DISPLAYON 0x04 #define LCD_DISPLAYOFF 0x00 #define LCD_CURSORON 0x02 #define LCD_CURSOROFF 0x00 #define LCD_BLINKON 0x01 #define LCD_BLINKOFF 0x00 // флаги для отображения / сдвига курсора #define LCD_DISPLAYMOVE 0x08 #define LCD_CURSORMOVE 0x00 #define LCD_MOVERIGHT 0x04 #define LCD_MOVELEFT 0x00 // флаги для набора функций #define LCD_8BITMODE 0x10 #define LCD_4BITMODE 0x00 #define LCD_2LINE 0x08 #define LCD_1LINE 0x00 #define LCD_5x10DOTS 0x04 #define LCD_5x8DOTS 0x00 // флаги для управления подсветкой #define LCD_lightON 0x08 #define LCD_lightOFF 0x00 #define En B00000100 // Бит разрешения #define Rw B00000010 // Чтение / запись бит #define Rs B00000001 // Бит выбора регистра class Cl_lcd1602_i2c : public Print { protected: uint8_t adr, posX, posY; uint8_t _lightONval; uint8_t _displayfunction; uint8_t _displaycontrol; uint8_t _displaymode; byte buffer[32]; public: Cl_lcd1602_i2c(uint8_t a): adr(a) {} void init() { Wire.begin(); write4bits(0x03 << 4); delayMicroseconds(4500); // wait min 4.1ms write4bits(0x03 << 4); delayMicroseconds(4500); // wait min 4.1ms write4bits(0x03 << 4); delayMicroseconds(150); write4bits(0x02 << 4); delay(50); _lightONval = LCD_lightOFF; expanderWrite(_lightONval); // сбросить расширение и выключить подсветку (бит 8 = 1) // режим работы дисплея 4-х битный интерфейс ,две строки,5х8 точек _displayfunction = LCD_4BITMODE | LCD_2LINE | LCD_5x8DOTS; command(LCD_FUNCTIONSET | _displayfunction); // режим контроля дисплей вкл, курсор не мигает,дисплей не мигает _displaycontrol = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF; command(LCD_DISPLAYCONTROL | _displaycontrol); // режим ввода текста в память-начинать слева с движением в право _displaymode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT; command(LCD_ENTRYMODESET | _displaymode); clear(); } // подсветку вкл/выкл void lightON(void) { _lightONval = LCD_lightON; expanderWrite(0); } void lightOFF(void) { _lightONval = LCD_lightOFF; expanderWrite(0); } // очистить буфер void clear() { for (byte i = 0; i < 32; i++ )buffer[i] = 0x20; posX = 0; posY = 0; } // отправить информацию из буфера на экран void show() { line(0); for (byte i = 0; i < 16; i++ )out(buffer[i]); line(1); for (byte i = 16; i < 32; i++ )out(buffer[i]); } void setCursor(byte x, byte y) { if (x > 16) x = 16; else posX = x; if (y > 2) x = 2; else posY = y; } private: /*внутрение функции*/ void line(byte l) { if (l == 0) command(LCD_SETDDRAMADDR | 0x00); else command(LCD_SETDDRAMADDR | 0x40); } inline void out(uint8_t value) { send(value, Rs); } inline size_t write(uint8_t value) { if (posX < 16 && posY < 2) { buffer[posY * 16 + posX] = value; posX++; } return 1; } /*команды низкоуровневого управления*/ inline void command(uint8_t value) { send(value, 0); } void send(uint8_t value, uint8_t mode) { uint8_t highnib = value & 0xf0; write4bits((highnib) | mode); uint8_t lownib = (value << 4) & 0xf0; write4bits((lownib) | mode); } void write4bits(uint8_t value) { expanderWrite(value); pulseEnable(value); } void expanderWrite(uint8_t _data) { Wire.beginTransmission(adr); Wire.write((int)(_data) | _lightONval); Wire.endTransmission(); } void pulseEnable(uint8_t _data) { expanderWrite(_data | En); // En high delayMicroseconds(1); // enable pulse must be >450ns expanderWrite(_data & ~En); // En low delayMicroseconds(50); // commands need > 37us to settle } }; Cl_lcd1602_i2c lcd(0x27);//0x3F //-----часы----------------------- uint8_t conv2d(const char* p) { uint8_t v = 0; if ('0' <= *p && *p <= '9') v = *p - '0'; return 10 * v + *++p - '0'; } class dTime { protected: public: byte hh, mm, ss; unsigned long time() { return ((hh * 24 + mm) * 60 + ss); } dTime(unsigned long t = 0) : hh(t / 60 / 60 % 24), mm(t / 60 % 60), ss(t % 60) {} dTime(byte h, byte m, byte s) : hh(h), mm(m), ss(s) {} dTime(const dTime& t)// : hh(copy.hh), mm(copy.mm), ss(copy.ss) { hh = t.hh; mm = t.mm; ss = t.ss; } dTime(const char* time) { hh = conv2d(time); mm = conv2d(time + 3); ss = conv2d(time + 6); } dTime(const __FlashStringHelper* time) { char buff[8]; memcpy_P(buff, time, 8); hh = conv2d(buff); mm = conv2d(buff + 3); ss = conv2d(buff + 6); } dTime& operator=(const dTime& t) { if (this == &t) return *this; hh = t.hh; mm = t.mm; ss = t.ss; return *this; } }; #define DS3231_ADDRESS 0x68 #define DS3231_CONTROL 0x0E #define DS3231_STATUSREG 0x0F #include <Wire.h> uint8_t read_i2c_register(uint8_t addr, uint8_t reg) { Wire.beginTransmission(addr); Wire.write((byte)reg); Wire.endTransmission(); Wire.requestFrom(addr, (byte)1); return Wire.read(); } void write_i2c_register(uint8_t addr, uint8_t reg, uint8_t val) { Wire.beginTransmission(addr); Wire.write((byte)reg); Wire.write((byte)val); Wire.endTransmission(); } uint8_t bcd2bin (uint8_t val) { return val - 6 * (val >> 4); } uint8_t bin2bcd (uint8_t val) { return val + 6 * (val / 10); } class RTC_DS3231 { public: void write(dTime t) { Wire.beginTransmission(DS3231_ADDRESS); Wire.write((byte)0); // start at location 0 Wire.write(bin2bcd(t.ss)); Wire.write(bin2bcd(t.mm)); Wire.write(bin2bcd(t.hh)); Wire.endTransmission(); uint8_t statreg = read_i2c_register(DS3231_ADDRESS, DS3231_STATUSREG); statreg &= ~0x80; // flip OSF bit write_i2c_register(DS3231_ADDRESS, DS3231_STATUSREG, statreg); } dTime read() { Wire.beginTransmission(DS3231_ADDRESS); Wire.write((byte)0); Wire.endTransmission(); Wire.requestFrom(DS3231_ADDRESS, 7); uint8_t s = bcd2bin(Wire.read() & 0x7F); uint8_t m = bcd2bin(Wire.read()); uint8_t h = bcd2bin(Wire.read()); return dTime(h, m, s); } }; RTC_DS3231 rtc;// часы dTime now;//текущее время //--------------Реле------------------------------------------------ typedef struct { byte hour; byte minute; byte second; } timer_t; class cl_timer { protected: timer_t *adr; public: cl_timer(timer_t *a): adr(a) {} void save(unsigned long t = 0) { setHour(t / 60 / 60 % 24); setMinute(t / 60 % 60); setSecond(t % 60); } void save(const char* time) { setHour(conv2d(time)); setMinute(conv2d(time + 3)); setSecond(conv2d(time + 6)); } void save(const __FlashStringHelper* time) { char buff[8]; memcpy_P(buff, time, 8); setHour(conv2d(buff)); setMinute(conv2d(buff + 3)); setSecond(conv2d(buff + 6)); } byte hour() { return eeprom_read_byte(&(adr->hour)); }; byte minute() { return eeprom_read_byte(&(adr->minute)); }; byte second() { return eeprom_read_byte(&(adr->second)); }; byte time() { return ((hour() * 24 + minute()) * 60 + second()); }; void setHour(byte h) { eeprom_write_byte(&adr->hour, h); } void setMinute(byte m) { eeprom_write_byte(&adr->minute, m); } void setSecond(byte s) { eeprom_write_byte(&adr->second, s); } }; /*состояния таймера*/ const byte sOFF = 0; const byte sON = 1; const byte sEND = 2; class Cl_Relay { protected: byte pin; byte state; void set(byte s) { state = s; switch (s) { case sOFF: digitalWrite(pin, HIGH); break; case sON: digitalWrite(pin, LOW); break; case sEND: digitalWrite(pin, HIGH); break; } } public: cl_timer timeON, timeOFF; Cl_Relay(byte p, cl_timer t1, cl_timer t2) : pin(p), timeON(t1), timeOFF(t2) {} void init() { pinMode(pin, OUTPUT); set(sOFF) ; } void run() { switch (state) { case sOFF: if (now.time() >= timeON.time())set(sON); break; case sON: if (now.time() >= timeOFF.time())set(sEND); break; case sEND: break; } } void reset() { set(sOFF) ; } }; const byte RelayNum = 4; //кол-во реле timer_t EEMEM adr[RelayNum * 2]; Cl_Relay Relay[RelayNum] = { Cl_Relay(/*пин*/2, &adr[0], &adr[1]),// 1-е реле Cl_Relay(/*пин*/3, &adr[2], &adr[3]),// 2-е реле Cl_Relay(/*пин*/4, &adr[4], &adr[5]),// 3-е реле Cl_Relay(/*пин*/5, &adr[6], &adr[7]) // 4-е реле }; // первичные настройки в EEPROM void setZero() { Relay[0].timeON.save(F("00:00:30")); Relay[0].timeOFF.save(F("00:02:30"));// 1-е реле Relay[1].timeON.save(F("00:01:00")); Relay[1].timeOFF.save(F("00:03:00"));// 2-е реле Relay[2].timeON.save(F("00:01:30")); Relay[2].timeOFF.save(F("00:03:30"));// 3-е реле Relay[3].timeON.save(F("00:02:00")); Relay[3].timeOFF.save(F("00:04:00"));// 4-е реле } //---кнопкa----------------------------- typedef void (*pDo)(); class Cl_btn { protected: byte pin; bool state; unsigned long past; void set(bool s) { state = s; past = millis(); switch (s) { case false: break; case true: Do(); break; } } public: Cl_btn(byte p): pin(p) {} pDo Do = [] {}; void init() { pinMode(pin, INPUT_PULLUP); set(false); } void run() { if (millis() - past >= 100) switch (state) { case false: if (!digitalRead(pin))set(true); break; case true: if (digitalRead(pin))set(false); if (millis() - past >= 300)set(false); break; } } }; Cl_btn Btn(/*пин*/A0); //------------------------------------------- const byte st1 = 0; const byte st0 = 1; const byte st2 = 2; class Cl_joystic { protected: byte pin; byte state; unsigned long past; void set(byte s) { state = s; past = millis(); switch (s) { case st0: break; case st1: Do1(); break; case st2: Do2(); break; } } public: Cl_joystic(byte p): pin(p) {} pDo Do1 = [] {}; pDo Do2 = [] {}; void init() { set(st0); } void run() { if (millis() - past >= 100) { int tmp = analogRead(pin); switch (state) { case st1: if (tmp > 450)set(st0); if (millis() - past >= 300)set(st0); break; case st0: if (tmp < 400)set(st1); else if (tmp > 600)set(st2); break; case st2: if (tmp < 550)set(st0); if (millis() - past >= 300)set(st0); break; } } } }; Cl_joystic JoyLR(/*пин*/A1); Cl_joystic JoyUD(/*пин*/A2); //---------меню---------------- const byte scr0 = 0; // показ времени const byte scr1 = 10; // показ времени реле1 вкл/выкл const byte scr1_hour1 = 11; // установка часов реле1 вкл const byte scr1_min1 = 12; // установка минут реле1 вкл const byte scr1_sec1 = 13; // установка секунд реле1 вкл const byte scr1_hour2 = 14; // установка часов реле1 выкл const byte scr1_min2 = 15; // установка минут реле1 выкл const byte scr1_sec2 = 16; // установка секунд реле1 выкл const byte scr2 = 20; // показ времени реле2 вкл/выкл const byte scr2_hour1 = 21; // установка часов реле2 вкл const byte scr2_min1 = 22; // установка минут реле2 вкл const byte scr2_sec1 = 23; // установка секунд реле2 вкл const byte scr2_hour2 = 24; // установка часов реле2 выкл const byte scr2_min2 = 25; // установка минут реле2 выкл const byte scr2_sec2 = 26; // установка секунд реле2 выкл const byte scr3 = 30; // показ времени реле3 вкл/выкл const byte scr3_hour1 = 31; // установка часов реле3 вкл const byte scr3_min1 = 32; // установка минут реле3 вкл const byte scr3_sec1 = 33; // установка секунд реле3 вкл const byte scr3_hour2 = 34; // установка часов реле3 выкл const byte scr3_min2 = 35; // установка минут реле3 выкл const byte scr3_sec2 = 36; // установка секунд реле3 выкл const byte scr4 = 40; // показ времени реле4 вкл/выкл const byte scr4_hour1 = 41; // установка часов реле4 вкл const byte scr4_min1 = 42; // установка минут реле4 вкл const byte scr4_sec1 = 43; // установка секунд реле4 вкл const byte scr4_hour2 = 44; // установка часов реле4 выкл const byte scr4_min2 = 45; // установка минут реле4 выкл const byte scr4_sec2 = 46; // установка секунд реле4 выкл const byte scr5 = 50; const byte scr5_hour = 51; // установка времени часы const byte scr5_min = 52; // установка времени минуты const byte scr5_sec = 53; // установка времени секунд const byte scr5_res = 54; // установка времени секунд byte scr; // номер экрана unsigned long past;// фик времени в этом экране byte var;// переменная для редактирования dTime Time;// переменая времени void go(byte s) { scr = s; past = millis(); lcd.clear(); switch (s) { case scr0: { // 0- экран lcd << now.hh << F(":") << now.mm << F(":") << now.ss ; lcd.show(); } Btn.Do = [] {}; JoyLR.Do1 = [] {}; JoyLR.Do2 = [] {go(scr1);}; break; case scr1: { // ------------------------------1- экран lcd << F("Re1 ") << Relay[0].timeON.hour() << F(":") << Relay[0].timeON.minute() << F(":") << Relay[0].timeON.second(); lcd.setCursor(4, 1); lcd << Relay[0].timeOFF.hour() << F(":") << Relay[0].timeOFF.minute() << F(":") << Relay[0].timeOFF.second(); lcd.show(); } Btn.Do = [] { var = Relay[0].timeON.hour(); go(scr1_hour1); }; JoyLR.Do1 = [] {go(scr0);}; JoyLR.Do2 = [] {go(scr2);}; break; case scr1_hour1: { // установка часов реле1 вкл lcd << F("Re1>") << var << F(":") << Relay[0].timeON.minute() << F(":") << Relay[0].timeON.second(); lcd.setCursor(4, 1); lcd << Relay[0].timeOFF.hour() << F(":") << Relay[0].timeOFF.minute() << F(":") << Relay[0].timeOFF.second(); lcd.show(); } Btn.Do = [] { Relay[0].timeON.setHour(var); var = Relay[0].timeON.minute(); go(scr1_min1); }; JoyLR.Do1 = [] { if (var < 23)var++; go(scr1_hour1); }; JoyLR.Do2 = [] { if (var > 0)var--; go(scr1_hour1); }; break; case scr1_min1: { // установка минут реле1 вкл lcd << F("Re1 ") << Relay[0].timeON.hour() << F(">") << var << F(":") << Relay[0].timeON.second(); lcd.setCursor(4, 1); lcd << Relay[0].timeOFF.hour() << F(":") << Relay[0].timeOFF.minute() << F(":") << Relay[0].timeOFF.second(); lcd.show(); } Btn.Do = [] { Relay[0].timeON.setMinute(var); var = Relay[0].timeON.second(); go(scr1_sec1); }; JoyLR.Do1 = [] { if (var < 59)var++; go(scr1_min1); }; JoyLR.Do2 = [] { if (var > 0)var--; go(scr1_min1); }; break; case scr1_sec1: { // установка секунд реле1 вкл lcd << F("Re1 ") << Relay[0].timeON.hour() << F(":") << Relay[0].timeON.minute() << F(">") << var; lcd.setCursor(4, 1); lcd << Relay[0].timeOFF.hour() << F(":") << Relay[0].timeOFF.minute() << F(":") << Relay[0].timeOFF.second(); lcd.show(); } Btn.Do = [] { Relay[0].timeON.setSecond(var); var = Relay[0].timeOFF.hour(); go(scr1_hour2); }; JoyLR.Do1 = [] { if (var < 59)var++; go(scr1_sec1); }; JoyLR.Do2 = [] { if (var > 0)var--; go(scr1_sec1); }; break; case scr1_hour2: { // установка часов реле1 выкл lcd << F("Re1 ") << Relay[0].timeON.hour() << F(":") << Relay[0].timeON.minute() << F(":") << Relay[0].timeON.second(); lcd.setCursor(3, 1); lcd << F(">") << var << F(":") << Relay[0].timeOFF.minute() << F(":") << Relay[0].timeOFF.second(); lcd.show(); } Btn.Do = [] { Relay[0].timeOFF.setHour(var); var = Relay[0].timeOFF.minute(); go(scr1_min2); }; JoyLR.Do1 = [] { if (var < 23)var++; go(scr1_hour2); }; JoyLR.Do2 = [] { if (var > 0)var--; go(scr1_hour2); }; break; case scr1_min2: { // установка минут реле1 выкл lcd << F("Re1 ") << Relay[0].timeON.hour() << F(":") << Relay[0].timeON.minute() << F(":") << Relay[0].timeON.second(); lcd.setCursor(4, 1); lcd << Relay[0].timeOFF.hour() << F(">") << var << F(":") << Relay[0].timeOFF.second(); lcd.show(); } Btn.Do = [] { Relay[0].timeOFF.setMinute(var); var = Relay[0].timeOFF.second(); go(scr1_sec2); }; JoyLR.Do1 = [] { if (var < 59)var++; go(scr1_min2); }; JoyLR.Do2 = [] { if (var > 0)var--; go(scr1_min2); }; break; case scr1_sec2: { // установка секунд реле1 выкл lcd << F("Re1 ") << Relay[0].timeON.hour() << F(":") << Relay[0].timeON.minute() << F(":") << Relay[0].timeON.second(); lcd.setCursor(4, 1); lcd << Relay[0].timeOFF.hour() << F(":") << Relay[0].timeOFF.minute() << F(">") << var; lcd.show(); } Btn.Do = [] { Relay[0].timeOFF.setSecond(var); go(scr1); }; JoyLR.Do1 = [] { if (var < 59)var++; go(scr1_sec2); }; JoyLR.Do2 = [] { if (var > 0)var--; go(scr1_sec2); }; break; case scr2: { //------------------------------------------------ 2- экран lcd << F("Re2 ") << Relay[1].timeON.hour() << F(":") << Relay[1].timeON.minute() << F(":") << Relay[1].timeON.second(); lcd.setCursor(4, 1); lcd << Relay[1].timeOFF.hour() << F(":") << Relay[1].timeOFF.minute() << F(":") << Relay[1].timeOFF.second(); lcd.show(); } Btn.Do = [] { var = Relay[1].timeON.hour(); go(scr2_hour1); }; JoyLR.Do1 = [] {go(scr1);}; JoyLR.Do2 = [] {go(scr3);}; break; case scr2_hour1: { // установка часов реле2 вкл lcd << F("Re2>") << var << F(":") << Relay[1].timeON.minute() << F(":") << Relay[1].timeON.second(); lcd.setCursor(4, 1); lcd << Relay[1].timeOFF.hour() << F(":") << Relay[1].timeOFF.minute() << F(":") << Relay[1].timeOFF.second(); lcd.show(); } Btn.Do = [] { Relay[1].timeON.setHour(var); var = Relay[1].timeON.minute(); go(scr2_min1); }; JoyLR.Do1 = [] { if (var < 23)var++; go(scr2_hour1); }; JoyLR.Do2 = [] { if (var > 0)var--; go(scr2_hour1); }; break; case scr2_min1: { // установка минут реле2 вкл lcd << F("Re2 ") << Relay[1].timeON.hour() << F(">") << var << F(":") << Relay[1].timeON.second(); lcd.setCursor(4, 1); lcd << Relay[1].timeOFF.hour() << F(":") << Relay[1].timeOFF.minute() << F(":") << Relay[1].timeOFF.second(); lcd.show(); } Btn.Do = [] { Relay[1].timeON.setMinute(var); var = Relay[1].timeON.second(); go(scr2_sec1); }; JoyLR.Do1 = [] { if (var < 59)var++; go(scr2_min1); }; JoyLR.Do2 = [] { if (var > 0)var--; go(scr2_min1); }; break; case scr2_sec1: { // установка секунд реле2 вкл lcd << F("Re2 ") << Relay[1].timeON.hour() << F(":") << Relay[1].timeON.minute() << F(">") << var; lcd.setCursor(4, 1); lcd << Relay[1].timeOFF.hour() << F(":") << Relay[1].timeOFF.minute() << F(":") << Relay[1].timeOFF.second(); lcd.show(); } Btn.Do = [] { Relay[1].timeON.setSecond(var); var = Relay[1].timeOFF.hour(); go(scr2_hour2); }; JoyLR.Do1 = [] { if (var < 59)var++; go(scr2_sec1); }; JoyLR.Do2 = [] { if (var > 0)var--; go(scr2_sec1); }; break; case scr2_hour2: { // установка часов реле2 выкл lcd << F("Re2 ") << Relay[1].timeON.hour() << F(":") << Relay[1].timeON.minute() << F(":") << Relay[1].timeON.second(); lcd.setCursor(3, 1); lcd << F(">") << var << F(":") << Relay[1].timeOFF.minute() << F(":") << Relay[1].timeOFF.second(); lcd.show(); } Btn.Do = [] { Relay[1].timeOFF.setHour(var); var = Relay[1].timeOFF.minute(); go(scr2_min2); }; JoyLR.Do1 = [] { if (var < 23)var++; go(scr2_hour2); }; JoyLR.Do2 = [] { if (var > 0)var--; go(scr2_hour2); }; break; case scr2_min2: { // установка минут реле2 выкл lcd << F("Re2 ") << Relay[1].timeON.hour() << F(":") << Relay[1].timeON.minute() << F(":") << Relay[1].timeON.second(); lcd.setCursor(4, 1); lcd << Relay[1].timeOFF.hour() << F(">") << var << F(":") << Relay[1].timeOFF.second(); lcd.show(); } Btn.Do = [] { Relay[1].timeOFF.setMinute(var); var = Relay[1].timeOFF.second(); go(scr2_sec2); }; JoyLR.Do1 = [] { if (var < 59)var++; go(scr2_min2); }; JoyLR.Do2 = [] { if (var > 0)var--; go(scr2_min2); }; break; case scr2_sec2: { // установка секунд реле2 выкл lcd << F("Re2 ") << Relay[1].timeON.hour() << F(":") << Relay[1].timeON.minute() << F(":") << Relay[1].timeON.second(); lcd.setCursor(4, 1); lcd << Relay[1].timeOFF.hour() << F(":") << Relay[1].timeOFF.minute() << F(">") << var; lcd.show(); } Btn.Do = [] { Relay[1].timeOFF.setSecond(var); go(scr2); }; JoyLR.Do1 = [] { if (var < 59)var++; go(scr2_sec2); }; JoyLR.Do2 = [] { if (var > 0)var--; go(scr2_sec2); }; break; case scr3: { //---------------------------------- 3- экран lcd << F("Re3 ") << Relay[2].timeON.hour() << F(":") << Relay[2].timeON.minute() << F(":") << Relay[2].timeON.second(); lcd.setCursor(4, 1); lcd << Relay[2].timeOFF.hour() << F(":") << Relay[2].timeOFF.minute() << F(":") << Relay[2].timeOFF.second(); lcd.show(); } Btn.Do = [] { var = Relay[2].timeON.hour(); go(scr3_hour1); }; JoyLR.Do1 = [] {go(scr2);}; JoyLR.Do2 = [] {go(scr4);}; break; case scr3_hour1: { // установка часов реле3 вкл lcd << F("Re3>") << var << F(":") << Relay[2].timeON.minute() << F(":") << Relay[2].timeON.second(); lcd.setCursor(4, 1); lcd << Relay[2].timeOFF.hour() << F(":") << Relay[2].timeOFF.minute() << F(":") << Relay[2].timeOFF.second(); lcd.show(); } Btn.Do = [] { Relay[2].timeON.setHour(var); var = Relay[2].timeON.minute(); go(scr3_min1); }; JoyLR.Do1 = [] { if (var < 23)var++; go(scr3_hour1); }; JoyLR.Do2 = [] { if (var > 0)var--; go(scr3_hour1); }; break; case scr3_min1: { // установка минут реле1 вкл lcd << F("Re3 ") << Relay[2].timeON.hour() << F(">") << var << F(":") << Relay[2].timeON.second(); lcd.setCursor(4, 1); lcd << Relay[2].timeOFF.hour() << F(":") << Relay[2].timeOFF.minute() << F(":") << Relay[2].timeOFF.second(); lcd.show(); } Btn.Do = [] { Relay[2].timeON.setMinute(var); var = Relay[2].timeON.second(); go(scr3_sec1); }; JoyLR.Do1 = [] { if (var < 59)var++; go(scr3_min1); }; JoyLR.Do2 = [] { if (var > 0)var--; go(scr3_min1); }; break; case scr3_sec1: { // установка секунд реле3 вкл lcd << F("Re3 ") << Relay[2].timeON.hour() << F(":") << Relay[2].timeON.minute() << F(">") << var; lcd.setCursor(4, 1); lcd << Relay[2].timeOFF.hour() << F(":") << Relay[2].timeOFF.minute() << F(":") << Relay[2].timeOFF.second(); lcd.show(); } Btn.Do = [] { Relay[2].timeON.setSecond(var); var = Relay[2].timeOFF.hour(); go(scr3_hour2); }; JoyLR.Do1 = [] { if (var < 59)var++; go(scr3_sec1); }; JoyLR.Do2 = [] { if (var > 0)var--; go(scr3_sec1); }; break; case scr3_hour2: { // установка часов реле3 выкл lcd << F("Re3 ") << Relay[2].timeON.hour() << F(":") << Relay[2].timeON.minute() << F(":") << Relay[2].timeON.second(); lcd.setCursor(3, 1); lcd << F(">") << var << F(":") << Relay[2].timeOFF.minute() << F(":") << Relay[2].timeOFF.second(); lcd.show(); } Btn.Do = [] { Relay[2].timeOFF.setHour(var); var = Relay[2].timeOFF.minute(); go(scr3_min2); }; JoyLR.Do1 = [] { if (var < 23)var++; go(scr3_hour2); }; JoyLR.Do2 = [] { if (var > 0)var--; go(scr3_hour2); }; break; case scr3_min2: { // установка минут реле3 выкл lcd << F("Re3 ") << Relay[2].timeON.hour() << F(":") << Relay[2].timeON.minute() << F(":") << Relay[2].timeON.second(); lcd.setCursor(4, 1); lcd << Relay[2].timeOFF.hour() << F(">") << var << F(":") << Relay[2].timeOFF.second(); lcd.show(); } Btn.Do = [] { Relay[0].timeOFF.setMinute(var); var = Relay[0].timeOFF.second(); go(scr3_sec2); }; JoyLR.Do1 = [] { if (var < 59)var++; go(scr3_min2); }; JoyLR.Do2 = [] { if (var > 0)var--; go(scr3_min2); }; break; case scr3_sec2: { // установка секунд реле3 выкл lcd << F("Re3 ") << Relay[2].timeON.hour() << F(":") << Relay[2].timeON.minute() << F(":") << Relay[2].timeON.second(); lcd.setCursor(4, 1); lcd << Relay[2].timeOFF.hour() << F(":") << Relay[2].timeOFF.minute() << F(">") << var; lcd.show(); } Btn.Do = [] { Relay[3].timeOFF.setSecond(var); go(scr3); }; JoyLR.Do1 = [] { if (var < 59)var++; go(scr3_sec2); }; JoyLR.Do2 = [] { if (var > 0)var--; go(scr3_sec2); }; break; case scr4: { // 4- экран lcd << F("Re4 ") << Relay[3].timeON.hour() << F(":") << Relay[3].timeON.minute() << F(":") << Relay[3].timeON.second(); lcd.setCursor(4, 1); lcd << Relay[3].timeOFF.hour() << F(":") << Relay[3].timeOFF.minute() << F(":") << Relay[3].timeOFF.second(); lcd.show(); } Btn.Do = [] { var = Relay[3].timeON.hour(); go(scr4_hour1); }; JoyLR.Do1 = [] {go(scr3);}; JoyLR.Do2 = [] {go(scr5);}; break; case scr4_hour1: { // установка часов реле4 вкл lcd << F("Re4>") << var << F(":") << Relay[3].timeON.minute() << F(":") << Relay[3].timeON.second(); lcd.setCursor(4, 1); lcd << Relay[3].timeOFF.hour() << F(":") << Relay[3].timeOFF.minute() << F(":") << Relay[3].timeOFF.second(); lcd.show(); } Btn.Do = [] { Relay[3].timeON.setHour(var); var = Relay[3].timeON.minute(); go(scr4_min1); }; JoyLR.Do1 = [] { if (var < 23)var++; go(scr4_hour1); }; JoyLR.Do2 = [] { if (var > 0)var--; go(scr4_hour1); }; break; case scr4_min1: { // установка минут реле4 вкл lcd << F("Re4 ") << Relay[3].timeON.hour() << F(">") << var << F(":") << Relay[3].timeON.second(); lcd.setCursor(4, 1); lcd << Relay[3].timeOFF.hour() << F(":") << Relay[3].timeOFF.minute() << F(":") << Relay[3].timeOFF.second(); lcd.show(); } Btn.Do = [] { Relay[0].timeON.setMinute(var); var = Relay[0].timeON.second(); go(scr4_sec1); }; JoyLR.Do1 = [] { if (var < 59)var++; go(scr4_min1); }; JoyLR.Do2 = [] { if (var > 0)var--; go(scr4_min1); }; break; case scr4_sec1: { // установка секунд реле4 вкл lcd << F("Re4 ") << Relay[3].timeON.hour() << F(":") << Relay[3].timeON.minute() << F(">") << var; lcd.setCursor(4, 1); lcd << Relay[3].timeOFF.hour() << F(":") << Relay[3].timeOFF.minute() << F(":") << Relay[3].timeOFF.second(); lcd.show(); } Btn.Do = [] { Relay[0].timeON.setSecond(var); var = Relay[3].timeOFF.hour(); go(scr4_hour2); }; JoyLR.Do1 = [] { if (var < 59)var++; go(scr4_sec1); }; JoyLR.Do2 = [] { if (var > 0)var--; go(scr4_sec1); }; break; case scr4_hour2: { // установка часов реле4 выкл lcd << F("Re4 ") << Relay[3].timeON.hour() << F(":") << Relay[3].timeON.minute() << F(":") << Relay[3].timeON.second(); lcd.setCursor(3, 1); lcd << F(">") << var << F(":") << Relay[3].timeOFF.minute() << F(":") << Relay[3].timeOFF.second(); lcd.show(); } Btn.Do = [] { Relay[3].timeOFF.setHour(var); var = Relay[3].timeOFF.minute(); go(scr4_min2); }; JoyLR.Do1 = [] { if (var < 23)var++; go(scr4_hour2); }; JoyLR.Do2 = [] { if (var > 0)var--; go(scr4_hour2); }; break; case scr4_min2: { // установка минут реле4 выкл lcd << F("Re4 ") << Relay[3].timeON.hour() << F(":") << Relay[3].timeON.minute() << F(":") << Relay[3].timeON.second(); lcd.setCursor(4, 1); lcd << Relay[3].timeOFF.hour() << F(">") << var << F(":") << Relay[3].timeOFF.second(); lcd.show(); } Btn.Do = [] { Relay[3].timeOFF.setMinute(var); var = Relay[3].timeOFF.second(); go(scr4_sec2); }; JoyLR.Do1 = [] { if (var < 59)var++; go(scr4_min2); }; JoyLR.Do2 = [] { if (var > 0)var--; go(scr4_min2); }; break; case scr4_sec2: { // установка секунд реле4 выкл lcd << F("Re4 ") << Relay[3].timeON.hour() << F(":") << Relay[3].timeON.minute() << F(":") << Relay[3].timeON.second(); lcd.setCursor(4, 1); lcd << Relay[3].timeOFF.hour() << F(":") << Relay[3].timeOFF.minute() << F(">") << var; lcd.show(); } Btn.Do = [] { Relay[3].timeOFF.setSecond(var); go(scr4); }; JoyLR.Do1 = [] { if (var < 59)var++; go(scr4_sec2); }; JoyLR.Do2 = [] { if (var > 0)var--; go(scr4_sec2); }; break; case scr5: { // 5- экран lcd << F("SetTime:") << now.hh << F(":") << now.mm << F(":") << now.ss ; lcd.show(); } Btn.Do = [] { Time = now; go(scr5_hour); }; JoyLR.Do1 = [] {go(scr4);}; JoyLR.Do2 = [] {go(scr0);}; break; case scr5_hour: { lcd << F("SetTime>") << Time.hh << F(":") << Time.mm << F(":") << Time.ss; lcd.show(); } Btn.Do = [] {go(scr5_min);}; JoyLR.Do1 = [] { if (Time.hh > 0)Time.hh--; go(scr5_hour); }; JoyLR.Do2 = [] { if (Time.hh < 23)Time.hh++; go(scr5_hour); }; break; case scr5_min: { lcd << F("SetTime:") << Time.hh << F(">") << Time.mm << F(":") << Time.ss ; lcd.show(); } Btn.Do = [] {go(scr5_sec);}; JoyLR.Do1 = [] { if (Time.mm > 0)Time.mm--; go(scr5_min); }; JoyLR.Do2 = [] { if (Time.mm < 59)Time.mm++; go(scr5_min); }; break; case scr5_sec: { lcd << F("SetTime:") << Time.hh << F(":") << Time.mm << F(">") << Time.ss; lcd.show(); } Btn.Do = [] { rtc.write(Time); now = Time; go(scr5); }; JoyLR.Do1 = [] { if (Time.ss > 0)Time.ss--; go(scr5_sec); }; JoyLR.Do2 = [] { if (Time.ss < 59)Time.ss++; go(scr5_sec); }; break; } } void menuInit() { lcd.lightON(); now = rtc.read(); JoyUD.Do1 = [] {lcd.lightON();}; JoyUD.Do2 = [] {lcd.lightOFF();}; go(scr0); } void menuRun() { if (scr != scr0 && millis() - past >= 3000)go(scr0); if (scr == scr0 && millis() - past >= 500)go(scr0); } //----------------------------- void setup() { lcd.init(); rtc.write(F("00:00:00")); //rtc.write(F(__TIME__));//(для первичной настройки часов) setZero();////(для первичной настройки устройства) for (int i = 0; i < RelayNum; i++)Relay[i].init(); Btn.init(); JoyLR.init(); JoyUD.init(); menuInit(); } void loop() { now = rtc.read(); for (int i = 0; i < RelayNum; i++)Relay[i].run(); Btn.run(); JoyLR.run(); JoyUD.run(); menuRun(); } /**/Немного подправил скетч.
/* часы с ручной установкой времени на DS3231*/ // Оборудование // Ардуино Нано // lcd1602_i2c -- I2C // модуль DS3231 -- I2C // ардуино джойстик кнопка A0 потенциометры A1,A2 // модуль реле 2,3,4,5 //---------------lcd--------------------------------------------- template <typename T> inline Print & operator << (Print &s, T n) { s.print(n); return s; } //------дисплей lcd1602_i2c----------------------------- // даташит https://www.sparkfun.com/datasheets/LCD/ADM1602K-NSW-FBS-3.3v.pdf // на русском http://www.melt.aha.ru/pdf/mt-16s2h.pdf #include <Wire.h> // команды #define LCD_CLEARDISPLAY 0x01 #define LCD_RETURNHOME 0x02 #define LCD_ENTRYMODESET 0x04 #define LCD_DISPLAYCONTROL 0x08 #define LCD_CURSORSHIFT 0x10 #define LCD_FUNCTIONSET 0x20 #define LCD_SETCGRAMADDR 0x40 #define LCD_SETDDRAMADDR 0x80 // флаги для режима ввода дисплея #define LCD_ENTRYRIGHT 0x00 #define LCD_ENTRYLEFT 0x02 #define LCD_ENTRYSHIFTINCREMENT 0x01 #define LCD_ENTRYSHIFTDECREMENT 0x00 // флаги для управления включением / выключением дисплея #define LCD_DISPLAYON 0x04 #define LCD_DISPLAYOFF 0x00 #define LCD_CURSORON 0x02 #define LCD_CURSOROFF 0x00 #define LCD_BLINKON 0x01 #define LCD_BLINKOFF 0x00 // флаги для отображения / сдвига курсора #define LCD_DISPLAYMOVE 0x08 #define LCD_CURSORMOVE 0x00 #define LCD_MOVERIGHT 0x04 #define LCD_MOVELEFT 0x00 // флаги для набора функций #define LCD_8BITMODE 0x10 #define LCD_4BITMODE 0x00 #define LCD_2LINE 0x08 #define LCD_1LINE 0x00 #define LCD_5x10DOTS 0x04 #define LCD_5x8DOTS 0x00 // флаги для управления подсветкой #define LCD_lightON 0x08 #define LCD_lightOFF 0x00 #define En B00000100 // Бит разрешения #define Rw B00000010 // Чтение / запись бит #define Rs B00000001 // Бит выбора регистра class Cl_lcd1602_i2c : public Print { protected: uint8_t adr, posX, posY; uint8_t _lightONval; uint8_t _displayfunction; uint8_t _displaycontrol; uint8_t _displaymode; byte buffer[32]; public: Cl_lcd1602_i2c(uint8_t a): adr(a) {} void init() { Wire.begin(); write4bits(0x03 << 4); delayMicroseconds(4500); // wait min 4.1ms write4bits(0x03 << 4); delayMicroseconds(4500); // wait min 4.1ms write4bits(0x03 << 4); delayMicroseconds(150); write4bits(0x02 << 4); delay(50); _lightONval = LCD_lightOFF; expanderWrite(_lightONval); // сбросить расширение и выключить подсветку (бит 8 = 1) // режим работы дисплея 4-х битный интерфейс ,две строки,5х8 точек _displayfunction = LCD_4BITMODE | LCD_2LINE | LCD_5x8DOTS; command(LCD_FUNCTIONSET | _displayfunction); // режим контроля дисплей вкл, курсор не мигает,дисплей не мигает _displaycontrol = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF; command(LCD_DISPLAYCONTROL | _displaycontrol); // режим ввода текста в память-начинать слева с движением в право _displaymode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT; command(LCD_ENTRYMODESET | _displaymode); clear(); } // подсветку вкл/выкл void lightON(void) { _lightONval = LCD_lightON; expanderWrite(0); } void lightOFF(void) { _lightONval = LCD_lightOFF; expanderWrite(0); } // очистить буфер void clear() { for (byte i = 0; i < 32; i++ )buffer[i] = 0x20; posX = 0; posY = 0; } // отправить информацию из буфера на экран void show() { line(0); for (byte i = 0; i < 16; i++ )out(buffer[i]); line(1); for (byte i = 16; i < 32; i++ )out(buffer[i]); } void setCursor(byte x, byte y) { if (x > 16) x = 16; else posX = x; if (y > 2) x = 2; else posY = y; } private: /*внутрение функции*/ void line(byte l) { if (l == 0) command(LCD_SETDDRAMADDR | 0x00); else command(LCD_SETDDRAMADDR | 0x40); } inline void out(uint8_t value) { send(value, Rs); } inline size_t write(uint8_t value) { if (posX < 16 && posY < 2) { buffer[posY * 16 + posX] = value; posX++; } return 1; } /*команды низкоуровневого управления*/ inline void command(uint8_t value) { send(value, 0); } void send(uint8_t value, uint8_t mode) { uint8_t highnib = value & 0xf0; write4bits((highnib) | mode); uint8_t lownib = (value << 4) & 0xf0; write4bits((lownib) | mode); } void write4bits(uint8_t value) { expanderWrite(value); pulseEnable(value); } void expanderWrite(uint8_t _data) { Wire.beginTransmission(adr); Wire.write((int)(_data) | _lightONval); Wire.endTransmission(); } void pulseEnable(uint8_t _data) { expanderWrite(_data | En); // En high delayMicroseconds(1); // enable pulse must be >450ns expanderWrite(_data & ~En); // En low delayMicroseconds(50); // commands need > 37us to settle } }; Cl_lcd1602_i2c lcd(0x27);//0x3F //-----часы----------------------- uint8_t conv2d(const char* p) { uint8_t v = 0; if ('0' <= *p && *p <= '9') v = *p - '0'; return 10 * v + *++p - '0'; } class dTime { protected: public: byte hh, mm, ss; unsigned long time() { return ((hh * 24 + mm) * 60 + ss); } dTime(unsigned long t = 0) : hh(t / 60 / 60 % 24), mm(t / 60 % 60), ss(t % 60) {} dTime(byte h, byte m, byte s) : hh(h), mm(m), ss(s) {} dTime(const dTime& t)// : hh(copy.hh), mm(copy.mm), ss(copy.ss) { hh = t.hh; mm = t.mm; ss = t.ss; } dTime(const char* time) { hh = conv2d(time); mm = conv2d(time + 3); ss = conv2d(time + 6); } dTime(const __FlashStringHelper* time) { char buff[8]; memcpy_P(buff, time, 8); hh = conv2d(buff); mm = conv2d(buff + 3); ss = conv2d(buff + 6); } dTime& operator=(const dTime& t) { if (this == &t) return *this; hh = t.hh; mm = t.mm; ss = t.ss; return *this; } }; #define DS3231_ADDRESS 0x68 #define DS3231_CONTROL 0x0E #define DS3231_STATUSREG 0x0F #include <Wire.h> uint8_t read_i2c_register(uint8_t addr, uint8_t reg) { Wire.beginTransmission(addr); Wire.write((byte)reg); Wire.endTransmission(); Wire.requestFrom(addr, (byte)1); return Wire.read(); } void write_i2c_register(uint8_t addr, uint8_t reg, uint8_t val) { Wire.beginTransmission(addr); Wire.write((byte)reg); Wire.write((byte)val); Wire.endTransmission(); } uint8_t bcd2bin (uint8_t val) { return val - 6 * (val >> 4); } uint8_t bin2bcd (uint8_t val) { return val + 6 * (val / 10); } class RTC_DS3231 { public: void write(dTime t) { Wire.beginTransmission(DS3231_ADDRESS); Wire.write((byte)0); // start at location 0 Wire.write(bin2bcd(t.ss)); Wire.write(bin2bcd(t.mm)); Wire.write(bin2bcd(t.hh)); Wire.endTransmission(); uint8_t statreg = read_i2c_register(DS3231_ADDRESS, DS3231_STATUSREG); statreg &= ~0x80; // flip OSF bit write_i2c_register(DS3231_ADDRESS, DS3231_STATUSREG, statreg); } dTime read() { Wire.beginTransmission(DS3231_ADDRESS); Wire.write((byte)0); Wire.endTransmission(); Wire.requestFrom(DS3231_ADDRESS, 7); uint8_t s = bcd2bin(Wire.read() & 0x7F); uint8_t m = bcd2bin(Wire.read()); uint8_t h = bcd2bin(Wire.read()); return dTime(h, m, s); } }; RTC_DS3231 rtc;// часы dTime now, now_; //текущее время //--------------Реле------------------------------------------------ typedef struct { byte hour; byte minute; byte second; } timer_t; class cl_timer { protected: timer_t *adr; public: cl_timer(timer_t *a): adr(a) {} void save(unsigned long t = 0) { setHour(t / 60 / 60 % 24); setMinute(t / 60 % 60); setSecond(t % 60); } void save(const char* time) { setHour(conv2d(time)); setMinute(conv2d(time + 3)); setSecond(conv2d(time + 6)); } void save(const __FlashStringHelper* time) { char buff[8]; memcpy_P(buff, time, 8); setHour(conv2d(buff)); setMinute(conv2d(buff + 3)); setSecond(conv2d(buff + 6)); } byte hour() { return eeprom_read_byte(&(adr->hour)); }; byte minute() { return eeprom_read_byte(&(adr->minute)); }; byte second() { return eeprom_read_byte(&(adr->second)); }; byte time() { return ((hour() * 24 + minute()) * 60 + second()); }; void setHour(byte h) { eeprom_write_byte(&adr->hour, h); } void setMinute(byte m) { eeprom_write_byte(&adr->minute, m); } void setSecond(byte s) { eeprom_write_byte(&adr->second, s); } }; /*состояния таймера*/ const byte sOFF = 0; const byte sON = 1; const byte sEND = 2; class Cl_Relay { protected: byte pin; byte state; void set(byte s) { state = s; switch (s) { case sOFF: digitalWrite(pin, HIGH); break; case sON: digitalWrite(pin, LOW); break; case sEND: digitalWrite(pin, HIGH); break; } } public: cl_timer timeON, timeOFF; Cl_Relay(byte p, cl_timer t1, cl_timer t2) : pin(p), timeON(t1), timeOFF(t2) {} void init() { pinMode(pin, OUTPUT); set(sOFF) ; } void run() { switch (state) { case sOFF: if (now.time() >= timeON.time())set(sON); break; case sON: if (now.time() >= timeOFF.time())set(sEND); break; case sEND: break; } } void reset() { set(sOFF) ; } void viev() { switch (state) { case sOFF: lcd << F("OFF"); break; case sON: lcd << F("ON "); break; case sEND: lcd << F("END"); break; } } }; const byte RelayNum = 4; //кол-во реле timer_t EEMEM adr[RelayNum * 2]; Cl_Relay Relay[RelayNum] = { Cl_Relay(/*пин*/2, &adr[0], &adr[1]),// 1-е реле Cl_Relay(/*пин*/3, &adr[2], &adr[3]),// 2-е реле Cl_Relay(/*пин*/4, &adr[4], &adr[5]),// 3-е реле Cl_Relay(/*пин*/5, &adr[6], &adr[7]) // 4-е реле }; // первичные настройки в EEPROM void setZero() { Relay[0].timeON.save(F("00:00:30")); Relay[0].timeOFF.save(F("00:02:30"));// 1-е реле Relay[1].timeON.save(F("00:01:00")); Relay[1].timeOFF.save(F("00:03:00"));// 2-е реле Relay[2].timeON.save(F("00:01:30")); Relay[2].timeOFF.save(F("00:03:30"));// 3-е реле Relay[3].timeON.save(F("00:02:00")); Relay[3].timeOFF.save(F("00:04:00"));// 4-е реле } //---кнопкa----------------------------- typedef void (*pDo)(); class Cl_btn { protected: byte pin; bool state; unsigned long past; void set(bool s) { state = s; past = millis(); switch (s) { case false: break; case true: Do(); break; } } public: Cl_btn(byte p): pin(p) {} pDo Do = [] {}; void init() { pinMode(pin, INPUT_PULLUP); set(false); } void run() { if (millis() - past >= 100) switch (state) { case false: if (!digitalRead(pin))set(true); break; case true: if (digitalRead(pin))set(false); if (millis() - past >= 300)set(false); break; } } }; Cl_btn Btn(/*пин*/A0); //------------------------------------------- const byte st1 = 0; const byte st0 = 1; const byte st2 = 2; class Cl_joystic { protected: byte pin; byte state; unsigned long past; void set(byte s) { state = s; past = millis(); switch (s) { case st0: break; case st1: Do1(); break; case st2: Do2(); break; } } public: Cl_joystic(byte p): pin(p) {} pDo Do1 = [] {}; pDo Do2 = [] {}; void init() { set(st0); } void run() { if (millis() - past >= 100) { int tmp = analogRead(pin); switch (state) { case st1: if (tmp > 450)set(st0); if (millis() - past >= 300)set(st0); break; case st0: if (tmp < 400)set(st1); else if (tmp > 600)set(st2); break; case st2: if (tmp < 550)set(st0); if (millis() - past >= 300)set(st0); break; } } } }; Cl_joystic JoyLR(/*пин*/A1); Cl_joystic JoyUD(/*пин*/A2); //---------меню---------------- const byte scr0 = 0; // показ времени const byte scr1 = 10; // показ времени реле1 вкл/выкл const byte scr1_hour1 = 11; // установка часов реле1 вкл const byte scr1_min1 = 12; // установка минут реле1 вкл const byte scr1_sec1 = 13; // установка секунд реле1 вкл const byte scr1_hour2 = 14; // установка часов реле1 выкл const byte scr1_min2 = 15; // установка минут реле1 выкл const byte scr1_sec2 = 16; // установка секунд реле1 выкл const byte scr2 = 20; // показ времени реле2 вкл/выкл const byte scr2_hour1 = 21; // установка часов реле2 вкл const byte scr2_min1 = 22; // установка минут реле2 вкл const byte scr2_sec1 = 23; // установка секунд реле2 вкл const byte scr2_hour2 = 24; // установка часов реле2 выкл const byte scr2_min2 = 25; // установка минут реле2 выкл const byte scr2_sec2 = 26; // установка секунд реле2 выкл const byte scr3 = 30; // показ времени реле3 вкл/выкл const byte scr3_hour1 = 31; // установка часов реле3 вкл const byte scr3_min1 = 32; // установка минут реле3 вкл const byte scr3_sec1 = 33; // установка секунд реле3 вкл const byte scr3_hour2 = 34; // установка часов реле3 выкл const byte scr3_min2 = 35; // установка минут реле3 выкл const byte scr3_sec2 = 36; // установка секунд реле3 выкл const byte scr4 = 40; // показ времени реле4 вкл/выкл const byte scr4_hour1 = 41; // установка часов реле4 вкл const byte scr4_min1 = 42; // установка минут реле4 вкл const byte scr4_sec1 = 43; // установка секунд реле4 вкл const byte scr4_hour2 = 44; // установка часов реле4 выкл const byte scr4_min2 = 45; // установка минут реле4 выкл const byte scr4_sec2 = 46; // установка секунд реле4 выкл const byte scr5 = 50; const byte scr5_hour = 51; // установка времени часы const byte scr5_min = 52; // установка времени минуты const byte scr5_sec = 53; // установка времени секунд const byte scr5_res = 54; // установка времени секунд byte scr; // номер экрана unsigned long past;// фик времени в этом экране byte var;// переменная для редактирования dTime Time;// переменая времени void go(byte s) { scr = s; past = millis(); lcd.clear(); switch (s) { case scr0: { // 0- экран lcd << now.hh << F(":") << now.mm << F(":") << now.ss ; lcd.setCursor(9, 0); Relay[0].viev(); lcd << F(" "); Relay[1].viev(); lcd << F(" "); lcd.setCursor(9, 1); Relay[2].viev(); lcd << F(" "); Relay[3].viev(); lcd << F(" "); lcd.show(); } Btn.Do = [] {}; JoyLR.Do1 = [] {}; JoyLR.Do2 = [] {go(scr1);}; break; case scr1: { // ------------------------------1- экран lcd << F("Re1 ") << Relay[0].timeON.hour() << F(":") << Relay[0].timeON.minute() << F(":") << Relay[0].timeON.second(); lcd.setCursor(4, 1); lcd << Relay[0].timeOFF.hour() << F(":") << Relay[0].timeOFF.minute() << F(":") << Relay[0].timeOFF.second(); lcd.show(); } Btn.Do = [] { var = Relay[0].timeON.hour(); go(scr1_hour1); }; JoyLR.Do1 = [] {go(scr0);}; JoyLR.Do2 = [] {go(scr2);}; break; case scr1_hour1: { // установка часов реле1 вкл lcd << F("Re1>") << var << F(":") << Relay[0].timeON.minute() << F(":") << Relay[0].timeON.second(); lcd.setCursor(4, 1); lcd << Relay[0].timeOFF.hour() << F(":") << Relay[0].timeOFF.minute() << F(":") << Relay[0].timeOFF.second(); lcd.show(); } Btn.Do = [] { Relay[0].timeON.setHour(var); var = Relay[0].timeON.minute(); go(scr1_min1); }; JoyLR.Do1 = [] { if (var < 23)var++; go(scr1_hour1); }; JoyLR.Do2 = [] { if (var > 0)var--; go(scr1_hour1); }; break; case scr1_min1: { // установка минут реле1 вкл lcd << F("Re1 ") << Relay[0].timeON.hour() << F(">") << var << F(":") << Relay[0].timeON.second(); lcd.setCursor(4, 1); lcd << Relay[0].timeOFF.hour() << F(":") << Relay[0].timeOFF.minute() << F(":") << Relay[0].timeOFF.second(); lcd.show(); } Btn.Do = [] { Relay[0].timeON.setMinute(var); var = Relay[0].timeON.second(); go(scr1_sec1); }; JoyLR.Do1 = [] { if (var < 59)var++; go(scr1_min1); }; JoyLR.Do2 = [] { if (var > 0)var--; go(scr1_min1); }; break; case scr1_sec1: { // установка секунд реле1 вкл lcd << F("Re1 ") << Relay[0].timeON.hour() << F(":") << Relay[0].timeON.minute() << F(">") << var; lcd.setCursor(4, 1); lcd << Relay[0].timeOFF.hour() << F(":") << Relay[0].timeOFF.minute() << F(":") << Relay[0].timeOFF.second(); lcd.show(); } Btn.Do = [] { Relay[0].timeON.setSecond(var); var = Relay[0].timeOFF.hour(); go(scr1_hour2); }; JoyLR.Do1 = [] { if (var < 59)var++; go(scr1_sec1); }; JoyLR.Do2 = [] { if (var > 0)var--; go(scr1_sec1); }; break; case scr1_hour2: { // установка часов реле1 выкл lcd << F("Re1 ") << Relay[0].timeON.hour() << F(":") << Relay[0].timeON.minute() << F(":") << Relay[0].timeON.second(); lcd.setCursor(3, 1); lcd << F(">") << var << F(":") << Relay[0].timeOFF.minute() << F(":") << Relay[0].timeOFF.second(); lcd.show(); } Btn.Do = [] { Relay[0].timeOFF.setHour(var); var = Relay[0].timeOFF.minute(); go(scr1_min2); }; JoyLR.Do1 = [] { if (var < 23)var++; go(scr1_hour2); }; JoyLR.Do2 = [] { if (var > 0)var--; go(scr1_hour2); }; break; case scr1_min2: { // установка минут реле1 выкл lcd << F("Re1 ") << Relay[0].timeON.hour() << F(":") << Relay[0].timeON.minute() << F(":") << Relay[0].timeON.second(); lcd.setCursor(4, 1); lcd << Relay[0].timeOFF.hour() << F(">") << var << F(":") << Relay[0].timeOFF.second(); lcd.show(); } Btn.Do = [] { Relay[0].timeOFF.setMinute(var); var = Relay[0].timeOFF.second(); go(scr1_sec2); }; JoyLR.Do1 = [] { if (var < 59)var++; go(scr1_min2); }; JoyLR.Do2 = [] { if (var > 0)var--; go(scr1_min2); }; break; case scr1_sec2: { // установка секунд реле1 выкл lcd << F("Re1 ") << Relay[0].timeON.hour() << F(":") << Relay[0].timeON.minute() << F(":") << Relay[0].timeON.second(); lcd.setCursor(4, 1); lcd << Relay[0].timeOFF.hour() << F(":") << Relay[0].timeOFF.minute() << F(">") << var; lcd.show(); } Btn.Do = [] { Relay[0].timeOFF.setSecond(var); go(scr1); }; JoyLR.Do1 = [] { if (var < 59)var++; go(scr1_sec2); }; JoyLR.Do2 = [] { if (var > 0)var--; go(scr1_sec2); }; break; case scr2: { //------------------------------------------------ 2- экран lcd << F("Re2 ") << Relay[1].timeON.hour() << F(":") << Relay[1].timeON.minute() << F(":") << Relay[1].timeON.second(); lcd.setCursor(4, 1); lcd << Relay[1].timeOFF.hour() << F(":") << Relay[1].timeOFF.minute() << F(":") << Relay[1].timeOFF.second(); lcd.show(); } Btn.Do = [] { var = Relay[1].timeON.hour(); go(scr2_hour1); }; JoyLR.Do1 = [] {go(scr1);}; JoyLR.Do2 = [] {go(scr3);}; break; case scr2_hour1: { // установка часов реле2 вкл lcd << F("Re2>") << var << F(":") << Relay[1].timeON.minute() << F(":") << Relay[1].timeON.second(); lcd.setCursor(4, 1); lcd << Relay[1].timeOFF.hour() << F(":") << Relay[1].timeOFF.minute() << F(":") << Relay[1].timeOFF.second(); lcd.show(); } Btn.Do = [] { Relay[1].timeON.setHour(var); var = Relay[1].timeON.minute(); go(scr2_min1); }; JoyLR.Do1 = [] { if (var < 23)var++; go(scr2_hour1); }; JoyLR.Do2 = [] { if (var > 0)var--; go(scr2_hour1); }; break; case scr2_min1: { // установка минут реле2 вкл lcd << F("Re2 ") << Relay[1].timeON.hour() << F(">") << var << F(":") << Relay[1].timeON.second(); lcd.setCursor(4, 1); lcd << Relay[1].timeOFF.hour() << F(":") << Relay[1].timeOFF.minute() << F(":") << Relay[1].timeOFF.second(); lcd.show(); } Btn.Do = [] { Relay[1].timeON.setMinute(var); var = Relay[1].timeON.second(); go(scr2_sec1); }; JoyLR.Do1 = [] { if (var < 59)var++; go(scr2_min1); }; JoyLR.Do2 = [] { if (var > 0)var--; go(scr2_min1); }; break; case scr2_sec1: { // установка секунд реле2 вкл lcd << F("Re2 ") << Relay[1].timeON.hour() << F(":") << Relay[1].timeON.minute() << F(">") << var; lcd.setCursor(4, 1); lcd << Relay[1].timeOFF.hour() << F(":") << Relay[1].timeOFF.minute() << F(":") << Relay[1].timeOFF.second(); lcd.show(); } Btn.Do = [] { Relay[1].timeON.setSecond(var); var = Relay[1].timeOFF.hour(); go(scr2_hour2); }; JoyLR.Do1 = [] { if (var < 59)var++; go(scr2_sec1); }; JoyLR.Do2 = [] { if (var > 0)var--; go(scr2_sec1); }; break; case scr2_hour2: { // установка часов реле2 выкл lcd << F("Re2 ") << Relay[1].timeON.hour() << F(":") << Relay[1].timeON.minute() << F(":") << Relay[1].timeON.second(); lcd.setCursor(3, 1); lcd << F(">") << var << F(":") << Relay[1].timeOFF.minute() << F(":") << Relay[1].timeOFF.second(); lcd.show(); } Btn.Do = [] { Relay[1].timeOFF.setHour(var); var = Relay[1].timeOFF.minute(); go(scr2_min2); }; JoyLR.Do1 = [] { if (var < 23)var++; go(scr2_hour2); }; JoyLR.Do2 = [] { if (var > 0)var--; go(scr2_hour2); }; break; case scr2_min2: { // установка минут реле2 выкл lcd << F("Re2 ") << Relay[1].timeON.hour() << F(":") << Relay[1].timeON.minute() << F(":") << Relay[1].timeON.second(); lcd.setCursor(4, 1); lcd << Relay[1].timeOFF.hour() << F(">") << var << F(":") << Relay[1].timeOFF.second(); lcd.show(); } Btn.Do = [] { Relay[1].timeOFF.setMinute(var); var = Relay[1].timeOFF.second(); go(scr2_sec2); }; JoyLR.Do1 = [] { if (var < 59)var++; go(scr2_min2); }; JoyLR.Do2 = [] { if (var > 0)var--; go(scr2_min2); }; break; case scr2_sec2: { // установка секунд реле2 выкл lcd << F("Re2 ") << Relay[1].timeON.hour() << F(":") << Relay[1].timeON.minute() << F(":") << Relay[1].timeON.second(); lcd.setCursor(4, 1); lcd << Relay[1].timeOFF.hour() << F(":") << Relay[1].timeOFF.minute() << F(">") << var; lcd.show(); } Btn.Do = [] { Relay[1].timeOFF.setSecond(var); go(scr2); }; JoyLR.Do1 = [] { if (var < 59)var++; go(scr2_sec2); }; JoyLR.Do2 = [] { if (var > 0)var--; go(scr2_sec2); }; break; case scr3: { //---------------------------------- 3- экран lcd << F("Re3 ") << Relay[2].timeON.hour() << F(":") << Relay[2].timeON.minute() << F(":") << Relay[2].timeON.second(); lcd.setCursor(4, 1); lcd << Relay[2].timeOFF.hour() << F(":") << Relay[2].timeOFF.minute() << F(":") << Relay[2].timeOFF.second(); lcd.show(); } Btn.Do = [] { var = Relay[2].timeON.hour(); go(scr3_hour1); }; JoyLR.Do1 = [] {go(scr2);}; JoyLR.Do2 = [] {go(scr4);}; break; case scr3_hour1: { // установка часов реле3 вкл lcd << F("Re3>") << var << F(":") << Relay[2].timeON.minute() << F(":") << Relay[2].timeON.second(); lcd.setCursor(4, 1); lcd << Relay[2].timeOFF.hour() << F(":") << Relay[2].timeOFF.minute() << F(":") << Relay[2].timeOFF.second(); lcd.show(); } Btn.Do = [] { Relay[2].timeON.setHour(var); var = Relay[2].timeON.minute(); go(scr3_min1); }; JoyLR.Do1 = [] { if (var < 23)var++; go(scr3_hour1); }; JoyLR.Do2 = [] { if (var > 0)var--; go(scr3_hour1); }; break; case scr3_min1: { // установка минут реле1 вкл lcd << F("Re3 ") << Relay[2].timeON.hour() << F(">") << var << F(":") << Relay[2].timeON.second(); lcd.setCursor(4, 1); lcd << Relay[2].timeOFF.hour() << F(":") << Relay[2].timeOFF.minute() << F(":") << Relay[2].timeOFF.second(); lcd.show(); } Btn.Do = [] { Relay[2].timeON.setMinute(var); var = Relay[2].timeON.second(); go(scr3_sec1); }; JoyLR.Do1 = [] { if (var < 59)var++; go(scr3_min1); }; JoyLR.Do2 = [] { if (var > 0)var--; go(scr3_min1); }; break; case scr3_sec1: { // установка секунд реле3 вкл lcd << F("Re3 ") << Relay[2].timeON.hour() << F(":") << Relay[2].timeON.minute() << F(">") << var; lcd.setCursor(4, 1); lcd << Relay[2].timeOFF.hour() << F(":") << Relay[2].timeOFF.minute() << F(":") << Relay[2].timeOFF.second(); lcd.show(); } Btn.Do = [] { Relay[2].timeON.setSecond(var); var = Relay[2].timeOFF.hour(); go(scr3_hour2); }; JoyLR.Do1 = [] { if (var < 59)var++; go(scr3_sec1); }; JoyLR.Do2 = [] { if (var > 0)var--; go(scr3_sec1); }; break; case scr3_hour2: { // установка часов реле3 выкл lcd << F("Re3 ") << Relay[2].timeON.hour() << F(":") << Relay[2].timeON.minute() << F(":") << Relay[2].timeON.second(); lcd.setCursor(3, 1); lcd << F(">") << var << F(":") << Relay[2].timeOFF.minute() << F(":") << Relay[2].timeOFF.second(); lcd.show(); } Btn.Do = [] { Relay[2].timeOFF.setHour(var); var = Relay[2].timeOFF.minute(); go(scr3_min2); }; JoyLR.Do1 = [] { if (var < 23)var++; go(scr3_hour2); }; JoyLR.Do2 = [] { if (var > 0)var--; go(scr3_hour2); }; break; case scr3_min2: { // установка минут реле3 выкл lcd << F("Re3 ") << Relay[2].timeON.hour() << F(":") << Relay[2].timeON.minute() << F(":") << Relay[2].timeON.second(); lcd.setCursor(4, 1); lcd << Relay[2].timeOFF.hour() << F(">") << var << F(":") << Relay[2].timeOFF.second(); lcd.show(); } Btn.Do = [] { Relay[0].timeOFF.setMinute(var); var = Relay[0].timeOFF.second(); go(scr3_sec2); }; JoyLR.Do1 = [] { if (var < 59)var++; go(scr3_min2); }; JoyLR.Do2 = [] { if (var > 0)var--; go(scr3_min2); }; break; case scr3_sec2: { // установка секунд реле3 выкл lcd << F("Re3 ") << Relay[2].timeON.hour() << F(":") << Relay[2].timeON.minute() << F(":") << Relay[2].timeON.second(); lcd.setCursor(4, 1); lcd << Relay[2].timeOFF.hour() << F(":") << Relay[2].timeOFF.minute() << F(">") << var; lcd.show(); } Btn.Do = [] { Relay[3].timeOFF.setSecond(var); go(scr3); }; JoyLR.Do1 = [] { if (var < 59)var++; go(scr3_sec2); }; JoyLR.Do2 = [] { if (var > 0)var--; go(scr3_sec2); }; break; case scr4: { // 4- экран lcd << F("Re4 ") << Relay[3].timeON.hour() << F(":") << Relay[3].timeON.minute() << F(":") << Relay[3].timeON.second(); lcd.setCursor(4, 1); lcd << Relay[3].timeOFF.hour() << F(":") << Relay[3].timeOFF.minute() << F(":") << Relay[3].timeOFF.second(); lcd.show(); } Btn.Do = [] { var = Relay[3].timeON.hour(); go(scr4_hour1); }; JoyLR.Do1 = [] {go(scr3);}; JoyLR.Do2 = [] {go(scr5);}; break; case scr4_hour1: { // установка часов реле4 вкл lcd << F("Re4>") << var << F(":") << Relay[3].timeON.minute() << F(":") << Relay[3].timeON.second(); lcd.setCursor(4, 1); lcd << Relay[3].timeOFF.hour() << F(":") << Relay[3].timeOFF.minute() << F(":") << Relay[3].timeOFF.second(); lcd.show(); } Btn.Do = [] { Relay[3].timeON.setHour(var); var = Relay[3].timeON.minute(); go(scr4_min1); }; JoyLR.Do1 = [] { if (var < 23)var++; go(scr4_hour1); }; JoyLR.Do2 = [] { if (var > 0)var--; go(scr4_hour1); }; break; case scr4_min1: { // установка минут реле4 вкл lcd << F("Re4 ") << Relay[3].timeON.hour() << F(">") << var << F(":") << Relay[3].timeON.second(); lcd.setCursor(4, 1); lcd << Relay[3].timeOFF.hour() << F(":") << Relay[3].timeOFF.minute() << F(":") << Relay[3].timeOFF.second(); lcd.show(); } Btn.Do = [] { Relay[0].timeON.setMinute(var); var = Relay[0].timeON.second(); go(scr4_sec1); }; JoyLR.Do1 = [] { if (var < 59)var++; go(scr4_min1); }; JoyLR.Do2 = [] { if (var > 0)var--; go(scr4_min1); }; break; case scr4_sec1: { // установка секунд реле4 вкл lcd << F("Re4 ") << Relay[3].timeON.hour() << F(":") << Relay[3].timeON.minute() << F(">") << var; lcd.setCursor(4, 1); lcd << Relay[3].timeOFF.hour() << F(":") << Relay[3].timeOFF.minute() << F(":") << Relay[3].timeOFF.second(); lcd.show(); } Btn.Do = [] { Relay[0].timeON.setSecond(var); var = Relay[3].timeOFF.hour(); go(scr4_hour2); }; JoyLR.Do1 = [] { if (var < 59)var++; go(scr4_sec1); }; JoyLR.Do2 = [] { if (var > 0)var--; go(scr4_sec1); }; break; case scr4_hour2: { // установка часов реле4 выкл lcd << F("Re4 ") << Relay[3].timeON.hour() << F(":") << Relay[3].timeON.minute() << F(":") << Relay[3].timeON.second(); lcd.setCursor(3, 1); lcd << F(">") << var << F(":") << Relay[3].timeOFF.minute() << F(":") << Relay[3].timeOFF.second(); lcd.show(); } Btn.Do = [] { Relay[3].timeOFF.setHour(var); var = Relay[3].timeOFF.minute(); go(scr4_min2); }; JoyLR.Do1 = [] { if (var < 23)var++; go(scr4_hour2); }; JoyLR.Do2 = [] { if (var > 0)var--; go(scr4_hour2); }; break; case scr4_min2: { // установка минут реле4 выкл lcd << F("Re4 ") << Relay[3].timeON.hour() << F(":") << Relay[3].timeON.minute() << F(":") << Relay[3].timeON.second(); lcd.setCursor(4, 1); lcd << Relay[3].timeOFF.hour() << F(">") << var << F(":") << Relay[3].timeOFF.second(); lcd.show(); } Btn.Do = [] { Relay[3].timeOFF.setMinute(var); var = Relay[3].timeOFF.second(); go(scr4_sec2); }; JoyLR.Do1 = [] { if (var < 59)var++; go(scr4_min2); }; JoyLR.Do2 = [] { if (var > 0)var--; go(scr4_min2); }; break; case scr4_sec2: { // установка секунд реле4 выкл lcd << F("Re4 ") << Relay[3].timeON.hour() << F(":") << Relay[3].timeON.minute() << F(":") << Relay[3].timeON.second(); lcd.setCursor(4, 1); lcd << Relay[3].timeOFF.hour() << F(":") << Relay[3].timeOFF.minute() << F(">") << var; lcd.show(); } Btn.Do = [] { Relay[3].timeOFF.setSecond(var); go(scr4); }; JoyLR.Do1 = [] { if (var < 59)var++; go(scr4_sec2); }; JoyLR.Do2 = [] { if (var > 0)var--; go(scr4_sec2); }; break; case scr5: { // 5- экран lcd << F("SetTime:") << now.hh << F(":") << now.mm << F(":") << now.ss ; lcd.show(); } Btn.Do = [] { Time = now; go(scr5_hour); }; JoyLR.Do1 = [] {go(scr4);}; JoyLR.Do2 = [] {go(scr0);}; break; case scr5_hour: { lcd << F("SetTime>") << Time.hh << F(":") << Time.mm << F(":") << Time.ss; lcd.show(); } Btn.Do = [] {go(scr5_min);}; JoyLR.Do1 = [] { if (Time.hh > 0)Time.hh--; go(scr5_hour); }; JoyLR.Do2 = [] { if (Time.hh < 23)Time.hh++; go(scr5_hour); }; break; case scr5_min: { lcd << F("SetTime:") << Time.hh << F(">") << Time.mm << F(":") << Time.ss ; lcd.show(); } Btn.Do = [] {go(scr5_sec);}; JoyLR.Do1 = [] { if (Time.mm > 0)Time.mm--; go(scr5_min); }; JoyLR.Do2 = [] { if (Time.mm < 59)Time.mm++; go(scr5_min); }; break; case scr5_sec: { lcd << F("SetTime:") << Time.hh << F(":") << Time.mm << F(">") << Time.ss; lcd.show(); } Btn.Do = [] { rtc.write(Time); now = Time; go(scr5); }; JoyLR.Do1 = [] { if (Time.ss > 0)Time.ss--; go(scr5_sec); }; JoyLR.Do2 = [] { if (Time.ss < 59)Time.ss++; go(scr5_sec); }; break; } } void menuInit() { lcd.lightON(); now = rtc.read(); JoyUD.Do1 = [] {lcd.lightON();}; JoyUD.Do2 = [] {lcd.lightOFF();}; go(scr0); } void menuRun() { if (scr != scr0 && millis() - past >= 3000)go(scr0); if (scr == scr0 && millis() - past >= 500)go(scr0); } //----------------------------- void setup() { lcd.init(); //rtc.write(F("00:00:00")); rtc.write(F(__TIME__));//(для первичной настройки часов) now = rtc.read(); setZero();////(для первичной настройки устройства) for (int i = 0; i < RelayNum; i++)Relay[i].init(); Btn.init(); JoyLR.init(); JoyUD.init(); menuInit(); } void loop() { now_ = now; now = rtc.read(); if (now_.time() - now.time() > 10) for (int i = 0; i < RelayNum; i++)Relay[i].reset(); for (int i = 0; i < RelayNum; i++)Relay[i].run(); Btn.run(); JoyLR.run(); JoyUD.run(); menuRun(); } /**/А точно 4500 - это 4.1ms?
ПС: Похоже передыдущий скетч не был избавлен от ошибок. Так что новый вариант.
/* часы с ручной установкой времени на DS3231*/ // Оборудование // Ардуино Нано // lcd1602_i2c -- I2C // модуль DS3231 -- I2C // ардуино джойстик кнопка A0 потенциометры A1,A2 // модуль реле 2,3,4,5 //---------------lcd--------------------------------------------- template <typename T> inline Print & operator << (Print &s, T n) { s.print(n); return s; } //------дисплей lcd1602_i2c----------------------------- // даташит https://www.sparkfun.com/datasheets/LCD/ADM1602K-NSW-FBS-3.3v.pdf // на русском http://www.melt.aha.ru/pdf/mt-16s2h.pdf #include <Wire.h> // команды #define LCD_CLEARDISPLAY 0x01 #define LCD_RETURNHOME 0x02 #define LCD_ENTRYMODESET 0x04 #define LCD_DISPLAYCONTROL 0x08 #define LCD_CURSORSHIFT 0x10 #define LCD_FUNCTIONSET 0x20 #define LCD_SETCGRAMADDR 0x40 #define LCD_SETDDRAMADDR 0x80 // флаги для режима ввода дисплея #define LCD_ENTRYRIGHT 0x00 #define LCD_ENTRYLEFT 0x02 #define LCD_ENTRYSHIFTINCREMENT 0x01 #define LCD_ENTRYSHIFTDECREMENT 0x00 // флаги для управления включением / выключением дисплея #define LCD_DISPLAYON 0x04 #define LCD_DISPLAYOFF 0x00 #define LCD_CURSORON 0x02 #define LCD_CURSOROFF 0x00 #define LCD_BLINKON 0x01 #define LCD_BLINKOFF 0x00 // флаги для отображения / сдвига курсора #define LCD_DISPLAYMOVE 0x08 #define LCD_CURSORMOVE 0x00 #define LCD_MOVERIGHT 0x04 #define LCD_MOVELEFT 0x00 // флаги для набора функций #define LCD_8BITMODE 0x10 #define LCD_4BITMODE 0x00 #define LCD_2LINE 0x08 #define LCD_1LINE 0x00 #define LCD_5x10DOTS 0x04 #define LCD_5x8DOTS 0x00 // флаги для управления подсветкой #define LCD_lightON 0x08 #define LCD_lightOFF 0x00 #define En B00000100 // Бит разрешения #define Rw B00000010 // Чтение / запись бит #define Rs B00000001 // Бит выбора регистра class Cl_lcd1602_i2c : public Print { protected: uint8_t adr, posX, posY; uint8_t _lightONval; uint8_t _displayfunction; uint8_t _displaycontrol; uint8_t _displaymode; byte buffer[32]; public: Cl_lcd1602_i2c(uint8_t a): adr(a) {} void init() { Wire.begin(); write4bits(0x03 << 4); delayMicroseconds(4500); // wait min 4.1ms write4bits(0x03 << 4); delayMicroseconds(4500); // wait min 4.1ms write4bits(0x03 << 4); delayMicroseconds(150); write4bits(0x02 << 4); delay(50); _lightONval = LCD_lightOFF; expanderWrite(_lightONval); // сбросить расширение и выключить подсветку (бит 8 = 1) // режим работы дисплея 4-х битный интерфейс ,две строки,5х8 точек _displayfunction = LCD_4BITMODE | LCD_2LINE | LCD_5x8DOTS; command(LCD_FUNCTIONSET | _displayfunction); // режим контроля дисплей вкл, курсор не мигает,дисплей не мигает _displaycontrol = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF; command(LCD_DISPLAYCONTROL | _displaycontrol); // режим ввода текста в память-начинать слева с движением в право _displaymode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT; command(LCD_ENTRYMODESET | _displaymode); clear(); } // подсветку вкл/выкл void lightON(void) { _lightONval = LCD_lightON; expanderWrite(0); } void lightOFF(void) { _lightONval = LCD_lightOFF; expanderWrite(0); } // очистить буфер void clear() { for (byte i = 0; i < 32; i++ )buffer[i] = 0x20; posX = 0; posY = 0; } // отправить информацию из буфера на экран void show() { line(0); for (byte i = 0; i < 16; i++ )out(buffer[i]); line(1); for (byte i = 16; i < 32; i++ )out(buffer[i]); } void setCursor(byte x, byte y) { if (x > 16) x = 16; else posX = x; if (y > 2) x = 2; else posY = y; } private: /*внутрение функции*/ void line(byte l) { if (l == 0) command(LCD_SETDDRAMADDR | 0x00); else command(LCD_SETDDRAMADDR | 0x40); } inline void out(uint8_t value) { send(value, Rs); } inline size_t write(uint8_t value) { if (posX < 16 && posY < 2) { buffer[posY * 16 + posX] = value; posX++; } return 1; } /*команды низкоуровневого управления*/ inline void command(uint8_t value) { send(value, 0); } void send(uint8_t value, uint8_t mode) { uint8_t highnib = value & 0xf0; write4bits((highnib) | mode); uint8_t lownib = (value << 4) & 0xf0; write4bits((lownib) | mode); } void write4bits(uint8_t value) { expanderWrite(value); pulseEnable(value); } void expanderWrite(uint8_t _data) { Wire.beginTransmission(adr); Wire.write((int)(_data) | _lightONval); Wire.endTransmission(); } void pulseEnable(uint8_t _data) { expanderWrite(_data | En); // En high delayMicroseconds(1); // enable pulse must be >450ns expanderWrite(_data & ~En); // En low delayMicroseconds(50); // commands need > 37us to settle } }; Cl_lcd1602_i2c lcd(0x27);//0x3F //-----часы----------------------- uint8_t conv2d(const char* p) { uint8_t v = 0; if ('0' <= *p && *p <= '9') v = *p - '0'; return 10 * v + *++p - '0'; } class dTime { protected: public: byte hh, mm, ss; unsigned long time() { return ((hh * 24 + mm) * 60 + ss); } dTime(unsigned long t = 0) : hh(t / 60 / 60 % 24), mm(t / 60 % 60), ss(t % 60) {} dTime(byte h, byte m, byte s) : hh(h), mm(m), ss(s) {} dTime(const dTime& t)// : hh(copy.hh), mm(copy.mm), ss(copy.ss) { hh = t.hh; mm = t.mm; ss = t.ss; } dTime(const char* time) { hh = conv2d(time); mm = conv2d(time + 3); ss = conv2d(time + 6); } dTime(const __FlashStringHelper* time) { char buff[8]; memcpy_P(buff, time, 8); hh = conv2d(buff); mm = conv2d(buff + 3); ss = conv2d(buff + 6); } dTime& operator=(const dTime& t) { if (this == &t) return *this; hh = t.hh; mm = t.mm; ss = t.ss; return *this; } }; #define DS3231_ADDRESS 0x68 #define DS3231_CONTROL 0x0E #define DS3231_STATUSREG 0x0F #include <Wire.h> uint8_t read_i2c_register(uint8_t addr, uint8_t reg) { Wire.beginTransmission(addr); Wire.write((byte)reg); Wire.endTransmission(); Wire.requestFrom(addr, (byte)1); return Wire.read(); } void write_i2c_register(uint8_t addr, uint8_t reg, uint8_t val) { Wire.beginTransmission(addr); Wire.write((byte)reg); Wire.write((byte)val); Wire.endTransmission(); } uint8_t bcd2bin (uint8_t val) { return val - 6 * (val >> 4); } uint8_t bin2bcd (uint8_t val) { return val + 6 * (val / 10); } class RTC_DS3231 { public: void write(dTime t) { Wire.beginTransmission(DS3231_ADDRESS); Wire.write((byte)0); // start at location 0 Wire.write(bin2bcd(t.ss)); Wire.write(bin2bcd(t.mm)); Wire.write(bin2bcd(t.hh)); Wire.endTransmission(); uint8_t statreg = read_i2c_register(DS3231_ADDRESS, DS3231_STATUSREG); statreg &= ~0x80; // flip OSF bit write_i2c_register(DS3231_ADDRESS, DS3231_STATUSREG, statreg); } dTime read() { Wire.beginTransmission(DS3231_ADDRESS); Wire.write((byte)0); Wire.endTransmission(); Wire.requestFrom(DS3231_ADDRESS, 7); uint8_t s = bcd2bin(Wire.read() & 0x7F); uint8_t m = bcd2bin(Wire.read()); uint8_t h = bcd2bin(Wire.read()); return dTime(h, m, s); } }; RTC_DS3231 rtc;// часы dTime now, now_; //текущее время //--------------Реле------------------------------------------------ typedef struct { byte hour; byte minute; byte second; } timer_t; class cl_timer { protected: timer_t *adr; public: cl_timer(timer_t *a): adr(a) {} void save(unsigned long t = 0) { setHour(t / 60 / 60 % 24); setMinute(t / 60 % 60); setSecond(t % 60); } void save(const char* time) { setHour(conv2d(time)); setMinute(conv2d(time + 3)); setSecond(conv2d(time + 6)); } void save(const __FlashStringHelper* time) { char buff[8]; memcpy_P(buff, time, 8); setHour(conv2d(buff)); setMinute(conv2d(buff + 3)); setSecond(conv2d(buff + 6)); } byte hour() { return eeprom_read_byte(&(adr->hour)); }; byte minute() { return eeprom_read_byte(&(adr->minute)); }; byte second() { return eeprom_read_byte(&(adr->second)); }; byte time() { return ((hour() * 24 + minute()) * 60 + second()); }; void setHour(byte h) { eeprom_write_byte(&adr->hour, h); } void setMinute(byte m) { eeprom_write_byte(&adr->minute, m); } void setSecond(byte s) { eeprom_write_byte(&adr->second, s); } }; /*состояния таймера*/ const byte sOFF = 0; const byte sON = 1; const byte sEND = 2; class Cl_Relay { protected: byte pin; byte state; void set(byte s) { state = s; switch (s) { case sOFF: digitalWrite(pin, HIGH); break; case sON: digitalWrite(pin, LOW); break; case sEND: digitalWrite(pin, HIGH); break; } } public: cl_timer timeON, timeOFF; Cl_Relay(byte p, cl_timer t1, cl_timer t2) : pin(p), timeON(t1), timeOFF(t2) {} void init() { pinMode(pin, OUTPUT); set(sOFF) ; } void run() { switch (state) { case sOFF: if (now.time() >= timeON.time())set(sON); break; case sON: if (now.time() >= timeOFF.time())set(sEND); break; case sEND: break; } } void reset() { set(sOFF) ; } void viev() { switch (state) { case sOFF: lcd << F("OFF"); break; case sON: lcd << F("ON "); break; case sEND: lcd << F("END"); break; } } }; const byte RelayNum = 4; //кол-во реле timer_t EEMEM adr[RelayNum * 2]; Cl_Relay Relay[RelayNum] = { Cl_Relay(/*пин*/2, &adr[0], &adr[1]),// 1-е реле Cl_Relay(/*пин*/3, &adr[2], &adr[3]),// 2-е реле Cl_Relay(/*пин*/4, &adr[4], &adr[5]),// 3-е реле Cl_Relay(/*пин*/5, &adr[6], &adr[7]) // 4-е реле }; // первичные настройки в EEPROM void setZero() { Relay[0].timeON.save(F("00:00:30")); Relay[0].timeOFF.save(F("00:02:30"));// 1-е реле Relay[1].timeON.save(F("00:01:00")); Relay[1].timeOFF.save(F("00:03:00"));// 2-е реле Relay[2].timeON.save(F("00:01:30")); Relay[2].timeOFF.save(F("00:03:30"));// 3-е реле Relay[3].timeON.save(F("00:02:00")); Relay[3].timeOFF.save(F("00:04:00"));// 4-е реле } //---кнопкa----------------------------- typedef void (*pDo)(); class Cl_btn { protected: byte pin; bool state; unsigned long past; void set(bool s) { state = s; past = millis(); switch (s) { case false: break; case true: Do(); break; } } public: Cl_btn(byte p): pin(p) {} pDo Do = [] {}; void init() { pinMode(pin, INPUT_PULLUP); set(false); } void run() { if (millis() - past >= 100) switch (state) { case false: if (!digitalRead(pin))set(true); break; case true: if (digitalRead(pin))set(false); if (millis() - past >= 300)set(false); break; } } }; Cl_btn Btn(/*пин*/A0); //------------------------------------------- const byte st1 = 0; const byte st0 = 1; const byte st2 = 2; class Cl_joystic { protected: byte pin; byte state; unsigned long past; void set(byte s) { state = s; past = millis(); switch (s) { case st0: break; case st1: Do1(); break; case st2: Do2(); break; } } public: Cl_joystic(byte p): pin(p) {} pDo Do1 = [] {}; pDo Do2 = [] {}; void init() { set(st0); } void run() { if (millis() - past >= 100) { int tmp = analogRead(pin); switch (state) { case st1: if (tmp > 450)set(st0); if (millis() - past >= 300)set(st0); break; case st0: if (tmp < 400)set(st1); else if (tmp > 600)set(st2); break; case st2: if (tmp < 550)set(st0); if (millis() - past >= 300)set(st0); break; } } } }; Cl_joystic JoyLR(/*пин*/A1); Cl_joystic JoyUD(/*пин*/A2); //---------меню---------------- const byte scr0 = 0; // показ времени const byte scr1 = 10; // показ времени реле1 вкл/выкл const byte scr1_hour1 = 11; // установка часов реле1 вкл const byte scr1_min1 = 12; // установка минут реле1 вкл const byte scr1_sec1 = 13; // установка секунд реле1 вкл const byte scr1_hour2 = 14; // установка часов реле1 выкл const byte scr1_min2 = 15; // установка минут реле1 выкл const byte scr1_sec2 = 16; // установка секунд реле1 выкл const byte scr2 = 20; // показ времени реле2 вкл/выкл const byte scr2_hour1 = 21; // установка часов реле2 вкл const byte scr2_min1 = 22; // установка минут реле2 вкл const byte scr2_sec1 = 23; // установка секунд реле2 вкл const byte scr2_hour2 = 24; // установка часов реле2 выкл const byte scr2_min2 = 25; // установка минут реле2 выкл const byte scr2_sec2 = 26; // установка секунд реле2 выкл const byte scr3 = 30; // показ времени реле3 вкл/выкл const byte scr3_hour1 = 31; // установка часов реле3 вкл const byte scr3_min1 = 32; // установка минут реле3 вкл const byte scr3_sec1 = 33; // установка секунд реле3 вкл const byte scr3_hour2 = 34; // установка часов реле3 выкл const byte scr3_min2 = 35; // установка минут реле3 выкл const byte scr3_sec2 = 36; // установка секунд реле3 выкл const byte scr4 = 40; // показ времени реле4 вкл/выкл const byte scr4_hour1 = 41; // установка часов реле4 вкл const byte scr4_min1 = 42; // установка минут реле4 вкл const byte scr4_sec1 = 43; // установка секунд реле4 вкл const byte scr4_hour2 = 44; // установка часов реле4 выкл const byte scr4_min2 = 45; // установка минут реле4 выкл const byte scr4_sec2 = 46; // установка секунд реле4 выкл const byte scr5 = 50; const byte scr5_hour = 51; // установка времени часы const byte scr5_min = 52; // установка времени минуты const byte scr5_sec = 53; // установка времени секунд const byte scr5_res = 54; // установка времени секунд byte scr; // номер экрана unsigned long past;// фик времени в этом экране byte var;// переменная для редактирования dTime Time;// переменая времени void go(byte s) { scr = s; past = millis(); lcd.clear(); switch (s) { case scr0: { // 0- экран lcd << now.hh << F(":") << now.mm << F(":") << now.ss ; lcd.setCursor(9, 0); Relay[0].viev(); lcd << F(" "); Relay[1].viev(); lcd << F(" "); lcd.setCursor(9, 1); Relay[2].viev(); lcd << F(" "); Relay[3].viev(); lcd << F(" "); lcd.show(); } Btn.Do = [] {}; JoyLR.Do1 = [] {}; JoyLR.Do2 = [] {go(scr1);}; break; case scr1: { // ------------------------------1- экран lcd << F("Re1 ") << Relay[0].timeON.hour() << F(":") << Relay[0].timeON.minute() << F(":") << Relay[0].timeON.second(); lcd.setCursor(4, 1); lcd << Relay[0].timeOFF.hour() << F(":") << Relay[0].timeOFF.minute() << F(":") << Relay[0].timeOFF.second(); lcd.show(); } Btn.Do = [] { var = Relay[0].timeON.hour(); go(scr1_hour1); }; JoyLR.Do1 = [] {go(scr0);}; JoyLR.Do2 = [] {go(scr2);}; break; case scr1_hour1: { // установка часов реле1 вкл lcd << F("Re1>") << var << F(":") << Relay[0].timeON.minute() << F(":") << Relay[0].timeON.second(); lcd.setCursor(4, 1); lcd << Relay[0].timeOFF.hour() << F(":") << Relay[0].timeOFF.minute() << F(":") << Relay[0].timeOFF.second(); lcd.show(); } Btn.Do = [] { Relay[0].timeON.setHour(var); var = Relay[0].timeON.minute(); go(scr1_min1); }; JoyLR.Do1 = [] { if (var < 23)var++; go(scr1_hour1); }; JoyLR.Do2 = [] { if (var > 0)var--; go(scr1_hour1); }; break; case scr1_min1: { // установка минут реле1 вкл lcd << F("Re1 ") << Relay[0].timeON.hour() << F(">") << var << F(":") << Relay[0].timeON.second(); lcd.setCursor(4, 1); lcd << Relay[0].timeOFF.hour() << F(":") << Relay[0].timeOFF.minute() << F(":") << Relay[0].timeOFF.second(); lcd.show(); } Btn.Do = [] { Relay[0].timeON.setMinute(var); var = Relay[0].timeON.second(); go(scr1_sec1); }; JoyLR.Do1 = [] { if (var < 59)var++; go(scr1_min1); }; JoyLR.Do2 = [] { if (var > 0)var--; go(scr1_min1); }; break; case scr1_sec1: { // установка секунд реле1 вкл lcd << F("Re1 ") << Relay[0].timeON.hour() << F(":") << Relay[0].timeON.minute() << F(">") << var; lcd.setCursor(4, 1); lcd << Relay[0].timeOFF.hour() << F(":") << Relay[0].timeOFF.minute() << F(":") << Relay[0].timeOFF.second(); lcd.show(); } Btn.Do = [] { Relay[0].timeON.setSecond(var); var = Relay[0].timeOFF.hour(); go(scr1_hour2); }; JoyLR.Do1 = [] { if (var < 59)var++; go(scr1_sec1); }; JoyLR.Do2 = [] { if (var > 0)var--; go(scr1_sec1); }; break; case scr1_hour2: { // установка часов реле1 выкл lcd << F("Re1 ") << Relay[0].timeON.hour() << F(":") << Relay[0].timeON.minute() << F(":") << Relay[0].timeON.second(); lcd.setCursor(3, 1); lcd << F(">") << var << F(":") << Relay[0].timeOFF.minute() << F(":") << Relay[0].timeOFF.second(); lcd.show(); } Btn.Do = [] { Relay[0].timeOFF.setHour(var); var = Relay[0].timeOFF.minute(); go(scr1_min2); }; JoyLR.Do1 = [] { if (var < 23)var++; go(scr1_hour2); }; JoyLR.Do2 = [] { if (var > 0)var--; go(scr1_hour2); }; break; case scr1_min2: { // установка минут реле1 выкл lcd << F("Re1 ") << Relay[0].timeON.hour() << F(":") << Relay[0].timeON.minute() << F(":") << Relay[0].timeON.second(); lcd.setCursor(4, 1); lcd << Relay[0].timeOFF.hour() << F(">") << var << F(":") << Relay[0].timeOFF.second(); lcd.show(); } Btn.Do = [] { Relay[0].timeOFF.setMinute(var); var = Relay[0].timeOFF.second(); go(scr1_sec2); }; JoyLR.Do1 = [] { if (var < 59)var++; go(scr1_min2); }; JoyLR.Do2 = [] { if (var > 0)var--; go(scr1_min2); }; break; case scr1_sec2: { // установка секунд реле1 выкл lcd << F("Re1 ") << Relay[0].timeON.hour() << F(":") << Relay[0].timeON.minute() << F(":") << Relay[0].timeON.second(); lcd.setCursor(4, 1); lcd << Relay[0].timeOFF.hour() << F(":") << Relay[0].timeOFF.minute() << F(">") << var; lcd.show(); } Btn.Do = [] { Relay[0].timeOFF.setSecond(var); go(scr1); }; JoyLR.Do1 = [] { if (var < 59)var++; go(scr1_sec2); }; JoyLR.Do2 = [] { if (var > 0)var--; go(scr1_sec2); }; break; case scr2: { //------------------------------------------------ 2- экран lcd << F("Re2 ") << Relay[1].timeON.hour() << F(":") << Relay[1].timeON.minute() << F(":") << Relay[1].timeON.second(); lcd.setCursor(4, 1); lcd << Relay[1].timeOFF.hour() << F(":") << Relay[1].timeOFF.minute() << F(":") << Relay[1].timeOFF.second(); lcd.show(); } Btn.Do = [] { var = Relay[1].timeON.hour(); go(scr2_hour1); }; JoyLR.Do1 = [] {go(scr1);}; JoyLR.Do2 = [] {go(scr3);}; break; case scr2_hour1: { // установка часов реле2 вкл lcd << F("Re2>") << var << F(":") << Relay[1].timeON.minute() << F(":") << Relay[1].timeON.second(); lcd.setCursor(4, 1); lcd << Relay[1].timeOFF.hour() << F(":") << Relay[1].timeOFF.minute() << F(":") << Relay[1].timeOFF.second(); lcd.show(); } Btn.Do = [] { Relay[1].timeON.setHour(var); var = Relay[1].timeON.minute(); go(scr2_min1); }; JoyLR.Do1 = [] { if (var < 23)var++; go(scr2_hour1); }; JoyLR.Do2 = [] { if (var > 0)var--; go(scr2_hour1); }; break; case scr2_min1: { // установка минут реле2 вкл lcd << F("Re2 ") << Relay[1].timeON.hour() << F(">") << var << F(":") << Relay[1].timeON.second(); lcd.setCursor(4, 1); lcd << Relay[1].timeOFF.hour() << F(":") << Relay[1].timeOFF.minute() << F(":") << Relay[1].timeOFF.second(); lcd.show(); } Btn.Do = [] { Relay[1].timeON.setMinute(var); var = Relay[1].timeON.second(); go(scr2_sec1); }; JoyLR.Do1 = [] { if (var < 59)var++; go(scr2_min1); }; JoyLR.Do2 = [] { if (var > 0)var--; go(scr2_min1); }; break; case scr2_sec1: { // установка секунд реле2 вкл lcd << F("Re2 ") << Relay[1].timeON.hour() << F(":") << Relay[1].timeON.minute() << F(">") << var; lcd.setCursor(4, 1); lcd << Relay[1].timeOFF.hour() << F(":") << Relay[1].timeOFF.minute() << F(":") << Relay[1].timeOFF.second(); lcd.show(); } Btn.Do = [] { Relay[1].timeON.setSecond(var); var = Relay[1].timeOFF.hour(); go(scr2_hour2); }; JoyLR.Do1 = [] { if (var < 59)var++; go(scr2_sec1); }; JoyLR.Do2 = [] { if (var > 0)var--; go(scr2_sec1); }; break; case scr2_hour2: { // установка часов реле2 выкл lcd << F("Re2 ") << Relay[1].timeON.hour() << F(":") << Relay[1].timeON.minute() << F(":") << Relay[1].timeON.second(); lcd.setCursor(3, 1); lcd << F(">") << var << F(":") << Relay[1].timeOFF.minute() << F(":") << Relay[1].timeOFF.second(); lcd.show(); } Btn.Do = [] { Relay[1].timeOFF.setHour(var); var = Relay[1].timeOFF.minute(); go(scr2_min2); }; JoyLR.Do1 = [] { if (var < 23)var++; go(scr2_hour2); }; JoyLR.Do2 = [] { if (var > 0)var--; go(scr2_hour2); }; break; case scr2_min2: { // установка минут реле2 выкл lcd << F("Re2 ") << Relay[1].timeON.hour() << F(":") << Relay[1].timeON.minute() << F(":") << Relay[1].timeON.second(); lcd.setCursor(4, 1); lcd << Relay[1].timeOFF.hour() << F(">") << var << F(":") << Relay[1].timeOFF.second(); lcd.show(); } Btn.Do = [] { Relay[1].timeOFF.setMinute(var); var = Relay[1].timeOFF.second(); go(scr2_sec2); }; JoyLR.Do1 = [] { if (var < 59)var++; go(scr2_min2); }; JoyLR.Do2 = [] { if (var > 0)var--; go(scr2_min2); }; break; case scr2_sec2: { // установка секунд реле2 выкл lcd << F("Re2 ") << Relay[1].timeON.hour() << F(":") << Relay[1].timeON.minute() << F(":") << Relay[1].timeON.second(); lcd.setCursor(4, 1); lcd << Relay[1].timeOFF.hour() << F(":") << Relay[1].timeOFF.minute() << F(">") << var; lcd.show(); } Btn.Do = [] { Relay[1].timeOFF.setSecond(var); go(scr2); }; JoyLR.Do1 = [] { if (var < 59)var++; go(scr2_sec2); }; JoyLR.Do2 = [] { if (var > 0)var--; go(scr2_sec2); }; break; case scr3: { //---------------------------------- 3- экран lcd << F("Re3 ") << Relay[2].timeON.hour() << F(":") << Relay[2].timeON.minute() << F(":") << Relay[2].timeON.second(); lcd.setCursor(4, 1); lcd << Relay[2].timeOFF.hour() << F(":") << Relay[2].timeOFF.minute() << F(":") << Relay[2].timeOFF.second(); lcd.show(); } Btn.Do = [] { var = Relay[2].timeON.hour(); go(scr3_hour1); }; JoyLR.Do1 = [] {go(scr2);}; JoyLR.Do2 = [] {go(scr4);}; break; case scr3_hour1: { // установка часов реле3 вкл lcd << F("Re3>") << var << F(":") << Relay[2].timeON.minute() << F(":") << Relay[2].timeON.second(); lcd.setCursor(4, 1); lcd << Relay[2].timeOFF.hour() << F(":") << Relay[2].timeOFF.minute() << F(":") << Relay[2].timeOFF.second(); lcd.show(); } Btn.Do = [] { Relay[2].timeON.setHour(var); var = Relay[2].timeON.minute(); go(scr3_min1); }; JoyLR.Do1 = [] { if (var < 23)var++; go(scr3_hour1); }; JoyLR.Do2 = [] { if (var > 0)var--; go(scr3_hour1); }; break; case scr3_min1: { // установка минут реле1 вкл lcd << F("Re3 ") << Relay[2].timeON.hour() << F(">") << var << F(":") << Relay[2].timeON.second(); lcd.setCursor(4, 1); lcd << Relay[2].timeOFF.hour() << F(":") << Relay[2].timeOFF.minute() << F(":") << Relay[2].timeOFF.second(); lcd.show(); } Btn.Do = [] { Relay[2].timeON.setMinute(var); var = Relay[2].timeON.second(); go(scr3_sec1); }; JoyLR.Do1 = [] { if (var < 59)var++; go(scr3_min1); }; JoyLR.Do2 = [] { if (var > 0)var--; go(scr3_min1); }; break; case scr3_sec1: { // установка секунд реле3 вкл lcd << F("Re3 ") << Relay[2].timeON.hour() << F(":") << Relay[2].timeON.minute() << F(">") << var; lcd.setCursor(4, 1); lcd << Relay[2].timeOFF.hour() << F(":") << Relay[2].timeOFF.minute() << F(":") << Relay[2].timeOFF.second(); lcd.show(); } Btn.Do = [] { Relay[2].timeON.setSecond(var); var = Relay[2].timeOFF.hour(); go(scr3_hour2); }; JoyLR.Do1 = [] { if (var < 59)var++; go(scr3_sec1); }; JoyLR.Do2 = [] { if (var > 0)var--; go(scr3_sec1); }; break; case scr3_hour2: { // установка часов реле3 выкл lcd << F("Re3 ") << Relay[2].timeON.hour() << F(":") << Relay[2].timeON.minute() << F(":") << Relay[2].timeON.second(); lcd.setCursor(3, 1); lcd << F(">") << var << F(":") << Relay[2].timeOFF.minute() << F(":") << Relay[2].timeOFF.second(); lcd.show(); } Btn.Do = [] { Relay[2].timeOFF.setHour(var); var = Relay[2].timeOFF.minute(); go(scr3_min2); }; JoyLR.Do1 = [] { if (var < 23)var++; go(scr3_hour2); }; JoyLR.Do2 = [] { if (var > 0)var--; go(scr3_hour2); }; break; case scr3_min2: { // установка минут реле3 выкл lcd << F("Re3 ") << Relay[2].timeON.hour() << F(":") << Relay[2].timeON.minute() << F(":") << Relay[2].timeON.second(); lcd.setCursor(4, 1); lcd << Relay[2].timeOFF.hour() << F(">") << var << F(":") << Relay[2].timeOFF.second(); lcd.show(); } Btn.Do = [] { Relay[0].timeOFF.setMinute(var); var = Relay[0].timeOFF.second(); go(scr3_sec2); }; JoyLR.Do1 = [] { if (var < 59)var++; go(scr3_min2); }; JoyLR.Do2 = [] { if (var > 0)var--; go(scr3_min2); }; break; case scr3_sec2: { // установка секунд реле3 выкл lcd << F("Re3 ") << Relay[2].timeON.hour() << F(":") << Relay[2].timeON.minute() << F(":") << Relay[2].timeON.second(); lcd.setCursor(4, 1); lcd << Relay[2].timeOFF.hour() << F(":") << Relay[2].timeOFF.minute() << F(">") << var; lcd.show(); } Btn.Do = [] { Relay[3].timeOFF.setSecond(var); go(scr3); }; JoyLR.Do1 = [] { if (var < 59)var++; go(scr3_sec2); }; JoyLR.Do2 = [] { if (var > 0)var--; go(scr3_sec2); }; break; case scr4: { // 4- экран lcd << F("Re4 ") << Relay[3].timeON.hour() << F(":") << Relay[3].timeON.minute() << F(":") << Relay[3].timeON.second(); lcd.setCursor(4, 1); lcd << Relay[3].timeOFF.hour() << F(":") << Relay[3].timeOFF.minute() << F(":") << Relay[3].timeOFF.second(); lcd.show(); } Btn.Do = [] { var = Relay[3].timeON.hour(); go(scr4_hour1); }; JoyLR.Do1 = [] {go(scr3);}; JoyLR.Do2 = [] {go(scr5);}; break; case scr4_hour1: { // установка часов реле4 вкл lcd << F("Re4>") << var << F(":") << Relay[3].timeON.minute() << F(":") << Relay[3].timeON.second(); lcd.setCursor(4, 1); lcd << Relay[3].timeOFF.hour() << F(":") << Relay[3].timeOFF.minute() << F(":") << Relay[3].timeOFF.second(); lcd.show(); } Btn.Do = [] { Relay[3].timeON.setHour(var); var = Relay[3].timeON.minute(); go(scr4_min1); }; JoyLR.Do1 = [] { if (var < 23)var++; go(scr4_hour1); }; JoyLR.Do2 = [] { if (var > 0)var--; go(scr4_hour1); }; break; case scr4_min1: { // установка минут реле4 вкл lcd << F("Re4 ") << Relay[3].timeON.hour() << F(">") << var << F(":") << Relay[3].timeON.second(); lcd.setCursor(4, 1); lcd << Relay[3].timeOFF.hour() << F(":") << Relay[3].timeOFF.minute() << F(":") << Relay[3].timeOFF.second(); lcd.show(); } Btn.Do = [] { Relay[0].timeON.setMinute(var); var = Relay[0].timeON.second(); go(scr4_sec1); }; JoyLR.Do1 = [] { if (var < 59)var++; go(scr4_min1); }; JoyLR.Do2 = [] { if (var > 0)var--; go(scr4_min1); }; break; case scr4_sec1: { // установка секунд реле4 вкл lcd << F("Re4 ") << Relay[3].timeON.hour() << F(":") << Relay[3].timeON.minute() << F(">") << var; lcd.setCursor(4, 1); lcd << Relay[3].timeOFF.hour() << F(":") << Relay[3].timeOFF.minute() << F(":") << Relay[3].timeOFF.second(); lcd.show(); } Btn.Do = [] { Relay[0].timeON.setSecond(var); var = Relay[3].timeOFF.hour(); go(scr4_hour2); }; JoyLR.Do1 = [] { if (var < 59)var++; go(scr4_sec1); }; JoyLR.Do2 = [] { if (var > 0)var--; go(scr4_sec1); }; break; case scr4_hour2: { // установка часов реле4 выкл lcd << F("Re4 ") << Relay[3].timeON.hour() << F(":") << Relay[3].timeON.minute() << F(":") << Relay[3].timeON.second(); lcd.setCursor(3, 1); lcd << F(">") << var << F(":") << Relay[3].timeOFF.minute() << F(":") << Relay[3].timeOFF.second(); lcd.show(); } Btn.Do = [] { Relay[3].timeOFF.setHour(var); var = Relay[3].timeOFF.minute(); go(scr4_min2); }; JoyLR.Do1 = [] { if (var < 23)var++; go(scr4_hour2); }; JoyLR.Do2 = [] { if (var > 0)var--; go(scr4_hour2); }; break; case scr4_min2: { // установка минут реле4 выкл lcd << F("Re4 ") << Relay[3].timeON.hour() << F(":") << Relay[3].timeON.minute() << F(":") << Relay[3].timeON.second(); lcd.setCursor(4, 1); lcd << Relay[3].timeOFF.hour() << F(">") << var << F(":") << Relay[3].timeOFF.second(); lcd.show(); } Btn.Do = [] { Relay[3].timeOFF.setMinute(var); var = Relay[3].timeOFF.second(); go(scr4_sec2); }; JoyLR.Do1 = [] { if (var < 59)var++; go(scr4_min2); }; JoyLR.Do2 = [] { if (var > 0)var--; go(scr4_min2); }; break; case scr4_sec2: { // установка секунд реле4 выкл lcd << F("Re4 ") << Relay[3].timeON.hour() << F(":") << Relay[3].timeON.minute() << F(":") << Relay[3].timeON.second(); lcd.setCursor(4, 1); lcd << Relay[3].timeOFF.hour() << F(":") << Relay[3].timeOFF.minute() << F(">") << var; lcd.show(); } Btn.Do = [] { Relay[3].timeOFF.setSecond(var); go(scr4); }; JoyLR.Do1 = [] { if (var < 59)var++; go(scr4_sec2); }; JoyLR.Do2 = [] { if (var > 0)var--; go(scr4_sec2); }; break; case scr5: { // 5- экран lcd << F("SetTime:") << now.hh << F(":") << now.mm << F(":") << now.ss ; lcd.show(); } Btn.Do = [] { Time = now; go(scr5_hour); }; JoyLR.Do1 = [] {go(scr4);}; JoyLR.Do2 = [] {go(scr0);}; break; case scr5_hour: { lcd << F("SetTime>") << Time.hh << F(":") << Time.mm << F(":") << Time.ss; lcd.show(); } Btn.Do = [] {go(scr5_min);}; JoyLR.Do1 = [] { if (Time.hh > 0)Time.hh--; go(scr5_hour); }; JoyLR.Do2 = [] { if (Time.hh < 23)Time.hh++; go(scr5_hour); }; break; case scr5_min: { lcd << F("SetTime:") << Time.hh << F(">") << Time.mm << F(":") << Time.ss ; lcd.show(); } Btn.Do = [] {go(scr5_sec);}; JoyLR.Do1 = [] { if (Time.mm > 0)Time.mm--; go(scr5_min); }; JoyLR.Do2 = [] { if (Time.mm < 59)Time.mm++; go(scr5_min); }; break; case scr5_sec: { lcd << F("SetTime:") << Time.hh << F(":") << Time.mm << F(">") << Time.ss; lcd.show(); } Btn.Do = [] { rtc.write(Time); now = Time; for (int i = 0; i < RelayNum; i++)Relay[i].reset(); go(scr5); }; JoyLR.Do1 = [] { if (Time.ss > 0)Time.ss--; go(scr5_sec); }; JoyLR.Do2 = [] { if (Time.ss < 59)Time.ss++; go(scr5_sec); }; break; } } void menuInit() { lcd.lightON(); now = rtc.read(); JoyUD.Do1 = [] {lcd.lightON();}; JoyUD.Do2 = [] {lcd.lightOFF();}; go(scr0); } void menuRun() { if (scr != scr0 && millis() - past >= 3000)go(scr0); if (scr == scr0 && millis() - past >= 500)go(scr0); } //----------------------------- void setup() { lcd.init(); //rtc.write(F("00:00:00")); rtc.write(F(__TIME__));//(для первичной настройки часов) now = rtc.read(); setZero();////(для первичной настройки устройства) for (int i = 0; i < RelayNum; i++)Relay[i].init(); Btn.init(); JoyLR.init(); JoyUD.init(); menuInit(); } void loop() { now_ = now; now = rtc.read(); if (now_.hh == 23 && now.hh == 0) for (int i = 0; i < RelayNum; i++)Relay[i].reset(); for (int i = 0; i < RelayNum; i++)Relay[i].run(); Btn.run(); JoyLR.run(); JoyUD.run(); menuRun(); } /**/А это мало кого заинтересует
/**/ class Cl_lcd: public Print { protected: public: void init() { Serial.begin(9600); } inline size_t write(uint8_t value) { Serial.write(value); return 1; } }; typedef Cl_lcd& (*pDo)(Cl_lcd&); inline Cl_lcd & operator << (Cl_lcd &s, pDo Do) { Do(s); return s; } inline Cl_lcd & operator << (Cl_lcd &s, const char *n) { s.print(n); return s; } Cl_lcd& clear(Cl_lcd& s) { s.print("<clear>"); return s; } Cl_lcd lcd; //------------------------------ class Cl_Data { protected: byte value; public: Cl_Data (byte v): value(v) {} friend Cl_lcd & operator << (Cl_lcd &s, Cl_Data obj) { s.print(obj.value); return s; } }; Cl_Data Data(5); //--------------------------- void setup() { lcd.init(); clear(lcd) << "aa:" << Data << " bbb" << clear; } void loop() { }Специализация шаблонов функций
template <typename T> inline Print & operator << (Print &s, T n) { s.print(n); return s; } template <> inline Print & operator << (Print &s, byte n) { if (n < 10)s.print(" "); s.print(n); return s; } void setup() { Serial.begin(9600); byte time = 9; Serial << "T:" << time << " :" << time << ":" << time; } void loop() { }Ну пока так.
так "мысли вслух"
/**/ class Cl_data {//<-недостаток2 - класс должен быть объявлен заранее public: byte value, value1;//<- недостаток - данные должны быть открыты Cl_data(byte v, byte v1) : value(v), value1(v1) {} }; // специализация шаблона << template <typename T> inline Print & operator << (Print &s, T n) { s.print(n); return s; } template <> inline Print & operator << (Print &s, byte n) { if (n < 10)s.print("0"); s.print(n); return s; } template <> inline Print & operator << (Print &s, Cl_data n) { return s << "data:" << n.value << "," << n.value1; } Cl_data data(5, 20); void setup() { Serial.begin(9600); byte time = 9; Serial << "T:" << time << " " << data; } void loop() { }/**/ typedef HardwareSerial& (*pDo1)(HardwareSerial&); //-------часы блок.h------------------------------- uint8_t conv2d(const char* p); class dTime { protected: public: byte hour, minute, second; dTime(unsigned long t = 0); dTime(byte h, byte m, byte s); dTime(const dTime& t); dTime(const char* time); dTime(const __FlashStringHelper* time); unsigned long time(); dTime& operator=(const dTime& t); }; uint8_t conv2d(const char* p); //-------часы блок.cpp------------------------------- uint8_t conv2d(const char* p) { uint8_t v = 0; if ('0' <= *p && *p <= '9') v = *p - '0'; return 10 * v + *++p - '0'; } dTime::dTime(unsigned long t) : hour(t / 60 / 60 % 24), minute(t / 60 % 60), second(t % 60) {} dTime::dTime(const dTime& t)// : hour(copy.hour), minute(copy.minute), second(copy.second) { hour = t.hour; minute = t.minute; second = t.second; } dTime::dTime(byte h, byte m, byte s) : hour(h), minute(m), second(s) {} dTime::dTime(const char* time) { hour = conv2d(time); minute = conv2d(time + 3); second = conv2d(time + 6); } dTime::dTime(const __FlashStringHelper* time) { char buff[8]; memcpy_P(buff, time, 8); hour = conv2d(buff); minute = conv2d(buff + 3); second = conv2d(buff + 6); } unsigned long dTime::time() { return ((hour * 24 + minute) * 60 + second); } dTime& dTime::operator=(const dTime& t) { if (this == &t) return *this; hour = t.hour; minute = t.minute; second = t.second; return *this; } dTime now("01:01:01"); //----------------------------------- // специализация шаблона << template <typename T> inline HardwareSerial & operator << (HardwareSerial &s, T n) { s.print(n); return s; } template <> inline HardwareSerial & operator << (HardwareSerial &s, pDo1 Do) { Do(s); return s; } template <> inline HardwareSerial & operator << (HardwareSerial &s, byte n) { if (n < 10)s.print("0"); s.print(n); return s; } template <> inline HardwareSerial & operator << (HardwareSerial &s, dTime obj) { return s << "time:" << obj.hour << ":" << obj.minute << ":" << obj.second ; } HardwareSerial & endl(HardwareSerial & streem) { streem << "\n"; return streem; } void setup() { Serial.begin(9600); now = dTime(F(__TIME__)); Serial << now << endl; Serial << now << endl; Serial << now << endl; } void loop() { }/* Не забудьте подключить часы DS3231 на I2C */ typedef HardwareSerial& (*pDo1)(HardwareSerial&); //-------часы блок.h------------------------------- #define DS3231_ADDRESS 0x68 #define DS3231_CONTROL 0x0E #define DS3231_STATUSREG 0x0F #include <Wire.h> class dTime { protected: public: byte hour, minute, second; dTime(unsigned long t = 0); dTime(byte h, byte m, byte s); dTime(const dTime& t); dTime(const char* time); dTime(const __FlashStringHelper* time); unsigned long time(); dTime& operator=(const dTime& t); }; class RTC_DS3231 { public: void write(dTime t);// записать время в часы dTime read();// прочитать время из часов }; uint8_t read_i2c_register(uint8_t addr, uint8_t reg); void write_i2c_register(uint8_t addr, uint8_t reg, uint8_t val); uint8_t conv2d(const char* p); uint8_t bcd2bin (uint8_t val); uint8_t bin2bcd (uint8_t val); //-------часы блок.cpp------------------------------- dTime::dTime(unsigned long t) : hour(t / 60 / 60 % 24), minute(t / 60 % 60), second(t % 60) {} dTime::dTime(const dTime& t)// : hour(copy.hour), minute(copy.minute), second(copy.second) { hour = t.hour; minute = t.minute; second = t.second; } dTime::dTime(byte h, byte m, byte s) : hour(h), minute(m), second(s) {} dTime::dTime(const char* time) { hour = conv2d(time); minute = conv2d(time + 3); second = conv2d(time + 6); } dTime::dTime(const __FlashStringHelper* time) { char buff[8]; memcpy_P(buff, time, 8); hour = conv2d(buff); minute = conv2d(buff + 3); second = conv2d(buff + 6); } unsigned long dTime::time() { return ((hour * 24 + minute) * 60 + second); } dTime& dTime::operator=(const dTime& t) { if (this == &t) return *this; hour = t.hour; minute = t.minute; second = t.second; return *this; } uint8_t read_i2c_register(uint8_t addr, uint8_t reg) { Wire.beginTransmission(addr); Wire.write((byte)reg); Wire.endTransmission(); Wire.requestFrom(addr, (byte)1); return Wire.read(); } void write_i2c_register(uint8_t addr, uint8_t reg, uint8_t val) { Wire.beginTransmission(addr); Wire.write((byte)reg); Wire.write((byte)val); Wire.endTransmission(); } void RTC_DS3231::write(dTime t) { Wire.beginTransmission(DS3231_ADDRESS); Wire.write((byte)0); // start at location 0 Wire.write(bin2bcd(t.second)); Wire.write(bin2bcd(t.minute)); Wire.write(bin2bcd(t.hour)); Wire.endTransmission(); uint8_t statreg = read_i2c_register(DS3231_ADDRESS, DS3231_STATUSREG); statreg &= ~0x80; // flip OSF bit write_i2c_register(DS3231_ADDRESS, DS3231_STATUSREG, statreg); } dTime RTC_DS3231::read() { Wire.beginTransmission(DS3231_ADDRESS); Wire.write((byte)0); Wire.endTransmission(); Wire.requestFrom(DS3231_ADDRESS, 7); uint8_t s = bcd2bin(Wire.read() & 0x7F); uint8_t m = bcd2bin(Wire.read()); uint8_t h = bcd2bin(Wire.read()); return dTime(h, m, s); } uint8_t bcd2bin (uint8_t val) { return val - 6 * (val >> 4); } uint8_t bin2bcd (uint8_t val) { return val + 6 * (val / 10); } uint8_t conv2d(const char* p) { uint8_t v = 0; if ('0' <= *p && *p <= '9') v = *p - '0'; return 10 * v + *++p - '0'; } //----------------------------------- // специализация шаблона << template <typename T> inline HardwareSerial & operator << (HardwareSerial &s, T n) { s.print(n); return s; } template <> inline HardwareSerial & operator << (HardwareSerial &s, pDo1 Do) { Do(s); return s; } template <> inline HardwareSerial & operator << (HardwareSerial &s, byte n) { if (n < 10)s.print("0"); s.print(n); return s; } template <> inline HardwareSerial & operator << (HardwareSerial &s, dTime obj) { return s << "time:" << obj.hour << ":" << obj.minute << ":" << obj.second ; } HardwareSerial & endl(HardwareSerial & streem) { streem << "\n"; return streem; } //------------------------------------------ RTC_DS3231 rtc;// часы dTime now("01:01:01"); //------------------------------------------- void setup() { Serial.begin(9600); Wire.begin(); now = dTime(F(__TIME__));// для первичной настройки часов rtc.write(now); } void loop() { now = rtc.read(); Serial << now << endl; delay(1000); }/**/ typedef byte state_t; const state_t sOFF = 0; const state_t sON = 1; const state_t sEND = 2; const char* viev(state_t s) { const char *pOFF PROGMEM = "sOFF"; const char *pON PROGMEM = "pON"; const char *pEND PROGMEM = "pEND"; const char *const MAP[] PROGMEM = {pOFF, pON, pEND}; return MAP[s]; } void setup() { Serial.begin(9600); for (state_t i = sOFF; i <= sEND; i++) Serial.println(viev(i)); } void loop() { }/**/ #define VIEV( n, a,b,c,d)\ reinterpret_cast<const __FlashStringHelper *>( \ __extension__(\ { static const char str1[] PROGMEM = a;\ static const char str2[] PROGMEM = b;\ static const char str3[] PROGMEM = c;\ static const char str4[] PROGMEM = d;\ static const char* const Arr[] PROGMEM = {str1, str2, str3, str4};\ Arr[n];\ }\ )\ ) //------------------------------------------------------- void setup() { Serial.begin(9600); Serial.println( reinterpret_cast<const __FlashStringHelper *>( __extension__( { static const char str1[] PROGMEM = "str1qwe"; static const char str2[] PROGMEM = "str2qwe"; static const char str3[] PROGMEM = "str3qwe"; static const char str4[] PROGMEM = "str4qwe"; static const char* const Arr[] PROGMEM = {str1, str2, str3, str4}; Arr[2]; } ) ) ); int a=0; Serial.println(VIEV( a,"1---","2----", "3---", "4---")); } void loop() { }/**/ //------------- дисплей----------------------- //--------------устройство--------------------- const byte dOFF = 0;// устройство выключено const byte dLOW = 1;// устройство включено низкий уровень const byte dHIGH = 2;// устройство включено высокий уровень unsigned long devPast; byte state; void set(const byte s) { devPast = millis(); state = s; switch (s) { case dOFF: break; case dLOW: break; case dHIGH: break; } } void devInit() { set(dOFF); } void devRun() {} //------- кнопки --------------------------- typedef void (*pDo)(); class Cl_Btn { protected: const byte pin; unsigned long past; bool state; public: pDo Do = [] {}; Cl_Btn(const byte p) : pin(p) {} void init() {}; void run() {}; }; Cl_Btn Left (/*пин*/2); Cl_Btn Right (/*пин*/3); Cl_Btn Select(/*пин*/4); //------------меню-------------------- const byte scr0 = 0;// главный экран const byte scr1 = 1;// пуск/стоп const byte scr2 = 2;// установка длительности const byte scr3 = 3;// установка периода const byte scr4 = 4;// установка ШИМ unsigned long past; byte scr;// текущий экран void go(const byte s) { scr = s; past = millis(); switch (s) { case scr0: break; case scr1: break; case scr2: break; case scr3: break; case scr4: break; } } void menuInit() { go(scr0); } void menuRun() { if (scr != scr0 && millis() - past >= 10000)go(scr0); if (scr == scr0 && millis() - past >= 1000)go(scr0); } //------------------------------- void setup() { devInit(); Left.init(); Right.init(); Select.init(); menuInit(); } void loop() { devRun(); Left.run(); Right.run(); Select.run(); menuRun(); } /**/С какой целью в строке №30 описана переменная Do, которая потом нигде не используется?
Стратегический запас.
С какой целью в строке №30 описана переменная Do, которая потом нигде не используется?
/**/ //------------- дисплей----------------------- #include <Wire.h> // команды #define LCD_CLEARDISPLAY 0x01 #define LCD_RETURNHOME 0x02 #define LCD_ENTRYMODESET 0x04 #define LCD_DISPLAYCONTROL 0x08 #define LCD_CURSORSHIFT 0x10 #define LCD_FUNCTIONSET 0x20 #define LCD_SETCGRAMADDR 0x40 #define LCD_SETDDRAMADDR 0x80 // флаги для режима ввода дисплея #define LCD_ENTRYRIGHT 0x00 #define LCD_ENTRYLEFT 0x02 #define LCD_ENTRYSHIFTINCREMENT 0x01 #define LCD_ENTRYSHIFTDECREMENT 0x00 // флаги для управления включением / выключением дисплея #define LCD_DISPLAYON 0x04 #define LCD_DISPLAYOFF 0x00 #define LCD_CURSORON 0x02 #define LCD_CURSOROFF 0x00 #define LCD_BLINKON 0x01 #define LCD_BLINKOFF 0x00 // флаги для отображения / сдвига курсора #define LCD_DISPLAYMOVE 0x08 #define LCD_CURSORMOVE 0x00 #define LCD_MOVERIGHT 0x04 #define LCD_MOVELEFT 0x00 // флаги для набора функций #define LCD_8BITMODE 0x10 #define LCD_4BITMODE 0x00 #define LCD_2LINE 0x08 #define LCD_1LINE 0x00 #define LCD_5x10DOTS 0x04 #define LCD_5x8DOTS 0x00 // флаги для управления подсветкой #define LCD_lightON 0x08 #define LCD_lightOFF 0x00 #define En B00000100 // Бит разрешения #define Rw B00000010 // Чтение / запись бит #define Rs B00000001 // Бит выбора регистра class Cl_lcd1602_i2c : public Print { protected: uint8_t adr, posX, posY; uint8_t _lightONval; uint8_t _displayfunction; uint8_t _displaycontrol; uint8_t _displaymode; byte buffer[32]; public: Cl_lcd1602_i2c(uint8_t a): adr(a) {} void init() { Wire.begin(); write4bits(0x03 << 4); delayMicroseconds(4500); // ждем не меньше 4.1ms write4bits(0x03 << 4); delayMicroseconds(4500); // ждем не меньше 4.1ms write4bits(0x03 << 4); delayMicroseconds(150); write4bits(0x02 << 4); delay(50); _lightONval = LCD_lightOFF; expanderWrite(_lightONval); // сбросить расширение и выключить подсветку (бит 8 = 1) // режим работы дисплея 4-х битный интерфейс ,две строки,5х8 точек _displayfunction = LCD_4BITMODE | LCD_2LINE | LCD_5x8DOTS; command(LCD_FUNCTIONSET | _displayfunction); // режим контроля дисплей вкл, курсор не мигает,дисплей не мигает _displaycontrol = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF; command(LCD_DISPLAYCONTROL | _displaycontrol); // режим ввода текста в память-начинать слева с движением в право _displaymode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT; command(LCD_ENTRYMODESET | _displaymode); clear(); } // подсветку вкл/выкл void lightON(void) { _lightONval = LCD_lightON; expanderWrite(0); } void lightOFF(void) { _lightONval = LCD_lightOFF; expanderWrite(0); } // очистить буфер void clear() { for (byte i = 0; i < 32; i++ )buffer[i] = 0x20; posX = 0; posY = 0; } // отправить информацию из буфера на экран void show() { line(0); for (byte i = 0; i < 16; i++ )out(buffer[i]); line(1); for (byte i = 16; i < 32; i++ )out(buffer[i]); } void setCursor(byte x, byte y) { if (x > 16) x = 16; else posX = x; if (y > 2) x = 2; else posY = y; } private: /*внутрение функции*/ void line(byte l) { if (l == 0) command(LCD_SETDDRAMADDR | 0x00); else command(LCD_SETDDRAMADDR | 0x40); } inline void out(uint8_t value) { send(value, Rs); } inline size_t write(uint8_t value) { if (posX < 16 && posY < 2) { buffer[posY * 16 + posX] = value; posX++; } return 1; } /*команды низкоуровневого управления*/ inline void command(uint8_t value) { send(value, 0); } void send(uint8_t value, uint8_t mode) { uint8_t highnib = value & 0xf0; write4bits((highnib) | mode); uint8_t lownib = (value << 4) & 0xf0; write4bits((lownib) | mode); } void write4bits(uint8_t value) { expanderWrite(value); pulseEnable(value); } void expanderWrite(uint8_t _data) { Wire.beginTransmission(adr); Wire.write((int)(_data) | _lightONval); Wire.endTransmission(); } void pulseEnable(uint8_t _data) { expanderWrite(_data | En); // En high delayMicroseconds(1); // enable pulse must be >450ns expanderWrite(_data & ~En); // En low delayMicroseconds(50); // commands need > 37us to settle } }; typedef Cl_lcd1602_i2c& (*pDo1)(Cl_lcd1602_i2c&); template <typename T> inline Cl_lcd1602_i2c & operator << (Cl_lcd1602_i2c &s, T n) { s.print(n); return s; } template <> inline Cl_lcd1602_i2c & operator << (Cl_lcd1602_i2c &s, pDo1 Do) { Do(s); return s; } template <> inline Cl_lcd1602_i2c & operator << (Cl_lcd1602_i2c &s, byte n) { if (n < 10)s.print("0"); s.print(n); return s; } Cl_lcd1602_i2c& clear(Cl_lcd1602_i2c& s) { s.clear(); return s; } Cl_lcd1602_i2c& show(Cl_lcd1602_i2c& s) { s.show(); return s; } Cl_lcd1602_i2c lcd(0x27);//0x3F //--------------устройство--------------------- const byte dOFF = 0;// устройство выключено const byte dLOW = 1;// устройство включено низкий уровень const byte dHIGH = 2;// устройство включено высокий уровень unsigned long devPast; byte state; void set(const byte s) { devPast = millis(); state = s; switch (s) { case dOFF: break; case dLOW: break; case dHIGH: break; } } void devInit() { set(dOFF); } void devRun() {} //------- кнопки --------------------------- typedef void (*pDo)(); class Cl_Btn { protected: byte pin; bool state; unsigned long past; void set(bool s) { state = s; past = millis(); if (s) Do(); } public: Cl_Btn(byte p): pin(p) {} pDo Do = [] {}; void init() { pinMode(pin, INPUT_PULLUP); set(false); } void run() { if (millis() - past >= 100) switch (state) { case false: if (!digitalRead(pin))set(true); break; case true: if (digitalRead(pin))set(false); if (millis() - past >= 300)set(false); break; } } }; Cl_Btn Left (/*пин*/2); Cl_Btn Right (/*пин*/3); Cl_Btn Select(/*пин*/4); //------------меню-------------------- const byte scr0 = 0;// главный экран const byte scr1 = 1;// пуск/стоп const byte scr2 = 2;// установка длительности const byte scr3 = 3;// установка периода const byte scr4 = 4;// установка ШИМ unsigned long past; byte scr;// текущий экран void go(const byte s) { scr = s; past = millis(); lcd << clear; switch (s) { case scr0: {// главный экран lcd << F("scr0") << show; } Left.Do = [] {}; Right.Do = [] {go(scr1);}; Select.Do = [] {}; break; case scr1: { // пуск/стоп lcd << F("scr1") << show; } Left.Do = [] {go(scr0);}; Right.Do = [] {go(scr2);}; Select.Do = [] {}; break; case scr2: { // установка длительности lcd << F("scr2") << show; } Left.Do = [] {go(scr1);}; Right.Do = [] {go(scr3);}; Select.Do = [] {}; break; case scr3: { // установка периода lcd << F("scr3") << show; } Left.Do = [] {go(scr2);}; Right.Do = [] {go(scr4);}; Select.Do = [] {}; break; case scr4: { // установка ШИМ lcd << F("scr4") << show; } Left.Do = [] {go(scr3);}; Right.Do = [] {}; Select.Do = [] {}; break; } } void menuInit() { lcd.lightON(); go(scr0); } void menuRun() { if (scr != scr0 && millis() - past >= 10000)go(scr0); if (scr == scr0 && millis() - past >= 1000)go(scr0); } //------------------------------- void setup() { lcd.init(); devInit(); Left.init(); Right.init(); Select.init(); menuInit(); } void loop() { devRun(); Left.run(); Right.run(); Select.run(); menuRun(); } /**/Поэтапное развитие проекта.
Даже компилятор замечает обкуренность автора :)
... :210:22: warning: switch condition has type bool [-Wswitch-bool]
Вррота, вы завязывайте с травой. Пользуйтесь провереными рецептами.
Так это компилятору надо завязывать. Он от твоего кода ох%евает - не я :)
До меня дошли слухи, что до народа дошли слухи, что я использую лямда функции не правильно. Сообщаю. Они не правдивы. Лямда-функции это очень простой иструмент и не надо носится с ним как с чемоданом без ручки. Отказаться жалко, а использовать страшно.
Возьмем этот скетч
typedef int num_t; //<-- создаем тип num_t aaa=5; // создаем переменную этого типа //--------------------------------------- void setup() { Serial.begin(9600); Serial.print(aaa); //<- используем эту переменую для вывода } void loop() { }Вам страшно использовать переменные. Нет. А чего здесь у Вас комплексы полезли.
typedef void(*pDo)(); //<-- создаем тип указатель на функцию pDo Do = []{}; // создаем переменую указатель на функцию и присваиваем ей значение лемдафункция void setup() { Do();//< - используем уже эту переменную как функцию } void loop() { }А так
typedef int(*pDo)(); //<-- создаем тип указатель на функцию pDo Do = [] { return 5;}; // создаем переменую указатель на функцию и присваиваем ей значение лемдафункция //----------------------------------- void setup() { Serial.begin(9600); Serial.print(Do()); } void loop() { }