Радиоуправляемый танк. Часть 1 – Базовый функционал

Идея создать что-то на пульте управления зародилась довольно давно. Были варианты сделать машину или небольшой танк (гусеничную платформу). В качестве первого проекта была выбрана платформа, т.к. реализовать её поворот вправо и влево- проще чем в машинке.

Итак, цели данного проекта:
  1. Освоить основы беспроводной передачи данных по радиоканалу.
  2. Понять, как работает драйвер двигателя.
  3. Поработать с механикой.
Заказ необходимых компонентов.
  1. Модули Arduino nano x2(для пульта и для танка).
  2. Драйвер двигателя двухканальный.
  3. Беспроводные модули для передачи данных NRF24L01
  4. Адаптеры для модулей NRF24L01+
  5. Небольшой джойстик для управления.
  6. Сама платформа (уже имеет на борту два двигателя с редукторами, выключатель и отсеки для 4-х батареек)
  7. Так же понадобятся некоторые сопутствующие компоненты (макетная плата, провода, диоды)
  8. Это очень важны пункт. Нужно купить 2 электролитических конденсатора (10v, 100мкФ).
О модулях беспроводной связи

Когда я принимал решение, какие модули заказывать, особо не задумывался, что брать. Поэтому, после пары статей были заказаны два модуля NRF24L01 с усиленной антенной. Так же были куплены адаптеры питания для запуска модулей.

Зачем нужны адаптеры питания? NRF24L01 питается от 3.3 вольт, но при подключении его напрямую к выходу ардуино 3.3 вольта, он при запуске, кратковременно потребляет большой ток, который ардуино может не выдать. Поэтому, рекомендуется соединение через адаптер. Он соединяется с 5 вольтами и понижает напряжение до 3.3 вольт, имеет на борту регулятор напряжения.

Так же, в статьях был описан вариант- напаять конденсатор (10 v 100 мкФ) к пинам питания NRF24L01 и подключать напрямую к ардуино.

Забегая вперед, хочу сказать, что, скорее всего, конденсатор напаивать придется в любом случае. Хоть и нижеописанная тестовая установка у меня заработала без него – по итогу были проблемы с собранным танком. И только после того, как были припаяны конденсаторы – все встало на свои места. Поэтому, я рекомендую после покупки сделать это сразу – хуже точно не будет.

Тестирование модулей беспроводной связи

Для тестирования была собрана небольшая установка с двумя ардуино и модулями связи. Задумка была следующая: при замыкании входа на одной ардуино, должен загореться диод, подключенный к другой ардуино.

Тестовый стенд
Рисунок 1. Тестовый стенд для проверки работоспособности радио модулей.

Модуль NRF24L01 соединяем с адаптером (просто вставляем модуль в адаптер). Далее адаптер подключаем к ардуино:

NRF24L01Arduino
VCC5V
GNDGND
MISO12
MOSI11
SCK13
CSN10*
CE9*

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

Нужно учитывать, что для каждой платы своя распиновка подключения беспроводного модуля. Их можно найти в свободном доступе. Если вы хотите подключить модуль напрямую, то VCC нужно подключать к 3v3.

Формально определяем, какая ардуино будет отправлять сигнал, а какая будет его принимать. К D5 пину принимающей ардуино подключаем диод. Пин D8 отправляющей ардуино притягиваем резистором 10 кОм к массе (этот пин будет играть роль кнопки, просто кнопки в наличие не было).

Далее нужно установить библиотеку RF24 в IDE. Очень советую ставить самую новую версию библиотеки. При первых проверках модуль не работал т.к. была скачана старая библиотека.

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

Если модули работают, то можно проверить управление диодом.

Теперь на отправляющую ардуино заливаем скетч:

#include <SPI.h
#include <nRF24L01.h>
#include <RF24.h>
#define PIN_LED 8 
#define PIN_CE  9 
#define PIN_CSN 10
RF24 radio(PIN_CE, PIN_CSN); 

int pinValue[1];

void setup() {
  pinMode(8, INPUT);
  radio.begin(); 
  radio.setChannel(5);
  radio.setDataRate (RF24_1MBPS);
  radio.setPALevel(RF24_PA_HIGH); 
  radio.openWritingPipe(0x7878787878LL); 
}

void loop() {
  pinValue[0] = digitalRead(PIN_LED);
  radio.write(pitValue, sizeof());
}

На принимающую ардуино заливаем следующий скетч:

#include <SPI.h>  
#include <nRF24L01.h> 
#include <RF24.h>
#define PIN_LED 5  
#define PIN_CE  9  
#define PIN_CSN 10
RF24 radio(PIN_CE, PIN_CSN); 

int pinValue[1]; 

void setup() {
  pinMode(PIN_LED, OUTPUT); 
  radio.begin();  
  radio.setChannel(5); 
  radio.setDataRate (RF24_1MBPS); 
  radio.setPALevel(RF24_PA_HIGH); 
  radio.openReadingPipe (1, 0x7878787878LL); 
  radio.startListening(); 
}

void loop() {
  if(radio.available()){ // Если в буфер приёмника поступили данные
    radio.read(&potValue, sizeof(potValue)); // Читаем показания потенциометра
    digitalWrite(PIN_LED, pinValue[0]); // Регулируем яркость диода
  }
}

Далее, все включаем. Диод не должен гореть. Теперь, на отправляющей стороне замыкаем D8 пин на 5 вольт – диод должен загораться.

И вот здесь меня поджидал сюрприз. Собранная схема заработала, хотя и с некоторыми помехами. Поэтому я приступил к сборке танка. Но  там я столкнулся с проблемой, которая была вызвана отсутствием конденсатора на модуле.

Сборка пульта и его логика работы.

 Для управления танком – будет собран небольшой пульт. От пульта к танку будет передавать массив байтов из двух элементов.

Первый элемент будет отвечать за движение левой гусеницы, а второй – правой. Каждый из элементов будет принимать значение 0, 50 или 100 (эти значения можно изменить на любые другие).

0 – не вращать гусеницу,

50 – движение вперед,

100 – движение назад.

Управляться танк будет с помощью четырехпозиционного джойстика. Изначально, была идея осуществлять управление с помощью небольшой матричной клавиатуры, но после некоторых тестов, стало понятно, что на такой клавиатуре нельзя одновременно наживать 2 и более кнопок в одном ряду (или столбце – в зависимости от соединения). Эта проблема решается, с помощью диодов. Так же, есть некоторые непонятные моменты с отлавливанием зажатых кнопок.

Блок клавиатуры
Рисунок 2. Матричная клавиатура

Все это, на данном этапе, решать не хотелось, поэтому был приобретен небольшой джойстик, который имеет 4 положения + 3 кнопки для дополнительного функционала (они пока не будут задействованы).

Джойстик
Рисунок 3. Четырехпозиционный джойстик.

Пульт и танк будут «общаться» постоянно. Поэтому в начале каждого цикла обоим элементам массива управления присваиваем значение 0. И начинаем отслеживать нажатые клавиши. Если нажато положение «вверх» – обоим элементам присваиваем значение 50 (движение вперед); «вниз» – 100 (движение назад); «влево» – элемент [0] = 0, [1] =  50; «вправо» – [0] = 50, [1] =  0. Далее отправляем все в радио модуль.

Пока, это основная логика для движения танка.

Схема пульта:

Принципиальная схема
Рисунок 4. Схема пульта.

Для того, чтобы не притягивать входы ардуино на землю – будем использовать режим входов INPUT_PULLUP. Поэтому выход «COM» клавиатуры соединен с землей (Будем отлавливать повышенное напряжение на входах).

Скетч для пульта:

#include <SPI.h>
#include <RF24.h>
#define LEFT_TRUCK 0
#define RIGHT_TRUCK 1

#define FORVARD 50
#define BACKWARD 100
#define STOP 0
RF24 radio(9, 10);
const uint32_t pipe = 111156789;

byte values[2];

void setup() {

  radio.begin();  
  radio.setChannel(0x6f); 
  radio.setDataRate (RF24_1MBPS);
  radio.setPALevel(RF24_PA_HIGH);
  radio.openWritingPipe(pipe); 

  pinMode(2, INPUT_PULLUP);
  pinMode(3, INPUT_PULLUP);
  pinMode(4, INPUT_PULLUP);
  pinMode(5, INPUT_PULLUP);

  values[LEFT_TRUCK] = STOP;
  values[RIGHT_TRUCK] = STOP;
}

void loop() {
  values[LEFT_TRUCK] = STOP;
  values[RIGHT_TRUCK] = STOP;
  if(!digitalRead(2)){
    values[LEFT_TRUCK] = FORVARD;
  }
  if(!digitalRead(3)){
    values[RIGHT_TRUCK] = FORVARD;
  }
  if(!digitalRead(4)){
    values[RIGHT_TRUCK] = BACKWARD;
    values[LEFT_TRUCK] = BACKWARD;
  }
  if(!digitalRead(5)){
    values[RIGHT_TRUCK] = FORVARD;
    values[LEFT_TRUCK] = FORVARD;
  }
  
  radio.write(&values, sizeof(values));

}
Прототип пульта
Рисунок 5. Пульт в сборе.

Для того, чтобы убедиться, что пульт формирует верные данные можно инициализировать Serial, и в конце каждого цикла вывести значения массива.

Сборка радиоуправляемого танка.

Платформа была куплена в сборе. Там уже был отсек для 4 батареек АА (пальчиковые), 2 мотора с редукторами и приводом на гусеницы. Так же для управления моторами необходим драйвер двигателя. Я заказал 2 драйвера: L9110 и DRV8833. Второго вполне достаточно для управления двигателями, но первый более легок в установке. Поэтому, изначально будем использовать L9110. Далее, как и в пульте, нам понадобится Arduino nano и радио модуль NRF24L01.

Первым делом на двигателях платформы были перепаяны тонкие провода на более толстые. Далее эти провода подключаем к драйверу двигателя, управляющие пины драйвера подключаем к ардуино.

Подключение драйвера к Arduino:

L9110Arduino
B-1AA0
B-2AA1
GNDGND
VCC5V (можно взять напрямую от батареек)
A-1AA2
A-2BA3

Подключение драйвера к моторам:

Левый мотор – MOTOR B (лево +, право -), Правый мотор – MOTOR A (лево +, право -). Подключаем радио модуль (так же, как и в пульте).

Принципиальная схема танка
Рисунок 6. Схема танка.

Скетч для танка:


#include <SPI.h>
#include <RF24.h>
#define LEFT_TRUCK 0
#define RIGHT_TRUCK 1

#define FORVARD 50
#define BACKWARD 100
#define STOP 0
const uint32_t pipe = 111156789;
RF24 radio(9, 10);
byte values[3];

void setup() {

  radio.begin(); 
  radio.setChannel(0x6f); 
  radio.setDataRate (RF24_1MBPS);
  radio.setPALevel(RF24_PA_HIGH);
  radio.openReadingPipe (1, pipe);
  radio.startListening();

  pinMode(A1, OUTPUT);
  pinMode(A0, OUTPUT);
  pinMode(A2, OUTPUT);
  pinMode(A3, OUTPUT);
  pinMode(2, OUTPUT);

  values[LEFT_TRUCK] = STOP;
  values[RIGHT_TRUCK] = STOP;
  digitalWrite(2, LOW);
}

void loop() {

  if(radio.available()){
    radio.read(&values, sizeof(values));
  }
  
  move();
  digitalWrite(2, values[2]);
}

void move(){

  if (values[LEFT_TRUCK] == FORVARD){
    digitalWrite(A1, HIGH);
    digitalWrite(A0, LOW);
  } else if (values[LEFT_TRUCK] == BACKWARD){
    digitalWrite(A1, LOW);
    digitalWrite(A0, HIGH);
  } else if (values[LEFT_TRUCK] == STOP){
    digitalWrite(A1, HIGH);
    digitalWrite(A0, HIGH);
  }

  if (values[RIGHT_TRUCK] == FORVARD){
    digitalWrite(A3, HIGH);
    digitalWrite(A2, LOW);
  } else if (values[RIGHT_TRUCK] == BACKWARD){
    digitalWrite(A3, LOW);
    digitalWrite(A2, HIGH);
  } else if (values[RIGHT_TRUCK] == STOP){
    digitalWrite(A3, HIGH);
    digitalWrite(A2, HIGH);
  }
  
}


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

Важное замечание.

После загрузки и сборки всего необходимого была замечена такая особенность (до того, как был напаян конденсатор): Когда я подключил танк к USB и включил питания от батареек, она вполне нормально принимала сигнал с пульта, но напряжения USB не хватало для работы (запуска двигателей). А при подключении от четырех батареек – индикация говорила о нормальной работе всех частей, но радио модуль не принимал ничего от пульта. И вот тут пришло время припаять конденсатор, о котором говорится во всех статьях об этом радио модуле. После припаивания конденсатора – все заработало.

Танк в сборе
Рисунок 7. Внешний вид танка(выключена).
Танк в сборе
Рисунок 7. Внешний вид танка(выключена).
Итоги.

Реализовав данный проект, я получил важный опыт, который пригодится в следующих проектах, где будут использоваться радио модули. На данном этапе танк выглядит не очень презентабельно, но я планирую все немного изменить. Поменять драйвер двигателя на DRV8833. Также есть идеи по добавлению функционала. Хочется добавить возможность включать фары спереди (возможно сзади), возможность выбора схемы поворота. Так же, хочу поставить fpv- систему. Но, эти изменения – тема для отдельной статьи.

Статьи по проекту

Радиоуправляемый танк. Часть 2 – Расширенный функционал

Радиоуправляемый танк. Часть 3 – FPV камера

4 комментария к “Радиоуправляемый танк. Часть 1 – Базовый функционал”

Оставьте комментарий