Обратная связь для коллекторного двигателя

Conradk10
Offline
Зарегистрирован: 28.04.2020

Добрый день. Интересует вопрос программно организовать обратную связь для коллекторного двигателя с помощью потенциометра. Есть потенциометр, который напрямую крутится от вала коллекторного двигателя, который подключен к драйверу BTS7960. Драйвер по пинам +,-, ШИМ лево, ШИМ право, лево, право подключен к ардуино, так же к ардуино подключен потенциометр. Хотелось бы как-то удобно организовать программно работу этих двух устройств чтобы они были похожи на обычный серво-привод. Мне нужно регулировать угол в котором находится двигатель. Вообще, задумка такая: стоит компас, по нажатию кнопки фиксируется положение компаса, а дальше двигатель должен крутиться в противоположную сторону на столько градусов насколько ушел компас, чтобы стабилизировать положение. 
Третий день ломаю голову, ничего не могу придумать.
На всякий случай приложу код.

 

#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BNO055.h>
#include <utility/imumaths.h>
#include <GyverButton.h>

#define BNO055_SAMPLERATE_DELAY_MS (100)
#define EN 3              // № вывода Arduino к которому подключены входы драйвера L_EN и R_EN. Можно указать любой вывод Arduino поддерживающий ШИМ.
#define L_PWM 4           // № вывода Arduino к которому подключён  вход  драйвера L_PWM.       Можно указать любой вывод Arduino, как цифровой, так и аналоговый.
#define R_PWM 5           // № вывода Arduino к которому подключён  вход  драйвера R_PWM.       Можно указать любой вывод Arduino, как цифровой, так и аналоговый.
#define fixButton 2       // Кнопка фиксации значения координаты fixedVal 
#define led1 6            // Индикатор работы автопилота
#define relay 7           // Реле двигателя
#define potInput A0       // Резистор руля
Adafruit_BNO055 bno = Adafruit_BNO055(-1, 0x29);

float fixedVal = 0;       // Принимает значение координаты
float tempVal = 0;        // Временная переменная зафиксированной координаты
float xVal = 0;
float engPosition = 0;      // Позиция руля
int engSpeed = 0;
bool apstate = 0;
bool setpos = 0;

int maxSpeed = 100;
int minSpeed = 1;

GButton butt1(2);         // Кнопка

void setup(){
  pinMode(EN,    OUTPUT);      // Конфигурируем вывод EN    как выход (выход Arduino, вход драйвера)
  pinMode(L_PWM, OUTPUT);      // Конфигурируем вывод L_PWM как выход (выход Arduino, вход драйвера)
  pinMode(R_PWM, OUTPUT);      // Конфигурируем вывод R_PWM как выход (выход Arduino, вход драйвера)
  pinMode(fixButton, INPUT);   // Кнопка фиксации значения координаты fixedVal
  pinMode(led1, OUTPUT);       // Индикатор работы автопилота
  pinMode(relay, OUTPUT);      // Реле двигателя
  digitalWrite(led1, LOW);      
  digitalWrite(relay, LOW);
  Serial.begin(115200);
  Serial.println("Orientation System 25.04.2020"); Serial.println("");
  Wire.begin(); 
  /* Initialise the sensor */
  if(!bno.begin())
  {
    Serial.print("Ooops, no BNO055 detected ... Check your wiring or I2C ADDR!");
    while(1);
  }
  delay(1000);
  bno.setExtCrystalUse(true);
  Serial.println("Loading done!");
}

void loop(){
  sensors_event_t event;
  bno.getEvent(&event);
  
  xVal = event.orientation.x-180;
  engPosition = map(analogRead(potInput), 0.00, 1023.00, -100.00, 100.00);
  
  butt1.tick();
  if(butt1.isPress()){
    if(apstate == 1){
      Serial.println("OFF!");
      digitalWrite(led1, LOW);
      digitalWrite(relay, LOW);
      engStop();
      engNeutral();
      apstate = 0;
    } else if(apstate == 0){
      Serial.println("ON!");
      digitalWrite(led1, HIGH);
      digitalWrite(relay, HIGH);
      bno.begin();
      xVal = event.orientation.x-180;
      fixedVal = xVal;
      apstate = 1;
    }
  }

if(apstate == 1){
  if(xVal > -179 && xVal < 0){   // ЛЕВО

    tempVal = xVal - fixedVal;
    
    Serial.print("1: ");
    Serial.print(tempVal);
    if(engPosition < tempVal){
      engStart();
      engLeft();
    } else
      engNeutral();
  }



  if(xVal < 179 && xVal > 0){   // ПРАВО

    tempVal = fixedVal + xVal;
    
    Serial.print("2: ");
    Serial.print(tempVal);
    if(engPosition > tempVal){
    engStart();
    engRight();
    } else 
    engNeutral();
  }



  if(xVal > 179 || xVal < -179){
    
    Serial.print("3: ");
    Serial.print(tempVal);
    if(engPosition > 2){
      engRight();
      engStart();
    } else if(engPosition < -2){
      engLeft();
      engStart();
    } else
    engNeutral();
  }
  







/*
if(fixedVal > 0){
  if(fixedVal < xVal){
    tempVal = fixedVal - xVal;
    Serial.print("  LEFT+  ");
} else if(xVal < fixedVal){
    tempVal = xVal + fixedVal - 360;
    Serial.print("  RIGHT+  ");
}
} else if(fixedVal < 0){
  if(fixedVal < xVal){
    tempVal = fixedVal - xVal + 360;
    Serial.print("  LEFT-  ");
} else if(xVal < fixedVal){
    tempVal = xVal + fixedVal;
    Serial.print("  RIGHT-  ");
}
}




if(apstate == 1){
    if(engPosition < -2.00 && engPosition > -100){
      digitalWrite(L_PWM, HIGH);
      digitalWrite(R_PWM, LOW);
      analogWrite (EN,   30);
      Serial.print("MODE 1  ");
    } else if(engPosition > 2.00 && engPosition < 100){
      digitalWrite(L_PWM, LOW);
      digitalWrite(R_PWM, HIGH);
      analogWrite (EN,   30);
      Serial.print("MODE 2  ");
    } else {
      digitalWrite(L_PWM, LOW);
      digitalWrite(R_PWM, LOW);
      analogWrite (EN,   LOW);
      Serial.print("MODE 3  ");
    }

if(xVal < 179 && xVal > 0){
  if(engPosition <= tempVal){
    digitalWrite(L_PWM, HIGH);
    digitalWrite(R_PWM, LOW);
    analogWrite (EN,   35);
    Serial.print("MODE 1  ");
  }
}

  if(xVal > -179 && xVal < 0){         //right
    tempVal = (-xVal-180)*8;
    //Serial.print(tempVal);
    Serial.print("  RIGHT  ");
    
    if(engPosition >= tempVal){
    digitalWrite(L_PWM, LOW );
    digitalWrite(R_PWM, HIGH);
    analogWrite (EN,   50);
    setpos = 0;
    } else if(engPosition <= tempVal){
    setpos = 1;
    } else {
    digitalWrite(L_PWM, LOW );
    digitalWrite(R_PWM, LOW);
    analogWrite (EN,    LOW);
    Serial.print("  STOP R  ");
    }
    
  } else if(xVal < 179 && xVal > 0){   //left
    tempVal = (-xVal+180)*8;
    //Serial.print(tempVal);
    Serial.print("  LEFT  ");
    
    if(engPosition > tempVal){
    digitalWrite(L_PWM, HIGH);
    digitalWrite(R_PWM, LOW);
    analogWrite (EN,    100);
    } else {
    analogWrite (EN,    LOW);
    Serial.print("  STOP L  ");
    }
*/
 /* 
}
  Serial.print(" xVal: ");
  Serial.print(xVal);
  Serial.print(" fixedVal: ");
  Serial.print(fixedVal);
  Serial.print(" engPosition: ");
  Serial.print(engPosition);
  Serial.print(" tempVal: ");
  Serial.println(tempVal);
  */
  }
  delay(BNO055_SAMPLERATE_DELAY_MS);
  Serial.print("   engPosition: ");
  Serial.print(engPosition);
  Serial.print("   xVal: ");
  Serial.println(xVal);
}



int engStart(){
  if(engSpeed < maxSpeed){
    engSpeed++;
    analogWrite(EN, engSpeed);
    delay(1);
    engStart();
  }
  analogWrite(EN, engSpeed);
  return engSpeed;
  Serial.print("  (engStart) Done!  ");
}

int engStop(){
  if(engSpeed >= minSpeed){
    engSpeed--;
    analogWrite(EN, engSpeed);
    delay(1);
    engStop();
  }
  analogWrite(EN, engSpeed);
  return engSpeed;
  Serial.print("  (engStop) Done!  ");
}

int engLeft(){
  digitalWrite(L_PWM, HIGH);
  digitalWrite(R_PWM, LOW);
  Serial.print("  (engLeft) Done!  ");
}

int engRight(){
  digitalWrite(R_PWM, HIGH);
  digitalWrite(L_PWM, LOW);
  Serial.print("  (engRight) Done!  ");
}

int engNeutral(){
  digitalWrite(R_PWM, LOW);
  digitalWrite(L_PWM, LOW);
  Serial.print("  (engNeutral) Done!  ");
}

int engExtraStop(){
  digitalWrite(R_PWM, HIGH);
  digitalWrite(R_PWM, HIGH);
  analogWrite(EN, HIGH);
  delay(100);
  digitalWrite(R_PWM, LOW);
  digitalWrite(L_PWM, LOW);
  analogWrite(EN, LOW);
  Serial.print("  (engExtraStop) Done!  ");
}

 

rkit
Offline
Зарегистрирован: 23.11.2016

Базовая схема управления серво

П-регулятор <искомое положение> - <реальное положение> = искомая скорость

ПИД-регулятор <искомая скорость> - <реальная скорость> = шим на моторе

 

Conradk10
Offline
Зарегистрирован: 28.04.2020

rkit пишет:

ПИД-регулятор <искомая скорость> - <реальная скорость> = шим на моторе

Посмотрел, спасибо за совет, попробую - отпишу.

Conradk10
Offline
Зарегистрирован: 28.04.2020

Conradk10 пишет:

rkit пишет:

ПИД-регулятор <искомая скорость> - <реальная скорость> = шим на моторе

Посмотрел, спасибо за совет, попробую - отпишу.

Нашёл вот такое видео: https://www.youtube.com/watch?v=K7FQSS_iAw0

Мне оно подходит как раз, но там энкодер, а мне нужен потенциометр...

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Ну дак выкинь энкодер, поставь потацометр.

GarryC
Offline
Зарегистрирован: 08.08.2016

Вообще то дешевые серво-приводы для Ардуино так и устроены - двигатель (скорее всего коллекторный, но это не точно) понижающий привод, потенциометр на оконечном валу, и микроконтроллер в корпусе девайса для управления этой системой. Так что смотрите, какой МК там стоит и ищите прошивку к нему.

nik182
Offline
Зарегистрирован: 04.05.2015

Тут засада в слове коллекторный. Очень трудно повернуть его на угол меньше 360 градусов. Проблема в том, что тронуться с места коллекторному двигателю нужен больший ток, чем потом на вращение. Поэтому регулятор сначала поднимает напряжение, потом сбрасывает, а движок крутится. В рулевых машинках это решается редуктором, который выбеги коллекторного двигателя уменьшает до приемлемых значений.   

Conradk10
Offline
Зарегистрирован: 28.04.2020

Вот я в своём коде 
 

#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BNO055.h>
#include <utility/imumaths.h>
#include <GyverButton.h>

#define BNO055_SAMPLERATE_DELAY_MS (100)
#define EN 3              // № вывода Arduino к которому подключены входы драйвера L_EN и R_EN. Можно указать любой вывод Arduino поддерживающий ШИМ.
#define L_PWM 4           // № вывода Arduino к которому подключён  вход  драйвера L_PWM.       Можно указать любой вывод Arduino, как цифровой, так и аналоговый.
#define R_PWM 5           // № вывода Arduino к которому подключён  вход  драйвера R_PWM.       Можно указать любой вывод Arduino, как цифровой, так и аналоговый.
#define fixButton 2       // Кнопка фиксации значения координаты fixedVal 
#define led1 6            // Индикатор работы автопилота
#define relay 7           // Реле двигателя
#define potInput A0       // Резистор руля
Adafruit_BNO055 bno = Adafruit_BNO055(-1, 0x29);

float fixedVal = 0;       // Принимает значение координаты
float tempVal = 0;        // Временная переменная зафиксированной координаты
float xVal = 0;
float engPosition = 0;      // Позиция руля
int engSpeed = 0;
bool apstate = 0;
bool setpos = 0;

int maxSpeed = 100;
int minSpeed = 1;

GButton butt1(2);         // Кнопка

void setup(){
  pinMode(EN,    OUTPUT);      // Конфигурируем вывод EN    как выход (выход Arduino, вход драйвера)
  pinMode(L_PWM, OUTPUT);      // Конфигурируем вывод L_PWM как выход (выход Arduino, вход драйвера)
  pinMode(R_PWM, OUTPUT);      // Конфигурируем вывод R_PWM как выход (выход Arduino, вход драйвера)
  pinMode(fixButton, INPUT);   // Кнопка фиксации значения координаты fixedVal
  pinMode(led1, OUTPUT);       // Индикатор работы автопилота
  pinMode(relay, OUTPUT);      // Реле двигателя
  digitalWrite(led1, LOW);      
  digitalWrite(relay, LOW);
  Serial.begin(115200);
  Serial.println("Orientation System 25.04.2020"); Serial.println("");
  Wire.begin(); 
  /* Initialise the sensor */
  if(!bno.begin())
  {
    Serial.print("Ooops, no BNO055 detected ... Check your wiring or I2C ADDR!");
    while(1);
  }
  delay(1000);
  bno.setExtCrystalUse(true);
  Serial.println("Loading done!");
}

void loop(){
  sensors_event_t event;
  bno.getEvent(&event);
  
  xVal = event.orientation.x-180;
  engPosition = map(analogRead(potInput), 0.00, 1023.00, -100.00, 100.00);
  
  butt1.tick();
  if(butt1.isPress()){
    if(apstate == 1){
      Serial.println("OFF!");
      digitalWrite(led1, LOW);
      digitalWrite(relay, LOW);
      engStop();
      engNeutral();
      apstate = 0;
    } else if(apstate == 0){
      Serial.println("ON!");
      digitalWrite(led1, HIGH);
      digitalWrite(relay, HIGH);
      bno.begin();
      xVal = event.orientation.x-180;
      fixedVal = xVal;
      apstate = 1;
    }
  }

if(apstate == 1){
  if(xVal > -179 && xVal < 0){   // ЛЕВО

    tempVal = xVal - fixedVal;
    
    Serial.print("1: ");
    Serial.print(tempVal);
    if(engPosition < tempVal){
      engStart();
      engLeft();
    } else
      engNeutral();
  }



  if(xVal < 179 && xVal > 0){   // ПРАВО

    tempVal = fixedVal + xVal;
    
    Serial.print("2: ");
    Serial.print(tempVal);
    if(engPosition > tempVal){
    engStart();
    engRight();
    } else 
    engNeutral();
  }



  if(xVal > 0 || xVal < 0){
    
    Serial.print("3: ");
    Serial.print(tempVal);
    if(engPosition > 2){
      engRight();
      engStart();
    } else if(engPosition < -2){
      engLeft();
      engStart();
    } else
    engNeutral();
  }
  







/*
if(fixedVal > 0){
  if(fixedVal < xVal){
    tempVal = fixedVal - xVal;
    Serial.print("  LEFT+  ");
} else if(xVal < fixedVal){
    tempVal = xVal + fixedVal - 360;
    Serial.print("  RIGHT+  ");
}
} else if(fixedVal < 0){
  if(fixedVal < xVal){
    tempVal = fixedVal - xVal + 360;
    Serial.print("  LEFT-  ");
} else if(xVal < fixedVal){
    tempVal = xVal + fixedVal;
    Serial.print("  RIGHT-  ");
}
}




if(apstate == 1){
    if(engPosition < -2.00 && engPosition > -100){
      digitalWrite(L_PWM, HIGH);
      digitalWrite(R_PWM, LOW);
      analogWrite (EN,   30);
      Serial.print("MODE 1  ");
    } else if(engPosition > 2.00 && engPosition < 100){
      digitalWrite(L_PWM, LOW);
      digitalWrite(R_PWM, HIGH);
      analogWrite (EN,   30);
      Serial.print("MODE 2  ");
    } else {
      digitalWrite(L_PWM, LOW);
      digitalWrite(R_PWM, LOW);
      analogWrite (EN,   LOW);
      Serial.print("MODE 3  ");
    }

if(xVal < 179 && xVal > 0){
  if(engPosition <= tempVal){
    digitalWrite(L_PWM, HIGH);
    digitalWrite(R_PWM, LOW);
    analogWrite (EN,   35);
    Serial.print("MODE 1  ");
  }
}

  if(xVal > -179 && xVal < 0){         //right
    tempVal = (-xVal-180)*8;
    //Serial.print(tempVal);
    Serial.print("  RIGHT  ");
    
    if(engPosition >= tempVal){
    digitalWrite(L_PWM, LOW );
    digitalWrite(R_PWM, HIGH);
    analogWrite (EN,   50);
    setpos = 0;
    } else if(engPosition <= tempVal){
    setpos = 1;
    } else {
    digitalWrite(L_PWM, LOW );
    digitalWrite(R_PWM, LOW);
    analogWrite (EN,    LOW);
    Serial.print("  STOP R  ");
    }
    
  } else if(xVal < 179 && xVal > 0){   //left
    tempVal = (-xVal+180)*8;
    //Serial.print(tempVal);
    Serial.print("  LEFT  ");
    
    if(engPosition > tempVal){
    digitalWrite(L_PWM, HIGH);
    digitalWrite(R_PWM, LOW);
    analogWrite (EN,    100);
    } else {
    analogWrite (EN,    LOW);
    Serial.print("  STOP L  ");
    }
*/
 /* 
}
  Serial.print(" xVal: ");
  Serial.print(xVal);
  Serial.print(" fixedVal: ");
  Serial.print(fixedVal);
  Serial.print(" engPosition: ");
  Serial.print(engPosition);
  Serial.print(" tempVal: ");
  Serial.println(tempVal);
  */
  }
  delay(BNO055_SAMPLERATE_DELAY_MS);
  Serial.print("   engPosition: ");
  Serial.print(engPosition);
  Serial.print("   xVal: ");
  Serial.println(xVal);
}



int engStart(){
  if(engSpeed < maxSpeed){
    engSpeed++;
    analogWrite(EN, engSpeed);
    delay(1);
    engStart();
  }
  analogWrite(EN, engSpeed);
  return engSpeed;
  Serial.print("  (engStart) Done!  ");
}

int engStop(){
  if(engSpeed >= minSpeed){
    engSpeed--;
    analogWrite(EN, engSpeed);
    delay(1);
    engStop();
  }
  analogWrite(EN, engSpeed);
  return engSpeed;
  Serial.print("  (engStop) Done!  ");
}

int engLeft(){
  digitalWrite(L_PWM, HIGH);
  digitalWrite(R_PWM, LOW);
  Serial.print("  (engLeft) Done!  ");
}

int engRight(){
  digitalWrite(R_PWM, HIGH);
  digitalWrite(L_PWM, LOW);
  Serial.print("  (engRight) Done!  ");
}

int engNeutral(){
  digitalWrite(R_PWM, LOW);
  digitalWrite(L_PWM, LOW);
  Serial.print("  (engNeutral) Done!  ");
}

int engExtraStop(){
  digitalWrite(R_PWM, HIGH);
  digitalWrite(R_PWM, HIGH);
  analogWrite(EN, HIGH);
  delay(100);
  digitalWrite(R_PWM, LOW);
  digitalWrite(L_PWM, LOW);
  analogWrite(EN, LOW);
  Serial.print("  (engExtraStop) Done!  ");
}

Организовал вот такой участок кода:
 

if(xVal > -179 && xVal < 0){   // ЛЕВО

    tempVal = xVal - fixedVal;
    
    Serial.print("1: ");
    Serial.print(tempVal);
    if(engPosition < tempVal){
      engStart();
      engLeft();
    } else
      engNeutral();
  }



  if(xVal < 179 && xVal > 0){   // ПРАВО

    tempVal = fixedVal + xVal;
    
    Serial.print("2: ");
    Serial.print(tempVal);
    if(engPosition > tempVal){
    engStart();
    engRight();
    } else 
    engNeutral();
  }



  if(xVal > 0 || xVal < 0){
    
    Serial.print("3: ");
    Serial.print(tempVal);
    if(engPosition > 2){
      engRight();
      engStart();
    } else if(engPosition < -2){
      engLeft();
      engStart();
    } else
    engNeutral();
  }
  

Который отвечает за позиционирования двигателя, но вот обратно он возвращается только в положении по середине, как мне сделать из потенциометра и двигателя (двигатель через редуктор медленно крутит потенциометр) - серво, который будет принимать положение которое ему будет указывать компас? Вообще ничего не могу понять, пытался разобраться с ПИД-регулятором, все равно ничего не получается, даже переделать программу, вообще не врубаюсь как организовать ПИД для двигателя и потенциометра... Подскажите кто что может пожалуйста

nik182
Offline
Зарегистрирован: 04.05.2015

Зачем ПИД? Зачем PWM? Сначала пишем скетч только с кнопкой. Нажали - едет на градусов на 40 влево или вправо, доехал по потенциометру - останавливаем и смотрим сколько переехал (это выбег)- на столько нужно выключать мотор раньше точки уставки. Потом берём компас и точно также - если угол больше выбега - включаем мотор на сколько надо, что бы остановился с учётом выбега. Не надо включать мотор часто. После пуска мотора ничего не проверять (кроме потенциометра) пока не остановился. 

rkit
Offline
Зарегистрирован: 23.11.2016

nik182 пишет:

Зачем ПИД? Зачем PWM? Сначала пишем скетч только с кнопкой. Нажали - едет на градусов на 40 влево или вправо, доехал по потенциометру - останавливаем и смотрим сколько переехал (это выбег)- на столько нужно выключать мотор раньше точки уставки.

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

nik182
Offline
Зарегистрирован: 04.05.2015

Ну может совет и бредовый, но именно по этому алгоритму отлаживал самодельную рулевую машинку на основе движка от шуруповёрта и стоящую на детской машинке. Уже полгода рулится с пульта. Сбоев не было. 

Conradk10
Offline
Зарегистрирован: 28.04.2020

nik182 пишет:

Зачем ПИД? Зачем PWM? Сначала пишем скетч только с кнопкой. Нажали - едет на градусов на 40 влево или вправо, доехал по потенциометру - останавливаем и смотрим сколько переехал (это выбег)- на столько нужно выключать мотор раньше точки уставки. Потом берём компас и точно также - если угол больше выбега - включаем мотор на сколько надо, что бы остановился с учётом выбега. Не надо включать мотор часто. После пуска мотора ничего не проверять (кроме потенциометра) пока не остановился. 

Мне нужно точное позиционирование руля в зависимости от угла на который повернулось судно, а не лево право

nik182
Offline
Зарегистрирован: 04.05.2015

Что значит точное позиционирование руля? Относительно чего? Куда указывает компас это опорная точка? Нужно устранить разницу между чем? Курсом и показанием компаса? Показанием компаса и углом руля?   В любом случае сервомашинка может крутиться в одну или в другую сторону. Команду на поворот формируете Вы в своей программе. Замените лево-право, на по часовой-против. Вам нужно рассчитать на сколько нужно повернуть сервомашинку, на какой-то угол, что бы устранить отклонение от заданного параметра. На этом основана работа регуляторов. Есть уставка - точка к которой надо стремиться, есть текущее положение, которое дают датчики, регуляторы по разным алгоритмам дают команду на исполнительный механизм для устранении разницы между уставкой и текущим положением. Как только Вы всё это опишите в своей программе, всё будет работать так как Вы хотите. Тут нужно точно понимать что такое для Вас уставка и текущее положение. Ещё нужно знать постоянную времени регулирования - время между выполнением команды регулятора и переходом всей системы в новое положение. Если это время не учитывает регулятор, то может возникнуть ситуация перерегулирования, когда за время выполнения первой команды регулятора, регулятор выдаст ещё насколько команд в том же направлении.            

Conradk10
Offline
Зарегистрирован: 28.04.2020

Разработал такой код, теперь он отвечает всем моим критериям.
 

#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BNO055.h>
#include <utility/imumaths.h>
#include <GyverButton.h>

#define EN 3              // Вывод Arduino к которому подключены входы драйвера L_EN и R_EN
#define L_PWM 4           // Вывод Arduino к которому подключён  вход  драйвера L_PWM
#define R_PWM 5           // Вывод Arduino к которому подключён  вход  драйвера R_PWM
#define fixButton 2       // Кнопка фиксации текущего значения координаты X (fixedVal)
#define led1 6            // Индикатор работы автопилота
#define relay 7           // Выход реле сцепления двигателя с рулём
#define potInput A0       // Потенциометр (обратная связь положения руля)
#define BNO055_SAMPLERATE_DELAY_MS (100)
Adafruit_BNO055 bno = Adafruit_BNO055(-1, 0x29);

float fixedVal = 0;       // Принимает значение текущей координаты X
float tempVal = 0;        // Разница между фикс координатой и настоящей
float xVal = 0;           // Текущая координата X
float engPosition = 0;    // Позиция потенциометра
float newxVal = 0;        // Новая текущая координата X
int engSpeed = 50;         // Скорость двигателя
bool apstate = 0;         // Разрешить(1)/запретить(0) работу автопилота
bool setpos = 0;          // ---
int maxSpeed = 100;       // Максимальная скорость двигателя
int minSpeed = 1;         // Минимальная скорость двигателя (не меньше 1)
GButton butt1(2);         // Кнопка управления режимом работы программы

void setup() {
  pinMode(EN,    OUTPUT);      // Конфигурируем вывод EN    как выход
  pinMode(L_PWM, OUTPUT);      // Конфигурируем вывод L_PWM как выход
  pinMode(R_PWM, OUTPUT);      // Конфигурируем вывод R_PWM как выход
  pinMode(fixButton, INPUT);   // Кнопка фиксации значения координаты fixedVal
  pinMode(led1, OUTPUT);       // Индикатор работы автопилота
  pinMode(relay, OUTPUT);      // Выход реле сцепления двигателя с рулём
  digitalWrite(led1, LOW);      
  digitalWrite(relay, LOW);
  Serial.begin(115200);
  Serial.println("Orientation System 25.04.2020");
  Wire.begin(); 
  if(!bno.begin())
  {
    Serial.print("Ooops, no BNO055 detected ... Check your wiring or I2C ADDR!");
    while(1);
  }
  delay(1000);
  bno.setExtCrystalUse(true);
  Serial.println("Loading done!");
  Serial.println("");
}

void loop() {
  sensors_event_t event;
  bno.getEvent(&event);
  xVal = event.orientation.x-180; // Значение компаса по координате X от 0..-180.(середина).180..0
  engPosition = map(analogRead(potInput), 0.00, 1023.00, -180.00, 180.00); // Текущая позиция потенциометра -180.(середина).180
  if(xVal <= 0 && xVal >= -180){
    newxVal = map(xVal, -180, 0, 0, -180);
  } else if (xVal >= 0 && xVal <= 180){
    newxVal = map(xVal, 180, 0, 0, 180);
  }

  if(newxVal > 0){
    if(newxVal > engPosition){
      digitalWrite(L_PWM, HIGH); // engPosition +
      digitalWrite(R_PWM, LOW);  // engPosition -
      analogWrite(EN, engSpeed);
    } else if (newxVal < engPosition+4 && newxVal+4 > engPosition){
      digitalWrite(L_PWM, HIGH);
      digitalWrite(R_PWM, HIGH);
      analogWrite(EN, engSpeed);
    } else if (newxVal < engPosition+2){
      digitalWrite(L_PWM, LOW); // engPosition +
      digitalWrite(R_PWM, HIGH);  // engPosition -
      analogWrite(EN, engSpeed);
    }

  } else if (newxVal < 0){
    if(newxVal < engPosition){
      digitalWrite(L_PWM, LOW); // engPosition +
      digitalWrite(R_PWM, HIGH);  // engPosition -
      analogWrite(EN, engSpeed);
    } else if (newxVal > engPosition-4 && newxVal-4 < engPosition){
      digitalWrite(L_PWM, HIGH);
      digitalWrite(R_PWM, HIGH);
      analogWrite(EN, engSpeed);
    } else if (newxVal > engPosition-2){
      digitalWrite(L_PWM, HIGH); // engPosition +
      digitalWrite(R_PWM, LOW);  // engPosition -
      analogWrite(EN, engSpeed);
    }
  }

  Serial.print("engPosition: ");
  Serial.print(engPosition);
  Serial.print(", newxVal: ");
  Serial.println(newxVal);
  delay(BNO055_SAMPLERATE_DELAY_MS);
}

Ещё подскажите пожалуйста как можно сделать плавный запуск и остановку двигателя? Чтобы значение engSpeed нарастало и убывало наверное

nik182
Offline
Зарегистрирован: 04.05.2015

На форуме были темы по плавному пуску коллекторных двигателей. Поиск по  плавный & пуск