Кремень КД Реклама
Кремень КМ Реклама

Проснись с комфортом — делаем светобудильник своими руками

masterkit
Идет загрузка
Загрузка
06.10.2015
9254
13
Применение

Подпишитесь на автора

Подпишитесь на автора, если вам нравятся его публикации. Тогда вы будете получать уведомления о его новых статьях.

Отписаться от уведомлений вы всегда сможете в профиле автора.

8
Статья относится к принтерам:
MC2 MC3 Stealth MC5
Вот и настала осень…

Впереди неумолимо маячит зима – утром темно, вечером темно.

Просыпаться по будильнику в полной темноте равносильно нырянию под лед. Стресс с утра – гарантированно унылый день.

Решение-то есть, светобудильник называется, но цена этой штуки от 5000 руб. Колется, однако. К тому же, алгоритм работы жестко запрограммирован, а ведь совершенно очевидно, что, по результатам просыпания, захочется что-то подкорректировать или расширить функционал.

А что, если на основе подручных средств соорудить что-то в этом духе? Хорошая задачка для DIY!
Проснись с комфортом — делаем светобудильник своими руками
Для решения были использованы следующие материалы:

— прототип отладочной платы набора для изучения программирования Ардуино (входит в будущий набор NR05), рассчитанная на установку Arduino Nano;

— часы реального времени MP1095;

— светодиоды разные;

— пьезопищалка со встроенным генератором;

— белая полупрозрачная штука, когда-то напечатанная при отладке 3D-принтера (можно приспособить еще что-нибудь полупрозрачное в качестве рассеивателя, а у кого есть 3D принтер, то напечатать что нибудь свое);

— желание все это соединить и запрограммировать подходящий алгоритм работы.

Белую штуку захотелось взгромоздить на какой-нибудь постамент, чтобы смонтировать туда светодиод и подключить его кабелем к плате. Недолго думая, рисуем в SketchUp и печатаем на 3D принтере оранжевую подставочку. При сильном желании можно напечатать корпус для платы-прототипа, но прототип и так немыслимо красив!

К тому же, его можно использовать и под разработку других проектов, а будильничек, по результатам эксплуатации опытного образца, можно оформить в более компактную конструкцию на основе той же платы Arduino Nano.

Сначала воткнули один светодиод. Он был приклеен к основанию инновационным клеем, отверждающимся при воздействии ульрафиолета. Называется Bondic. Полезная в хозяйстве штучка, надо сказать! Держит крепко.
Проснись с комфортом — делаем светобудильник своими руками
Проснись с комфортом — делаем светобудильник своими руками
Проснись с комфортом — делаем светобудильник своими руками
Проснись с комфортом — делаем светобудильник своими руками
Тем же клеем приклеили разъем и собрали.
Проснись с комфортом — делаем светобудильник своими руками
Проснись с комфортом — делаем светобудильник своими руками
Посмотрели, как светиться. Не понравилось. В темноте, конечно, видно, но для активации мозга через оптические рецепторы не хватает. По сусекам набрали несколько ярких белых светодиодов. Объединенные параллельно в такую вот веточку, они дают вполне пробуждающий в максимуме яркости свет.
Проснись с комфортом — делаем светобудильник своими руками
Потребляют в максимуме порядка 100 мА, напрямую к порту Ардуино не подсоединишь, но на отладочной плате имеется усилитель тока на транзисторе, обеспечивающий 200 мА.
Проснись с комфортом — делаем светобудильник своими руками
Также на плате есть пять кнопок для всяких экспериментов, их задействуем для управления режимами и настройки будильника.

В целом, отладочная плата интересна наличием маркированных разъемов-штырей для подключения различных датчиков и исполнительных устройств, обеспечивая хороший функционал и дружелюбный интерфейс – можно, особо не задумываясь (разъемы подписаны) подключить датчики температуры, давления, сервомашинки, реле, устройства с интерфейсом I2C и т.п. Для подключение нужны только провода с разъемами-розетками.
Проснись с комфортом — делаем светобудильник своими руками
Яркость будем регулировать ШИМом с девятого пина Ардуино, разведенного на плате к усилителю. Пищалку подсоединим к разъему SOUND, на DAT плюсом, на GND минусом. Часы реального времени – к разъему I2C_5V, поскольку 5В им и надо для питания. На плате уже установлен двухстрочный LCD индикатор, весьма контрастный, с приятными белыми знаками на синем фоне.

Собственно, все железо на месте, теперь дело за софтом.

Алгоритм был задуман так:

— при совпадении текущего времени с временем, на которое установлен будильник, яркость светильника должна медленно повышаться по полной;

— при этом несколько раз по нарастающей должны подаваться звуковые сигналы, не дающие wakeUp-объекту начихать на лампочку и уснуть при свете;

— надо дать возможность выключить в конце-концов надоедливый звук, а также включить полный свет вручную, или выключить его, уже будучи в полном сознании.

— должна быть возможность ставить время на часах и будильнике.

Получившийся скетч приведен в конце материала и снабжен подробными комментариями. Его несложно модифицировать под ваши желания и предпочтения.

Всем приятного пробуждения!
Проснись с комфортом — делаем светобудильник своими руками
п.с. Внимание! С с 23 сентября по 23 октября 2015 г.мы проводим фотоконкурс

«3 D печать для решения бытовых вопросов»!

Победитель получит в подарок 3D принтер-конструктор MC5 с акриловым корпусом.

Условия фотоконкурса.

Скетч для светобудильника:

// Подключаем библиотеки вывода кириллицы на индикатор

#include

#include

#include

// Подключаем библиотеку последовательной шины I2C

#include

// Подключаем библиотеку часов реального времени RTC

#include «RTClib.h»

// Подключаем библиотеку для использование встроенного таймера 2

// для управления временными интервалами сигнала

#include

//-----------------------------------------------------------------------

#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);

}

}

Подпишитесь на автора

Подпишитесь на автора, если вам нравятся его публикации. Тогда вы будете получать уведомления о его новых статьях.

Отписаться от уведомлений вы всегда сможете в профиле автора.

8
Комментарии к статье