Управление сервами по rs485

klen7832

✩✩✩✩✩✩✩
17 Мар 2025
9
0
Ребят, из зоны СВО, прошу помощи.
Есть антенный привод, с двумя сервами, одна врашает по азимуту, другая по углу цели.
Пульт управления - джойстик и lcd-дисплей, где отображаются углы поворота.
Но всё это не работает на большом расстоянии(больше 50м.), а нужно 100м. как минимум.
Знаю, что есть возможность передачи по rs485.
Не могли бы вы накидать схему и код, для соединения посредством 485?
Код и схему приложу. Там всё просто для программистов, но нет к сожалению рядом таких.
 

klen7832

✩✩✩✩✩✩✩
17 Мар 2025
9
0
/* --------------------- Antenna v 1.2 -----------------------------
V.1.0 Реализовано:
  • Движение от стика + быстрый возврат на исходнуу позицию
  • Движение с защитой выхода за пределы мак. углов
  • Вывод на экран с кор. для удобства
V.1.1 Реализовано:
  • Выбор угла (центр позиции)
  • Запоминание угла при отключении питания
V.1.2 Реализовано:
  • Запоминание фактических углов
  • Плавный возврат к центру при включении и от кнопки.
  • Дисплей и центровка выведены в отдельные блоки
--------------- Разработанно группой ПаялоХаб ------------------------ */

// ------------------------------ Библиотеки ------------------------
#include <I2Cdev.h> // Подключаем библиотеку
#include <Servo.h> // Подключаем библиотеку
#include <LiquidCrystal_I2C.h> // Подключаем библиотеку
#include <EEPROM.h> //Подключаем библиотеку

// ------------------------------ Управление ------------------------
LiquidCrystal_I2C lcd(0x27,16,2); // обьявляем экран
Servo myservo1; // обьявляем серво
Servo myservo2; // обьявляем серво

// ------------------------------ Переменные ------------------------
int dirX = 90; //центр 90
int dirX_center = 0; //Указатель центра
float dirX_disp = 0; //Переменная для правельного отображения угла на дисплее
int dirY = 90; //пог 65, центр 155
int dirX_Go = 0; //шаг для серво (плавность)
int dirY_Go = 0; //шаг для серво (плавность)
int x; // ось х стик
int y; // ось y стик
int val = 1; // Кнопка стика
int work = 0; // режим работы

void setup() // основной код. выполняется разово
{
pinMode(5, INPUT); // ввкл. кнопки стика
digitalWrite(5, HIGH); // уст. напряжение
lcd.init(); // вкл. экрана
lcd.backlight(); // Включаем подсветку
lcd.clear(); // Очистка экрана
lcd.setCursor(0, 0); // Позиция курсора
lcd.print("X :"); // вывод инф.
lcd.setCursor(0, 1); // Позиция курсора
lcd.print("Y :"); // вывод инф.
dirX = (EEPROM.read(2)); // Читаем с памяти dirX
dirY = (EEPROM.read(3)); // Читаем с памяти dirY
if (dirX < 0) {dirX = 90;} // Защита
if (dirX > 180) {dirX = 90;} // Защита
if (dirY < 0) {dirY = 90;} // Защита
if (dirY > 90) {dirY = 90;} // Защита
if (dirX < 90) {CenterGo1();} //Центровка
if (dirX > 90) {CenterGo2();} //Центровка
while (dirY < 90) //Центровка
{
dirY = dirY + 2; ////Центровка
oled(); // Экран
myservo2.attach(9); //Вкл. серво
myservo2.write(dirY+65); //Направляем серво
delay(150); // задержка
myservo2.detach(); // откл. сервы
}
dirY = 90; // Контроль
myservo2.attach(9); //Вкл. серво
myservo2.write(dirY+65); //Направляем серво
delay(150); // задержка
myservo2.detach(); // откл. сервы
dirX_center = dirX_center + (EEPROM.read(1)); //Читаем с памяти 2 значение
dirX_center = dirX_center + (EEPROM.read(0)*100); //Читаем с памяти 1 значение
if (dirX_center <0 and dirX_center>360){dirX_center = 0;} //Защита от ошибок
delay (3000); // Задержка
lcd.clear(); // Очистка экрана
lcd.setCursor(0, 0); // Позиция курсора
lcd.print("Center:"); // вывод инф.
}

void loop() // основной код. выполняется циклично
{
//Работа 0 - поворотный механизм выключен. Задаем центр
if (work == 0)
{
val = digitalRead(5); // состояние кнопки (0 нажата кнопка, 1 - нет)
dirX_disp = analogRead(A0); // считываем данные по x со стика
if (dirX_disp <= 123 ) {dirX_center = dirX_center - 2;} //шаг для указания центра
if (dirX_disp > 123 and dirX_disp <= 462) {dirX_center = dirX_center - 1;} //шаг для указания центра
if (dirX_disp >= 562 and dirX_disp < 900) {dirX_center = dirX_center + 1;} //шаг для указания центра
if (dirX_disp > 900) {dirX_center = dirX_center + 2;} //шаг для указания центра

if (val == 0) //Если нажата кнопка серво (возврат на начальную позицию)
{
work = 1; // сброс движения серво
lcd.clear(); // Очистка экрана
lcd.setCursor(0, 0); // Позиция курсора
lcd.print("X :"); // вывод инф.
lcd.setCursor(0, 1); // Позиция курсора
lcd.print("Y :"); // вывод инф.
if (dirX_center < 100){EEPROM.write(0, 0);} // Записываем в память 1 значение
if (dirX_center >= 300) {dirX_center = dirX_center - 300; EEPROM.write(0, 3);} //Записываем в память 1 значение
if (dirX_center >= 200) {dirX_center = dirX_center - 200; EEPROM.write(0, 2);} //Записываем в память 1 значение
if (dirX_center >= 100) {dirX_center = dirX_center - 100; EEPROM.write(0, 1);} //Записываем в память 1 значение
EEPROM.write(1, dirX_center); // Записываем в память 2 значение
dirX_center = dirX_center + (EEPROM.read(0)*100); // Читаем с памяти 1 значение
if (dirX_center <0 and dirX_center>360){dirX_center = 0;} //Защита от ошибок
}

// дисплей
if (dirX_center < 0) {dirX_center = dirX_center + 360;} // защита
if (dirX_center >= 360) {dirX_center = dirX_center - 360;} // защита
lcd.setCursor(7, 0); // Позиция курсора
if (dirX_center < 10) {lcd.print(" ");} // вывод инф.
if (dirX_center >= 10 and dirX_center < 100) {lcd.print(" ");} // вывод инф.
if (dirX_center >= 100) {lcd.print(" ");} // вывод инф.
lcd.print(dirX_center); // вывод инф.
delay(150); // задержка
}

//Работа 1 - поворотный механизм включен
if (work == 1)
{
// Данные со стика
val = digitalRead(5); // состояние кнопки (0 нажата кнопка, 1 - нет)
x = analogRead(A1); // считываем данные по x со стика
if (x <= 123 ) {dirX = dirX + 2; dirX_Go = 1;} //шаг для серво (плавность)
if (x > 123 and x <= 462) {dirX = dirX + 1; dirX_Go = 1;} //шаг для серво (плавность)
if (x >= 562 and x < 900) {dirX = dirX - 1; dirX_Go = 1;} //шаг для серво (плавность)
if (x > 900) {dirX = dirX - 2; dirX_Go = 1;} //шаг для серво (плавность)
y = analogRead(A0); // считываем данные по y со стика
if (y <= 23 ) {dirY = dirY + 2; dirY_Go = 1;} //шаг для серво (плавность)
if (y > 23 and y <= 462) {dirY = dirY + 1; dirY_Go = 1;} //шаг для серво (плавность)
if (y >= 562 and y < 1000) {dirY = dirY - 1; dirY_Go = 1;} //шаг для серво (плавность)
if (y > 1000) {dirY = dirY - 2; dirY_Go = 1;} //шаг для серво (плавность)

// защита пределов углов
if (dirX < 0) {dirX = 0; dirX_Go = 0;} // Предел угла для x
if (dirX > 180) {dirX = 180; dirX_Go = 0;} // Предел угла для x
if (dirY < 0) {dirY = 0; dirY_Go = 0;} // Предел угла для y
if (dirY > 90) {dirY = 90; dirY_Go = 0;} // Предел угла для y

EEPROM.write(2, dirX); // Записываем в память X значение
EEPROM.write(3, dirY); // Записываем в память Y значение

// Перемещение серво
if (val == 0) //Если нажата кнопка серво (возврат на начальную позицию)
{
dirX_Go = 0; // сброс движения серво
if (dirX < 90) {CenterGo1();}
if (dirX > 90) {CenterGo2();}
while (dirY < 90)
{
dirY = dirY + 2; //плавное движение
oled(); //экран
myservo2.attach(9); //Вкл. серво
myservo2.write(dirY+65); //движение серво
delay(150); // задержка
myservo2.detach(); // откл. сервы
}
dirY = 90; //контроль
myservo2.attach(9); //Вкл. серво
myservo2.write(dirY+65); //движение серво
delay(150); // задержка
myservo2.detach(); // откл. сервы
}
if (dirX_Go == 1) // Если движение серво по оси х доступно
{
myservo1.attach(8); // вкл. серво
myservo1.write(dirX); // поворот серво
dirX_Go = 0; // сброс движения серво
}
if (dirY_Go == 1) // Если движение серво по оси y доступно
{
myservo2.attach(9); // вкл. серво
myservo2.write(dirY+65); // поворот серво
dirY_Go = 0; // сброс движения серво
}
oled(); //экран
delay(150); // задержка
myservo1.detach(); // откл. сервы
myservo2.detach(); // откл. сервы
}
}

void CenterGo1 ()
{
while (dirX < 90)
{
dirX = dirX + 2; //плавное движение
oled(); //экран
myservo1.attach(8); //Вкл. серво
myservo1.write(dirX); //Направляем серво
delay(150); // задержка
myservo1.detach(); // откл. сервы
}
dirX = 90; //Контроль
myservo1.attach(8); //Вкл. серво
myservo1.write(dirX); //Направляем серво
delay(150); // задержка
myservo1.detach(); // откл. сервы
oled(); //экран
}

void CenterGo2 ()
{
while (dirX > 90)
{
dirX = dirX - 2; //плавное движение
oled(); //экран
myservo1.attach(8); //Вкл. серво
myservo1.write(dirX); //Направляем серво
delay(150); // задержка
myservo1.detach(); // откл. сервы
}
dirX = 90; //Контроль
myservo1.attach(8); //Вкл. серво
myservo1.write(dirX); //Направляем серво
delay(150); // задержка
myservo1.detach(); // откл. сервы
oled(); //экран
}

void oled ()
{
// дисплей (с кор. показаний для удобства восприятия)
dirX_disp = -1.66*(dirX-90); //Находим изменение угла
dirX_disp = dirX_center + dirX_disp; //Находим изменение угла от центра
if (dirX_disp < 0) {dirX_disp = dirX_disp + 360;} // защита
if (dirX_disp >= 360) {dirX_disp = dirX_disp - 360;} // защита
lcd.setCursor(3, 1); // Позиция курсора
if (dirX_disp < 10) {lcd.print(" ");} // вывод инф.
if (dirX_disp >= 10 and dirX_disp < 100) {lcd.print(" ");} // вывод инф.
if (dirX_disp >= 100) {lcd.print(" ");} // вывод инф.
lcd.print(dirX_disp); // вывод инф.
lcd.setCursor(3, 0); // Позиция курсора
if (((dirY-90)*-1) < 10) {lcd.print(" ");} // вывод инф.
if (((dirY-90)-1) >= 10 and ((dirY-90)-1) < 100 ) {lcd.print(" ");} // вывод инф.
lcd.print((dirY-90)*-1); // вывод инф.
lcd.print(".00 "); // вывод инф.
}
 

klen7832

✩✩✩✩✩✩✩
17 Мар 2025
9
0
@Геннадий П, а какая разница? Я прошу помощи в рамках интересов этого форума. И мало того, что это будет интересно кому-то в техническом плане, так тем более, что это в интересах войск в зоне СВО. Просто у вас видимо интересы не в этой стране. Извините за флуд, но я должен был ответить.
 

ZamPoTeh

✩✩✩✩✩✩✩
2 Янв 2024
5
0
Сервы точно подключены к D8, D10? Может быть D9, D10? И ещё вопрос, сервы какие?
 

klen7832

✩✩✩✩✩✩✩
17 Мар 2025
9
0
@ZamPoTeh, да, точно. Дело в том, что на коротком отрезке витой пары все работает адекватно, но при увеличении длинны кабеля, более 30м., сервы сходят с ума - постоянные дергания, зависания. Питание в норме, тем более, даем 24В. с понижением. Видимо все-таки управляющему сигналу слишком далеко. Сервы обычные (270градусов./35кг. и 180гр./25кг.). Если нужно, сделаю фото.
 

klen7832

✩✩✩✩✩✩✩
17 Мар 2025
9
0
@ZamPoTeh, можно более подробно, что это, для чего, и что и куда припаивать? В табличном формате можно.
 

ZamPoTeh

✩✩✩✩✩✩✩
2 Янв 2024
5
0
Это усилитель, увеличит нагрузочную способность ардуинки, только питание на неё придется подавать отдельно
 

klen7832

✩✩✩✩✩✩✩
17 Мар 2025
9
0
@ZamPoTeh, с самой обвязкой разберёмся. Куда её цеплять на ардуино?

И вопрос по 485... не проще он, не надёжнее ли?
 

ZamPoTeh

✩✩✩✩✩✩✩
2 Янв 2024
5
0
У Вас сервы управляются ШИМ сигналом, при чём тут RS485. Микросхемку к выходу ардуино. Она 7-ми канальная, я бы попробовал даже выходы запараллелить, если нагрузочной способности на 100м витуху не хватит.
 

klen7832

✩✩✩✩✩✩✩
17 Мар 2025
9
0
@ZamPoTeh, ок.
Будем пробовать.
Можно подробнее по подключению этой микросхемы к ардуино? Что там и куда, на какой контакт микросхемы, и на какой пин платы?
 

poty

★★★★★★✩
19 Фев 2020
3,353
961

@klen7832, давайте не будем прикрываться СВО. Чувствительные темы в открытом разделе писать, даже если они по теме форума, не самая хорошая идея. Хотя бы потому, что идентифицировать сторону помощи на этом форуме невозможно.
А так, расстояние между чем и чем должно быть 100м? Упоминание RS485 предполагает вынос управления (джойстик или что там у Вас), но Вы согласились на тестирование драйвера, а это уже между МП и сервоприводами.