Я хочу закодировать датчик глубины для 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);
}
}
@rallen24, 👍0
Обсуждение2 ответа
Лучший ответ:
#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
В вашем коде есть несколько проблем:
- Вы включаете библиотеку 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
- Как разделить входящую строку?
- Как использовать SPI на Arduino?
- Как сбросить или отформатировать Arduino?
- Управление скоростью вентилятора с помощью библиотеки Arduino PID
- Arduino Due vs Mega 2560
- Как получить уникальный идентификатор для всех плат Arduino?
- Почему я получаю avrdude: stk500v2_ReceiveMessage(): timeout error when uploading to Arduino Mega?
- Тайм-аут связи Arduino Mega с ошибкой программатора
Помочь с чем? Что не работает должным образом и каков ожидаемый результат? Вы получаете какие-либо ошибки или что-то еще происходит?, @AJD
Код компилируется и работает, да, но когда он достигает установленного значения, он не удерживает скорость, чтобы поддерживать ее на заданной глубине., @rallen24
Пожалуйста, отредактируйте вопрос, чтобы добавить всю необходимую информацию. Не обязательно читать все комментарии, чтобы понять вопрос. Насчет «_он не держит скорость_»: что он делает вместо этого? Вы должны попытаться дать _полное_ описание проблемы., @Edgar Bonet
вопрос отредактирован., @rallen24