остановить шаговый двигатель

landla
Offline
Зарегистрирован: 27.05.2017

Здравствуйте!

Написал свой первый скетч, но не получается закончить его правильно.

Программа должна работать так: Запуск двигателя по кнопки пуск, каретка едет до датчика холла, срабатывает функция прерывания и двигатель меняет направление, едет до второго датчика холла, срабатывает прерывание и он останавливается и ждёт следующего нажатия кнопки. Всё это выполняется отлично, с одним недостатком, на двигателе остаётся на одной обмотке напряжение и он греется вместе с драйвером. Я так понял, что команда stepper.step(0) когда двигатель уже запущен останавливает его т.к. шаг равен нулю и напряжения перестают переключаться между обмотками зависая на одной из них. Есть ли команда стоп двигателя, которая обесточивает все обмотки или как изменить программу, чтобы она работала правильно?

#include <Stepper.h>
int in3 = 4;                           // порт кнопки пуск
int valst = 0;                         // переменная для хранения данных кнопки пуск
volatile int state = 0;               
Stepper stepper(200, 8, 9, 10, 11);    
void setup() {                         
pinMode(4, INPUT);                     
digitalWrite(4, HIGH);                 
attachInterrupt(0, reverse, RISING);   // обработка реверс, переход на функцию reverse
attachInterrupt(1, stop, RISING);      // обработка остановки, переход на функцию stop
}
void loop()                            
{  
label:                                
stepper.setSpeed(300);                
stepper.step(state);                
for (valst = digitalRead(in3); valst == LOW;) // Цикл опроса кнопки пуск
{                                      
state = 1;                            
goto label;                            
}
}
void reverse()                         // функция возврата 
{                                     
state = -1;                           
}                                      
void stop()                            // функция остановки 
{                                    
state = 0;                             
}                                     

 

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Так и должно быть. Режим "удержание" - стандартный режим работы двигателя.

landla
Offline
Зарегистрирован: 27.05.2017

Спасибо за ответ. )))

Как обойти этот режим можно, так чтобы вернуть двигатель к первоначальным установкам в режим готовности?

landla
Offline
Зарегистрирован: 27.05.2017

Всё, разобрался. Вот так получилось, через программный сброс.

#include <Stepper.h>
int in3 = 4;                           // порт кнопки пуск
int valst = 0;                         // переменная для хранения данных кнопки пуск
volatile int state = 0;               
Stepper stepper(200, 8, 9, 10, 11);    
void setup() {
pinMode(4, INPUT);                     
digitalWrite(4, HIGH);                 
attachInterrupt(0, reverse, RISING);   // обработка реверс, переход на функцию reverse
attachInterrupt(1, stop, RISING);      // обработка остановки, переход на функцию stop
}
void loop()                            
{  
label:                                
stepper.setSpeed(300);                
stepper.step(state);                
for (valst = digitalRead(in3); valst == LOW;) // Цикл опроса кнопки пуск
{                                      
state = 1;                            
goto label;                            
}
}
void reverse()                         // функция возврата 
{                                     
state = -1;                           
}                                      
void stop()                            // функция остановки 
{                                    
state = 0;
digitalWrite(8, LOW);
digitalWrite(9, LOW);
digitalWrite(10, LOW);
digitalWrite(11, LOW);
void(* resetFunc) (void) = 0;
resetFunc(); 
}                                     

 

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Примерно как дубиной по ишаку.

landla
Offline
Зарегистрирован: 27.05.2017

А как правильнее покажи - буду учиться на примерах.

Клапауций 112
Клапауций 112 аватар
Offline
Зарегистрирован: 01.03.2017

landla пишет:

А как правильнее покажи - буду учиться на примерах.

двигатель!, рав-няйсь, сми-рно, шагом м-арш, кру-гом, сто-й!

Клапауций 112
Клапауций 112 аватар
Offline
Зарегистрирован: 01.03.2017

DetSimen пишет:

Примерно как дубиной по ишаку.

...калибром по иранскому ишаку.

nik182
Offline
Зарегистрирован: 04.05.2015

А просто записать нолики на выходы к которым прицеплен двигатель? Без библиотек?

landla
Offline
Зарегистрирован: 27.05.2017

nik182 пишет:

А просто записать нолики на выходы к которым прицеплен двигатель? Без библиотек?

Покажи как это сделать, я ещё очень плохо знаю программирование?

Я вроде как нолики на выходе и прописал перед сбросом программы, но это не помогало без сброса.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

А есть уверенность, что нужно прописывать именно нолики?

Ну и еще раз намекну: ответ на вопрос

Цитата:
как изменить программу, чтобы она работала правильно?

такоы: она сейчас работает правильно, а вЫ хотите, чтобы она работала неправильно.

Подумайте еще раз - оно Вам надо?

landla
Offline
Зарегистрирован: 27.05.2017

Программа работает правильно.  )))

Просто хотел ещё посмотреть какие есть варианты, для общего образования. Хотя бы несколько... 

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

landla пишет:

Программа работает правильно.  )))

Просто хотел ещё посмотреть какие есть варианты, для общего образования. Хотя бы несколько... 

А смысл кому-то корячется над тем что выше вашего уровня , как программиста в Си.

landla
Offline
Зарегистрирован: 27.05.2017

Цитата:

А смысл кому-то корячется над тем что выше вашего уровня , как программиста в Си.

Я не прошу весь скетч, просто варианты оконцовки программы, чтобы двигатель переходил в режим ожидания, так как он находится при старте программы. Это даже для средного программиста скорее всего минутное дело(наверное), а мне для самообразования.

Скетч уже записан в станок и работает, просто любопытно как ещё можно (проще или сложнее) закончить программу.

Шаговик, драйвер, ардуино, макетка есть, собрать на столе и проверить, что получилось могу.

В любом случае спасибо за внимание. )))

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

1) всегда уважайте чужой труд. И труд не может быть "минутное дело".

2) Проектирование программ может быть снизу -вверх или сверху-вниз. Грубая аналогия . Проектировать автомобиль с точки зрения водителя и окружающих или с точки зрения мотора. В первом случае получится что-то удобное и практичное в вождении, во втором хрень опасная для окружающих, но все таки движется. Разумеется в 1 варианте будет затрачено много ресурсов и сил.

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

4) в Stepper.h для ШД в 4 вывода

   Step C0 C1 C2 C3
      1  1  0  1  0
      2  0  1  1  0
      3  0  1  0  1
      4  1  0  0  1
Нет  ситуации когда на всех будет 0.
landla
Offline
Зарегистрирован: 27.05.2017

Цитата:

1) всегда уважайте чужой труд. И труд не может быть "минутное дело".

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

Некоторые поломки в аппаратуре я могу делать за минуты, но на эти знания ушли многие года практики и учёбы, тоже самое и у вас программистов, скорее всего даже сложнее! Я на эту-то програмку в 30 строчек потратил весь день пока составил, так, что всё понимаю и писал не со зла или попыткой обидеть. )))

Сейчас замерил все четыре пина на драйвере шаговика, пока кнопка пуск не нажата на всех четырёх выводах висит 0. Естественно после запуска программы идет перебор нуля и единицы и двигатель работает. Если нет команды на общий программный сброс то на одной из обмоток постянно висит напряжение после остановки двигателя командой stepper.step(0). Режим удержание как писал  andriano. Но мне он не нужен в моём случае. Сейчас программа работает, просто хочу узнать есть ли специальные команды которые выполняют функцию остановки двигателя со снятием напряжения со всех его обмоток? (То, что я сделал у себя общим сбросом программы) Ведь программа в 30 строчек этого не заметит, а большая программа потратит какое-то время на её сброс, да и не правильно это - сбрасывать всю программу, в моей значение не имеет, а вот в других может оказаться фатальным для других функций.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

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

/*Cl_Stepper_motor.ino
   Step C0 C1
      1  0  1
      2  1  1
      3  1  0
      4  0  0

   Step C0 C1 C2 C3
      1  1  0  1  0
      2  0  1  1  0
      3  0  1  0  1
      4  1  0  0  1

  шаговый двигатель (8,9,10,11)
  датчик начала ->2
  датчик конца  ->3
  кнопка Пуск   ->4
*/
//--------------------class Cl_Step_motor------------------------
byte MAP[2][4] = {
  {0x01, 0x03, 0x02, 0x00},
  {0x0A, 0x06, 0x05, 0x09}
};
class Cl_Step_motor {
    byte N_pin; // 0 - 2 вывода / 1 - 4 вывода
    byte pin_1; // ноги двигателя
    byte pin_2;
    byte pin_3;
    byte pin_4;
    int Dir = 0;  // 0 - стоит / 1 поворот+ /  -1 поворот-
    int Step = 0; // номер шага 0,1,2,3
    uint32_t step_delay = 200; // длительность шага
    uint32_t past = 0;
  public:
    // указатель на следующий элемент
    Cl_Step_motor *pnt;
    // конструктор
    Cl_Step_motor( byte _pin_1, byte _pin_2): pin_1(_pin_1), pin_2(_pin_2), N_pin(0), pnt(NULL) {}
    Cl_Step_motor( byte _pin_1, byte _pin_2, byte _pin_3, byte _pin_4): pin_1(_pin_1), pin_2(_pin_2), pin_3(_pin_3), pin_4(_pin_4), N_pin(1), pnt(NULL) {}
    // setup()
    void setup() {
      if (this->pnt != NULL) this->pnt->setup();
      pinMode(pin_1, OUTPUT);
      pinMode(pin_2, OUTPUT);
      if (N_pin == 1) {
        pinMode(pin_3, OUTPUT);
        pinMode(pin_4, OUTPUT);
      }
      stop();
    }
    // loop()
    void loop() {
      if (this->pnt != NULL) this->pnt->loop();
      if (millis() - past >= step_delay) {
        past = millis();
        if (Dir == 0)return;
        Step += Dir;
        if (Step < 0)Step = 3;
        if (Step > 3)Step = 0;
        write(Step);
      }
    }
    void write(byte pos) { // сделать шаг
      digitalWrite(pin_1 , MAP[N_pin][pos] & 0x01);
      digitalWrite(pin_2 , MAP[N_pin][pos] & 0x02);
      if (N_pin == 1) {
        digitalWrite(pin_3, MAP[N_pin][pos] & 0x04);
        digitalWrite(pin_4, MAP[N_pin][pos] & 0x08);
      }
    }
    void forward()  { // вперед
      Dir = 1;
    }
    void forward(uint32_t time)  { // вперед c шагом time
      Dir = 1;
      step_delay = time;
    }
    void backward()  { // назад
      Dir = -1;
    }
    void backward(uint32_t time)  { // назад c шагом time
      Dir = -1;
      step_delay = time;
    }
    void stop()      { // стоп
      Dir = 0;
      digitalWrite(pin_1, LOW);
      digitalWrite(pin_2, LOW);
      if (N_pin == 1) {
        digitalWrite(pin_3, LOW);
        digitalWrite(pin_4, LOW);
      }
    }
};
//--------------------class Cl_Btn------------------------
// класс кнопки с 1 обработчиком кнопки
class Cl_Btn {
    byte pin; // номер ноги на кнопке
    void (* Do)();// указатель на обработчик
    bool btn, btn_old;
    bool bounce = 0; // антидребезговый флаг
    uint32_t past = 0 ;
  public:
    // указатель на следующую
    Cl_Btn *pnt = NULL;
    // конструктор
    Cl_Btn(byte _pin, void (* _Do)()): pin(_pin), Do(_Do) {};
    // setup()
    void setup() {
      if (this->pnt != NULL) this->pnt->setup();
      pinMode(pin, INPUT_PULLUP);// подключить кнопку 1 с подтяжкой
      btn = digitalRead(pin); // прочитать реальное значение на выводе};
    }
    // loop()
    void loop() {
      if (this->pnt != NULL) this->pnt->loop();
      if (! bounce && btn != digitalRead(pin)) { // если прошел фронт изм на выводн
        bounce = 1;                              // выставить флаг
        past = millis();                         // сделать временую засветку
      }
      else if ( bounce && millis() - past >= 5 ) { // если прошло антидребезговое время
        bounce = 0;                                // то снять флаг
        btn_old = btn ;
        btn = digitalRead(pin) ;                   // прочитать реальное значение на выводе
        if (btn_old && ! btn) Do();
      }
    }
};
//-----------------class Cl_sys---------------------------
class Cl_sys {
    Cl_Step_motor *Start_Step_motor = NULL;
    Cl_Btn *Start_Btn               = NULL;
  public:
    Cl_sys() {}
    void Plug(Cl_Step_motor * obj) {
      obj->pnt = Start_Step_motor;
      Start_Step_motor = obj;
    }
    void Plug(Cl_Btn * obj) {
      obj->pnt = Start_Btn;
      Start_Btn = obj;
    }
    void setup() {
      Start_Step_motor ->setup();
      Start_Btn        ->setup();
    }
    void loop() {
      Start_Step_motor ->loop();
      Start_Btn        ->loop();
    }
} Sys;
//--------------------------------------------
Cl_Step_motor Step_motor(/*pin_1*/8,/*pin_2*/9,/*pin_3*/10,/*pin_4*/11);// подключить шаговый двигатель

void Do_Home() {
  Step_motor.stop();
}
void Do_End() {
  Step_motor.backward(100);
}
void Do_Btn_1() {
  Step_motor.forward(400);
}
Cl_Btn Home (/*pin*/2,/*обработчик*/ Do_Home); // подключить концевик начало
Cl_Btn End  (/*pin*/3,/*обработчик*/ Do_End); // подключить концевик конец
Cl_Btn Btn_1(/*pin*/4,/*обработчик*/ Do_Btn_1); // подключить кнопку Btn_1

void setup() {
  Sys.Plug(&Step_motor);

  Sys.Plug(&Btn_1);
  Sys.Plug(&End  );
  Sys.Plug(&Home );

  Sys.setup();
}
void loop() {

  Sys.loop();
}

 

landla
Offline
Зарегистрирован: 27.05.2017

Спасибо большое! )))

Буду разбираться.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

landla пишет:

Я на эту-то програмку в 30 строчек потратил весь день пока составил...

Обратил внимание, что Ваша производительность труда в точности совпадает с производительностью квалифицированного программиста - 4 строки в час.