Рулонные шторы на ардуино.

sheff
Offline
Зарегистрирован: 14.11.2017

Управление шторами при помощи ардуино и шаговых моторов. 

http://www.youtube.com/watch?v=P_dk7K4_4fI&t

sandr4
sandr4 аватар
Offline
Зарегистрирован: 11.02.2015

Как это всё реализовано? Особенно заинтересовали "кнопки".

sheff
Offline
Зарегистрирован: 14.11.2017

Кнопки использовал TTP223, вот ссылка на али.
Моторчики 5v с драйвером, еще ссылка.
 

sheff
Offline
Зарегистрирован: 14.11.2017

Сделал несколько фоток монтажа моторчиков к шторам...

Знакомый токарь выточил втулки вместо родного механизма.

Разбираем штору и вместо механизма вставляем втулку.

Собираем боковую часть и тонким сверлом делаем отверстие, для того чтобы отметить центр.

Замеряем диаметр той части втулки, под которую будем делать отверстие в боковой крышке.

Делаем отверстие.

Прикладываем моторчик и отмечаем где будет крепление.

Собираем всё на место...

Устанавливаем штору, подключаем и радуемся.

sir_kimas
Offline
Зарегистрирован: 01.08.2016

sheff пишет:

Сделал несколько фоток монтажа моторчиков к шторам...

Знакомый токарь выточил втулки вместо родного механизма.

Разбираем штору и вместо механизма вставляем втулку.

Собираем боковую часть и тонким сверлом делаем отверстие, для того чтобы отметить центр.

Замеряем диаметр той части втулки, под которую будем делать отверстие в боковой крышке.

Делаем отверстие.

Прикладываем моторчик и отмечаем где будет крепление.

Собираем всё на место...

Устанавливаем штору, подключаем и радуемся.

 

Молоток! :)

evgta
Offline
Зарегистрирован: 02.09.2016
sheff
Offline
Зарегистрирован: 14.11.2017

Согласен, моторчик крутит медленно, но солидно и зрелищно :)
Сейчас сделал замер - 50 сек полное открытие или закрытие.
Торопиться некуда, можно и не ждать....сама доедет и остановится.

pozdnyakov
Offline
Зарегистрирован: 16.01.2018

Фотки не грузятся, перезалей плз

sheff
Offline
Зарегистрирован: 14.11.2017

sheff пишет:

Управление шторами при помощи ардуино и шаговых моторов. 

http://www.youtube.com/watch?v=P_dk7K4_4fI&t

Видео доступно по ссылке: https://youtu.be/1ZVcHS72KFg

Схема подключения

//**********  (РЕЖИМ 1-ШАГ) Крутим с помощью сдвига --рабочая - крутит туда сюда без потери шагов - ускоряет - отключает катушки после бездействия
//PORTB - 8, 9, 10, 11 - Шаговик. && 12-кнопка Menu \ 13-Светодиод 1й штор.
//PORTD - 4, 5, 6, 7 - Шаговик. && 2-кнопка UP \ 3-кнопка DOWN
// А0-Светодиод 2й штор..
#include <EEPROM.h> 
#include <CyberLib.h>
#define uskor 3 //Задаем ускорение
//Здесь устанавливаем максимальное кол. шагов для штор
#define max_Sht1 28900
#define max_Sht2 27500
 
byte n1 = 1;// Сдвигаем 1 бит
byte n3 = 0x10;
bool f_timX = 0;
bool f_timZ = 0;
 
byte sped_Xt = uskor;//Начальная скорость
byte sped_X = 0; //Ускорение
byte sped_Zt = uskor;//Начальная скорость
byte sped_Z = 0; //Ускорение
 
bool f_run1X = 0;//Сброс после остановки 2 переменные.
unsigned long no_runX; //Переменная для прошедшего периода
 
bool f_run1Z = 0;//Сброс после остановки 2 переменные.
unsigned long no_runZ; //Переменная для прошедшего периода
// Переменные для кн.Menu
bool kn_menu;
bool f_menu;
bool f_Mpush;
bool f_Md;
uint8_t Menu = 1;
uint8_t temp_Menu;
bool kalib;
unsigned long menu_dreb;
unsigned long menu_klik;
// Переменные для кн.Up
bool kn_Up;
bool f_Up;
bool state_Up;
bool _UP;
uint32_t Up_dreb;
// Переменные для кн.Down
bool kn_Down;
bool f_Down;
bool state_Down;
bool _Down;
uint32_t Down_dreb;
//сбрасываем UP\Down
bool f_sbrosZ = 1;
bool f_sbrosX = 1;
 
uint32_t cur_time;//Миллис читаем один раз
uint32_t blink_time;//Мигаем в режиме калибровки
 
int Shtora1;
int Shtora2;
const int ton = 16;//пищалка
// чтение
int EEPROM_int_read(int addr) {   
  byte raw[2];
  for(byte i = 0; i < 2; i++) raw[i] = EEPROM.read(addr+i);
  int &num = (int&)raw;
  return num;
}
// запись
void EEPROM_int_write(int addr, int num) {
  if (EEPROM_int_read(addr)!= num){//если сохраняемое отличается
  byte raw[2];
  (int&)raw = num;
  for(byte i = 0; i < 2; i++) EEPROM.write(addr+i, raw[i]);
}
}
 
void setup() {
  // DDRB пин, 8,9,10,11 - Шаговик, pin 12- вход, 13- Выход
  DDRB = DDRB | B00101111;
  // pin 8,9,10,11,13 - выход в 0 а входы pin 12, - 0
  PORTB = B00000000;
  //  DDRD, подключенный к двигателю pin 4,5,6,7 как выход,pin2,3 Выход
  DDRD = DDRD | B11110000;
  // pin 4,5,6,7 - выход в 0 а входы pin 2,3 - 0
  PORTD = B00000000;//;
  D14_Out;  // Led_1
  D14_Low;
  D15_Out;  // Led_2
  D15_Low;
    pinMode(ton,OUTPUT);//пищалка
  //Serial.begin(9600);
  // Инициализировать TIMER1
  StartTimer1(Time_Closk, 2200);
      Shtora1 = EEPROM_int_read(0);
      Shtora2 = EEPROM_int_read(2);
}
void Beep() //короткий звук, переключение шторы
{
  tone(ton,500,500);
  delay(200);
  noTone(ton);
}
void Beep_long()  //длинный звук, вход и выход из режима калибровки "0"
{
  tone(ton,200,1000);
  delay(200);
  noTone(ton);
}
 
void Time_Closk() // Функция прерывания таймера
{
  f_timX = 1;
  f_timZ = 1;
}
 
//Функция вращения  dvigatel 1
void RunX (bool perem_X)
{
  f_sbrosX = 0;
  f_timX = 0;
  if (perem_X) {
    n1 = (n1 >> 1) | (n1 << 3); //Сдвигаем
    --Shtora1;
  }
  else {
    n1 = (n1 << 1) | (n1 >> 3); //Сдвигаем
    ++Shtora1;
  }
  n1 = 0x0F & n1; //Маскируем кнопки
  PORTB = (PORTB & 0xF0) | n1; //Очищаем Младшие биты и пишем туда n1
}
 
//Функция dvigatel 3
void RunZ (bool perem_Z)
{
  f_sbrosZ = 0;
  f_timZ = 0;
  if (perem_Z) {
    n3 = (n3 >> 1) | (n3 << 3); //Сдвигаем
    --Shtora2;
  }
  else {
    n3 = (n3 << 1) | (n3 >> 3); //Сдвигаем
    ++Shtora2;
  }
  n3 = 0xF0 & n3;//Маскируем
  PORTD = (PORTD & 0xF) | n3; //Очищаем старшие биты и пишем туда n3
}
 
void loop() {
 
  cur_time = millis();
  ///////////////////Проверка кнопки МЕНЮ - АНТИДРЕБЕЗГ
  if (D12_Read && !f_menu)
  {
    menu_dreb = cur_time;
    f_menu = 1;
  }
  if (!D12_Read)
  {
    kn_menu = 0;
    f_menu = 0;
  }
 
  if (f_menu && cur_time - menu_dreb >= 20)
  {
    kn_menu = 1;
    if (!f_Mpush) {
      menu_klik = cur_time;
      f_Mpush = 1;
    }
 
  }
//Был клик
if (f_Mpush && !kn_menu && cur_time - menu_klik < 1000) {
   if (_UP || _Down) {
    _UP = 0;
    _Down = 0;
  }
  else Menu++, Beep();     // Меняем
  if (Menu > 3) Menu = 1;
  f_Mpush = 0;
}
//Было нажатие
else if (f_Mpush && !kn_menu && cur_time - menu_klik > 1000) {
  Beep_long();
  kalib = !kalib; // Включаем калибровку
  f_Mpush = 0;
}  ///////////////////////Проверка кнопки UP - АНТИДРЕБЕЗГ
  if (D2_Read != f_Up) { //Если сигнал изменился
    f_Up = !f_Up;
    Up_dreb = cur_time;
  }
  if (kn_Up == D2_Read && cur_time - Up_dreb > 20) kn_Up = !D2_Read;
  // Было нажатие
  if (kn_Up && !state_Up) {
    if (_UP || _Down) {
      _UP = 0;
      _Down = 0;
      state_Up = 1;
    }
    else {
      _UP = !_UP;    // Меняем значение
      state_Up = 1;
    }
  }
  if (!kn_Up)state_Up = 0; // Отпустили
  ///////////////////////Проверка кнопки DOWN - АНТИДРЕБЕЗГ
  if (D3_Read != f_Down) { //Если сигнал изменился
    f_Down = !f_Down;
    Down_dreb = cur_time;
  }
  if (kn_Down == D3_Read && cur_time - Down_dreb > 20) kn_Down = !D3_Read;
  // Было нажатие
  if (kn_Down && !state_Down) {
    if (_UP || _Down) {
      _UP = 0;
      _Down = 0;
      state_Down = 1;
    }
    else {
      _Down = !_Down;    // Меняем значение
      state_Down = 1;
    }
  }
  if (!kn_Down)state_Down = 0; // Отпустили
  //////////////////////// С кнопками закончили продолжаем логику
  if (!kalib)
  {
    if (Menu != temp_Menu) {
      temp_Menu = Menu;
      switch (Menu) {
        case 1: D14_High; D15_Low; break;
        case 2: D14_Low; D15_High; break;
        case 3: D14_High; D15_High; break;
      }
    }
  }
  else {
    if (cur_time - blink_time >= 300)
    {
      blink_time = cur_time;
      switch (Menu) {
        case 1: D14_Inv; D15_Low; break;
        case 2: D14_Low; D15_Inv; break;
        case 3: D14_Inv; D15_Inv; break;
      }
    }
  }
  /////////////////////////// Запуск 1го двигателя если " perem_X != 0 "
  if (f_timX) {
    if (_UP || _Down) {
      if (Menu != 2) {
        if (!sped_X) {
          if (!kalib) { //Калибровка отк.
            if (_Down && Shtora1 < max_Sht1) {
              RunX(0);
            }
            if (_UP && Shtora1 > 0) {
              RunX(1);
            }
          }
          else { //Калибровка вкл.
            if (_Down) {
              Shtora1 = 0;
              RunX(0);
            }
            if (_UP) {
              Shtora1 = 1;
              RunX(1);
            }
          }
          //Три поверки для разгона
          if (sped_Xt > 0) {
            --sped_Xt;
            sped_X = sped_Xt;
            // f_timX = 0;
          }
        }
        else {
          --sped_X;
          f_timX = 0;
        }
      }
    }////
    else {
      sped_Xt = uskor;
      sped_X = 0;
    }
  }
  else { //Для снятия напряжения
    f_run1X = 1;
    no_runX = cur_time;
  }
  /////////////////Запуск 3го двигателя если " perem_Z != 0 "
  if (f_timZ) {
    if (_UP || _Down) {
      if (Menu != 1) {
        if (!sped_Z) {
          if (!kalib)//Калибровка отк.
          {
            if (_UP && Shtora2 < max_Sht2) {
              RunZ(0);
            }
            if (_Down && Shtora2 > 0) {
              RunZ(1);
            }
          }
          else {//Калибровка Вкл.
            if (_UP) {
              Shtora2 = 0;
              RunZ(0);
            }
            if (_Down) {
              Shtora2 = 1;
              RunZ(1);
            }
          }
          //Три поверки для разгона
          if (sped_Zt > 0) {
            --sped_Zt;
            sped_Z = sped_Zt;
            f_timZ = 0;
          }
        }
        else {
          --sped_Z;
          f_timZ = 0;
        }
      }
    }////
    else {
      sped_Zt = uskor;
      sped_Z = 0;
    }
  }
  else { //Для снятия напряжения
    f_run1Z = 1;
    no_runZ = cur_time;
  }
  //Возврат по достижению конечной точки
  if (f_sbrosZ && f_sbrosX) {
    _UP = 0;
    _Down = 0;
  }
  //Снимаем напряжение с катушек двигателя X
  if (f_run1X && cur_time - no_runX >= 1000)
  {
    f_run1X = 0;
    PORTB &= 0xF0;
    f_sbrosX = 1;
    if (EEPROM_int_read(0)!=Shtora1)
    {
     EEPROM_int_write(0, Shtora1); // адрес 0 (+2 байта)
    }
  }
  //Снимаем напряжение с катушек двигателя Z
  if (f_run1Z && cur_time - no_runZ >= 1000)
  {
    f_run1Z = 0;
    PORTD &= 0xF;
    f_sbrosZ = 1;
    if (EEPROM_int_read(2)!=Shtora2)
    {
     EEPROM_int_write(2, Shtora2); // адрес 0 (+2 байта)
    }
  }
}

 

adread
Offline
Зарегистрирован: 23.01.2018

Хорошая робота, автор молодец.

yucan
Offline
Зарегистрирован: 20.04.2015

sheff пишет:

Торопиться некуда, можно и не ждать....сама доедет и остановится.

Здравствуйте! Подскажите, по какому событию происходит останов двигателей?

И как прикрутить к проекту фотодатчик для автоматизации процесса? (закат\рассвет)

sheff
Offline
Зарегистрирован: 14.11.2017

yucan пишет:

Здравствуйте! Подскажите, по какому событию происходит останов двигателей?

И как прикрутить к проекту фотодатчик для автоматизации процесса? (закат\рассвет)


Доброй ночи. Двигатели останавливаются при нажатии любой кнопки или по достижении конечного положения.
Я еще новичок в ардуино, с фоторезистором еще не разбирался (видел обзоры на ютубе).
Вот в этой ветке мне помогли с написанием скетча, задайте вопрос там, возможно Вам подскажут.
http://arduino.ru/forum/programmirovanie/proshu-pomoshchi-problema-s-odnovremennoi-rabotoi-shagovykh-dvigatelei

trembo
trembo аватар
Offline
Зарегистрирован: 08.04.2011

Супер!
Вопрос:  Хватает ли крутящего момента для поднятия штор.
Почему задаю этот вопрос?
Этот шаговичёк куплен был лет 5 назад.
Даже два.
И даже где-то потерялись дома.
При проверке выяснилось что оба пробуксовывают внутри редуктора,
то есть мотор крутится, а вал можно остановить  при достаточно небольшом усилии.
Такие шаговики видел в кондиционерах на качающемся дефлекторе и понятно что там момент не главное.

Даже помню что один переделывал в биполярник......

Тоже думал сделать, но мои шторы в два раза длиннее.

trembo
trembo аватар
Offline
Зарегистрирован: 08.04.2011
sheff
Offline
Зарегистрирован: 14.11.2017

trembo пишет:

Супер!
Вопрос:  Хватает ли крутящего момента для поднятия штор.
Почему задаю этот вопрос?
Этот шаговичёк куплен был лет 5 назад.
Даже два.
И даже где-то потерялись дома.
При проверке выяснилось что оба пробуксовывают внутри редуктора,
то есть мотор крутится, а вал можно остановить  при достаточно небольшом усилии.
Такие шаговики видел в кондиционерах на качающемся дефлекторе и понятно что там момент не главное.

Даже помню что один переделывал в биполярник......

Тоже думал сделать, но мои шторы в два раза длиннее.

Пробуксовывать может из-за недостатка питания или от большой скорости.

У меня сейчас питание 6 вольт и на входе каждого драйвера стоят кондеры на 1000мкФ, штора едет одинаково вверх и вниз. Когда эксперементировал со скоростью было так, что вниз штора опускается быстро, а вверх даже стронуться не может - подтолкнешь, тогда тянет. Вообщем в скетче оптимальный вариант.

gzp13
Offline
Зарегистрирован: 06.04.2015

А я вот по бырику сварганил вот такой электромеханизм управления обычными шторами под управлением ардуино)

https://www.youtube.com/watch?v=Tx47Dj791JU&feature=youtu.be

sheff
Offline
Зарегистрирован: 14.11.2017

gzp13 пишет:

А я вот по бырику сварганил вот такой электромеханизм управления обычными шторами под управлением ардуино)

Прикольно. Шустренько тянет, только для моих нужд великоват малость.

gzp13
Offline
Зарегистрирован: 06.04.2015

Скорость можно регулировать в скетче, но чем медленнее тем шумнее слышно работу мотора.

sheff
Offline
Зарегистрирован: 14.11.2017

Решил добавить еще парочку фоток.
К драйверу ULN2003 идеально подходит коробочка от телефонной розетки

А вот так выглядит плата под подоконником

С обратной стороны расположилась кренка на 6 вольт

А вот так выглядят кнопки под пластиковым уголком

RizONE
Offline
Зарегистрирован: 22.03.2018

Доброго!

Проект завершен или еще делается? На работающий скетч можно глянуть?

sheff
Offline
Зарегистрирован: 14.11.2017

RizONE пишет:

Доброго!

Проект завершен или еще делается? На работающий скетч можно глянуть?

Пост #8, под схемой работающий скетч.

Bob_
Offline
Зарегистрирован: 13.07.2018

А как запрограммированы кнопки. В режиме кнопки или выключатель с фиксацией? Просто замыкают на землю при нажатии?

sheff
Offline
Зарегистрирован: 14.11.2017

Bob_ пишет:

А как запрограммированы кнопки. В режиме кнопки или выключатель с фиксацией? Просто замыкают на землю при нажатии?


Работает как кнопка, а программа отслеживает длинное или короткое нажатие.

Bob_
Offline
Зарегистрирован: 13.07.2018

А как организовано питание всей системы?

sheff
Offline
Зарегистрирован: 14.11.2017

Bob_ пишет:

А как организовано питание всей системы?

Обычный адаптер на 9 вольт.

Вот ссылка на али https://ru.aliexpress.com/item/1pcs-AC-100V-240V-Converter-Adapter-DC-9V-1A-Power-Supply-EU-Plug-DC-5-5mm/32769484388.html?spm=a2g0s.9042311.0.0.274233ed35FFzP

Bob_
Offline
Зарегистрирован: 13.07.2018

sheff пишет:

Bob_ пишет:

А как организовано питание всей системы?

Обычный адаптер на 9 вольт.

На vin как я понимаю. Тогда получается 9 вольт идет и на контроллеры моторов? 

sheff
Offline
Зарегистрирован: 14.11.2017

Bob_ пишет:

sheff пишет:

Bob_ пишет:

А как организовано питание всей системы?

Обычный адаптер на 9 вольт.

На vin как я понимаю. Тогда получается 9 вольт идет и на контроллеры моторов? 

На моторы питание идет через кренку на 6 вольт.

Bob_
Offline
Зарегистрирован: 13.07.2018

Собрал все по схеме. Все работает, но есть странность. Провожу калибровку обоих штор ноль наверху. Перехожу в рабочий режим. При нажатии вниз - едет только первая штора. Доезжает до низа. Вторая стоит. При нажатии вверх - первая нормально, а вторая заматывается на установленное количество витков. То есть получается что у одной шторы ноль наверху, а у второй ноль внизу. Что то не так в скетче?

sheff
Offline
Зарегистрирован: 14.11.2017

Да, такая "особенность", моторы стоят зеркально. У левой шторы ноль внизу. Один раз то и надо настроить, потом всё работает нормально. 

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

sheff пишет:

RizONE пишет:

Доброго!

Проект завершен или еще делается? На работающий скетч можно глянуть?

Пост #8, под схемой работающий скетч.

Добавлю и себе в закладки

Bob_
Offline
Зарегистрирован: 13.07.2018

sheff пишет:

Один раз то и надо настроить, потом всё работает нормально. 

Ну это да. Особо не напрягает. Эх, еще бы фоторезистор прикрутить.

Nickakoi
Offline
Зарегистрирован: 27.07.2018

Хвала автору! Всё прекрасно работает, моторы поставил на 12в. Дайте совет - буду делать второй экземпляр, там где балкон. Окно большое, штора длинная, один мотор не осилит, поставлю два с разных сторон. Как подключать два мотора? 1. Два мотора, два драйвера входы объеденить и к arduino. Или 2. Два мотора запараллелить и к одному драйверу.

Bob_
Offline
Зарегистрирован: 13.07.2018

Прикрутил к скетчу датчик освещенности. Цифровой выход модуля повесил на А3

Опыта мало. Наверняка можно код сделать правильнее, но как получилось. По крайней мере работает. Утром открывает, вечером закрывает. Когда начинает двигатся, если нажать на любую кнопку, то движение остановится и не возобновляется до следующей смены состояния освещенности. И чуть подправил скетч. Нулевая точка обоих штор теперь наверху. Если надо сделать на одном моторе обратное вращение, надо зазеркалить подключение самого мотора.

//**********  (РЕЖИМ 1-ШАГ) Крутим с помощью сдвига --рабочая - крутит туда сюда без потери шагов - ускоряет - отключает катушки после бездействия
//PORTB - 8, 9, 10, 11 - Шаговик.  
//PORTD - 4, 5, 6, 7 - Шаговик.  
// 12-кнопка Menu
// 2-кнопка UP
// 3-кнопка DOWN
// A1-Светодиод 1й штор
// А0-Светодиод 2й штор
// А2-Пищалка
// А3-Фотомодуль, цифровой выход
#include <EEPROM.h> 
#include <CyberLib.h>
#define uskor 3 //Задаем ускорение
//Здесь устанавливаем максимальное кол. шагов для штор
#define max_Sht1 29500
#define max_Sht2 29500
#define PH_PIN 17    //цифровой выход фотомодуля на А3 

byte n1 = 1;// Сдвигаем 1 бит
byte n3 = 0x10;
bool f_timX = 0;
bool f_timZ = 0;
 
byte sped_Xt = uskor;//Начальная скорость
byte sped_X = 0; //Ускорение
byte sped_Zt = uskor;//Начальная скорость
byte sped_Z = 0; //Ускорение

bool f_run1X = 0;//Сброс после остановки 2 переменные.
unsigned long no_runX; //Переменная для прошедшего периода
 
bool f_run1Z = 0;//Сброс после остановки 2 переменные.
unsigned long no_runZ; //Переменная для прошедшего периода
// Переменные для кн.Menu
bool kn_menu;
bool f_menu;
bool f_Mpush;
bool f_Md;
uint8_t Menu = 1;
uint8_t temp_Menu;
bool kalib;
unsigned long menu_dreb;
unsigned long menu_klik;
// Переменные для кн.Up
bool kn_Up;
bool f_Up;
bool state_Up;
bool _UP;
uint32_t Up_dreb;
// Переменные для кн.Down
bool kn_Down;
bool f_Down;
bool state_Down;
bool _Down;
uint32_t Down_dreb;

// переменные для фотомодуля
byte timePh = 100; // время устойчивого состояния фотомодуля
byte  phCount1= 0; 
byte  phCount2= 0;  // счетчики подтверждений состояния  
bool old_Ph;
bool new_Ph; 

//сбрасываем UP\Down 
bool f_sbrosZ = 1;
bool f_sbrosX = 1;

uint32_t cur_time;//Миллис читаем один раз
uint32_t blink_time;//Мигаем в режиме калибровки
 
int Shtora1;
int Shtora2;
const int ton = 16;//пищалка
// чтение
int EEPROM_int_read(int addr) {   
  byte raw[2];
  for(byte i = 0; i < 2; i++) raw[i] = EEPROM.read(addr+i);
  int &num = (int&)raw;
  return num;
}
// запись
void EEPROM_int_write(int addr, int num) {
  if (EEPROM_int_read(addr)!= num){//если сохраняемое отличается
  byte raw[2];
  (int&)raw = num;
  for(byte i = 0; i < 2; i++) EEPROM.write(addr+i, raw[i]);
}
}
 
void setup() {
  // DDRB пин, 8,9,10,11 - Шаговик, pin 12- вход, 13- Выход
  DDRB = DDRB | B00101111;
  // pin 8,9,10,11,13 - выход в 0 а входы pin 12, - 0
  PORTB = B00000000;
  //  DDRD, подключенный к двигателю pin 4,5,6,7 как выход,pin2,3 Выход
  DDRD = DDRD | B11110000;
  // pin 4,5,6,7 - выход в 0 а входы pin 2,3 - 0
  PORTD = B00000000;//;
/////
  
//////  
  D14_Out;  // Led_1
  D14_Low;
  D15_Out;  // Led_2
  D15_Low;
    pinMode(ton,OUTPUT);//пищалка
  //Serial.begin(9600);
  // Инициализировать TIMER1
  StartTimer1(Time_Closk, 2800);
      Shtora1 = EEPROM_int_read(0);
      Shtora2 = EEPROM_int_read(2);
}
void Beep() //короткий звук, переключение шторы
{
  tone(ton,500,500);
  delay(200);
  noTone(ton);
}
void Beep_long()  //длинный звук, вход и выход из режима калибровки "0"
{
  tone(ton,200,1000);
  delay(200);
  noTone(ton);
}
 
void Time_Closk() // Функция прерывания таймера
{
  f_timX = 1;
  f_timZ = 1;
}
 
//Функция вращения  dvigatel 1
void RunX (bool perem_X)
{
  f_sbrosX = 0;
  f_timX = 0;
  if (perem_X) {
    n1 = (n1 >> 1) | (n1 << 3); //Сдвигаем
    --Shtora1;
  }
  else {
    n1 = (n1 << 1) | (n1 >> 3); //Сдвигаем
    ++Shtora1;
  }
  n1 = 0x0F & n1; //Маскируем кнопки
  PORTB = (PORTB & 0xF0) | n1; //Очищаем Младшие биты и пишем туда n1
}
 
//Функция dvigatel 3
void RunZ (bool perem_Z)
{
  f_sbrosZ = 0;
  f_timZ = 0;
  if (perem_Z) {
    n3 = (n3 >> 1) | (n3 << 3); //Сдвигаем
    --Shtora2;
  }
  else {
    n3 = (n3 << 1) | (n3 >> 3); //Сдвигаем
    ++Shtora2;
  }
  n3 = 0xF0 & n3;//Маскируем
  PORTD = (PORTD & 0xF) | n3; //Очищаем старшие биты и пишем туда n3
}
 
void loop() {
 
  cur_time = millis();
  ///////////////////Проверка кнопки МЕНЮ - АНТИДРЕБЕЗГ
  if (D12_Read && !f_menu)
  {
    menu_dreb = cur_time;
    f_menu = 1;
  }
  if (!D12_Read)
  {
    kn_menu = 0;
    f_menu = 0;
  }
 
  if (f_menu && cur_time - menu_dreb >= 20)
  {
    kn_menu = 1;
    if (!f_Mpush) {
      menu_klik = cur_time;
      f_Mpush = 1;
    }
 
  }
//Был клик
if (f_Mpush && !kn_menu && cur_time - menu_klik < 1000) {
   if (_UP || _Down) {
    _UP = 0;
    _Down = 0;
  }
  else Menu++, Beep();     // Меняем
  if (Menu > 3) Menu = 1;
  f_Mpush = 0;
}
//Было нажатие
else if (f_Mpush && !kn_menu && cur_time - menu_klik > 1000) {
  Beep_long();
  kalib = !kalib; // Включаем калибровку
  f_Mpush = 0;
}  ///////////////////////Проверка кнопки UP - АНТИДРЕБЕЗГ
  if (D2_Read != f_Up) { //Если сигнал изменился
    f_Up = !f_Up;
    Up_dreb = cur_time;
  }
  if (kn_Up == D2_Read && cur_time - Up_dreb > 20) kn_Up = !D2_Read;
  // Было нажатие
  if (kn_Up && !state_Up) {
    if (_UP || _Down) {
      _UP = 0;
      _Down = 0;
      state_Up = 1;
    }
    else {
      _UP = !_UP;    // Меняем значение
      state_Up = 1;
    }
  }
  if (!kn_Up)state_Up = 0; // Отпустили
  ///////////////////////Проверка кнопки DOWN - АНТИДРЕБЕЗГ
  if (D3_Read != f_Down) { //Если сигнал изменился
    f_Down = !f_Down;
    Down_dreb = cur_time;
  }
  if (kn_Down == D3_Read && cur_time - Down_dreb > 20) kn_Down = !D3_Read;
  // Было нажатие
  if (kn_Down && !state_Down) {
    if (_UP || _Down) {
      _UP = 0;
      _Down = 0;
      state_Down = 1;
    }
    else {
      _Down = !_Down;    // Меняем значение
      state_Down = 1;
    }
  }
  if (!kn_Down)state_Down = 0; // Отпустили
  //////////////////////// С кнопками закончили продолжаем логику
  if (!kalib)
  {
    if (Menu != temp_Menu) {
      temp_Menu = Menu;
      switch (Menu) {
          case 1: D14_High; D15_High; break;
          case 2: D14_Low; D15_High; break;
          case 3: D14_High; D15_Low; break;
      }
    }
  }
  else {
    if (cur_time - blink_time >= 300)
    {
      blink_time = cur_time;
      switch (Menu) {
        case 1: D14_Inv; D15_Inv; break;
        case 2: D14_Low; D15_Inv; break;
        case 3: D14_Inv; D15_Low; break;
      }
    }
  }
  /////////////////////////////////
 
  // блок фотомодуля

    new_Ph = D17_Read;
    if ((new_Ph ==LOW)&&(old_Ph != new_Ph)) {
     phCount1++;
     }
     else
     phCount1=0;
     
       if ( phCount1 >= timePh) {    
        old_Ph = new_Ph;
        phCount1 = 0;
        _UP = 1;
        _Down = 0;
       }


  if ((new_Ph ==HIGH)&&(old_Ph != new_Ph)) {
     phCount2++;
     }
     else
     phCount2= 0;
     
       if ( phCount2 >= timePh) {    
        old_Ph = new_Ph;
        phCount2= 0;
        _Down = 1;
        _UP = 0;
       }
  
       
 
  /////////////////////////// Запуск 1го двигателя если " perem_X != 0 "
  if (f_timX) {
       
   if (_UP || _Down) {
      if (Menu != 2) {
        if (!sped_X) {
          if (!kalib) { //Калибровка отк.
            if (_Down && Shtora1 < max_Sht1) {
              RunX(0);
            }
            if (_UP && Shtora1 > 0) {
              RunX(1);
            }
            
          }
            
          else { //Калибровка вкл.
            if (_Down) {
              Shtora1 = 0;
              RunX(0);
            }
            if (_UP) {
              Shtora1 = 1;
              RunX(1);
            }
          }
          //Три поверки для разгона
          if (sped_Xt > 0) {
            --sped_Xt;
            sped_X = sped_Xt;
            // f_timX = 0;
          }
        }
        else {
          --sped_X;
          f_timX = 0;
        }
      }
    }////
    else {
      sped_Xt = uskor;
      sped_X = 0;
    }
  }
  else { //Для снятия напряжения
    f_run1X = 1;
    no_runX = cur_time;
  }
  /////////////////Запуск 3го двигателя если " perem_Z != 0 "
  if (f_timZ){
    if (_UP || _Down) {
      if (Menu != 3) {
        if (!sped_Z) {
          if (!kalib)//Калибровка отк.
          {
            if (_Down && Shtora2 < max_Sht2) {
              RunZ(0);
            }
            if (_UP && Shtora2 > 0) {
              RunZ(1);
            }
            }
             
          else {//Калибровка Вкл.
            if (_Down) {
              Shtora2 = 0;
              RunZ(0);
            }
            if (_UP) {
              Shtora2 = 1;
              RunZ(1);
            }
           }
           //Три поверки для разгона
          if (sped_Zt > 0) {
            --sped_Zt;
            sped_Z = sped_Zt;
            f_timZ = 0;
          }
        }
        else {
          --sped_Z;
          f_timZ = 0;
        }
      }
    }////
    else {
      sped_Zt = uskor;
      sped_Z = 0;
    }
  }
  else { //Для снятия напряжения
    f_run1Z = 1;
    no_runZ = cur_time;
  }
  //Возврат по достижению конечной точки
  if (f_sbrosZ && f_sbrosX) {
    _UP = 0;
    _Down = 0;
    }
  //Снимаем напряжение с катушек двигателя X
  if (f_run1X && cur_time - no_runX >= 1000)
  {
    f_run1X = 0;
    PORTB &= 0xF0;
    f_sbrosX = 1;
    if (EEPROM_int_read(0)!=Shtora1)
    {
     EEPROM_int_write(0, Shtora1); // адрес 0 (+2 байта)
    }
  }
  //Снимаем напряжение с катушек двигателя Z
  if (f_run1Z && cur_time - no_runZ >= 1000)
  {
    f_run1Z = 0;
    PORTD &= 0xF;
    f_sbrosZ = 1;
    if (EEPROM_int_read(2)!=Shtora2)
    {
     EEPROM_int_write(2, Shtora2); // адрес 0 (+2 байта)
    }
  }
}

PS У меня одна штора шире и соответственно тяжелее чем вторая. Поэтому пришлось немного уменьшить скорость, а то были пропуски шагов. В авторском варианте 2,2 мс, у меня 2,8 мс. Тут можно поиграться при желании.

yucan
Offline
Зарегистрирован: 20.04.2015

Bob_ пишет:

Прикрутил к скетчу датчик освещенности. Цифровой выход модуля повесил на А3

На  BH1750 не похож. Что за датчик?

yucan
Offline
Зарегистрирован: 20.04.2015

LPC810 похоже

Bob_
Offline
Зарегистрирован: 13.07.2018

Модуль с Алиэкспресса. https://ru.aliexpress.com/item/Photosensitive-Sensor-Module-Light-Detection-Module-for-Arduino/32248249658.html?spm=a2g0s.9042311.0.0.274233edYVnL7B

Не важно какой модуль. Надо только что бы был цифровой выход. Этот дает 1 - днем, 0 - ночью.

alex1978
alex1978 аватар
Offline
Зарегистрирован: 09.09.2017

Отлично, надо тоже забабахать

ronixx
ronixx аватар
Offline
Зарегистрирован: 20.12.2018

gzp13 пишет:

А я вот по бырику сварганил вот такой электромеханизм управления обычными шторами под управлением ардуино)

https://www.youtube.com/watch?v=Tx47Dj791JU&feature=youtu.be


Как реализовали крепление штор к шаговым ? Сбросьте фото пожалуйста
artur.gromyko@yandex.ru

Vlad55
Offline
Зарегистрирован: 27.03.2019

Двигатели останавливаются по достижении конечного положения.как вы нашли конечное положение шторы

ivankd2
Offline
Зарегистрирован: 24.09.2020

Всем привет.Собираюсь сделать такие же шторы. Купил шаговые 28ИНО-48 на 12вольт,но они тоже как то не айс тянут. По документации эти шаговики на 400 грамм тяги. Вытащил перемычку с драйвера и запитал 12в поставив + на 4-ю ногу драйвера. Стал тянуть 700гр. Но пришла идея установить вместо шаговых горелые микросервоприводы SG90. По тяге они аж на 4кг идут и на 5 вольт крутят довольно таки быстро. На одну минуту работы, думаю их хватит,что бы не перегрелись. Есть еще горелый серво MG995 на 7кг,но он жутко шумный. Только вот осталось крепление и скетч переделать... Подсобите пожалуйста со скетчем)

Xumuk
Xumuk аватар
Offline
Зарегистрирован: 03.03.2016

Vlad55 пишет:
Двигатели останавливаются по достижении конечного положения.как вы нашли конечное положение шторы

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