- PVSM.RU - https://www.pvsm.ru -
Иногда в интернете вижу вопросы от новичков, которые хотят с нуля построить квадрокоптер и написать к нему прошивку. Сам являюсь таким и чтобы попрактиковаться в создании RC моделей решил начать с чего-то более простого.
В статье в подробностях для самых маленьких описал алгоритм работы лодки, пульта управления и выбор компонентов.
Летающие аппараты — это здорово, но сложно. В воздухе нельзя так просто выключить винты, если что-то пойдёт не так. Да и удельная тяга нужна весьма приличная даже для самолётов не говоря уже про мультикоптеры.
Платформы по типу этой
(тут [1]есть более подробное описание).
умеют двигаться только по, в большинстве случаев, искусственной ровной поверхности, да и управление у них сильно отличается.
А вот на воде мы можем плыть куда угодно, что в дальнейшем может дать нам возможность сделать автопилот с использованием GPS. Классическая конструкция с гребным винтом для меня сложна узлом выхода вала из корпуса — не представляю как его загерметизировать.
Ещё преимущества воздушного движителя:
Надо чтобы аппарат мог поворачивать. Есть 3 варианта:
1 джойстик + несколько переключателей. Задача пульта — несколько раз в секунду посылать в эфир данные о положении ручки джойстика и переключателей.
Во-первых, нужен радиопередатчик. Самый дешёвый вариант — это NRF24L01+, стоит $0.85 [4]
Во-вторых, нужен джойстик. Ещё $1 [5].
Несколько переключателей — $0.12 [6].
Ну и всё это закрепить на куске текстолита за $0.13 [7].
Уже насчитали $2.1, а нужен ещё МК и питание. Тут всё не так однозначно.
Забегая вперёд, скажу, что вполне достаточно ATmega8 или STM8S103F3P6, но так как начинал этот проект я давно и опыта было мало, влепил в пульт управления Arduino Pro Mini, а в лодку Arduino Nano (везде ATmega32P).
В пульт ещё понадобились:
Всего плюс $0.53. Не считая контроллера, пары конденсаторов и проводов, стоимость компонентов пульта получается $2,63.
Тут всё идёт от двигателей. Какие двигатели купите, такой мощности электронику и придётся ставить, и база (судно, сани) потребуются соответствующей грузоподъёмности. Да и идеологически, всё остальное нужно лишь для того, чтобы вращать винты с нужной скоростью.
Я купил вот такие моторчики с пропеллерами
по $2.88 за пару [11].
В качестве драйвера моторов взял L293D — ещё $0.35 [12].
Питание. Нам потребуются аж три напряжения питания:
1 и 2 получим также как в пульте управления, а для моторчиков поставим MT3608 за $0.86 [13].
Теперь самое интересное: гироскоп. Модуль MPU-6050 стоит $1.53 [14]. Было желание использовать ещё и акселерометр, чтобы при движении ручки джойстика в сторону судно разворачивалось на месте. Но в итоге от этой идеи отказался: небольшой наклон по тангажу, и система начинает думать, что она ускоряется вперёд или назад. Проще оказалось разворачивать судно на месте просто компенсируя джойстиком движение вперёд/назад.
Добавим к этому $0.4 за батарейный отсек на 2 элемента AA и получим компонентов на $6.4 без контроллера и проводов.
И снова пойдём от двигателей. Каждый из двух двигателей управляемый L293D может копать, а может не копать:
Чтобы код легче читался, напишем
inline void motLeftStop(){
PORTD &= ~(1 << MOT_LEFT_PLUS);
PORTD &= ~(1 << MOT_LEFT_MINUS);
}
inline void motLeftForward(){
PORTD |= 1 << MOT_LEFT_PLUS;
PORTD &= ~(1 << MOT_LEFT_MINUS);
}
inline void motLeftBackward(){
PORTD &= ~(1 << MOT_LEFT_PLUS);
PORTD |= 1 << MOT_LEFT_MINUS;
}
inline void motRightStop(){
PORTD &= ~(1 << MOT_RIGHT_PLUS);
PORTD &= ~(1 << MOT_RIGHT_MINUS);
}
inline void motRightForward(){
PORTD |= 1 << MOT_RIGHT_PLUS;
PORTD &= ~(1 << MOT_RIGHT_MINUS);
}
inline void motRightBackward(){
PORTD &= ~(1 << MOT_RIGHT_PLUS);
PORTD |= 1 << MOT_RIGHT_MINUS;
}
Теперь мы хотим управлять скоростью вращения винтов. Конечно, делать это будем при помощи ШИМ. Не знаю, можно ли такую ШИМ сделать аппаратно… я сделал программно на прерываниях. Объявим пару глобальных переменных
int8_t motLeft = 0, motRight = 0; // -127..+127
Пусть значения этих переменных < 0 означают, что крутить надо назад, значения > 0 — вперёд, а если они равны 0, то крутить не надо.
ISR(TIMER2_OVF_vect)
{
if(motLeft > 0)
motLeftForward();
else if(motLeft < 0)
motLeftBackward();
if(motRight > 0)
motRightForward();
else if(motRight < 0)
motRightBackward();
}
ISR(TIMER2_COMPA_vect)
{
motLeftStop();
}
ISR(TIMER2_COMPB_vect)
{
motRightStop();
}
Теперь, чтобы изменить скорость вращения пропеллера, нам надо сделать 2 действия:
void setMotLeft(int8_t v){ // -127..+127
if(abs(v) < 5) v = 0;
motLeft = v;
OCR2A = abs(v) * 2;
}
void setMotRight(int8_t v){ // -127..+127
if(abs(v) < 5) v = 0;
motRight = v;
OCR2B = abs(v) * 2;
}
Строки
if(abs(v) < 5) v = 0;
нужны чтобы лодка не тратила энергию на попытку крутить винты записывая в OCR2x значение меньшее 5 (они при этом всё равно не крутятся).
void motInit(){
DDRD |= (1 << MOT_LEFT_PLUS) | (1 << MOT_LEFT_MINUS) | (1 << MOT_RIGHT_PLUS) | (1 << MOT_RIGHT_MINUS);
//TCCR2B |= (1 << CS22)|(1 << CS21)|(1 << CS20); // set up timer with prescaler = 1024. Переполнение каждые 16 мс
//TCCR2B |= (1 << CS22)|(0 << CS21)|(0 << CS20); // set up timer with prescaler = 64. Переполнение каждую 1 мс
TCCR2B |= (0 << CS22)|(1 << CS21)|(0 << CS20); // set up timer with prescaler = 8. Переполнение 128 мкс
//TCCR2B |= (0 << CS22)|(0 << CS21)|(1 << CS20); // set up timer with prescaler = 1. Переполнение 16 мкс
TIMSK2 |= (1 << TOIE2)|(1 << OCIE2A)|(1 << OCIE2B); // enable overflow interrupt
TCCR2A &= ~(3); // set WGM20 = 0, WGM21 = 0
TCCR2B &= ~(1 << 3); // set WGM22 = 0
setMotLeft(0);
setMotRight(0);
sei();
}
И можно управлять моторчикам просто вызывая функции setMotLeft(int8_t v) и setMotRight(int8_t v).
Но мы же хотим управлять лодкой не так! Мы хотим давать команды типа «вперёд/назад» и «вправо/влево»! И пусть она сама разбирается, какие пропеллеры ей для этого куда придётся крутить. Более того, хочется, чтобы лодка сама компенсировала поворачивающее действие ветра, течения и… криво поставленных пропеллеров!
Пойдём теперь с другой стороны. Со стороны ПДУ. В простейшем случае алгоритм его работы следующий:
Наш радиомодуль поддерживает пакеты до 32 байт. Чтобы не запоминать смещения, будем использовать запись
struct ControlStatus{
int16_t x,y;
} controlStatus;
uint8_t packet[MAX_BUFF];
memset(packet, 0, MAX_BUFF);
controlStatus.x = (int16_t)analogRead(1) - x0;
controlStatus.y = (int16_t)analogRead(0) - y0;
memcpy(packet, &controlStatus, sizeof(controlStatus));
Mirf.send(packet);
while(Mirf.isSending()){;};
На стороне приёмника объявим точно такую же запись и
while (Mirf.dataReady()) {
uint8_t data[MAX_BUFF];
Mirf.getData(data);
memcpy(&controlStatus, data, sizeof(controlStatus));
setMotRot(-controlStatus.x);
setMotForward(controlStatus.y);
}
В функциях setMotRot и setMotForward
void setMotRot(int16_t v){
if(abs(v)<10) v = 0;
motRot = (int32_t)v;
}
void setMotForward(int16_t v){
if(abs(v)<10) v = 0;
motForward = (int32_t)v;
}
И перейдём к самому интересному. К тому, как преобразовать «поворачивать налево со скоростью 5 градусов в секунду и чуть-чуть двигаться вперёд!» в «левый двигатель 10% назад, правый 20% вперёд!».
Про то, что такое ПИД регуляторы [15] написано достаточно много. Я использовал для вращения всего две составляющие:
А для движения вперёд-назад регулятор не стал использовать.
Разберём на примере:
int32_t iDeltaRot = 0;
void motTick(){
int32_t rot = getRotAvg(); // получаем реальную скорость вращения лодки
int32_t deltaRot = rot - motRot * rotMaxSpeed / 512;
iDeltaRot += deltaRot;
int32_t motRight = (int32_t)motForward * forwardMult - deltaRot * rotMult - iDeltaRot * iDeltaRotMult,
motLeft = (int32_t)motForward * forwardMult + deltaRot * rotMult + iDeltaRot * iDeltaRotMult;
int32_t motMax = max(abs(motRight), abs(motLeft));
if(motMax > 127){
motRight = (int32_t)motRight * 127 / motMax;
motLeft = (int32_t)motLeft * 127 / motMax;
}
setMotRight(motRight);
setMotLeft(motLeft);
}
Код упростил, чтобы сконцентрировать внимание на важных частях, в архиве будет полная версия.
Что же мы тут делаем?
Всё!
Это весь алгоритм управления лодкой!
Сложно? Мне кажется, нет. Но, тем не менее, в ходе испытаний и настроек возникала целая куча проблем, которая привела бы к многочисленным крушениям, если бы это был летательный аппарат.
В описанной функции есть 4 коэффициента:
Эти коэффициенты настраиваем экспериментально, и от них будет зависеть реакция лодки на джойстик и внешние разворачивающие воздействия.
При отладке/настройке будут возникать непонятки из серии «почему лодка реагирует на джойстик не так, как мне этого хочется?». Некоторые моменты можно отладить, выводя отладочную информацию на ПК, но было бы удобнее прямо на месте понимать, что происходит. Вначале я рассматривал 2 варианта:
Недостатки и того, и другого понятны: ноутбук большой и его неудобно с собой таскать, а дисплей Nokia 5110 не позволит наглядно отобразить одновременно большое количество параметров состояния лодки.
Я взял нечто среднее между ними: Nextion Enhanced NX4827K043 — Generic 4.3'' HMI Touch Display [16]. Благодаря сенсорному дисплею, можно прям на ходу быстро и удобно настраивать параметры лодки. Это своеобразный компьютер состоящий из:
Всё в сборе выглядит вот так (кликабельно):
[17]
Является этот компьютер/дисплей чёрным ящиком и заточен на взаимодействие с человеком. Даже имеющийся GPIO заточен для подключения кнопок и индикаторов. Их же Expansion Board [18] это подтверждает. Так что использовать встроенный контроллер в качестве пульта управления лодкой (считывать показания джойстика, обмениваться данными с радиомодулем NRF24L01+) не получится. Для взаимодействия с микроконтроллером есть UART и… и всё.
О том как и что можно делать при помощи этого дисплея можно делать написано куча + есть ролики на Youtube. Посмотрите, например, вот это [19] — там всё понятно показано. Но так как этот дисплей стоит дороже, чем все остальные компоненты лодки и пульта вместе взятые, опишу подробнее свои впечатления от работы с ним. Возможно, это кому-то поможет понять подходит ли ему этот вариант или ноутбук/дисплей Nokia 5110 будут предпочтительнее. Достоинства Nextion Enhanced NX4827K043:
Недостатки:
В целом, дисплей создаёт впечатление весьма качественного изделия, с которым легко и приятно работать.
Дисплей может выполнить сразу две задачи:
Сделал 2 странички (кликабельны для оценки качества):
Видео теста лодки на полу:
Реакция лодки на внешнее разворачивающее воздействие при различных iDeltaRotMult (интегральных коэффициентах):
Демонстрация влияния параметров на воде:
Видео на открытой воде заснять не удалось. Можете принять на веру, что управляемость у него хорошая, а максимальная скорость не очень.
Тем, у кого есть желание собрать что-то радиоуправляемое, рекомендую начать с судна с двумя фиксированными воздушными винтами. На мой взгляд, это самое простое, что можно сделать в этой области.
Архив с проектами [24]
Ну и напоследок, чтобы было к чему стремиться, вот видео удивительного аппарата:
Автор: xedas
Источник [25]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/diy/185790
Ссылки в тексте:
[1] тут : http://informatik-m.ru/mir_robototehniki/kak-sdelat-mini-robota-svoimi-rukami.html
[2] Один винт + руль для поворотов: https://www.youtube.com/watch?v=b3DOPYeYqZY
[3] Один винт + система его поворачивающая: https://www.youtube.com/watch?v=8LyCP_28QAg
[4] $0.85: http://www.ebay.com/itm/2PCS-Hot-Sell-NRF24L01-2-4GHz-Antenna-Wireless-Transceiver-Module-for-Arduino-/221746847061
[5] $1: http://www.ebay.com/itm/Hot-Sale-JoyStick-Breakout-Module-Shield-PS2-Joystick-Game-Controller-Arduino-/201416176593
[6] $0.12: http://www.ebay.com/itm/10Pcs-Slide-Type-Switch-Module-2-54mm-4-Bit-4-Position-Way-DIP-Red-Pitch-FKS-/321897494822
[7] $0.13: http://www.ebay.com/itm/10Pcs-5-x-7-cm-DIY-Prototype-Paper-PCB-fr4-Universal-Board-prototyping-pcb-kit-/181846671646
[8] $0.35: http://www.ebay.com/itm/5PCS-0-9V-5V-to-5V-DC-DC-Booster-USB-Mobile-Step-up-Power-Supply-Module-/181916952600
[9] $0.03 в пересчёте на штуку: http://www.ebay.com/itm/100PCS-AMS1117-3-3-LM1117-1A-3-3V-SOT-223-Voltage-Regulator-/181930531943
[10] $0.15: http://www.ebay.com/itm/10Pcs-1-5V-Plastic-Hard-Storage-Holder-Case-Box-For-1-AA-Battery-With-Wire-Leads-/262239973732
[11] $2.88 за пару: http://www.ebay.com/itm/2PCS-DC-3-7V-22000RPM-Coreless-Motor-Propeller-for-RC-Aircraft-Helicopter-Toy-/381374910740
[12] $0.35: http://www.ebay.com/itm/5PCS-Push-Pull-Four-Channel-Motor-Driver-IC-ST-DIP-16-L293D-/272041696769
[13] $0.86: http://www.ebay.com/itm/MT3608-DC-DC-Step-Up-Power-Apply-Module-Booster-Power-Module-for-Arduino-WF-R4-/141881461656
[14] стоит $1.53: http://www.ebay.com/itm/MPU-6050-3-Axis-Gyroscope-Acce-lerometer-Module-3V-5V-Compatible-Arduino-/181922780294
[15] ПИД регуляторы: https://ru.wikipedia.org/wiki/%D0%9F%D0%98%D0%94-%D1%80%D0%B5%D0%B3%D1%83%D0%BB%D1%8F%D1%82%D0%BE%D1%80
[16] Nextion Enhanced NX4827K043 — Generic 4.3'' HMI Touch Display: https://www.itead.cc/nextion-nx4827k043.html
[17] Image: https://habrastorage.org/files/423/e3a/006/423e3a006a824678ade4d5a5ad52c99d.JPG
[18] Expansion Board: https://www.itead.cc/nextion-expansion-board.html
[19] вот это: https://www.youtube.com/watch?v=D-zgtylBKUc
[20] вики страничка: https://www.itead.cc/wiki/NX4827K043
[21] Instruction Set: https://www.itead.cc/wiki/Nextion_Instruction_Set
[22] Image: https://habrastorage.org/files/410/664/348/41066434884347ac96f56f486ea6b597.JPG
[23] Image: https://habrastorage.org/files/1c6/46b/725/1c646b72566e431ab7b4b0e98a2302b5.JPG
[24] Архив с проектами: https://dl.dropboxusercontent.com/u/46112531/DIY/toHabr/rcboat.zip
[25] Источник: https://geektimes.ru/post/271066/
Нажмите здесь для печати.