ARDUINO Помощь по работе прерываний для Шагового двигателя и энкодера.

Ahtung533

✩✩✩✩✩✩✩
21 Июл 2022
1
0
Добрый день, друзья! Решил собрать себе станок для протяжки PET пластика в пруток для печати, и написать программу я взялся сам своими силами. Схема простая, к Arduino nano подключаются: MOSFET для нагревателя, NTC термистор, драйвер A4988, OLED экран и энкодер. Так вот у меня проблема, шаговый двигатель не работает нормально при обработке энкодера, шаговик еле крутится. Независимо от того как энкодер обрабатывается в loop-е или в прерываниях. Если убираю обработку энкодера, то шаговик работает нормально. Использовал библиотеки от уважаемого Alex Gyver-а. Куда копать и как обрабатывать и энкодер и ШД?
Мой скетч без работы PID:
#include <GyverStepper.h>
#include <GyverOLED.h>
#include <EncButton.h>
#include <GyverNTC.h>
#include <GyverPID.h>
#include <GyverTimers.h>

#define MOS_PIN 10
#define THERM_PIN A7

GStepper<STEPPER2WIRE> stepper(6400, 5, 6); //400*16=6400 шагов, пин step, пин dir (шагов на градус берется из документации на двигатель)
EncButton<EB_TICK, 2, 3, 4> encoder;  // энкодер с кнопкой
GyverOLED<SSD1306_128x32, OLED_NO_BUFFER> oled;  //oled подключается на пины sck - A5, sda - A4
GyverNTC NTC (THERM_PIN, 100000, 3950, 25, 4693); //термистор (аналоговый пин, сопротивление термистора, коэффицент(обычно 3950), базовая температура термистора, сопротивление парного резистора)
GyverPID pid(15.2, 0.82, 0);

int period = 500;
unsigned long timing;
int count = 1;
bool flag1;



void setup() {
  //Serial.begin(9600);

  stepper.setRunMode(KEEP_SPEED); // режим поддержания скорости
  stepper.setSpeedDeg(1);        // в градусах/сек, не ставить 0, иначе не запускается прога
  stepper.setMaxSpeedDeg(600);  //нужно для работы getMinPeriod

  encoder.setEncType(EB_HALFSTEP);

  Timer2.setPeriod(stepper.getMinPeriod() / 2);
  Timer2.enableISR();

  pid.setpoint = 243;
  pid.setDt(period);
  pinMode(MOS_PIN, OUTPUT);

  oled.init();
  oled.clear();
  oled.setCursor(5, 1);   // курсор в (пиксель X, строка Y)
  oled.setScale(2);
  oled.print("PeT_Pull_2");
  delay(2000);
  oled.clear();
  oled.setScale(1);

  // прерывание обеих фаз энкодера на функцию isr
  attachInterrupt(0, isr, CHANGE);
  attachInterrupt(1, isr, CHANGE);
}


void loop() {
  encoder.tick();

  if (encoder.right()) {
    count = count - 50;
    if (count < 1) count = 1;
    flag1 = 1;
  }

  if (encoder.left()) {
    count = count + 50;
    if (count == 51) count = 50;
    if (count > 600) count = 600;   // Скорость от 0 до 600 градусов/сек при повороте движка
    flag1 = 1;
  }

  if (encoder.click()) {
    stepper.setSpeedDeg(count);  //скорость записывается в драйвер по нажатию на энкодер.
    oled.setCursor(5, 2);
    oled.print("Set!");
    flag1 = 1;
  }

  if (millis() - timing > 1000) { // 1 сек
    timing = millis();
    if (flag1 == 1) {
      oled.clear();
      oled.home();
      oled.print("Stp_spd=");
      oled.print(count);
      oled.setCursor(5, 2);
      oled.print("temp=");
      oled.print(pid.setpoint);
      oled.print("/");
      oled.print(NTC.getTempAverage());
      flag1 = 0;
    }
  }
}

ISR(TIMER2_A) {
  stepper.tick(); // мотор асинхронно крутится в прерывании
}

void isr() {
  encoder.tickISR();  // тикер в прерывании
  // Не вызывает подключенные коллбэки внутри прерывания!!!
}