Дергания бесщеточного мотора при управлении датчиком холла 49E

Здравствуйте всем! Делаю подводный буксир. Мотор бесщеточный 140kv. Батарея 4s li-ion. ESC BLHELI 60A. В полной нагрузке в воде ток 22А. ESC работает исправно. Если пользоваться серво тестером, скачков нет, дерганий нет. Пульт управления сделал на датчике холла 49E. Он похож на курок и диапазон значений составляет от 600 до 668. Не получается удержать обороты на двигателе с помощью этого пульта и поэтому мотор немного дергается. Пришла мысль сделать условно три скорости, но не знаю как правильно сделать. Например 1 скорость, если от 620-640 диапазон, 2-ая если значение от 641-655 и 3-я от 656 до 680. Если курок не нажимать то значение прыгает от 603 до 605. В ардуино это мой первый опыт и скетч лишь немного правил под свой датчик и свой ESC. Пожалуйста скажите реально применить такую функцию использовав датчик холла?
Вот мой скетч:

#include <Servo.h>
Servo motor;
void setup() {
  motor.attach(2);
  Serial.begin(9600);
}
void loop() {
  int val = map(analogRead(0), 620, 660, 1100, 1900);
  val = constrain(val, 1100, 1900);
  motor.writeMicroseconds(val);
  Serial.println(analogRead(0));
  delay(100);
}

Так будет дёргаться. Нужен гистерезис.

68 единиц для регулятора мотора которому надо 1000 это вообще ни о чём

я написал в каком диапазоне работает датчик холла. это от 1100 до 1900 оборотов. на полностью выжатом курке при значении 667-669, то есть полный газ - мотор не дёргается. он нормально работает, так как уже при 660 считается полный газ.

А как его вписать в код? поддерживает ли эта библиотека такой код? я не смог найти информации

Обычно исчерпывающая информация о библиотеке содержится в тексте самой библиотеки.
И очень часто какие-либо другие источники информации о конкретной библиотеке напрочь отсутствуют.

непонятно, почему так сильно датчик моросит, у меня на обычном резисторе всего 1 по значениям, надо смотреть в эту сторону, устранишь скачки
можно конечно сделать три диапазона с зазорами и получить три скорости, зазоры по 5 единиц (датчика)

Ну, как, определить не “граничащие”, как у Вас, а пересекающийся диапазоны. И переключаться только когда выходит за зону пересечения.

Не понял, причём тут библиотека вообще.

Спасибо за подсказку! Состряпал код. В терминале вроде все правильно, но не работает. Инициализация не нужна. От серво тестера работает норм. Что не так в коде? Что-то где упустил. Подскажите пожалуйста

#include <Servo.h>

Servo motor;

// Пороговые значения
const int lowThreshold = 620;     // Нижняя граница для низкой скорости
const int midThresholdLow = 630;  // Нижняя граница для средней скорости
const int midThresholdHigh = 650; // Верхняя граница для средней скорости
const int highThresholdLow = 650; // Нижняя граница для высокой скорости
const int highThresholdHigh = 750; // Верхняя граница для высокой скорости

void setup() {
  motor.attach(2);
  Serial.begin(9600);
}

void loop() {
  int sensorValue = analogRead(A0);
  int speed;

  // Если значение меньше 620, останавливаем двигатель
  if (sensorValue < lowThreshold) {
    speed = 0; // Остановка
  } 
  // Низкая скорость
  else if (sensorValue >= lowThreshold && sensorValue < midThresholdLow) {
    speed = 1100; // Низкая скорость
  } 
  // Средняя скорость
  else if (sensorValue >= midThresholdLow && sensorValue <= midThresholdHigh) {
    speed = 1500; // Средняя скорость
  } 
  // Высокая скорость с учетом гистерезиса
  else if (sensorValue > highThresholdHigh) {
    speed = 1900; // Высокая скорость
  } 
  // Проверка на высокую скорость в пределах гистерезиса
  else if (sensorValue >= highThresholdLow && sensorValue <= highThresholdHigh) {
    speed = 1900; // Высокая скорость
  } 
  // Промежуточное значение между низкой и высокой скоростью
  else {
    speed = constrain(map(sensorValue, lowThreshold, highThresholdHigh, 1100, 1900), 1100, 1900);
  }

  motor.writeMicroseconds(speed);
  Serial.print("Analog Value: ");
  Serial.print(sensorValue);
  Serial.print(" Speed: ");
  Serial.println(speed);
  delay(100);
}

Вы её не поняли.

Никакого отношения к тому, что я говорил этот код не имеет.

Наберите в поисковике “гистерезис” и разберитесь, что это такое.

поясняю Петровича, у Вас зазоров между 630 и 650 нету, а должны быть, датчик моросит на 2 единицы, чтобы мотор не дергал зазор надо удвоить а то и утроить, то есть не 630, а 627 к примеру а второй отрезок начнётся с 633

PS если не выпендриваться со знанием языка, а написать по простому в стиле ардуино, это будет сразу видно:

#include <Servo.h>

Servo motor;

// Пороговые значения
const int lowThreshold = 620;     // Нижняя граница для низкой скорости
const int midThresholdLow = 630;  // Нижняя граница для средней скорости
const int midThresholdHigh = 650; // Верхняя граница для средней скорости
const int highThresholdLow = 650; // Нижняя граница для высокой скорости
const int highThresholdHigh = 750; // Верхняя граница для высокой скорости

void setup() {
  motor.attach(2);
  Serial.begin(9600);
}

void loop() {
  int sensorValue = analogRead(A0);
  int speed;

  // Если значение меньше 620, останавливаем двигатель
  if (sensorValue < 620) {
    speed = 0; // Остановка
  } 
  // Низкая скорость
  else if (sensorValue >= 620 && sensorValue < 630) {
    speed = 1100; // Низкая скорость
  } 
  // Средняя скорость
  else if (sensorValue >= 630 && sensorValue <= 650) {
    speed = 1500; // Средняя скорость
  } 
  // Высокая скорость с учетом гистерезиса
  else if (sensorValue > 750) {
    speed = 1900; // Высокая скорость
  } 
  // Проверка на высокую скорость в пределах гистерезиса
  else if (sensorValue >= 650 && sensorValue <= 750) {
    speed = 1900; // Высокая скорость
  } 
  // Промежуточное значение между низкой и высокой скоростью
  else {
    speed = constrain(map(sensorValue, 620, 750, 1100, 1900), 1100, 1900);
  }

  motor.writeMicroseconds(speed);
  Serial.print("Analog Value: ");
  Serial.print(sensorValue);
  Serial.print(" Speed: ");
  Serial.println(speed);
  delay(100);
}

Да, в промежуточное значение ( в зазоре) должна оставаться прежняя скорость

Всем спасибо за помощь. Непросто было разобраться, но я как то смог. Всё работает отлично. Да. На радостях в первой версиях кода забыл о гистерезисе, сейчас всё сделал. Теперь у меня 3 скорости. Есть пороги переключений. Еще может добавлю чуть более плавное переключение скоростей, потому что с1 на 2 чувствуется сильный толчок, а вот с 2 на 3 его совсем не заметно так как уже мотор достаточно раскручен (нудить физикой не хочу =) . Вот полностью рабочий код для тех кто хочет управлять мотором 140KV со сборкой 4s li-ion с помощью датчика холла E49 с блоком ESC (BLHELI, ZMR и другими подобными) на arduino хоть на китайской. В моём случае LGT8F328P. Ход датчика управления 1,9 мм. Магнит извините, не помню, но сами можете подобрать. У меня с какого то CD rom.

#include <Servo.h>

Servo motor;

// Пороговые значения для скоростей
const int lowSpeedLowerBound = 620;   // Нижняя граница для первой скорости
const int lowSpeedUpperBound = 629;   // Верхняя граница для первой скорости
const int midSpeedLowerBound = 633;   // Нижняя граница для второй скорости
const int midSpeedUpperBound = 650;   // Верхняя граница для второй скорости
const int highSpeedLowerBound = 655;  // Нижняя граница для третьей скорости
const int highSpeedUpperBound = 680;  // Верхняя граница для третьей скорости

int currentSpeed = 0;
bool midSpeedActive = false; // Флаг для отслеживания состояния второй скорости

void setup() {
  motor.attach(2);
  Serial.begin(9600);

  // Инициализация ESC
  motor.writeMicroseconds(2000); // Максимальное значение
  delay(2000); // Подождите 2 секунды
  motor.writeMicroseconds(1000); // Минимальное значение
  delay(2000); // Подождите 2 секунды
}

void regulateSpeed(int sensorValue) {
  // Логика переключения скоростей
  if (sensorValue < lowSpeedLowerBound) {
    currentSpeed = 0; // Остановка
    midSpeedActive = false; // Сброс флага
  } 
  else if (sensorValue >= lowSpeedLowerBound && sensorValue <= lowSpeedUpperBound) {
    currentSpeed = 1500; // Первая скорость
    midSpeedActive = false; // Сброс флага
  } 
  else if (sensorValue >= midSpeedLowerBound && sensorValue <= midSpeedUpperBound) {
    if (!midSpeedActive) {
      currentSpeed = 1750; // Вторая скорость
      midSpeedActive = true; // Устанавливаем флаг
    }
  } 
  else if (sensorValue >= highSpeedLowerBound && sensorValue <= highSpeedUpperBound) {
    currentSpeed = 1900; // Третья скорость
    midSpeedActive = false; // Сброс флага
  }

  // Проверяем, если вторая скорость активна, и значение падает ниже 626
  if (midSpeedActive && sensorValue <= 626) {
    currentSpeed = 1500; // Возвращаемся к первой скорости
    midSpeedActive = false; // Сброс флага
  }
}

void debug(int sensorValue) {
  Serial.print("Analog Value: ");
  Serial.print(sensorValue);
  Serial.print(" Current Speed: ");
  Serial.println(currentSpeed);
}

void loop() {
  int sensorValue = analogRead(A0);
  regulateSpeed(sensorValue);
  motor.writeMicroseconds(currentSpeed);
  debug(sensorValue);
  delay(100);
}

Второй раз встречается одна и та же ошибка, я о строках калибровки (20-25)
калибровка регулятора осуществляется под данные реального канала, почему - в программе регулятора уже заложен необходимый запас снизу на старт двигателя, к примеру если с канал пришел сигнал максимума 1900 а сигнал минимума 1100, то регулятор вносит эти константы и пуск двигателя будет где-то с 1150, поэтому процедура и называется - калибровка

И поставил благодарность за это себе, любимому. В общем-то, логично, чё :slight_smile:

Это уже бич какой то, надо к модераторам обратится, не знаю, в движке можно запретить ставить эту галку самому себе.

2 лайка

Пока не совсем разобрался на форуме. Если что то буду менять в этом коде, то поделюсь. Спасибо

о тебя код ждали, а ты гистерезис да гистерезис, пришлось ТСу самому писать, ну себе и поставил )))

2 лайка

Так я ж и говорю - логично.