Я хочу закодировать датчик глубины для arduino

Я хочу закодировать датчик глубины для маленькой субмарины, над которой я работаю. Я хочу, чтобы он погружался на любую определенную глубину, например, на 2 фута. Скорость двигателя должна увеличиваться на 5, пока не достигнет заданного значения. Проблема, с которой я столкнулся, заключается в следующем: всякий раз, когда он достигает установленной примерной точки в 2 фута, двигатель отключается, и переводник всплывает наверх и не держит глубину. Я хочу, чтобы при любой скорости двигателя на глубине 2 фута поддерживалась его скорость и сохранялась глубина погружения подводной лодки 2 фута.

#include <MS5837.h>
#include <Wire.h>
#include "MS5837.h"
#include <Servo.h>
MS5837 sensor;
Servo vertical_thruster;

float x;
float error;
int pwm = 1525;
float currentdepth = sensor.depth();       
float recquireddepth = -0.4;  // установить глубину, которую вы хотите поддерживать в метрах

void setup() {
      Serial.begin(9600);  
     vertical_thruster.attach(6);
     vertical_thruster.writeMicroseconds(1500);
 /////////////////////////////////////////////Конфигурация бара 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");
    delay(2000);
  }  
  sensor.setModel(MS5837::MS5837_30BA);
  sensor.setFluidDensity(997); // кг/м^3 (пресная вода, 1029 для морской воды)
}

void loop() {

  sensor.read(); 
  Serial.print("Depth: "); 
  Serial.print(currentdepth); 
  Serial.println("m");
error = (currentdepth) - (recquireddepth) ;

if ( error!=0)
  { pwm +=5;
    vertical_thruster.writeMicroseconds(pwm+=5);
    Serial.println( pwm+=5);
    Serial.print ( " Submerging ");
  }
if ( error=0){
  vertical_thruster.writeMicroseconds(pwm);
  Serial.print ( "  At Depth");
}
else if ( error >-0){
  vertical_thruster.writeMicroseconds(1400);
  Serial.print ( "resurfacing");
  delay(1000);
}
}

, 👍0

Обсуждение

Помочь с чем? Что не работает должным образом и каков ожидаемый результат? Вы получаете какие-либо ошибки или что-то еще происходит?, @AJD

Код компилируется и работает, да, но когда он достигает установленного значения, он не удерживает скорость, чтобы поддерживать ее на заданной глубине., @rallen24

Пожалуйста, отредактируйте вопрос, чтобы добавить всю необходимую информацию. Не обязательно читать все комментарии, чтобы понять вопрос. Насчет «_он не держит скорость_»: что он делает вместо этого? Вы должны попытаться дать _полное_ описание проблемы., @Edgar Bonet

вопрос отредактирован., @rallen24


2 ответа


Лучший ответ:

0
#include <MS5837.h>
#include <Wire.h>
#include <Servo.h>

MS5837 sensor;
Servo vertical_thruster;

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

float current_depth ;
float set_depth = 0.30 ; // глубина, которую вы хотите пройти, в метрах
float PID_error = 0;
float previous_error = 0;
float elapsedTime,  Time , timePrev;
float pwmvertical_thruster;
int PID_value = 0;
int PID_p = 0;
int PID_i = 0;
int PID_d = 0;

//ПИД-константы
float kp = 4.1;         
float ki = 0.03;
float kd = 1.8;




void setup() {
  Serial.begin(9600);  
 vertical_thruster.attach(6);
 Time = millis ();
 vertical_thruster.writeMicroseconds(1500);


///Конфигурация бара 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;

// Рассчитываем значение i в диапазоне +-0,3

 if (-0.3 < PID_error < 0.3 ) 
  { 
  PID_i = PID_i + (ki * PID_error);
  }

// Рассчитываем значение d
PID_d = kd*((PID_error - previous_error)/elapsedTime);
// Общее значение PID
PID_value = PID_p + PID_i + PID_d; 

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

 if ( PID_value < -400)
 { 
 PID_value = -400;
  }
  if( PID_value >400)
  { 
 PID_value = 400;
  }
// вычисляем ШИМ
 pwmvertical_thruster = (1500 + PID_value) || ( 1500 - PID_value);
if(pwmvertical_thruster < 1500)
 {
  pwmvertical_thruster= 1500;
  }
 if(pwmvertical_thruster > 1900)
  {
   pwmvertical_thruster=1900;
   }
    Serial.print("Depth: "); 
    Serial.print(sensor.depth()); 
    Serial.println(" m");
    vertical_thruster.writeMicroseconds(pwmvertical_thruster);
    Serial. println ( "t\t");
    Serial. println ( pwmvertical_thruster);
     previous_error = PID_error;


   }`
,

Это рабочий код? Правильно ведет себя? (Поскольку вы теперь отметили это как правильный ответ), @chrisl

@chrisl это работает, но мне нужно, чтобы мои значения были правильными, если esc правильный. У esc, который я использую, есть 2 максимума с 1500 равными для остановки. От 1500 до 1900 — от минимального до максимального по часовой стрелке, а от 1500 до 1100 — от минимального до максимального против часовой стрелки., @rallen24


2

В вашем коде есть несколько проблем:

  • Вы включаете библиотеку MS5837 дважды. Это просто не представляет проблемы, потому что в библиотеке есть защита включения, которая гарантирует, что она включена только один раз.
  • В глобальном масштабе вы используете float currentdepth = sensor.depth();, который вызывает функцию sensor.depth(). Это будет сделано перед функцией setup(), поэтому в это время в библиотеке датчиков нет достоверных данных о глубине. Так что это бесполезно. Вы можете просто установить его равным нулю.
  • В своем loop() вы выполняете sensor.read(), но на самом деле никогда не получаете новое значение глубины из библиотеки. Вы просто снова используете currentdepth, никогда его не меняя. Вы должны установить переменную в новое значение, используя currentdepth = sensor.depth(); после sensor.read().
  • Вы используете оператор if ( error=0). Использование только одного = означает присвоение. Итак, здесь переменная error устанавливается равной нулю, и оператор if не будет сравнивать ее с нулевым значением. Вы должны использовать двойной =: if(error == 0).
  • if(ошибка >-0): почему вы проверяете ошибку, превышающую МИНУС НОЛЬ. Конечно, -0 является допустимым целым числом, но в основном бессмысленным. Также сомнительно, верна ли здесь логика, поскольку сначала вы проверяете, не отличается ли ошибка от нуля. Затем вы проверяете, что оно равно нулю, а затем (если оно не равно нулю) вы проверяете, что оно больше нуля. Если error действительно окажется больше нуля, вы сначала запишете pwm в сервопривод, а затем сразу 1400, который погружается и всплывает сразу после другого только в одном цикле.
  • Вся структура if кажется совершенно неправильной. Вам следует переосмыслить логику программы.

Тем не менее, для достижения заданного значения любого типа полезно использовать ПИД-регулятор, который довольно быстро приведет вас к заданному значению и будет удерживать его там. ПИД-регулятор может быть реализован аппаратно или программно. Для реализации программного ПИД-регулятора на Arduino вы можете использовать одну из различных библиотек ПИД, например эту. Большинство библиотек также содержат примеры, показывающие, как их использовать.

,

Хорошо, через ответ. (Проголосовал) Я также собирался предложить PID. Вам нужно что-то, что будет «оттачивать» целевую глубину, а затем удерживать ее на этом уровне. Однако вам придется настроить PID с правильными значениями управления., @Duncan C

@chrisl @ Duncan CI обновил и исправил код. Вы можете взглянуть на это?, @rallen24