класс титановый велосипед для тактовой кнопки.
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- …
- следующая ›
- последняя »
- Войдите на сайт для отправки комментариев
Чт, 06/08/2015 - 20:46
класс титановый велосипед для тактовой кнопки.
фильтр дребезга, отслеживание событий: нажатие, отпускание, двойное нажатие(doubleclick), нажато и удерживается в течении определённого времени, отпущено и неактивно в течении определённого времени.
01
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
02
// класс титановый велосипед для тактовой кнопки.
03
// фильтр дребезга, отслеживание событий: нажатие, отпускание, двойное нажатие(doubleclick), нажато и удерживается в течении определённого времени, отпущено и неактивно в течении определённого времени.
04
05
class
BUTTON {
06
public
:
07
//================================================================
08
static
const
byte
bounce_ = 50;
// длительность отслеживания дребезга.
09
static
const
byte
doubleclick_ = 200;
// длительность отслеживания двойного клика.
10
static
const
unsigned
long
timer_ = 5000;
// длительность отслеживания неактивности.
11
static
const
unsigned
int
retention_ = 2000;
// длительность отслеживания нажатия и удержания.
12
//================================================================
13
boolean click_down;
14
boolean click_up;
15
boolean doubleclick;
16
boolean timer;
17
boolean retention;
18
//=================================
19
unsigned
long
m;
20
boolean p;
21
boolean b;
22
boolean dc;
23
byte
c;
24
boolean t;
25
boolean r;
26
//=================================
27
byte
_pb;
28
//=================================
29
BUTTON(
byte
pb) {
30
_pb = pb;
31
pinMode(_pb, INPUT);
32
digitalWrite(_pb, 1);
33
//====
34
click_down = 0;
35
click_up = 0;
36
doubleclick = 0;
37
timer = 0;
38
retention = 0;
39
//====
40
m = millis();
41
p = digitalRead(_pb);
42
b = 0;
43
dc = 0;
44
c = 0;
45
t = 0;
46
r = 0;
47
//====
48
}
49
50
void
read() {
51
//=======================================================
52
unsigned
long
nm = millis();
53
boolean np = digitalRead(_pb);
54
//=================
55
boolean nb = 0;
56
boolean ndc = 0;
57
boolean nt = 0;
58
boolean nr = 0;
59
//================
60
click_down = 0;
61
click_up = 0;
62
doubleclick = 0;
63
timer = 0;
64
retention = 0;
65
//=================
66
if
(np != p) {p = np; m = nm; }
67
//=======================================================
68
if
(nm - m > bounce_) {nb = 1;}
69
if
(nm - m > doubleclick_) {ndc = 1;}
70
if
(ndc != dc) {dc = ndc;
if
(dc == 1) {c = 0;}}
71
if
(nb != b) {b = nb;
72
if
(p == 0 && b == 0) {click_down = 1;
73
++c;
if
(c == 2) {c = 0; doubleclick = 1;}
74
}
75
if
(p == 1 && b == 1) {click_up = 1;}
76
}
77
//=======================================================
78
if
(nm - m > timer_) {nt = 1;}
79
if
(nt != t) {t = nt;
80
if
(p == 1 && t == 1) {timer = 1;}
81
}
82
//=======================================================
83
if
(nm - m > retention_) {nr = 1;}
84
if
(nr != r) {r = nr;
85
if
(p == 0 && r == 1) {retention = 1;}
86
}
87
//=======================================================
88
}
89
};
90
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
пример, объясняющий отличия работы с кнопкой классическим способом и с использованием предложенного класса:
01
void
loop
() {
02
03
// классический способ использования кнопки.
04
if
(считываем логическое состояние пина кнопки == LOW) {что-то делаем при нажатой кнопке}
// стоп! а, зачем что-то делается во время каждого цикла loop многократно, если мы нажали на кнопку только один раз?
05
if
(считываем логическое состояние пина кнопки == HIGH) {что-то делаем при отпущенной кнопке}
// так же непорядок - что-то делается многократно, не смотря на то, что событие отпускания кнопки произошло ровно один раз.
06
07
// использование кнопки с классом - всё корректно: одно физическое событие генерит одно программное событие.
08
if
(нажатие == TRUE) {что-то делаем при нажатой кнопке}
09
if
(отпускание == TRUE) {что-то делаем при отпущенной кнопке}
10
if
(двойное нажатие == TRUE) {что-то делаем при двойном нажатии}
11
if
(удержание == TRUE) {что-то делаем, если нажато и удерживается в течении определённого времени}
12
if
(неактивность == TRUE) {что-то делаем, если отпущено и неактивно в течении определённого времени}
13
14
}
пример скетча с использованием класса:
01
//~~~~~~~~~~~~~~~~~~~~
02
// здесь код приведённого выше класса class BUTTON {};
03
//~~~~~~~~~~~~~~~~~~~~
04
05
BUTTON BUTTON_01(3);
// объявляем объект класса BUTTON кнопку с именем BUTTON_01, подключенную к пину 3.
06
BUTTON BUTTON_02(4);
// объявляем объект класса BUTTON кнопку с именем BUTTON_02, подключенную к пину 4.
07
08
void
setup
() {}
09
10
void
loop
() {
11
12
BUTTON_01.read();
// обновляем состояние переменных кнопки BUTTON_01.
13
BUTTON_02.read();
// обновляем состояние переменных кнопки BUTTON_02.
14
15
// работаем с переменными кнопки BUTTON_01.
16
if
(BUTTON_01.click_down) {что-то делаем при нажатии}
17
if
(BUTTON_01.click_up) {что-то делаем при отпускании}
18
if
(BUTTON_01.doubleclick) {что-то делаем при двойном нажатии(doubleclick)}
19
if
(BUTTON_01.timer) {что-то делаем, если кнопка отпущена и неактивна в течении определённого времени}
20
if
(BUTTON_01.retention) {что-то делаем при нажатии и удержании в течении определённого времени}
21
22
// работаем с переменными кнопки BUTTON_02.
23
if
(BUTTON_02.click_down) {}
24
if
(BUTTON_02.click_up) {}
25
if
(BUTTON_02.doubleclick) {}
26
if
(BUTTON_02.timer) {}
27
if
(BUTTON_02.retention) {}
28
29
}
UPD: упустил из вида очевидное - надеюсь, ползателям ясно, что эти переменные можно настраивать по своему хотению:
07
//================================================================
08
static
const
byte
bounce_ = 50;
// длительность отслеживания дребезга.
09
static
const
byte
doubleclick_ = 200;
// длительность отслеживания двойного клика.
10
static
const
unsigned
long
timer_ = 5000;
// длительность отслеживания неактивности.
11
static
const
unsigned
int
retention_ = 2000;
// длительность отслеживания нажатия и удержания.
12
//================================================================
Щас 10-ка ставится, потому много не напишу с телефона, но
Имена локальных переменных - мама роди меня обратно. Автор через неделю забудет что это и для чего. Для либы - это смерть. Утрирую, но так и есть, имена переменных должны пониматься без переводчика. Далее, все, что есть в классе имеет доступ public. Блджад, так нельзя. Нужно исходить из мысли, что члены класса не должны меняться снаружи никогда, только методами set и т.п. А щас, что хочу, то и ворочу. Это неправильно.
private - все, что никто не увидит. protected - это увидят только здесь и в порождённое классе. public - увидят все. Типа так
Огромное человеческое спасибо за данный класс. В своем новом проекте(новый контроллер для пивоварни) я полностью использую события данного класса.
Проект на стадии 50% готовности, кому интересно код прилагаю.
Проект разбит на 6 файлов.
001
// Last Relise - 05/08/2015 Alpha //
002
// Last Relise - 19/08/2015 Betha //
003
// Last Relise - 00/00/0000 Relise //
004
/////////////////////////////////////
005
006
// #define ENCODER_DO_NOT_USE_INTERRUPTS
007
008
#include <SD.h>
009
#include <SPI.h>
010
#include <Wire.h>
011
#include <EEPROM.h>
012
#include <Encoder.h>
013
#include <OneWire.h>
014
#include <LiquidCrystal_I2C.h>
015
#include <DS1307.h>
016
#include <RTClib.h>
017
#include <PID_v1.h>
018
#include <IniFile.h>
019
#include <TimeHelpers.h>
020
021
#define ONE_WIRE_BUS 7 // Шина датчика температуры
022
#define SD_SELECT 4 // Шина CS SD карты
023
#define ButtonEnc 8 // Кнопка энкодора
024
#define TEN1 13 // Порт шины нагревательного элемента 1
025
#define UPGRADE 1000 // Частота обновления главного экрана в милисикундах
026
027
//``````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````
028
byte
type_s;
// Создание переменной типа датчика измерения температуры
029
byte
data[12];
// Создание переменной данных датчика температуры
030
byte
addr[8];
// Создание переменной адреса датчика температуры
031
//
032
long
Pos;
// Создание переменной нового положения энкодера
033
long
position;
// Создание переменной текущего положения энкодера
034
long
NeoTime = 0;
// Создание переменной хранения значения unix времени конца выполнения программы
035
//
036
const
size_t bufferLen = 30;
// Создания константы размера буфера строк читаемых из ini файла
037
//
038
char
buffer[bufferLen];
// Создания буфера строк читаемых из ini файла
039
//
040
double
Setpoint;
// Создание переменной устанавливаемой температуры (и передача данных из памяти)
041
double
Input;
// Создание переменной входящих данных в ПИД регулятор
042
double
Output;
// Создание переменной исходящих данных из ПИД регулятора
043
double
consKp = 5;
// Создание переменных констант ПИД регулятора
044
double
consKi = 75;
// Создание переменных констант ПИД регулятора
045
double
consKd = 1;
// Создание переменных констант ПИД регулятора
046
//
047
String FileiniNAMEAn;
048
String FileiniNAME;
049
// 0 1 2 3 4 5 6 7 8 9
050
const
String Prog[10] = {
"PROG_1"
,
"PROG_2"
,
"PROG_3"
,
"PROG_4"
,
"PROG_5"
,
"PROG_6"
,
"PROG_7"
,
"PROG_8"
,
"PROG_9"
,
"PROG_10"
};
051
int
Pat[10][3] = {{20,0,0}, {20,0,0}, {20,0,0}, {20,0,0}, {20,0,0}, {20,0,0}, {20,0,0}, {20,0,0}, {20,0,0}, {20,0,0} };
052
int
prog = 0;
053
int
mem1 = 0;
054
int
mem2 = 0;
055
int
mem3 = 0;
056
int
Nasos_Start = 30;
057
int
Nasos_Stop = 80;
058
int
PID_SPEED = 3;
059
int
_HR = 0;
// Создание переменной хранения значения часов
060
int
_MI = 0;
// Создание переменной хранения значения минут
061
int
_SE = 0;
// Создание переменной хранения значения секунд
062
int
A_H = 0;
// Создание переменной хранения значения часов при изменении времени
063
int
A_M = 0;
// Создание переменной хранения значения минут при изменении времени
064
int
maxMenu = 40;
// Отсчет от 0 (количество пунктов -1).
065
int
curMenu = 0;
// Значение текущего пункта меню.
066
int
Moschnost;
// Создание переменной мощности нагревательного элемента
067
int
T_Upr = 0;
// Режим работы.
068
int
P_Numb = 0;
// Создание переменной определения пункта масива програмируемых периодов (общего назначения)
069
int
R_Numb = 0;
// Создание переменной определения пункта масива програмируемых периодов (отрисовка меню)
070
long
unixt;
// Создание переменной хранения текущего unix времени
071
long
Sec;
// Создание переменной временивыполнения программы
072
//
073
float
Mic1 = 0;
// Переменные измерения производительности
074
float
Mic2 = 0;
// Переменные измерения производительности
075
float
celsius;
// Создание переменной значения измерений датчика температуры
076
//
077
boolean StartTime = 0;
// Создание переменной начала работы по заданному переоду (Р1 - Р9)
078
boolean Rabota = 1;
// Создание переменной дополнительная переменная управления переключением периодов (Р1 - Р9)
079
boolean Alarm = 0;
// Создание переменной значения сигнализации
080
boolean chgTemp = 0;
// Создание переменной флага изменения значения температуры
081
boolean flag = 0;
// Создание переменной флага управления пьезо излучателем
082
boolean rasTempBol = 0;
// Создание переменной флага необходимости расчета времени
083
boolean tr_menu =
false
;
// Признак входа в меню настройки.
084
boolean dir =
false
;
// Признак переключения между вводом данных и листанием меню.
085
boolean keyPres =
false
;
// Признак исплнния клика по кнопке.
086
boolean STATUS =
false
;
// Состояние предохранителя (программа включена/выключенна)
087
boolean Udate =
true
;
// Обновление основного экрана
088
boolean SD_stat =
false
;
// Определяет наличие или отсутствие SD карты.
089
//``````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````
090
091
RTC_DS1307 rtc;
// Инициализация Часов точного времени
092
OneWire ds(ONE_WIRE_BUS);
// Инициализация шины датчика измерения температуры
093
LiquidCrystal_I2C lcd(0x27, 20, 4);
// Инициализация дисплея
094
DateTime now;
// Создания объекта Часов точного времени
095
PID myPID(&Input, &Output, &Setpoint, consKp, consKi, consKd, DIRECT);
// Инициализация ПИД регулятора
096
Encoder myEnc(2, 3);
097
File root;
098
File entry;
099
100
101
class
BUTTON {
102
public
:
103
//================================================================
104
static
const
byte
bounce_ = 50;
// длительность отслеживания дребезга.
105
static
const
byte
doubleclick_ = 200;
// длительность отслеживания двойного клика.
106
static
const
unsigned
int
retention_ = 2000;
// длительность отслеживания нажатия и удержания.
107
static
const
unsigned
long
timer_ = 60000;
// длительность отслеживания неактивности.
108
//================================================================
109
boolean click_down;
110
boolean click_up;
111
boolean doubleclick;
112
boolean timer;
113
boolean retention;
114
//=================================
115
unsigned
long
m;
116
boolean p;
117
boolean b;
118
boolean dc;
119
byte
c;
120
boolean t;
121
boolean r;
122
//=================================
123
byte
_pb;
124
//=================================
125
BUTTON(
byte
pb) {
126
_pb = pb;
127
pinMode(_pb, INPUT);
128
digitalWrite(_pb, 1);
129
//====
130
click_down = 0;
131
click_up = 0;
132
doubleclick = 0;
133
timer = 0;
134
retention = 0;
135
//====
136
m = millis();
137
p = digitalRead(_pb);
138
b = 0;
139
dc = 0;
140
c = 0;
141
t = 0;
142
r = 0;
143
//====
144
}
145
146
void
read() {
147
//=======================================================
148
unsigned
long
nm = millis();
149
boolean np = digitalRead(_pb);
150
//=================
151
boolean nb = 0;
152
boolean ndc = 0;
153
boolean nt = 0;
154
boolean nr = 0;
155
//================
156
click_down = 0;
157
click_up = 0;
158
doubleclick = 0;
159
timer = 0;
160
retention = 0;
161
//=================
162
if
(np != p) {p = np; m = nm; }
163
//=======================================================
164
if
(nm - m > bounce_) {nb = 1;}
165
if
(nm - m > doubleclick_) {ndc = 1;}
166
if
(ndc != dc) {dc = ndc;
if
(dc == 1) {c = 0;}}
167
if
(nb != b) {b = nb;
168
if
(p == 0 && b == 0) {click_down = 1;
169
++c;
if
(c == 2) {c = 0; doubleclick = 1;}
170
}
171
if
(p == 1 && b == 1) {click_up = 1;}
172
}
173
//=======================================================
174
if
(nm - m > timer_) {nt = 1;}
175
if
(nt != t) {t = nt;
if
(p == 1 && t == 1) {timer = 1;}}
176
//=======================================================
177
if
(nm - m > retention_) {nr = 1;}
178
if
(nr != r) {r = nr;
if
(p == 0 && r == 1) {retention = 1;}}
179
//=======================================================
180
}};
181
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
182
183
BUTTON BUTTON_01(ButtonEnc);
184
185
/////////////////////////////////////////////////////////////////\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
186
void
clearLine(
int
line){
if
(line <= 3 && line >= 0){lcd.setCursor(0, line); lcd.print(
" "
); lcd.setCursor(0, line);}
else
{lcd.clear();}}
187
void
Enc_Zero(
int
ps = 0){
if
(ps == 0) {myEnc.write(0);}
else
{ps = ps*4; myEnc.write(ps);} position = Pos;}
188
void
EnterCHG(){
if
(tr_menu ==
true
) {
if
(dir ==
true
) {Enc_Zero(curMenu); menu(curMenu);}
else
{lcd.setCursor(13, 0); lcd.print(
"Chenge"
); Enc_Zero(0); ChgData();} dir = !dir;}}
189
/////////////////////////////////////////////////////////////////\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
190
191
int
s;
// удалить временная парковочная переменная
192
193
void
setup
()
194
{
195
Serial
.begin(115200);
196
// SavePAT();
197
LoadPAT();
198
rtc.begin();
199
lcd.init(); lcd.backlight();
200
201
pinMode(TEN1, OUTPUT);
202
pinMode(ButtonEnc, INPUT); digitalWrite(ButtonEnc, HIGH);
203
204
myPID.SetMode(AUTOMATIC);
205
delay(500);
206
207
if
(!SD.begin(SD_SELECT)) {lcd.setCursor(0, 0); lcd.print(
"SD init - failed!"
);}
// Тестирование SD карты (карта отсутствует)
208
else
{lcd.setCursor(0, 0); lcd.print(
"SD init - ok"
); root = SD.open(
"/"
); root.rewindDirectory(); SD_stat =
true
;}
// Тестирование SD карты (карта на месте, исправна)
209
delay(1000); lcd.setCursor(0, 1); lcd.print(
"CPU init - ok"
);
// Приятный красивый мультик (несёт только эстетический хорактер)
210
delay(1000); lcd.setCursor(0, 2); lcd.print(
"SYS init - ok"
);
// Приятный красивый мультик (несёт только эстетический хорактер)
211
delay(1000); lcd.setCursor(0, 3); lcd.print(
"PID init - ok"
);
// Приятный красивый мультик (несёт только эстетический хорактер)
212
delay(2000);
213
lcd.clear();
214
}
215
216
void
loop
(){
217
Mic1 = millis();
218
now = rtc.now(); _HR = now.hour(); _MI = now.minute(); _SE = now.second();
219
getTemp();
220
Input = celsius;
// Конвертация типов переменных на вход ПИД регулятора.
221
DO_EVERY(PID_SPEED,{ myPID.Compute(); });
222
Pos = myEnc.read() / 4;
223
Moschnost = map(Output, 0, 255, 0, 100);
224
225
if
(STATUS) {analogWrite(TEN1, Output);}
else
{analogWrite(TEN1, 0); Moschnost = 0;}
226
227
//--------------------------------------------------------
228
BUTTON_01.read();
229
if
(BUTTON_01.timer) {lcd.noBacklight(); tr_menu =
false
; lcd.noBlink(); lcd.clear(); Enc_Zero(0); keyPres =
false
;}
230
if
(BUTTON_01.click_down) {keyPres =
true
; lcd.backlight();}
231
if
(BUTTON_01.retention) {lcd.backlight(); tr_menu = !tr_menu;
if
(tr_menu ==
true
) {Enc_Zero(0); menu(0); lcd.blink();}
else
{lcd.noBlink(); lcd.clear(); Enc_Zero(0); SavePAT();} keyPres =
false
;}
232
if
(BUTTON_01.doubleclick) {
if
(tr_menu ==
false
&& position == 1){STATUS =
true
; Enc_Zero(0);}
else
{STATUS =
false
;} Udate =
true
;}
233
if
(BUTTON_01.click_up) {
if
(keyPres ==
true
) {EnterCHG();} keyPres =
false
;}
234
//--------------------------------------------------------
235
236
if
(tr_menu ==
false
){ DO_EVERY(UPGRADE,{Udate =
true
;}); menu(99); }
237
238
if
(Pos != position) {position = Pos; lcd.backlight();
239
if
(tr_menu ==
false
) {
if
(position > 1) {Enc_Zero(0);}
else
if
(position < 0) {Enc_Zero(1);} Print_ctrl_main();}
240
if
(tr_menu ==
true
&& dir ==
false
) {
if
(position > maxMenu) {Enc_Zero(0);}
else
if
(position < 0) {Enc_Zero(maxMenu);} menu(position);}
241
if
(tr_menu ==
true
&& dir ==
true
) {ChgData();}
242
}
243
244
//``````````````````````````````````````````
245
Mic2 = 1000 / (millis() - Mic1);
// Вычисление количества операций(циклов) в секунду
246
Serial
.print(
" CPU-"
);
Serial
.print(Mic2);
Serial
.print(
"Lps"
);
Serial
.print(
" Status-"
);
Serial
.print(STATUS);
Serial
.print(
" Output-"
);
Serial
.println(Output);
247
//``````````````````````````````````````````
248
}
// end Loop
01
void
ChgData(){
02
if
(curMenu == 0) {
if
(position >= 0 && position <= 3) {s = position; lcd.setCursor(12, 1); lcd.print(position); lcd.print(
" "
);}
else
{Enc_Zero(0);} lcd.setCursor(0, 1); lcd.blink();}
03
if
(curMenu == 1) {
if
(position >= 0 && position <= 100) {s = position; lcd.setCursor(12, 1); lcd.print(position); lcd.print(
" "
);}
else
{Enc_Zero(0);} lcd.setCursor(0, 2); lcd.blink();}
04
if
(curMenu == 2) {
if
(position >= 0 && position <= 100) {s = position; lcd.setCursor(12, 1); lcd.print(position); lcd.print(
" "
);}
else
{Enc_Zero(0);} s = position; lcd.setCursor(0, 3); lcd.blink();}
05
if
(curMenu == 3) {lcd.setCursor(6, 1); lcd.print(
" "
); CHGFile(); lcd.setCursor(6, 1); lcd.print(FileiniNAME); lcd.setCursor(0, 1); lcd.blink();}
06
if
(curMenu == 4) {ReadINI(); lcd.setCursor(8, 3); lcd.print(
"ok"
); lcd.setCursor(0, 3); lcd.blink();}
07
if
(curMenu == 5) {
if
(position >= 1 && position <= 100) {PID_SPEED = position; lcd.setCursor(12, 1); lcd.print(position); lcd.print(
" "
);}
else
{Enc_Zero(0);} lcd.setCursor(0, 1); lcd.blink();}
08
if
(curMenu == 6) {
if
(position >= 0 && position <= 100) {consKi = position; lcd.setCursor(12, 2); lcd.print(position); lcd.print(
" "
);}
else
{Enc_Zero(0);} lcd.setCursor(0, 2); lcd.blink();}
09
if
(curMenu == 7) {
if
(position >= 0 && position <= 100) {Setpoint = position; lcd.setCursor(12, 3); lcd.print(position); lcd.print(
" "
);}
else
{Enc_Zero(0);} lcd.setCursor(0, 3); lcd.blink();}
10
if
(curMenu == 8) {
if
(position >= 0 && position <= 24) {A_H = position; lcd.setCursor(12, 1); lcd.print(position); lcd.print(
" "
);}
else
{Enc_Zero(0);} lcd.setCursor(0, 1); lcd.blink();}
11
if
(curMenu == 9) {
if
(position >= 0 && position <= 59) {A_M = position; lcd.setCursor(12, 2); lcd.print(position); lcd.print(
" "
);}
else
{Enc_Zero(0);} lcd.setCursor(0, 2); lcd.blink();}
12
if
(curMenu == 10){rtc.adjust(DateTime(2015, 8, 19, A_H, A_M, 0)); lcd.setCursor(12, 3); lcd.print(
"ok"
); lcd.setCursor(0, 3); lcd.blink();}
13
14
if
(curMenu == 11) {
if
(position >= 0 && position <= 100) {Pat[0][0] = position; lcd.setCursor(12, 1); lcd.print(position); lcd.print(
" "
);}
else
{Enc_Zero(0);} lcd.setCursor(0, 1); lcd.blink();}
15
if
(curMenu == 12) {
if
(position >= 0 && position <= 32000) {Pat[0][1] = position; lcd.setCursor(12, 2); lcd.print(position); lcd.print(
" "
);}
else
{Enc_Zero(0);} lcd.setCursor(0, 2); lcd.blink();}
16
if
(curMenu == 13) {
if
(position >= 0 && position <= 1) {Pat[0][2] = position; lcd.setCursor(12, 3); lcd.print(position); lcd.print(
" "
);}
else
{Enc_Zero(0);} lcd.setCursor(0, 3); lcd.blink();}
17
if
(curMenu == 14) {
if
(position >= 0 && position <= 100) {Pat[1][0] = position; lcd.setCursor(12, 1); lcd.print(position); lcd.print(
" "
);}
else
{Enc_Zero(0);} lcd.setCursor(0, 1); lcd.blink();}
18
if
(curMenu == 15) {
if
(position >= 0 && position <= 32000) {Pat[1][1] = position; lcd.setCursor(12, 2); lcd.print(position); lcd.print(
" "
);}
else
{Enc_Zero(0);} lcd.setCursor(0, 2); lcd.blink();}
19
if
(curMenu == 16) {
if
(position >= 0 && position <= 1) {Pat[1][2] = position; lcd.setCursor(12, 3); lcd.print(position); lcd.print(
" "
);}
else
{Enc_Zero(0);} lcd.setCursor(0, 3); lcd.blink();}
20
if
(curMenu == 17) {
if
(position >= 0 && position <= 100) {Pat[2][0] = position; lcd.setCursor(12, 1); lcd.print(position); lcd.print(
" "
);}
else
{Enc_Zero(0);} lcd.setCursor(0, 1); lcd.blink();}
21
if
(curMenu == 18) {
if
(position >= 0 && position <= 32000) {Pat[2][1] = position; lcd.setCursor(12, 2); lcd.print(position); lcd.print(
" "
);}
else
{Enc_Zero(0);} lcd.setCursor(0, 2); lcd.blink();}
22
if
(curMenu == 19) {
if
(position >= 0 && position <= 1) {Pat[2][2] = position; lcd.setCursor(12, 3); lcd.print(position); lcd.print(
" "
);}
else
{Enc_Zero(0);} lcd.setCursor(0, 3); lcd.blink();}
23
if
(curMenu == 20) {
if
(position >= 0 && position <= 100) {Pat[3][0] = position; lcd.setCursor(12, 1); lcd.print(position); lcd.print(
" "
);}
else
{Enc_Zero(0);} lcd.setCursor(0, 1); lcd.blink();}
24
if
(curMenu == 21) {
if
(position >= 0 && position <= 32000) {Pat[3][1] = position; lcd.setCursor(12, 2); lcd.print(position); lcd.print(
" "
);}
else
{Enc_Zero(0);} lcd.setCursor(0, 2); lcd.blink();}
25
if
(curMenu == 22) {
if
(position >= 0 && position <= 1) {Pat[3][2] = position; lcd.setCursor(12, 3); lcd.print(position); lcd.print(
" "
);}
else
{Enc_Zero(0);} lcd.setCursor(0, 3); lcd.blink();}
26
if
(curMenu == 23) {
if
(position >= 0 && position <= 100) {Pat[4][0] = position; lcd.setCursor(12, 1); lcd.print(position); lcd.print(
" "
);}
else
{Enc_Zero(0);} lcd.setCursor(0, 1); lcd.blink();}
27
if
(curMenu == 24) {
if
(position >= 0 && position <= 32000) {Pat[4][1] = position; lcd.setCursor(12, 2); lcd.print(position); lcd.print(
" "
);}
else
{Enc_Zero(0);} lcd.setCursor(0, 2); lcd.blink();}
28
if
(curMenu == 25) {
if
(position >= 0 && position <= 1) {Pat[4][2] = position; lcd.setCursor(12, 3); lcd.print(position); lcd.print(
" "
);}
else
{Enc_Zero(0);} lcd.setCursor(0, 3); lcd.blink();}
29
if
(curMenu == 26) {
if
(position >= 0 && position <= 100) {Pat[5][0] = position; lcd.setCursor(12, 1); lcd.print(position); lcd.print(
" "
);}
else
{Enc_Zero(0);} lcd.setCursor(0, 1); lcd.blink();}
30
if
(curMenu == 27) {
if
(position >= 0 && position <= 32000) {Pat[5][1] = position; lcd.setCursor(12, 2); lcd.print(position); lcd.print(
" "
);}
else
{Enc_Zero(0);} lcd.setCursor(0, 2); lcd.blink();}
31
if
(curMenu == 28) {
if
(position >= 0 && position <= 1) {Pat[5][2] = position; lcd.setCursor(12, 3); lcd.print(position); lcd.print(
" "
);}
else
{Enc_Zero(0);} lcd.setCursor(0, 3); lcd.blink();}
32
if
(curMenu == 29) {
if
(position >= 0 && position <= 100) {Pat[6][0] = position; lcd.setCursor(12, 1); lcd.print(position); lcd.print(
" "
);}
else
{Enc_Zero(0);} lcd.setCursor(0, 1); lcd.blink();}
33
if
(curMenu == 30) {
if
(position >= 0 && position <= 32000) {Pat[6][1] = position; lcd.setCursor(12, 2); lcd.print(position); lcd.print(
" "
);}
else
{Enc_Zero(0);} lcd.setCursor(0, 2); lcd.blink();}
34
if
(curMenu == 31) {
if
(position >= 0 && position <= 1) {Pat[6][2] = position; lcd.setCursor(12, 3); lcd.print(position); lcd.print(
" "
);}
else
{Enc_Zero(0);} lcd.setCursor(0, 3); lcd.blink();}
35
if
(curMenu == 32) {
if
(position >= 0 && position <= 100) {Pat[7][0] = position; lcd.setCursor(12, 1); lcd.print(position); lcd.print(
" "
);}
else
{Enc_Zero(0);} lcd.setCursor(0, 1); lcd.blink();}
36
if
(curMenu == 33) {
if
(position >= 0 && position <= 32000) {Pat[7][1] = position; lcd.setCursor(12, 2); lcd.print(position); lcd.print(
" "
);}
else
{Enc_Zero(0);} lcd.setCursor(0, 2); lcd.blink();}
37
if
(curMenu == 34) {
if
(position >= 0 && position <= 1) {Pat[7][2] = position; lcd.setCursor(12, 3); lcd.print(position); lcd.print(
" "
);}
else
{Enc_Zero(0);} lcd.setCursor(0, 3); lcd.blink();}
38
if
(curMenu == 35) {
if
(position >= 0 && position <= 100) {Pat[8][0] = position; lcd.setCursor(12, 1); lcd.print(position); lcd.print(
" "
);}
else
{Enc_Zero(0);} lcd.setCursor(0, 1); lcd.blink();}
39
if
(curMenu == 36) {
if
(position >= 0 && position <= 32000) {Pat[8][1] = position; lcd.setCursor(12, 2); lcd.print(position); lcd.print(
" "
);}
else
{Enc_Zero(0);} lcd.setCursor(0, 2); lcd.blink();}
40
if
(curMenu == 37) {
if
(position >= 0 && position <= 1) {Pat[8][2] = position; lcd.setCursor(12, 3); lcd.print(position); lcd.print(
" "
);}
else
{Enc_Zero(0);} lcd.setCursor(0, 3); lcd.blink();}
41
if
(curMenu == 38) {
if
(position >= 0 && position <= 100) {Pat[9][0] = position; lcd.setCursor(12, 1); lcd.print(position); lcd.print(
" "
);}
else
{Enc_Zero(0);} lcd.setCursor(0, 1); lcd.blink();}
42
if
(curMenu == 39) {
if
(position >= 0 && position <= 32000) {Pat[9][1] = position; lcd.setCursor(12, 2); lcd.print(position); lcd.print(
" "
);}
else
{Enc_Zero(0);} lcd.setCursor(0, 2); lcd.blink();}
43
if
(curMenu == 40) {
if
(position >= 0 && position <= 1) {Pat[9][2] = position; lcd.setCursor(12, 3); lcd.print(position); lcd.print(
" "
);}
else
{Enc_Zero(0);} lcd.setCursor(0, 3); lcd.blink();}
44
}
01
void
CHGFile(){
02
entry = root.openNextFile();
if
(!entry) { root.rewindDirectory(); }
03
FileiniNAMEAn = entry.name();
04
if
(FileiniNAMEAn ==
""
or FileiniNAMEAn ==
"SYSTEM~1"
) {entry = root.openNextFile();}
05
else
{FileiniNAME = entry.name();}}
06
07
void
ReadINI(){
08
if
(SD_stat){
09
char
Str2[FileiniNAME.length()+1]; FileiniNAME.toCharArray(Str2, FileiniNAME.length()+1);
10
IniFile ini(Str2);
11
12
if
(!ini.open()) {clearLine(0); lcd.print(
"Ini file does not exist"
);
while
(1);}
13
if
(!ini.validate(buffer, bufferLen)) {clearLine(0); lcd.print(
"ini file "
); lcd.print(ini.getFilename()); lcd.print(
" not valid"
);
while
(1);}
14
//--------------------------------------------------------------------
15
if
(ini.open()) {
/* clearLine(0); lcd.print("Load: "); lcd.print(ini.getFilename()); */
}
16
if
(ini.getValue(
"NAME"
,
"NAME"
, buffer, bufferLen)) {
if
(curMenu == 4) {clearLine(2); lcd.setCursor(1, 2); lcd.print(buffer);}}
//else {clearLine(0); lcd.print("Default Error file");}
17
if
(ini.getValue(
"PID"
,
"consKp"
, buffer, bufferLen)) {consKp = String(buffer).toInt();}
18
if
(ini.getValue(
"PID"
,
"consKi"
, buffer, bufferLen)) {consKi = String(buffer).toInt();}
19
if
(ini.getValue(
"PID"
,
"consKd"
, buffer, bufferLen)) {consKd = String(buffer).toInt();}
20
if
(ini.getValue(
"PID"
,
"PID_SPEED"
, buffer, bufferLen)) {PID_SPEED = String(buffer).toInt();}
21
if
(ini.getValue(
"NASOS"
,
"start"
, buffer, bufferLen)) {Nasos_Start = String(buffer).toInt();}
22
if
(ini.getValue(
"NASOS"
,
"stop"
, buffer, bufferLen)) {Nasos_Stop = String(buffer).toInt();}
23
24
for
(
int
mesMas=0; mesMas <= 9; mesMas++){
25
char
Str1[Prog[mesMas].length()+1]; Prog[mesMas].toCharArray(Str1, Prog[mesMas].length()+1);
26
if
(ini.getValue(Str1,
"P_Temp"
, buffer, bufferLen)) {Pat[mesMas][0] = String(buffer).toInt();}
27
if
(ini.getValue(Str1,
"P_Time"
, buffer, bufferLen)) {Pat[mesMas][1] = String(buffer).toInt();}
28
if
(ini.getValue(Str1,
"P_Alar"
, buffer, bufferLen)) {Pat[mesMas][2] = String(buffer).toInt();}
29
}
30
ini.close();
31
entry.close();
32
//--------------------------------------------------------------------
33
}}
01
void
LoadPAT(){
02
INI_pat_mem();
03
for
(
int
pr=50; pr <= 59; pr++){
04
prog = pr - 50;
05
mem1 = pr;
06
mem2 = pr + 10;
07
mem3 = pr + 20;
08
Pat[prog][0] = EEPROM.read(mem1); Pat[prog][1] = EEPROM.read(mem2); Pat[prog][2] = EEPROM.read(mem3);
09
}
10
T_Upr = EEPROM.read(111);
11
consKi = EEPROM.read(112);
12
PID_SPEED = EEPROM.read(113);
13
myPID.SetTunings(consKp, consKi, consKd);
14
}
15
16
void
SavePAT(){
17
INI_pat_mem();
18
for
(
int
pr=50; pr <= 59; pr++){
19
prog = pr - 50;
20
mem1 = pr;
21
mem2 = pr + 10;
22
mem3 = pr + 20;
23
EEPROM.write(mem1, Pat[prog][0]); EEPROM.write(mem2, Pat[prog][1]); EEPROM.write(mem3, Pat[prog][2]);
24
}
25
if
(EEPROM.read(111) != T_Upr) {
if
(T_Upr != 3){ EEPROM.write(111, T_Upr); } }
// Сохранение значения режима работы
26
if
(EEPROM.read(112) != consKi) { EEPROM.write(112, consKi); myPID.SetTunings(consKp, consKi, consKd); }
// Сохранение значения режима consKi PID регулятора
27
if
(EEPROM.read(113) != PID_SPEED) { EEPROM.write(113, PID_SPEED); myPID.SetTunings(consKp, consKi, consKd); }
// Сохранение значения режима SPEED PID регулятора
28
}
29
30
void
INI_pat_mem(){
31
prog = 0; mem1 = 0; mem2 = 0; mem3 = 0;
32
}
01
void
getTemp() {
02
ds.reset();
03
ds.select(addr);
04
ds.write(0x44, 1);
05
ds.reset();
06
ds.select(addr);
07
ds.write(0xBE);
08
for
(
int
i = 0; i < 9; i++) {data[i] = ds.read();}
09
int16_t raw = (data[1] << 8) | data[0];
10
if
(type_s) {
11
raw = raw << 3;
12
if
(data[7] == 0x10) {raw = (raw & 0xFFF0) + 12 - data[6];}
13
}
else
{
14
byte
cfg = (data[4] & 0x60);
15
if
(cfg == 0x00) raw = raw & ~7;
16
else
if
(cfg == 0x20) raw = raw & ~3;
17
else
if
(cfg == 0x40) raw = raw & ~1;
18
}
19
celsius = (
float
)raw / 16.0;
20
return
;
21
}
001
void
menu(
int
lvl){
002
if
(lvl == 0 || lvl == 1 || lvl == 2){ lcd.clear(); curMenu = lvl;
003
lcd.setCursor(0, 0); lcd.print(
" MENU - 0 "
);
004
lcd.setCursor(0, 1); lcd.print(
" -"
); lcd.setCursor(12, 1); lcd.print(
""
);
005
lcd.setCursor(0, 2); lcd.print(
" -"
); lcd.setCursor(12, 2); lcd.print(
""
);
006
lcd.setCursor(0, 3); lcd.print(
" -"
); lcd.setCursor(12, 3); lcd.print(
""
);
007
switch
(lvl){
case
0:lcd.setCursor(0, 1); lcd.blink();
break
;
008
case
1:lcd.setCursor(0, 2); lcd.blink();
break
;
009
case
2:lcd.setCursor(0, 3); lcd.blink();
break
;}
010
}
011
if
(lvl == 3 || lvl == 4){ lcd.clear(); curMenu = lvl;
012
lcd.setCursor(0, 0); lcd.print(
" MENU - 1 "
);
013
lcd.setCursor(0, 1); lcd.print(
" File:"
); lcd.print(FileiniNAME);
014
if
(!SD_stat) {lcd.setCursor(0, 2); lcd.print(
" SD init - failed!"
);}
015
lcd.setCursor(0, 3); lcd.print(
" Load"
);
016
switch
(lvl){
case
3:lcd.setCursor(0, 1); lcd.blink();
break
;
017
case
4:lcd.setCursor(0, 3); lcd.blink();
break
;}
018
}
019
if
(lvl == 5 || lvl == 6 || lvl == 7 ){ lcd.clear(); curMenu = lvl;
020
lcd.setCursor(0, 0); lcd.print(
" MENU - 2 "
);
021
lcd.setCursor(0, 1); lcd.print(
" PID_SPEED "
); lcd.setCursor(12, 1); lcd.print(PID_SPEED);
022
lcd.setCursor(0, 2); lcd.print(
" consKi "
); lcd.setCursor(12, 2); lcd.print(consKi);
023
lcd.setCursor(0, 3); lcd.print(
" Setpoint "
); lcd.setCursor(12, 3); lcd.print(Setpoint);
024
switch
(lvl){
case
5:lcd.setCursor(0, 1); lcd.blink();
break
;
025
case
6:lcd.setCursor(0, 2); lcd.blink();
break
;
026
case
7:lcd.setCursor(0, 3); lcd.blink();
break
;}
027
}
028
if
(lvl == 8 || lvl == 9 || lvl == 10 ){ lcd.clear(); curMenu = lvl;
029
lcd.setCursor(0, 0); lcd.print(
" MENU - 3 "
);
030
lcd.setCursor(0, 1); lcd.print(
" hour"
); lcd.setCursor(12, 1); lcd.print(A_H);
031
lcd.setCursor(0, 2); lcd.print(
" minute"
); lcd.setCursor(12, 2); lcd.print(A_M);
032
lcd.setCursor(0, 3); lcd.print(
" set clock"
);
033
switch
(lvl){
case
8: lcd.setCursor(0, 1); lcd.blink();
break
;
034
case
9: lcd.setCursor(0, 2); lcd.blink();
break
;
035
case
10:lcd.setCursor(0, 3); lcd.blink();
break
;}
036
}
037
//```````````````````````````````````````````````````````````````````````````````````````````
038
if
(lvl == 11 || lvl == 12 || lvl == 13){ lcd.clear(); curMenu = lvl;
039
lcd.setCursor(0, 0); lcd.print(
" MENU - 4.0 "
);
040
lcd.setCursor(0, 1); lcd.print(
" P_Temp "
); lcd.setCursor(12, 1); lcd.print(Pat[0][0]);
041
lcd.setCursor(0, 2); lcd.print(
" P_Time "
); lcd.setCursor(12, 2); lcd.print(Pat[0][1]);
042
lcd.setCursor(0, 3); lcd.print(
" P_Alar "
); lcd.setCursor(12, 3); lcd.print(Pat[0][2]);
043
switch
(lvl){
case
11:lcd.setCursor(0, 1); lcd.blink();
break
;
044
case
12:lcd.setCursor(0, 2); lcd.blink();
break
;
045
case
13:lcd.setCursor(0, 3); lcd.blink();
break
;}
046
}
047
if
(lvl == 14 || lvl == 15 || lvl == 16){ lcd.clear(); curMenu = lvl;
048
lcd.setCursor(0, 0); lcd.print(
" MENU - 4.1 "
);
049
lcd.setCursor(0, 1); lcd.print(
" P_Temp "
); lcd.setCursor(12, 1); lcd.print(Pat[1][0]);
050
lcd.setCursor(0, 2); lcd.print(
" P_Time "
); lcd.setCursor(12, 2); lcd.print(Pat[1][1]);
051
lcd.setCursor(0, 3); lcd.print(
" P_Alar "
); lcd.setCursor(12, 3); lcd.print(Pat[1][2]);
052
switch
(lvl){
case
14:lcd.setCursor(0, 1); lcd.blink();
break
;
053
case
15:lcd.setCursor(0, 2); lcd.blink();
break
;
054
case
16:lcd.setCursor(0, 3); lcd.blink();
break
;}
055
}
056
if
(lvl == 17 || lvl == 18 || lvl == 19){ lcd.clear(); curMenu = lvl;
057
lcd.setCursor(0, 0); lcd.print(
" MENU - 4.2 "
);
058
lcd.setCursor(0, 1); lcd.print(
" P_Temp "
); lcd.setCursor(12, 1); lcd.print(Pat[2][0]);
059
lcd.setCursor(0, 2); lcd.print(
" P_Time "
); lcd.setCursor(12, 2); lcd.print(Pat[2][1]);
060
lcd.setCursor(0, 3); lcd.print(
" P_Alar "
); lcd.setCursor(12, 3); lcd.print(Pat[2][2]);
061
switch
(lvl){
case
17:lcd.setCursor(0, 1); lcd.blink();
break
;
062
case
18:lcd.setCursor(0, 2); lcd.blink();
break
;
063
case
19:lcd.setCursor(0, 3); lcd.blink();
break
;}
064
}
065
if
(lvl == 20 || lvl == 21 || lvl == 22){ lcd.clear(); curMenu = lvl;
066
lcd.setCursor(0, 0); lcd.print(
" MENU - 4.3 "
);
067
lcd.setCursor(0, 1); lcd.print(
" P_Temp "
); lcd.setCursor(12, 1); lcd.print(Pat[3][0]);
068
lcd.setCursor(0, 2); lcd.print(
" P_Time "
); lcd.setCursor(12, 2); lcd.print(Pat[3][1]);
069
lcd.setCursor(0, 3); lcd.print(
" P_Alar "
); lcd.setCursor(12, 3); lcd.print(Pat[3][2]);
070
switch
(lvl){
case
20:lcd.setCursor(0, 1); lcd.blink();
break
;
071
case
21:lcd.setCursor(0, 2); lcd.blink();
break
;
072
case
22:lcd.setCursor(0, 3); lcd.blink();
break
;}
073
}
074
if
(lvl == 23 || lvl == 24 || lvl == 25){ lcd.clear(); curMenu = lvl;
075
lcd.setCursor(0, 0); lcd.print(
" MENU - 4.4 "
);
076
lcd.setCursor(0, 1); lcd.print(
" P_Temp "
); lcd.setCursor(12, 1); lcd.print(Pat[4][0]);
077
lcd.setCursor(0, 2); lcd.print(
" P_Time "
); lcd.setCursor(12, 2); lcd.print(Pat[4][1]);
078
lcd.setCursor(0, 3); lcd.print(
" P_Alar "
); lcd.setCursor(12, 3); lcd.print(Pat[4][2]);
079
switch
(lvl){
case
23:lcd.setCursor(0, 1); lcd.blink();
break
;
080
case
24:lcd.setCursor(0, 2); lcd.blink();
break
;
081
case
25:lcd.setCursor(0, 3); lcd.blink();
break
;}
082
}
083
if
(lvl == 26 || lvl == 27 || lvl == 28){ lcd.clear(); curMenu = lvl;
084
lcd.setCursor(0, 0); lcd.print(
" MENU - 4.5 "
);
085
lcd.setCursor(0, 1); lcd.print(
" P_Temp "
); lcd.setCursor(12, 1); lcd.print(Pat[5][0]);
086
lcd.setCursor(0, 2); lcd.print(
" P_Time "
); lcd.setCursor(12, 2); lcd.print(Pat[5][1]);
087
lcd.setCursor(0, 3); lcd.print(
" P_Alar "
); lcd.setCursor(12, 3); lcd.print(Pat[5][2]);
088
switch
(lvl){
case
26:lcd.setCursor(0, 1); lcd.blink();
break
;
089
case
27:lcd.setCursor(0, 2); lcd.blink();
break
;
090
case
28:lcd.setCursor(0, 3); lcd.blink();
break
;}
091
}
092
if
(lvl == 29 || lvl == 30 || lvl == 31){ lcd.clear(); curMenu = lvl;
093
lcd.setCursor(0, 0); lcd.print(
" MENU - 4.6 "
);
094
lcd.setCursor(0, 1); lcd.print(
" P_Temp "
); lcd.setCursor(12, 1); lcd.print(Pat[6][0]);
095
lcd.setCursor(0, 2); lcd.print(
" P_Time "
); lcd.setCursor(12, 2); lcd.print(Pat[6][1]);
096
lcd.setCursor(0, 3); lcd.print(
" P_Alar "
); lcd.setCursor(12, 3); lcd.print(Pat[6][2]);
097
switch
(lvl){
case
29:lcd.setCursor(0, 1); lcd.blink();
break
;
098
case
30:lcd.setCursor(0, 2); lcd.blink();
break
;
099
case
31:lcd.setCursor(0, 3); lcd.blink();
break
;}
100
}
101
if
(lvl == 32 || lvl == 33 || lvl == 34){ lcd.clear(); curMenu = lvl;
102
lcd.setCursor(0, 0); lcd.print(
" MENU - 4.7 "
);
103
lcd.setCursor(0, 1); lcd.print(
" P_Temp "
); lcd.setCursor(12, 1); lcd.print(Pat[7][0]);
104
lcd.setCursor(0, 2); lcd.print(
" P_Time "
); lcd.setCursor(12, 2); lcd.print(Pat[7][1]);
105
lcd.setCursor(0, 3); lcd.print(
" P_Alar "
); lcd.setCursor(12, 3); lcd.print(Pat[7][2]);
106
switch
(lvl){
case
32:lcd.setCursor(0, 1); lcd.blink();
break
;
107
case
33:lcd.setCursor(0, 2); lcd.blink();
break
;
108
case
34:lcd.setCursor(0, 3); lcd.blink();
break
;}
109
}
110
if
(lvl == 35 || lvl == 36 || lvl == 37){ lcd.clear(); curMenu = lvl;
111
lcd.setCursor(0, 0); lcd.print(
" MENU - 4.8 "
);
112
lcd.setCursor(0, 1); lcd.print(
" P_Temp "
); lcd.setCursor(12, 1); lcd.print(Pat[8][0]);
113
lcd.setCursor(0, 2); lcd.print(
" P_Time "
); lcd.setCursor(12, 2); lcd.print(Pat[8][1]);
114
lcd.setCursor(0, 3); lcd.print(
" P_Alar "
); lcd.setCursor(12, 3); lcd.print(Pat[8][2]);
115
switch
(lvl){
case
35:lcd.setCursor(0, 1); lcd.blink();
break
;
116
case
36:lcd.setCursor(0, 2); lcd.blink();
break
;
117
case
37:lcd.setCursor(0, 3); lcd.blink();
break
;}
118
}
119
if
(lvl == 38 || lvl == 39 || lvl == 40){ lcd.clear(); curMenu = lvl;
120
lcd.setCursor(0, 0); lcd.print(
" MENU - 4.9 "
);
121
lcd.setCursor(0, 1); lcd.print(
" P_Temp "
); lcd.setCursor(12, 1); lcd.print(Pat[9][0]);
122
lcd.setCursor(0, 2); lcd.print(
" P_Time "
); lcd.setCursor(12, 2); lcd.print(Pat[9][1]);
123
lcd.setCursor(0, 3); lcd.print(
" P_Alar "
); lcd.setCursor(12, 3); lcd.print(Pat[9][2]);
124
switch
(lvl){
case
38:lcd.setCursor(0, 1); lcd.blink();
break
;
125
case
39:lcd.setCursor(0, 2); lcd.blink();
break
;
126
case
40:lcd.setCursor(0, 3); lcd.blink();
break
;}
127
}
128
129
//```````````````````````````````````````````````````````````````````````````````````````````
130
if
(lvl == 99){
131
132
if
(Udate){ Udate =
false
;
133
lcd.setCursor(0, 0); lcd.print(
"T.ust "
); lcd.print(Setpoint);
if
(STATUS) {lcd.setCursor(17, 0); lcd.print(
"RUN"
);}
else
{lcd.setCursor(17, 0); lcd.print(
"OFF"
);}
134
lcd.setCursor(0, 1); lcd.print(
"T.zid "
); lcd.print(Input);
135
lcd.setCursor(0, 2); lcd.print(
"P.ten "
);
136
137
if
(Moschnost <= 100) {lcd.setCursor(6, 2);lcd.print(Moschnost); lcd.print(
"% "
);}
138
if
(Moschnost < 10) {lcd.setCursor(6, 2);lcd.print(Moschnost); lcd.print(
"% "
);}
139
140
Print_ctrl_main();
141
142
lcd.setCursor(0, 3);
if
(_HR < 10) {lcd.print(
"0"
); lcd.print(_HR);}
else
{lcd.print(_HR);} lcd.print(
":"
);
143
if
(_MI < 10) {lcd.print(
"0"
); lcd.print(_MI);}
else
{lcd.print(_MI);} lcd.print(
":"
);
144
if
(_SE < 10) {lcd.print(
"0"
); lcd.print(_SE);}
else
{lcd.print(_SE);}
145
}
146
}
147
}
148
149
void
Print_ctrl_main(){
150
if
(tr_menu ==
false
&& position == 0) {lcd.setCursor(14, 1); lcd.print(
">>STOP"
);
151
lcd.setCursor(14, 2); lcd.print(
" WORK"
);}
152
153
if
(tr_menu ==
false
&& position == 1) {lcd.setCursor(14, 1); lcd.print(
" STOP"
);
154
lcd.setCursor(14, 2); lcd.print(
">>WORK"
);}
155
}
попробовал и я велосипед
001
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
002
// класс титановый велосипед для тактовой кнопки.
003
// фильтр дребезга, отслеживание событий: нажатие, отпускание, двойное нажатие(doubleclick), нажато и удерживается в течении определённого времени, отпущено и неактивно в течении определённого времени.
004
005
class
BUTTON {
006
public
:
007
//===================================================================================================
008
static
const
byte
bounce_ = 50;
// длительность отслеживания дребезга.
009
static
const
byte
doubleclick_ = 200;
// длительность отслеживания двойного клика.
010
static
const
unsigned
long
timer_ = 10000;
// длительность отслеживания неактивности.
011
static
const
unsigned
int
retention_ = 1000;
// длительность отслеживания нажатия и удержания.
012
//===================================================================================================
013
boolean click_down;
014
boolean click_up;
015
boolean doubleclick;
016
boolean timer;
017
boolean retention;
018
//=================================
019
unsigned
long
m;
020
boolean p;
021
boolean b;
022
boolean dc;
023
byte
c;
024
boolean t;
025
boolean r;
026
//=================================
027
byte
_pb;
028
//=================================
029
BUTTON(
byte
pb) {
030
_pb = pb;
031
pinMode(_pb, INPUT);
032
digitalWrite(_pb, 1);
033
//====
034
click_down = 0;
035
click_up = 0;
036
doubleclick = 0;
037
timer = 0;
038
retention = 0;
039
//====
040
m = millis();
041
p = digitalRead(_pb);
042
b = 0;
043
dc = 0;
044
c = 0;
045
t = 0;
046
r = 0;
047
//====
048
}
049
050
void
read() {
051
//=======================================================
052
unsigned
long
nm = millis();
053
boolean np = digitalRead(_pb);
054
//=================
055
boolean nb = 0;
056
boolean ndc = 0;
057
boolean nt = 0;
058
boolean nr = 0;
059
//================
060
click_down = 0;
061
click_up = 0;
062
doubleclick = 0;
063
timer = 0;
064
retention = 0;
065
//=================
066
if
(np != p) {p = np; m = nm; }
067
//=======================================================
068
if
(nm - m > bounce_) {nb = 1;}
069
if
(nm - m > doubleclick_) {ndc = 1;}
070
if
(ndc != dc) {dc = ndc;
if
(dc == 1) {c = 0;}}
071
if
(nb != b) {b = nb;
072
if
(p == 0 && b == 0) {click_down = 1;
073
++c;
if
(c == 2) {c = 0; doubleclick = 1;}
074
}
075
if
(p == 1 && b == 1) {click_up = 1;}
076
}
077
//=======================================================
078
if
(nm - m > timer_) {nt = 1;}
079
if
(nt != t) {t = nt;
080
if
(p == 1 && t == 1) {timer = 1;}
081
}
082
//=======================================================
083
if
(nm - m > retention_) {nr = 1;}
084
if
(nr != r) {r = nr;
085
if
(p == 0 && r == 1) {retention = 1;}
086
}
087
//=======================================================
088
}
089
};
090
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
091
092
////////////////////////
093
BUTTON BUTTON_01(3);
094
////////////////////////
095
096
void
setup
() {
097
098
/////
099
pinMode(16, OUTPUT);
100
digitalWrite(16, 1);
101
pinMode(14, OUTPUT);
102
digitalWrite(14, 1);
103
pinMode(15, OUTPUT);
104
digitalWrite(15, 1);
105
pinMode(13, OUTPUT);
106
}
107
108
void
loop
()
109
{
110
if
(BUTTON_01.click_down) {digitalWrite(16, !digitalRead(16));}
111
if
(BUTTON_01.click_up) {}
112
if
(BUTTON_01.doubleclick) {digitalWrite(14, !digitalRead(14));}
113
if
(BUTTON_01.timer) {}
114
if
(BUTTON_01.retention) {digitalWrite(15, !digitalRead(15));}
115
116
BUTTON_01.read();
117
}
при двойном клике или удержании кнопки одиночное нажатие всё равно срабатывает, что иногда не приемлемо
при двойном клике или удержании кнопки одиночное нажатие всё равно срабатывает, что иногда не приемлемо
в версии Дуино ИДЕ arduino-1.6.6 класс можно подключить как библиотеку:
1
#include <class_BUTTON.h>
схема подключения кнопки некоторым ползателям класса оказалась неочевидной - прилагаю расово правильную схему
если эта схема расово правильная, то почему большинство схем в гугле не имеют сопротивления R1? На что оно влияет?
Резистор ограничивает ток через контакты кнопки при её нажимании.
Смотреть про второй закон коммутации:
https://ru.wikipedia.org/wiki/%D0%9F%D0%B5%D1%80%D0%B5%D1%85%D0%BE%D0%B4%D0%BD%D1%8B%D0%B5_%D0%BF%D1%80%D0%BE%D1%86%D0%B5%D1%81%D1%81%D1%8B_%D0%B2_%D1%8D%D0%BB%D0%B5%D0%BA%D1%82%D1%80%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B8%D1%85_%D1%86%D0%B5%D0%BF%D1%8F%D1%85
Хотя при 0.1 без резистора будет и не смертельно для кнопки...... какое-то время......
Поставьте для "пробы" 2200.0 - могут и контакты "свариться"
если эта схема расово правильная, то почему большинство схем в гугле не имеют сопротивления R1? На что оно влияет?
*большинство схем в гугле имеют сиськи.
R1 , если:
1. если ты по запарке что-то не то зальёшь в дуино и пин у тебя окажется оутпут.
2. см. #128
отлично. Беру на вооружение.
и еще один дурацкий вопрос - а конденсатор зачем? от скачков напряжения?
он забирает на себя дребезг контактов. Кое-что, конечно, прорывается, но для МК все же легче.
алгоритм борьбы с дребезгом, используемый в класс титановый велосипед для тактовой кнопки.
в версии Дуино ИДЕ arduino-1.6.6 класс можно подключить как библиотеку:
1
#include <class_BUTTON.h>
*работает только в версии arduino-1.6.7
что бы работало в версиях младше вплоть до Arduino 1.0, нужно в код #1 добавить первой строкой
1
#include <Arduino.h>
**проверяем.
Попробовал класс, понравилось. Но я так и не догнал как сделать повторяющиеся нажатия?
Но я так и не догнал как сделать повторяющиеся нажатия?
после нажатия кнопки, повторяешь действие.
а можно сделать, чтобы при даблклике не выполнялось действие одного клика (т.е. поставить небольшую задержку одиночного нажатия, и если обнаружено двойное нажатие, то не выполнять действие по одиночному нажатию)?
а можно сделать, чтобы при даблклике не выполнялось действие одного клика (т.е. поставить небольшую задержку одиночного нажатия, и если обнаружено двойное нажатие, то не выполнять действие по одиночному нажатию)?
а, можно у тебя узнать алгоритм предсказания действий пользователя кнопки и попросить тебя прочитать топик полностью или начиная отсюда #100 ?
Только вот одно не понятно, почему на хорошую вещь сначала пытаются нагадить.
жёстким БДСМпричинно-следственными связями.3. всё оказалось совсем не так, как на самом деле.
желающим познать дзен - странный диалог Клапауций&Logik начало отсюда #62
*подписчикам, срочно отписаться - титановый велосипед подготавливается к переплавке в титановый костыль на три кнопки. :D
делаю зарядное для LI-Io и Ni-Mh ...
в контексте обсуждения класс титановый велосипед для тактовой кнопки. - эта информация не имеет значения и впредь прошу не засорять тему схемами и другими фактами автобиографии, не относящимися в обсуждению работы и практическому применению класс титановый велосипед для тактовой кнопки.
1. Подскажите, плз, где глянуть примеры с разными действиями на разное количество нажатий кнопки?
заведи переменную, считающую количество нажатий кнопки - будешь что-то делать не просто по условию нажатия, а по условию нажатия и значения этой переменной.
т.е.:
01
#include <class_BUTTON.h>
02
03
BUTTON BUTTON_01(3);
// объявляем объект класса BUTTON кнопку с именем BUTTON_01, подключенную к пину 3.
04
05
byte
tick_click_down_01 = 0;
// счётчик нажатий кнопки BUTTON_01
06
07
void
setup
() {}
08
09
void
loop
() {
10
11
BUTTON_01.read();
// обновляем состояние переменных кнопки BUTTON_01.
12
13
// работаем с переменными кнопки BUTTON_01.
14
if
(BUTTON_01.click_down) {++tick_click_down_01;
if
(tick_click_down_01 == 5) {tick_click_down_01 = 4;}}
// подсчёт нажатий кнопки до 4.
15
if
(BUTTON_01.timer) {tick_click_down_01 = 0;}
// сброс счётчика нажатий в 0 после 5 секунд неактивности кнопки.
16
17
if
(BUTTON_01.click_down && tick_click_down_01 == 1) {}
// что-то делаем по событию первого нажатия.
18
if
(BUTTON_01.click_down && tick_click_down_01 == 2) {}
// что-то делаем по событию второго нажатия.
19
if
(BUTTON_01.click_down && tick_click_down_01 == 3) {}
// что-то делаем по событию третьго нажатия.
20
if
(BUTTON_01.click_down && tick_click_down_01 == 4) {}
// что-то делаем по событию червёртого нажатия.
21
22
}
2. Как организовать запрет опроса кнопки после того, как процесс будет запущен, т.е. на РВ3( Ардуино 2) будет лог 1 и Тини 13 не должна реагировать на нажатие кнопки.
#4
if (!условие) {BUTTON_01.read();}
// обновляем состояние переменных кнопки BUTTON_01.
При паузе между нажатиями более 5 сек, фиксируется последнее состояние портов, которое можно изменить следующим нажатием кнопки (если на порту РВ3 лог 0).
здесь не понятно - последнее состояние фиксируется в момент изменения состояния и сохраняется навсегда до следующего события изменения состояния и никак не зависит от времени.
если ты желаешь сбросить счётчик нажатий, то выше в примере реализовано. и настраивается
static
const
unsigned
long
timer_ = 5000;
// длительность отслеживания неактивности.
ооооо! Клапауций 232, гораздо понятнее стало.
спасибо!
а про тему я понял что ошибся, да уже ничё не исправить.
Клапацуй 232, попробовал Ваш класс (после того как в своём обнаружил баг (при создании более одного экземпляра класса защита от дребезга не производится, в данный момент ищу причину).
Использовал для проверки следующий код
01
#include <BUTTON.h>
02
BUTTON BUTTON_01(2);
03
void
setup
() {
04
pinMode(13,OUTPUT);
05
}
06
void
loop
() {
07
BUTTON_01.read();
// обновляем состояние
08
if
(BUTTON_01.click_down) {
09
digitalWrite(13,!digitalRead(13));
10
}
11
}
К удевлению задержку между нажатием кнопки и реакцией на неё в течении длительности отслеживания дребезга я не обнаружил. В чем может быть проблемма? Код класса взят из поста #1.
К удевлению задержку между нажатием кнопки и реакцией на неё в течении длительности отслеживания дребезга я не обнаружил. В чем может быть проблемма? Код класса взят из поста #1
для обнаружения реакции на дребезг нужно симулировать ситуацию дребезга - нажатия кнопки чаще, чем
static
const
byte
bounce_
:для проверки вручную и визуально установи
static
const
byte
bounce_ = 1000;
// длительность отслеживания дребезга.
нажатия реже, чем один раз в секунду у тебя будут отрабатываться - чаще, чем один раз в секунду будут игнорироваться.
или сгенери аппаратным образом нажатие кнопки чаще, чем
static
const
byte
bounce_ = 50
при дефолтных настройках класса, если владеешь осциллографом.*код класса работает по следующему алгоритму - если время между нажатиями кнопки меньше
static
const
byte
bounce_
, то событие считается дребезгом и игнорируются, если больше, то нажатием и отрабатывается немедленно.** начиная отсюда #173 пытаюсь объяснить, почему так, а не иначе.
Провел эксперимент. Если на вход пина кнопки подавать прямоугольные импульсы (имитация дребезга) на выходе класса должны видеть 0.
Начал с 50Гц и снижал частоту до 10Гц, и Ваш и мой класс отработали одинаково, вплоть до 11Гц на выходе у них ничего небыло, а вот на 10Гц и Ваш и мой начал переодически устанавливать выход т.к. длина импульса при частоте 10Гц около 50мс.
Так что оба решения состоятельны.
Так что оба решения состоятельны.
как же состоятельны, если
далее, я тебе объяснил, что бабушку хоронят потому, что она умерла, а не потому, что выкопана могила.
Тогда лично я не очень понял, зачем Вы текст тут разместили, если юзать будете сами? Чтобы не забыть? Или все таки для того, чтобы им могли пользоваться другие? Если второй вариант, то тогда надо позаботится об удобстве будущих пользователей и добавить в описание класа одну строчку private: в нужном месте, а не становится в позицию оскорбленного справедливой критикой.
Тогда лично я не очень понял, зачем Вы текст тут разместили, если юзать будете сами? Чтобы не забыть? Или все таки для того, чтобы им могли пользоваться другие? Если второй вариант, то тогда надо позаботится об удобстве будущих пользователей и добавить в описание класа одну строчку private: в нужном месте, а не становится в позицию оскорбленного справедливой критикой.
и, кто мне это переведёт на русский язык?
кому я снова недодал личного внимания или недостаточно убедительно послал в пень?
Боюсь Вас огорчить, но послать меня достаточно убедительно в пень Вам удасться лет через 15-20 занятий встроенным программированием.
Есть такая очаровательная фраза "В Уставе караульной службы каждая строчка написана кровью людей, которые пытались делать по своему". Вы, похоже, решили пройти путь по хорошо освещенным граблям самостоятельно, в добрый путь.
Мое же мнение состоит в том, что программировать можно или хорошо, или никак. Поскольку Ваша программа до уровня хорошо не дотягиваем явно, и советы по ее улучшению Вы категорически отвергаете, то готов оставить Вас с программой уровня никак.
Если Вы действительно считаете, что потрясающие в своей эффективности алгоритмы и необычные, не приходящие до сего момента никому в голову решения, примененные в Вашем чудесном коде, вызывают злопыхания завистников, который в бессильной злобе пытаются своими грязными лапами обеспечить Ваше прекрасное детище, то боюсь, Вы живете в вымышленном мире.
Ни в коей мере не претендуя на личное внимание столь продвинутого программиста, тем не менее мог бы порекомендовать посмотреть исходные коды обработки событий мыши в древней системе Turbo Pascal, где то, что Вы считаете невозможным без заглядывания в будущее, реализуется вполне понятными и довольно таки тривиальными конструкциями.
Боюсь Вас огорчить...
я тебя огорчать не боюсь - т.к. у тебя несколько вариантов поведения:
- ты пишешь хороший код для работы с кнопкой и публикуешь его на этом форуме.
- ты исправляешь ошибки в код класс титановый велосипед для тактовой кнопки.
- ты идёшь в пень, как программист-пустомеля.
*кретинам, обзывающим меня программистом, повторяю: я - радиомонтажник.
Уважаемый GarryC, не сочтите за труд прочитать.
Тогда лично я не очень понял, зачем Вы текст тут разместили, если юзать будете сами? ...то тогда надо позаботится об удобстве будущих пользователей и добавить в описание класа одну строчку private: в нужном месте.
Если Вы пришли к нам в "песочницу" из "конструкторского бюро", так помогите, если не затруднит. Если обратите внимание на попытки написать альтернативу этому коду, то увидите, что никто не довел дела до конца и/или его теория оказалась не состоятельной.
Боюсь Вас огорчить, но послать меня достаточно убедительно в пень Вам удасться лет через 15-20 занятий встроенным программированием.
Мда, сколько таких тут мимо проходило, ни один не доказал своей состоятельности ДЕЛОМ.
..., и советы по ее улучшению Вы категорически отвергаете, ..
Достаточно часто проглядываю топики, чего-то не увидел дельных советов.
... Если Вы действительно считаете, что потрясающие в своей эффективности алгоритмы и необычные, не приходящие до сего момента никому в голову решения, примененные в Вашем чудесном коде, вызывают злопыхания завистников, который в бессильной злобе пытаются своими грязными лапами обеспечить Ваше прекрасное детище...
Ежу понятно, что нет предела совершенству. Вот только где эти "супер коды-алгоритмы" в законченном виде? Где-то выше, только один человек написал "я использую вот такой код" но он мне не подходит, а кде все остальные???
...тем не менее мог бы порекомендовать посмотреть исходные коды обработки событий мыши в древней системе Turbo Pascal, где то, что Вы считаете невозможным без заглядывания в будущее, реализуется вполне понятными и довольно таки тривиальными конструкциями.
Мог (я) бы сказать СПАСИБО, ЕСЛИ БЫ такой продвинутый человек за "спасибо" (как это сделал Клапауций 232) подарил БЫ сообществу сие чудо.
Ну и, чтоб не из пустоты писать. Вот мой четвертый или пятый код в жизни (вполне рабочий говнокод), чтоб Вы понимали уровень многих участников, для которых код написан.
001
/*
002
этот код я написал для замка в деревне, чтоб за ключем не бегать. Если работаешь
003
не далеко и кто-то пришел, он должен знать код. Устройсто втягивает защелку на замке.
004
КОД необходимо набирать последовательно, дождавшись когда КРАСНЫЙ светик потухнет,
005
иначе нажитие другой кнопки будет включено в КОД (комбинацию кнопок).
006
Каждая кнопка имеет "вес" 1, 2, 4 и 8 соответственно, пока горит КРАСНЫЙ светодиод
007
вводится КОД соответствующий зашитому в программе и установленному джамперами.
008
Невозможно понять, ошибся ты или нет, пока не набраны 4 комбинации.
009
Для повторного нажатия неоходимо дождаться пока потухнет подсветка...
010
Ну не хватило у меня кнопок на полную клавиатуру :)))))))))))))))
011
Если на А3 (тумблер в доме) лог 0 (тумблер включен)
012
при любой комбинации А0, А1 и А2 (выбор кода) работает "простой код"
013
силовой "полевик" выдран с компьютерной матери 18N06L (что было, то и ставим)
014
*/
015
#include <class_noDELAY.h>
016
#include <class_BUTTON.h>
017
018
// коды доступа :)))------------
019
020
byte
COD_A[8][5] = {
// [строка] [значение]
021
{0, 0, 0, 0, 0},
// нули. чтоб код не править по инициализации
022
{0, 1, 8, 2, 4},
// код при нажатом тумблере (простой код)
023
{0, 2, 2, 5, 5},
// первый код (по перемычкам кода)
024
{0, 2, 6, 8, 10},
// второй код и т.д.
025
{0, 10, 2, 8, 2},
026
{0, 1, 6, 8, 8},
027
028
};
029
030
//----------------------------
031
032
033
noDELAY nD_01;
// таймер 1
034
noDELAY nD_02;
// таймер 2
035
noDELAY nD_011;
// таймер 11
036
noDELAY nD_022;
// таймер 22
037
noDELAY nD_03;
// таймер 3 - сброс незавершенного кода
038
039
BUTTON BT_01(2);
// кнопок 1 разряда
040
BUTTON BT_02(3);
// кнопок 2 разряда
041
BUTTON BT_03(4);
// кнопок 4 разряда
042
BUTTON BT_04(5);
// кнопок 8 разряда
043
BUTTON BT_05(8);
// кнопка в доме
044
045
// A0, A1, A2 - джамперы выбора предустановленного кода
046
// A3 - упрощенный код доступа
047
048
// an array of pin numbers to which BUTTON or jumper are attached
049
int
BUTTON_Pins[] = { 2, 3, 4, 5, 8, A0, A1, A2, A3 };
050
int
i=0, j=0;
051
byte
q1=0, q2=0;;
// перебор кода, очередь нажатия
052
byte
Bt = 0;
// код кнопок
053
byte
Bt1=0, Bt2=0, Bt3=0, Bt4=0, Bt5=0;
// результат (факт) нажатия кнопок по весу
054
byte
AC0=0, AC1=0, AC2=0, AC3=0, AC4=0, AC5=0, AC6=0;
// выбор кода
055
boolean Btc = 0;
// признак обработки кода кнопок, 1 если еще не обработан
056
boolean OL=0;
// открыть замок
057
058
059
060
061
//----------------------------------------------------
062
void
setup
()
063
{
064
for
(
int
k = 0; k < 9; k++)
065
{ pinMode(BUTTON_Pins[i], INPUT); }
066
067
pinMode(6,OUTPUT);
// белый светик на подсветку
068
pinMode(7,OUTPUT);
// красный светик на индикацию
069
pinMode(9,OUTPUT);
// ШИМ на мотор замка
070
071
Serial
.begin(9600);
// for deBug
072
}
073
//------------------------------------------------------
074
//----------------------------------------------------------
075
// процедура открытия замка
076
void
OPE_LOCK ()
077
{
078
if
(OL == 1)
079
080
{
081
082
nD_011.start();
083
nD_011.read(1000);
084
nD_022.start();
// мигалка красным светиком пока открываем
085
nD_022.read(100);
//мигает красный светик открытого замка
086
if
(nD_011.tick) {j++;}
087
088
if
(j==1)
089
{
090
digitalWrite(9, 1);
// рывок на открытие, время nD_011.read(1000);
091
}
092
if
(j>=2) {analogWrite(9, 30);}
// удержание задвижки замка ШИМом
093
094
if
(nD_022.tick) {digitalWrite(7, !digitalRead(7));}
//мигает красный светик открытого замка
095
096
if
(j>=5)
// открыли, обнуляем все переменные
097
{
098
digitalWrite(9, 0);
099
digitalWrite(7, 0);
100
q1=0;
101
q2=0;
102
j=0;
103
Bt = 0;
104
Btc = 0;
105
nD_011.stop();
106
nD_022.stop();
107
OL=0;
108
}
109
}
110
}
111
112
//------------------------------------------------------
113
void
loop
()
114
{
115
//--------------------------------- получаем код нажатия кнопок
116
BT_01.read();
// обновляем состояние
117
BT_02.read();
// обновляем состояние
118
BT_03.read();
// обновляем состояние
119
BT_04.read();
// обновляем состояние
120
BT_05.read();
// обновляем состояние кнопка в доме
121
122
if
(BT_01.click_down) { Bt1=1;}
123
if
(BT_02.click_down) { Bt2=2;}
124
if
(BT_03.click_down) { Bt3=4;}
125
if
(BT_04.click_down) { Bt4=8;}
126
if
(BT_05.click_down) { Bt5=16;}
127
128
//------------------- если нажата кнопка - подсветка и отсчет на сброс переменных кода
129
if
(Bt1==1 || Bt2==2 || Bt3==4 || Bt4==8 || Bt5==16)
130
{
131
// Serial.println ("nD_03.start() ");
132
nD_03.start();
133
digitalWrite(6, 1);
134
}
135
nD_03.read(10000);
// время до сброса или нажатия
136
if
(nD_03.tick)
137
{
138
digitalWrite(6, 0);
139
nD_03.stop();
140
Bt=0;
141
Btc=0;
142
q1=0;
143
q2=0;
144
}
145
// конец подсветки и ограничения времени
146
147
148
// начало проверки набранной комбинации кнопок
149
if
(Btc == 0)
// если предыдущий код обработан, а новый еще нет
150
{
151
if
(Bt1==1 || Bt2==2 || Bt3==4 || Bt4==8 || Bt5==16)
//если кнопка нажата
152
{
153
digitalWrite(7, 1);
154
nD_01.start();
155
nD_01.read(200);
156
if
(nD_01.tick) {i++;}
157
if
(i>=3)
// интервал определения одновременного нажатия кнопок
158
{
159
Bt=Bt1 + Bt2 + Bt3 + Bt4 + Bt5 ;
// получен код набора кнопок
160
Bt1=0, Bt2=0, Bt3=0, Bt4=0, Bt5=0;
// получен код набора кнопок
161
Btc = 1;
// признак, код еще не обработан
162
// Serial.println (Bt);
163
i=0;
164
nD_01.stop();
165
digitalWrite(7, 0);
166
// Serial.println ("Bt1=0, Bt2=0, Bt3=0, Bt4=0, Bt5=0; ");
167
}}}
168
//======== подучен код кнопок и признак обработки
169
//----------------------------------------
170
// обработчик кода нажатия кнопок
171
if
(Btc == 1)
172
{
173
q1++;
// перебор очереди нажатия
174
// Serial.print ("q1= ");
175
// Serial.println (q1);
176
if
(Bt >= 16)
// если нажата кнопка в доме (независимо от набора на улице)
177
{
178
// Serial.println ("if (Bt>=16) !!!!!! ");
179
OL=1;
180
// OPEN_LOCK (1); // в конце лупа
181
Btc=0;
182
q1=0;
183
q2=0;
184
}
185
186
if
(Bt<=15)
//набираем кнопки на улице
187
{
188
// Serial.println ("[AC4] = ");
189
// Serial.println (AC4);
190
// Serial.println ("[q1] = ");
191
// Serial.println (q1 );
192
// Serial.println ("COD_A[AC4][q1] ");
193
// Serial.println (COD_A[AC4][q1]);
194
ACCESS_CODE ();
// какой код выбран т.е. где стоят джамперы (работа с массивом)
195
196
if
(Bt == COD_A[AC4][q1])
// если код совпал
197
{
198
q2++;
199
// Serial.print ("q2= ");
200
// Serial.println (q2);
201
}
202
else
{q2=0;}
203
if
( q2 >= 4)
//если все 4 цифры верно набрали
204
{
205
OL=1;
// открыть и обнулить
206
Btc=0;
207
q1=0;
208
q2=0;
209
}
210
if
( q1 >= 12)
// если кто-то брутит, можно еще больше сделать
211
{
212
// OL=1;
213
Btc=0;
214
q1=0;
215
q2=0;
216
}
217
218
Btc=0;
// ХБЗ зачем оно тут :)
219
}
220
221
222
}
// конец обработчика кода нажатия кнопок
223
224
225
//---------------------------------------
226
227
228
// Serial.print ("OL ");
229
// Serial.println (OL);
230
OPE_LOCK ();
// открыть замок, если OL = 1
231
}
// loop
232
233
//--------------------------------------------------------------
234
235
void
ACCESS_CODE ()
// работа с кодом доступа
236
{
237
// Serial.println ("void ACCESS_CODE () ");
238
AC0 = !digitalRead(A0);
239
AC1 = !digitalRead(A1);
240
AC2 = !digitalRead(A2);
241
AC3 = !digitalRead(A3);
242
243
// Serial.print ("AC0... AC2= ");
244
// Serial.print (AC0);
245
// Serial.print (AC1);
246
// Serial.println (AC2);
247
248
if
(AC3 == 1)
// если код "простой" т.е. вкл. тумблер в доме
249
{
// byte COD_A[8][4] = // [строка] [значение]
250
AC4 = 1;
251
}
252
253
if
(AC3 == 0)
// собираем код из джамперов и спускаем ниже кода тумблера (+1)
254
{
255
AC4 = 1 + AC0 + AC1 + AC1 + AC2 + AC2 + AC2 + AC2;
256
}
257
// Serial.print ("AC3= ");
258
// Serial.println (AC3);
259
// Serial.print ("AC4= ");
260
// Serial.println (AC4);
261
262
}
UPD
так я и не понял этой фразы....
...мог бы порекомендовать посмотреть исходные коды обработки событий мыши в древней системе Turbo Pascal, где то, что Вы считаете невозможным без заглядывания в будущее, реализуется вполне понятными и довольно таки тривиальными конструкциями.
объяснитесь, пожалуйста, так я собираюсь нажать, кликнуть 2 раза или подержать (ну скажем 5 секунд). И как там это реализовано?
пост 100
при двойном клике или удержании кнопки одиночное нажатие всё равно срабатывает, что иногда не приемлемо
опиши мне словами алгоритм, который будет предсказывать будущее, например:
я нажал кнопку и... [здесь девайс смотрит в будущее и он точно знает, что]....
так я и не понял этой фразы....
Гриша, если бы хоть у одного, пострадавшего от класс титановый велосипед для тактовой кнопки., было желание вести конструктивный диалог с целью улучшения, исправления, приведения к некоему стардарту кода класса, то это звучало бы следующим образом - в языке Z++ кнопки обрабатываются таким кодом по такому алгоритму.
т.е. забей на этот серый шум профессиональных безработных программистов - времени у них дофига, а код бесплатно написать им профессиональность не позволяет.
анонс.
на днях выложу переписанную заново версию кода класса - через более чем год многие вещи вижу иначе.
анонс.
на днях выложу переписанную заново версию кода класса - через более чем год многие вещи вижу иначе.
Ждем. Юзаю более или менее данный класс. Немного переписал под себя, убрал лишние примочки.
Ждем. Юзаю более или менее данный класс. Немного переписал под себя, убрал лишние примочки.
и чего мешает поделиться результатом (ну соответственно, с описание переделок.)? Я пример использования кинул в посте 243 (тока там без переделок, я их не делал)
Прежде всего, хотелось бы подчеркнуть, что воспитанный человек не может обращаться на ты к незнакомому человеку в русском языке, поскольку это невежливо. В других языках, где понятия ты И Вы сливаются, это вполне допустимо, но даже в них при общении с малознакомыми людьми принято применять безличные Mrs и Ms вместо You. Но это так заметка по поводу, конечно, можно быть хорошим разработчикам и при этом пренебрегать правилами поведения в обществе, но мне подобное сочетания представляется маловероятным в силу ряда причин, излагать которые в данном комменте считаю излишним.
Насчет первого варианта поведение - предложение интересное, своего рода вызов, конечно, не моего уровня, но вполне себе вызов. У меня такой код есть, написан он лет 15 назад на ассемблере для I8051, в ближайшие выходные постараюсь первратить его в программу для среды Ардуино и выложить.
Второй вариант, простите, не рассматриваю - здесь как раз тот случай, когда проше выкинуть, чем переделать, постараюсь свой интерфейс сделать максимально близким к Вашему.
Третий вариант, с Вашего позволения, пока не рассматриваем до ближайших выходных.
Ну и последнее, по моему мнению, назвать человека программистом - это не обозвать его, поскольку программирование, как профессия, требует весьма высокого уровня интеллектуального развития и не может быть оскорбительныи. А что касается того, чем Вы зарабатываете в реальной жизни - по Вашему, это существенно? Я должен сделать скидку и относится к Вашей программе, исходя из иных критериев, нежели к своей или к программе коллеги? Это почему, собственно?
Если я Вам принесу криво собранную плату со "слепыми " пайками и в ответ на Ваши замечания гордо заявлю, что я программист, это как-то улучшит качество этой платы?
Сразу отвечу на вопрос из следующего Вашего комментария о заглядывании в будущее - Вы увидите это в коле, который я обещал написать за выходные, но сразу изложу основную идею - событие нажатия задерживается до того момента, когда достоверно станет известно, что это не двойной клик и не длительное нажатие - довольно таки несложно. Постараюсь обратить внимание на данный момент в комментариях.
1. В том то и дело, что я прочитал комменты в начале и там уважаемому автору предлагалось другими участниками ввести некоторые элементарные исправления в код, чтобы соблюсти общепринятые соглашения о написании классов. Но, вместо того, чтобы последовать этим несомненно разумным советам, автор начинает вопрошать, зачем это делать (я не буду цитировать содержимое любой книги по ООП, там все наглядно показано с примерами), заявлять, что он и так прекрасно использует свой класс, что и вызвало к жизни мой комментарий относительно намерений, сподвигнувших его на выставление своего кода на всеобщее обозрение. Да, Вы правы, никто из критикующих код не предложил внятной альтернативы; как я и обещал, постараюсь исправить данное упущение.
2. Отосительно проходящих мимо, ничего не могу сказать, надеюсь, что после выходных буду зачислен в другую категорию, пока могу порекомендовать посмотреть мои посты на Хабре, я там пишу исключительно о встроенном программировании и разработке, возможно, они позволят Вам создать первое впечатление о моем уровне.
3. По поводу советов именно они и были в комментах к этому посту - посмотрите внимательнее.
4. Да, это был сарказм, возможно, излишний, наверное, погорячился.
5. Если я выполню свое обещание за эти выходные, то вполне приму Вашу благодарность, ни на что другое я не рассчитываю, мои посты удовлетворяют не нижние уровни пирамиды потребностей.
6. Ваш код (я никогда в своей жизни в письменном виде слово, которым Вы его охаректеризовали, не использовал и использовать не собираюсь), несомненно, тоже посмотрю и постараюсь дать к нему комментарий (по первому впечатлению, там есть, что комментировать в плане улучшения), но сразу хочу заявить, что ..
7. Если Вы занялись программированием, то Вы должны ответственно относиться к данному процессу и постоянно повышать свой уровень, какой бы он в данный момент не был.
Прежде всего, хотелось бы подчеркнуть, что воспитанный человек не может обращаться на ты к незнакомому человеку в русском языке, поскольку это невежливо.
почему ты решил, что ты мне не знаком?
IMHO (лирика) {
Уважаемый GarryC, что касается:
Прежде всего, хотелось бы подчеркнуть, что воспитанный человек не может обращаться на ты к незнакомому человеку в русском языке, поскольку это невежливо.
Давно заметил, что чем дальше на восток, тем больше люди говорят друг - другу Вы. На западе (России) подавляющее большинство ТЫчет :) такая вот диалектика. Это становится для меня вопросом восприятия и, Я лично, отношусь к этому так:
И посылал в иные земли [посланников, как правило, перед объявлением войны] со словами: „Иду на Вы!“
Если копнуть историю, несложно нарыть вагон информации, где среди прочего "Как называть родителей на «ты» или на «вы» ".
Что же касается грубости "Клапауций ХХХ (и его ипостаси)" комментировать не буду, тем более воспитывать, он не один на форуме.
} IMHO (лирика)
Сразу отвечу на вопрос из следующего Вашего комментария о заглядывании в будущее ... событие нажатия задерживается до того момента, когда достоверно станет известно, что это не двойной клик и не длительное нажатие - довольно таки несложно.
пост 110
* возможно!, этот алгоритм поможет следующим пользователям... :
в программе определяется "что" использовать (нажатие, двойное нажатие, удержание) и устанавливается интервал (время) определения - до его окончания никаких действий. Соответственно если использовать только простое нажатие - мгновенное исполнение, во всех других комбинациях - действие исполняется по истечении времени интервала определения - да хоть тройное нажатие!
ты не оригинален в желании программно затупить работу кнопки на время, превышающее bounce_ - длительность отслеживания дребезга.
пост113
UPD пост 109. "залипание кнопки" - если перекрыть все моменты, то необходимо позаботиться в алгоритме о том, что есть "залипание кнопки" и как этот момент обрабатывать!!!
никак не обрабатывать, т.к. при залипании кнопки(постоянном нажатии) обработается один раз событие удержание кнопки и в дальнейшем кнопка перестанет работать совсем от слова СОВСЕМ.
исходя из условий поставленной задачи, можно вообще не обрабатывать "удержание" если кнопку не отпустили!!! НО, это все должен определить РАЗРАБОТЧИК (програмист) согласно алгоритму по ТЗ.
ИМХО. Написать код достаточно просто, правильно составить алгоритм почти - искусство. Это как в школе – правильно составленное условие задачи больше половины решения. А в данном случае, разработчик должен описать все возможные события именно так, как ему это нужно.
Темка понравилась именно тем, что есть код (доступный), который можно допилить под свои нужды – все универсальное слишком громоздко.
PS. тем не менее ждем Вашего расширенного варианта кода
Давно заметил, что чем дальше на восток, тем...
...толще партизаны.(с)
Гриша, неужели моё обращение к GarryC на "ты", является главным из перечисленных им, моих преступлений против человечности в общем и ползателями форума в частности, что бы акцентировать внимание именно на этом, вместо того, что бы осудить меня по совокупности моих ужасных деяний?
весь в сомнениях - ведь, весь этот флуд просто обязан как-то коррелировать к кодом для обработки работы тактовой кнопки... но, как и каким местом?
что GarryC хотел мне и нам донести, потратив время для написания таких длинных и полезных для меня и всех нас постов?
весь в сомнениях - ведь, весь этот флуд просто обязан как-то коррелировать к кодом для обработки работы тактовой кнопки... но, как и каким местом?
да никакак - это ИМХО
уже раз 5 писал:
пост 15
3) Пожалуйста, дайте право ТС дополнять (возможно, и изменять) первый пост всегда!!!
пост 25
Назрела проблема с офф.топом. Много сообщений убивающих время и не несущих полезной информации....
01
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
02
// класс титановый велосипед для тактовой кнопки. (версия 1.0)
03
// фильтр дребезга, отслеживание событий: нажатие, отпускание, двойное нажатие(doubleclick), нажато и удерживается в течении определённого времени, отпущено и неактивно в течении определённого времени.
04
05
#include <Arduino.h>
06
07
class
BUTTON {
08
public
:
09
//============================================================================================
10
// константы настроек класса.
11
static
const
byte
bounce_ = 50;
// длительность отслеживания дребезга.
12
static
const
byte
doubleclick_ = 250;
// длительность отслеживания двойного нажатия.
13
static
const
unsigned
long
timer_ = 5000;
// длительность отслеживания неактивности.
14
static
const
unsigned
int
retention_ = 2000;
// длительность отслеживания нажатия и удержания.
15
//============================================================================================
16
unsigned
long
start;
// старт отсчёта времени.
17
boolean p;
// состояние пина кнопки.
18
boolean s;
// программное состояние кнопки.
19
boolean b;
// состояние таймера фильтра дребезга.
20
byte
c;
// переменная счётчика двойного нажатия.
21
boolean t;
// состояние таймера неактивности.
22
boolean r;
// состояние таймера нажатия и удержания.
23
//============================================================
24
boolean click_down;
// событие нажатия.
25
boolean click_up;
// событие отпускания.
26
boolean doubleclick;
// событие двойного нажатия.
27
boolean timer;
// событие неактивности.
28
boolean retention;
// событие нажатия и удержания.
29
//============================================================
30
byte
_pb;
31
//============================================================
32
BUTTON(
byte
pb) {
33
_pb = pb;
34
pinMode(_pb, INPUT);
35
digitalWrite(_pb, 1);
36
//===================
37
start = millis();
38
p = digitalRead(_pb);
39
// p = !digitalRead(_pb); // отключить тихий старт.
40
s = p;
41
b = 0;
42
c = 0;
43
t = 0;
44
r = 0;
45
//==============
46
click_down = 0;
47
click_up = 0;
48
doubleclick = 0;
49
timer = 0;
50
retention = 0;
51
//==============
52
}
53
54
void
read() {
55
//==============================================================================
56
boolean np = digitalRead(_pb);
// текущее состояние пина кнопки.
57
unsigned
long
stop = millis();
// стоп отсчёта времени.
58
//==============================================================================
59
click_down = 0;
60
click_up = 0;
61
doubleclick = 0;
62
timer = 0;
63
retention = 0;
64
//==============================================================================
65
if
(np != p) {p = np; click(); start = stop; b = 1; t = 1; r = 1;}
// состояние цифрового пина изменилось.
66
//==============================================================================
67
if
(b != 0 ) {
if
(stop - start > bounce_ ) {b = 0; click(); }}
// фильтр дребезга.
68
if
(c != 0 ) {
if
(stop - start > doubleclick_) {c = 0; }}
// обнуление счётчика двойного клика.
69
if
(t != 0 && s == 1) {
if
(stop - start > timer_ ) {t = 0; timer = 1;}}
// неактивность.
70
if
(r != 0 && s == 0) {
if
(stop - start > retention_ ) {r = 0; retention = 1;}}
// нажатие и удержание.
71
//==============================================================================
72
}
73
74
void
click() {
// нажатие, отпускание, двойное нажатие.
75
if
(b == 0 && s != p) {s = p;
76
if
(s == 0) {click_down = 1; ++c;
if
(c == 2) {c = 0; doubleclick = 1;}}
77
if
(s == 1) {click_up = 1; }
78
}
79
}
80
81
};
82
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Уважаемый, строка 35, случаем не ошибка?????????? или это pullup?
digitalWrite(_pb, 1);