Если не против.
Редактируемые переменные (уставки) и их мин. и макс. значения можно не хранить в ОЗУ, а только в еепром и загружать в локальные по необходимости. Это на случай если уставок десятки-сотни.
При работе с еепром удобно пользоваться атрибутом ЕЕМЕМ. Ненадо помнить где какая переменная лежит.
А теперь подключим 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
Ну где-то так
Поправил скетч #50 Понятно что скеч стал сложнее для понимания.Но проверил - работает
Ну а теперь подключим ... реле
Так на будущее на подумать.
Переписал программу #11 под теперешний стиль
Скетч для использования Ардуино-джойстика для меню, работает .
А теперь подключим lcd I2C с меню . джойстик вверх вкл подсветку, вниз выключить . вправо-влево бегаем по экранам меню . если ничего не делаем 10сек возврат на главный экран. Подобный скетч выше но на трех кнопках.
Добавил таймер на millis
Немного громоздко.Но похоже надо еще думать как упростить.
Тоже самое но чуть попроще в чтении скетча
Подключим 5 реле на таймеры и получим.
Моя упрощенная библиотека для работы с lcd1602 i2c
Я планирую позже использовать ее,так как она уменьшает мигание дисплея.
И вот с этой библиотекой код. И да если вы будете ее использовать,то не забывайте использовать команды clear() -очистка буфера и show()- отправка этого буфера в память дисплея
добавил класс- millis-часы(не полный)
Модуль с DS3231 и тестовый скетч
С недостатками но работает уже с модулем
Возможно это баян. Но вставив этот код в скетч вы всегда будете знать время последней зашивки кода
баян, еще какой.
тебе совсем там плохо ?
Может не NAME а всеже __FILE__? Да и VERSION - сугубо личное наверно.
Как бы расположение мне не особо нужно...
Да, и то и другое сугубо личное, но иногда полезное. С особо одарёнными заказчиками(.
Мой программный компонент для модуля DS3231
Добавил к часам управление 4-мя реле . Удачно получилось.
Немного подправил скетч.
А точно 4500 - это 4.1ms?
ПС: Похоже передыдущий скетч не был избавлен от ошибок. Так что новый вариант.
А это мало кого заинтересует
Специализация шаблонов функций
Ну пока так.
так "мысли вслух"
С какой целью в строке №30 описана переменная Do, которая потом нигде не используется?
Стратегический запас.
С какой целью в строке №30 описана переменная Do, которая потом нигде не используется?
Поэтапное развитие проекта.
Даже компилятор замечает обкуренность автора :)
... :210:22: warning: switch condition has type bool [-Wswitch-bool]
Вррота, вы завязывайте с травой. Пользуйтесь провереными рецептами.
Так это компилятору надо завязывать. Он от твоего кода ох%евает - не я :)
До меня дошли слухи, что до народа дошли слухи, что я использую лямда функции не правильно. Сообщаю. Они не правдивы. Лямда-функции это очень простой иструмент и не надо носится с ним как с чемоданом без ручки. Отказаться жалко, а использовать страшно.
Возьмем этот скетч
Вам страшно использовать переменные. Нет. А чего здесь у Вас комплексы полезли.
А так