Шаговые моторы проблема со скоростью

Тема в разделе "Arduino & Shields", создана пользователем sanik, 7 янв 2020.

Метки:
  1. sanik

    sanik Гик

    Доброго времечка! Не оставьте в беде подкиньте идею В чем может быть загвоздка Есть три шаговика Сделал разгон на таймере все работает отлично в отдельности. А вот все три некорректно. Суть в том что скорость берется общая по непонятным причинам причем самая минимальная все три мотора разгоняются до первого меньшего значения и крутятся на нем хотя в коде прописано что два других должны набирать свою скорость.
    Код (C++):
    byte LR_Dolly = 0;  // Направление в лево
    int Speed_Dolly = 80; //  Скорость
    long countStep_Dolly = 26000; //// подсчитываем количество импульсов
    #define powerMotor_Dolly 10 // Питание мотора X
    //------------------------------------------------------------------------------

    int Speed_Pan = 100;   //
    byte LR_Pan = 1; //  направление
    long countStep_Pan = 5200; // подсчитываем количество импульсов
    #define powerMotor_Pan 7 // Питание мотора Y

    //-----------------------------------------------------------------------------

    int Speed_Tilt = 150;   //  Скорость
    byte LR_Tilt = 0; //  направление
    long countStep_Tilt = 6670; // подсчитываем количество импульсов
    #define powerMotor_Tilt 13 // Питание мотора Z

    //------------------------------------------------------------------------------

    #define dir_Dolly 8
    #define step_Dolly 9
    #define dir_Pan 5
    #define step_Pan 6
    #define dir_Tilt 12
    #define step_Tilt 11


    // Счетчик текущей позиции
    long Position_Dolly = 0;
    long Position_Pan = 0;
    long Position_Tilt = 0;

    int Sp_Dolly = 500; // начальная скорость
    int Sp_Pan = 1000;
    int Sp_Tilt = 1100;

    int speedCount_Dolly = Sp_Dolly; // cчетчик разгона
    unsigned int  StepTime_Dolly = 1;
    unsigned long prStep_Dolly = 0;

    int speedCount_Pan = Sp_Pan;
    unsigned int  StepTime_Pan = 1;
    unsigned long prStep_Pan = 0;

    int speedCount_Tilt = Sp_Tilt;
    unsigned int  StepTime_Tilt = 1;
    unsigned long prStep_Tilt = 0;

    void setup() {
      pinMode(dir_Dolly, OUTPUT);
      pinMode(step_Dolly, OUTPUT);
      pinMode(dir_Pan, OUTPUT);
      pinMode(step_Pan, OUTPUT);
      pinMode(dir_Tilt, OUTPUT);
      pinMode(step_Tilt, OUTPUT);
      pinMode(powerMotor_Dolly , OUTPUT);
      digitalWrite(powerMotor_Dolly, HIGH);
      pinMode(powerMotor_Pan , OUTPUT);
      digitalWrite(powerMotor_Pan, HIGH);
      pinMode(powerMotor_Tilt , OUTPUT);
      digitalWrite(powerMotor_Tilt, HIGH);

    }

    void loop() {
      RunMotorALL();
    }


    void RunMotorALL() {
      byte exD = 1;
      boolean flag_Dolly = true;
      boolean flag_Pan = true;
      boolean flag_Tilt = true;


      // ***************************Первый мотор*************************

      while (exD != 0) {
        if (LR_Dolly == 0) {
          digitalWrite(dir_Dolly, LOW);
          if (millis() - prStep_Dolly > StepTime_Dolly) {
            prStep_Dolly = millis();
            if (flag_Dolly == true && Sp_Dolly > Speed_Dolly) { // увеличиваем скорость
              speedCount_Dolly--;
              if (speedCount_Dolly < Speed_Dolly) {
                speedCount_Dolly = Speed_Dolly;
              }
            }
            if (speedCount_Dolly == Speed_Dolly && countStep_Dolly == 1100) {
              flag_Dolly = false;
            }

            if (flag_Dolly == false ) {
              if (countStep_Dolly < 1100) { // уменьшаем скорость
                speedCount_Dolly++;
                if (speedCount_Dolly > Sp_Dolly) speedCount_Dolly = Sp_Dolly;
              }
            }

          }
          digitalWrite(step_Dolly, HIGH);
          delayMicroseconds(speedCount_Dolly);
          countStep_Dolly --;
          digitalWrite(step_Dolly, LOW);
          delayMicroseconds(speedCount_Dolly);

        }

        // ***************************Второй мотор*************************
        if (LR_Pan == 1) {
          digitalWrite(dir_Pan, HIGH);
          if (millis() - prStep_Pan > StepTime_Pan) {
            prStep_Pan = millis();
            if (flag_Pan == true && Sp_Pan > Speed_Pan) {
              speedCount_Pan--;
              if (speedCount_Pan < Speed_Pan) {
                speedCount_Pan = Speed_Pan;
              }
            }
            if (speedCount_Pan == Speed_Pan && countStep_Pan == 600) {
              flag_Pan = false;
            }

            if (flag_Pan == false ) {
              if (countStep_Pan < 600) {
                speedCount_Pan++; // каждую милисекунду прибавляем счетчик пока не достигнем  600
                if (speedCount_Pan >= Sp_Pan) speedCount_Pan = Sp_Pan;
              }
            }
          }

          digitalWrite(step_Pan, HIGH);
          delayMicroseconds(speedCount_Pan);
          countStep_Dolly --;
          digitalWrite(step_Pan, LOW);
          delayMicroseconds(speedCount_Pan);

        }

    // ***************************Третий мотор*************************
        if (LR_Tilt == 0) {
          digitalWrite(dir_Tilt, LOW);
          if (millis() - prStep_Tilt > StepTime_Tilt) {
            prStep_Tilt = millis();
            if (flag_Tilt == true && Sp_Tilt > Speed_Tilt) {
              speedCount_Tilt--;
              if (speedCount_Tilt < Speed_Tilt) {
                speedCount_Tilt = Speed_Tilt;
              }
            }
            if (speedCount_Tilt == Speed_Tilt && countStep_Tilt == 600) {
              flag_Tilt = false;
            }
            if (flag_Tilt == false ) {
              if (countStep_Tilt < 600) {
                speedCount_Tilt++;
                if (speedCount_Tilt >= Sp_Tilt) speedCount_Tilt = Sp_Tilt;
              }
            }
          }

          digitalWrite(step_Tilt, HIGH);
          delayMicroseconds(speedCount_Tilt);
          countStep_Tilt --;
          digitalWrite(step_Tilt, LOW);
          delayMicroseconds(speedCount_Tilt);
        }


      }
    }
     
  2. Daniil

    Daniil Гуру

    Код мозговыносящий:confused:
    похожие названия к разным переменным - speedCount и countSpeed к одному мотору, все что относится к одному мотору разбросано по коду, магические числа в самом коде, разные типы у, вроде бы, похожих по смыслу переменных заметил, что просто порядок объявления переменных разный, но их типы всё же неоптимально выбраны. While попал к 1-му мотору (судя по коментарию), хотя, кажется, это очередной цикл в цикле (понятно, что это заготовка на будущее, но тоже мешает чтению).
    Что бросается в глаза:
    Если я правильно понял, то поворот каждого мотора обеспечивается дерганьем ноги step_XYZ. Каждая нога дергается с некоторой задержкой (speedCount), поэтому максимальная скорость зависит от периода дерганья ногой, но при увеличении кол-ва моторов период дерганья растет в N раз из-за самого наличия задержек в алгоритме другого мотора. Кажется, что данная проблема должна была решиться наличием временного разделения управления с помощью millis (stepTime), но не происходит ли наложения? Ведь, получается "умная" задержка и "тупая" задержка имеют один и тот же порядок (1 мс. против 500-1100 мкс.), да и "умная" задержка у всех моторов одинаковая, т.е. временного разделения нет от слова "совсем".
    Если бы максимальная сумма удвоенных (пренебрегаю уменьшением на 1 каждую итерацию) всех "тупых" задержек была бы меньше минимального периода "умной" задержки одного из моторов, например, на порядок, то можно было бы пытаться гадать дальше в чем проблема, но, я считаю, что лучшим решением будет это изучение аппаратного таймера и построение алгоритма управления набора моторов более оптимальным образом. Ну или избавиться от "тупых" задержек, что породит еще стопку переменных...
    Для более удобного чтения кода, и написания, и оптимизации, т.к. алгоритмы управления у вас одинаковые и язык С, то, я думаю, было бы удобно создать структуру, которая описывает все параметры мотора и его текущее состояние. А потом создал бы массив из этих структур. В лупе запускал бы цикл по массиву и больше бы не парился бы огромным количеством переменных, отличающихся только окончанием. Код стал бы в 3 раза короче.
     
    Последнее редактирование: 9 янв 2020
    Un_ka нравится это.
  3. vvr

    vvr Инженерище

    панорамную головку на слайдере гоняем ?
     
  4. sanik

    sanik Гик

    Давно гоняю но только в режиме таймлапса Хотелось бы внедрить простой режим Но увы Сколько не брался так ничего и не получается.
     
  5. sanik

    sanik Гик

    Спасибо! Я понял вашу идею. но с масивами у меня как то трудно попытаюсь испробовать своими силами насколько я умею. Но что странно в другом проекте это работает правда там немного другой принцип На одной задержке millis несколько счетчиков которые сбрасываются в нужный момент Там нет наложения по времени Хотя и задержки в миллис а не микросекунд. Ну а по поводу переменных для меня так удобней. Все же лучше че типа R SX AB и так далее)
     
  6. vvr

    vvr Инженерище

    я сейчас тоже очередной рельс собираю...

    простой режим на шаговиках не совсем хорошее решение.
    на медленных проводках дёрганья будут видны даже в режиме большого микрошага.
    мотор-редуктор даёт более плавное движение.
    проверено..
    для таймлапсов подходят оба.
     
  7. Daniil

    Daniil Гуру

    может поэтому и нет наложения.
    Художнику виднее:) но изучение массивов не задвигайте в долгий ящик
     
  8. sanik

    sanik Гик

    У меня изначально применены шаговые с редуктором. Я долго свой слайдер изготовлял Вот он. Правда на видео более старая версия и старый код Сейчас контроллер стал выглядеть более приятным уменьшился в размерах. И приобрел более заводской вид.

     
  9. sanik

    sanik Гик

    Спасибо! Подскажите с чего начать а то в интернете столько лишней информации что пока доберешься до сути голову сломаешь потеряв годы.
     
  10. sanik

    sanik Гик

    Да и простые движки я юзал в свое время но увы тогда мало знал и код получился малоэффективный.Зато управление было по радиомодулю и никаких проводов)

     
  11. Daniil

    Daniil Гуру

    Керниган и Ритчи "язык программирования ansi C" - тонкая книжка, в спокойном темпе рассказывает обо всем в яп С (без ооп из с++).
     
    parovoZZ нравится это.
  12. sanik

    sanik Гик

    Попробовал я сделать так думал будет поочередно подавать сигнал но ничего не изменилось. а как сделать смещение во времени?
    Код (C++):
     for (int i = 0; i < 3; i++) {
          digitalWrite(steps [i], HIGH);
          delayMicroseconds(speedCount_Tilt);
        }
        for (int i = 0; i < 3; i++) {
          digitalWrite(steps [i], LOW);
          delayMicroseconds(speedCount_Tilt);
        }
     
  13. sanik

    sanik Гик

    Вот полностью
    Код (C++):
    byte LR_Dolly = 0;  // Направление в лево
    int Speed_Dolly = 100; //  Скорость
    long countStep_Dolly = 26000; //// подсчитываем количество импульсов
    #define powerMotor_Dolly 10 // Питание мотора X
    //------------------------------------------------------------------------------

    int Speed_Pan = 120;   //
    byte LR_Pan = 1; //  направление
    long countStep_Pan = 15200; // подсчитываем количество импульсов
    #define powerMotor_Pan 7 // Питание мотора Y

    //-----------------------------------------------------------------------------

    int Speed_Tilt = 150;   //  Скорость
    byte LR_Tilt = 0; //  направление
    long countStep_Tilt = 16670; // подсчитываем количество импульсов
    #define powerMotor_Tilt 13 // Питание мотора Z

    //------------------------------------------------------------------------------

    #define dir_Dolly 8
    #define dir_Pan 5
    #define dir_Tilt 12
    int steps [] = {9, 6, 11};

    // Счетчик текущей позиции
    long Position_Dolly = 0;
    long Position_Pan = 0;
    long Position_Tilt = 0;

    int Sp_Dolly = 500; // начальная скорость
    int Sp_Pan = 1000;
    int Sp_Tilt = 1100;

    int speedCount_Dolly = Sp_Dolly; // cчетчик разгона
    unsigned int  StepTime_Dolly = 1;
    unsigned long prStep_Dolly = 0;

    int speedCount_Pan = Sp_Pan;
    unsigned int  StepTime_Pan = 1;
    unsigned long prStep_Pan = 0;

    int speedCount_Tilt = Sp_Tilt;
    unsigned int  StepTime_Tilt = 1;
    unsigned long prStep_Tilt = 0;

    void setup() {
      for (int i = 0; i < 3; i++) {
        pinMode(steps [i], OUTPUT);
      }
      pinMode(dir_Dolly, OUTPUT);
      pinMode(dir_Pan, OUTPUT);
      pinMode(dir_Tilt, OUTPUT);
      pinMode(powerMotor_Dolly , OUTPUT);
      pinMode(powerMotor_Pan , OUTPUT);
      pinMode(powerMotor_Tilt , OUTPUT);
    }

    void loop() {

      RunMotorALL();
    }


    void RunMotorALL() {
      byte exD = 1;
      boolean flag_Dolly = true;
      boolean flag_Pan = true;
      boolean flag_Tilt = true;


      // ***************************Направление в лево*************************

      while (exD != 0) {
        digitalWrite(powerMotor_Pan, HIGH);
        digitalWrite(powerMotor_Dolly, HIGH);
        digitalWrite(powerMotor_Tilt, HIGH);
        if (LR_Dolly == 0) {
          digitalWrite(dir_Dolly, LOW);
          if (millis() - prStep_Dolly > StepTime_Dolly) {
            prStep_Dolly = millis();
            if (flag_Dolly == true && Sp_Dolly > Speed_Dolly) { // увеличиваем скорость
              speedCount_Dolly--;
              if (speedCount_Dolly < Speed_Dolly) {
                speedCount_Dolly = Speed_Dolly;
              }
            }
            if (speedCount_Dolly == Speed_Dolly && countStep_Dolly == 1100) {
              flag_Dolly = false;
            }

            if (flag_Dolly == false ) {
              if (countStep_Dolly < 1100) { // уменьшаем скорость
                speedCount_Dolly++;
                if (speedCount_Dolly > Sp_Dolly) speedCount_Dolly = Sp_Dolly;
              }
            }

          }

        }

        // ***************************Направление в право*************************
        if (LR_Pan == 1) {
          digitalWrite(dir_Pan, HIGH);
          if (millis() - prStep_Pan > StepTime_Pan) {
            prStep_Pan = millis();
            if (flag_Pan == true && Sp_Pan > Speed_Pan) {
              speedCount_Pan--;
              if (speedCount_Pan < Speed_Pan) {
                speedCount_Pan = Speed_Pan;
              }
            }
            if (speedCount_Pan == Speed_Pan && countStep_Pan == 600) {
              flag_Pan = false;
            }

            if (flag_Pan == false ) {
              if (countStep_Pan < 600) {
                speedCount_Pan++; // каждую милисекунду прибавляем счетчик пока не достигнем  600
                if (speedCount_Pan >= Sp_Pan) speedCount_Pan = Sp_Pan;
              }
            }
          }

        }


        if (LR_Tilt == 0) {
          digitalWrite(dir_Tilt, LOW);
          if (millis() - prStep_Tilt > StepTime_Tilt) {
            prStep_Tilt = millis();
            if (flag_Tilt == true && Sp_Tilt > Speed_Tilt) {
              speedCount_Tilt--;
              if (speedCount_Tilt < Speed_Tilt) {
                speedCount_Tilt = Speed_Tilt;
              }
            }
            if (speedCount_Tilt == Speed_Tilt && countStep_Tilt == 600) {
              flag_Tilt = false;
            }
            if (flag_Tilt == false ) {
              if (countStep_Tilt < 600) {
                speedCount_Tilt++;
                if (speedCount_Tilt >= Sp_Tilt) speedCount_Tilt = Sp_Tilt;
              }
            }
          }
        }

        for (int i = 0; i < 3; i++) {
          digitalWrite(steps [i], HIGH);
          delayMicroseconds(speedCount_Tilt);
        }
        for (int i = 0; i < 3; i++) {
          digitalWrite(steps [i], LOW);
          delayMicroseconds(speedCount_Tilt);
        }
        countStep_Tilt --;
        countStep_Dolly --;
        countStep_Pan --;
      }
    }
     
  14. Daniil

    Daniil Гуру

    Потому что по сути ничего не изменилось.
    Чтобы нам выполнять некоторые операции, которым нужна задержка, без использования "тупых" задержек нам нужно ввести таймер. Таймер это переменная, которая будет хранить время последнего вызова нужных операций и, соответственно, этому таймеру нужно иметь пару, которая будет задавать период выполнения операций.
    Код (C++):

    uint16_t period_ms = 16; //период выполнения программы
    unsigned long last_time = 0; // Переменная для хранения последнего выполнения программы
    void setup() {
      Serial.begin(9600);
    }
    void loop() {
      if (millis() - last_time > period_ms){
        last_time = millis();
        Serial.println ("good");
      }
    }
     
    теперь нужно научиться определять состояние пина и взводить его соответственно. Для этого нужно хранить переменную состояния пина.
    Код (C++):

    #define pin 1
    uint8_t pin_State=0;
    uint16_t period_ms = 16; //период выполнения программы
    unsigned long last_time = 0; // Переменная для хранения последнего выполнения программы
    void setup() {
      pinMode(pin, OUTPUT);
    }
    void loop() {
      if (millis() - last_time > period_ms){
        last_time = millis();
        digitalWrite(pin,pin_State);
        pin_State=!(pin_State); //инвертирование переменной состояния пина
      }
    }
     
    теперь у нас пин мигает постоянно с периодом period_ms.
    Попробуем теперь сделать массив из 2-х пинов.
    Код (C++):

    #define pin1 1
    #define pin2 2
    const uint8_t kol_Pins=2; // количество пинов с моторами
    uint8_t mpin_State[]={LOW, LOW};//массив состояний пинов
    const uint8_t mpin_Num[]={pin1, pin2};//т.к. пинов уже несколько, то одним дефайном уже не обойтись. Это массив номеров пинов
    uint16_t mperiod_ms = {16, 4900};//массив периодов выполнения программы
    uint32_t mlast_time = {0, 0}; //массив времён последнего выполнения кода для каждого пина

    void setup() {
      for (uint8_t num=0; num < kol_Pins; num++){
        pinMode(mpin_Num[num], OUTPUT);
      }
    }

    void loop() {
      for (uint8_t num=0; num < kol_Pins; num++){
        if (millis() - mlast_time[num] > mperiod_ms[num]){
          last_time[num] = millis();
          digitalWrite(mpin_Num[num],mpin_State[num]);
    //      if (mpin_State[num] == LOW) {//если мы хотим после выставления нуля
    //        mperiod_ms[num]--;//уменьшить период мигания пина, то находим момент времени когда == 0 (у вас так)
    //      }//и уменьшаем период.
    //(Обратите внимание, что в данном случае для начала уменьшаем период, а потом меняем состояние пина)
          mpin_State[num]=!(mpin_State[num]); //инвертирование переменной состояния пина
        }
      }
    }
     
    Теперь должны мигать 2 пина и не сильно влиять друг на друга. Собственно, мы реализовали программный ШИМ, В Loop нужно менять period_ms для каждого пина тоже с некоторой задержкой, поэтому нужно ввести ещё несколько переменных, которые соответствуют "таймеру" для изменения "таймера" мигания. Да, такая тавтология, но я надеюсь понятно. Кстати, эта часть у вас и реализована "по-умному".
    Код не проверял на работоспособность, но логика должна быть правильной.
     
  15. Daniil

    Daniil Гуру

    Вот со структурами. Сейчас стало только хуже, но когда вы сделаете ещё одну структуру motor_t, где будете использовать ещё раз тип timer_t для уменьшения с задержкой ещё какой-то переменной, то выигрыш появится.
    Код (C++):
    //Объявляем тип структуры таймера
    struct timer_t {
      uint16_t period_ms;
      uint32_t last_time;
    };
    //Объявляем тип структуры пина
    struct pin_t {
      uint8_t Name;
      uint8_t State;
      timer_t PWM;
    };

    #define pin1 D13
    #define pin2 A2
    const uint8_t kol_Pins=2; // количество пинов с моторами
    pin_t pins[kol_Pins];

    //Иницализация переменных
    void init_mas(){
      pins[0].Name=pin1;
      pins[0].State=LOW;
      pins[0].PWM.period_ms=13;
      pins[0].PWM.last_time=0;
      pins[1].Num=pin2;
      pins[1].State=LOW;
      pins[1].PWM.period_ms=1123;
      pins[1].PWM.last_time=0;
    }

    void setup() {
      init_mas();
      for (uint8_t num=0; num < kol_Pins; num++){
        pinMode(pins[num].Name, OUTPUT);
      }
    }

    void loop() {
      for (uint8_t num=0; num < kol_Pins; num++){
        if (millis() - pins[num].PWM.last_time > pins[num].PWM.period_ms){
          pins[num].PWM.last_time = millis();
          digitalWrite(pins[num].Name, pins[num].State);
    //      if (pins[num].State== LOW) {//если мы хотим после выставления нуля
    //        pins[num].PWM.period_ms--;//уменьшить период мигания пина, то находим момент времени когда == 0 (у вас так)
    //      }//и уменьшаем период.
    //(Обратите внимание, что в данном случае для начала уменьшаем период, а потом меняем состояние пина)
          pins[num].State=!(pins[num].State); //инвертирование переменной состояния пина
        }
      }
    }
     
     
    sanik нравится это.
  16. sanik

    sanik Гик

    Д и что то меня смущает и путает Инициализация переменных
    Код (C++):
    void init_mas() {
      pins[0].Name = pin1; // ?
      pins[0].State = LOW; // это преременная состояния пина под номером 0 из массива
      pins[0].PWM.period_ms = 13;// Это как я понял задержка мотора под номером 0 из массива
      pins[0].PWM.last_time = 0; // это переменная  для хранения последнего выполнения программы мотора под номером 0
      pins[1].Num = pin2; //?
      pins[1].State = LOW; // это преременная состояния пина под номером 1 из массива
      pins[1].PWM.period_ms = 1123; // Это  задержка мотора под номером 1 из массива
      pins[1].PWM.last_time = 0; // это переменная  для хранения последнего выполнения программы мотора под номером 1
    }
     
  17. sanik

    sanik Гик

    Разобрался Спасибо! А как мне теперь обращаться к нужному мотору Например если мне из участка какого либо кода надо остановить мотор 1 а мотор 0 должен вращаться , Я должен указать pins[1].State== 0; Верно? Ну и на последок мне нужно подсчитать сколько раз пин поменял состояние То есть нужно if (pins[0].State== LOW) count ++;
     
  18. Daniil

    Daniil Гуру

    На всякий случай поясню uintN_t - если читать с конца, то "_t" таким окончанием обычно обозначают типы, N - количество занимаемых бит (кратно 8), "int" - целое число, "u" от слова "беззнаковый".
    на всякий случай поясню, pin1 и pin2 обозначил в дефайнах.
    Я рассматриваю 1 цикл loop в целом, мне так удобнее. За один цикл loop я пробегаю по всем задержкам пинов и если у кого-то время вышло, то его обрабатываю.
    Я этого не заметил, думаю исправить не проблема;)
    Да, в квадратных скобках указывается номер мотора и с ним можно производить работу из вне. Обратите внимание, нумерация начинается с нуля.
    Остановку мотора мой код не предусматривает, я не думал что это необходимо. Решение в лоб установить таймер нужного мотора в maxINT, тогда он будет вращяться, но ооочень медленно, если, конечно, ему хватит такого периода. Но не хорошо подавать в холостую напряжение на мотор, поэтому нужно отредактировать код и алгоритм. К примеру в структуру pin_t ввести флаг uint8_t fOn. При управлении мотора в задержке проверять, если сейчас будет(!) state==1 и fOn==0 то break;. Флагом fOn можно управлять откуда угодно.
    Если же в моем коде из вне сделать state=1, то ничего не изменится, мотор может дернуться, но через 2 цикла (максимум) loop все точно вернется как было.
    Если понравились структуры, то еще можно посмотреть на битовые поля. Если у вас будет несколько флагов или дискретных состояний, то для экономии памяти битовые поля будут очень полезны. (см. книгу)
    Сколько раз он поменял состояние? Тогда после digitalWrite должен идти count++.
    Или сколько раз было полных периодов работы? (смена с 0 на 1, а потом с 1 на 0), тогда как вы написали - через if state==0 count++.
    Понятное дело count можно пихнуть в структуру pin_t.
     
    Последнее редактирование: 11 янв 2020
    sanik нравится это.
  19. sanik

    sanik Гик

    С типами я немного знаком И сразу понял. Была ошибка в именах пина у первого был name у второго Num что меня и смутило внимательно посмотрев исправил.
     
    Последнее редактирование: 11 янв 2020
  20. sanik

    sanik Гик

    break; Я встречал только в case switch Это получается
    if (pins[num].State == 1 && pins[num].fOn == 0) break;
    А команда остановки первого мотора будет выглядеть так?
    pins[0].fOn = 0; // остановка
     
    Последнее редактирование: 11 янв 2020