Smart Relay. Делаем своими руками


Анекдот-вступление:
Мужчины молчат в двух случаях:
1.Что тут говорить, когда всё ясно.
2.Что тут говорить, когда ничего не разберёшь.


Так вот. Как то, разговаривая со своим другом, Александром, пришли к выводу, что среди радиолюбителей-профессионалов редко кто-то тратит время на подробное описание своих изделий. Типа, «а что тут описывать. ВСЕ и так ПРЕДЕЛЬНО ясно и понятно». А вот в среде «новичков», радиоГубителей и тому подобных, обмен информацией и обсуждение происходит более «живо» и интенсивно. Тут люди не стесняются задавать «глупые» вопросы (получая, зачастую такие же глупые ответы). И как правило, в конце дискуссии приходят к некому консенсусу.
Это к тому, что, я отношусь именно к касте радиолюбителей-новичков. Поэтому стараюсь делать ОЧЕНЬ подробное описание своих поделок.

Ладно, довольно лирики.
Существует интересный способ для создания, так называемых «умных вещей».

Благодаря этому способу появились на свет умные светодиоды (BlinkM), умные розетки и т.д. Ну и естественно, не обошлось и без «умного реле».

Итак, приступим.
Устройств, отмеряющих временные интервалы достаточно много. Взять хотя бы бесчисленные реализации на NE555 (GOOGLE Вам в помощь). Тем не менее, я считаю, что, появление альтернативных вариантов большой беды не делает. Как говорят, «у потребителя должен быть выбор». Спешу Вам представить устройство «Smart RELAY». Очень надеюсь, что найдутся желающие повторить проделанную мною работу. По «выхлопу» вы получите в меру малогабаритный, «копеечно стоящий», самодостаточный модуль. Применений которому можно найти великое множество.

Ну, поехали. (с) Ю.А. Гагарин
Вдохновение было навеяно этим.

Общая идея такая. Это должно быть устройство, которое по определенному событию (в самом простом варианте — по замыканию некого контакта), будет на определенное время включать реле (к которому может быть подключено все, что угодно).

Для «сладости» добавим, как говорят, автолюбители, немного «фарша». А именно:


Изначально планировалось все делать на Arduino. (Просто, программист из меня – «как из говна рябины пуля». Хотя, в детстве весьма неплохо получалось писать на ассемблере для Z-80. Но, как оказалось, полезные навыки со временем легко утрачиваются). Изучение СИ для AVR или переход AVR Studio я пока не планирую (банально не хватает времени). А вот в Arduino IDE я более-менее (или как еще говорят, «худо-бедно») что-то могу сделать. Правда, написанные мною исходные коды мой приятель-программист (которого, кстати, зовут Юрой) чаще всего называет или «г… нокодом» или «индийским стилем».

Так вот, планировалось, что я все сделаю на Arduino. Отлажу, «отшлифую». Потом просто разведу простенькую печатную плату «embedded Arduino» с реле. А «прошитую» в Arduino Atmega8 я возьму и вставлю в конечное устройство.

Ай-ай! Не рационально как-то получается. Да и затратно по бюджету. Как говорит мой хороший приятель, Дмитрий: «Это же не наш метод!». А тут еще не так давно, начитался про возможность писать код в привычном Arduino IDE, но под маленькие контроллеры (семейство Attiny).

Важное замечание: у меня уже был в наличии Attiny2313 (который, кстати, стоит около 1.5$, против 3$ за Atmega8 на нашем радиорынке). DIP-переключатель я выпаял из чекового принтера. Реле тоже было обнаружено в «загашнике». В общем, принцип Ивановича — «используй то, что под рукою и не ищи себе другого», в данном изделии показан как нельзя лучше. Я даже скажу, ИДЕАЛЬНО. У меня оказалось в наличии ВСЕ!!!.

Итак, по предварительным прикидкам наш модуль SMART RELAY будет состоят из трех блоков:
— мозг (это микроконтроллер) с небольшой «обвязкой»
— система питания (линейный стабилизатор напряжения на базе LM7805)
— коммутационный узел (это собственно наше реле с обвязкой)


Кстати, попутно прорекламирую проект одного итальянца. Называется ABC – Arduino Basic Connections. Что же в нем интересного? Для специалистов-схемотехников (Александру – привет!), скорее всего, ничего. Просто человек очень наглядно разрисовал типовые подключения разнообразных устройств к Arduino. Вот, например, как подключить реле:


(Я давно уже распечатал для себя картинки c этого ресурса на фотобумаге A6 и вставил их в маленький фотоальбом. И теперь он валяется на рабочем столе. Всегда под рукой. Все очень наглядно. Всем рекомендую).

Схема задуманного устройства ниже. Выбор пинов для варианта с Attiny был сделан в угоду удобства при разводке печатной платы, т.е., не догма. Можете менять, как Вам будет угодно (поправив в скетче нумерацию pin-ов). Особнячком выделен блок «на перспективу». Это просто на оставшиеся незадействованные ножки микроконтроллера я повесил дополнительную кнопку и светодиод. Правда, в представленном ниже коде они не задействованы.

Принципиальная схема:


Надеюсь, что схема пояснений не требует :)

ОКОНЧАТЕЛЬНОЕ ОПИСАНИЕ ФУНКЦИОНАЛА (так сказать, USER MANUAL)


Для нормального функционирования нашему устройству нужно электропитание. В принципе подойдет любой малогабаритный блок питания со следующими параметрами: Напряжение -7.5..15 Вольт и ток порядка 150 mA.

Установка времени DIP-переключателями.
Интервалы, которые будут доступны для установки: min=1 секунда; max= 31 час
Предлагаемый способ установки времени (IMHO) очень удобен. Принцип достаточно прост.
Есть переключатели установки секунд. Суммируем включенные значения, согласно «весу».
(Например 15 секунд:(1х1)+(2 х1)+(4 х1)+(8 х1)+(16х0)=15 секунд.)
И есть три множителя. На которые нужно умножать значение установленных секунд.
В таблице приведены некоторые примеры установки.


Доступные режимы работы.

Спешу заметить, что режимы работы можно задавать не только перемычками, но и выносными кнопками, активными модулями и т.д. Согласно выполняемой модулем задачи.
Естественно, допускается установка нескольких режимов работы, для получения нужного алгоритма. Например, установка перемычек [REPEAT]+[TRG&RESET] приводит к старту циклов включения и выключения при подаче питания и будет выполняться бесконечно.

С описанием пока все. В конце своего «опуса» приведу пару примеров возможного применения SMART RELAY в реальной жизни.
— По примеру «авторитетных» изданий, прилагаю список необходимого для повторения (aka BOM-list):

=== BOM LIST (Распечатать для похода на радиорынок)====
-кусок стеклотекстолита 70x50mm
-МК ATtiny 2313
-колодка под мк (20 ножек)
-Реле с напряжением срабатывания 5В (я брал HJR-3FF-S-Z)
-стабилизатор напряжения 7805
-диод 1N4007 (2 шт)
-электролитический конденсатор 10х50В
-электролитический конденсатор 100х16В
-конденсаторы 100н (маркировка 104)- (2 шт)
-резистор SMD 1кОм (4 шт)
-светодиоды 3 мм (3 шт)
-транзистор n-p-n C945 (подойдет любой аналогичный)
-кнопка — (2шт)
-Винтовые клеммники 1х2 — (2шт), 1х3- 1шт
-разъем питания (2.1мм)
-DIP-переключатель (на 8 позиций)
===END BOM LIST (Распечатать для похода на радиорынок)====

Напомню, что себестоимость проекта (даже если ВСЕ купить) получается достаточно низкой. Что-то в районе 5 у.е.

Печатная плата:

(Схема и печатная плата находятся а архиве в папке Hardware)
Все, как обычно по плану: «лутим», лудим, паяем…. На этом этапе не буду заострять Ваше внимание.

«ЖЕЛЕЗЯЧНАЯ ЧАСТЬ» готова.

Переходим к софту.
Отладочная версия, в «Arduino Style»

При отладке, я вместо реле использовал светодиод. И большую часть отладки и написания кода делал лежа на диване с ноутом и платой CraftDuino, которую мне подарили за участие в конкурсе «КиберВесна». Оказалось очень удобно, нет необходимости в дополнительном блоке питания. Еще раз, спасибо ресурсу www.robocraft.ru!

ВАЖНОЕ ЗАМЕЧАНИЕ! Я старался не допускать грубых ошибок в коде. И проводил тестирование (по несколько суток!), однако, гарантировать 100%-ое отсутствие ошибок, ЕСТЕСТВЕННО, не могу. Поэтому, НЕ РЕКОМЕНДУЮ использовать SMART RELAY для управления космическими кораблями, ядерными реакторами, искусственными почками и т.п.

Получившейся код (старался комментировать по максимуму):


/*  Smart Relay module (beta)
    04/2/2014 Ghost D.
    Compiled on Aurdino IDE (2 Attiny2313)
*/


//Блок определения пинов для Attiny2313
/*
//схема моего подключения
//в скобках указана "ардуиновская" нумерация выводов
//                +-\/-+
// 	  (D17)  1|    |29  VCC
// x60	   (D0)  2|    |19   (D16)
// x10	   (D1)  3|    |18   (D15) - Button2 (пока резерв)
// x6	   (D2)  4|    |17   (D14) - Led2 (пока резерв)
// 16	   (D3)  5|    |16   (D13) - Rele
// 8	   (D4)  6|    |15   (D12) - Repeat
// 4	   (D5)  7|    |14   (D11) - Start/Stop Trigger
// 2 	   (D6)  8|    |13   (D10) - Triger & Reset
// 1	   (D7)  9|    |12   (D9)  - Cancel Trigger
// 	    GND 10|    |11   (D8)  - Trigger(Button)
//                +----+
------------------------------------------
*/

//Start -- блок описания пинов, ответ. за установку времени
byte pin_1=7; // 
byte pin_2=6;
byte pin_4=5;
byte pin_8=4;
byte pin_16=3;
byte pin_x6=2;
byte pin_x10=1;
byte pin_x60=0;
//End -- блок описания пинов, ответ. за установку времени

byte rele_pin=13;// пин, к которому подключено реле

//Start -  дополнительные параметры
byte triggerButton=8;   // пин, к которому подключен триггер
byte cancelTrigger=9;   // игнорирование нажатия кнопки триггер
byte trigReset=10;      //запуск цикла при ресете или кнопке триггера
byte startStopTrig=11;  //Прерывание текущего цикла по кнопке триггер
byte repeatMode=12;     //режим повтора
//End -  дополнительные параметры

unsigned long releOnTime; // Тут будем хранить заданное DIP-переключателями время
unsigned long myIntTimer; //
unsigned long myIntTimer_temp;
unsigned long debounceStartTime; // нужно для защиты от "дребезга"


byte Triggered;
byte releOn;
byte debounced;
byte TrigInLast;
byte TrigIn;
byte doCancel;

void setup(){
pinMode(pin_1,INPUT_PULLUP);
pinMode(pin_2,INPUT_PULLUP);
pinMode(pin_4,INPUT_PULLUP);
pinMode(pin_8,INPUT_PULLUP);
pinMode(pin_16,INPUT_PULLUP);
pinMode(pin_x6,INPUT_PULLUP);
pinMode(pin_x10,INPUT_PULLUP);
pinMode(pin_x60,INPUT_PULLUP);
pinMode(triggerButton,INPUT_PULLUP);
pinMode(cancelTrigger,INPUT_PULLUP);
pinMode (trigReset,INPUT_PULLUP);
pinMode (startStopTrig,INPUT_PULLUP);
pinMode (repeatMode,INPUT_PULLUP);
pinMode(rele_pin,OUTPUT);


  resetTimer(); //запоминаем текущее значение millis() в переменную myIntTimer, от которого и будем отсчитывать интервал
  releOnTime=readStopTime(); //Процедура расчета установленного времени

//
// Проверяем, если установлена фича ТриггерРесет и нету Cancel триггер
// то нужно включить реле 
  
if (digitalRead(cancelTrigger) && digitalRead(trigReset)==0){
  TurnReleOn();
  Triggered=1;
  releOn=1;
}
 else{
  TurnReleOff();
  Triggered=0;
  releOn=0;
 }
 
 debounced=0;
 debounceStartTime=0;
 
 TrigInLast=((digitalRead(triggerButton))==0);
}


/* Основной цикл */
void loop(){

 TrigIn=((digitalRead(triggerButton))==0);
 doCancel=0;
 
 if (TrigIn && (TrigInLast==0) &&(debounced>1)) //
     {  
       if (Triggered==0)
         {
           if (digitalRead(cancelTrigger))
         {
           resetTimer();
           releOnTime=readStopTime();
           TurnReleOn();
           Triggered=1;
           releOn=1;
          }
         }
          else if (digitalRead(startStopTrig)==0)
          //Если Start-Stop trigger активен
          {
            doCancel=1;
          }
          
       }

if (TrigIn==0){
  if (TrigInLast)
    {
      debounceStartTime=millis();
      debounced=1;
    }
    else
    {
      if ((millis()-debounceStartTime)>50)
      {
        debounced=2;
      }
    }
}

if (TrigIn)
  {
    debounced=0;
  }

if (Triggered)
  {
    if (digitalRead(cancelTrigger)==0)
    {
      doCancel=1;
    }



//Ниже-"стремное место" в случае переполнения счетчика. Можем получить отрицательный результат
//Защита от сброса счетчика таймера
//Если текущее значение millis() стало ВДРУГ меньше, чем предыдущее
//То уменьшаем время ожидания (releOnTime) на (4294967295-myIntTimer) - это время, которое уже "протикало"
//а переменной myIntTimer присваиваем 0
//  
//
myIntTimer_temp=millis();

if (myIntTimer_temp<myIntTimer){
    releOnTime=(4294967295-myIntTimer);
    myIntTimer=0;
}


if ((myIntTimer_temp-myIntTimer) >= releOnTime){
  //если время прошедшее с момента Ресета больше или равно расчетному
 if (digitalRead(repeatMode)) //Если режим повтора выключен
    { //проверяем установку режима повтора (если 1-выключено)
      doCancel=1;
    }
  else
    {
      //Если режим повтора включен, готовим следующий цикл
      resetTimer();
      releOnTime=readStopTime();
      
      if (releOn){
        TurnReleOff();
        releOn=0;
      }
      else {
        TurnReleOn();
        releOn=1;
      }
    }
 }
 if (doCancel)
   {
     //если doCancel=1 выключаем реле
     TurnReleOff();
     Triggered=0;
     releOn=0;
   }
  }
  
  TrigInLast=TrigIn;
     
} 
//end основного цикла


// Подпрограммы
//--------------

//считываем значение времени с переключателей
//Время считается в "тиках". кол-во тиков/1000 => время в секундах
unsigned long readStopTime(){
  unsigned long total=0;
  unsigned int temp=1;
  if (digitalRead(pin_1)==0) total=1;
  if (digitalRead(pin_2)==0) total+=2;
  if (digitalRead(pin_4)==0) total+=4;
  if (digitalRead(pin_8)==0) total+=8;
  if (digitalRead(pin_16)==0) total+=16;
  if (total==0) total=1;
  if (digitalRead(pin_x6)==0) temp*=6;
  if (digitalRead(pin_x10)==0) temp*=10;
  if (digitalRead(pin_x60)==0) temp*=60;
  return (total*temp*1000);
  
}

//сброс счетчика времени
void resetTimer(){
       myIntTimer=millis();
   }

//тут включаем реле
void TurnReleOn(){
  digitalWrite(rele_pin, HIGH);
}

//тут выключаем реле
void TurnReleOff(){
  digitalWrite(rele_pin, LOW);
}


Подготовка ARDUINO IDE для работы с м/к Attiny2313

Оригинал читаем тут. Кому лень читать по «не по-русски», кратко перескажу:
Архив arduino-tiny-0100-0018.zip (я, на всякий случай, положил в архив проекта), распаковываем в папку со скетчами!!! ЭТО ВАЖНО!!! Т.е., все это хозяйство должно лечь так:

[путь к папке со скетчами]\HARDWARE\TINY

Открываем файл Prospective Boards.txt, все что в файле, комментируем, кроме текста ниже (чтобы не захламлять список наших контроллеров. Если что-то понадобиться в дальнейшем — добавите). Файл сохранить с названием boards.txt:

###########################################################################

attiny2313at8.name=ATtiny2313 @ 8 MHz

# The following do NOT work...
# attiny2313at8.upload.using=avrispv2
# attiny2313at8.upload.using=Pololu USB AVR Programmer

# The following DO work (pick one)...
attiny2313at8.upload.using=arduino:arduinoisp
# attiny2313at8.upload.protocol=avrispv2
# attiny2313at8.upload.using=pololu

attiny2313at8.upload.maximum_size=2048

# Default clock (slowly rising power; long delay to clock; 8 MHz internal)
# Int. RC Osc. 8 MHz; Start-up time: 14 CK + 65 ms; [CKSEL=0100 SUT=10]; default value 
# Brown-out detection disabled; [BODLEVEL=111]
# Serial program downloading (SPI) enabled; [SPIEN=0]
# Preserve EEPROM memory through the Chip Erase cycle; [EESAVE=0]

attiny2313at8.bootloader.low_fuses=0xE4
attiny2313at8.bootloader.high_fuses=0x9F
attiny2313at8.bootloader.extended_fuses=0xFF
attiny2313at8.bootloader.path=empty
attiny2313at8.bootloader.file=empty2313at8.hex

attiny2313at8.build.mcu=attiny2313
attiny2313at8.build.f_cpu=8000000L
attiny2313at8.build.core=tiny
 
###########################################################################


Запускаем Arduino IDE (я пользуюсь версией 1.0.5), и в примерах выбираем ArduinoISP
Жмем кнопку загрузить… ждем успешного окончания процесса


Далее выбираем в меню [СЕРВИС]->[ПРОГРАММАТОР] выбираем Arduino as ISP



Далее указываем, что будем программировать [СЕРВИС]->[ПЛАТА] и выбираем Attiny 2313 @ 8Mhz


На макетной плате подключаем ATTiny2313 согласно выводам

20 — VCC
10 — GND
17 — MOSI — Arduino Pin11
18 — MISO — Arduino Pin12
19 — SCK — Arduino Pin13
1 — RESET — Arduino Pin10



Дополнительно (чтобы Arduino не перезагружался во время заливки скетчей в Attiny) ставим электролитический конденсатор на 10x16V между GND и Reset на ардуино, минусом на землю.
Осталось чуть-чуть… Компилируем и «прошиваем».

Для особо ленивых. Допускаю, что есть люди, которые сделали плату, все запаяли, но разбираться с Arduino и особенностями ее программирования не особо желают. Для этого случая, в каталог FIRMWARE\HEX\ я положил готовую прошивку в hex и bat-файл для программатора. Правда, для этого случая Вам понадобиться программатор. Например USBTinyISP. Запускаем burn_(with USBTiny).cmd.

Все, готово!!!

Небольшой BONUS. Примеры применения в жизни

Пример одного из применения. «Экономная подсветка подъезда».

Выставляем DIP-переключателями время, необходимое для того, чтобы человек успел подняться на свой этаж (считаем, что на последний). Ставим режим [START/STOP TRIGGER]. Итак, человек входит в подъезд, нажимает кнопку (именно КНОПКУ! без фиксации) реле включается и начинается отсчет времени. Поднявшись на свой этаж, человек снова нажимает кнопку — цикл прерывается и реле отключается. А если человек поленился нажимать на кнопку на своем этаже, то спустя заданное время, освещение выключится автоматически.
Для вообще «экономно-бережливых», можно установить датчик освещения на контакты [CANCEL]. Что, по идее, будет препятствовать срабатыванию реле при достаточной освещенности :)

Пример №2
Тут приведу ответ на вопрос от одного моего «поклонника» (в хорошем смысле этого слова). Тут, он пишет что бы ему хотелось получить:


Отвечаю. Да, это устройство позволяет выполнить поставленную задачу. Даже более того. Получится вообще «СУПЕР экономичный» режим. Т.к., в данном варианте нету потребления энергии «холостого хода

Выставляем необходимый интервал времени (допустим, 10 минут на «заседание» и 10 минут проветривание. Следовательно, устанавливаем время 20 минут). Режим работы ставим [TRIGGER & RESET]
При появлении питания, SMART-RELAY включается и уже через свои контакты реле запитывает себя и вентилятор. После отсчета заданного интервала времени, цепь питания разрывается (к этому времени, основной выключатель уже выключен). И вуа-ля!!! То, что нужно!

Пример №3
Тут уже используем «особенность» используемого реле. А именно, тот факт, что у нас реле с переключающимися контактами.

Устанавливаем нужный интервал времени, и режим работы [REPEAT]. (на рисунке вариант с 12-ти вольтовой нагрузкой. Единственное, учитывайте возможности своего БП).

И у нас будут поочередно находиться в работе то куллер, то лампочка.
Естественно, аналогичным образом можно организовать коммутацию и устройств, рассчитанный на напряжение 220 Вольт. (Например, переключение подсветки с дежурного освещения, на основное. Т.е., подключаем две лампочки, «тускленькая» снаружи гаража и яркая внутри).

И так далее и тому подобное. Предлагаю Вам самостоятельно поискать интересные способы применения этого «маленького кирпичика умного дома».

Весь материал по проекту одним архивов забираем тут.

Всем удачи и благополучия!
  • +1
  • 20 февраля 2014, 06:53
  • Ghost_D

Комментарии (4)

RSS свернуть / развернуть
+
0
Интересная статья. Спасибо
avatar

DevOS

  • 4 марта 2014, 03:31
+
0
Статья хорошая, спасибо
Но есть вопрос
беру реле SRD-05VDC-SL-C
собираю по данной схеме — никаких движений
на обмотке реле — 0 — 1.33 В
Подсоединяю напрямую ) к выводу Arduino — все работает!!!
Не подскажите в чем дело?
avatar

victoruni

  • 28 марта 2014, 06:53
+
0
Ой, ой! Наверное напрямую подключать реле к пинам — не самая лучшая идея. Так, что у тебя получается проблема с транзистором? Транзистор работает как ключ. Можно вытащить Attiny из колодки, подать питание и проводком с 5В коснуться вывода №16 на колодке. Должен загореться светодиод и щелкнуть реле :) Если нет, проверь транзистор и его цоколевку.
avatar

Ghost_D

  • 28 марта 2014, 09:17
+
0
День добрый! Как реализовать по вашему примеру № 2, следующие:
Первое: работа реле должна управляться с МК;
Во вторых должна стоять кнопка на вкл/выкл нагрузки;
И в третьих при срабатывание реле в тех или иных случаях положения кнопки нагрузка должна «падать» или «подыматься»! Т.е. не подавая команды на реле мы включаем нагрузки при помощи кнопки. А выкл/вкл нагрузку при помощи реле. Допустим у нас включен свет через выключатель, а выключить мы его хотим через МК с помощью реле.

P.S. 1 и 2 — реализовано у вас, главное волнует 3 пункт.
Заранее благодарен!!!
avatar

Konstantin_B

  • 22 января 2015, 16:09

Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.