22 авг. 2025

Шаговый двигатель униполярный 28BYJ-48: пример кода управления для ЧПУ станка

В версии 0.05 реализовано только калибровка в минус по осям X, Y, Z. Если нужно инвертированная калибровка ее придется добавить, а так же добавить инвертирование заданию шагов движения мотора, делается это просто, нужно тупо перемножить все на -1.

Для завершения калибровки у вас обязательно должны быть концевики для осей, подключены на пины А0, А1, А2.

Микропереключатель OFF-(ON) с лапкой - для обозначения, что двигателю не куда больше двигаться. Подтяжка контактов по минусу.

#define VERSION "0.05"

#define ABORTX A0 //Пин прерывателя  для оси ИКС

#define ABORTY A1 //Пин прерывателя  для оси ИГРИК

#define ABORTZ A2 //Пин прерывателя  для оси ЗЕТ

#include "GyverStepper2.h"

GStepper2<STEPPER4WIRE> stepperX(64, 2, 4, 3, 5); // in1 in2 in3 in4

GStepper2<STEPPER4WIRE> stepperY(64, 6, 8, 7, 9); // in1 in2 in3 in4

//GStepper2<STEPPER4WIRE> stepperZ(64, 6, 8, 7, 9); // in1 in2 in3 in4

uint32_t Timer0 = 0;

uint32_t Timer1 = 0;

char command[64];

int CountBuf = 0;

int32_t SizeStepX = 4; //Размер шага для оси ИКС

int32_t SizeStepY = 4; //Размер шага для оси ИГРИК

int32_t SizeStepZ = 4; //Размер шага для оси ЗЕТ

int32_t StepX = 0; //Количесво шагов по оси

int32_t StepY = 0; //Количесво шагов по оси

int32_t StepZ = 0; //Количесво шагов по оси

bool calibx = false; //Переменная для калибровки по оси ИКС

bool caliby = false; //Переменная для калибровки по оси ИГРИК

bool calibz = false; //Переменная для калибровки по оси ЗЕТ

void setup()

{

  StartConf();

}

void loop()

{

  // здесь происходит движение моторов, вызывать как можно чаще

  stepperX.tick(); //Вертим  пока есть куда

  stepperY.tick(); //Вертим  пока есть куда

  //stepperZ.tick(); //Вертим  пока есть куда

  if(calibx || caliby || calibz) //Есть  ли калибровка по какой либо оси

  {

    Calibration();

  }

  if (millis() - Timer0 >= 1000)

  {

    Timer0 = millis();

    //Выводим  сырые данные по позициям мотора

    Serial.print("Position X: ");

    Serial.print(stepperX.pos);

    Serial.print(" Y: ");

    Serial.println(stepperY.pos);

  }

  if (millis() - Timer1 >= 50)

  {

    Timer1 = millis();

    UART0();

  }

}

void UART0()

{

  if (Serial.available() > 0)

  {

    CountBuf = Serial.readBytes(command, 64);

    for(int  i = 0; i < CountBuf; i++)//Принудительно переводим все в нижний регистр

    {

      if(command[i]<= 0x5a && command[i] >= 0x41)

      { //Проверяем большая ли буква

        command[i] = command[i] + 32; //Переводим  в нижний  регистр

      }

    }

    if(strncmp(command, "resetx", 6) == 0) //Устанавливаем позицию в ноль

    {

      stepperX.reset();

      Serial.println("RESET X OK!");

    }

    else if(strncmp(command, "resety", 6) == 0) //Устанавливаем позицию в ноль

    {

      stepperY.reset();

      Serial.println("RESET Y OK!");

    }

    /*else if(strncmp(command, "resetz", 6) == 0) //Устанавливаем позицию в ноль

    {

      stepperZ.reset();

      Serial.println("RESET Z OK!");

    }*/

    else if(strncmp(command, "x=", 2) == 0)

    {

      if(calibx || caliby || calibz)

      {

        Serial.println("Calibration is being performed!");

      }

      else

      {

        int32_t val = myatol(command, 2);

        Serial.println(val);

        stepperX.setTarget(val);//Задаем позицию куда двигаться

      }

    }

    else if(strncmp(command, "y=", 2) == 0)

    {

      if(calibx || caliby || calibz)

      {

        Serial.println("Calibration is being performed!");

      }

      else

      {

        int32_t val = myatol(command, 2);

        Serial.println(val);

        stepperY.setTarget(val);//Задаем позицию куда двигаться

      }

    }

    /*else if(strncmp(command, "z=", 2) == 0)

    {

      if(calibx || caliby || calibz)

      {

        Serial.println("Calibration is being performed!");

      }

      else

      {

        int32_t val = myatol(command, 2);

        Serial.println(val);

        stepperZ.setTarget(val);//Задаем позицию куда двигаться

      }

    }*/

    else if(strncmp(command, "sizestepx=", 10) == 0) //Устанавливаем  размер шага  по оси ИКС

    {

      int32_t val = myatol(command, 10);

      SizeStepX = val;

      Serial.print("Set size step X: ");

      Serial.println(val);

    }

    else if(strncmp(command, "sizestepy=", 10) == 0) //Устанавливаем  размер шага  по оси ИГРИК

    {

      int32_t val = myatol(command, 10);

      SizeStepY = val;

      Serial.print("Set size step Y: ");

      Serial.println(val);

    }

    else if(strncmp(command, "sizestepz=", 10) == 0) //Устанавливаем  размер шага  по оси ЗЕТ

    {

      int32_t val = myatol(command, 10);

      SizeStepZ = val;

      Serial.print("Set size step Z: ");

      Serial.println(val);

    }

    else if(strncmp(command, "getsizestep", 11) == 0) //Получить размеры  всех шагов

    {

      Serial.print("SIZE STEP - X:");

      Serial.print(SizeStepX);

      Serial.print(" Y:");

      Serial.print(SizeStepY);

      Serial.print(" Z:");

      Serial.println(SizeStepZ);

    }

    else if(strncmp(command, "stepx=", 6) == 0) //Сделать шаг с размером

    {

      if(calibx || caliby || calibz)

      {

        Serial.println("Calibration is being performed!");

      }

      else

      {

        int32_t val = myatol(command, 6);

        val = val * SizeStepX;

        stepperX.setTarget(stepperX.pos + val);//Задаем позицию куда двигаться

      }

    }

    else if(strncmp(command, "stepy=", 6) == 0) //Сделать шаг с размером

    {

      if(calibx || caliby || calibz)

      {

        Serial.println("Calibration is being performed!");

      }

      else

      {

        int32_t val = myatol(command, 6);

        val = val * SizeStepY;

        stepperY.setTarget(stepperY.pos + val);//Задаем позицию куда двигаться

      }

    }

    /*else if(strncmp(command, "stepz=", 6) == 0) //Сделать шаг с размером

    {

      if(calibx || caliby || calibz)

      {

        Serial.println("Calibration is being performed!");

      }

      else

      {

        int32_t val = myatol(command, 6);

        val = val * SizeStepZ;

        stepperZ.setTarget(stepperZ.pos + val);//Задаем позицию куда двигаться

      }

    }*/

    else if(strncmp(command, "help", 4) == 0)

    {

      Serial.println("АВТОР: Мельник Д.В.");

      Serial.println("ПОЧТА: urbannova@yandex.ru");

    }

    else if(strncmp(command, "clbx", 4) == 0) //Калибровка оси ИКС

    {

      Serial.println("X-axis calibration has started.");

      calibx = true;

    }

    else if(strncmp(command, "clby", 4) == 0) //Калибровка оси ИГРИК

    {

      Serial.println("Y-axis calibration has started.");

      caliby = true;

    }

    else if(strncmp(command, "clbz", 4) == 0) //Калибровка оси ЗЕт

    {

      Serial.println("Z-axis calibration has started.");

      calibz = true;

    }

    else if(strncmp(command, "version", 7) == 0) //Калибровка оси ЗЕт

    {

      Serial.print("VERSION: ");

      Serial.println(VERSION);

    }

  }

}

void StartConf()//Выполняется стартовое конфигурирование системы

{

  Serial.begin(115200); // Иницилизация  сериала

  Serial.setTimeout(10); // Ограничиваем время  конца приема

  stepperX.setMaxSpeed(64); // Скорость  шагов,  более 512 начинает пропускать  шаги

  stepperY.setMaxSpeed(64); // Скорость  шагов,  более 512 начинает пропускать  шаги

  //stepperZ.setMaxSpeed(64); // Скорость  шагов,  более 512 начинает пропускать  шаги

  pinMode(ABORTX, INPUT_PULLUP); //Устанавливаем пин в режим подтяжки для  определения нуля оси

  pinMode(ABORTY, INPUT_PULLUP); //Устанавливаем пин в режим подтяжки для  определения нуля оси

  pinMode(ABORTZ, INPUT_PULLUP); //Устанавливаем пин в режим подтяжки для  определения нуля оси

  //Так как подключена подтяжка то на  пине +5 вольт  это ноль, подтяжка к  земле  будет еденицей.

}

void Calibration()

{

 if(calibx)

 {

  if(!digitalRead(ABORTX))

  {

    calibx = false;

    Serial.println("Calibration of the X-axis is completed");

    stepperX.brake();

    stepperX.reset();

  }

  else

  {

    stepperX.setTarget(stepperX.pos - 1);

  }

 }

 if(caliby)

 {

  if(!digitalRead(ABORTY))

  {

    caliby = false;

    Serial.println("Calibration of the y-axis is completed");

    stepperY.brake();

    stepperY.reset();

  }

  else

  {

    stepperY.setTarget(stepperY.pos - 1);

  }

 }

 /*if(calibz)

 {

  if(!digitalRead(ABORTZ))

  {

    calibz = false;

    Serial.println("Calibration of the z-axis is completed");

    stepperZ.brake();

    stepperZ.reset();

  }

  else

  {

    stepperZ.setTarget(stepperZ.pos - 1);

  }

 }*/

}

int32_t myatol(char * arr, int count) //Ищем число в строке с позиции

{

  int32_t val;

  char Temp[10] = {0};

  for(int i = 0; i < 10; i++)

  {

    if(arr[i+count] <= 0x39 && arr[i+count] >= 0x30 || arr[i+count] == '-')

    {

      Temp[i] = arr[i+count];

    }

    else

    {

      Temp[i] = 0x00;

      break;

    }

  }

  val = atol(Temp);

  return val;

}

//stepper.setSpeed(val);//задаем скорость вращения на сколько позиций

//stepper.reset();//Обнуляем позицию

//stepper.setTarget(val);//Задаем позицию куда  двигаться

Craftum Сайт создан на Craftum