ARDUINO gps и шаговый мотор. Где косячу и как сделать лучше.

Romashchandr

✩✩✩✩✩✩✩
19 Июл 2022
19
0
Здравствуйте. совсем новичок. поморгал лампой, покрутил шаговый мотор энкодером.
Теперь хочу заставить крутится шаговый мотор в зависимости от курса, выдаваемого приемником GPS.
написал два код: На милис, и на задержке.
там где Delay мотор не захотел вращаться вообще

gps-stepper delay:
void setup() {
 stepper.setRunMode(FOLLOW_POS);   // режим следования к целевй позиции
 stepper.setMaxSpeed(400);         // установка макс. скорости в шагах/сек
 stepper.setAcceleration(400);     // установка ускорения в шагах/сек/сек
// enc.setStepTimeout(500);
  // пусть драйвер выключается при достижении позиции
 stepper.autoPower(true);


 // Инициируем последовательный порт
    Serial.begin(9600);
// Инициируем работу с модулем GPS
     SettingsGPS.begin(SerialGPS);                 //  Инициируем работу с GPS модулем по указанной шине UART. Функция сама определит текущую скорость GPS модуля ATGM336 (вместо программной шины, можно указывать аппаратные: Serial, Serial1, Serial2, Serial3).
         // Инициируем интерпретацию строк NMEA
    gps.begin(SerialGPS);
    // Устанавливаем часовой пояс
    gps.timeZone(3);
    // Устанавливаем скорость передачи данных модулем
    SettingsGPS.baudrate(9600);
    // Указываем, что данные можно получать от спутников GPS и GLONASS
    SettingsGPS.system(GPS_GP, GPS_GL);
    // Указываем, что нам необходимы только строки с текущей скоростью и временем
    SettingsGPS.composition(NMEA_VTG, NMEA_ZDA, NMEA_GLL);
    // Устанавливаем режим "Транспортное средство"
    SettingsGPS.model(GPS_VEHICLE);
    // Указываем частоту обновления
    SettingsGPS.updaterate(1);

}

void loop() {
  
    // Считываем данные из модуля
    gps.read(i,true);

    // Если курс ошибочен
   if (gps.errCrs) { 
 
       val +=180;
     Serial.print("Скорость и курс недостоверны. ");
   }
       // Иначе
   else {
       /* Координаты (широта, долгота, высота):      */  Serial.print("Ш: "); Serial.print(gps.latitude,5); Serial.print("°, Д: "); Serial.print(gps.longitude,5); Serial.print("°, В: "); Serial.print(gps.altitude,1); Serial.print("м. ");
  Serial.print("Скорость: "); Serial.print(gps.speed); Serial.print("км/ч, "); Serial.print(gps.course); Serial.print("°. ");
        // Выводим курс
          
       val += gps.course; }
       delay (5000);
   }
       void yeld(){
  stepper.tick();
    stepper.setTargetDeg(val, ABSOLUTE);     // ставим новую позицию

}
наверное и слава богу.


миллис интересней. моторчик сначала подергивался, но потом поигравшись со верменем, я настроил его вращение, цикл вращение-остановка равняется таймеру tmr1 (но в определенных пределах на таймере в 10000 мс -- цикл становится 30 сек).

gps-stepper millis:
const uint8_t pinRX = 3;                           //  Определяем вывод RX (программного UART) на плате Arduino к которому подключён вывод TX модуля. Номер вывода можно изменить.

const uint8_t pinTX = 4;                           //  Определяем вывод TX (программного UART) на плате Arduino к которому подключён вывод RX модуля. Номер вывода можно изменить.



#include <FIFO.h>

#include <GStypes.h>

#include <GyverPlanner.h>

#include <GyverPlanner2.h>

#include <GyverStepper.h>

#include <GyverStepper2.h>

#include <StepperCore.h>


#include <iarduino_GPS_NMEA.h>                     //  Подключаем библиотеку для расшифровки строк протокола NMEA получаемых по UART.

#include <iarduino_GPS_ATGM336.h>                  //  Подключаем библиотеку для настройки параметров работы GPS модуля ATGM336.

#include <SoftwareSerial.h>                        //  Подключаем библиотеку для работы с программным UART.

      

           // Инстанцируем объекты библиотек


iarduino_GPS_NMEA    gps;                          //  Объявляем объект gps         для работы с функциями и методами библиотеки iarduino_GPS_NMEA.

iarduino_GPS_ATGM336 SettingsGPS;                  //  Объявляем объект SettingsGPS для работы с функциями и методами библиотеки iarduino_GPS_ATGM336.

SoftwareSerial       SerialGPS(pinRX, pinTX);      //  Объявляем объект SerialGPS   для работы с функциями и методами библиотеки SoftwareSerial, указав выводы RX и TX Arduino.

uint8_t i[30][6];                                  //  Объявляем массив для получения данных о 30 спутниках в формате: {ID спутника (1...255), Отношение сигнал/шум (SNR) в дБ, тип навигационной системы (1-GPS/2-Глонасс/3-Galileo/4-Beidou/5-QZSS), Флаг участия спутника в позиционировании (1/0), Азимут положения спутника (0°...360°), Угол возвышения спутника (0°-горизонт ... 90°-зенит) }.

char* sa[]={"NoName ","GPS    ","Глонасс"};        //  Определяем массив строк содержащих названия навигационных систем спутников.

char* wd[]={"Вс","Пн","Вт","Ср","Чт","Пт","Сб"};   //  Определяем массив строк содержащих по две первых буквы из названий дня недели.

uint32_t myTimer1, myTimer2;

// Обьявляем настойки мотора

#define EB_DEB 50   

#define EB_FAST 30 

GStepper<STEPPER4WIRE> stepper(2048,9, 7, 8, 6);

//EncButton2<EB_ENCBTN> enc(INPUT, 2, 3, 4);  // энкодер с кнопкой


//Обьявляем переменные курса

 static float val; 

  float course;  //?? оно надо??

  

  void setup() {

 stepper.setRunMode(FOLLOW_POS);   // режим следования к целевй позиции

 stepper.setMaxSpeed(400);         // установка макс. скорости в шагах/сек

 stepper.setAcceleration(100);     // установка ускорения в шагах/сек/сек

  // пусть драйвер выключается при достижении позиции

 stepper.autoPower(true);



 // Инициируем последовательный порт

    Serial.begin(9600);

// Инициируем работу с модулем GPS

     SettingsGPS.begin(SerialGPS);                 //  Инициируем работу с GPS модулем по указанной шине UART. Функция сама определит текущую скорость GPS модуля ATGM336 (вместо программной шины, можно указывать аппаратные: Serial, Serial1, Serial2, Serial3).

         // Инициируем интерпретацию строк NMEA

    gps.begin(SerialGPS);

    // Устанавливаем часовой пояс

    gps.timeZone(3);

    // Устанавливаем скорость передачи данных модулем

    SettingsGPS.baudrate(9600);

    // Указываем, что данные можно получать от спутников GPS и GLONASS

    SettingsGPS.system(GPS_GP, GPS_GL);

    // Указываем, что нам необходимы только строки с текущей скоростью и временем

    SettingsGPS.composition(NMEA_VTG, NMEA_ZDA, NMEA_GLL);

    // Устанавливаем режим "Транспортное средство"

    SettingsGPS.model(GPS_VEHICLE);

    // Указываем частоту обновления

    SettingsGPS.updaterate(1);

 

}


void loop() {

  

   if (millis() - myTimer1 >= 3000) {   // таймер на 2000 мс (1 раз в 2 сек)

    myTimer1 = millis();              // сброс таймера

    // выполнить действие 1

    // Считываем данные из модуля

    gps.read(i,true);


    // Если курс ошибочен

   if (gps.errCrs) { 

  

       val +=180;

     Serial.print("Скорость и курс недостоверны. ");

   }

       // Иначе

   else {

       /* Координаты (широта, долгота, высота):      */  Serial.print("Ш: "); Serial.print(gps.latitude,5); Serial.print("°, Д: "); Serial.print(gps.longitude,5); Serial.print("°, В: "); Serial.print(gps.altitude,1); Serial.print("м. ");

  Serial.print("Скорость: "); Serial.print(gps.speed); Serial.print("км/ч, "); Serial.print(gps.course); Serial.print("°. "); 

        // Выводим курс

       val += gps.course; }

   }

      

       if (millis() - myTimer2 >= 5) {   // таймер на 333 мс (3 раза в сек)

    myTimer2 = millis();              // сброс таймера

    // выполнить действие 2

  stepper.tick();

    stepper.setTargetDeg(val, ABSOLUTE);     // ставим новую позицию


} 

  }
мотор крутится и вроде даже на заданный GPS угол.
Но по сути работает неправильно.
1. постоянно крутится , хотя я надеялся на то что мотор повернется от начального положения и в следующий раз будет поворачиваться только по сле смены курса.
хотя сейчас написав это. понял что для этого необходимо сравнивать предыдущее показание курса с новым. как это сделать не знаю.

2. мне кажется я что то не так с милис делаю.
 

PiratFox

★★★★★✩✩
13 Фев 2020
1,724
481
необходимо сравнивать предыдущее показание курса с новым. как это сделать не знаю.
Просто. Ввести переменную, скажем, float old_course, и сравнивать её значение с новыми показаниями, затем присваивать ей новое значение. И так всё время.
 
  • Лойс +1
Реакции: Romashchandr

Старик Похабыч

★★★★★★★
14 Авг 2019
4,192
1,281
Москва
Честно не стал смотреть код. Но как бы сделал я:
По небольшому опыту (руки все не доходят) получения данных с простых ГПС приемников - обновление происходит раз в секунду. Там код простой: если есть что принимать - принимаем. Далее есть пауза в эту самую примерно секунду. А значит эту самую секунду можно использовать для вращения мотором, чего вполне хватит на 5 полных оборотов мотора. А значит для начал вполне можно использовать миллис для задержки. Конечно много нюансов, может мотор стоит с редуктором и 200 полных шагов н оборот это далеко не полный оборот на устройстве. но все же.
Но даже если так, то что мешает делать 0.8 -0,9 сек шаги мотором (подобрать по месту), а потом опять получать данные с ГПС ?
 

Romashchandr

✩✩✩✩✩✩✩
19 Июл 2022
19
0
@PiratFox, а есть пример как признать переменную course старой переменной old course и сравнивать с вновь полученной course/
Там код простой
да функция сразу возвращает значение в градусах.

Но даже если так, то что мешает делать 0.8 -0,9 сек шаги мотором (подобрать по месту), а потом опять получать данные с ГПС
пока так , наверное и происходит или наоборот неправильно происходит.

Миллис запускает вывод данных с жпс каждые 2.5 секунды, а затем запускается мотор каждые 10мс.


задача то дурацкая , компас механический, на данных жпс
 
Изменено:

Старик Похабыч

★★★★★★★
14 Авг 2019
4,192
1,281
Москва
Если других обязанностей на ардуину не предполагается, то вполне можно сделать с делеями.
Т.е. читаем, далее шаги мотра каждые 10 мс (можно чаще, каждую 1 мс) шагаем до достижения круса. повторяем . вроде все просто.
если так и задумано, но не выходит , то сообщите, завтра гляну код, сегодня по плану хенесси , а он как бы не располагает к чтению чужого кода
 

PiratFox

★★★★★✩✩
13 Фев 2020
1,724
481
а есть пример как признать переменную course старой переменной old course и сравнивать с вновь полученной course/
Ну, алгоритм такой:
1. В setup добавить old_course = course;
2. В loop опрашивать gps и сравнивать:
course = опросить gps;
если course != old_course {
old_course = course;
двигать мотор согласно course; }
ждать нового опроса gps;
Как-то так.
 
Изменено:

Romashchandr

✩✩✩✩✩✩✩
19 Июл 2022
19
0
.е. читаем, далее шаги мотра каждые 10 мс (можно чаще, каждую 1 мс) шагаем до достижения круса. повторяем . вроде все просто.
если так и задумано, но не выходит , то сообщите, завтра гляну код
я сделал с Делэй так: датчик читает данные, потом задержка 5 cек. , а мотор я загнал в void yeld().
и вот не крутится мотор от слова совсем даже на драйвере лампочки не горят.

если что у обоих вариантов код максимально одинаковый. разница только в части отвечающей за время.
 

Старик Похабыч

★★★★★★★
14 Авг 2019
4,192
1,281
Москва
не так
1 читаются данные.
2. далее цикл типа такого:
C++:
uint32_t tmr=miilis();
// тут нужно вычислить нужное число шагов исходя из разницы курсов, а так же задать направление вращения.
while (millis()-tmr<5000)
   if (число шагов не равно нулю)
{
    тут 1 шг мотором в нужную сторону и нужная задержка между шагами в мик через delayMicroseonds
   число шагов уменьшить на 1
}
пе
 

Boroda22

★✩✩✩✩✩✩
23 Фев 2022
240
42
а у Гайвера случаем не было подобного видео, кажется он собирал подобное
 

Romashchandr

✩✩✩✩✩✩✩
19 Июл 2022
19
0
@PiratFox,
что то не получилось
C++:
 if (val != old_course) {    // разрешает крутится мотору если новое показание не равно старому, НЕ РАБОТАЕТ
// val += old_course - val; //двигать мотор на разницу старого и нового курса; пока закомментировал
  stepper.tick();
    stepper.setTargetDeg(val, ABSOLUTE);     // ставим новую позицию
}
1. В setup добавить old_course = val;
2. В loop опрашивать gps и сравнивать
это естественно сделал


@Старик Похабыч, кажеться понял что вы предлагаете. но не понял почему нельзя использовать две библиотеки: одна выдает курс в градусах, а другая крутит мотор в градусах.
 
Изменено:

PiratFox

★★★★★✩✩
13 Фев 2020
1,724
481
@Romashchandr, во-первых, откуда берётся val? Далее, поменять местами строки 3, 4 и перед пуском мотора stepper.tick(); нужно сделать присвоение old_course = val. Примерно так:

C++:
 if (val != old_course) {    // разрешает крутится мотору если новое показание не равно старому, НЕ РАБОТАЕТ
// val += old_course - val; //двигать мотор на разницу старого и нового курса; пока закомментировал
    
     stepper.setTargetDeg(val, ABSOLUTE);     // ставим новую позицию
     old_course = val;
     stepper.tick();
}
 
Изменено:

Romashchandr

✩✩✩✩✩✩✩
19 Июл 2022
19
0
@Старик Похабыч, кажеться понял что вы предлагаете. попробую для саморазвития.

НО я не понял почему нельзя использовать две библиотеки: одна выдает курс в градусах, а другая крутит мотор в градусах.

@PiratFox,
что то вы путаете , если stepper.tick ставить в конце ничего не работает абсолютно.
да и в примера Гайвера эта команда стоит всегда первой, там же задание переменной и уже в конце команда типа
stepper.setTargetDeg(val, ABSOLUTE);

откуда берётся val?
у меня в коде изначально переменная val и была. в нее записываются данные курса,
 

Старик Похабыч

★★★★★★★
14 Авг 2019
4,192
1,281
Москва
Почему нельзя, наверное можно. У каждого свой "таков путь". Но для этого надо хорошо понимать что делают функции библиотеки мотора.
 

PiratFox

★★★★★✩✩
13 Фев 2020
1,724
481
что то вы путаете , если stepper.tick ставить в конце ничего не работает абсолютно.
Ну, я исхожу из описания библиотеки Гайвера, которое он сам и приводит.
C++:
// Здесь происходит движение мотора, вызывать как можно чаще!
// Имеет встроенный таймер
// Возвращает true, если мотор движется к цели или крутится по KEEP_SPEED
bool tick();
Следовательно, нужно вначале задать цель с помощью stepper.setTargetDeg(val, ABSOLUTE), а потом уже двигать мотор при помощи stepper.tick . Описание всех функций библиотеки здесь, но как по мне, оно какое-то неполное и слегка туманное. Почему у Вас не работает - это другой вопрос. Возможно, Вы в коде что-то упустили, например, неправильно пересчитываются параметры для stepper.setTargetDeg при преобразовании gps координат. Разбирайтесь, это же Ваш код.
 

Romashchandr

✩✩✩✩✩✩✩
19 Июл 2022
19
0
@PiratFox, я конечно проштудировал его бибилиотеки и на сайте и в гитхабе неоднократно... мне не все понятно... но что то понял. и в примерах гайвера как раз СТеппер.тик стоит в начале
C++:
    stepper3.tick();
  static uint32_t tmr;
  if (millis() - tmr > 5000) {   // каждые 5 секунд
    tmr = millis();
    stepper3.setTarget(random(0, 2000));  // рандом 0-2000
  }
Возможно, Вы в коде что-то упустили, например, неправильно пересчитываются параметры для stepper.setTargetDeg при преобразовании gps координат.
тут как раз все более менее ровно. gps выдает курс (0-360). мотор у крутит на полученную от gps цифру. ЕСЛИ он успевает это сделать за период срабатывания таймера ЖПС. если нет, то крутит столько сколько успеет.

Ну и самая главная проблема. каждый цикл он крутится на вновь полученную цифру от ЖПС. .Например на 180 градусов каждый цикл.

Для компаса необходимо в конце цикла записывать цифру полученного курса от ЖПС, а в начале следующего цикла получать разность между данными ЖПС старого цикла и нового цикла. после чего мотор будет крутится именно на разность данных.
если я правильно понимаю для этого нужно
C++:
static float  new_course;
  static float real_course
  static float old_course;  //три глобальные переменные

void loop

// Выводим курс
       new_course += gps.course;  //пишем данные с gps
real_course += old_course -  new_course; // вычисляем угол на который должен повернуться мотор в новом цикле

// крутим мотор
stepper.tick();
    stepper.setTargetDeg(real_course, ABSOLUTE);  
//сохраняем данные для нового цикла
old_course = new_course;
таймеры опустил.
где я ошибаюсь?
 

PiratFox

★★★★★✩✩
13 Фев 2020
1,724
481
@Romashchandr, можете дать ссылку на используемую библиотеку приёмника gps? И да, почему у Вас все переменные course типа static float, а не просто float, они же всё равно объявлены как глобальные.
 
Изменено:

Romashchandr

✩✩✩✩✩✩✩
19 Июл 2022
19
0
@PiratFox, две библиотеки https://iarduino.ru/file/539.html
https://iarduino.ru/file/538.html

static потому что
" Вспомним, как работает обычная локальная переменная: при входе в свой блок кода локальная переменная создаётся заново, а при выходе – удаляется из памяти и теряет своё значение. Если локальная переменная объявлена как
static
– она будет сохранять своё значение на всём протяжении работы программы, но область видимости останется локальной: взаимодействовать с переменной можно будет только внутри блока кода, где она создана (и во всех вложенных в него) "

а то что это глобальная переменная и соответсвенно имеет то же самое, я и не подумал, а может подумал, но плохо
 

PiratFox

★★★★★✩✩
13 Фев 2020
1,724
481
@Romashchandr, Библиотеки я посмотрел, вроде без непоняток. Непонятно мне другое, вот в этой строке:
new_course += gps.course; //пишем данные с gps
зачем делать составное сложение += вместо того, чтобы просто присвоить новое значение? Например, вот так:
new_course = gps.course; //пишем данные с gps
Кстати, к строке:
real_course += old_course - new_course; // вычисляем угол на который должен повернуться мотор в новом цикле
такой же вопрос.
 
Изменено:

Romashchandr

✩✩✩✩✩✩✩
19 Июл 2022
19
0
хмм. скорей всего просто копировал откуда то строку и так и осталось.
 

Romashchandr

✩✩✩✩✩✩✩
19 Июл 2022
19
0
с расчетами переменной разобрался. для контроля, вывел в монитор значения каждой переменной.
две переменные сделал глобальными, одну (new_course) локальной.
Получилось, что если показания ЖПС не меняются, то переменная real_course принимает нулевое значение, команда на движение мотора не поступает. в ином случае на драйвер мотора поступает сигнал --- драйвер мотора зажигает лампочки, мотор шевелится

Но одновременно стал неправильно работать мотор, делает шаг раз в секунду, (даже не поворот на 1 градус в секунду, а именно один шаг/сек)

C++:
//Обьявляем переменные курса

//  float course;  //?? оно надо??
  float old_course;
  float real_course;


  void setup() {
stepper.setRunMode(FOLLOW_POS);   // режим следования к целевй позиции
stepper.setMaxSpeed(400);         // установка макс. скорости в шагах/сек
stepper.setAcceleration(100);     // установка ускорения в шагах/сек/сек
  // пусть драйвер выключается при достижении позиции
stepper.autoPower(true);


   // Инициируем последовательный порт
    Serial.begin(9600);
// Инициируем работу с модулем GPS
     SettingsGPS.begin(SerialGPS);                 //  Инициируем работу с GPS модулем по указанной шине UART. Функция сама определит текущую скорость GPS модуля ATGM336 (вместо программной шины, можно указывать аппаратные: Serial, Serial1, Serial2, Serial3).
         // Инициируем интерпретацию строк NMEA
    gps.begin(SerialGPS);
    // Устанавливаем часовой пояс
    gps.timeZone(3);
    // Устанавливаем скорость передачи данных модулем
    SettingsGPS.baudrate(9600);
    // Указываем, что данные можно получать от спутников GPS и GLONASS
    SettingsGPS.system(GPS_GP, GPS_GL);
    // Указываем, что нам необходимы только строки с текущей скоростью и временем
    SettingsGPS.composition(NMEA_VTG, NMEA_ZDA, NMEA_GLL);
    // Устанавливаем режим "Транспортное средство"
    SettingsGPS.model(GPS_VEHICLE);
    // Указываем частоту обновления
    SettingsGPS.updaterate(1);

}

void loop() {

   if (millis() - myTimer1 >= 6000) {   // таймер на 2000 мс (1 раз в 2 сек)
    myTimer1 = millis();              // сброс таймера
    // выполнить действие 1
    // Считываем данные из модуля
    gps.read(i,true);
  float new_course;
    // Если курс ошибочен
   if (gps.errCrs) {
 
       real_course = 45;
     Serial.print("Скорость и курс недостоверны. ");
   }
       // Иначе
   else {
       /* Координаты (широта, долгота, высота):      */ // Serial.print("Ш: "); Serial.print(gps.latitude,5); Serial.print("°, Д: "); Serial.print(gps.longitude,5); Serial.print("°, В: "); Serial.print(gps.altitude,1); Serial.print("м. ");
// Serial.print("Скорость: "); Serial.print(gps.speed); Serial.print("км/ч, "); Serial.print(gps.course); Serial.print("°. ");
        // Выводим курс
Serial.print("ЖПС"); Serial.print(gps.course); Serial.print("°. ");
     float new_course;
     new_course = gps.course;
//    if (new_course!=old_corse) {
       real_course = new_course - old_course;
//      }
//    else (real_course = 0)  
  Serial.print("new_course");Serial.print(new_course);

Serial.print("real_course");Serial.print(real_course);  
old_course = new_course;
 
Serial.print("old_course");Serial.print(old_course);
  }
     }



 
       if (millis() - myTimer2 >= 3) {   // таймер на 333 мс (3 раза в сек)
    myTimer2 = millis();              // сброс таймера
    // выполнить действие 2

//двигать мотор согласно course;
  stepper.tick();
    stepper.setTargetDeg(real_course, RELATIVE);     // ставим новую позицию

}
       }
 

Старик Похабыч

★★★★★★★
14 Авг 2019
4,192
1,281
Москва
Вот эту команду надо делать как можно чаще.
stepper.tick();
Т.е. смело можно ее вызывать в самом начале loop без всяких условий.
 
  • Лойс +1
Реакции: poty

poty

★★★★★★✩
19 Фев 2020
2,989
895
Вообще не понимаю, что делает эта программа. Кто задаёт курс (old_course нигде не определён, фактически после первого использования со случайным значением внутри приравнивается к gps.course, который и является текущим реальным курсом, однако real_course вычисляется из двух, фактически случайных, направлений)? Почему считается, что угол мотора (включая направление вращения) будет соответствовать курсу? Каким образом, без анализа координат, кто-то может быть уверен, что аппарат, отклонившись от заданного курса, пролетев некоторое расстояние в другом направлении, а потом выровнявшись на правильный курс придёт в нужную точку?
 

Romashchandr

✩✩✩✩✩✩✩
19 Июл 2022
19
0
команду надо делать как можно чаще.
Кстати часто вижу эту фразу у гайвера. но до конца смысл до меня не доходит
как можно чаще -- я могу через строчку писать команду, но что это даст?
как часто надо давать команду в таких случаях?
или под этим что то другое понимается?
 

Старик Похабыч

★★★★★★★
14 Авг 2019
4,192
1,281
Москва
Нет, через строчку это дурь
Есть цикл loop - это цикл! он крутиться не переставая . Соотв. тИкать надо в каждом цикле - библиотека сама знает когда тик будет полезным, а когда холостым, соотв. делать это надо без условий.
Если надо замедлить скорость мотора, то делать это надо изменением скорости, а не частоты вызова тика.
Еще надо позаботиться , чтобы остальные функции в loop не занимали чрезмерно много времени. Если такое невозможно, то мотор не будет работать на полную скорость. Если функции долгие, а надо крутить быстро тИкать надо по прерыванию таймера.
 
  • Лойс +1
Реакции: Romashchandr