ARDUINO Радиоуправление для подводной лодки на HC12

Mosy25605

✩✩✩✩✩✩✩
22 Мар 2024
5
0
Добрый день , помогите убрать непроизвольные повороты сервоприводов.
В проекте используется 4 сервопривода и коллекторный мотор.
Передатчик(пульт 2 джойстика + 3х позиционная кнопка"крайнее положение 0v- среднее 2.5в - крайнее 5в ) и потенциометр
Скетч
//Скетч передатчика::
#include <SoftwareSerial.h>
SoftwareSerial HC12(11, 10); //выбор пинов для обмена данными (D11 - TX, D10 - RX)

int pin1 = A0; //пин для приема сигнала с первого стика газ вперед мотор
int pin2 = A1; //пин для приема сигнала со второго стика поворот лево-право
int pin3 = A2; //пин для приема сигнала с второго стика  поворот вверх-вниз
int pin4 = A3; //пин для приема сигнала с 3х позиц.тумблер глубина
int pin5 = A4;//пин для приема сигнала с крутилки 2 крылья

byte arr[] = {0, 0, 0, 0, 0}; //массив, в котором будем отправлять данные

void setup() {

//Serial.begin(9600);   //инициализация работы порта на скорости 9600 бод

  HC12.begin(57600); //инициализация работы порта на скорости 57600 бод
  pinMode(pin1, INPUT); //настройка пина A0 на прием данных
  pinMode(pin2, INPUT); //настройка пина A1 на прием данных
  pinMode(pin3, INPUT); //настройка пина A2 на прием данных
  pinMode(pin4, INPUT); //настройка пина A3 на прием данных
  pinMode(pin5, INPUT); //настройка пина A4 на прием данных
}

void loop() {
         //чтение, масштабирование и запись в массив данных с пинов А0 - А7
  arr[0] = map(analogRead(pin1), 0, 1023, 0, 180);  //пин для приема сигнала с первого стика газ вперед мотор 180
  arr[1] = map(analogRead(pin2), 0, 1023, 0, 90);   //пин для приема сигнала со второго стика поворот лево-право 90
  arr[2] = map(analogRead(pin3), 0, 1023, 0, 90);   //пин для приема сигнала с второго стика  поворот вверх-вниз 90
  arr[3] = map(analogRead(pin4), 0, 1023, 30, 140);  //пин для приема сигнала с 3х позиц.тумблер глубина 179
  arr[4] = map(analogRead(pin5), 0, 1023, 20, 160);  //пин для приема сигнала с с крутилки 2 крылья 160
//Вывод в монитор портов что передаем ВКЛЮЧИ ВЫШЕ Serial.begin(9600);
//Serial.print(arr[0]);
//Serial.print(arr[1]);
//Serial.print(arr[2]);
//Serial.print(arr[3]);
//Serial.print(arr[4]);
//Serial.println( " " );

HC12.write(arr, 5); //передача сигнала другому модулю
delay(200); //пауза на 0.2 секунды для стабилизации
}

Данные передаются в формате 9246458977


//Скетч приемника::
#include <SoftwareSerial.h>
#include <Servo.h>

SoftwareSerial HC12(11, 10); //выбор пинов для обмена данными (D11 - TX, D10 - RX)
Servo motor, servo2, servo3, servo4, servo5; // задаем переменные типа Servo

byte arr[] = {0, 0, 0, 0, 0}; //массив для записи входящего сигнала

void setup() {

  HC12.begin(57600); //инициализируем работу порта на скорости 57600 бод

  motor.attach(3); //привязка мотор к пину 3 мотор газ
  servo2.attach(4); //привязка серводвигателя к пину 4 лево-право
  servo3.attach(5); //привязка серводвигателя к пину 5 вверх-вниз
  servo4.attach(6); //привязка серводвигателя к пину 6 сервопривод глубины
  servo5.attach(7); //привязка серводвигателя к пину 7 сервопривод выход передних рулей

}

void loop() {

HC12.readBytes(arr, 5); //принимаем сигнал и заполняем ячейки массива

  motor.write(arr[0]); //фиксируем вал первого серводвигателя под заданным углом
  delay(10); //пауза на 0.01 секунды для стабилизации
  servo2.write(arr[1]); //фиксируем вал второго серводвигателя под заданным углом
  delay(10); //пауза на 0.01 секунды для стабилизации
  servo3.write(arr[2]); //фиксируем вал первого серводвигателя под заданным углом
  delay(10); //пауза на 0.01 секунды для стабилизации
  servo4.write(arr[3]); //фиксируем вал второго серводвигателя под заданным углом
  delay(10); //пауза на 0.01 секунды для стабилизации
  servo5.write(arr[4]); //фиксируем вал первого серводвигателя под заданным углом
  delay(10); //пауза на 0.01 секунды для стабилизации
}
 

bort707

★★★★★★✩
21 Сен 2020
3,058
910
Подводная лодка на радиоуправлении? И что, модули НС12 и под водой передают?
 

Bruzzer

★★★✩✩✩✩
23 Май 2020
472
134
@Mosy25605,
Непроизвольные повороты - как это выглядит - при каких действиях, на какой угол и т.д.
Но общие замечания:
  • При использовании Servo и SoftwareSerial могу возникать колебания (обычно небольшие) около заданного положения, т.к. SoftwareSerial запрещает прерывания на время приема и Servo может выдавать длительность импульсов с ошибками.
  • HC12.readBytes(arr, 5); Наверное стоит проверять, сколько реально байт получено.
Добавлено позже.
Необходимо предусмотреть согласованность передатчика и приемника. Сейчас у вас возможна ситуация, когда Передача и прием будут вестись со сдвигом - Передатчик отправляет 12345 12345 12345 ... Приемник принимает 34512 34512 34512 ...
 
Изменено:

Mosy25605

✩✩✩✩✩✩✩
22 Мар 2024
5
0
Спасибо всем откликнувшимся!!!!
согласованность передатчика и приемника
Все четко
Передатчик Пульт отправляет угол поворота 9245448488
Приемник принимает

18:40:37.223 -> 9245448488
18:40:37.410 -> 9245448488
18:40:37.597 -> 9245448488
18:40:37.831 -> 9245448488
18:40:38.018 -> 9245448488
18:40:38.206 -> 9245448488
18:40:38.393 -> 9275137133253 редко такое скорее всего помехи.
18:40:38.627 -> 9245448488
18:40:38.814 -> 9245448488
18:40:39.001 -> 9245448488
18:40:39.235 -> 9245448488
18:40:39.422 -> 9245448488

Все равно все сервоприводы дергаются.
Заметил если отключить пульт, то сервы прекращают дергатся.
Видео попозже скину.
 

bort707

★★★★★★✩
21 Сен 2020
3,058
910
согласованность передатчика и приемника
Все четко
вы бы не спорили, а слушали что вам говорят.
@Bruzzer дело написал. Передавать голые данные по последовательному порту, надеясь что приемник их примет в правильном порядке - лотерея. Правильные программы так не пишутся. В посылке данных обязательно должен быть заголовок, отмечающий начало пакета. И терминатор - там где окончание. Только в этом случае вы можете быть уверены, что приемник принял правильные данные.
 

Геннадий П

★★★★★★✩
14 Апр 2021
1,970
632
45
Только в этом случае вы можете быть уверены, что приемник принял правильные данные.
Это при условии протокола включающего в себя встроенную проверку целостности данных. Например Bluetooth на сколько помнится имеет такую проверку. Но на "голой" передачи данных нужны еще контрольные суммы передаваемых данных.
 

rkit

★★★✩✩✩✩
5 Фев 2021
508
127
Сервоприводы sg90, стоит полагать? Они дергаются от плохого питания и в целом схемотехники.
 

Bruzzer

★★★✩✩✩✩
23 Май 2020
472
134
@Mosy25605,
Можно попробовать не использовать SoftwareSerial для приема от HC12, а использовать обычный Serial. Т.е на принимающей стороне соединить RX Ардуино и TX приемника и отсоединять (например переключателем) на время прошивки.
Зачеркнуто позже - как не правильный совет, т.к. в HC-12 скорее всего стоит последовательный резистор 1 КОм на линиях RX и TX, и при подключенной CH310 уровни сигналов будут "неправильные".
 
Изменено:

Bruzzer

★★★✩✩✩✩
23 Май 2020
472
134
@Mosy25605,
Я был неправ, когда писал про подключение к обычному Serial на плате NANO. Не учел, что в модуле HC-12 стоят последовательные резисторы 1 КОм на линиях RX и TX.
 

Mosy25605

✩✩✩✩✩✩✩
22 Мар 2024
5
0
Помогите переписать под ServoTimer2 или как попробывать без библиотеки servo
 

Bruzzer

★★★✩✩✩✩
23 Май 2020
472
134
@Mosy25605,
В чем у вас сложность с ServoTimer2 ? Все аналогично, только угол задается не в градусах (или микросекундах), а только в микросекундах. Можно использовать функцию map для перевода. По хорошему (по описанию) и для Servo.h рекомендуется проверять заданное по умолчанию соответствие Угол => мкс. (или мкс. => Угол. )

Зачем вам ServoTimer2 ?
Если чтобы запустить AltSoftSerial, то если можно уменьшить скорость обмена по Serial до 9600 (или 19200) - попробовать использовать другую программу, которой не нужен Timer1 (Хотя AltSoftSerial наверное лучше)
(Первое сообщение в теме. Сам не пробовал)

Но я продолжаю считать, что в вас не надежный протокол в плане восстановления после сбоев. Когда, как я писал раньше "Передатчик отправляет 12345 12345 12345 ... Приемник принимает 34512 34512 34512 ... ". Здесь 12345 - это номера байт в пакете. Посмотрите сами с расчетами, что будет, если приемник включится когда передатчик отправляет 3 (или был сбой и 12 потерялись). Приемник примет 345 и будет ждать секунду данные(время по умолчанию может быть другое). Т.к. передатчик отправляет чаще, чем раз в секунду, то приемник дождется 12 и продолжит выполнение, а 345 запишутся в приемный буфер и так далее.
 
Изменено:

VictorArx

★★✩✩✩✩✩
22 Мар 2021
525
86
Ещё сервоприводы дёргаются, когда корпус дуньки не соединён с корпусом питания серво.
 

Bruzzer

★★★✩✩✩✩
23 Май 2020
472
134
@Mosy25605,
А какие у вас сомнения?
Смотрите. Сейчас у вас данные не могут быть меньше 5 или больше 175. Поэтому в этом конкретном случае можно выбрать, например, стартовый байт=1, конечный байт 254 (1 и 254 это не символы а значение байта). Но если в дальнейшем допускается, что данные смогут принимать все значения от 0 до 254, тогда 1 и 254 ничем не лучше '#' и ';'

Дополнено позже.
В целом, по этому проекту на вопросы - "правильно ли я делаю?" ответ зависит от вашей цели.
Если это учебное задание - то зависит от того, какие знания вы должны продемонстрировать, и в каком объеме на устраивающую вас оценку.

Отлавливать ошибки приема передачи можно разными способами с разной степени надежности. Но если сигнал не будет приниматься под водой, то усилия сведутся на нет.
Дальность связи у HC12 зависит в том числе от скорости по сом порту, и для скорости 57600 - она минимальна.
 
Изменено:

VictorArx

★★✩✩✩✩✩
22 Мар 2021
525
86
motor.attach(9); //привязка серводвигателя к пину 3 мотор газ
 

Bruzzer

★★★✩✩✩✩
23 Май 2020
472
134
Помогите сменить на AltsoftSerial
Я сам не работал с сервами, но судя по описанию, я думаю что связка AltSoftSerial и ServoTimer2 это рабочий вариант.

Устанавливаете библиотеку AltSoftSerial
Открываете файл примера из этой библиотеки Echo.ino
Пробуете, добиваетесь работы.

Устанавливаете библиотеку ServoTimer2
Открываете файл примера из этой библиотеки.
Пробуете, добиваетесь работы.
Основное отличие ServoTimer2 это то, что угол поворота задается ТОЛЬКО в мкс
при помощи функции map можете пересчитывать угол в градусах - угол в мкс
В самой библиотеке Servo.h это и делается, но автоматически
C++:
void Servo::write(int value)
{
  if(value < MIN_PULSE_WIDTH)
  {  // treat values less than 544 as angles in degrees (valid values in microseconds are handled as microseconds)
    if(value < 0) value = 0;
    if(value > 180) value = 180;
    value = map(value, 0, 180, SERVO_MIN(),  SERVO_MAX());
  }
  this->writeMicroseconds(value);
}

После этого меняете вашу программу
#include <SoftwareSerial.h>
#include <ServoTimer2.h>
AltSoftSeriall HC12; //пины для обмена данными ТОЛЬКО (D9 - TX, D8 - RX)
ServoTimer2 motor, servo0, servo3, servo4, servo5;
Угол сервам передаете не сразу, а после пересчета через map в мкс

По поводу того, что "я не программист".
На мой взгляд для изготовления машины важно понимать работу узлов машины и их особенности.
При работе с Серво, скорее необходимо, чем желательно понимать их общие принципы работы, и особенности конкретно вашего экземпляра. Не сломается ли серва если будет часто упираться в ограничение, какой реальный угол поворота у вашего экземпляра и каким временам в мс это соответсвтует.
Например у Гайвера в ОЧЕНЬ короткой статье про сервы, в одном месте нарисовано, что длительность меняется от 1 мкс до 2 мс. В другом месте, что "стандартный: 544.. 2400 мкс". А в файле ServoTimer2.h хоть в описании и упоминаются "стандартный: 544.. 2400 мкс", но реально заданы 750 .. 2250

P/S
Скажите, вы уже проводили опыты - до какой глубины и расстояния сохраняется связь?
 

Mosy25605

✩✩✩✩✩✩✩
22 Мар 2024
5
0
AltSoftSeriall HC12; //пины для обмена данными ТОЛЬКО (D9 - TX, D8 - RX)
Не как не работает что только не делал.
Есть у кого пример
 

Bruzzer

★★★✩✩✩✩
23 Май 2020
472
134
@vortigont,
У ТС проблема не с контроллером. На данном этапе atmega328 вполне достаточно.
Проблема, что "Не как не работает что только не делал."
А с "более современным контроллером" причин для "Не как не работает что только не делал." намного больше (ИМХО).
В #23 сообщении, я по шагам описал порядок действий.
Какие этапы действий у ТС работают, какие нет - не понятно.
 
Изменено:
  • Ахах! +1
Реакции: vortigont

Mosy25605

✩✩✩✩✩✩✩
22 Мар 2024
5
0
@Bruzzer,Добрый вечер.Проблему решил но об этом позже.
На ардуино nano коректно работает только 4 сервопривода. Возможно из за таймеров.
Если на ServoTimer2 ставиш больше 3х сервоприводов (вываливается ошибка с таймерами).
ТАНЦЕМ С БУБНОМ СДЕЛАЛ НО ВПУСТУЮ ПОТРАЧЕННО ВРЕМЯ!
То есть ServoTimer2 и AltSoftSerial все тоже самое тергаюся приводы.

Bruzzer
Помощь 0. Только время потратил.
vortigont
Современные контроллеры не поместятся и хотелось бюджетненько.)))
 
Изменено:

Bruzzer

★★★✩✩✩✩
23 Май 2020
472
134
Помощь 0. Только время потратил.
Ну хоть я получил от вас какие то знания.
Я до этого не знал о ServoTimer2 и соответственно не знал готового решения для Servo и AltSoftSerial.
У себя на симуляторе в Proteus проверил, вроде работает. Проверял для 5 серв, Дрожание в Proteus (на глаз) не больше градуса.

Так как вы проблему решили, то дальше уже не важные замечания.
Понимать ваши сообщения не легко.
"На ардуино nano коректно работает только 4 сервопривода."
"Если на ServoTimer2 ставиш больше 3х сервоприводов (вываливается ошибка с таймерами). "

Сначала 4 работают корректно.
Потом больше 3-х - вываливается ошибка. (Т.е. для 4 тоже вываливается ошибка).
Сообщение ошибки не приведено.
Вполне возможно, что связка ServoTimer2 и AltSoftSerial не работоспособна в вашем случае, но из ваших сообщений трудно понять почему.