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

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

Метки:
  1. Daniil

    Daniil Гуру

    всё равно пока непонятно почему код не работает. Можете привести код полностью?
     
  2. sanik

    sanik Гик

    Он пока в беспорядке чисто тренировка и проверка на работоспособность из вне.
    Код (C++):
    byte LR_Pan = 1; //  направление
    byte LR_Dolly = 0;  // Направление в лево
    byte LR_Tilt = 0; //  направление

    uint16_t Speed_Dolly = 120; //  Установка скорости
    uint16_t Speed_Pan = 920;
    uint16_t Speed_Tilt = 350;

    uint16_t  Velocity_Dolly = 1400;//Установка скорости разгона моторов pins[1].PWM.period_ms = 1000;
    uint16_t  Velocity_Pan = 1800;
    uint16_t  Velocity_Tilt = 1600;
    #define powerMotor_Dolly 10 // Питание мотора X
    #define powerMotor_Pan 7 // Питание мотора Y
    #define powerMotor_Tilt 13 // Питание мотора Z
    #define dir_Dolly 8
    #define dir_Pan 5
    #define dir_Tilt 12
    //Объявляем тип структуры таймера
    struct timer_t {
      uint16_t period_ms;
      uint32_t last_time;
      uint16_t periodV_ms;
      uint32_t prew_time;
      uint16_t step_time;
    };

    #define pin1 9
    #define pin2 6
    #define pin3 11

    //Объявляем тип структуры пина
    struct pin_t {
      uint8_t Name; // номер пина
      uint8_t State; // состояние пина
      timer_t PWM;
      timer_t VLS;
      timer_t ST;
      uint32_t count;
      uint8_t fOn;
      boolean fVel;
    };

    const uint8_t kol_Pins = 3; // количество пинов step
    pin_t pins[kol_Pins];

    uint32_t pr = 0;

    //Иницализация переменных
    void init_mas() {
      pins[0].Name = pin1;
      pins[0].State = LOW; // преременная состояния пина под номером 0 Dolly из массива
      pins[0].PWM.period_ms = Velocity_Dolly;//  задержка мотора под номером 0 из массива
      pins[0].PWM.last_time = 0; //  переменная  хранения последнего обновления пина dir Dolly
      pins[0].VLS.periodV_ms = 1; //период наращивания скорости
      pins[0].VLS.prew_time = 0;
      pins[0].ST.step_time = Speed_Dolly; //установленная скорость;
      pins[0].count = 0;
      pins[0].fOn = 1;
      pins[0].fVel = true;
      pins[1].Name = pin2;
      pins[1].State = LOW; // преременная состояния пина под номером 1 Pan из массива
      pins[1].PWM.period_ms = Velocity_Pan; //  начальная скорость Pan
      pins[1].PWM.last_time = 0; // переменная  хранения последнего обновления пина dir Pan
      pins[1].VLS.periodV_ms = 1;
      pins[1].VLS.prew_time = 0;
      pins[1].ST.step_time = Speed_Pan;  //установленная скороость  Pan
      pins[1].count = 0;
      pins[1].fOn = 1;
      pins[2].Name = pin3;
      pins[2].State = LOW; // преременная состояния пина под номером 2 Tilt из массива
      pins[2].PWM.period_ms = Velocity_Tilt; // начальная скорость Pan
      pins[2].PWM.last_time = 0; // переменная  хранения последнего обновления пина dir Tilt
      pins[2].VLS.periodV_ms = 1;
      pins[2].VLS.prew_time = 0;
      pins[2].ST.step_time = Speed_Tilt; //установленная скороость Tilt
      pins[2].count = 0;
      pins[2].fOn = 1;
    }

    void setup() {
      // Serial.begin(9600);
      init_mas();
      for (uint8_t i = 0; i < kol_Pins; i++) {
        pinMode(pins[i].Name, OUTPUT);
      }
      pinMode(dir_Dolly, OUTPUT);
      digitalWrite(dir_Dolly, LOW);
      pinMode(dir_Pan, OUTPUT);
      digitalWrite(dir_Pan, HIGH);
      pinMode(dir_Tilt, OUTPUT);
      digitalWrite(dir_Tilt, LOW);
      pinMode(powerMotor_Dolly , OUTPUT);
      pinMode(powerMotor_Pan , OUTPUT);
      pinMode(powerMotor_Tilt , OUTPUT);
      digitalWrite(powerMotor_Pan, HIGH);
      digitalWrite(powerMotor_Dolly, HIGH);
      digitalWrite(powerMotor_Tilt, HIGH);
    }

    void loop() {
      // if (millis() - pr > 2000) {
      //  pr = millis();
      //  serial();
      // }

      if ( pins[0].count == 97982) {
        pins[0].fOn = 0;
      }

      for (uint8_t num = 0; num < kol_Pins; num++) {
        if (pins[0].State == 1 && pins[0].fOn == 0) {//
          if (num == 0) continue;
        }
        if (millis() - pins[num].VLS.prew_time > pins[num].VLS.periodV_ms) {
          pins[num].VLS.prew_time = millis();
          if ( pins[0].PWM.period_ms > pins[0].ST.step_time) {
            pins[0].PWM.period_ms--;//уменьшить период мигания пина,
          }
          if (pins[0].PWM.period_ms < pins[0].ST.step_time) {
            pins[0].ST.step_time = pins[0].ST.step_time;
          }
          //************************************************

          if (pins[1].PWM.period_ms > pins[1].ST.step_time) {
            pins[1].PWM.period_ms--;//уменьшить период мигания пина,
          }
          if (pins[1].PWM.period_ms < pins[1].ST.step_time) {
            pins[1].ST.step_time = pins[1].ST.step_time;
          }
          //*************************************************
          if (pins[2].PWM.period_ms > pins[2].ST.step_time) {
            pins[2].PWM.period_ms--;//уменьшить период мигания пина,
          }
          if (pins[2].PWM.period_ms < pins[2].ST.step_time) {
            pins[2].ST.step_time = pins[2].ST.step_time;
          }
        }
        if (micros() - pins[num].PWM.last_time > pins[num].PWM.period_ms) {
          pins[num].PWM.last_time = micros();
          digitalWrite(pins[num].Name, pins[num].State);
          pins[num].count++;//
          pins[num].State = !(pins[num].State); //инвертирование переменной состояния пина
        }
      }

    }

    void serial() {
      Serial.println("Dolly");
      Serial.println(pins[0].count);
      Serial.println("Pan");
      Serial.println(pins[1].count);
      Serial.println("Tilt");
      Serial.println(pins[2].count);
    }
     
  3. sanik

    sanik Гик

    Как я понял это из за того что continue; в цикле for в цикле wile он будет работать по другому.
    Хотя могу ошибаться
     
  4. sanik

    sanik Гик

    Сейчас проверил и остановил второй мотор а первый и третий как положено вращаются
    Код (C++):
    if (pins[1].State == 1 && pins[1].fOn == 0) {//
          if (num == 1) continue;
        }
     
  5. sanik

    sanik Гик

    Ту часть что отвечает за ускорение Переписал как положено...
    Код (C++):
    if (millis() - pins[num].VLS.prew_time > pins[num].VLS.periodV_ms) {
          pins[num].VLS.prew_time = millis();
          if ( pins[num].PWM.period_ms > pins[num].ST.step_time) {
            pins[num].PWM.period_ms--;//уменьшить период  пина,
          }
          if (pins[num].PWM.period_ms < pins[num].ST.step_time) {
            pins[num].ST.step_time = pins[num].ST.step_time;
          }
     
  6. Daniil

    Daniil Гуру

    Смотрите. Сейчас придерусь по стилю/оптимизации, которая вам, наверное, сейчас мало нужна. Я думаю, что для изменения скорости не нужно хранить step_time в структуре таймера, поэтому структуру timer_t можно было бы вообще ничем не дополнять, а step_time перенести в структуру pin_t.
    Проблема в том, что по смыслу period_ms и periodV_ms, а так же last_time и prew_time идентичны - они хранят периоды изменения пина/ускорения и время их последних изменений.
    Структура это не переменная, это описание типа переменной.
    Поэтому у вас получилось что для pin[num].PWM выделяется память для prew_time и для pin[num].ST выделяется память под last_time, которые вы не используете, хотя, опять таки, по смыслу это одно и тоже. Вы могли обращаться как к pin[num].PWM.last_time, так и к pin[num].ST.last_time и получать разные значения.
    Поэтому, я предложил вынести в step_time к стуктуре pin_t.
    Но
    Я вижу, что по step_time несёт смысловую нагрузку у pin[num].ST, поэтому можно было бы создать ещё одну структуру, похожую на таймер, но дополнительно она имела бы ещё и step_time (ознакомьтесь со структурами и типами).
    Ну это всё оптимизационная лирика, пока памяти хватает по лбу не получите:D

    А как вы ранее писали обработку остановки мотора, что оно не работало?
    Что если написать так? continue находится перед блоком изменения пина, ведь именно его нужно пропустить.
    Код (C++):
        if (micros() - pins[num].PWM.last_time > pins[num].PWM.period_ms)
        {
            if ((pins[num].State == 1) && (pins[num].fOn == 0)) continue;
            pins[num].PWM.last_time = micros();
            digitalWrite(pins[num].Name, pins[num].State);
            pins[num].count++;//
            pins[num].State = !(pins[num].State); //инвертирование переменной состояния пина
        }
    Почти одинаково, переход к концу цикла. У цикла for обязательно выполняется оператор который указан в 3-й позиции (num++).
    А что тут делает 2-е условие? мне кажется от него можно избавиться и ничего не изменится. period_ms уменьшается до тех пор пока условие pins[num].PWM.period_ms > pins[num].ST.step_time не станет ложным, т.е. до того момента как pins[num].PWM.period_ms станет равным pins[num].ST.step_time, а значит условие pins[num].PWM.period_ms < pins[num].ST.step_time не выполняется никогда. Что может привести к уменьшению period_ms? я не нашёл, если в другом месте кода, то может быть и выполнится условие.
     
    sanik нравится это.
  7. sanik

    sanik Гик

    Заработало! Счетчик поставил на уменьшение так легче управлять))
    Код (C++):
    if (micros() - pins[num].PWM.last_time > pins[num].PWM.period_ms) {
          if ((pins[num].State == 1) && (pins[num].fOn == 0)) continue;
          pins[num].PWM.last_time = micros();
          pins[num].State = !(pins[num].State); //инвертирование переменной состояния пина
          digitalWrite(pins[num].Name, pins[num].State);
          pins[num].count--;//
        }
     
    Daniil нравится это.
  8. sanik

    sanik Гик

    Но они же имеют разные значения по времени.Я попробовал заменить pins[num].VLS.prew_time
    Код (C++):
    if (millis() - pins[num].PWM.last_time > pins[num].VLS.periodV_ms) {
    и движки понеслись как угорелые )
     
  9. sanik

    sanik Гик

    Перед каждым новым входом в цикл я так понимаю мне нужно вызвать init_mas(); ? Просто я заметил что при выходе у меня например pins[1].PWM.period_ms отличается от начального.
     
  10. Daniil

    Daniil Гуру

    Какой из циклов вы имеете в виду?
    я написал инициализацию в самом начале, т.к. она обязательна, т.к. после ресета не гарантируются адекватные данные. Как пример, в самом начале нужно указать номер пина - без этого точно работать не будет.
    Вы fOn меняете как вам угодно, в любой момент программы, так и настройки таймера имеете право менять когда вам нужно. Ваша задача продумать алгоритм. Если по истечении N времени вам нужно запустить процесс с начальными или другими временными интервалами, то, конечно, "инициализировать" повторно нужно.
    В кавычках написал, т.к. повторная "инициализация" просто устанавливает новые временные интервалы. Как минимум пины уже не нужно обозначать заново.
    Аналогия с грузовиком. Он, код/грузовик, едет по кругу из точки А в точку А (по кругу же). В самом начали инициализируем/собираем его (колеса/пины устанавливаем). И кладем в него ящики/таймеры. По пути он делает остановки и по нескольку ящиков оставляет. Когда он доедет до т. А, то он может быть пустой, но чтобы его запустить заново собирать его уже не нужно, только вынуть старые ящики и загрузить новые..
    тут вы явно чего-то недопонимаете.
    Посмотрите пример где я создавал точки и геометрические фигуры. Тип point_t у всех фигур одинаковый, а у вас получается, что вы в памяти выделяете некий диапазон для таймеров вращения мотора (PWM) и изменения ускорения (ST). Но для вращения мотора вы используете одну часть памяти (last_time и period_ms), а для ускорения (perodV_ms и prev_time). У переменной вращения все время пустует/не используется perodV_ms и prev_time, а у ускорения last_time и period_ms.
    Если объяснять на грузовиках, то вы выделили в своем парке 2 грузовика для лекарств. У вас на складе есть активированные уголь и аспирин. Вместо того чтобы в один грузовик класть уголь, а в другой аспирин, вы издали приказ, что в каждом грузовике должно быть выделено место для угля и для аспирина и ни в ком случае уголь/аспирин не должен занимать место аспирина/угля, НО в один грузовик вы грузите только уголь, а в другой только аспирин и получается, что грузовики у вас катаются полупустые.
     
  11. sanik

    sanik Гик

    Добрый день! Оказалось что .VLS.periodV_ms вообще не нужен был избавился от него. Скажите а как управлять pins[0].ST.step_time и pins[0].PWM.period_ms через меню меняю в меню значения а они сбрасываются на начальные. Нужно еще что то делать? Я так понял в структуре таймера просто так значения не поменяешь?
     
  12. Daniil

    Daniil Гуру

    а что такое "меню"? Вы реализовали сами? В любом случае нужен код.
     
  13. sanik

    sanik Гик

    Да меню настроек реализовано в цикле while В этом цикле я в ручную ставлю положения моторов и записываю их для дальнейших нужд)Так же движения моторов тоже сделано в отдельном цикле из цикла реализован выход в том случае когда счетчики обнулятся и сбросятся все флаги . К сожалению весь код не лезет но вот его главная часть Изначально были созданы массивы
    //uint16_t Speed [] = {105, 600, 600};// Установка скорости
    //uint16_t Velocity [] = {800, 1000, 1000};
    Как потом оказалось они бесполезны у меня возник еще вариант включить их в структуры пина но опять же ими нельзя управлять Я так думаю нужно создавать Публичные классы и от туда уже управлять. Я правильно понимаю? Просто в этом вопросе еще не силен а читая многого не понять и спросить не у кого.
    Код (C++):
    void SetPosition() {
      // long DollySetSTEP = longitudeSlider;
      regimMotor = 0;
      byte MENUPos = 0 ;
      boolean RegimRun = false;
      byte flagOK = 0;
      byte flagOUTOK = 0;
      byte regimError = 0;
      flagSETmenu = 0;
      byte flagKey5 = 0;
      boolean onKEY = false;
      SetPosShow (MENUPos, RegimRun, flagOK, flagOUTOK, flagKey5);
      do {

    if (millis() - pr > 1000) {
          pr = millis();
          serial();
        }
       
        byte KEY = key();
        if ( KEY == 0) {
          onKEY = false;
          flagbeep2 = 0;
          flagbeep = 0;
          flagbipOk = 0;
          if (flagSETmenu == 0) {
            SetPosShow (MENUPos, RegimRun, flagOK, flagOUTOK, flagKey5);
            flagSETmenu = 1;
          }
        }
        //******************************Крутим позицию

        if (KEY == 4 ) {
          ++ flagbeep ;
          beeper2(100);
          MENUPos = MENUPos == 5 ? 0 : MENUPos + 1;
          flagSETmenu = 0;
        }

        if (KEY == 3 ) {
          ++ flagbeep ;
          beeper2(100);
          MENUPos = MENUPos == 0 ? 5 : MENUPos - 1;
          flagSETmenu = 0;
        }
        //--------------------------------регулируем скорость----------
        for (uint8_t i = 0; i < 3; i++) {
          ShowSP [i] = map(pins[i].ST.step_time, 105, 2010, 100, 0);
          ShowSP [i] = constrain(ShowSP [i], 0, 100);
        }
        for (uint8_t i = 0; i < 3; i++) {
          Acceleration [i] = map(pins[i].PWM.period_ms, 400, 2000, 100, 0);
          Acceleration [i] = constrain(Acceleration [i], 0, 100);
        }
        if (MENUPos == 0) {
          if (KEY == 2 ) {
            ++ flagbeep ;
            beeper(15);
            switch (AngleSlaider) {
              case 0: //угол наклона 0 градусов
                pins[0].ST.step_time = pins[0].ST.step_time == 2005 ? 105 : pins[0].ST.step_time + 57;
                break;
              case 1: //угол наклона 45 градусов
                pins[0].ST.step_time = pins[0].ST.step_time == 2000 ? 200 : pins[0].ST.step_time + 54;
                break;
              case 2:  //угол наклона 75 градусов
                pins[0].ST.step_time = pins[0].ST.step_time == 2010 ? 510 : pins[0].ST.step_time + 45;
                break;
            }
            flagSETmenu = 0;
          }
          if (KEY == 1 ) {
            ++ flagbeep ;
            beeper(15);
            switch (AngleSlaider) {
              case 0: //угол наклона 0 градусов
                pins[0].ST.step_time = pins[0].ST.step_time == 105 ? 2005 : pins[0].ST.step_time - 57;
                break;
              case 1: //угол наклона 45 градусов
                pins[0].ST.step_time = pins[0].ST.step_time == 200 ? 2000 : pins[0].ST.step_time - 54;
                break;
              case 2:  //угол наклона 75 градусов
                pins[0].ST.step_time = pins[0].ST.step_time == 510 ? 2010 : pins[0].ST.step_time - 45;
                break;
            }
            flagSETmenu = 0;
          }
        }
        //-----------------------------------------------------------------
        if (MENUPos == 1) {
          if (KEY == 2 ) {
            ++ flagbeep ;
            beeper(15);
            pins[1].ST.step_time = pins[1].ST.step_time == 2005 ? 105 : pins[1].ST.step_time + 57;
            flagSETmenu = 0;
          }
          if (KEY == 1 ) {
            ++ flagbeep ;
            beeper(15);
            pins[1].ST.step_time = pins[1].ST.step_time == 105 ? 2005 : pins[1].ST.step_time - 57;
            flagSETmenu = 0;
          }
        }
        //-----------------------------------------------------------------
        if (MENUPos == 2) {
          if (KEY == 2 ) {
            ++ flagbeep ;
            beeper(15);
            pins[2].ST.step_time = pins[2].ST.step_time == 2005 ? 105 : pins[2].ST.step_time + 57;
            flagSETmenu = 0;
          }
          if (KEY == 1 ) {
            ++ flagbeep ;
            beeper(15);
            pins[2].ST.step_time = pins[2].ST.step_time == 105 ? 2005 : pins[2].ST.step_time - 57;
            flagSETmenu = 0;
          }
        }
        //--------------------------------регулируем разгон----------
        if (MENUPos == 3) {
          if (KEY == 2 ) {
            ++ flagbeep ;
            beeper(15);
            pins[0].PWM.period_ms = pins[0].PWM.period_ms == 2000 ? 400 : pins[0].PWM.period_ms + 64;
            flagSETmenu = 0;
          }
          if (KEY == 1 ) {
            ++ flagbeep ;
            beeper(15);
            pins[0].PWM.period_ms = pins[0].PWM.period_ms == 400 ? 2000 : pins[0].PWM.period_ms - 64;
            flagSETmenu = 0;
          }
        }
        //-------------------------------------------------------------
        if (MENUPos == 4) {
          if (KEY == 2 ) {
            ++ flagbeep ;
            beeper(15);
            pins[1].PWM.period_ms = pins[1].PWM.period_ms == 4000 ? 400 : pins[1].PWM.period_ms + 64;
            flagSETmenu = 0;
          }
          if (KEY == 1 ) {
            ++ flagbeep ;
            beeper(15);
            pins[1].PWM.period_ms = pins[1].PWM.period_ms == 400 ? 2000 : pins[1].PWM.period_ms - 64;
            flagSETmenu = 0;
          }
        }
        //-------------------------------------------------------------
        if (MENUPos == 5) {
          if (KEY == 2 ) {
            ++ flagbeep ;
            beeper(15);
            pins[2].PWM.period_ms = pins[2].PWM.period_ms == 2000 ? 400 : pins[2].PWM.period_ms + 64;
            flagSETmenu = 0;
          }
          if (KEY == 1 ) {
            ++ flagbeep ;
            beeper(15);
            pins[2].PWM.period_ms = pins[2].PWM.period_ms == 400 ? 2000 : pins[2].PWM.period_ms - 64;
            flagSETmenu = 0;
          }
        }

        if (MENUPos != 6) {
          if (( KEY == 5) && (flagKey5 == 2 ) && (onKEY == false)) {
            onKEY = true;
            ++ flagbeep ;
            beeper(15);
            if ((flagOUTOK > 0) && (flagOK > 0)) {
              MENUPos = 6;
            } else {
              ++ flageror;
              beepereror();
            }
            flagSETmenu = 0;
          }
          //-----------------------------записываем точки-----------
          if ((flagKey5 == 0) && (KEY == 5) && (onKEY == false)) {
            onKEY = true;
            ++ flagbeep ;
            beeper(15);
            flagOK = 1;
            if (powerX == true) {
              ChecIN_Dolly =  Position [0] ;
              delay(100);
            }
            if (powerY == true) {
              ChecIN_Pan =  Position [1];
              delay(100);
            }
            if (powerZ == true) {
              ChecIN_Tilt =  Position [2];
              delay(100);
            }
            flagKey5++;
            flagbipOk ++; beeperOK(100);
            flagSETmenu = 0;
          }
          //------------------------------------------
          if ((flagKey5 == 1) && (KEY == 5) && (onKEY == false)) {
            onKEY = true;
            ++ flagbeep ;
            beeper(15);
            if (powerX == true) {
              if (ChecIN_Dolly == ChecOUT_Dolly) {
                flagOK = 0;
              } else {
                flagOUTOK = 1;
                ChecOUT_Dolly =  Position [0];
                delay(100);
              }
            }
            if (powerY == true) {
              if (ChecIN_Pan == ChecOUT_Pan) {
                flagOK = 0;
                if (powerX == false) {
                  flagOUTOK = 0;
                }
              } else {
                flagOUTOK = 1;
                ChecOUT_Pan =  Position [1];
                delay(100);
              }
            }
            if (powerZ == true) {
              if (ChecIN_Tilt == ChecOUT_Tilt) {
                flagOK = 0;
              } else {
                flagOUTOK = 1;
                ChecOUT_Tilt =  Position [2];
                delay(100);
              }
            }
            if (flagOUTOK != 0) {
              flagbipOk ++; beeperOK(100);
            } else {
              ++ flageror;
              beepereror();
            }
            flagSETmenu = 0;
            flagKey5++;
          }
         
    }
     
  14. sanik

    sanik Гик

    Продолжение кода
    Код (C++):
       if (MENUPos != 6) {
          if (( KEY == 5) && (flagKey5 == 2 ) && (onKEY == false)) {
            onKEY = true;
            ++ flagbeep ;
            beeper(15);
            if ((flagOUTOK > 0) && (flagOK > 0)) {
              MENUPos = 6;
            } else {
              ++ flageror;
              beepereror();
            }
            flagSETmenu = 0;
          }
          //-----------------------------записываем точки-----------
          if ((flagKey5 == 0) && (KEY == 5) && (onKEY == false)) {
            onKEY = true;
            ++ flagbeep ;
            beeper(15);
            flagOK = 1;
            if (powerX == true) {
              ChecIN_Dolly =  Position [0] ;
              delay(100);
            }
            if (powerY == true) {
              ChecIN_Pan =  Position [1];
              delay(100);
            }
            if (powerZ == true) {
              ChecIN_Tilt =  Position [2];
              delay(100);
            }
            flagKey5++;
            flagbipOk ++; beeperOK(100);
            flagSETmenu = 0;
          }
          //------------------------------------------
          if ((flagKey5 == 1) && (KEY == 5) && (onKEY == false)) {
            onKEY = true;
            ++ flagbeep ;
            beeper(15);
            if (powerX == true) {
              if (ChecIN_Dolly == ChecOUT_Dolly) {
                flagOK = 0;
              } else {
                flagOUTOK = 1;
                ChecOUT_Dolly =  Position [0];
                delay(100);
              }
            }
            if (powerY == true) {
              if (ChecIN_Pan == ChecOUT_Pan) {
                flagOK = 0;
                if (powerX == false) {
                  flagOUTOK = 0;
                }
              } else {
                flagOUTOK = 1;
                ChecOUT_Pan =  Position [1];
                delay(100);
              }
            }
            if (powerZ == true) {
              if (ChecIN_Tilt == ChecOUT_Tilt) {
                flagOK = 0;
              } else {
                flagOUTOK = 1;
                ChecOUT_Tilt =  Position [2];
                delay(100);
              }
            }
            if (flagOUTOK != 0) {
              flagbipOk ++; beeperOK(100);
            } else {
              ++ flageror;
              beepereror();
            }
            flagSETmenu = 0;
            flagKey5++;
          }
          //---------------------------------------------Двигаем моторы
          if (powerX == true) {
            if (( KEY == 6) || (KEY == 7 )) {
              ++ flagbeep ;
              beeper(15);
              delay(100);
              pins[0].count = longitudeSlider;
              if ( KEY == 6 ) {
                LR_Dolly = 1;
                //  pins[0].count = (Position [0] - DollySetSTEP);
                digitalWrite(dir_Dolly, HIGH);// // Направление в право
              } else if ( KEY == 7 ) {
                LR_Dolly = 0;
                //   pins[0].count = DollySetSTEP;
                digitalWrite(dir_Dolly, LOW);// // Направление в лево
              }
              ++ flagbeep ;
              beeper(15);
              delay(100);
              Ex = 1;
              pins[0].fOn = 1;
              pins[1].fOn = 0;
              pins[2].fOn = 0;

              Run ();
            }
          }
          //---------------------------------------------------
          if (powerY == true) {
            if (( KEY == 8) || (KEY == 9 )) {
              ++ flagbeep ;
              beeper(15);
              delay(100);
              if ( KEY == 8 ) {
                LR_Pan = 1; // Направление в право
                digitalWrite(dir_Pan, LOW); // Направление в право
              } else if ( KEY == 9 ) {
                LR_Pan = 0;
                digitalWrite(dir_Pan, HIGH); // Направление в лево
              }
              Ex = 1;
              pins[0].fOn = 0;
              pins[1].fOn = 1;
              pins[2].fOn = 0;
              pins[1].count = (360 * STEPmm_Pan);
              RegimCount = 1;
              Run ();
            }
          }
          //---------------------------------------------------
          if (powerZ == true) {
            if (( KEY == 10) || (KEY == 11 )) { //TiltUp || TiltDown
              ++ flagbeep ;
              beeper(15);
              delay(100);
              if ( KEY == 10 ) {
                LR_Tilt = 1; // Направление в низ
                digitalWrite(dir_Tilt, HIGH);// Направление в низ
              } else if ( KEY == 11) {
                LR_Tilt = 0; // Направление в верх
                digitalWrite(dir_Tilt, LOW);// Направление в верх
              }
              ++ flagbeep ;
              beeper(15);
              delay(100);
              Ex = 1;
              pins[0].fOn = 0;
              pins[1].fOn = 0;
              pins[2].fOn = 1;
              pins[2].count = (180 * STEPmm_Tilt);
              RegimCount = 2;
              Run ();
            }
          }
          //-----------------------------Стираем точки-----------
          if ((flagKey5 == 3) && (KEY == 5) && (onKEY == false)) {
            onKEY = true;
            ClearPOI();
            ++ flageror;
            beepereror();
            flagOUTOK = 0;
            flagOK = 0;
            flagSETmenu = 0;
            flagKey5 = 0;
          }
        }
        //-------------------------------------- определяем направление
        if (ChecIN_Dolly < ChecOUT_Dolly) {
          startX = true;
        }
        if (ChecIN_Dolly > ChecOUT_Dolly) {
          startX = false;
        }

        if (ChecOUT_Pan > ChecIN_Pan) {
          startY = false;
        }
        if (ChecOUT_Pan < ChecIN_Pan) {
          startY = true; //влево Position --
        }

        if (ChecOUT_Tilt > ChecIN_Tilt) {
          startZ = false;
        }
        if ( ChecOUT_Tilt < ChecIN_Tilt) {
          startZ = true; //в низ (влево) Position --
        }
        //------------------------------------------------------------
        if (MENUPos == 6) {

          flagSETmenu = 0;
          if (( KEY == 5) && (onKEY == false)) {
            onKEY = true;
            ++ flagbeep ;
            beeper(15);
            StartPosition(MENUPos, RegimRun, flagOK, flagOUTOK, flagKey5);
          }
        }

      } while (1);
    }

    void ClearPOI() {
      ChecOUT_Dolly = 0; ChecOUT_Pan = 0; ChecOUT_Tilt = 0;
      ChecIN_Dolly = 0; ChecIN_Pan = 0; ChecIN_Tilt = 0;
    }


    void SetPosShow (byte MENUPos, boolean RegimRun, byte flagOK, byte flagOUTOK, byte flagKey5) {
      myOLED.clrScr();
      myOLED.invertText(false);
      myOLED.print("S", 2, 1);
      if (MENUPos == 0) {
        myOLED.invertText(true);
        myOLED.print("d", 18, 1);
      } else if (MENUPos != 0) {
        myOLED.invertText(false);
        myOLED.print("d:", 18, 1);
      }
      if (MENUPos == 1) {
        myOLED.invertText(true);
        myOLED.print("p", 53, 1);
      } else if (MENUPos != 1) {
        myOLED.invertText(false);
        myOLED.print("p:", 53, 1);
      }
      if (MENUPos == 2) {
        myOLED.invertText(true);
        myOLED.print("t", 88, 1);
      } else if (MENUPos != 2) {
        myOLED.invertText(false);
        myOLED.print("t:", 88, 1);
      }
      myOLED.invertText(false);
      myOLED.printNumI(ShowSP [0], 31, 1);
      myOLED.printNumI(ShowSP [1], 66, 1);
      myOLED.printNumI(ShowSP [2], 102, 1);
      //--------------------------------------------------------
      myOLED.print("A", 2, 11);
      if (MENUPos == 3) {
        myOLED.invertText(true);
        myOLED.print("d", 18, 11);
      } else if (MENUPos != 3) {
        myOLED.invertText(false);
        myOLED.print("d:", 18, 11);
      }
      if (MENUPos == 4) {
        myOLED.invertText(true);
        myOLED.print("p", 53, 11);
      } else if (MENUPos != 4) {
        myOLED.invertText(false);
        myOLED.print("p:", 53, 11);
      }
      if (MENUPos == 5) {
        myOLED.invertText(true);
        myOLED.print("t", 88, 11);
      } else if (MENUPos != 5) {
        myOLED.invertText(false);
        myOLED.print("t:", 88, 11);
      }
      myOLED.invertText(false);
      myOLED.printNumI(Acceleration [0], 31, 11);
      myOLED.printNumI(Acceleration [1], 66, 11);
      myOLED.printNumI(Acceleration [2], 102, 11);
      //---------------------------------------------------------
      myOLED.print("DR", LEFT, 28);
      if (powerX == true) {
        myOLED.print("D-", 35, 28);
        if (startX == false) {
          myOLED.print("L", 47, 28);
        }
        if (startX == true) {
          myOLED.print("R", 47, 28);
        }
      }
      if (powerY == true) {
        myOLED.print("P-", 70, 28);
        if (startY == true) {
          myOLED.print("L", 82, 28);
        }
        if (startY == false) {
          myOLED.print("R", 82, 28);// 20,45
        }
      }
      if (powerZ == true) {
        myOLED.print("T-", 105, 28);
        if (startZ == false) {
          myOLED.print("U", 117, 28); // left
        }
        if (startZ == true) {
          myOLED.print("D", 117, 28);// Right
        }
      }
      //--------------------------------------------
      myOLED.invertText(false);
      myOLED.print("IN", 5, 40);
      myOLED.print("OU", 50, 40);
      if (MENUPos == 6) {
        myOLED.print("F", 115, 40);
      } else {
        myOLED.printNumI(flagKey5, 115, 40);  // pins[0].count
      }
      if (flagOK != 0) myOLED.print("OK", 25, 40);
      if (flagOUTOK != 0) myOLED.print("OK", 70, 40);// 70, 40

      myOLED.printNumI( Position [0] / STEPmm_Dolly, 21, 55);  //flagKey5
      myOLED.print("D", 10, 55);


      myOLED.printNumI( Position [1] / STEPmm_Pan, 64, 55); //countY
      myOLED.print("P", 50, 55);


      myOLED.print("T", 88, 55);
      myOLED.printNumI( Position [2] / STEPmm_Tilt, 100, 55);

      myOLED. drawLine(0, 0, 127, 0);
      myOLED. drawLine(0, 22, 127, 22);
      myOLED. drawLine(0, 0, 0, 22);
      myOLED. drawLine(127, 0, 127, 22);
      myOLED. drawLine(5, 63, 123, 63);
      myOLED. drawLine(123, 53, 123, 63);
      myOLED. drawLine(5, 53, 123, 53);
      myOLED. drawLine(5, 53, 5, 63);
      myOLED.update();
    }
     
  15. sanik

    sanik Гик

    В общем принцип кода состоит из цикличного автомата переход от цикла к циклу выполняется бесконечно пока не будут условия перехода в другой цикл в этой функции как раз идет настройки скорости но они не принимаются. при переходе в цикл движения моторов
     
  16. sanik

    sanik Гик

    Да почитал еще про указатели вообще ни черта не понял понял что как раз через них было бы удобнее передавать в структуру таймера новые данные. вот цикл моторов
    Код (C++):
    void Run () {
      do {
        byte KEY = key();
        if ( KEY == 0) {
          flagbeep2 = 0;
          flagbeep = 0;
        }
        if (regimMotor == 1) {
          if ((pins[0].fOn == 0) && (pins[1].fOn == 0) && (pins[2].fOn == 0)) {
            Clear();
            Ex = 0;
          }
        }
    for (uint8_t num = 0; num < kol_Pins; num++) {
          if ( pins[num].count == 0) {
            pins[num].fOn = 0;
          }
          //***********************Ускорение*************************
          if (millis() - pins[num].VLS.prew_time > 1) {
            pins[num].VLS.prew_time = millis();
            if (pins[num].fVel == true) {
              if ( pins[num].PWM.period_ms > pins[num].ST.step_time) {
                pins[num].PWM.period_ms--;//уменьшить период  пина,
              }
            }
            if (pins[num].PWM.period_ms == pins[num].ST.step_time) {
              pins[num].fVel = false;
            }
            //**********************Замедление **************************
            if (pins[num].fVel == true) {
              pins[num].cOut = pins[num].count * 0.06;
            }
            if (pins[num].count <= pins[num].cOut) {
              pins[num].PWM.period_ms++;
              if (pins[num].PWM.period_ms > 600) {
                pins[num].PWM.period_ms = 600;
              }
            }
          }
          // кнопки остановки
          if (regimMotor != 1) {
            if ( KEY == 6 || KEY == 7 || KEY == 8 || KEY == 9 || KEY == 10 || KEY == 11 || KEY == 5) {
              ++ flagbeep ;
              beeper(15);
              delay(100);
              flagSETmenu = 0;
              pins[num].fVel = true;
              // Clear();
              Ex = 0;
            }
    //************************************************
          if (micros() - pins[num].PWM.last_time > pins[num].PWM.period_ms) {
            if (pins[num].fOn == 0) continue;
            pins[num].PWM.last_time = micros();
            pins[num].State = !(pins[num].State); //инвертирование переменной состояния пина
            digitalWrite(pins[num].Name, pins[num].State);
            pins[num].count--;
            if (regimMotor < 6) {
              if (pins[0].fOn == 1) {
                if (LR_Dolly == 1) {
                  Position [0] ++;
                } else if (LR_Dolly == 0) {
                  Position [0] --;
                }
              }
              if (pins[1].fOn == 1) {
                if (LR_Pan == 1) {
                  Position [1] ++;
                } else if (LR_Pan == 0) {
                  Position [1] --;
                }
              }
              if (pins[2].fOn == 1) {
                if (LR_Tilt == 0) {
                  Position [2] ++;
                } else if (LR_Tilt == 1) {
                  Position [2] --;
                }
              }
            }
          //************************************************
        } /
      } while (Ex != 0);
    }
    void Clear() {
      for (uint8_t num = 0; num < kol_Pins; num++) {
        pins[num].fVel = true;
        pins[num].count = 0;
      }
    }
     
     
    Последнее редактирование: 21 янв 2020
  17. Daniil

    Daniil Гуру

    Да, указатели это мощь, но ими нужно тренироваться на простых примерах.
    Если у вас pins объявлены как глобальные, то их не нужно передавать в процедуры, т.к. они глобальные (извиняюсь за тавтологию) и обращаться к ним можно в любой момент времени.
    К сожалению, код у вас значительно подрос) магические числа у вас остались, но в данном случае одно только кол-во переменных вводит апатию;), поэтому буду пробовать "тыкать в небо". Буду говорить о подозрительных местах, где можно запутаться (не факт, что вы запутались, но проверить стоит).
    Вот ещё хорошая табличка приоритетов операций, в некоторых местах может выручить, потому что в одной строке и "=", и "==" и "?:". СтОит аккуратно отнестись к последовательности операций и в некоторых местах расставлять скобки "()" для явного указания приоритетов.

    Есть вероятность ошибки в таких строчках:
    Код (C++):
    pins[0].ST.step_time = pins[0].ST.step_time == 2005 ? 105 : pins[0].ST.step_time + 57;
    Есть ли уверенность, что прибавление к pins[0].ST.step_time какой-то константы (в данном случае 57) может привести к точному равенству другой константе (в данном случае 2005). Если бы вы прибавляли бы 1, то я был бы уверен, а так как она 57, то опасность есть. В какой-то момент можно просто-напросто перепрыгнуть 2005 и уехать в бесконечность (переполнение).
    Отвечу запоздало. Менять можно в любой момент времени, если эти переменные глобальные. Главное, чтобы алгоритм это предусматривал. Может быть случай когда в одном куске кода вы приравниваете pins[0].ST.step_time = 100500, а где-то в другом месте идёт проверка pins[0].ST.step_time>10? Надо предусмотреть такие случаи, когда внешнее возмущение корректно обрабатывалось текущим алгоритмом (режимом) действий.

    У вас есть возможность выводить данные в Serial? если да, то пора осваивать ардуино-методы отладки) Пихать везде, Serial.print(<data>) и в мониторе порта наблюдать за той или иной переменной. Причём будьте внимательны процесс вывода данных является времязатратным. Продумайте какой-нибудь тестовый режим моторов, который очень медленный (по меркам человека), чтобы вы могли глазами видеть как мотор замедляется и наблюдать в мониторе порта цифры.

    Я пробежался поиском по вашему коду (3 последние части, которые вы выложили). Искал "period_ms". Есть 3 случая когда у вас изменяется period_ms.
    1. В процедуре Run, в процессе замедления или ускорения (++ или --), тут, подозреваю всё работает, т.е. нет "залипания" на начальное значение.
    2. В процедуре Run, в процессе замедления в случае если period_ms>600. Возникает вопрос, когда вы в меню меняете period_ms не попадаете ли вы в это самое условие? Если да, то вот тут вы можете залипнуть period_ms=600. Таким образом нужно убедиться, что при изменении period_ms вы меняете все остальные параметры так, чтобы не попадать в эту часть кода. Т.е. вместе с изменением period_ms, нужно проконтролировать (pins[num].count <= pins[num].cOut), и (pins[num].fVel == true). Мне сложно это сделать из-за огромного кода и непонимания назначения тех или иных переменных.
    3. Изменение в меню. Там уже нужно рассматривать и замечание выше (по-поводу точного равенства) и правильного выхода из меню. См. пункт 2. Если мы вышли из меню, а в процедуре Run выполняются условия (pins[num].count <= pins[num].cOut), и (pins[num].fVel == true), то ничто нам не мешает залететь и в
    Код (C++):
    if (pins[num].PWM.period_ms > 600) {
                pins[num].PWM.period_ms = 600;
    Т.е. вот ещё одна возможная причина залипания.
    Или вы не до конца изменили все параметры в меню так, что алгоритм не доходит до операций ++ или -- в процедуре Run.
    Аналогично такой поиск можно провести и для ST.step_time.
     
    sanik нравится это.
  18. sanik

    sanik Гик

    Да вы верно подметили насчет строчки где идет + 57 Я это вычислил как раз с помощью сериал порта)) Отладкой пользуюсь Забыл скопировать ограничивающие строчки где идет слежение чтоб не выходил за рамки 2005 ? 105.
    А вот в пункте три возможно там и есть ошибка об этом я как раз и не подумал. Буду проверять спасибо Вам огромное.
     
    Daniil нравится это.
  19. sanik

    sanik Гик

    Все разобрался! Оказалось что нужно было всего лишь при выходе из цикла pins[num].PWM.period_ms привести в исходное состояние так как в некоторых случаях цикл резко прерывался и не успевал дойти до строк плавной остановки перед выходом надо было. добавить еше переменную
    Код (C++):
    for (uint8_t i = 0; i < 3; i++) {
          pins[i].PWM.period_ms = Velocity [i];
        }
    Спасибо за подсказку!
     
    Последнее редактирование: 22 янв 2020
    Daniil нравится это.
  20. sanik

    sanik Гик

    Я ту еще раз поразмыслил над "грузовиками" наконец то дошло до меня вы имели ввиду это?
    Код (C++):
    //Объявляем тип структуры таймера
    struct timer_t {
      uint16_t period_ms;
      uint32_t last_time[2];//
      uint16_t step_time;
    };
    //Объявляем тип структуры пина
    struct pin_t {
      uint8_t Name; // номер пина
      uint8_t State; // состояние пина
      timer_t PWM;
      timer_t ST;
      uint32_t count;
      uint32_t cOut;
      uint8_t fOn;
      boolean fVel;
    };
    const uint8_t kol_Pins = 3; // количество пинов step
    pin_t pins[kol_Pins];
    //Иницализация переменных
    void init_mas() {
      pins[0].Name = pin1;
      pins[0].State = LOW; // преременная состояния пина под номером 0 Dolly из массива
      pins[0].PWM.period_ms = Velocity_Dolly;// начальная скорость Dolly  задержка мотора под номером 0 из массива
      pins[0].PWM.last_time[0] = 0; //  переменная  хранения последнего обновления пина dir Dolly
      pins[0].PWM.last_time[1] = 0;
      pins[0].ST.step_time = Speed_Dolly; //установленная скорость;
      pins[0].count = RunDolly; // подсчет импульсов расстояние которое нужно пройти
      pins[0].cOut = 0; // подсчет импульсов вычесления наращивания скорости
      pins[0].fOn = 1; // флаг остановки мотора
      pins[0].fVel = true; // флаг оканчания подсчета вычесления наращивания скорости
      pins[1].Name = pin2;
      pins[1].State = LOW; // преременная состояния пина под номером 1 Pan из массива
      pins[1].PWM.period_ms = Velocity_Pan; //  начальная скорость Pan
      pins[1].PWM.last_time[0] = 0; // переменная  хранения последнего обновления пина dir Pan
      pins[1].PWM.last_time[1] = 0;
      pins[1].ST.step_time = Speed_Pan;  //установленная скороость  Pan
      pins[1].count = RunPan;
      pins[1].cOut = 0;
      pins[1].fOn = 1;
      pins[1].fVel = true;
      pins[2].Name = pin3;
      pins[2].State = LOW; // преременная состояния пина под номером 2 Tilt из массива
      pins[2].PWM.period_ms = Velocity_Tilt; // начальная скорость Pan
      pins[2].PWM.last_time[0] = 0; // переменная  хранения последнего обновления пина dir Tilt
      pins[2].PWM.last_time[1] = 0;
      pins[2].ST.step_time = Speed_Tilt; //установленная скороость Tilt
      pins[2].count = RunTilt;
      pins[2].fOn = 1;
      pins[2].cOut = 0;
      pins[2].fVel = true;
    }