Впереди неумолимо маячит зима – утром темно, вечером темно.
Просыпаться по будильнику в полной темноте равносильно нырянию под лед. Стресс с утра – гарантированно унылый день.
Решение-то есть, светобудильник называется, но цена этой штуки от 5000 руб. Колется, однако. К тому же, алгоритм работы жестко запрограммирован, а ведь совершенно очевидно, что, по результатам просыпания, захочется что-то подкорректировать или расширить функционал.
А что, если на основе подручных средств соорудить что-то в этом духе? Хорошая задачка для DIY!
Для решения были использованы следующие материалы:
— прототип отладочной платы набора для изучения программирования Ардуино (входит в будущий набор NR05), рассчитанная на установку Arduino Nano;
— часы реального времени MP1095;
— светодиоды разные;
— пьезопищалка со встроенным генератором;
— белая полупрозрачная штука, когда-то напечатанная при отладке 3D-принтера (можно приспособить еще что-нибудь полупрозрачное в качестве рассеивателя, а у кого есть 3D принтер, то напечатать что нибудь свое);
— желание все это соединить и запрограммировать подходящий алгоритм работы.
Белую штуку захотелось взгромоздить на какой-нибудь постамент, чтобы смонтировать туда светодиод и подключить его кабелем к плате. Недолго думая, рисуем в SketchUp и печатаем на 3D принтере оранжевую подставочку. При сильном желании можно напечатать корпус для платы-прототипа, но прототип и так немыслимо красив!
К тому же, его можно использовать и под разработку других проектов, а будильничек, по результатам эксплуатации опытного образца, можно оформить в более компактную конструкцию на основе той же платы Arduino Nano.
Сначала воткнули один светодиод. Он был приклеен к основанию инновационным клеем, отверждающимся под воздействием ульрафиолета. Называется Bondic. Полезная в хозяйстве штучка, надо сказать! Держит крепко.
Тем же клеем приклеили разъем.
Посмотрели, как светиться. Не понравилось. В темноте, конечно, видно, но для активации мозга через оптические рецепторы не хватает. По сусекам набрали несколько ярких белых светодиодов. Объединенные параллельно в такую вот веточку, они дают вполне пробуждающий в максимуме яркости свет.
Потребляют в максимуме порядка 100 мА, напрямую к порту Ардуино не подсоединишь, но на отладочной плате имеется усилитель тока на транзисторе, обеспечивающий 200 мА.
Также на плате есть пять кнопок для всяких экспериментов, их задействуем для управления режимами и настройки будильника.
В целом, отладочная плата интересна наличием маркированных разъемов-штырей для подключения различных датчиков и исполнительных устройств, обеспечивая хороший функционал и дружелюбный интерфейс – можно, особо не задумываясь (разъемы подписаны) подключить датчики температуры, давления, сервомашинки, реле, устройства с интерфейсом I2C и т.п. Для подключение нужны только провода с разъемами-розетками.
Яркость будем регулировать ШИМом с девятого пина Ардуино, разведенного на плате к усилителю. Пищалку подсоединим к разъему SOUND, на DAT плюсом, на GND минусом. Часы реального времени – к разъему I2C_5V, поскольку 5В им и надо для питания. На плате уже установлен двухстрочный LCD индикатор, весьма контрастный, с приятными белыми знаками на синем фоне.
Собственно, все железо на месте, теперь дело за софтом.
Алгоритм был задуман так:
— при совпадении текущего времени с временем, на которое установлен будильник, яркость светильника должна медленно повышаться по полной;
— при этом несколько раз по нарастающей должны подаваться звуковые сигналы, не дающие wakeUp-объекту начихать на лампочку и уснуть при свете;
— надо дать возможность выключить в конце-концов надоедливый звук, а также включить полный свет вручную, или выключить его, уже будучи в полном сознании.
— должна быть возможность ставить время на часах и будильнике.
Получившийся скетч приведен в конце материала и снабжен подробными комментариями. Его несложно модифицировать под ваши желания и предпочтения.
Всем приятного пробуждения!
#include <LiquidCrystalRus.h>
#include <LiquidCrystalExt.h>
#include <LineDriver.h>
// Подключаем библиотеку последовательной шины I2C
#include <Wire.h>
// Подключаем библиотеку часов реального времени RTC
#include «RTClib.h»
// Подключаем библиотеку для использование встроенного таймера 2
// для управления временными интервалами сигнала
#include <MsTimer2.h>
//-----------------------------------------------------------------------
#define NUM_KEYS 5
// Для каждой кнопки заносим калибровочные значения (выведены экспериментально)
int adcKeyVal[NUM_KEYS] = {30, 150, 360, 535, 760};
//-----------------------------------------------------------------------
int led13 = 13; // встроенный в Arduino Nano светодиод
int alarmPin = 3; // пин для управления сигналом будильника
int led = 9; // пин вывода ШИМ на светодиодную лампу
int brightness = 0; // начальная яркость
int riseAmount = 1; // шаг увеличения яркости 0-255
int timeAmount = 500; // шаг времени, мс
int beepCount = 0; // служебные переменные
int numberOfBeeps = 0;
unsigned long time_old;
unsigned long time_curr;
int alarm = 0; // флаг срабатывания будильника
int Step; // служебные переменные
unsigned long tSetOld;
unsigned long tTickOld;
// Создаем программный объект дисплей lcd, объясняя программе куда подключены линии RS,EN,DB4,DB5,DB6,DB7
LiquidCrystalRus lcd(A1, A2, A3, 2, 4, 7);
// Создаем программный объект RTC
RTC_DS1307 RTC;
int Year; // переменные для хранения данных с RTC
int Month;
int Day;
int Hour;
int Minute;
int Second;
int alarmHour = 0;
int alarmMinute = 0;
int setAlarm = 0; // будильник вкл./выкл.
int SetMode = 0; // режим установки часов/будильника вкл./выкл.
int AlarmOn; // сигнал вкл./выкл.
void setup() {
pinMode(led13, OUTPUT);
pinMode(3, OUTPUT);
lcd.begin(16, 2);
Wire.begin(); // инициализируем 1Wire (необходио для RTC)
RTC.begin(); // инициализируем RTC
RTC.writenvram(2, 0); // секунды сигнала устанавливаем в 00 (ячейка 2 постоянной памяти RTC)
tTickOld = millis(); // запомнаем число мс с момента запуска микроконтроллера для отсчета интервалов времени
// если нажата кнопка 5, установить текущее время из компьюьера на момент компиляции программы
// и сбросить будильник в 0
if (get_key() == 5) {
RTC.adjust(DateTime(__DATE__, __TIME__));
for (int i = 0; i < 5; i++) RTC.writenvram(i, 0);
}
}
void loop() {
AlarmOn = RTC.readnvram(3); // читаем 3-ю ячейку памяти RAM RTC: будильник включен (1) или выключен (0)
if (get_key() == 2) { // если нажата кнопка 2
SetMode++; // вход в режим установки часов
delay(500);
tSetOld = millis();
}
while (SetMode) { // установка показаний часов и будильника
if (get_key() == 2) {
SetMode++;
delay(200);
tSetOld = millis();
}
if (SetMode > 4) { // выход из режима установки
SetMode = 0;
lcd.noBlink();
lcd.noCursor();
}
switch (SetMode) { // установка мигающего курсора
case 1:
lcd.setCursor(12, 1); lcd.blink();
break;
case 2:
lcd.setCursor(9, 1); lcd.blink();
break;
case 3:
lcd.setCursor(12, 0); lcd.blink();
break;
case 4:
lcd.setCursor(9, 0); lcd.blink();
break;
}
if (get_key() == 1 or get_key() == 3) { // если нажата кнопка 1 или 3
tSetOld = millis(); // обнуляем счетчик нахождения в режиме установки
if (get_key() == 3) Step = 1; // если кнопка 3 — увеличиваем
if (get_key() == 1) Step = -1; // если кнопка 1 — уменьшаем
switch (SetMode) {
case 1:
SetMinuteAlarm(Step); // минуты будильника
break;
case 2:
SetHrAlarm(Step); // часы будильника
break;
case 3:
SetMinute(Step); // минуты текущего времени
break;
case 4:
SetHr(Step); // часы текущего времени
break;
}
}
if ((millis() — tTickOld) > 1000) {
displayTime(); // раз в секунду отображаем время на индикаторе в режиме установки
tTickOld = millis();
}
if ((millis() — tSetOld) > 10000) {
SetMode = 0; // автовыход из режима установки через 10 сек.
lcd.noBlink();
}
} // end SetMode
if (get_key() == 4) { // включаем/выключаем будильник
int alarm_ram = RTC.readnvram(3);
RTC.writenvram(3, !alarm_ram);
delay(50);
AlarmOn = alarm_ram;
delay(500);
}
if (get_key() == 5) { // выключение света вручную
alarm = 0;
digitalWrite(led13, LOW);
lightDown();
}
if (get_key() == 5 && brightness >= 0) { // включение света вручную
lightUp();
}
if (get_key() == 1 && !SetMode) { // выключение звука сработавшего будильника
//alarm = 0;
MsTimer2::stop();
digitalWrite(alarmPin, LOW);
}
if ((millis() — tTickOld) > 1000) {
displayTime(); // раз в секунду отображаем время на индикаторе
tTickOld = millis();
}
if (alarm == 1) // если будильник сработал
{
digitalWrite(led13, HIGH);
time_curr = millis();
if ((time_curr — time_old) > timeAmount) {
if (brightness < 255) {
brightness = brightness + riseAmount;
time_old = time_curr;
if (brightness > 255) brightness = 255;
analogWrite(led, brightness); // медленно повышаем яркость с помощью ШИМ
switch (brightness) { // пищим пьезодинамиком по мере повышения яркости
case 60:
numberOfBeeps = 4;
alarmRun();
break;
case 120:
numberOfBeeps = 4;
alarmRun();
break;
case 180:
numberOfBeeps = 8;
alarmRun();
break;
case 220:
numberOfBeeps = 14;
alarmRun();
break;
}
if (brightness >= 255) {
numberOfBeeps = 32000; // пищим непрерывно (32000 раз)
alarmRun();
}
}
else digitalWrite(led13, LOW);
}
}
} // end loop
//----------------------------------------------
int get_key() // функция считывания номера нажатой кнопки
{
int input = analogRead(A6);
int k;
for (k = 0; k < NUM_KEYS; k++)
if (input < adcKeyVal[k])
return k + 1;
return 0;
}
void SetMinuteAlarm(int Step) { // установка минут будильника
alarmMinute = RTC.readnvram(1);
alarmMinute += Step;
if (alarmMinute > 59) alarmMinute = 0;
if (alarmMinute < 0) alarmMinute = 59;
RTC.writenvram(1, alarmMinute);
delay(300);
}
void SetHrAlarm(int Step) { // установка часов будильника
alarmHour = RTC.readnvram(0);
alarmHour += Step;
if (alarmHour > 23) alarmHour = 0;
if (alarmHour < 0) alarmHour = 23;
RTC.writenvram(0, alarmHour);
delay(300);
}
void SetMinute(int Step) { // установка минут времени
DateTime now = RTC.now();
Year = now.year();
Month = now.month();
Day = now.day();
Hour = now.hour();
Minute = now.minute();
Second = now.second();
Minute += Step;
if (Minute > 59) Minute = 0;
if (Minute < 0) Minute = 59;
RTC.adjust(DateTime(Year, Month, Day, Hour, Minute, Second));
delay(300);
}
void SetHr(int Step) { // установка часов часов
DateTime now = RTC.now();
Year = now.year();
Month = now.month();
Day = now.day();
Hour = now.hour();
Minute = now.minute();
Second = now.second();
Hour += Step;
if (Hour > 23) Hour = 0;
if (Hour < 0) Hour = 23;
RTC.adjust(DateTime(Year, Month, Day, Hour, Minute, Second));
delay(300);
}
void displayTime() { // вывод на индикатор
DateTime now = RTC.now();
Year = now.year() — 2000;
Month = now.month();
Day = now.day();
Hour = now.hour();
Minute = now.minute();
Second = now.second();
lcd.setCursor(0, 0);
lcd.print(«Время: „);
if (Hour < 10) lcd.print(' ');
lcd.print(Hour);
lcd.print(':');
if (Minute < 10) lcd.print('0');
lcd.print(Minute);
lcd.print(':');
if (Second < 10) lcd.print('0');
lcd.print(Second);
int h = RTC.readnvram(0);
int m = RTC.readnvram(1);
int s = RTC.readnvram(2);
if (AlarmOn) {
lcd.setCursor(0, 1);
lcd.print(“Сигнал: „);
if (h < 10) lcd.print(' ');
lcd.print(h);
lcd.print(':');
if (m < 10) lcd.print('0');
lcd.print(m);
lcd.print(':');
if (s < 10) lcd.print('0');
lcd.print(s);
}
else {
lcd.setCursor(0, 1);
lcd.print(“Сигнал: --:--:--»);
}
if (Hour == h && Minute == m && Second == s && AlarmOn) { // срабатывание будильника!
alarm = 1;
numberOfBeeps = 2;
alarmRun();
}
}
void lightDown() { // плавное выключение светодиода
while (brightness > 0) {
time_curr = millis();
if ((time_curr — time_old) > 10) {
if (brightness > 0) {
brightness = brightness — 1;
time_old = time_curr;
if (brightness < 1) brightness = 0;
analogWrite(led, brightness);
}
}
}
}
void lightUp() { // плавное выключение светодиода
while (brightness < 255) {
time_curr = millis();
if ((time_curr — time_old) > 10) {
if (brightness < 255) {
brightness++;
time_old = time_curr;
if (brightness > 255) brightness = 255;
analogWrite(led, brightness);
}
}
}
}
void alarmRun() { // включение сигнала 1 раз (один бип)
digitalWrite(alarmPin, HIGH);
beepCount = 0;
MsTimer2::set(500, beep); // 500ms period
MsTimer2::start();
}
void beep() { // выключение сигнала через 500 мс по прерыванию от таймера 2
if (beepCount < numberOfBeeps) {
static boolean output = HIGH;
digitalWrite(alarmPin, output);
output = !output;
beepCount++;
}
else {
MsTimer2::stop();
digitalWrite(alarmPin, LOW);
}
}
п.с. Внимание! С с 23 сентября по 23 октября 2015 г.мы проводим фотоконкурс
«3 D печать для решения бытовых вопросов»!
Победитель получит в подарок 3D принтер-конструктор MC5 с акриловым корпусом.
Желающие могут просто зайти и проголосовать за понравившиеся работы.
Условия фотоконкурса.
Комментарии (46)
IronHead
06.10.2015 17:25Скрытая реклама клея понравилась
Сначала воткнули один светодиод. Он был приклеен к основанию инновационным клеем, отверждающимся под воздействием ульрафиолета. Называется Bondic. Полезная в хозяйстве штучка, надо сказать! Держит крепко.
Потом с матами отдираем этот чудо клей, потому что
Посмотрели, как светиться. Не понравилось. В темноте, конечно, видно, но для активации мозга через оптические рецепторы не хватает. По сусекам набрали несколько ярких белых светодиодов.
masterkit
07.10.2015 08:52Ни разу не реклама. Вы ссылку на продавца клея видите? И я не вижу. Просто попробовали сами, понравилось. Может кому пригодится, штука удобная, правда недешевая. И да, приклеивать надо было после теста. Держит реально крепко, светодиод пришлось выдирать пассатижами за корпус.
artyums
06.10.2015 18:27+4Интересно, а на меня одного абсолютно никак не влияет свет во сне? Просыпаюсь либо поскольку выспался, либо из-за звуков (будильник, проснувшиеся рядом люди и т.д.).
Нет, если, конечно, прожектором в глаза посветить во сне — я, конечно, проснусь. Но от стандартных источников света (вроде Солнца за окном или домашнего света) — никак)SADKO
06.10.2015 18:38+1Ну, солнца за окном в дефолт сити маловато даже летом, осень-зима вообще труба, а бытового освещения ИМХО должно быть маловато…
wormball
07.10.2015 07:13+2Ну по идее свет влияет не столько на факт пробуждения, сколько на «качество» этого пробуждения. В идеале надо так — чтобы всю ночь было темно, а за полчаса-час до пробуждения свет постепенно бы разгорался до максимума. А ежели спать при свете или вставать, когда ещё темно — то и чувствовать вы себя будете далеко не лучшим образом.
Я вот уже давно хочу такое сделать. Точнее, хотел люстру из светодиодов с плавным запуском. Правда, чувствую, уже дождался — рубль в два раза упал, а цены на светодиоды и вовсе раз в пять выросли.artyums
08.10.2015 18:45Дело в том, что я не хожу какой связи между светом, пробуждением и самочувствием)
На мое самочувствие после сна (прилив сил, бодрость и т.д.) сильно влияет оптимальная для меня продолжительность сна — 7-8 часов. Меньший и больший сон выражается в отсутствии тех самых чувств выше.
nitso
06.10.2015 18:56+3Ацетоновой бани вашему светильнику не хватает.
masterkit
07.10.2015 08:55Специально не печатали, лежала на полке тестовая моделька, оставшаяся после настройки принтера. Нашли применение вот. Ацетон не поможет, из pla пластика.
artyums
08.10.2015 19:39Интересно, а каким методом избавляются от «ступенек» между слоями в этом случае? Только механическим или подобная химия тоже существует?
masterkit
09.10.2015 08:22Или с настройками печати экспериментировать (тоньше слой, медленнее печать и т.п.), или механическая обработка или дихлорэтан. Народ пробовал, говорит, пла пластик поддается дихлорэтану. У нас на форуме писали.
sashabeep
06.10.2015 22:30Начал собирать похожий проект на WS2812, но часы реального времени, оказалось, сильно спешат, на несколько минут за час.
wormball
07.10.2015 07:33Кварц надо поменять, скорее всего.
sashabeep
07.10.2015 10:06Во-первых, непонятно, как его проверить, во-вторых, где его взять :)
Быстрее просто выкинуть этот модуль и купить другой на заменуwormball
07.10.2015 10:37Да вы, батенька, буржуй! Кварц можно выпаять из старой мыши или из прочего электронного мусора. Ну или купить в том же магазине, где модуль покупали.
sashabeep
07.10.2015 10:39Покупал на алиэкспрессе, у нас нет радиомагазов :)
Да он стоит там рублей 50, а мой модуль часов был вообще в составе набора с разной рассыпухой для ардуиноwormball
07.10.2015 11:23А я вот не умею покупать в интернет-магазинах, тем паче в китайских. :( Наверное, придётся научиться.
> Быстрее
Выпаять кварц из мышки и припаять на модуль — десять минут. Неужто к вам из китая всё за десять минут доходит?
Ну и это, быть может, он потому и за 50 рублей продавался, что дефектный?artyums
08.10.2015 19:43Очень советую научиться) в наших магазинах аналогичные компоненты в 2-3-4 раза дороже, а про знаменитый Чип и Дип вообще молчу)
Ни разу не сталкивался с использованием отдельных кварцев — неужели они все универсальные и пойдет любой на замену любому?wormball
08.10.2015 20:23> Очень советую научиться
А может, ещё и посоветуете статью, где об этом рассказывается «для тупых»?
> неужели они все универсальные и пойдет любой на замену любому?
Часовые кварцы (цилиндр 3*8 мм) по идее все на 32768 Гц и подходят к чему угодно. А на «нечасовых» обычно частоту пишут. Вообще у меня с кварцами (с совместимостью) проблем не было, и я не слышал, чтобы у кого-то они были.artyums
08.10.2015 21:12Да в общем-то мало чем отличается от обычных российских интернет магазинов) Разве что описание товаров на английском и адрес на нем же заполнять надо) во всем остальном — никаких отличий: ищем товар, указываем количество, заполняем адрес, платим по реквизитам карты или другим способом — ждем доставку, следя за online-треком отправления в качестве дополнительного развлечения :)
Наименования деталей, если говорить про электронные компоненты, все такие же (ну разве что, понятное дело, чисто российских марок там не будет :D), поэтому с поиском никаких проблем. Тем более на том же AliExpress есть продавцы, которые торгуют чисто всей этой рассыпухой, и можно сразу у одного продавца заказывать всего и сразу в одной посылке :))
__
Интересная информация про кварцы. Спасибо!wormball
08.10.2015 22:00> платим по реквизитам карты или другим способом
Вот у меня с этим пунктом проблема. Какая-то карта есть, только оплачивать ею что-либо по интернету не получается.artyums
08.10.2015 22:08Карта должна быть уровня MasterCard Standart или Visa Classic. Либо более высокого уровня. Также работают некоторые карты Maestro, если банк разрешает онлайн-операции. Скорее всего у Вас та карта, которая не работает в Интернете.
Можете также платить и вовсе без карт, через Яндекс.Деньги или QIWI Wallet. Все эти способы (включая карты) — без комиссии.
sashabeep
07.10.2015 10:24A еще проще — купить часы «Montana» и отпаять динамик. От ардуины-то, собственно, требуется только рисование художеств в ленте
Keroro
07.10.2015 07:55Кварц проверьте, обычно такое бывает если для микросхемы нужен кварц, к примеру, на 12пик (если микросхема типа DS1338), а запаян на 6пик. Если кварц нормальный, то даже без термостабилизации, калибровки и прочих плясок точность получается порядка 30ppm (несколько минут в месяц).
avs24rus
07.10.2015 05:38Интересное изделие. Единственное что внапряг — покупка 3Д принтера, всеж целых 20 тыщ, а то и больше!
Я бы не стал заморачиваться на RTC, а поставил бы nRF24 и запрашивал бы время у метеостанции при вкючении питания ну и переодически, скажем 2 раза в сутки. Установку будильника сделал бы через Веб-интерфейс. А метеостанция получает время из интернета, так что там с точностью все ОК.masterkit
07.10.2015 09:00Наличие принтера позволяет напечатать что угодно, пример тому — работы на нашем фотоконкурсе. Один участник даже сверлильный мини станок сделал. Но, даже если у вас нет принтера, то можно легко найти конторы и частников, оказывающих услуги 3д печати. Сейчас 3д печать становится все доступней. Если вам надо, то могу подсказать где поискать.
avs24rus
07.10.2015 09:19Да мне даже не столько денег жалко, просто круг использования такого принтера для меня — это изготовление корпусов (по сути коробочек) для своих поделок, а их не так уж и много. А потом он будет просто стоять и пылиться.
Подскажите, пожалуйста, где поискать, с учетом того, что я живу в Красноярске.
amarao
Я вопрос решил проще:
1) Контроллер розетки с таймером. Набор расписаний, часы, время включения и выключения.
2) 200Вт галогенный напольный светильник.
И да, я просыпаюсь _каждый_ раз. Хотя потом могу отвернуться и сделать вид, что не заметил, но 200Вт света не заметить не возможно.
Цена: €15 за контроллер розетки, €50 за лампу. Итого — €75, и это с поправкой на местные негуманные наценки.
SADKO
А можно по подробнее о том куда светит 200Вт что бы хватило проснуться?
В смысле лампа ложе освещает или в потолок долбит?
amarao
Сверху для сравнения — 60Вт лампочка включена.
Chris_Griffin
А что за лампа? Цоколь/типоразмер?
amarao
Обычная вытянутая галогенка. Вот такая примерно: www.amazon.com/HALOGEN-LIGHT-TYPE-T3-150WATT/dp/B005MS8U5C
sashabeep
Вы, наверное, не очень понимаете смысл светобудильника
amarao
Проснуться без ощущения, что надо срочно затыкать будильник, но всё-таки проснуться.
Яркий свет будит не очень резко (обычно к этому времени уже рассвело и из окна есть свет), а тут свет становится сильнее и очень напоминает солнечный.
sashabeep
Смысл в плавном нарастании яркости — это делает подъем естественным, так же, как это делает солнце — чем больше света, тем меньше выработка мелатонина — гормона сна
amarao
Ну так лампа примерно с тем же и справляется.
Обычные же светильники с микроскопической яркостью в десятки люменов не дают засветку глаз сквозь веки.
sashabeep
Такой пойдет?
amarao
Сколько люменов? У моего будильника — порядка 4000-5000, и то, я бы предпочёл ещё поярче.
SADKO
ИМХО тут дело ещё не только в люменах, на то есть забористые светодиоды, дело в спектре, у диодов он дюже полосатый.
А галогенок большой перекос в инфракрасный, он прекрасно пробивает веки и мягкие ткани тела, ближе к природе.
wormball
А разве она у вас плавно разгорается?
amarao
Она просто включается. Там только диммер есть — но, кстати, я думаю, можно найти управлялку розетки с диммером — тогда будет и плавно.
olex
В свое время сделал такое же чудо. И когда 200 ватт включились утром, я просто взлетел в кровати. Это как прожектор в лицо.
Подключил люминесцентную трубку ватт на 20, что ли, положил ее на шкаф. И вот это стало реально легким пробужденнием.
Из сна не вырывает, но через полчаса просыпаешься сам.
Сейчас у меня такое и в спальне, и в детской.