Управление двумя двигателями по радиомодулю

photomuza
Offline
Зарегистрирован: 16.09.2021

ЖЕЛЕЗО:
- Ардуино НАНО 2 шт.
- Радиомодуль NRF24L01 2 шт. (с адаптером питания 3.3В)
- Драйвер двигателя L298N (мини) 1 шт.
- Аналоговый джойстик 2 шт.
- Коллекторный двигатель 2 шт.
Всё соединяется без проблем.
ТЗ
Нужно два скетча TX/RX. Модель автомобиля с воздушными винтами.
АЛГОРИТМ
1. Оба джойстика в нейтральном положении - двигатели не работают.
2. При отклонении джойстика-1 от среднего положения вперед скорость обоих двигателей плавно нарастает (FORWARD).
3. При отклонении джойстика-1 от среднего положения назад скорость обоих двигателей плавно растет обратно (BACKWARD).
4. При смещении джойстика-2 осуществляется поворот: отклонение джойстика-2 от нейтрального меняет соотношение скоростей обоих двигателей. Алгоритм такой: с отклонением джойстика-2 от нейтрального до 100% (вправо или влево) уменьшается влияние джойстика-1 на свой двигатель - от 100% до 0%. Т.е. при джойстике-2 100% или (-100%) работает только один двигатель на максимум, независимо от джойстика-1 (его влияние 0%).
Этот алгоритм и для FORWARD и для BACKWARD.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

комплект аппаратуры будет стоить дешевле, однозначно, скетч для управления авто можно взять тут

photomuza
Offline
Зарегистрирован: 16.09.2021

Согласен, на фрилансе в 5000 р оценили. Пробую пока сам. Ну, тут нет хорошего структурированного архива скетчей, у Гайвера на сайте в разы грамотней и полезней да и форум тоже есть с проектами. Рыскал, не нашел пока, хотя казалось бы, простая вещь.

rkit
Offline
Зарегистрирован: 23.11.2016

photomuza пишет:

хотя казалось бы, простая вещь.

В том и дело

man9913
Offline
Зарегистрирован: 19.03.2016

простая, не простая, но иметь железки и макет собирать всё равно надо. поэтому предлагаю свои услуги за 2к. man9913@mail.ru

rkit
Offline
Зарегистрирован: 23.11.2016

Хорошо, когда не надо строить дом и кормить семью.

photomuza
Offline
Зарегистрирован: 16.09.2021

man9913 пишет:

простая, не простая, но иметь железки и макет собирать всё равно надо.

С этим проблем нет, написал в начале. А вот с кодингом дело хуже обстоит. Спасибо за ответ, это более привлекательное предложение.

Пока запускаю без радиомодуля, по скетчу из гайверского архива. Вот рабочий вариант (стандартный: каждый стик на каждый мотор) без радиомодуля с добавкой разгона ШИМа (моторы пищали) и плавностью изменения скорости.

/*
  Пример управления двумя моторами
*/
#include "GyverMotor.h"
GMotor motor1(DRIVER2WIRE, 2, 3, HIGH);
GMotor motor2(DRIVER2WIRE, 4, 5, HIGH); // поменял 11-й на 5-й (ради эксперимента, т.к. 11-й занят радиомодулем)
// используем оба ШИМа таймера 2 (пины 3 и 11)

void setup() {

  // разгоняем ШИМ на пинах 3 и 11 (atmega328) до 31 кГц
  TCCR2B = 0b00000001;  // x1
  TCCR2A = 0b00000001;  // phase correct

  // Пины D5 и D6 - 31.4 кГц
TCCR0B = 0b00000001;  // x1
TCCR0A = 0b00000001;  // phase correct

  // минимальный сигнал (по модулю), который будет подан на мотор
  // Избавляет от ситуаций, когда мотор покоится и "пищит"
  //////////////////////////////// не заладилось: самопроизвольное вращение, нет нормального управления
//  motor1.setMinDuty(150);
//  motor2.setMinDuty(150);
 
  // установка скорости изменения скорости (ускорения) мотора (плавность)
  motor1.setSmoothSpeed(120);
  motor2.setSmoothSpeed(120);

 
  // ключ на старт!
  motor1.setMode(FORWARD);
  motor2.setMode(FORWARD);
}

void loop() {
  // потенциометр на А0
  // преобразуем значение в -255.. 255
  int val_1 = 255 - analogRead(0) / 2;

  // потенциометр на А1
  // преобразуем значение в -255.. 255
  int val_2 = 255 - analogRead(1) / 2;

  motor1.setSpeed(val_1);
  motor2.setSpeed(val_2);
  // в данном случае мотор будет остановлен в среднем положении рукоятки
  // и разгоняться в противоположные скорости в крайних её положениях
 
  delay(10);  // задержка просто для "стабильности"
}

Теперь надо искать-думать над логикой. 1. Управление обоих мотором одним стиком. 2. Задействование второго стика как регулятора % между двумя моторами. Надеюсь, ссылка выше от ua6em мне поможет. Или закажу man9913-у, все же время не резиновое.

lilik
Offline
Зарегистрирован: 19.10.2017

photomuza пишет:

Теперь надо искать-думать над логикой. 1. Управление обоих мотором одним стиком. 2. Задействование второго стика как регулятора % между двумя моторами. Надеюсь, ссылка выше от ua6em мне поможет. Или закажу man9913-у, все же время не резиновое.

:-)

Лучше закажите сразу за 2 штуки три логики работы: одним джойстиком управлять, двумя - независимо каждым мотором и вашу.

photomuza
Offline
Зарегистрирован: 16.09.2021

Пожалуй, так и сделаю. О man9913 есть полож. отзывы.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

lilik пишет:

photomuza пишет:

Теперь надо искать-думать над логикой. 1. Управление обоих мотором одним стиком. 2. Задействование второго стика как регулятора % между двумя моторами. Надеюсь, ссылка выше от ua6em мне поможет. Или закажу man9913-у, все же время не резиновое.

:-)

Лучше закажите сразу за 2 штуки три логики работы: одним джойстиком управлять, двумя - независимо каждым мотором и вашу.

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

Рабочий код приёмника и передатчика могу скинуть за скромную бутылку коньяку )))

PS после аппаратуры управления (их у меня несколько начиная с Футабы) - два шага назад )))
PPS сдаётся мне, что надо как на корабликах делать раздрай - их есть у меня тоже

 

photomuza
Offline
Зарегистрирован: 16.09.2021

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

lilik
Offline
Зарегистрирован: 19.10.2017

ua6em пишет:

... все проблемы ожидают с радиоканалом недаром местные старшие их мешками на помойку вынесли и взяли другие девайсы на этот диапазон...

PS после аппаратуры управления (их у меня несколько начиная с Футабы) - два шага назад )))

Ну я вообще поклонник блютуз. Управляем с ПК, телефона и "железным" пультом. По моему мнению он явно должен быть одноруким :-)

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

photomuza пишет:

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

вы большой оптимист если думаете одолеть авто на винтах без мучений, 100500 аналогичной конструкции здесь никто не делал, написать рабочий код - да, но довести до хотелок - отнюдь, на отладку раздрая  у меня ушло полгода )))

PS для соревнований

photomuza
Offline
Зарегистрирован: 16.09.2021

Да? А в чем проблема-то? В весе? У меня легкая конструкция. Ну, как запасной вариант - лодка.

Voodoo Doll
Voodoo Doll аватар
Offline
Зарегистрирован: 18.09.2016

1. Гувер делал проект с радиоуправляемой машиной, плохо ищете.

2. Трансиверы nRF24L01+ и голубой зуб работают в диапазоне 2.4 ГГц. Этот диапазон очень сильно засран бытовым вайфаем, условия приёма будут тяжёлыми. Не рассчитывайте что посылки будут доходить целыми в реальном времени. Я подобное управление делаю на кнопках, которые передают абсолютное состояние, как в кондиционерах.

3. Вы на форуме, который слегка модерируется. Одним человеком или двумя, если мне не изменяет память. На этом форуме пять разделов, в трёх из которых - 950 страниц, на каждой из которых по 25 тем. Вас удивляет что возникла помойка, которую невозможно разобрать? У меня есть граббер, который умеет сосать списки тем, размечая в диалект xml, и сами темы в виде обычного html как есть. Могу дать, выкачаете и может что найдёте. Системные требования - php 5.2, js 1.1 (на стабильной сборке денвера прошлого поколения пашет, во всяком случае).

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Voodoo Doll пишет:

1. Гувер делал проект с радиоуправляемой машиной, плохо ищете.

смотрел я его проект, он как обычно на предупреждения компилятора, о чём не раз тут вещал Евгений Петрович - забил, а напрасно )))

Поделись грабером

PS против Гайвера ничего не имею, даже больше, нравится его подача материала )))

rst
Offline
Зарегистрирован: 25.06.2018

Такие nRF24L01+, как на картинке вверху, ещё более-менее нормально работают в пределах квартиры (на 250кб/с) с редкими потерями кадров. Но если планируете использовать на бОльшие расстояния, то думаю нужно что-то другое.

Можно попробовать похожие модули nRF24L01+, но с дополнительным чипом-усилителем ВЧ и внешней антенной. Типа таких (1-й вариант): https://aliexpress.ru/item/32517849393.html

Я себе один такой купил "на попробовать", но пока руки не дошли.

SAB
Offline
Зарегистрирован: 27.12.2016

Если хотите надежности, тогда Zigbee с технологией мэш https://aliexpress.ru/item/1005003302284233.html

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

SAB пишет:

Если хотите надежности, тогда Zigbee с технологией мэш https://aliexpress.ru/item/1005003302284233.html

А у него чего сеть из пультов !? :)

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

brokly пишет:

SAB пишет:

Если хотите надежности, тогда Zigbee с технологией мэш https://aliexpress.ru/item/1005003302284233.html

А у него чего сеть из пультов !? :)

нет, из наземных станций )))

Voodoo Doll
Voodoo Doll аватар
Offline
Зарегистрирован: 18.09.2016

ua6em

1. Нужны списки тем в таком формате:

<script type=text/javascript src="utils/grabcall.js"></script>
<entry><href>/forum/obshchii/pomogite-novichku-7</href><hdr>помогите новичку</hdr></entry>
<entry><href>/forum/obshchii/atmel-studio</href><hdr>Атмел Студио</hdr></entry>
<entry><href>/forum/proekty/transistor-tester-arduino</href><hdr>transistor tester</hdr><qty>16</qty></entry>

в файлах .html, чтобы их можно было открывать на localhost в обозревателе. Тег <entry> невидимый, мешаться не будет.

Рядом (там где хтмл файлы) создать каталоги utils, data, в utils положить файлы grabcall.js и grabproc.php

Если каталог data не существует то работать не захочет (не умеет создавать этот каталог). Файлы будут называться testNN.htl, где test - имя файла со списком (оно берётся из адресной строки). Эти файлы это обычный хмл, их можно переименовать в html и читать, но поудобнее будет если маленько причесать и раскрасить. Нечётные посты имеют другой класс, чтобы можно было чередовать цвет, так читать удобнее.

var grablist=[];
var i_grab=0;
var grab_process=false;
var grabber=new XMLHttpRequest();
var grab_restrict_retry=false;
var grab_restrict_timer=undefined;
var gpos=undefined;
var data=undefined;

function grab(){
  if(i_grab==grablist.length) return;
  if(grab_restrict_retry) return;
  if(!grab_process){
    grab_process=true;
    i_grab++;
    gpos.innerHTML=i_grab+"/"+grablist.length;
    grab_exec();
    grabber.onreadystatechange=function(){
      if(grabber.readyState!=4 || grabber.status!=200) return;
      grab_process=false;
      if(grab_restrict_timer!=undefined) clearTimeout(grab_restrict_timer);
      grab_restrict_retry=false;
      gpos.style.color="#000";
      setTimeout(function(){grab();},150);
    };
  }else grab_exec();
}
function grab_exec(){
  var s=grablist[i_grab-1];
  gpos.style.color="#f00";
  grabber.open("POST","utils/grabproc.php?r="+Math.random(),true); // mb index/utils/grabproc.php?r=
  grabber.send(s);
  grab_restrict_retry=true;
  grab_restrict_timer=setTimeout(function(){
    grab_restrict_retry=false;
    clearTimeout(grab_restrict_timer);
  },5000);
}
function spawn_tools(){
  gpos=document.createElement("div");      // req starter
  gpos.setAttribute("id","gpos");
  gpos.style.font="20pt arial";
  document.body.appendChild(gpos);
  gpos.innerHTML="Launch";
  gpos.addEventListener("click",function(){
    gpos.removeEventListener("click",arguments.callee,false);
    grab();
  });
}
document.addEventListener("DOMContentLoaded",function(){
  spawn_tools();
  var m=document.getElementsByTagName("entry").length;
  for(var k=0;k<m;k++){
    data=document.getElementsByTagName("entry")[k].children;
    var n=0;
    if(data.length==3) n=eval(data[2].innerHTML);
    var qtarg="http___arduino_ru"+data[0].innerHTML;
    grablist.push(qtarg);
    for(var i=1;i<n+1;i++) grablist.push(qtarg+"?page="+i);
    document.getElementsByTagName("entry")[k].innerHTML="";
  }
  gpos.innerHTML+=" (tot: "+grablist.length+")";
});
<?php
function curlquery($url){
  $ch=curl_init();
  curl_setopt($ch,CURLOPT_URL,$url);
  curl_setopt($ch,CURLOPT_AUTOREFERER,true);
  curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);
  curl_setopt($ch,CURLOPT_FOLLOWLOCATION,true);
  curl_setopt($ch,CURLOPT_HEADER,true);
  curl_setopt($ch,CURLOPT_USERAGENT,'Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)');
  $rawdata=curl_exec($ch);
  curl_close($ch);
  return $rawdata;
}
function lz($n){
  if($n<10) return '0'.$n; else return $n;
}
$targ=file_get_contents('php://input');
if(isset($_SERVER['HTTP_REFERER'])){
  $fname=$_SERVER['HTTP_REFERER'];
  $fname=str_replace(substr($fname,0,strrpos($fname,'/')+1),'',$fname);
  $fname=str_replace('.htm','.htl',$fname);
}
$fname='../data/'.$fname;
$new_fname=$fname;
$new_flag=false;
$maxsize=700000;
if(file_exists($fname) && filesize($fname)>$maxsize){
  $n=1;
  while(file_exists($new_fname=str_replace('.htl',lz($n).'.htl',$fname)) && filesize($new_fname)>$maxsize) $n++;
  $new_flag=true;
}
$cfg_file='grablast.json';
if(file_exists($cfg_file)){
  $cfg_str=file_get_contents($cfg_file);
  $cfg_str=json_decode($cfg_str);
  $last_thread=$cfg_str[0];
  $hide_counter=$cfg_str[1];
  $last_odd=$cfg_str[2];
}else{
  $last_thread='';
  $hide_counter=0;
  $last_odd=false;
}
if(!$new_flag) $new_fname=str_replace('.htl','00.htl',$new_fname);
$fp=fopen($new_fname,'a+');
if($targ!=""){
  $rawpage=curlquery($targ);
  if($rawpage){
    $pos_s=strpos($rawpage,'<title>')+7;    // thread
    $pos_e=strpos($rawpage,' | ',$pos_s);
    $thrtitle=substr($rawpage,$pos_s,$pos_e-$pos_s);
    if($last_thread!=$thrtitle || $new_flag){
      fwrite($fp,'<thread><h2>'.iconv('utf-8','windows-1251',$thrtitle).'</h2></thread>'.PHP_EOL);
      $last_thread=$thrtitle;
    }
    $searchpos=0;
    $x=0;
    while($x<51){
      $hide_counter++;
      $last_odd=!$last_odd;
      $hide_id='hide_'.$hide_counter;                                                    
      $x++;
      $pos_s=strpos($rawpage,'author-pane-line author-name',$searchpos);
      $pos_e=strpos($rawpage,' </div>',$pos_s);
      $searchpos=$pos_e;
      $author=substr($rawpage,$pos_s+39,$pos_e-$pos_s-44);
      $pos_s=strpos($rawpage,'<div class="content">',$searchpos);
      $pos_e=strpos($rawpage,'forum-post-footer clear-block',$pos_s);                                     // start
      $searchpos=$pos_e;
      $posttext=substr($rawpage,$pos_s+0,$pos_e-$pos_s-43);
      $posttext=str_replace('<div class="content">','<div class="content" id="'.$hide_id.'">',$posttext); // unique hide id
      $posttext=str_replace('<strong','<b',$posttext);
      $posttext=str_replace('</strong','</b',$posttext);
      $posttext=str_replace('<em','<i',$posttext);
      $posttext=str_replace('</em','</i',$posttext);
      $posttext=str_replace('&nbsp;',' ',$posttext);
      $posttext=str_replace(chr(9),' ',$posttext);
      for($i=0;$i<5;$i++) $posttext=str_replace('  ',' ',$posttext);
      $posttext=str_replace('/sites/default/files/u','http___arduino_ru/sites/default/files/u',$posttext);
      if(strpos($rawpage,'author-pane-line author-name',$searchpos)===false) $x=70;                       // end
      $postdata=iconv('utf-8','windows-1251','<postdata><postauthor>'.$author.'</postauthor>'.$posttext.'</postdata>').PHP_EOL;
      $postdata=str_replace(' <p>','<p>',$postdata);
      $postdata=str_replace(' </div>','</div>',$postdata);
      $postdata=str_replace('<p>'.chr(160).'</p>','',$postdata);
      $postdata=str_replace(chr(10).chr(10),chr(10),$postdata);
      $postdata=str_replace(chr(160),'',$postdata);
      if($last_odd) $postodd="post_odd"; else $postodd="post_even";
      $postdata=str_replace('<div class="content"','<div class="content '.$postodd.'"',$postdata);
      fwrite($fp,$postdata);
    }
  }
  $cfg_str=array($last_thread,$hide_counter,$last_odd);
  file_put_contents($cfg_file,json_encode($cfg_str),LOCK_EX);
}
fclose($fp);
?>

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

2. Открыть сайт localhost/вашкаталог/text.htm

Зачем-то был вариант с путём localhost/вашкаталог/index/text.htm, то есть всё что относилось к спискам тем было переложено в подкаталог. Скорее всего потому что у меня старые списки были свалены отдельно в попытке разобрать по ключевым словам комплектухи (всё с цифрами 9341, 2004, 1602 к экранам и т п).

На странице будет надпись из количества подлежащих скачиванию страниц сделанных/всего. На неё нажать мышкой. Активная красная. Если оба номера равны всего и надпись чёрная - значит готово. Если залагало/оборвалось, то автосохранется в файле grablast.json, потом можно заново открыть, нажать и продолжится. Я бы его конешно переделал под более цивильный вид и чтобы без js (чтобы работало интерактивно команднострочно), но это у меня, скажем так, щас неактивный проект. Если переделаю то выложу в отдельную тему.

3. Как делать списки тем

curl -L -o file.ext http___arduino_ru/forum/6

потом curl -L -o файлтемы URLссылкинатему

на последние страницы придётся в обозревателе понажимать.

<qty> - количество страниц в теме минус 1 (потому что вторая страница содержит в URL двойку, но первая не содержит единицу)

Длину тем придётся попарсить (выуживая из страниц, сграбленных в разделах). Автоматизировать bat-файлами. Разбирать тексты можно каким-нибудь редактором с макросами. Мне лично нравится FAR т. к. он универсальный и я могу лазить в файлы из панелей, не покидая его окна, то есть получаю бесшовную работу как с содержимым диска, так и самих файлов (не надо альттабаться). Но дело вкуса и я ни к чему не принуждаю.

Лайфхак для машин с антивирусом в агрессивном режиме: не стоит пытаться что-то запускать из php. лучше писать bat, который потом запустить руками. Если происходит цепной запуск "пользователь->php->bat->curl например" то антивирусы агрятся. Любые. Да неудобняк с curl, но делал для себя и потому граббер полуавтоматический а не автоматический. Я вообще не спец в написании релизных прог, делаю в программе только то что мне впадлу/долго делать руками.

Если лень их составлять то эту работу я уже делал, но те списки по состоянию на 2018й год (если судить по атрибутам файлов). Их где-то полтора мегабайта, тоже если надо поделюсь, но актуальнее всё же будет забрать curl-ом новые.

Voodoo Doll
Voodoo Doll аватар
Offline
Зарегистрирован: 18.09.2016

UPD: конечные хтмлы режутся по ~700 килобайт, чтобы не лагало когда читаешь.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Voodoo Doll пишет:

UPD: конечные хтмлы режутся по ~700 килобайт, чтобы не лагало когда читаешь.

TKS!

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Посмотрел Гайверовскую библиотеку и рисунок, вот как-то не верится, что он не понимает, что при таком раскладе сигналов на пины на ШИМе влетает каждый период на активное торможение?

(при движении назад естественно)

lilik
Offline
Зарегистрирован: 19.10.2017

Да, это ошибка, но видимо он экономит ШИМ выводы :-)

А говоря философически - большое число "покатушек-ходунов" имеют и сервоприводы и ШИМ управляемые моторы. Как бы хорошо иметь общую библиотеку на 20 ШИМ выводов и сервоприводов :-), не мешающих друг другу.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

lilik пишет:

Да, это ошибка, но видимо он экономит ШИМ выводы :-)

А говоря философически - большое число "покатушек-ходунов" имеют и сервоприводы и ШИМ управляемые моторы. Как бы хорошо иметь общую библиотеку на 20 ШИМ выводов и сервоприводов :-), не мешающих друг другу.

ну да, пару ШИМ каналов, но и в библиотеке жеж аналогично...
Архат брал мегу, даже расширял ей память и в размерах ужимал значительно,
для сына пилил, на скоростные покатушки, у меги с этим получше