Радиоуправляемая тележка или танк на arduino nano
- Войдите на сайт для отправки комментариев
Открою новую тему.
Тележка о четырёх колёсах с алиэкспреса, бралась как конструктор, была собрана и ездила по комнате в автоматическом режиме, захотелось, чтобы внучки порулили )))
Аппаратрура радиоуправления FlySky FS-GT3C c приёмником FS-GR3E но возможна любая с числом каналов два и более.
Скетч, буквально набросок выполненный за вечер, будет дальнейшее расширение возможностей, остален ультразвуковой датчик и попытка научить объезжать препятствия подруливая в автоматическом режиме )))
Не проверялся в железе, в мониторе порта всё изумительно (после небольшого триммирования руля), пока реализовано движение только прямо, реверс будет попозжее.
Критика для улучшения приветствуется!!!
volatile unsigned int rc1_data = 1500; volatile unsigned int rc2_data = 1500; volatile unsigned int rc3_data = 1500; volatile unsigned long start_timeRC1 = 0; volatile unsigned long start_timeRC2 = 0; volatile byte flag_RC1 = 0; volatile byte flag_RC2 = 0; /***LM398***/ const int in1 = 4; // direction pin 1 const int in2 = 7; // direction pin 2 const int ena = 5; // PWM pin to change speed const int in3 = 8; // direction pin 1 const int in4 = 12; // direction pin 2 const int enb = 6; // PWM pin to change speed int fspeed; // forward speed int lr; // положение руля void setup() { Serial.begin(115200); pinMode(in1, OUTPUT); // connection to L298n pinMode(in2, OUTPUT); // connection to L298n pinMode(ena, OUTPUT); // connection to L298n pinMode(in3, OUTPUT); // connection to L298n pinMode(in4, OUTPUT); // connection to L298n pinMode(enb, OUTPUT); // connection to L298n analogWrite(ena, 0); analogWrite(enb, 0); // Привязываем к Pin2 прерывание по фронту сигнала attachInterrupt(0, Rc1, CHANGE); // Привязываем к Pin3 прерывание по фронту сигнала attachInterrupt(1, Rc2, CHANGE); } void loop() { // Serial.println(rc1_data); lr = map(rc1_data,1000,2000, -20,20); // Serial.println(rc2_data); if(rc2_data >=1520){ fspeed=map(rc2_data,1520,2000,20,230); digitalWrite(in1, LOW); digitalWrite(in2, HIGH); analogWrite(ena, fspeed+lr); digitalWrite(in3, LOW); digitalWrite(in4, HIGH); analogWrite(enb, fspeed-lr); Serial.println(fspeed+lr); Serial.println(fspeed-lr); } } /******Обработчик прерывания на возрастание сигнала ******/ void Rc1() { if(digitalRead(2) == HIGH && flag_RC1==0){ //сохраняем значение времени начала импульса start_timeRC1 = micros(); flag_RC1=1; } if(digitalRead(2) == LOW && flag_RC1==1){ //сохраняем значение длительности импульса rc1_data = micros() - start_timeRC1; flag_RC1=0; }} void Rc2() { if(digitalRead(3) == HIGH && flag_RC2==0){ //сохраняем значение времени начала импульса start_timeRC2 = micros(); flag_RC2=1; } if(digitalRead(3) == LOW && flag_RC2==1){ //сохраняем значение длительности импульса rc2_data = micros() - start_timeRC2; flag_RC2=0; }}
Попробовать на тележке не удалось, после длительного простоя, попытка зарядить аккумуляторы (использую банки от ноутбука ) модуль зарядки пустил дым, вот и первые потери в ардуиностроении ...
Дело было вечером делать было нечего - добавил реверс, осталось понять, будет ли "сквозняк" на мостах )))
Не было проблем и снова здорово. Если вы собираетесь делать большой проект, то начинайте учится структурировать код а не программировать "росыпью". http://arduino.ru/reference/functiondeclaration
Не было проблем и снова здорово. Если вы собираетесь делать большой проект, то начинайте учится структурировать код а не программировать "росыпью". http://arduino.ru/reference/functiondeclaration
большой точно не нужен, прикручу ультразвуковой датчик и как бы всё...можно конечно чтобы пела плясала и огоньками мигала, но пока это даже не планировалось, идея приучить внучек к пультам управления )))
С линейного кода (программирования в лоб) конечно надо бы перейти к функциям
поправил скетч, как-то заёрзала тележка, но очень плохо управляется, особенно при движении вперёд )))
А в чём проявляется проблема? Как едет без управления? Ровно?
Едет ровно! Нормальное движение при ШИМ от 75% ручки газа, АРХАТ говорит, что для танкового управления регулировка на ШИМ должна быть квадратичной, а для большей резвости даже кубической, Ваш ТАНК у внука как себя ведёт при поворотах?
Нормально, но у нас по жизни квадратичное управление, просто в силу теоремы Пифагора, мы для этого никаких усилий не прикладываем.
Нормально, но у нас по жизни квадратичное управление, просто в силу теоремы Пифагора, мы для этого никаких усилий не прикладываем.
Для квадратичной мысль математика требуется, чтобы смиксировать сигналы должным образом и уложить в граничные значения шим, то-есть, есть скрость выставляем максимальную, ШИМ должен принимать максимальное значение
Для квадратичной мысль математика требуется
Всё намного проще.
Вот тут недавно Ворота пульсметр показывал. У него там совсем снимается сигнал с АЦП, а потом совсем нетривиально программно интегрируется не уходя от целых числе. для этого ему ажно int64_t потребовался. Хотя простенькая интегрирующая цепочка из резистора и конденсатора дала бы этот результат уже готовым с того же АЦП и считать не надо вообще ничего.
Так и здесь.
У нас стоит джйстик и мы подаём ШИМ пропорционально размерам катета ттреугольника, который образует ручка джойстика с ветрикальным направлением. Даже это объяснение черечур словжное - настоьлькот там всё тривиально. В итога изменения именно квадратичные, т.к. зависимость размеров катетов квадратичная по теореме Пифагора. Если всё ещё непонятно, , я могу разрисовать картинку джойстика и что именно мы подаём.
имею, по одному каналу принимаю уровень педали газа -1000 -1500 -2000 мксек
по второму каналу уровень с руля 1000 -1500 -2000 мксек, 1500 и руль и педаль газа - нулевое положение
вот эти два сигнала и надо смиксировать чудным образом, преобразовав в два канала ШИМ, левого и правого бортов.
Простым способом не получается, да если бы было возможно к танкам давно бы руль приделали, ан нет )))
Доопределите, чего не хватает и подбирайте масштаб рулевого управления в map() так, чтобы скорость могла меняться
Не оптимально, ибо переключалки задействованы при каждом управлении, но тут оно как раз "без разницы" и даже повышает надежность ПО.
Мысль понятна, попробую
Получилось так, работает неправильно при старте назад едет прямо, вперёд - крутится только одна сторона
if от else отделите. Накидал как идею, надеялся справитесь самостоятельно. Там ещё надо грамотно типизацию целых расставить, дабы лишнее в лонгах не гонять и на расширение до целого не нарваться. :)
Я бы ваще всё в байтовых переменных сделал. Изменение ШИМ на 1..2 практически не сказываются даже на легких тележках со скоростями под 5м/сек. Стало быть ШИМ можно считать в диапазоне -127 .. 127 и тупо домножать на 2, сдвигом при подаче на analogWrite() .. :)
отрабатывает следующим образом:
ручка газа вперёд, крутится правая сторона, поворачиваем руль вправо, в какой-то момент колёса правой стороны останавливаются и начинают крутиться назад, руль влево, то-же самое, в какой то момент поворота руля колёса правой стороныостанавливаюся и начинают крутится назад ))) левая сторона не дышит
ручка газа назад, крутятся левая и правая стороны ровно, при движении руля хоть вправо хоть влево левая сторона останавливается правая начинает крутиться в два раза быстрее
)))
Да, зачем Вам руль? Сделайте джойстик, как у нас и проблемы вообще не будет от слова совсем.
Да, зачем Вам руль? Сделайте джойстик, как у нас и проблемы вообще не будет от слова совсем.
у меня джойстик тоже выдает стандартизованные сигналы 1000 - 2000 )))
Блин, Вы его не так используете. Ладно, чейчас мне надо убегать, завтра нарисую как его надо ставить и как интерпретировать сигналы.
Блин, Вы его не так используете. Ладно, чейчас мне надо убегать, завтра нарисую как его надо ставить и как интерпретировать сигналы.
я прикручиваю к стандартному комплекту радиоуправления, а там никакой самодеятельности )))
Где-то, что-то напутано.
Закомментируйте if-else блоки непосредственного управления моторами и раскоментируйте вывод в Сериал, только сделайте подписи параметров, хотя бы так:
Serial.print(", spA="); Serial.print(speedA, DEC);
Перевод строки стараюсь ставить 1 раз в начале loop(), так видней что творится на одном проходе loop().
Посмотрите, что у вас получается в управляющих сигналах по результату приема в прерываниях, посмотрите что получается в качестве скоростей speedA,B ..
Скорее всего при квадратичной функции lr*lr у Вас слишком велико управление, но почему только на 1 мотор? В целом ШИМ в пределах 512 (от -255 до 255), соответственно квадрат рулевого должен попадать в эти пределы и макс рулевого маппинга нормально должен быть как SQRT(255) = 16, то есть подбор надо начинать примерно с такого:
map(rul, 1000, 2000, -16, 16)
и там вряд ли будет большое изменение .. 1,2 вряд ли больше 3,4. :)
Где-то, что-то напутано.
по левому борту нашёл, строка 131, поправил
направление поиска понятно, вечером поищу
Тогда проверьте и все остальные пины в блоках элементарного управления. Такие ошибки не ходят по одиночке. :) О результате отпишитесь - уже интересно что получится.
Тогда проверьте и все остальные пины в блоках элементарного управления. Такие ошибки не ходят по одиночке. :) О результате отпишитесь - уже интересно что получится.
понятно, строки 74 и 75 при умножении на самое себя теряем знак, а он важен
lr*lr*sign(lr) домножить на знак, стало быть.
или так: fspeed + (lr*lr*(lr>=0? 1: -1)) :)
lr*lr*sign(lr) домножить на знак, стало быть.
или так: fspeed + (lr*lr*(lr>=0? 1: -1)) :)
так как языками не владею, хотел сделать как во второй строке только через if )))
Поправил, вечером попробую
немного изменил, чтобы при педали газа в нейтральном положении не ездила при вращении руля
Немно поразмыслив добавил еще пару строк, как по мне получилась неплохая основа для скетча вездехода, что имеем - при движения прямо или назад "программная блокировка дифференциала всех ведущих колёс", поворотом руля влево или вправо можно добиться передачи усилия на пару из левых или правых колёс...
Машинка на аккумуляторах литий-ион бегает очень резво )))
Здорово.
Но .. Вы так устранили чисто "танковый разворот" одной педалью руля, без газа.. может здря строки 75,76 и 79? :)
Здорово.
Но .. Вы так устранили чисто "танковый разворот" одной педалью руля, без газа.. может здря строки 75,76 и 79? :)
я не специалист в танковых разворотах )))
Скетч выше как раз с этой возможностью, бери - не хочу, а то на просторах интернета не смог найти аналогичный проект...
Теперь надо прикручивать ультразвуковой датчик, для автоматического объезда препятствий на трассе )))
Баловства ради добавлю скетч переделанный под библиотеку PWM.hpp, точность библиотеки конечно ни о чём, зато позволяет обрабатывать до 20 каналов )))
Да ну что тут такого-то .. главное что оно ездит у Вас, то бишь доведено до ума. Дитенок - доволен?
А то вот дорисовал мотор-редуктор на базе 4-х ступенчатого редуктора, т.с. "универсальный" с к-том передачи от 27.5 до 165 со "сменными шестеренками" .. и? Начал ваять "пробную версию" и столкнулся с проблемами: требуется точность изготовления менее 0.1мм, корпус имеет зазоры 0.3-0.5мм до шестеренок, толщина стенок 1мм - это ещё вольготно .. да, все это под "лего формат" редуктор со встроенным энкодером, типа EV3 "большой мотор", только в размере "средний мотор" .. сижу ломаю голову: КАК это воплотить в натуре в количестве хотя бы 4шт?
3Д принтер - не потянет, лазерная резка - как показал жопыт, аналогично .. а хочется. ;) Я понимаю, что китаезы способны сделать форму и наштамповать корпусов к этому чуду .. тока "цена вопроса" за 4-8шт ..
Ладно, это я так .. завидую..
Да ну что тут такого-то .. главное что оно ездит у Вас, то бишь доведено до ума. Дитенок - доволен?
Еще не доделал, сенсор надо сделать и окультурить, чуть попозжее, пока есть возможность и с другими бублиотеками поэкспериментировать
Да, у тележки база коротковата, надо за основу брать пропорции Вазовской НИВА 4х4
Подправил немного константы так как подключил аппаратуту FUTABA и добивался минимальных значений для триммирования (получилось уложиться в 5 единиц)
Всё управление на одном стике
Как вам квадратичное управление поворотом на "ручке управления", особенно на скоростях? Ощущается как верное или нет? Интересно..
Как вам квадратичное управление поворотом на "ручке управления", особенно на скоростях? Ощущается как верное или нет? Интересно..
Хотел даже ролик снять, крутиться можно очень неплохо
Пасибки. Просто именно квадратичное управление оно больше для "скоростных" тележек, где центробежная сила достаточна для нагрузки внешнего колеса. Но ваш "танк", вполне может создавать аналогичную проблему в более широком диапазоне скоростей. Поэтому и было интересно "полезно ли".
P.S. отсюда следствие (можно улучшить поведение): предпочтительней разгонять внешнее колесо чем тормозить внутренее. Можно сделать неравновесное управление внешним и внутренним колесом домножая квадрат управляющей величины lr на разные к-ты в зависимости от того цнутренне колесо или внешнее (больше/меньше нуля величина управления) .. попробуйте.
думал об этом, точнее концептуально иметь от одного стика - скорость и при этом при повороте другим стиком, чтобы было и агрессивно и средняя скорость не изменялась, то, что пробую - падает число градаций скорости, а не хотелось бы
Ну .. всегда приходится выбирать что-то одно (или трусы или крестик). В этом и состоит работа конструктора изделия. :) а так - да, улучшая динамику поворотов без снижения скорости вынужденно снижаем среднюю скорость движения по прямой и уменьшаем диапазон скоростей. Поэтому и писал и говорил всем страждущим на соревнованиях: хотите иметь агрессивную динамику в поворотах и неплохую скорость на прямой .. выводите макс. движение по прямой (ШИМ 255) на 5м/сек, тогда можно ехать 2.5-3 метра по прямой на трассе и оч. хорошо вилять в поворотах и давить колебания тележки а-ля ПИДом. Запас. Но .. тут он как раз "тянет карман"..
Да ну что тут такого-то . .. сижу ломаю голову: КАК это воплотить в натуре в количестве хотя бы 4шт?
3Д принтер - не потянет, л ..
Ладно, это я так .. завидую..
Я себе для решения таких задач фотополимерник Photon Any Cubic купил, работает из коробки с одной настройкой - высотой.
Хотел даже ролик снять, крутиться можно очень неплохо
у меня дети в кружке сделали на линейной, тут вариант на BT, но есть такой же на FlySky 3- канальной (скорость, угол, свет), если интересно код могу выложить, или можно скачать с hackaday.
https://youtu.be/jDATptM75Ew
Хотел даже ролик снять, крутиться можно очень неплохо
у меня дети в кружке сделали на линейной, тут вариант на BT, но есть такой же на FlySky 3- канальной (скорость, угол, свет), если интересно код могу выложить, или можно скачать с hackaday.
https://youtu.be/jDATptM75Ew
я бы посмотрел, интересно как реализовали обработку приёмника
Код обработки приемника - пины А0-А2 задействованы для входов с приемника, для них прерывания включены, в setup
а сам обработчик прерывания- включается при change, когда соотв. пин ввер- записывает таймер micros() в переменную, когда пин вниз- считает длину импульса, ну и дуракозащита некая, часть в обработчике (что вобщем неправильно - должно быть минимально), часть в основном коде. Кто вверх - кто вниз вычисляем исходя из предыдущего состояния пинов. Поскольку обработчик должен действовать по принципу "ударил - убежал", то напрямую юзаем регистры вместо медленных (4-7 мкс) digitalRead, ну может пропустили где. Дискретностью micros() (4 мкс) пренебрегаем, все равно это меньше шим шума нашего комплекта (до 12 доходит). ModeLight управляется переключателем пульта, вкл/выкл, а Speed и Turn - курок и крутилка соотв. RC FlySky 3 канала автомобильный.
Понятно!!!
А вместо micros() 16 битный счетчик не пробовали использовать?
Кстати у меня аналогичная аппаратура есть, так сильно не моросит, максимум 1 микросекунда
Пока задача столь высокой точности не стоит - используются analogWrite(), а они все равно 8 бит, а обратная связь только по азимуту, по скорости не контролируем. Была задача постоянной скорости, там по энкодерам считали.
Я дико ивиняюсь, взял за основу это , немного допилил под себя. при выключении пульта или приемника, если машина управлялась с пульта, то она продолжает ехать с той скоростью с которой ехала.
Вопрос: что дописать чтобы при потере связи всё остоновилось? Это машинка в которой ездит ребенок.
выставить на аппаратуре файлсэйв по газу на 1500 и включить его, тогда при потере связи с пультом машинка остановится
Тогда сохранится локальное управление. А нужно чтобы при отсутствии связи с пультом все останавливалось.
Заведите счетчик, например NoSignalCounter , в прерываниях его обнуляйте, а в loop напишите
if(NoSignalCounter++> CriticalNumber)
Stop=1;
else
Stop=0;
и введите во все if, в которых задается скорость, условие Stop==0
Заведите счетчик, например NoSignalCounter , в прерываниях его обнуляйте, а в loop напишите
if(NoSignalCounter++> CriticalNumber)
Stop=1;
else
Stop=0;
и введите во все if, в которых задается скорость, условие Stop==0
при обрыве связи, если не выставлен файлсэйв приёмник гонит последнее принятое значение
Все верно, но так я и предлагаю выдавать нуль на пины силового H-моста после CriticalNumber прокруток loop() если не было ни одного прерывания. Когда срабатывают прерывания, то у нас выставляется NoSignalCounter=0; , а в каждой прокрутке loop() выполняется NoSignalCounter++. Как только петля прокрутилась большее чем надо раз - выставляем флаг Stop=0.
можно еще подключить 3-й канал и на нём выставить файлсейв, по третьему каналу при файлсэйве выставите 0, этим нулём и тушите моторы, то-есть при обрыве связи приёмник выставит вам на канале 0, третий канал можно подцепить на PCINT
Пока вышел из положения установив фейлчэйв в максимальное значение движения назад и сместил расходы педали газа. Все что больше полный стоп.
Пока вышел из положения установив фейлчэйв в максимальное значение движения назад и сместил расходы педали газа. Все что больше полный стоп.
вот, код оказался полезен не только для игрушки )))
вернулся снова к теме, зима, а не попробовать ли принять каналы по SBUS? Кое-какие намётки кода уже есть, реализацию опубликую.
Это даст нам 8 каналов высокой точности )))
Подписался