суббота, 2 апреля 2016 г.

13. Концевики, самодиагностика, установка нулевых точек


  Как и обещал в прошлой статье, выкладываю код программы для самодиагностики и установки нулевых точек по датчикам. Кстати забыл рассказать о датчиках (концевиках). В качестве концевиков я применил кнопки от старых компьютерных мышек. Подключил их по схеме на рисунке ниже. Подтягивающий резистор имеет номинал 10 кОм. 

 

 Эти кнопки достаточно миниатюрны и имеют огромный ресурс - цикл нажатий. Как и любые другие кнопки они не лишены недостатков - так называемого дребезга. Как я с ним борюсь? Да никак. Только в параллель кнопке впаял конденсатор на 1 мкФ.

 

  Конечно это не дает стопроцентной защиты от дребезга контактов но значительно снижает его.
Мной был проведен эксперимент, целью которого была регистрация дребезга. В опытах без конденсатора кнопка меняла свое состояние от трех до семнадцати раз, с конденсатором один- два раза. 
  В принципе в моем случае с дребезгом можно вообще не бороться, это никак не влияет вообще ни на что. Ну вызвалась функция обработки аппаратного прерывания вместо одно раза - десять раз. И что? Да ничего. Функция обработки прерывания меняет только флаг/переменную (F_Nul_X, F_Nul_Y, F_Nul_Z) с 0 на 1 и все. А все остальное обрабатывается в основном цикле программы. Конечно можно было бы сделать задержку скажем на 50-100 миллисекунд для того чтобы прошел переходной процесс в кнопке и установилось устойчивое состояние 0 или 1, но в функции обработки прерывания не работает delay(). Какая досада, а ведь так хочется. Вот и получается что либо бороться с дребезгом контактов только аппаратными методами либо вообще не бороться.
  Ниже представляю код программы в среде Arduino IDE. Постарался все оформить в отдельных функциях и сделать понятные комментарии.
 
  Код программы в среде Arduino IDE:

#include <Stepper.h>

// Количество шагов в одном обороте шпинделя
#define STEPS_X 200
#define STEPS_Y 200
#define STEPS_Z 51

// Скорость вращения ШД
#define XSpeed 300
#define YSpeed 300
#define ZSpeed 200

// Выводы для управления ШД по оси Y
#define Xa 23
#define Xb 25
#define Xc 27
#define Xd 29

#define Ya 31
#define Yb 33
#define Yc 35
#define Yd 37

#define Za 39
#define Zb 41
#define Zc 43
#define Zd 45

// Флаги прерываний по осям
volatile boolean F_Nul_X = 0;
volatile boolean F_Nul_Y = 0;
volatile boolean F_Nul_Z = 0;

// Флаги пройденных тестов
int F_Test_XYZ =0;

boolean F_Test_X = 0;
boolean F_Test2_X = 0;

boolean F_Test_Y = 0;
boolean F_Test2_Y = 0;

boolean F_Test_Z = 0;
boolean F_Test2_Z = 0;

Stepper stepperX(STEPS_X, Xa, Xb, Xc, Xd);
Stepper stepperY(STEPS_Y, Ya, Yb, Yc, Yd);
Stepper stepperZ(STEPS_Z, Za, Zb, Zc, Zd);

void setup() {
  stepperX.setSpeed(XSpeed);
  stepperY.setSpeed(YSpeed);
  stepperZ.setSpeed(ZSpeed);
 
  attachInterrupt(2, X_stop, RISING); // инициализация прерываний
  attachInterrupt(3, Y_stop, RISING); //
  attachInterrupt(4, Z_stop, RISING); //

}

void loop() {
  // Проводим прогон и устанавливаем в нулевое положение все оси
  if (F_Test_XYZ == 0) {
    X_null();
    if (F_Test_X == 1 && F_Test2_X ==1) {
      stepperX.step(400);
      Atermo(Xa, Xb, Xc, Xd);
      F_Test_XYZ = 1;
      delay(2000); //Задержка-спецэфект :-)
    }
  }
  if (F_Test_XYZ == 1) {
    Y_null();
    if (F_Test_Y == 1 && F_Test2_Y ==1) {
      stepperY.step(400);
      Atermo(Ya, Yb, Yc, Yd);
      F_Test_XYZ = 2;
      delay(2000); //Задержка-спецэфект :-)
    }
  }
  if (F_Test_XYZ == 2) {
    Z_null();
    if (F_Test_Z == 1 && F_Test2_Z ==1) {
      stepperZ.step(-102);
      Atermo(Za, Zb, Zc, Zd);
      F_Test_XYZ = 3;
      delay(2000); //Задержка-спецэфект :-)
    }
  }
}

// Защита от перегрева ШД по осям
void Atermo(int A, int B, int C, int D) {
    digitalWrite(A, LOW); //
    digitalWrite(B, LOW); // Устанавливаем 0 по всем
    digitalWrite(C, LOW); // входам управления ШД
    digitalWrite(D, LOW); //
  }

/////////////////////////////////////////
// Установка оси X в нулевое положение //
/////////////////////////////////////////

void X_null()  {
  if (F_Nul_X == 0 && F_Test2_X == 0) {
       stepperX.step(-100);
  }
  else  {
    F_Test2_X = 1;
    Atermo(Xa, Xb, Xc, Xd);
    delay(2000); //Задержка-спецэфект :-)
   
    if (F_Nul_X == 1 && F_Test_X == 0)  { // После достижения нулевого положения каретка движется в обратном направлении
       for (int i=0; i <= 18; i++) {
         stepperX.step(2000);
       }
       F_Nul_X = 0;
       F_Test_X = 1;
       F_Test2_X = 0;
       Atermo(Xa, Xb, Xc, Xd);
       delay(2000); //Задержка-спецэфект :-)
    }
  }
}

/////////////////////////////////////////
// Установка оси Y в нулевое положение //
/////////////////////////////////////////

void Y_null()  {
  if (F_Nul_Y == 0 && F_Test2_Y == 0) {
       stepperY.step(-100);
  }
  else  {
    F_Test2_Y = 1;
    Atermo(Ya, Yb, Yc, Yd);
    delay(2000); //Задержка-спецэфект :-)
   
    if (F_Nul_Y == 1 && F_Test_Y == 0)  { // После достижения нулевого положения каретка движется в обратном направлении
       for (int i=0; i <= 18; i++) {
         stepperY.step(2000);
       }
       F_Nul_Y = 0;
       F_Test_Y = 1;
       F_Test2_Y = 0;
       Atermo(Ya, Yb, Yc, Yd);
       delay(2000); //Задержка-спецэфект :-)
    }
  }
}

/////////////////////////////////////////
// Установка оси Z в нулевое положение //
/////////////////////////////////////////

void Z_null()  {
  if (F_Nul_Z == 0 && F_Test2_Z == 0) {
       stepperZ.step(51);
  }
  else  {
    F_Test2_Z = 1;
    Atermo(Za, Zb, Zc, Zd);
    delay(2000); //Задержка-спецэфект :-)
   
    if (F_Nul_Z == 1 && F_Test_Z == 0)  { // После достижения нулевого положения каретка движется в обратном направлении
       for (int i=0; i <= 22; i++) {
         stepperZ.step(-510);
       }
       F_Nul_Z = 0;
       F_Test_Z = 1;
       F_Test2_Z = 0;
       Atermo(Za, Zb, Zc, Zd);
       delay(2000); //Задержка-спецэфект :-)
    }
  }
}

////////////////////////////////////
// Функции обработчики прерываний //
////////////////////////////////////

void X_stop() {
  F_Nul_X = 1;
}

void Y_stop() {
  F_Nul_Y = 1;
}

void Z_stop() {
  F_Nul_Z = 1;
}


  Видеоролик демонстрирует выполнение кода.