Изготовление ПИД-регулятора для датчика давления BAR 30

У меня возникли проблемы с ПИД-регулятором для датчика глубины BAR 30. У меня проблема в том, что мой ESC имеет два начальных запуска {1500-1900} - это минимум-максимум соответственно по часовой стрелке, а {1500-1900} - это максимум соответственно против часовой стрелки. Я хочу, чтобы я установил глубину, и я мог бы погрузиться на определенную глубину и зафиксироваться на этой определенной глубине.

#include <PID_v1.h>
#include <MS5837.h>
#include <Wire.h>
#include <Servo.h>
MS5837 sensor;
Servo vertical_thruster1;


// Переменные

float current_depth ;
float set_depth = 0.50 ; // глубина, которую вы хотите пройти, в метрах
float PID_error = 0;
float previous_error = 0;
float elapsedTime,  Time , timePrev;
double pwmvertical_thruster1 = 1440;

int s;

float PID_value = 0;
float PID_p = 0;
float PID_d = 0;
float PID_i = 0;
//ПИД-константы
float kp = 100;         
float ki = 0.003;
float kd = 5.2;




void setup() {
  Serial.begin(9600);  
 vertical_thruster1.attach(4);
   vertical_thruster1.writeMicroseconds(1500);

 Time = millis ();

 ///Конфигурация бара 30

  Serial.println("Starting");  
  Wire.begin();
 while (!sensor.init()) {
Serial.println("Init failed!");
Serial.println("Are SDA/SCL connected correctly?");
Serial.println("Blue Robotics Bar30: White=SDA, Green=SCL");
Serial.println("\n\n\n");
delay(2000);
  }  
  sensor.setModel(MS5837::MS5837_30BA);
  sensor.setFluidDensity(997); // кг/м^3 (пресная вода, 1029 для морской воды)
}

void loop() {

///*
// Сначала читаем текущее значение датчика глубины
sensor.read();    
current_depth = sensor.depth();

timePrev = Time; 
Time= millis();
elapsedTime = ( Time - timePrev) / 1000;

// вычисляем ошибку между заданной глубиной и текущей глубиной
 PID_error =  set_depth - current_depth ;

 // Рассчитываем значение P
 PID_p = kp * PID_error;
   Serial.print("PID_p: ");
    Serial.print(PID_p);
    Serial. println ( "\t\t");
// Рассчитываем значение i в диапазоне +-0,3

 if (-0.2 < PID_error < 0.2) 
 { 
  PID_i = PID_i + (ki * PID_error);
 }
Serial.print("PID_i: ");
Serial.print(PID_i);
Serial. println ( "\t\t");
// Рассчитываем значение d
 PID_d = kd*((PID_error - previous_error)/elapsedTime);
Serial.print("PID_d: ");
Serial.print(PID_d);
Serial. println ( "\t\t");
// Общее значение PID
PID_value = (PID_p + PID_i + PID_d) ; 

// диапазон для синей робототехники esc

if ( PID_value < -150)
 { 
 PID_value = -150;
  }
  if( PID_value >150)
  { 
  PID_value = 150;

  }
  Serial.print("PID_value: ");
  Serial.print(PID_value);
  Serial. println ( "\t\t");
 // вычисляем ШИМ

 s =  (pwmvertical_thruster1 + PID_value  );
 if(s < 1350)
{
 s= 1450;

}
else if(s> 1650)
{
  s=1550;

}
  Serial.print("Depth: "); 
  Serial.print(sensor.depth()); 
  Serial.println(" m");
  Serial.print ( "Speed s  ");
  vertical_thruster1.writeMicroseconds(s);
  Serial.print( s) ;  
  Serial. println ( "\t\t");
  previous_error = PID_error;
  // */
  delay(300);
 }

, 👍0


1 ответ


2

ПИД-регулятор должен хорошо подходить для вашего приложения, но похоже, что ваш код вообще не использует преимущества библиотеки PID_v1; объект PID_v1 никогда не объявляется, и, похоже, вы пытаетесь вручную вычислить, что библиотека PID предназначена для автоматического выполнения.

Я бы порекомендовал вам «начинать медленно и просто», изучая, как использовать ПИД-регулятор в его самой простой форме. В библиотеке ПИД есть очень простой пример, который я немного изменил, чтобы продемонстрировать, как работает ПИД-регулятор. Я протестировал этот пример с UNO, потенциометром (переменным резистором) и конденсатором. Значения резистора и конденсатора не критичны - я использовал первое, что нашел в коробке с деталями. Выход на контакте 3 представляет собой последовательность импульсов ШИМ, и комбинация резистор/конденсатор фильтрует эту последовательность импульсов в аналоговый сигнал с переменным уровнем, который ПИД-регулятор воспринимает как аналоговый «вход» на A5.

После того, как вы это запустите, вы можете изменить значение потенциометра, чтобы увидеть, как ПИД изменяет выходное значение для достижения значения уставки на входе, и вы можете изменять уставку и параметры ПИД, чтобы поиграть с различными конфигурациями. . Как только вы освоитесь с основными операциями PID, вы сможете правильно настроить их для своего приложения.

Надеюсь, это поможет,

#include <PID.h>

 // Определяем переменные, к которым мы будем подключаться
double Setpoint, Input, Output;

//Указываем ссылки и параметры начальной настройки
PID myPID(&Input, &Output, &Setpoint, 2, 5, 1, DIRECT);

void setup()
{
    Serial.begin(115200);

    // инициализируем переменные, с которыми мы связаны
    //Ввод = аналоговоеЧтение(0);
    Input = analogRead(A5);  // Я использовал A5, так как A0 был недоступен
    Setpoint = 100;

    // включаем PID
    myPID.SetMode(AUTOMATIC);
}

void loop()
{
    //Ввод = аналоговоеЧтение(0);
    Input = analogRead(A5); // Я использовал A5, так как A0 был недоступен
    myPID.Compute();
    analogWrite(3, Output);
    Serial.print("Input = "); Serial.print(Input); Serial.print(", Output = "); Serial.println(Output);
    delay(100);

}

,