Прошу помощи (проблема с одновременной работой шаговых двигателей)

vosara
vosara аватар
Offline
Зарегистрирован: 08.02.2014
Немножко на мой взгляд улутшил код. Теперь при входе в режим КАЛИБРОВКИ, в зависимости от режима меню - мигает тот светодиод - который ми калибруем или оба.
До этого было не понятно в каком режиме мы находимся.
//**********  (РЕЖИМ 1-ШАГ) Крутим с помощью сдвига --рабочая - крутит туда сюда без потери шагов - ускоряет - отключает катушки после бездействия
//PORTB - 8, 9, 10, 11 - Шаговик. && 12-кнопка Menu \ 13-Светодиод 1й штор.
//PORTD - 4, 5, 6, 7 - Шаговик. && 2-кнопка UP \ 3-кнопка DOWN
// А0-Светодиод 2й штор..

#include <CyberLib.h>
//Задаем ускорение
#define uskor 3
byte n1 = 1;// Сдвигаем 1 бит
byte n3 = 0x10;
byte f_tim = 0;
byte sped_Xt = uskor;//Начальная скорость
byte sped_X = 0; //Ускорение
byte sped_Zt = uskor;//Начальная скорость
byte sped_Z = 0; //Ускорение

bool f_run1X = 0;//Сброс после остановки 3 переменные.
bool f_run2X = 0;
unsigned long no_runX; //Переменная для прошедшего периода

bool f_run1Z = 0;//Сброс после остановки 3 переменные.
bool f_run2Z = 0;
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;

uint32_t sbros;
bool f_sbros;
uint32_t cur_time;
uint32_t blink_time;
bool f_blink;

int Shtora1 = 50;// количество шагов для полного закрытия шторы 1;
int Shtora2 = 34;// количество шагов для полного закрытия шторы 2


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_2
  D14_Low;
  Serial.begin(9600);
  // Инициализировать TIMER1
  noInterrupts (); // отключить все прерывания
  TCCR1A = 0;
  TCCR1B = 0;
  TCNT1 = 0;
  OCR1A = 125; // сравнить регистр (скорость!!!(2ms=125 - если медленнее - УВЕЛИЧИВАЕМ)
  TCCR1B |= (1 << WGM12); // Режим СТС
  TCCR1B |= (1 << CS12); // 256 делитель
  TIMSK1 |= (1 << OCIE1A ); // включить таймер сравнить прерываний
  interrupts(); // включить все прерывания
}

ISR (TIMER1_COMPA_vect) // Функция прерывания таймера
{
  // Serial.println(f_tim);
  f_tim = B1111;
}

//Функция вращения  dvigatel 1
void RunX (bool perem_X)
{
  f_tim &= B1110;
  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_tim &= B1011;
  if (perem_Z) {
    n3 = (n3 >> 1) | (n3 << 3); //Сдвигаем
    --Shtora2;
  }
  else {
    n3 = (n3 << 1) | (n3 >> 3); //Сдвигаем
    ++Shtora2;
  }
  n3 = 0xF0 & n3;//Маскируем
  PORTD = (PORTD & 0xF) | n3; //Очищаем старшие биты и пишем туда n3
  //Serial.println(n3);
}

void loop() {

  static bool tem_UP;
  if (_UP != tem_UP) {
    tem_UP = _UP;
    Serial.print("UP- "); Serial.println(_UP);
  }
  static bool tem_Down;
  if (_Down != tem_Down)
  {
    tem_Down = _Down;
    Serial.print("Down- "); Serial.println(_Down);
  }

  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 < 500) {
    if (_UP || _Down) {
      _UP = 0;
      _Down = 0;
    }
    else Menu++;     // Меняем
    if (Menu > 3) Menu = 1;
    f_Mpush = 0;
  }

  else if (f_Mpush && !kn_menu && cur_time - menu_klik > 500) {
    kalib = !kalib; // Включаем калибровку
    Serial.print("kalib- "); Serial.println(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;
      Serial.print("Menu- "); Serial.println(Menu);
      switch (Menu) {
        case 1: D13_High; D14_Low; break;
        case 2: D13_Low; D14_High; break;
        case 3: D13_High; D14_High; break;
      }
    }
  }
  else {
    if (cur_time - blink_time >= 300)
    {
      blink_time = cur_time;
      switch (Menu) {
        case 1: D13_Inv; D14_Low; break;
        case 2: D13_Low; D14_Inv; break;
        case 3: D13_Inv; D14_Inv; break;
      }
    }
  }


  /////////////////////////// Запуск 1го двигателя если " perem_X != 0 "
  //if (!kalib) {
  if (_UP || _Down) {
    if (Menu != 2) {
      if (f_tim & (1 << 0)) {
        if (!sped_X) {

          if (!kalib)//Калибровка отк.
          {
            if (_UP && Shtora1 < 50) {//3592
              RunX(0);
              Serial.print("Shtora1- "); Serial.println(Shtora1);
            }
            if (_Down && Shtora1 > 0) {
              RunX(1);
              Serial.print("Shtora1- "); Serial.println(Shtora1);
            }
          }
          else { //Калибровка вкл.
            if (_UP) {
              Shtora1 = 0;
              RunX(0);
              Serial.print("Shtora1- "); Serial.println(Shtora1);
            }
            if (_Down) {
              Shtora1 = 1;
              RunX(1);
              Serial.print("Shtora1- "); Serial.println(Shtora1);
            }
          }

          if (sped_Xt > 0) {
            --sped_Xt;
            sped_X = sped_Xt;
          }
        }
        else {
          --sped_X;
          f_tim &= B1110;
        }
      }////
      else {
        f_run2X = 1;
        no_runX = cur_time;
      }
    }
  }
  else {
    sped_Xt = uskor;
    sped_X = 0; // для пропуска 1го тика
  }
  //}

  /////////////////Запуск 3го двигателя если " perem_Z != 0 "
  //if (!kalib) {
  if (_UP || _Down) {
    if (Menu != 1) {
      if (f_tim & (1 << 2)) {
        if (!sped_Z) {

          if (!kalib)//Калибровка отк.
          {
            if (_UP && Shtora2 < 34) {//3475
              RunZ(0);
              Serial.print("Shtora2- "); Serial.println(Shtora2);
            }
            if (_Down && Shtora2 > 0) {
              RunZ(1);
              Serial.print("Shtora2- "); Serial.println(Shtora2);
            }
          }
          else {//Калибровка Вкл.
            if (_UP) {
              Shtora2 = 0;
              RunZ(0);
              Serial.print("Shtora2- "); Serial.println(Shtora2);
            }
            if (_Down) {
              Shtora2 = 1;
              RunZ(1);
              Serial.print("Shtora2- "); Serial.println(Shtora2);
            }
          }

          if (sped_Zt > 0) {
            --sped_Zt;
            sped_Z = sped_Zt;
          }
        }
        else {
          --sped_Z;
          f_tim &= B1011;
        }
      }////
      else {
        f_run2Z = 1;
        no_runZ = cur_time;
      }
    }
  }
  else {
    sped_Zt = uskor;
    sped_Z = 0; // для пропуска 1го тика
  }

  //Если достигли конца сбрасываем UP\Down
  if (f_tim != 15)
  {
    sbros = cur_time;
    f_sbros = 0;
  }
  if (!f_sbros && cur_time - sbros > 1500)
  {
    f_sbros = 1;
    _UP = 0;
    _Down = 0;
  }

  //Снимаем  напряжение с катушек двигателя X
  if (f_run2X && cur_time - no_runX >= 1000)// закончилось ли время
  {
    f_run2X = 0;
    PORTB &= 0xF0;
  }

  //Снимаем напряжение с катушек двигателя Z
  if (f_run2Z && cur_time - no_runZ >= 1000)// закончилось ли время
  {
    f_run2Z = 0;
    PORTD &= 0xF;
  }
}

 

 

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

vosara пишет:

Немножко на мой взгляд улутшил код. Теперь при входе в режим КАЛИБРОВКИ, в зависимости от режима меню - мигает тот светодиод - который ми калибруем или оба.
До этого было не понятно в каком режиме мы находимся.

А оба зачем? Две шторы одновременно смысла нет калибровать. У нас самое главное не работает.....моторы не крутятся и кренка сильно греется!!! В симуляторе светодиоды бегают прикольно, а реальная сборка работать не хочет. Первый скетч работает изумительно, для режима калибровки самое то....пока держишь кнопку - мотор крутится, отпустил - остановился. Вот этот скетч. 

//**********  (РЕЖИМ 1-ШАГ) Крутим с помощью сдвига --рабочая - крутит туда сюда без потери шагов - ускоряет - отключает катушки после бездействия
//PORTB - 8, 9, 10, 11 - Шаговик. && 12, 13 - Вход сигнал от 2х кнопок (влево - вправо)
//PORTD - 4, 5, 6, 7 - Шаговик. && 2, 3 - остаются для переферии
#define uskor 2 //Задаем ускорение
byte n1 = 1;// Сдвигаем 1 бит
byte n3 = 0x10;
byte f_tim = 0;
long int perem_X = 0;
long int perem_Z = 0;
byte sped_Xt = uskor;//Начальная скорость
byte sped_X = 0; //Ускорение
byte sped_Zt = uskor;//Начальная скорость
byte sped_Z = 0; //Ускорение
 
bool f_run1X = 0;//Сброс после остановки 3 переменные.
bool f_run2X = 0;
unsigned long no_runX; //Переменная для прошедшего периода
 
bool f_run1Z = 0;//Сброс после остановки 3 переменные.
bool f_run2Z = 0;
unsigned long no_runZ; //Переменная для прошедшего периода
 
 
void setup() {
  //  пин, 8, 9, 10, 11 - Шаговик, 2, 3- переферия
  DDRB = 0xCF;
  //Устанавлюем значение выходов в 0 а входы - подтягивающий резистор
  PORTB = 0x30;
  //   PORTD, подключенный к двигателю 3 как выход, Две кнопки с подтяжкой pin2-3
  DDRD = DDRD | B11110000;
  //Устанавлюем значение выходов PORTD в 0
  PORTD = PORTD | B00001100;//x0F;
 
 // Serial.begin(9600);
 
  // Инициализировать TIMER1
  noInterrupts (); // отключить все прерывания
  TCCR1A = 0;
  TCCR1B = 0;
  TCNT1 = 0;
  OCR1A = 125; // сравнить регистр (скорость!!!(2ms=125 - если медлиннее - УВЕЛИЧУЕМ)
  TCCR1B |= (1 << WGM12); // Режим СТС
  TCCR1B |= (1 << CS12); // 256 делитель
  TIMSK1 |= (1 << OCIE1A ); // включить таймер сравнить прерываний
  interrupts(); // включить все прерывания
}
 
ISR (TIMER1_COMPA_vect) // Функция прерывания таймера
{
//   Serial.println(f_tim);
  f_tim = B1111;
}
 
//Функция вращения  dvigatel 1
void RunX ()
{
  f_tim &= B1110;
  if (perem_X > 0) {
    n1 = (n1 >> 1) | (n1 << 3); //Сдвигаем
    --perem_X;
  }
  else {
    n1 = (n1 << 1) | (n1 >> 3); //Сдвигаем
    ++perem_X;
  }
  n1 = 0x0F & n1; //Маскируем кнопки
  PORTB = (PORTB & 0xF0) | n1; //Очищаем Младшие биты и пишем туда n1
}
 
//Функция dvigatel 3
void RunZ ()
{
  f_tim &= B1011;
  if (perem_Z > 0) {
    n3 = (n3 >> 1) | (n3 << 3); //Сдвигаем
    --perem_Z;
  }
  else {
    n3 = (n3 << 1) | (n3 >> 3); //Сдвигаем
    ++perem_Z;
  }
  n3 = 0xF0 & n3;//Маскируем
  PORTD = (PORTD & 0xF) | n3; //Очищаем старшие биты и пишем туда n3
  //Serial.println(n3);
}
 
void loop() {
 
  //Кнопки 1 и 2 служат для демонстрации работы. Считается замкнутой при подаче МИНУСА
  if ((PIND & (1 << 3))) //проверяем кнопку 1 - нажали? Можно использовать if(!digitalRead(2))
  {
    //Задаем количество шагов для дв.- ВПРАВО "perem_X = Количеству шагов;"
    perem_X = 10;
    perem_Z = -10;
  }
  //else perem_X = 0; // ВНИМАНИЕ если задаём количество шагов - эту строчку удаляем!!!
 
  if ((PIND & (1 << 2))) //проверяем кнопку 2 - нажали? Можно использовать if(!digitalRead(3))
  {
    //Задаем количество шагов для дв.- ВЛЕВО "perem_X = -Количеству шагов;"
    perem_X = -10;
    perem_Z = 10;
  }
 
  /////////////////////////// Запуск 1го двигателя если " perem_X != 0 "
  if (perem_X != 0) {
    f_run1X = 1;
    f_run2X = 0;
 
    if (f_tim & (1 << 0)) {
      if (!sped_X) {
        RunX();
        if (sped_Xt > 0) {
          --sped_Xt;
          sped_X = sped_Xt;
        }
      }
      else {
        --sped_X;
        f_tim &= B1110;
      }
    }
  }
  else {
    sped_Xt = uskor;
    sped_X = 0; // для пропуска 1го тика
  }
 
  /////////////////Запуск 3го двигателя если " perem_Z != 0 "
 
  if (perem_Z != 0) {
    f_run1Z = 1;
    f_run2Z = 0;
 
    if (f_tim & (1 << 2)) {
      if (!sped_Z) {
        RunZ();
        if (sped_Zt > 0) {
          --sped_Zt;
          sped_Z = sped_Zt;
        }
      }
      else {
        --sped_Z;
        f_tim &= B1011;
      }
    }
  }
  else {
    sped_Zt = uskor;
    sped_Z = 0; // для пропуска 1го тика
  }
 
  //Снимаеммаем напряжение с катушек двигателя X
  if (f_run1X && perem_X == 0) //Служит для запуска отключения катушек
  {
    f_run1X = 0;
    f_run2X = 1;
    no_runX = millis();
  }
 
  if (f_run2X && millis() - no_runX >= 1000)// Проверяем закончилось ли время
  {
    f_run2X = 0;
    //Снимаем напряжение с катушек
    PORTB &= 0xF0;
  }
 
  //Снимаеммаем напряжение с катушек двигателя Z
  if (f_run1Z && perem_Z == 0) //Служит для запуска отключения катушек
  {
    f_run1Z = 0;
    f_run2Z = 1;
    no_runZ = millis();
  }
 
  if (f_run2Z && millis() - no_runZ >= 1000)// Проверяем закончилось ли время
  {
    f_run2Z = 0;
    //Снимаем напряжение с катушек
    PORTD &= 0xF;
  }
}

 

 

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

По-поводу калибровки я считаю, что правильней калибровать "0" вверху, т.е. начальное положение из которого штора разматывается и чтобы штора не замоталась в барабан.

vosara
vosara аватар
Offline
Зарегистрирован: 08.02.2014

Вот скетч провери его на живой ардуине, правда на однм двигателе,  крутит отключает, ничего не греется. Проблему скорости давал Сериал, пришлось его удалить. В принцепе он нужен только для настройки. А так пока искал причину по скорости то таймер поменял и так помелочам. Ммаксимальную высоту будете ставить в самом начале _ там написано

//**********  (РЕЖИМ 1-ШАГ) Крутим с помощью сдвига --рабочая - крутит туда сюда без потери шагов - ускоряет - отключает катушки после бездействия
//PORTB - 8, 9, 10, 11 - Шаговик. && 12-кнопка Menu \ 13-Светодиод 1й штор.
//PORTD - 4, 5, 6, 7 - Шаговик. && 2-кнопка UP \ 3-кнопка DOWN
// А0-Светодиод 2й штор..

#include <CyberLib.h>
#define uskor 5 //Задаем ускорение
//Здесь устанавливаем максимальное кол. шагов для штор
#define max_Sht1 5000
#define max_Sht2 5000

byte n1 = 1;// Сдвигаем 1 бит
byte n3 = 0x10;
bool f_timX = 0;
bool f_timZ = 0;

//long int perem_X = 0;
//long int perem_Z = 0;
byte sped_Xt = uskor;//Начальная скорость
byte sped_X = 0; //Ускорение
byte sped_Zt = uskor;//Начальная скорость
byte sped_Z = 0; //Ускорение

bool f_run1X = 0;//Сброс после остановки 2 переменные.
//bool f_run1X = 0;
unsigned long no_runX; //Переменная для прошедшего периода

bool f_run1Z = 0;//Сброс после остановки 2 переменные.
//bool f_run1Z = 0;
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

uint32_t sbros;
bool f_sbros;

uint32_t cur_time;//Миллис читаем один раз
uint32_t blink_time;//Мигаем в режиме калибровки

int Shtora1 = 50;// количество шагов для полного закрытия шторы 1;
int Shtora2 = 34;// количество шагов для полного закрытия шторы 2

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_2
  D14_Low;
  //Serial.begin(9600);
  // Инициализировать TIMER1
   StartTimer1(Time_Closk, 2000);
}

void Time_Closk() // Функция прерывания таймера
{
  f_timX = 1;
  f_timZ = 1;
}

//Функция вращения  dvigatel 1
void RunX (bool perem_X)
{
  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_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 < 500) {
    if (_UP || _Down) {
      _UP = 0;
      _Down = 0;
    }
    else Menu++;     // Меняем
    if (Menu > 3) Menu = 1;
    f_Mpush = 0;
  }

  else if (f_Mpush && !kn_menu && cur_time - menu_klik > 500) {
    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: D13_High; D14_Low; break;
        case 2: D13_Low; D14_High; break;
        case 3: D13_High; D14_High; break;
      }
    }
  }
  else {
    if (cur_time - blink_time >= 300)
    {
      blink_time = cur_time;
      switch (Menu) {
        case 1: D13_Inv; D14_Low; break;
        case 2: D13_Low; D14_Inv; break;
        case 3: D13_Inv; D14_Inv; break;
      }
    }
  }

  /////////////////////////// Запуск 1го двигателя если " perem_X != 0 "
  if (f_timX) {
    if (_UP || _Down) {
      if (Menu != 2) {
        if (!sped_X) {
          if (!kalib) { //Калибровка отк.
            if (_UP && Shtora1 < max_Sht1) {//3592
              RunX(0);
            }
            if (_Down && Shtora1 > 0) {
              RunX(1);
            }
          }
          else { //Калибровка вкл.
            if (_UP) {
              Shtora1 = 0;
              RunX(0);
            }
            if (_Down) {
              Shtora1 = 1;
              RunX(1);
            }
          }
        }
        else if (sped_Xt > 0) {
          --sped_Xt;
          sped_X = sped_Xt;
          f_timX = 0;
        }
        else {
          --sped_X;
          f_timX = 0;
        }
      }
    }////
    
  }
  else {
    f_run1X = 1;
    no_runX = cur_time;
    sbros = cur_time;
    f_sbros = 1;
    sped_Xt = uskor;
    sped_X = 0; // для пропуска 1го тика
  }
  /////////////////Запуск 3го двигателя если " perem_Z != 0 "
  //if (!kalib) {
  if (f_timZ) {
    if (_UP || _Down) {
      if (Menu != 1) {

        if (!sped_Z) {

          if (!kalib)//Калибровка отк.
          {
            if (_UP && Shtora2 < max_Sht2) {//3475
              RunZ(0);
            }
            if (_Down && Shtora2 > 0) {
              RunZ(1);
            }
          }
          else {//Калибровка Вкл.
            if (_UP) {
              Shtora2 = 0;
              RunZ(0);
            }
            if (_Down) {
              Shtora2 = 1;
              RunZ(1);
            }
          }
        }
        else if (sped_Zt > 0) {
          --sped_Zt;
          sped_Z = sped_Zt;
          f_timZ = 0;
        }
      }
      else {
        --sped_Z;
        f_timZ = 0;
      }
    }////
  }
  else {
    f_run1Z = 1;
    no_runZ = cur_time;
    sbros = cur_time;
    f_sbros = 1;
    sped_Zt = uskor;
    sped_Z = 0; // для пропуска 1го тика
  }

  //Снимаем напряжение с катушек двигателя X
  if (f_run1X && cur_time - no_runX >= 1000)// закончилось ли время
  {
    f_run1X = 0;
    PORTB &= 0xF0;
  }

  //Снимаем напряжение с катушек двигателя Z
  if (f_run1Z && cur_time - no_runZ >= 1000)// закончилось ли время
  {
    f_run1Z = 0;
    PORTD &= 0xF;
  }
}

 

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

Добрый вечер. Спасибо, сейчас буду проверять. Я тут немного со схемой повозился, 1 светодиод повесил на 14 пин, 2 светодиод на 15 пин, а на 16 пин прицепил пищалку(при навигации по меню удобно). Можно добавить в скетч?
 

void Beep() //короткий звук, переключение шторы
{
  tone(ton,500,500);
  delay(200);
  noTone(ton);
}
void Beep_long()  //длинный звук, вход и выход из режима калибровки "0"
{
  tone(ton,200,1000);
  delay(200);
  noTone(ton);
}

 

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

Проверил скетч...
Со второй шторой всё получилось хорошо, методом тыка настроил высоту - 27500. Ездит хорошо. Полное закрытие или открытие занимает 55 секунд. Немножко не понял в режиме калибровки....как только в него входишь, штору сразу затягивает в барабан, кнопками UP и DOWN возвращаешь на нужное место. С моргающим светодиодом прикольно!
С первой шторой не получится настроить, потому что она должна работать в обратном порядке...моторы стоят не симметрично, здесь нужно инверсию делать.

vosara
vosara аватар
Offline
Зарегистрирован: 08.02.2014

Вот сделал инверсию попробуйте.  Поповоду скорости в стр.72 - StartTimer1(Time_Closk, 2000); можете поиграться с числом, сейчас стоит 2 мс.  на меньшем значении у меня стабильно не работает, а у Вас может и будет. По поводу калибровки: при первом входе он сам движется  или после установки, при втором заходе тоже? 

//**********  (РЕЖИМ 1-ШАГ) Крутим с помощью сдвига --рабочая - крутит туда сюда без потери шагов - ускоряет - отключает катушки после бездействия
//PORTB - 8, 9, 10, 11 - Шаговик. && 12-кнопка Menu \ 13-Светодиод 1й штор.
//PORTD - 4, 5, 6, 7 - Шаговик. && 2-кнопка UP \ 3-кнопка DOWN
// А0-Светодиод 2й штор..

#include <CyberLib.h>
#define uskor 2 //Задаем ускорение
//Здесь устанавливаем максимальное кол. шагов для штор
#define max_Sht1 5000
#define max_Sht2 5000

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 переменные.
//bool f_run1X = 0;
unsigned long no_runX; //Переменная для прошедшего периода

bool f_run1Z = 0;//Сброс после остановки 2 переменные.
//bool f_run1Z = 0;
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

uint32_t sbros;
bool f_sbros;

uint32_t cur_time;//Миллис читаем один раз
uint32_t blink_time;//Мигаем в режиме калибровки

int Shtora1 = 50;// количество шагов для полного закрытия шторы 1;
int Shtora2 = 34;// количество шагов для полного закрытия шторы 2

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_2
  D14_Low;
  //Serial.begin(9600);
  // Инициализировать TIMER1
   StartTimer1(Time_Closk, 2000);
}

void Time_Closk() // Функция прерывания таймера
{
  f_timX = 1;
  f_timZ = 1;
}

//Функция вращения  dvigatel 1
void RunX (bool perem_X)
{
  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_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 < 500) {
    if (_UP || _Down) {
      _UP = 0;
      _Down = 0;
    }
    else Menu++;     // Меняем
    if (Menu > 3) Menu = 1;
    f_Mpush = 0;
  }

  else if (f_Mpush && !kn_menu && cur_time - menu_klik > 500) {
    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: D13_High; D14_Low; break;
        case 2: D13_Low; D14_High; break;
        case 3: D13_High; D14_High; break;
      }
    }
  }
  else {
    if (cur_time - blink_time >= 300)
    {
      blink_time = cur_time;
      switch (Menu) {
        case 1: D13_Inv; D14_Low; break;
        case 2: D13_Low; D14_Inv; break;
        case 3: D13_Inv; D14_Inv; break;
      }
    }
  }

  /////////////////////////// Запуск 1го двигателя если " perem_X != 0 "
  if (f_timX) {
    if (_UP || _Down) {
      if (Menu != 2) {
        if (!sped_X) {
          if (!kalib) { //Калибровка отк.
            if (_UP && Shtora1 < max_Sht1) {//3592
              RunX(0);
            }
            if (_Down && Shtora1 > 0) {
              RunX(1);
            }
          }
          else { //Калибровка вкл.
            if (_UP) {
              Shtora1 = 0;
              RunX(0);
            }
            if (_Down) {
              Shtora1 = 1;
              RunX(1);
            }
          }
        }
        else if (sped_Xt > 0) {
          --sped_Xt;
          sped_X = sped_Xt;
          f_timX = 0;
        }
        else {
          --sped_X;
          f_timX = 0;
        }
      }
    }////
    
  }
  else {
    f_run1X = 1;
    no_runX = cur_time;
    sbros = cur_time;
    f_sbros = 1;
    sped_Xt = uskor;
    sped_X = 0; // для пропуска 1го тика
  }
  /////////////////Запуск 3го двигателя если " perem_Z != 0 "
  //if (!kalib) {
  if (f_timZ) {
    if (_UP || _Down) {
      if (Menu != 1) {

        if (!sped_Z) {

          if (!kalib)//Калибровка отк.
          {
            if (_Down && Shtora2 < max_Sht2) {//3475
              RunZ(0);
            }
            if (_UP && Shtora2 > 0) {
              RunZ(1);
            }
          }
          else {//Калибровка Вкл.
            if (_UP) {
              Shtora2 = 0;
              RunZ(0);
            }
            if (_Down) {
              Shtora2 = 1;
              RunZ(1);
            }
          }
        }
        else if (sped_Zt > 0) {
          --sped_Zt;
          sped_Z = sped_Zt;
          f_timZ = 0;
        }
      }
      else {
        --sped_Z;
        f_timZ = 0;
      }
    }////
  }
  else {
    f_run1Z = 1;
    no_runZ = cur_time;
    sbros = cur_time;
    f_sbros = 1;
    sped_Zt = uskor;
    sped_Z = 0; // для пропуска 1го тика
  }

  //Снимаем напряжение с катушек двигателя X
  if (f_run1X && cur_time - no_runX >= 1000)// закончилось ли время
  {
    f_run1X = 0;
    PORTB &= 0xF0;
  }

  //Снимаем напряжение с катушек двигателя Z
  if (f_run1Z && cur_time - no_runZ >= 1000)// закончилось ли время
  {
    f_run1Z = 0;
    PORTD &= 0xF;
  }
}

 

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

При первом входе точно движется, сейчас проверю еще пару раз.

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

vosara пишет:

Вот сделал инверсию попробуйте.  Поповоду скорости в стр.72 - StartTimer1(Time_Closk, 2000); можете поиграться с числом, сейчас стоит 2 мс.  на меньшем значении у меня стабильно не работает, а у Вас может и будет. По поводу калибровки: при первом входе он сам движется  или после установки, при втором заходе тоже? 


Скетч с инверсией проверил - с первой шторой: нажимаешь кнопку DOWN штора едет вверх, UP - вниз.

Со второй шторой тоже самое.
В режиме калибровки первая штора при нажатии DOWN едет вверх, UP-вниз. Вторая штора DOWN -вниз, UP-вверх.

Еще одна особенность появилась....кнопки UP и DOWN срабатывают со второго нажатия.

P/S похоже я Вас ввожу в заблуждение....первая штора пины:8 9 10 11, вторая штора пины:4 5 6 7

Т.е. получается, что до инверсии вторая штора работала правильно.

vosara
vosara аватар
Offline
Зарегистрирован: 08.02.2014

По поводу проблемы с калибровкой, у себя (на живой плате и в симуляторе) не заметил. Вот проверяйте с инверсией

//**********  (РЕЖИМ 1-ШАГ) Крутим с помощью сдвига --рабочая - крутит туда сюда без потери шагов - ускоряет - отключает катушки после бездействия
//PORTB - 8, 9, 10, 11 - Шаговик. && 12-кнопка Menu \ 13-Светодиод 1й штор.
//PORTD - 4, 5, 6, 7 - Шаговик. && 2-кнопка UP \ 3-кнопка DOWN
// А0-Светодиод 2й штор..

#include <CyberLib.h>
#define uskor 3 //Задаем ускорение
//Здесь устанавливаем максимальное кол. шагов для штор
#define max_Sht1 2500
#define max_Sht2 2750

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;

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_2
  D14_Low;
  //Serial.begin(9600);
  // Инициализировать TIMER1
  StartTimer1(Time_Closk, 2000);
}

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++;     // Меняем
    if (Menu > 3) Menu = 1;
    f_Mpush = 0;
  }
  //Было нажатие
  else if (f_Mpush && !kn_menu && cur_time - menu_klik > 1000) {
    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: D13_High; D14_Low; break;
        case 2: D13_Low; D14_High; break;
        case 3: D13_High; D14_High; break;
      }
    }
  }
  else {
    if (cur_time - blink_time >= 300)
    {
      blink_time = cur_time;
      switch (Menu) {
        case 1: D13_Inv; D14_Low; break;
        case 2: D13_Low; D14_Inv; break;
        case 3: D13_Inv; D14_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;
  }
  //Снимаем напряжение с катушек двигателя Z
  if (f_run1Z && cur_time - no_runZ >= 1000)
  {
    f_run1Z = 0;
    PORTD &= 0xF;
    f_sbrosZ = 1;
  }
}

 

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

Проверил новый скетч.
В режиме калибровки всё отлично! шторы ездят правильно.
В рабочем режиме вторая штора работает, а с первой шторой происходит следущее:
1. При нажатии DOWN штора стоит.
2. При нажатии UP штора заматывается в барабан.
3. Если сначала в режиме калибровки штору опустить полностью и перейти в рабочий режим, то всё работает как надо.

P.S. Погонял шторы одновременно...когда подогнал высоту, все заработало как и хотелось.
Получается, что сначала нужно провести калибровку, а именно опустить шторы в режиме калибровки до нужного положения, выйти из режима калибровки и всё будет работать. Тогда имеет смысл запретить нажатие кнопок UP  и DOWN если калибровка не была проведена, это будет один раз при первом запуске, потом когда положения штор и флаг калибровки(шторы уже калибровались) будут храниться в энергонезависимой памяти, разрешить нажатие кнопок.

vosara
vosara аватар
Offline
Зарегистрирован: 08.02.2014

34 стр. (kalib) присвойте 1, тоесть (bool kalib = 1;) тогда при запуске\перезапуске сразу будет включена калибровка и чтобы выйти изнеё нужно длинное нажатие

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

vosara пишет:

34 стр. (kalib) присвойте 1, тоесть (bool kalib = 1;) тогда при запуске\перезапуске сразу будет включена калибровка и чтобы выйти изнеё нужно длинное нажатие

Понял, а можете на 16 пин повесить пищалку? Я пробовал, но что-то не получается. Только для кнопки меню, на короткое нажатие - короткий сигнал, на длинное - длинный сигнал, ну и тон может отличаться.

vosara
vosara аватар
Offline
Зарегистрирован: 08.02.2014

Канешно могу, но мы же с Вами договаривались вместе писать код. Общую логику я вывел а такие дополнения подключайтесь и Вы!

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

vosara пишет:

Канешно могу, но мы же с Вами договаривались вместе писать код. Общую логику я вывел а такие дополнения подключайтесь и Вы!

Я пробовал вот так:
 

void Beep() //короткий звук, переключение шторы
{
  tone(ton,500,500);
  delay(200);
  noTone(ton);
}
void Beep_long()  //длинный звук, вход и выход из режима калибровки "0"
{
  tone(ton,200,1000);
  delay(200);
  noTone(ton);
}

И вот здесь указал функцию:
 

  //Был клик
  if (f_Mpush && !kn_menu && cur_time - menu_klik < 1000) {
    Beep();
    if (_UP || _Down) {
      _UP = 0;
      _Down = 0;
    }
    else Menu++;     // Меняем
    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;
  }

Но так работать не хочет....где я ошибаюсь?

vosara
vosara аватар
Offline
Зарегистрирован: 08.02.2014

Хотя если по мне так надобности в пищалке я не вижу потому что кнопка проверяется после отпукания - был клик или нажатие. Светодиоды прекрасно все показывают. При любом писке Вы все равно смотрите на диоды - а что же я включил.

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

vosara пишет:

Хотя если по мне так надобности в пищалке я не вижу потому что кнопка проверяется после отпукания - был клик или нажатие. Светодиоды прекрасно все показывают. При любом писке Вы все равно смотрите на диоды - а что же я включил.

Согласен, но всё же....привыкли уже.
Я так думаю ошибка как всегда в делеях?

vosara
vosara аватар
Offline
Зарегистрирован: 08.02.2014

Если пин ton Вы настроили как ВЫХОД, то почти угадали. А еще в библиотеке CyberLib есть встроеная функция beep, можно почитать и вызывать ее

/Был клик
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;
}

 

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

Заработало!
Теперь осталось сохранять позиции штор в память. Такая реализация как у меня была подойдет?
Еще нужно как то высчитывать оставшееся количество шагов до нужной позиции и сохранять результат калибровки....после отключения/включения питания.

vosara
vosara аватар
Offline
Зарегистрирован: 08.02.2014
По поводу памяти я Вашу реализацию не разбирал но если работала то должна подойти. Алгоритм предлагаю такой:
1- При загрузке читаем с памяти и присваюем значение перемен. штора1 и штора2
2- После сброса напряжения на двигателе - проверяем изменилось ли значение если да переписуем
3- Не нужно вычислять никаких остатков, просто сохранять перем. штора1(2)
4- калибровку сохранять не нужно - 0 нам звестный также как максимум
Память имеет ограниченный ресурс перезаписи и на сколько Вам ее хватит, Это вопрос, как часто будете дергать штору?
 
Если что то в тойже CyberLib есть функция работы с помятью
sheff
Offline
Зарегистрирован: 14.11.2017

vosara пишет:

По поводу памяти я Вашу реализацию не разбирал но если работала то должна подойти. Алгоритм предлагаю такой:
1- При загрузке читаем с памяти и присваюем значение перемен. штора1 и штора2
2- После сброса напряжения на двигателе - проверяем изменилось ли значение если да переписуем
3- Не нужно вычислять никаких остатков, просто сохранять перем. штора1(2)
4- калибровку сохранять не нужно - 0 нам звестный также как максимум
Память имеет ограниченный ресурс перезаписи и на сколько Вам ее хватит, Это вопрос, как часто будете дергать штору?
 
Если что то в тойже CyberLib есть функция работы с помятью

Я по-поводу калибровки хочу спросить...когда мы даем питание на плату, как узнать, что калибровка уже проводилась и в ячейках записано значения положения штор? А если, к примеру, хранить в отдельной ячейке 1 - если калибровка проводилась и 0 - если не проводилась. И если 1, то считать значения из ячеек.
Вопрос: в каком месте скетча сделать запись того, что калибровка провелась?
Чтение и запись значений сделал вот так:
 

#include <EEPROM.h> 
---------------------------------------------------------------------
// чтение
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(){

     if (EEPROM_int_read(4)!=1)
    {
      Shtora1=28900;
      Shtora2=27500;
    }
    else
    {
      Shtora1 = EEPROM_int_read(0);
      Shtora2 = EEPROM_int_read(2);
    }
 
}
----------------------------------------------------------------------
void loop(){
    //Снимаем напряжение с катушек двигателя 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 байта)
    }
  }

}

 

vosara
vosara аватар
Offline
Зарегистрирован: 08.02.2014

Поповоду калибровки: Глобальная калибровка должна проводиться один раз после перезаписи Ардуино, Это Вы должны знать и без записи в память. Представим что вы провели калибровку и в памяти записали 1, после этого решили обновить программу а у Вас в памяти записано что калибровку проводить не надо, хотя по факту ее надо провести. Так что я не вижу как указать програме что она перепрошыта и нужно калибровать. А поточные - если будут пропуски двигателя и нужно будет подкоректировать штору то Вы будете сами видеть нужно или нет. А вот записать полжение шторы после ее движения - это можно. После перезапуска программа просто востановит положение штор. 

#include <EEPROM.h> 
---------------------------------------------------------------------
// чтение
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(){
     
      Shtora1 = EEPROM_int_read(0);
      Shtora2 = EEPROM_int_read(2);
 
}
----------------------------------------------------------------------
void loop(){
    //Снимаем напряжение с катушек двигателя 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 байта)
    }
  }

}

 

Mouflon
Offline
Зарегистрирован: 17.01.2018

А если для перевода в режим калибровке включить её с нажатыми кнопками или в сетапе считывать значение определённой ячейки. если там скажем 0xff или 0x00 то считаем что калибровки нет.

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

Я тоже об этом думал и не нашел решения, только появилось еще больше вопросов, поэтому согласен с Вами. Сейчас залью скетч и проверю. Можно Вас попросить, так сказать "на пальцах" объяснить мне, что означают все эти PORTB &= 0xF0, PORTD &= 0xF,   n3 = 0xF0 & n3;//Маскируем  PORTD = (PORTD & 0xF) | n3; //Очищаем старшие биты и пишем туда n3,   DDRB = DDRB | B00101111;, PORTB = B00000000;, DDRD = DDRD | B11110000;,

  PORTD = B00000000;//;
Если в остальном еще можно разобраться, то это для меня темный лес...
 
sheff
Offline
Зарегистрирован: 14.11.2017

Похоже действительно, запись о калибровке не нужна. Сейчас проверил, ставил шторы в разных положениях и отключал питание, после включения все работает как надо, шторы в крайних положениях останавливаются.

vosara
vosara аватар
Offline
Зарегистрирован: 08.02.2014

Mouflon пишет:

А если для перевода в режим калибровке включить её с нажатыми кнопками или в сетапе считывать значение определённой ячейки. если там скажем 0xff или 0x00 то считаем что калибровки нет.

Установить или прочитать это не проблема, Проблема состоит в ее ипользовании - выше я описал. 

Mouflon
Offline
Зарегистрирован: 17.01.2018

ИМХО без наличия ООС точное определение положения шторы невозможно. Вот если бы концевики. или по току моторчика определять крайние положения... Но это так - мысли вслух... 

Было бы интересно посмотреть видео с работой устройства когда будет всё готово. 

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

Mouflon пишет:

ИМХО без наличия ООС точное определение положения шторы невозможно. Вот если бы концевики. или по току моторчика определять крайние положения... Но это так - мысли вслух... 

Было бы интересно посмотреть видео с работой устройства когда будет всё готово. 

Видео есть в этой теме http://arduino.ru/forum/proekty/rulonnye-shtory-na-arduino

Это еще до переделки, у меня моторы не хотели работать одновременно, а по-одному работали практически так же, только чуть медленнее. Сейчас вообще всё работает изумительно!
Может завтра пересниму....главное не забыть телефон горизонтально держать :)

vosara
vosara аватар
Offline
Зарегистрирован: 08.02.2014

На пальцах не получится да и не все сразу как пример можете посмотреть

http://arduino.net.ua/Arduino_articles/Opisanie%20jazyka%20Arduino%20na%20russkom%20jazyke/Manipuljacii%20s%20portami/

http://cxem.net/arduino/arduino6.php

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

vosara пишет:

На пальцах не получится да и не все сразу как пример можете посмотреть

http://arduino.net.ua/Arduino_articles/Opisanie%20jazyka%20Arduino%20na%20russkom%20jazyke/Manipuljacii%20s%20portami/

http://cxem.net/arduino/arduino6.php

Спасибо. Я это уже читал, похоже пока не пощупаешь фиг научишься....

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

vosara пишет:

На пальцах не получится да и не все сразу как пример можете посмотреть

Я Вам еще не сильно надоел?

Mouflon
Offline
Зарегистрирован: 17.01.2018

Посмотрел - с учтётом монументальности конструкции - склоняюсь ко мнению что дрейф будет минимальным и ООС можно принебречь. 

PS. Очень понравилось качество изготовления. 

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

Mouflon пишет:

Посмотрел - с учтётом монументальности конструкции - склоняюсь ко мнению что дрейф будет минимальным и ООС можно принебречь. 

PS. Очень понравилось качество изготовления. 


Спасибо! Старался, чтобы выглядело не очень колхозно....еще бы моторчики спрятать под колпачком, но для этого 3д принтер бы.....

vosara
vosara аватар
Offline
Зарегистрирован: 08.02.2014

Да тоже посмотрел - сделано акуратно!

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

vosara пишет:

Да тоже посмотрел - сделано акуратно!

Спасибо! Можно Вас еще подаставать?

vosara
vosara аватар
Offline
Зарегистрирован: 08.02.2014

Ну если смогу то помогу.

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

vosara пишет:

Ну если смогу то помогу.

Сначала хочу Вас поблагодарить! Без Вашей помощи был бы у меня коряво работающий скетч....а сейчас я просто ненарадуюсь :) Спасибо огромное!
Ну а теперь .....у меня в зале окно эркер....
Там установлены 3 шторки. Вас не затруднит переделать этот скетч под Мегу на 3 мотора?
Особенности: на 1 и 3 шторах моторы установлены так же как и в этом скетче, а у 2-ой шторы так же как у 3-ей.
Воистину человеческой наглости нет предела, но без Вашей помощи я еще полгода буду учиться моргать светодиодом, а шторы хочется закончить уже сейчас.

vosara
vosara аватар
Offline
Зарегистрирован: 08.02.2014

Ладно попробую, только Меги у меня нет испытувать будете Вы 

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

vosara пишет:

Ладно попробую, только Меги у меня нет испытувать будете Вы 

Я завтра попробую переделать часть скетча по аналогии, я так понимаю нужно добавить все как для Z только с Y? Плюс меню увеличить на 1, добавить светодиод.....ну а моторы вращать уже мне не по силам. А еще нужно с пинами определиться...

Mouflon
Offline
Зарегистрирован: 17.01.2018

Кстати, никогда не игрался с шаговыми двигателями, но почитав в интернете возникла следующая мысль - правильно ли я понял, что если взять два двигателя и подключить их парраллельно но с распиновкой у одного в порядке 1-2-3-4 а у другого 4-3-2-1 то мы получим одновременно работающие двигатели крутящиеся в противоположные стороны?

Если это так, то можно было бы взять 3 мосфета, и ими включать и выключать нужные двигатели, подключенные параллельно, а всё управление останется на 4х выводах. ведь ситуация при которой одна штора опускается, а другая поднимается - не предусмотрена ТЗ?

vosara
vosara аватар
Offline
Зарегистрирован: 08.02.2014

Mouflon пишет:

Кстати, никогда не игрался с шаговыми двигателями, но почитав в интернете возникла следующая мысль - правильно ли я понял, что если взять два двигателя и подключить их парраллельно но с распиновкой у одного в порядке 1-2-3-4 а у другого 4-3-2-1 то мы получим одновременно работающие двигатели крутящиеся в противоположные стороны?

Если это так, то можно было бы взять 3 мосфета, и ими включать и выключать нужные двигатели, подключенные параллельно, а всё управление останется на 4х выводах. ведь ситуация при которой одна штора опускается, а другая поднимается - не предусмотрена ТЗ?

На мой взгляд в этом есть зерно. Их не обезтельно включать навстречу, пусть крутят и  паралельно.

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

sheff пишет:

Я завтра попробую переделать часть скетча по аналогии, я так понимаю нужно добавить все как для Z только с Y? Плюс меню увеличить на 1, добавить светодиод.....ну а моторы вращать уже мне не по силам. А еще нужно с пинами определиться...

Кнопки: 2 - UP, 3 - DOWN, 4 - MENU
Светодиоды: 5 - Led1, 6 - Led2, 7 - Led3
Пищалка: 8 - Ton
Моторы: PORTA, PORTC, PORTL

Так пойдет? Я просто не знаю, может один порт управлять двумя моторами.
Я еще ничего не подключал, поэтому пока не критично.
И вот изменил скетч, поправьте если что не так. (что не смог сделать я отметил /////////////////////////)
 

//**********  (РЕЖИМ 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 30500
#define max_Sht3 28900
 
byte n1 = 1;// Сдвигаем 1 бит
byte n3 = 0x10;
bool f_timX = 0;
bool f_timY = 0;
bool f_timZ = 0;
 
byte sped_Xt = uskor;//Начальная скорость
byte sped_X = 0; //Ускорение
byte sped_Yt = uskor;//Начальная скорость
byte sped_Y = 0; //Ускорение
byte sped_Zt = uskor;//Начальная скорость
byte sped_Z = 0; //Ускорение
 
bool f_run1X = 0;//Сброс после остановки 2 переменные.
unsigned long no_runX; //Переменная для прошедшего периода

bool f_run1Y = 0;//Сброс после остановки 2 переменные.
unsigned long no_runY; //Переменная для прошедшего периода
 
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_sbrosY = 1;
bool f_sbrosX = 1;
 
uint32_t cur_time;//Миллис читаем один раз
uint32_t blink_time;//Мигаем в режиме калибровки
 
int Shtora1;
int Shtora2;
int Shtora3;
const int ton = 8;//пищалка
// чтение
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;//;
  D2_In; //2-кнопка UP
  D3_In; //3-кнопка DOWN
  D4_In; //4-кнопка MENU
  D5_Out;  // Led_1
  D5_Low; 
  D6_Out;  // Led_2
  D6_Low;
  D7_Out;  // Led_3
  D7_Low;
    pinMode(ton,OUTPUT);//пищалка
  //Serial.begin(9600);
  // Инициализировать TIMER1
  StartTimer1(Time_Closk, 2200);
      Shtora1 = EEPROM_int_read(0);
      Shtora2 = EEPROM_int_read(2);
      Shtora3 = EEPROM_int_read(4);
}
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_timY = 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 2
void RunY (bool perem_Y)
{
  f_sbrosY = 0;
  f_timY = 0;
  if (perem_Y) {
    n3 = (n3 >> 1) | (n3 << 3); //Сдвигаем
    --Shtora2;
  }
  else {
    n3 = (n3 << 1) | (n3 >> 3); //Сдвигаем
    ++Shtora2;
  }
///////////////////////////////////////////////////  n3 = 0xF0 & n3;//Маскируем
///////////////////////////////////////////////////  PORTD = (PORTD & 0xF) | n3; //Очищаем старшие биты и пишем туда n3
}
 
//Функция dvigatel 3
void RunZ (bool perem_Z)
{
  f_sbrosZ = 0;
  f_timZ = 0;
  if (perem_Z) {
    n3 = (n3 >> 1) | (n3 << 3); //Сдвигаем
    --Shtora3;
  }
  else {
    n3 = (n3 << 1) | (n3 >> 3); //Сдвигаем
    ++Shtora3;
  }
//////////////////////////////////////////////////  n3 = 0xF0 & n3;//Маскируем
//////////////////////////////////////////////////  PORTD = (PORTD & 0xF) | n3; //Очищаем старшие биты и пишем туда n3
}
 
void loop() {
 
  cur_time = millis();
  ///////////////////Проверка кнопки МЕНЮ - АНТИДРЕБЕЗГ
  if (D4_Read && !f_menu)
  {
    menu_dreb = cur_time;
    f_menu = 1;
  }
  if (!D4_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 > 4) 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: D5_High; D6_Low; D7_Low; break;
        case 2: D5_Low; D6_High; D7_Low; break;
        case 3: D5_Low; D6_Low; D7_High; break;
        case 4: D5_High; D6_High; D7_High; break;
      }
    }
  }
  else {
    if (cur_time - blink_time >= 300)
    {
      blink_time = cur_time;
      switch (Menu) {
        case 1: D5_Inv; D6_Low; D7_Low; break;
        case 2: D5_Low; D6_Inv; D7_Low; break;
        case 3: D5_Low; D6_Low; D7_Inv break;        
        case 4: D5_Inv; D6_Inv; D7_Inv break;
      }
    }
  }
  /////////////////////////// Запуск 1го двигателя если " perem_X != 0 "
  if (f_timX) {
    if (_UP || _Down) {
      if (Menu != 1) {
        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;
  }
  /////////////////Запуск 2го двигателя если " perem_Y != 0 "
  if (f_timY) {
    if (_UP || _Down) {
      if (Menu != 2) {
        if (!sped_Y) {
          if (!kalib)//Калибровка отк.
          {
            if (_UP && Shtora2 < max_Sht2) {
              RunY(0);
            }
            if (_Down && Shtora2 > 0) {
              RunY(1);
            }
          }
          else {//Калибровка Вкл.
            if (_UP) {
              Shtora2 = 0;
              RunY(0);
            }
            if (_Down) {
              Shtora2 = 1;
              RunY(1);
            }
          }
          //Три поверки для разгона
          if (sped_Yt > 0) {
            --sped_Yt;
            sped_Y = sped_Yt;
            f_timY = 0;
          }
        }
        else {
          --sped_Y;
          f_timY = 0;
        }
      }
    }////
    else {
      sped_Yt = uskor;
      sped_Y = 0;
    }
  }
  else { //Для снятия напряжения
    f_run1Y = 1;
    no_runY = cur_time;
  }

  /////////////////Запуск 3го двигателя если " perem_Z != 0 "
  if (f_timZ) {
    if (_UP || _Down) {
      if (Menu != 3) {
        if (!sped_Z) {
          if (!kalib)//Калибровка отк.
          {
            if (_UP && Shtora3 < max_Sht3) {
              RunZ(0);
            }
            if (_Down && Shtora3 > 0) {
              RunZ(1);
            }
          }
          else {//Калибровка Вкл.
            if (_UP) {
              Shtora3 = 0;
              RunZ(0);
            }
            if (_Down) {
              Shtora3 = 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_sbrosY && 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 байта)
    }
  }
  //Снимаем напряжение с катушек двигателя Y
  if (f_run1Y && cur_time - no_runY >= 1000)
  {
    f_run1Y = 0;
/////////////////////////////////////////////////////////////    PORTD &= 0xF;
    f_sbrosY = 1;
    if (EEPROM_int_read(2)!=Shtora2)
    {
     EEPROM_int_write(2, Shtora2); // адрес 2 (+2 байта)
    }
  }
  //Снимаем напряжение с катушек двигателя Z
  if (f_run1Z && cur_time - no_runZ >= 1000)
  {
    f_run1Z = 0;
///////////////////////////////////////////////////////////    PORTD &= 0xF;
    f_sbrosZ = 1;
    if (EEPROM_int_read(4)!=Shtora3)
    {
     EEPROM_int_write(4, Shtora3); // адрес 4 (+2 байта)
    }
  }
}

 

Mouflon
Offline
Зарегистрирован: 17.01.2018

Я просто не знаю, может один порт управлять двумя моторами.

а почему бы и нет? Он же через ULN работает. 
Кстати, ИМХО, есть смысл провести эксперимент - подключить два мотора, как я писал выше. Что бы они от одного порта крутились в разные стороны. Тогда будет достаточно 10 лап на 3 кнопки, 3 мотора и 4 вывода управления 

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

Mouflon пишет:

Кстати, ИМХО, есть смысл провести эксперимент - подключить два мотора, как я писал выше. Что бы они от одного порта крутились в разные стороны. Тогда будет достаточно 10 лап на 3 кнопки, 3 мотора и 4 вывода управления 

Проверил Ваше предположение....верно, можно все три мотора подключить к четырем пинам по схеме 1-2-3-4, причем один мотор подключил 4-3-2-1....нажимаешь кнопку "вправо" крутятся два в право, а один влево и наоборот. Удерживая вращение, снимал перемычку на драйвере (как Вы и сказали типа мосфетом дал команду), нужный мотор останавливался, остальные крутятся.
Получается, что нужно дать команду на вращение и мосфетами выбирать нужный мотор или все сразу. А по мин или макс положению выключать.

Mouflon
Offline
Зарегистрирован: 17.01.2018

Да. Мне кажется что так и код будет проще, и ардуинку подешевле можно использовать. 

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

Mouflon пишет:

Да. Мне кажется что так и код будет проще, и ардуинку подешевле можно использовать. 

Осталось придумать как считать шаги каждого мотора отдельно, шторы могут находиться в разных положениях, а двигаться нужно к примеру в мах.

vosara
vosara аватар
Offline
Зарегистрирован: 08.02.2014

sheff пишет:

Mouflon пишет:

Да. Мне кажется что так и код будет проще, и ардуинку подешевле можно использовать. 

Осталось придумать как считать шаги каждого мотора отдельно, шторы могут находиться в разных положениях, а двигаться нужно к примеру в мах.

Давайте пока попробуем на Мега, которой у меня нет и испытать не могу

//**********  (РЕЖИМ 1-ШАГ) Крутим с помощью сдвига --рабочая - крутит туда сюда без потери шагов - ускоряет - отключает катушки после бездействия
//PORTA - к двигателю X (22,23,24,25,) - как выход 
//PORTC - к двигателю Y,Z (37,36,35,34) (33,32,31,30) как выход
// 2, 3, 4 - Кнопки

#include <EEPROM.h>
#include <CyberLib.h>
#define uskor 3 //Задаем ускорение
//Здесь устанавливаем максимальное кол. шагов для штор
#define max_Sht1 28900
#define max_Sht2 30500
#define max_Sht3 28900
byte n_x = 1;//
byte n_y = 1;
byte n_z = 0x10;

bool f_timX = 0;
bool f_timY = 0;
bool f_timZ = 0;

byte sped_Xt = uskor;//Начальная скорость
byte sped_X = 0; //Ускорение
byte sped_Yt = uskor;//Начальная скорость
byte sped_Y = 0; //Ускорение
byte sped_Zt = uskor;//Начальная скорость
byte sped_Z = 0; //Ускорение

bool f_run1X = 0;//Сброс после остановки 2 переменные.
unsigned long no_runX; //Переменная для прошедшего периода

bool f_run1Y = 0;//Сброс после остановки 2 переменные.
unsigned long no_runY; //Переменная для прошедшего периода

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_sbrosY = 1;
bool f_sbrosX = 1;

uint32_t cur_time;//Миллис читаем один раз
uint32_t blink_time;//Мигаем в режиме калибровки

int Shtora1;
int Shtora2;
int Shtora3;
const int ton = 8;//пищалка

void setup() {
  // DDRA , к двигателю X (22,23,24,25,) - как выход Led, Beep (26,27,28,29)
  DDRA = 0xFF;
  //Устанавлюем значение выходов PORTA в 0
  PORTA = 0x00;
  //DDRC к двигателю Y,Z (37,36,35,34) (33,32,31,30) как выход
  DDRC = DDRC | B11111111;
  //Устанавлюем значение выходов PORTC в 0
  PORTC = B00000000;//x0F;

  //Serial.begin(9600);
  // Инициализировать TIMER1
  noInterrupts (); // отключить все прерывания
  TCCR1A = 0;
  TCCR1B = 0;
  TCNT1 = 0;
  OCR1A = 125; // сравнить регистр (скорость!!!(2ms=125 - если медлиннее - УВЕЛИЧУЕМ)
  TCCR1B |= (1 << WGM12); // Режим СТС
  TCCR1B |= (1 << CS12); // 256 делитель
  TIMSK1 |= (1 << OCIE1A ); // включить таймер сравнить прерываний
  interrupts(); // включить все прерывания

  D2_In;
  D3_In;
  D4_In;
  D5_Out;
  D5_Low;
  D6_Out;
  D6_Low;
  D7_Out;
  D7_Low;
  D8_Out;
  D8_Low;
}

// чтение
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 Beep() //короткий звук, переключение шторы
{
  tone(ton, 500, 500);
  delay(200);
  noTone(ton);
}
void Beep_long()  //длинный звук, вход и выход из режима калибровки "0"
{
  tone(ton, 200, 1000);
  delay(200);
  noTone(ton);
}

//Функция 1 dvigatel
void RunX (bool perem_X)
{
  f_sbrosX = 0;
  f_timX = 0;
  if (perem_X)
  {
    n_x = (n_x >> 1) | (n_x << 3); //Сдвигаем
    --Shtora1;
  }
  else {
    n_x = (n_x << 1) | (n_x >> 3); //Сдвигаем
    ++Shtora1;
  }
  n_x = 0x0F & n_x; //Маскируем кнопки
  PORTA = (PORTA & 0xF0) | n_x; //Очищаем Младшие биты и пишем туда n_x
}

//Функция 2 dvigatel
void RunY (bool perem_Y)
{
  f_sbrosY = 0;
  f_timY = 0;
  if (perem_Y) {
    n_y = (n_y >> 1) | (n_y << 3); //Сдвигаем
    --Shtora2;
  }
  else {
    n_y = (n_y << 1) | (n_y >> 3); //Сдвигаем
    ++Shtora2;
  }
  n_y = 0xF & n_y; //Маскируем кнопки
  PORTC = (PORTC & 0xF0) | n_y; //Очищаем Младшие биты и пишем туда n_y
}

//Функция 3 dvigatel
void RunZ (bool perem_Z)
{
  f_sbrosZ = 0;
  f_timZ = 0;
  if (perem_Z) {
    n_z = (n_z >> 1) | (n_z << 3); //Сдвигаем
    --Shtora3;
  }
  else {
    n_z = (n_z << 1) | (n_z >> 3); //Сдвигаем
    ++Shtora3;
  }

  n_z = 0xF0 & n_z;//Маскируем
  PORTC = (PORTC & 0xF) | n_z; //Очищаем старшие биты и пишем туда n_z
}

ISR (TIMER1_COMPA_vect)  // Функция прерывания таймера
{
  f_timX = 1;
  f_timY = 1;
  f_timZ = 1;
}

void loop() {

  cur_time = millis();
  ///////////////////Проверка кнопки МЕНЮ - АНТИДРЕБЕЗГ
  if (D4_Read && !f_menu)
  {
    menu_dreb = cur_time;
    f_menu = 1;
  }
  if (!D4_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 > 4) 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: D5_High; D6_Low; D7_Low; break;
        case 2: D5_Low; D6_High; D7_Low; break;
        case 3: D5_Low; D6_Low; D7_High; break;
        case 4: D5_High; D6_High; D7_High; break;
      }
    }
  }
  else {
    if (cur_time - blink_time >= 300)
    {
      blink_time = cur_time;
      switch (Menu) {
        case 1: D5_Inv; D6_Low; D7_Low; break;
        case 2: D5_Low; D6_Inv; D7_Low; break;
        case 3: D5_Low; D6_Low; D7_Inv; break;
        case 4: D5_Inv; D6_Inv; D7_Inv; break;
      }
    }
  }
  /////////////////////////// Запуск 1го двигателя если
  if (f_timX) {
    if (_UP || _Down) {
      if (Menu == 1 || Menu == 4) {
        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;
  }
  /////////////////Запуск 2го двигателя если
  if (f_timY) {
    if (_UP || _Down) {
      if (Menu == 2 || Menu == 4) {
        if (!sped_Y) {
          if (!kalib)//Калибровка отк.
          {
            if (_UP && Shtora2 < max_Sht2) {
              RunY(0);
            }
            if (_Down && Shtora2 > 0) {
              RunY(1);
            }
          }
          else {//Калибровка Вкл.
            if (_UP) {
              Shtora2 = 0;
              RunY(0);
            }
            if (_Down) {
              Shtora2 = 1;
              RunY(1);
            }
          }
          //Три поверки для разгона
          if (sped_Yt > 0) {
            --sped_Yt;
            sped_Y = sped_Yt;
            f_timY = 0;
          }
        }
        else {
          --sped_Y;
          f_timY = 0;
        }
      }
    }////
    else {
      sped_Yt = uskor;
      sped_Y = 0;
    }
  }
  else { //Для снятия напряжения
    f_run1Y = 1;
    no_runY = cur_time;
  }

  /////////////////Запуск 3го двигателя
  if (f_timZ) {
    if (_UP || _Down) {
      if (Menu == 3 || Menu == 4) {
        if (!sped_Z) {
          if (!kalib)//Калибровка отк.
          {
            if (_UP && Shtora3 < max_Sht3) {
              RunZ(0);
            }
            if (_Down && Shtora3 > 0) {
              RunZ(1);
            }
          }
          else {//Калибровка Вкл.
            if (_UP) {
              Shtora3 = 0;
              RunZ(0);
            }
            if (_Down) {
              Shtora3 = 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_sbrosY && f_sbrosX) {
    _UP = 0;
    _Down = 0;
  }
  //////////////////////
  //Снимаем напряжение с катушек двигателя X
  if (f_run1X && cur_time - no_runX >= 1000)
  {
    f_run1X = 0;
    PORTA &= 0xF0;
    f_sbrosX = 1;
    if (EEPROM_int_read(0) != Shtora1)
    {
      EEPROM_int_write(0, Shtora1); // адрес 0 (+2 байта)
    }
  }
  //Снимаем напряжение с катушек двигателя Y
  if (f_run1Y && cur_time - no_runY >= 1000)
  {
    f_run1Y = 0;
    PORTC &= 0xF0;
    f_sbrosY = 1;
    if (EEPROM_int_read(2) != Shtora2)
    {
      EEPROM_int_write(2, Shtora2); // адрес 2 (+2 байта)
    }
  }
  //Снимаем напряжение с катушек двигателя Z
  if (f_run1Z && cur_time - no_runZ >= 1000)
  {
    f_run1Z = 0;
    PORTC &= 0xF;
    f_sbrosZ = 1;
    if (EEPROM_int_read(4) != Shtora3)
    {
      EEPROM_int_write(4, Shtora3); // адрес 4 (+2 байта)
    }
  }
}

 

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

vosara пишет:

Давайте пока попробуем на Мега, которой у меня нет и испытать не могу

Испытывал на столе, моторы разложил как они должны стоять на шторах. Сначала была небольшая путаница, моторы крутились не в те стороны какие нужно....подключал вот так:

//PORTA - к двигателю X (22,23,24,25,) - как выход 
//PORTC - к двигателю Y,Z (37,36,35,34) (33,32,31,30) как выход
Потом переподключил вот так:
//PORTA - к двигателю X (25,24,23,22,) - как выход 
//PORTC - к двигателю Y,Z (37,36,35,34) (30,31,32,33)  как выход
Моторы стали крутиться в нужную сторону, но Y - это 3 мотор, а Z - 2 мотор.
В принципе можно "забить" на это, подключить как нужно, и пофиг как это в скетче называется. В комментарии написать, что Z - второй мотор (30,31,32,33), Y  - третий мотор (37,36,35,34).
 

 

vosara
vosara аватар
Offline
Зарегистрирован: 08.02.2014

Mouflon пишет:

Да. Мне кажется что так и код будет проще, и ардуинку подешевле можно использовать. 

Вот попробовал - Сказать что код по проще это врядли а на ардуинке  да выигруем. Если интересно то вот

//**********  (РЕЖИМ 1-ШАГ) Крутим с помощью сдвига --рабочая - крутит туда сюда без потери шагов - ускоряет - отключает катушки после бездействия
//PORTB - 8, 9, 10, 11 - Шаговик. && 12-кнопка ; 13 лед Menu1
//PORTD - 4, 5, 6, Выход но транзистор; 7 - лед Menu3  && 2-кнопка UP \ 3-кнопка DOWN (УСЛОВНО!!!)
// А0-Светодиод 2й штор (Menu2)..

#include <CyberLib.h>
#define uskor 3 //Задаем ускорение
//Здесь устанавливаем максимальное кол. шагов для штор
#define max_Sht1 28900
#define max_Sht2 30500
#define max_Sht3 28900

byte n1 = 1;// Сдвигаем 1 бит
bool f_timX = 0;
byte sped_Xt = uskor;//Начальная скорость
byte sped_X = 0; //Ускорение
bool f_run1X = 0;//Сброс после остановки 2 переменные.
unsigned long no_runX; //Переменная для прошедшего периода
// Переменные для кн.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_sbrosX = 1;

bool _Mofs1;
bool _Mofs2;
bool _Mofs3;

uint32_t cur_time;//Миллис читаем один раз
uint32_t blink_time;//Мигаем в режиме калибровки

int Shtora1;
int Shtora2;
int Shtora3;

void setup() {
  // DDRB пин, 8,9,10,11 - Шаговик, pin 12- вход, 13- Выход
  DDRB = DDRB | 0B00101111;
  // pin 8,9,10,11,13 - выход в 0 а входы pin 12, - 0
  PORTB = 0B00000000;
  //  DDRD,  pin 4,5,6,7 как выход,pin2,3 Выход
  DDRD = DDRD | 0B11110000;
  // pin 4,5,6,7 - выход в 0 а входы pin 2,3 - 0
  PORTD = PORTD & 0b00001111;//;
  D14_Out;  // Led_2
  D14_Low;
  //Serial.begin(9600);
  // Инициализировать TIMER1
  StartTimer1(Time_Closk, 2000);
}

void Time_Closk() // Функция прерывания таймера
{
  f_timX = 1;
}

//Функция вращения  dvigatel 1
void RunX (bool perem_X)
{
  f_sbrosX = 0;
  f_timX = 0;
  if (perem_X) {
    n1 = (n1 >> 1) | (n1 << 3); //Сдвигаем
  }
  else {
    n1 = (n1 << 1) | (n1 >> 3); //Сдвигаем
  }
  n1 = 0x0F & n1; //Маскируем кнопки
  PORTB = (PORTB & 0xF0) | n1; //Очищаем Младшие биты и пишем туда n1
  switch (Menu) {
    case 1:
      if (_Down)Shtora1++;
      if (_UP)Shtora1--;
      break;
    case 2:
      if (_Down)Shtora2++;
      if (_UP)Shtora2--;
      break;
    case 3:
      if (_Down)Shtora3++;
      if (_UP)Shtora3--;
      break;
    case 4:
      if (_Down) {
        if (_Mofs1)Shtora1++;
        if (_Mofs2)Shtora2++;
        if (_Mofs3)Shtora3++;
      }
      if (_UP) {
        if (_Mofs1)Shtora1--;
        if (_Mofs2)Shtora2--;
        if (_Mofs3)Shtora3--;
      }
      break;
  }
}


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;
      _Mofs1 = 0;
      _Mofs2 = 0;
      _Mofs3 = 0;
    }
    else Menu++;     // Меняем
    if (Menu > 4) Menu = 1;
    f_Mpush = 0;
  }
  //Было нажатие
  else if (f_Mpush && !kn_menu && cur_time - menu_klik > 1000) {
    _Mofs1 = 0;
    _Mofs2 = 0;
    _Mofs3 = 0;
    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;
      _Mofs1 = 0;
      _Mofs2 = 0;
      _Mofs3 = 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;
      _Mofs1 = 0;
      _Mofs2 = 0;
      _Mofs3 = 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;
      Serial.print("Menu- "); Serial.println(Menu);
      switch (Menu) {
        case 1: D13_High; D14_Low; D7_Low; break;
        case 2: D13_Low; D14_High; D7_Low; break;
        case 3: D13_Low; D14_Low; D7_High; break;
        case 4: D13_High; D14_High; D7_High; break;
      }
    }
  }
  else {
    if (cur_time - blink_time >= 300)
    {
      blink_time = cur_time;
      switch (Menu) {
        case 1: D13_Inv; D14_Low; D7_Low; break;
        case 2: D13_Low; D14_Inv; D7_Low; break;
        case 3: D13_Low; D14_Low; D7_Inv; break;
        case 4: D13_Inv; D14_Inv; D7_Inv; break;
      }
    }
  }
  /////////////////////////// Запуск 1го двигателя если " perem_X != 0 "
  if (f_timX) {
    if (_UP || _Down) {
      if (!sped_X) {
        if (Menu == 1 || Menu == 4) {
          if (!kalib) { //Калибровка отк.
            if (Shtora1 >= max_Sht1 || Shtora1 <= 0) _Mofs1 = 0;
            if (Shtora1 < max_Sht1) {
              if (_Down)_Mofs1 = 1;
            }
            if (Shtora1 > 0) {
              if (_UP)  _Mofs1 = 1;
            }
          }
          else { //Калибровка вкл.
            _Mofs1 = 1;
            if (_Down) {
              Shtora1 = 0;
            }
            if (_UP) {
              Shtora1 = 1;
            }
          }
        }
        if (Menu == 2 || Menu == 4) {
          if (!kalib) { //Калибровка отк.
            if (Shtora2 >= max_Sht2 || Shtora2 <= 0) _Mofs2 = 0;
            if (Shtora2 < max_Sht2) {
              if (_Down)_Mofs2 = 1;
            }
            if (Shtora2 > 0) {
              if (_UP)_Mofs2 = 1;
            }
          }
          else { //Калибровка вкл.
            _Mofs2 = 1;
            if (_Down) {
              Shtora2 = 0;
            }
            if (_UP) {
              Shtora2 = 1;
            }
          }
        }
        if (Menu == 3 || Menu == 4) {
          if (!kalib) { //Калибровка отк.
            if (Shtora3 >= max_Sht3 || Shtora3 <= 0) _Mofs3 = 0;
            if (Shtora3 < max_Sht3) {
              if (_Down)_Mofs3 = 1;
            }
            if (Shtora3 > 0) {
              if (_UP)  _Mofs3 = 1;
            }
          }
          else { //Калибровка вкл.
            _Mofs3 = 1;
            if (_Down) {
              Shtora3 = 0;
            }
            if (_UP) {
              Shtora3 = 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;
  }

  if (_Mofs1)D4_High;
  else D4_Low;
  if (_Mofs2)D5_High;
  else D5_Low;
  if (_Mofs3)D6_High;
  else D6_Low;
  if (f_timX) {
    if (_Mofs1 || _Mofs2 || _Mofs3) {
      if (_Down)  RunX(0);
      if (_UP) RunX(1);
    }
  }
  //Возврат по достижению конечной точки
  if (f_sbrosX) {
    _UP = 0;
    _Down = 0;
  }
  //Снимаем напряжение с катушек двигателя X
  if (f_run1X && cur_time - no_runX >= 1000)
  {
    f_run1X = 0;
    PORTB &= 0xF0;
    f_sbrosX = 1;
  }
}

 

Mouflon
Offline
Зарегистрирован: 17.01.2018

ИМХО надо или класс делать, или структуру. А их них массив - размерностью в количество двигателей.

тогда 

switch (Menu) {
    case 1:
      if (_Down)Shtora1++;
      if (_UP)Shtora1--;
      break;
    case 2:
      if (_Down)Shtora2++;
      if (_UP)Shtora2--;
      break;
    case 3:
      if (_Down)Shtora3++;
      if (_UP)Shtora3--;
      break;
    case 4:
      if (_Down) {
        if (_Mofs1)Shtora1++;
        if (_Mofs2)Shtora2++;
        if (_Mofs3)Shtora3++;
      }
      if (_UP) {
        if (_Mofs1)Shtora1--;
        if (_Mofs2)Shtora2--;
        if (_Mofs3)Shtora3--;
      }
      break;
  }

Будет выглядеть как

  for( int i = 0; i < MotorCount; i++)
  {
    if( motorArr[i].State == HIGH ) 
    {
      motorArr[i].Shtora += direction; // direction 1 в одну сторону, -1 в другую.
    }
  }