Модернизация кода от Adafruit в код для Atmega 328P

OBN_RacerMan
Offline
Зарегистрирован: 11.08.2019

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

Я, к сожалению, совсем не программист. Максимум, на что моих познаний хватило, это "подогнать под себя" код Marlin 1.х.х при постройке 3D принтера.

Сейчас есть желание "прикрутить" к самодельному SLS 3D каннеру моторизованный стол от простенького лазерного 3D сканера Ciclop.

Нашёл подходящий (на мой взгляд) код, но написанный под плату Adafruit:

#include <Wire.h>
#include <Adafruit_MotorShield.h>
#include "utility/Adafruit_MS_PWMServoDriver.h"
// Create the motor shield object with the default I2C address
Adafruit_MotorShield AFMS = Adafruit_MotorShield();
// Connect a stepper motor with 400 steps per revolution (0.9 degree)
// to motor port #2 (M3 and M4)
Adafruit_StepperMotor *myMotor = AFMS.getStepper(400, 2);
void setup() {
  Serial.begin(9600);   // open serial port
  AFMS.begin();         // create with the default frequency 1.6KHz
  myMotor->setSpeed(1); // 1 rpm  
  myMotor->step(1, FORWARD, MICROSTEP);  // take a step to initialize position
  delay(250);           // settle mechanics for 250 ms
  myMotor->release();   // turn off current
}
void loop() {
  static int counter = 0;
  if(Serial.available()>0) // is there any unread serial data?
    {
    char ch = Serial.read();    // read a character from the serial port
    Serial.print("echo");Serial.println(ch); // echo back so that it is displayed in DAVID debug console
    if (ch == '2')              // is it the character for the number 2?
      {
      counter = counter + 1;    // increment the scan count
      myMotor->step(10, FORWARD, MICROSTEP); // take a step
      delay(250);           // settle mechanics for 250 ms
      myMotor->release();   // turn off current
      if (counter == 40)    // we have performed a full rotation
        {
          counter = 0;      // reset for next scan
        }
      else
        {
        Serial.println("S"); // Tell DAVID to do another Scan
        }
      }
    }  // end Serial.available
  }

Разумеется, что он не заработал при заливке его в Atmega 328P. Попытка изменить его по примеру  из библиотек Arduino Stepper приводит, конечно, к ошибке компиляции, начиная прямо с myStepper.begin();.

#include <Stepper.h>

const int stepsPerRevolution = 200;  // change this to fit the number of steps per revolution

// initialize the stepper library on pins 8 through 11:
Stepper myStepper (stepsPerRevolution, 8, 9, 10, 11);

int stepCount = 0;         // number of steps the motor has taken

void setup() {
     Serial.begin(9600);   // open serial port
     myStepper.begin();       // create with the default frequency 1.6KHz
     myStepper.setSpeed(1); // 1 rpm
     myStepper.step(10, FORWARD, MICROSTEP);  // take a step to initialize position
     myStepper.step(stepsPerRevolution); // take a step
     delay(250);           // settle mechanics for 250 ms
     myStepper.release();   // turn off current
  }
void loop() {
  static int counter = 0;
  if(Serial.available()>0) // is there any unread serial data?
    {
    char ch = Serial.read();    // read a character from the serial port
    Serial.print("echo");
    Serial.println(ch); // echo back so that it is displayed in DAVID debug console
    if (ch == '2')              // is it the character for the number 2?
      {
      counter = counter + 1;    // increment the scan count
      myStepper.step(20, FORWARD, MICROSTEP); // take a step
      delay(250);           // settle mechanics for 250 ms
      myStepper.release();   // turn off current
      if (counter == 16)    // we have performed a full rotation
        {
          counter = 0;      // reset for next scan
        }
      else
        {
        Serial.println("S"); // Tell DAVID to do another Scan
        }
      }
    }  // end Serial.available
  }

Знающие люди, подскажите хоть, в какую сторону "копать".. изучить программирование, может быть, и было бы лучшим решением.. если б это не было потребно "раз в жизни"... да и возраст уже не тот.

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Тут два варианта:

1. самый простой - заказать платную помощь в разделе «ищу исполнителя»

2. Привести полную информацию и полные данные по существующему проекту. А именно - схема подключения, при появлении ошибок - полный вывод этих ошибок и так далее. 

Второй способ не гарантирует ничего. Особенно если «время жмёт». 

OBN_RacerMan
Offline
Зарегистрирован: 11.08.2019

Спасибо. В будущем не исключаю и платный вариант помощи.

Но пока что хочу, своими силами, хотя бы сделать так, чтобы запускались примеры по моторам из библиотеки Arduino - а то на данный момент обнаружил, что после прошивки примера мотор просто трещит "где-то там, внутри себя" но не крутит... если рукой проворачивать то он дёргает стол до некоего "усточивого" положения и опять встаёт, продолжая трещать (при этом в мониторе COM порта идут отклики (step1, step2, ...), как будто мотор крутится)

Переделал методом тыка код - что-то начало "откликаться" (в мониторе на нажатие цифры "2" начал приходить ответ "S" (что и должно быть), а также мотор начал после ввода щёлкать (но, к сожалению, не вращаться) прописанное число раз)

#include <Stepper.h>

const int stepsPerRevolution = 200;  // change this to fit the number of steps per revolution

// initialize the stepper library on pins 8 through 11:
// Stepper myStepper (stepsPerRevolution, 2, 3, 4, 5);
// Stepper myStepper = Stepper (200, 8, 9, 10, 11);
Stepper myStepper (stepsPerRevolution, 8, 9, 10, 11);

int stepCount = 0;         // number of steps the motor has taken

void setup() {
     Serial.begin(9600);   // open serial port
   //  myStepper.begin();       // create with the default frequency 1.6KHz
       myStepper.setSpeed(1); // 1 rpm
   //  myStepper.step(20, FORWARD, MICROSTEP);  // take a step to initialize position
       myStepper.step(10); // take a step
       delay(250);           // settle mechanics for 250 ms
     // myStepper->release();   // turn off current
  }
void loop() {
  static int counter = 0;
  if(Serial.available()>0) // is there any unread serial data?
    {
    char ch = Serial.read();    // read a character from the serial port
    Serial.print("echo");
    Serial.println(ch); // echo back so that it is displayed in DAVID debug console
    if (ch == '2')              // is it the character for the number 2?
      {
      counter = counter + 1;    // increment the scan count
    //  myStepper.step(20, FORWARD, MICROSTEP); // take a step
        myStepper.step(10); // take a step
        delay(250);           // settle mechanics for 250 ms
      //  myStepper->release();   // turn off current
        if (counter == 200)    // we have performed a full rotation
        {
          counter = 0;      // reset for next scan
        }
      else
        {
        Serial.println("S"); // Tell DAVID to do another Scan
        }
      }
    }  // end Serial.available
  }

Плата у меня "оригинальная", от сканера Ciclop компании HE3D (с интегрированным драйвером мотора)

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

А это читали?

Это к теме о вращении.

Stepper.step(steps)

Функция вращает шаговый двигатель на определенное количество шагов, на скорости, заданной функцией setSpeed(). Эта функция блокирующая, то есть она ожидает окончания вращения двигателя, прежде чем передать управление в следующую строку кода.  Например, если скорость вращения установлена на 1 RPM (1 оборот в минуту), и вызвано  step(100)  на двигателе с полным оборотом в 100 шагов, то выполнение этой функции займет целую минуту. Правильней организовывать управление так, чтобы скорость была высокая, а за один вызов step() делалось всего несколько шагов, для избежания длительной блокировки выполнения кода скетча.

К томуже непонятно зачем используется counter и сколько положений двигателя «на круг»?

OBN_RacerMan
Offline
Зарегистрирован: 11.08.2019

BOOM пишет:

К томуже непонятно зачем используется counter и сколько положений двигателя «на круг»?

Счётчик нужен, чтобы в процессе сканирования поворачивать стол только определённое число раз (например 8 или 16) на совершение 1 оборота, нобходимого для "всестороннего" сканирования.

P.S. (у автора скрипта было задано аж 40 фиксированных положений на оборот (с мотором на 0.9°), но я считаю это совершенно излишней тратой времени на сканирование).

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

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

А сам вал то вращается от руки? Может вал заклинило?

OBN_RacerMan
Offline
Зарегистрирован: 11.08.2019

BOOM пишет:

А сам вал то вращается от руки? Может вал заклинило?

Да, тут проблем нет (я и другой мотор подцеплял).

Сейчас опять загнал тестовый код и поменял пины... и, пусть и с визгом, получил вращение (неуправляемое, фактически) потому как, вроде должно крутиться то в одну, то в другую сторону... а я смог заставить именять направление только сменой пинов в прошивке...

Причём если Stepper myStepper(stepsPerRevolution, 8, 9, 11, 12); "зуммерит", но крутится рывками против часовой стрелки (то же самое при 9, 10, 11, 12)

Если Stepper myStepper(stepsPerRevolution, 8, 9, 12, 13); "зуммерит", но крутится рывками по часовой стрелке  (то же самое при 9, 10, 12, 13)

А с пинами по-умолчанию 8, 9, 10, 11 только "зуммерит" и руками вал не стронуть (как на удержании)

P.S. Не могу после кода писать (всё пытается в код превратиться) - в общем только что поставил пины как:

Stepper myStepper(stepsPerRevolution, 13, 9, 12, 11); !!! и получил вроде то, что должно быть - мотор то в одну, то в другую сторону стал крутиться...

 

#include <Stepper.h> // библиотека для шагового двигателя

// количество шагов на 1 оборот, измените значение для вашего мотора
const int stepsPerRevolution = 200;

// устанавливаем порты для подключения драйвера
Stepper myStepper(stepsPerRevolution, 8, 9, 10, 11);

void setup() {
  myStepper.setSpeed(240); // устанавливаем скорость 60 об/мин
}

void loop() {
  // поворачиваем ротор по часовой стрелке
  myStepper.step(stepsPerRevolution);
  delay(250);

  // поворачиваем ротор против часовой стрелки
  myStepper.step(-stepsPerRevolution);
  delay(250);
}

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

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

  if ($process.Name == "HP3DScan5.exe") then
    $hook = $comObject.CreateHook("kernel32.dll!CreateFileW", 0)
    $hook.Attach($process, True)
    $hook.Hook()
    MsgBox($MB_SYSTEMMODAL, $process.name, "HP3DScan5.exe started and hooked", 10)
  EndIf

). 

Финальный (на данный момент) код выглядит так:

#include <Stepper.h>

const int stepsPerRevolution = 200;  // change this to fit the number of steps per revolution

// initialize the stepper library on pins 8 through 11:
Stepper myStepper (stepsPerRevolution, 13, 9, 12, 11);

int stepCount = 0;         // number of steps the motor has taken

void setup() {
     Serial.begin(9600);   // open serial port
     myStepper.setSpeed(240); // 1 rpm
     myStepper.step(1800);  // take a step to initialize position
     myStepper.step(stepsPerRevolution); // take a step
     delay(250);           // settle mechanics for 250 ms
       }
       
void loop() {
  static int counter = 0;
  if(Serial.available()>0) // is there any unread serial data?
    {
    char ch = Serial.read();    // read a character from the serial port
    Serial.print("echo");
    Serial.println(ch); // echo back so that it is displayed in DAVID debug console
    if (ch == '2')              // is it the character for the number 2?
      {
      counter = counter + 1;    // increment the scan count
      myStepper.step(1800); // take a step
      delay(250);           // settle mechanics for 250 ms
      if (counter == 16)    // we have performed a full rotation
        {
          counter = 0;      // reset for next scan
        }
      else
        {
        Serial.println("S"); // Tell DAVID to do another Scan
        }
      }
    }  // end Serial.available
  }

 

Morroc
Offline
Зарегистрирован: 24.10.2016

OBN_RacerMan пишет:

Причём если Stepper myStepper(stepsPerRevolution, 8, 9, 11, 12); "зуммерит", но крутится рывками против часовой стрелки (то же самое при 9, 10, 11, 12)

Если Stepper myStepper(stepsPerRevolution, 8, 9, 12, 13); "зуммерит", но крутится рывками по часовой стрелке  (то же самое при 9, 10, 12, 13)

А с пинами по-умолчанию 8, 9, 10, 11 только "зуммерит" и руками вал не стронуть (как на удержании)

P.S. Не могу после кода писать (всё пытается в код превратиться) - в общем только что поставил пины как:

Stepper myStepper(stepsPerRevolution, 13, 9, 12, 11); !!! и получил вроде то, что должно быть - мотор то в одну, то в другую сторону стал крутиться...

Ничеси метод тыка :) Теперь то уверены, что именно эти 4 пина используются драйвером ? Что за драйвер ?

OBN_RacerMan
Offline
Зарегистрирован: 11.08.2019

Morroc пишет:

Ничеси метод тыка :) Теперь то уверены, что именно эти 4 пина используются драйвером ? Что за драйвер ?

По драйверу ничего точного сказать не могу (он под радиатором, никаких пинов установки микрошагов нет). По звуку мотора похоже на А4988 (плата "узкоспециализированная" только под 3D сканер Ciclop, и в её задачах было поворачивать стол и включать в нужный момент один из лазеров).

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

На самом деле, как оказалось, там есть ещё пара "левых комбинаций", в которых тоже работает... какую либо "систематику" не выявлял - заработало - и отлично.

P.S. Я экспериментально установил, на каких пинах управление лазерами.. только не помню, т.к. сейчас на работе, да и не нужно мне это.... :-)

P.P.S. Осталось разобраться с вероятной блокировкой антивирусом перехвата действий программы с помощью Deviare. И, если удастся это победить, вероятно, соберу всё на нормальной Nano с драйвером типа 2208 (в принтере стоят - просто тишина).. а с тем что тут стоит стол и "в оригинале" резонировал от мотора так, что ночью всех будил...

Morroc
Offline
Зарегистрирован: 24.10.2016

Есть такое, у меня принтер на 2208 сейчас.

OBN_RacerMan
Offline
Зарегистрирован: 11.08.2019

Morroc пишет:

Есть такое, у меня принтер на 2208 сейчас.

Вот пока я на работе, а плата дома, сравнил "по фото" внешний вид части драйвера с этой платы, видной из-под радиатора с фото отдельного драйвера - формой-то он, оказывается, на DRV8825 больше похож, и "обвязка" практически такая же.

Morroc
Offline
Зарегистрирован: 24.10.2016

Угу, А4988 в руках не держал, а на микросхемку DRV8825 похоже то, что выглядывает, оба драйвера жужжащие.