// © Klop 2018
// Реле времени для часов/минут
// погрешность ~ 2 секунды в час
#include <TM1637Display.h>
#include <TimerOne.h>
#include <Encod_er.h>
#define CLK 4 // пин 4 подключаем к CLK дисплея
#define DIO 3 // пин 3 подключаем к DIO дисплея
#define pin_DT 9 // пин 9 подключаем к DT энкодера
#define pin_CLK 2 // пин 2 подключаем к CLK энкодера
#define pin_SW 12 // пин 12 подключаем к SW энкодера
#define pin_Relay 7 // пин 7 подключаем к реле
#define pin_Speaker 11// пин 11 подключаем к + пищалки ( - пищалки на землю)
#define NotPush 0
#define ShortPush 1
#define LongPush 2
#define DurationOfLongPush 2000 // длительность длинного нажатия
#define interval 250
Encod_er encoder(pin_CLK, pin_DT, pin_SW);
TM1637Display display(CLK, DIO);
byte cyfra[]={63,6,91,79,102,109,125,7,127,111};
byte data[] = {0,0,0,0};
byte mask=15, Hour=0, Minut=0, flsvet, zn, Signal=0;
unsigned long TimeOfPush, tempu, TimerSec=0, mycounter=0, temp1, temp2;
bool dvoet, myfl=false, ModeArbeiten=false, UkazHM=true, flEND=false;
int8_t VAL;
struct myMerz
{word freq;
unsigned long temp;
bool flsvet;
};
myMerz trig[]={{500,0,false}, // интервал мерцания двоеточия при работе
{200,0,false}, // интервал мерцания минут и часов при задании времени
{1000,0,false}};// интервал прерывания сигнала при окончании работы
void setup()
{ Timer1.initialize(interval); // инициализация таймера 1, период interval мкс
Timer1.attachInterrupt(timerInterrupt, interval); // задаем обработчик прерываний
display.setBrightness(1);
pinMode (pin_DT,INPUT);
pinMode (pin_CLK,INPUT);
pinMode (pin_SW,INPUT);
pinMode (pin_Relay,OUTPUT);
digitalWrite(pin_Relay, HIGH);
digitalWrite(pin_SW, HIGH); // подтягиваем к 5V
TimeOfPush=0;
delay(100);
encoder.timeLeft= 0;
encoder.timeRight= 0;
}
//------------------------------------------------------------
// обработчик прерывания
void timerInterrupt() {
encoder.scanState();
if (ModeArbeiten)
{tempu++;
if (tempu==4000) {tempu=0; mycounter++;}
}
}
//------------------------------------------------------------
void View()
{ // byte h=Hour; byte m=Minut; //для любителей видеть неполные мин (править ниже Hour и Minut на h и m)
// if (ModeArbeiten && mycounter>0) {m++; if (m==60) {m=0; h++;}
data[0]=cyfra[Hour/10];
data[1]=cyfra[Hour%10];
data[2]=cyfra[Minut/10];
data[3]=cyfra[Minut%10];
for (byte i=0;i<4;i++) if (!bitRead(mask,i)) data[3-i]=0;
if (dvoet) data[1]= data[1]|0x80;
display.setSegments(data);
}
//------------------------------------------------------------
bool procmerz(byte num)
{ unsigned long tempmillis=millis(); // триггер переключается с периодом из trig
if (tempmillis-trig[num].temp>trig[num].freq)
{ trig[num].temp=tempmillis;
trig[num].flsvet=!trig[num].flsvet;
}
return(trig[num].flsvet);
}
//------------------------------------------------------------
byte mypush() // возвращает длинное-2, короткое-1 или осутствие нажатия-0
{ unsigned long tpr=millis();
byte res=NotPush;
if (!digitalRead(pin_SW))
{ if (TimeOfPush==0) TimeOfPush=tpr; else
if (tpr-TimeOfPush>DurationOfLongPush && !myfl)
{ TimeOfPush=0;
myfl=true;
return(LongPush);
}
} else
{ if (TimeOfPush>0 && !myfl) res=ShortPush;
TimeOfPush=0;
myfl=false;
}
return(res);
}
//------------------------------------------------------------
int8_t norm(int8_t aa, byte dob, byte mf) // делаем аа в пределах mf, начиная от dob
{
if (aa>mf) return(dob);
if (aa<dob) return(mf);
return(aa);
}
//------------------------------------------------------------
void Sec2HourMin()
{
Hour=(TimerSec-mycounter)/3600;
Minut=(TimerSec-mycounter)%3600/60;
}
//------------------------------------------------------------
void loop()
{
dvoet=true;
zn=procmerz(1);
mask=15;
unsigned long tempx=millis();
if (procmerz(2) && flEND && tempx-temp2<10000L) analogWrite(pin_Speaker,150); // издаем звук
else analogWrite(pin_Speaker,0);
byte rrr=mypush();
if (rrr!=NotPush) // произошло нажатие
{ flEND=false;
if (rrr==ShortPush) UkazHM=!UkazHM; // короткое
if (rrr==LongPush) {ModeArbeiten=!ModeArbeiten; // длинное
if (ModeArbeiten) { mycounter=0; // запуск таймера
TimerSec=Hour*3600L+Minut*60L;
tempu=0;
if (TimerSec==0) ModeArbeiten=false;
else digitalWrite(pin_Relay,LOW);
} else
{ digitalWrite(pin_Relay,HIGH);//отключаем реле принудительно
Hour=0;
Minut=0;
}
}
}
if (ModeArbeiten) // режим работы
{ dvoet=procmerz(0);
if (TimerSec==mycounter) { ModeArbeiten=false; // отключаем реле по времени
digitalWrite(pin_Relay,HIGH);
temp2=tempx;
flEND=true;
}
Sec2HourMin();
} else // режим установки времени
{if (UkazHM) { if (zn) mask=B0011;
Hour=norm(Hour+VAL,0,99);
}
else {if (zn) mask=B1100;
Minut=norm(Minut+VAL,0,59);
}
if (tempx-temp1<500) mask=15; // не моргать при вращении энкодера
}
VAL=0;
if (encoder.timeRight!=0) // обрабатываем повороты энкодера
{ VAL=1;
encoder.timeRight=0;
goto m1;
} else
if (encoder.timeLeft!=0)
{ VAL=-1;
encoder.timeLeft=0;
m1: temp1=tempx;
flEND=false; // при любом повороте отключаем сигнал
if (!digitalRead(pin_SW)) VAL=0; // если кнопка нажата, поворот игнорить
}
View();
}
+23 |
1888
52
|
+47 |
2506
89
|
+165 |
3946
48
|
+24 |
1965
26
|
Многими учеными неоднократно доказывалось умение комаров прокалывать пространственно-временной континуум на дистанции не менее двух метров. Вот он был в районе лампочки… Бац! И он уже заходит в атаку на твою мягкую шкурку.
Вот во время мгновенного перемещения по проколу, комар не подвержен влиянию никаким средствам уничтожения извне.
А отстрел комара непосредственно вблизи объекта его атаки, т.е. твоей шкурки, чреват повреждениями шкурки. Что не есть good.
чем пока пользуются мутоцеклисты (Att, я — предупредил!;)
с желающих избавиться от комаров — брать денег;
с желающих пострелять по чужим комарам — брать денег;)
Единственное, что я бы сделал иначе — перенёс бы ручку энкодера на одну поверхность с дисплеем. В нынешнем исполнении нажимать на кнопку кажется весьма неудобным.
Внёс себе в закладки, на будущее..-свой выращенный табак сушить буду..(-разумеется, подогнав параметры под оный).Ну, и прочие «деликатесы» из сада-огорода.
ps ещё кто-то помнит фильм?
Резюме:-попытка повсюду выглядеть остроумным превращает некоторых особей в заурядных «абырвалг»ов… ;-)
https://aliexpress.com/item/item/CN101A-AC-12V-Digital-LCD-Power-Timer-Programmable-Time-Switch-Relay-8A-TO-16A-CN101-TIMER/32652166624.html
или отсюда
ru.aliexpress.com/af/%25D1%2580%25D0%25B5%25D0%25BB%25D0%25B5-%25D0%25B2%25D1%2580%25D0%25B5%25D0%25BC%25D0%25B5%25D0%25BD%25D0%25B8.html
но просто таймер на 99 часов, без дней недели и т.д. Механический на 24 часа не подходит- нужно более 24 часов и возможность выставить время с точностью до минуты.
Куплен в оффлайне за 300-500 рублей, точно не помню :)
Выставляется (в том числе) когда включить или когда выключить до 99 часов 59 минут с точностью до минуты :)
Считать какое время и день будет через 40 часов 10 минут и вводить день и время ненадо?
свет
https://aliexpress.com/item/item/Hot-Selling-XH-M131-DC-5V-Light-Control-Switch-Photoresistor-Relay-Module-Detection-Sensor/32813461661.html
температура
https://aliexpress.com/item/item/W1209-LED-Digital-Thermostat-Temperature-Control-Thermometer-Thermo-Controller-Switch-Module-DC-12V-Waterproof-NTC-Sensor/32802291474.html
времени
ru.aliexpress.com/af/%25D1%2580%25D0%25B5%25D0%25BB%25D0%25B5-%25D0%25B2%25D1%2580%25D0%25B5%25D0%25BC%25D0%25B5%25D0%25BD%25D0%25B8.html
и т.д.
Если нужно просто решить задачу — можно и готовое купить.
Оба подхода имеют право на существование.
Термоклей поплывет, когда Вы выселите устройство в гараж.
А почему термоклей в гараже должен поплыть?
Отказался от термоклея в пользу УФ полимеров с Али + УФ фонарик
Берите любой прозрачный.
Для полимеризации использую Convoy S2+ black UV 365nm led flashlight. Немного дорого для этих целей, но за 10 секунд всё схватывается. Можно использовать и подручные источники УФ.
ЗЫ: Есть два типа гелей — top cover и build. Топ при полимеризации дает твердую поверхность. Билд получается мягче.
Ну, в принципе, прочности должно хватить. Не ясно только, как он отнесется к вибрациям и продолжительному использованию. Ногти-то вроде больше месяца «не ходят».
У меня 4 яблони (а вообще их 6, но 2 ранние). Когда пипец сколько яблок — это как минимум 5-6 мешков с каждой, в мешке 4 ведра. Это значит я только с одной яблони яблоки сушить буду месяц :-) при этом переодически переставляя поддоны, как вы правильно заметили.
Не, этот ветерок не вариант ниразу. :-)
— Дорогая, что то мясо жестковато…
— Не знаю, я варила, как в в поваренной книге написано: возьмите один килограмм мяса и варите его один час. Я взяла полкило и варила полчаса…
Один черт — только на своем опыте станет понятно, сколько сушить.
а так сейчас в продаже полно всяких сушилок хушь с таймером, хуж без, другое дело — агрегаты с более менее приличным объёмом и производительностью сушки стоят нормальных денег.
небыло кстати мыслей сделать пастилу из яблок, коли их так много.
за стиль изложения — плюс!
10-20 л воды
2-4 кг сахара
100 г сухих дрожжей
и,
надоможно чаще пищать;)откуда я все это знаю? я сам переписывал свою билиотеку под энкодер аж три раза — elchupanibrei.livejournal.com/29025.html
но получилось очень хорошо. имхо одна из лучших на github под arduino. поддерживает все популярные камни: Arduino AVR, Arduino ESP8266, Arduino STM32
ошибок нет, есть пропуски.
возможно дело в конструкции енкодеров, конечно.
Может кондеры на экодер повесить, как тут советовали?
сигнал при вращении по часовой:
сигнал при вращении против часовой:
вроде кардинальной разницы не видно.
пропуски, особенно против часовой, начинались на заметно меньших скоростях, тут пытался крутануть максимально быстро.
возможно емкость тут и поможет. по идее это не дребезг после переключения, а нестабильный контакт при высокой скорости скольжения (возможно еще и отклонения вала добавляют).
моя на пост выше, но без конденсаторов не обошлось — быстрые камни Cortex аля ESPЗ8266 и STM32 успавали ловить кучу дребезга.
Для каждой кнопки есть ее состояние и счетчик опросов. Состояния могут быть: «свободна», «проверка нажатия», «нажата», «долго нажата», «отпущена», «отпущена после долгого нажатия», «обработана». Изначальное состояние кнопок — «свободна».
Опрашиваете состояние в прерывании таймера, например, 100 раз в секунду. Если нажатие появляется когда у кнопки состояние «свободна» или «отпущена» или «отпущена после долгого нажатия», то переводите состояние кнопки в «проверка нажатия» начинаете выжидать, например, 5 опросов. Если за эти 5 опросов нажатие пропало, переводите состояние кнопки обратно в «свободна» и сбрасываете счетчик. Если все 5 опросов нажатие сохраняется — переводите состояние в «нажата» и начинаете выжидать, например, 100 опросов. Если в течении этих 100 опросов нажатие сохраняется и состояние не изменилось на «обработана» (см. ниже), то переводите состояние в «долго нажата». Если нажатие пропало когда состояние было «нажата», переводите в состояние «отпущена», если пропало когда состояние было «долго нажата», переводите состояние в «отпущена после долгого нажатия», если пропало когда состояние было «обработана» переводите состояние в «свободна».
В основном цикле программы просто проверяете состояние кнопок и если оно равно «нажата», «отпущена», «долго нажата» или «отпущена после долгого нажатия», то выполняете соответствующие действие (или ничего не выполняете) и ставите кнопке состояние «обработана».
Алгоритм проверен годами и не в одном девайсе с самыми разными видами кнопок. Аналогично можно и с энкодером, только еще добавить счетчик нажатий. Хотя в STM32 есть аппаратный интерфейс энкодера со своими фильтрами и он превосходно работает… с дополнительными небольшими конденсаторами :)
ведь достаточно всего-то немного подумать…
или погуглить.
Ну и форумы, наверное, по ардуине? Типа "- У меня этот скетч работает неправильно, помогите! — Попробуй вон тот скетч или вот этот." :)
Что-то я на более профессиональных форумах (тот же электроникс, к примеру) не видел многолетних поисков алгоритма обработки энкодера :)
Сам я написал обработку энкодера на STM32 часа за два, проблем не было :)
у меня на работе иногда программисты таскают что-то кусками готовыми, а потом при неожиданных результатах или просто вопросах по коду начинается «я оттуда взял, не разбирался, работает же»… приходится отучать по возможности.
Без проблем.
Наверное, потому что тогда не только ардуины, тогда и интернета не было…
И приходилось самому думать и самому писать.
На али продается таймер с энкодером. Так, даже на китайщине нет никаких переключателей минуты-часы.
Все уже придумано :)
Вообще прогрессивная регулировка очень удобная вещь, просто надо правильно ее настроить и тогда все отлично регулируется.
Кстати интересная вещь, у той же плиты где стоят эти часы (а не только таймер), нет 00.00, вместо этого они показывают 24.00 :)
С одного энкодера, без переключения, вполне можно настраивать от, положим, 30 секунд до пары недель, если сие нужно. Поупражняйте мозг, это интересно.
Если «никак», то в PM.
Но, имхо, в данном случае имеем «дорога ложка к обеду».
Автору нравится так, с отдельными часам и минутами. Так зачем ему переделывать работающее у НЕГО так, чтобы это нравилось ВАМ?
Если ЕМУ надоест ЕГО реализация, он её переделает. Если, конечно, захочет. :)
Я попытался 'достучаться' до автора, но такие, как вы,
Samman, могут только мешать.
Ага, «Есть только 2 мнения, неправильное и моё.» :D
Не у всех любителей сушить яблоки, яблони рядом духовками, в которых 24-часовые таймеры.
Как-то так…
Как только вес загруженного продукта уменьшился до определенного значения — сушилка выключается…
Продукт никогда не будет работать как осушитель потому что его влажность никогда не упадет ниже влажности продуваемого через сушилку воздуха :)
Именно это я и написал в предыдущем комментарии.
А если руки растут из нужного места, так и вообще приделать всю ардуину непосредственно к сушилке.
На AVR давно делал, использовал исходник Chan'a
предыдущее время выдержки, и как его использовать — никак), брать предопределённое в скетче, или брать за основу
а вот сохранять прошлое значение в nvram я бы не стал — не потому, что жалко флеш (не жалко!), а из-за того, что «питание просто так не пропадает»
У меня задача включать таймер на вентиляторе в туалете, после выключения в нём света.
Вот таймер на мой взгляд удобный, управление (установка времени) не кнопками и не энкодером.
https://aliexpress.ru/item/item/32837313833.html
Там стоит переменный резистор на 500 ком.
Также дисплей показывает установленное время переменным резистором. При работе таймера бегут секунды и минуты, меняется соответственно обратному отсчёту.
Резистор с платы можно выпаять и установить вместо него удобный большой потенциометр на корпус в котором будет таймер, также и дисплей перенести на корпус.
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.