roboforum.ru

Технический форум по робототехнике.


соединение 2х ардуин

Как собрать и запрограммировать робота на Arduino(Freeduino, Roboduino, Seeduino ...). Используем Wiring и Processing.

Re: соединение 2х ардуин

Сообщение Angel71 » 16 апр 2015, 20:31

при чём тут великие? вам уже даже немного кода подсказали и название библиотеки, но додумать, что с этим делать наверно лень. вбейте себе в голову, что между помогать и постоянно делать что-то за других разные вещи. разницу между кормить постоянно и дать удочку, что бы сами еду добывали, понимаете? если не доходит, идите лесом и тупите сколько и как вам захочется.
Dmitry__, дануна, мне соседей и знакомых хватает - постоянно то на шашлыки тянут, то ещё куда. пару раз за несколько месяцев "немного" повыпивали и хватит, чтот меня за последний год почти не тянет даже на пиво. :ROFL: поржал с того примера кода. ладно, скучно с вами, уйду я от вас.
Аватара пользователя
Angel71
 
Сообщения: 10668
Зарегистрирован: 18 апр 2009, 22:18
Предупреждения: -1

Re: соединение 2х ардуин

Сообщение slom » 16 апр 2015, 21:14

Dmitry__ писал(а):
slom, обещаешь всех тут напоить, если получится? Особенно angel-а? :D


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

вот мой нынешний код от которого управляется тирекс контролер с телефона:

Код: Выделить всёРазвернуть
// Скетч для управления через блютус, Wild Thumper 6WD, на ардуино совместимом контролере TREX controller. реализовано движение и стрельба с водомета, захват клешней манипулятором. 
// по вопросам и предложениям писать на почту slom1@list.ru
// новые фото и видео можно найти на www.шоуальянс.com

#include <BTCA2ALite.h>// Добавляем библиотеку блютус программы
#include <Servo.h> // Добавляем библиотеку серво

Servo myservoH; // Горизонтальная серва углы от 0 до 180 (центровка 89)
Servo myservoV; // Вертикальная серва углы от 1 до 45
Servo myservoZ; // серва Клешня
Servo myservoR; // серва рука клешни
const int Z_SERVO_PIN = 5; // добовляем пин захвата
const int R_SERVO_PIN = 6; // добовляем пин руки манипулятора
const int H_SERVO_PIN = 7; // Горизонтальная серва подключена к пину 7
const int V_SERVO_PIN = 8; //Пин вертикального сервопривода 8
const float Z_L_ANGLE = 116; // Максимальные угл поворота башни налево
const float Z_R_ANGLE = 45; // Максимальные угл поворота башни направо
const float Z_DEF_ANGLE = 50; // Дефолтный угол (центровка)
const float R_L_ANGLE = 178; // Максимальные угл поднятия руки
const float R_R_ANGLE = 3; // Максимальные угл наклона руки
const float R_DEF_ANGLE = 160; // Дефолтный угол руки
const float H_L_ANGLE = 180; // Максимальные угл поворота башни налево
const float H_R_ANGLE = 0; // Максимальные угл поворота башни направо
const float H_DEF_ANGLE = 84; // Дефолтный угол (центровка)
const float V_U_ANGLE = 140; // Максимальные угл поворота башни вверх
const float V_D_ANGLE = 45; // Максимальные угл поворота башни вниз
const float V_DEF_ANGLE = 60; // Дефолтный угол (центровка)
//Размер шага V_STEP и H_STEP побираем экспериментально для достижения нужной скорости поворота серв
const float V_STEP = 0.012; // Шаг - знаение отвечающее за скорость вращения по вертикали.
const float H_STEP = 0.012; // Шаг - знаение отвечающее за скорость вращения по горизонтали
const float Z_STEP = 0.012; // шаг захвата
const float R_STEP = 0.012; // шаг руки
float curVAngle = V_DEF_ANGLE; //Переменная текущего угла верт. сервы
float curHAngle = H_DEF_ANGLE; //Переменная текущего угла гор. сервы
float curZAngle = Z_DEF_ANGLE; //
float curRAngle = R_DEF_ANGLE; //
bool moveServoVUp = false; //Флаг движения верт. сервы вверх
bool moveServoVDown = false; //Флаг движения верт. сервы вниз
bool moveServoHLeft = false; //Флаг движения гор. сервы влево
bool moveServoHRight = false; //Флаг движения гор. сервы вправо
bool moveServoZLeft = false; //Флаг движения гор. сервы влево
bool moveServoZRight = false; //Флаг движения гор. сервы вправо
bool moveServoRLeft = false; //Флаг движения гор. сервы влево
bool moveServoRRight = false; //Флаг движения гор. сервы вправо

btca2aLite btca2aLite; // Конструктор btca2aLite


// задаем пины для левого мотора
#define Dir_L 2
#define Pwm_L 3
#define Brake_L 4
// задаем пины для правого мотора
#define Dir_R 10
#define Pwm_R 11
#define Brake_R 9

// Задаем скорости для движения
byte MaxSpeed = 230; // Максимальная скорость
byte MinSpeed = 90;  // Минимальная скорость

int forw_back = 0;
int righ_left = 0;

byte step_fb = 5;     // Шаг изменения скорости движения вперед - назад
byte step_stop = 10;  // Шаг изменения скорости остановки
byte step_rl =  10;    // Шаг изменения скорости движения вправо - влево
byte step_dir = 10;   // Шаг изменения скорости выравнивания



#define SHOT  12 // пин для водомета

enum States
{
    WAITING,
    READING,
    RUNNING,
    ERROR,
    TIMEOUT
};

States state;
States onWait();
States onRead();
States onRun();
States onError();

States onTimeout();

void performServo(); // добовляем сервы


void setup(){
    Serial.begin(9600); // Скорость BT и порта должна быть 9600
    //Моторы
    pinMode (Pwm_L, OUTPUT);
    pinMode (Dir_L, OUTPUT);
    pinMode (Brake_L, OUTPUT);
   
    pinMode (Pwm_R, OUTPUT);
    pinMode (Dir_R, OUTPUT);
    pinMode (Brake_R, OUTPUT);
   
    digitalWrite (Pwm_L, LOW);
    digitalWrite (Pwm_R, LOW);
   
    digitalWrite (Brake_L, LOW);
    digitalWrite (Brake_R, LOW);
 
pinMode(SHOT, OUTPUT); // задаем выход для стрельбы водой
   
    // устанавливаем пин как вывод управления сервой
    myservoH.attach(H_SERVO_PIN);
    myservoV.attach(V_SERVO_PIN);
    myservoZ.attach(Z_SERVO_PIN);
    myservoR.attach(R_SERVO_PIN);
    myservoH.write(curHAngle);
    myservoV.write(curVAngle);
    myservoZ.write(curZAngle);
    myservoR.write(curRAngle);
   
    //Светодиод
    pinMode(13, OUTPUT); // Инициализируем пин светодиода
    digitalWrite(13, HIGH); // Светодиод выключен
}

void loop(){
   
    btca2aLite.ReadCommand(); // Считывание принятых команд (кодов кнопок)
    //Вызываем функцию управление сервами
    performServo();
   
//этот код для меня темный лес, мне его дали для плавного старта и торможения моторов. если ехать вперед и резко нажать кнопку назад, машина продолжит ехать вперед, плавно остановиться и только потом поедет назад, это спасает редуктора от разрушения.
//если ктото знает что тут к чему, прокоментируйте пожалуйста, чтоб я тоже понимал :)
  static unsigned long pre_millis = 0;
  if(millis()-pre_millis > 50)
  {
    pre_millis = millis();
   
    if(btca2aLite.ButtonPressed(KEYCODE_DPAD_UP))
    {
      forw_back += step_fb;
      if(forw_back > 0 && forw_back < MinSpeed) forw_back = MinSpeed;
    }
    else if(btca2aLite.ButtonPressed(KEYCODE_DPAD_DOWN))
    {
      forw_back -= step_fb;
      if(forw_back < 0 && forw_back > MinSpeed*-1) forw_back = MinSpeed*-1;
    }
    else
    {
      if(forw_back < 0) forw_back += step_stop;
      else if(forw_back > 0) forw_back -= step_stop;
      if(abs(forw_back) < MinSpeed) forw_back = 0;
    }
    forw_back = constrain(forw_back, MaxSpeed*-1, MaxSpeed);


    if(btca2aLite.ButtonPressed(KEYCODE_DPAD_RIGHT))
    {
      righ_left += step_rl;
      if(righ_left > 0 && righ_left < MinSpeed) righ_left = MinSpeed;
    }
    else if(btca2aLite.ButtonPressed(KEYCODE_DPAD_LEFT))
    {
      righ_left -= step_rl;
      if(righ_left < 0 && righ_left > MinSpeed*-1) righ_left = MinSpeed*-1;
    }
    else
    {
      if(righ_left < 0) righ_left += step_dir;
      else if(righ_left > 0) righ_left -= step_dir;
      if(abs(righ_left) < MinSpeed) righ_left = 0;
    }
    righ_left = constrain(righ_left, MaxSpeed*-1, MaxSpeed);


    int pwm_l = forw_back + righ_left;
    int pwm_r = forw_back - righ_left;
    pwm_l = constrain(pwm_l, MaxSpeed*-1, MaxSpeed);
    pwm_r = constrain(pwm_r, MaxSpeed*-1, MaxSpeed);

    digitalWrite(Dir_L, (pwm_l<0)?0:1);
    digitalWrite(Dir_R, (pwm_r<0)?0:1);
    analogWrite(Pwm_L, abs(pwm_l));
    analogWrite(Pwm_R, abs(pwm_r));
  }
       
  //дальше идут кнопки управления
   
    //-------— включение насоса —-------------
   if (btca2aLite.ButtonPressed(KEYCODE_BUTTON_SELECT))
    {
     digitalWrite (SHOT, HIGH);
     }
    //-------— выключение насоса происходит автоматически после отпускания кнопки—-------------
   if(btca2aLite.ButtonReleased(KEYCODE_BUTTON_SELECT))
    {
   digitalWrite (SHOT, LOW);
    }
   
        if(btca2aLite.Button(KEYCODE_BUTTON_START)) // алгоритм автоматического хватания предметов
    {
       
/* шаг вперед, отключил....
      digitalWrite (Dir_L, HIGH);
      analogWrite (Pwm_L, 150);
      digitalWrite (Dir_R, HIGH);
      analogWrite (Pwm_R, 150);
      delay (100);
      // потом стоп
      analogWrite (Pwm_L, 0);
      analogWrite (Pwm_R, 0);
      delay (500);
*/
     
       myservoZ.write(45);; // Клешня разжимается
        myservoR.write(3);; // рука клешни опускаем
        delay(2000); /* ждем 2 секунды, */
         myservoZ.write(116);; // Клешня сжимаем
         delay(1000); /* ждем 1 секунду, */
          myservoR.write(170);; // рука клешни поднимаем
           delay(1000); /* ждем  */
           myservoZ.write(45);; // Клешня разжимаем
    }
   
   
    //--------— Повороты серв при нажатии кнопок —-------------
   
    if(btca2aLite.Button(KEYCODE_BUTTON_X)) // поворот водомета вниз
    {
        moveServoVDown = true;
             
    }
    if(btca2aLite.Button(KEYCODE_BUTTON_A)) // поворот водомета направо
    {
        moveServoHRight = true;
    }
    if(btca2aLite.Button(KEYCODE_BUTTON_B)) // поворот водомета вверх
    {
        moveServoVUp = true;
             
    }
   
    if(btca2aLite.Button(KEYCODE_BUTTON_Y)) // поворот водомета налево
    {
        moveServoHLeft = true;
    }
   
        if(btca2aLite.Button(KEYCODE_BUTTON_R1)) // зхахват сжать
    {
        moveServoZLeft = true;
    }
    if(btca2aLite.Button(KEYCODE_BUTTON_R2)) // захват разжать
    {
        moveServoZRight = true;
    }
   
   
           if(btca2aLite.Button(KEYCODE_BUTTON_L1)) // рука клешни вниз
    {
        moveServoRLeft = true;
    }
    if(btca2aLite.Button(KEYCODE_BUTTON_L2)) // рука клешни вверх
    {
        moveServoRRight = true;
    }
   
   
//--------— чтобы сервы не продолжали движения при отжатых кнопках —-------------   
if(btca2aLite.ButtonReleased(KEYCODE_BUTTON_X))
{
moveServoVDown = false;
}
if(btca2aLite.ButtonReleased(KEYCODE_BUTTON_B))
{
moveServoVUp = false;
}

if(btca2aLite.ButtonReleased(KEYCODE_BUTTON_A))
{
moveServoHRight = false;
}
if(btca2aLite.ButtonReleased(KEYCODE_BUTTON_Y))
{
moveServoHLeft = false;
}

if(btca2aLite.ButtonReleased(KEYCODE_BUTTON_R2))
{
moveServoZRight = false;
}
if(btca2aLite.ButtonReleased(KEYCODE_BUTTON_R1))
{
moveServoZLeft = false;
}   
   
if(btca2aLite.ButtonReleased(KEYCODE_BUTTON_L2))
{
moveServoRRight = false;
}
if(btca2aLite.ButtonReleased(KEYCODE_BUTTON_L1))
{
moveServoRLeft = false;
}       
   
   
    //----------------— Стоп —---------------------
   
    // Если не нажата ни одна кнопка курсора происходит остановка, скорость 0 для каждого мотора
    if (btca2aLite.ButtonReleased(KEYCODE_DPAD_UP) && btca2aLite.ButtonReleased(KEYCODE_DPAD_DOWN) && btca2aLite.ButtonReleased(KEYCODE_DPAD_LEFT) && btca2aLite.ButtonReleased(KEYCODE_DPAD_RIGHT)){
        analogWrite (Pwm_L, 0);
        analogWrite (Pwm_R, 0);
    }
}



//Функция управления сервоприводами (вызывается в теле loop на каждой итерации)
//Выполняет изменения положения серв на подобранный шаг согласно установленным флагам движения
//Флаги устанавливаются согласно поступившим символам управления сервами
void performServo()
{
    //Установлен флаг движения вверх и текущий угол не максимальный
    if (moveServoVUp && curVAngle + V_STEP <= V_U_ANGLE)
    {
        //К текущему верт. углу прибавляем шаг
        curVAngle += V_STEP;
    }
    //Установлен флаг движения вниз и текущий угол не минимален
    else if (moveServoVDown && curVAngle - V_STEP >= V_D_ANGLE)
    {
        //От текущего верт. угла отнимаем шаг
        curVAngle -= V_STEP;
    }
    //Установлен флаг движения влево и текущий угол не максимален
    if (moveServoHLeft && curHAngle + H_STEP <= H_L_ANGLE)
    {
        //К текущему гор. углу прибавляем гор. шаг
        curHAngle += H_STEP;
    }
    //Установлен флаг движения вправо и текущий угол не минимален
    else if (moveServoHRight && curHAngle - H_STEP >= H_R_ANGLE)
    {
        //От текущего угла отнимаем гор. шаг
        curHAngle -= H_STEP;
    }
   
    //Установлен
    if (moveServoZLeft && curZAngle + Z_STEP <= Z_L_ANGLE)
    {
        //К текущему гор. углу прибавляем гор. шаг
        curZAngle += Z_STEP;
    }
    //Установлен флаг движения вправо и текущий угол не минимален
    else if (moveServoZRight && curZAngle - Z_STEP >= Z_R_ANGLE)
    {
        //От текущего угла отнимаем гор. шаг
        curZAngle -= Z_STEP;
    }
   
   
        //Установлен
    if (moveServoRLeft && curRAngle + R_STEP <= R_L_ANGLE)
    {
        //К текущему гор. углу прибавляем гор. шаг
        curRAngle += R_STEP;
    }
    //Установлен флаг движения вправо и текущий угол не минимален
    else if (moveServoRRight && curRAngle - R_STEP >= R_R_ANGLE)
    {
        //От текущего угла отнимаем гор. шаг
        curRAngle -= R_STEP;
    }
   
    //Если было движние по вертикали
    if (moveServoVUp || moveServoVDown)
    {
        myservoV.write(curVAngle);
    }
    //Если было движение по горизонтали
    if (moveServoHLeft || moveServoHRight)
    {
        myservoH.write(curHAngle);
    }
   
    if (moveServoZLeft || moveServoZRight)
    {
        myservoZ.write(curZAngle);
    }
   
        if (moveServoRLeft || moveServoRRight)
    {
        myservoR.write(curRAngle);
    }
}


далее код который я нашел тут:
http://arduino.ru/forum/proekty/tank-up ... tikom-ps-2

а именно на этой странице:
http://arduino.ru/forum/proekty/tank-up ... s-2?page=3

я всеголиш перебил пины под свои и добавил еще одну серву

Добавлено спустя 1 минуту 27 секунд:
Angel71 писал(а): чтот меня за последний год почти не тянет даже на пиво. :ROFL: поржал с того примера кода. ладно, скучно с вами, уйду я от вас.


нам спиртное не к чему, я отвечу почему.... :lol:
иди иди постылый.... :wink:

Добавлено спустя 4 минуты 23 секунды:
Angel71 писал(а): разницу между кормить постоянно и дать удочку, что бы сами еду добывали, понимаете?


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

лучший метод обучения - на живых примерах, а все эти теории про буковки и прочее, конечно полезны но неочень интересны и мало чем помогут, вот толку от того что вы их знаете, если сами не можете связать 2 ардуины... :wink:
Аватара пользователя
slom
 
Сообщения: 645
Зарегистрирован: 07 сен 2014, 19:29
Откуда: Севастополь
Skype: slom_3d
прог. языки: 3d max :)

Re: соединение 2х ардуин

Сообщение Angel71 » 16 апр 2015, 21:28

с гранатой это метко - вам дали кусок кода для вывода инфы в консоль и которую вы не сможете применять на второй дуне и вы расплылись в блаженной улыбке. то, что с подобным кодом, засирающим вывод, ресурсы меги будут просто в никуда улетать, вы даже пока и не поняли. :ROFL: это называется над вами пошутили, а вы и не поняли. наверно более подходящий вариант кода отфильтровывает та часть уязвлённого мозга, кричащая "он некхарофай, скип, скип, скип, там нет ничего полезного". :crazy: 2? максимум для быстрого теста функционала. а так интересней гетерогенная сеть из 3х и более железок.
Аватара пользователя
Angel71
 
Сообщения: 10668
Зарегистрирован: 18 апр 2009, 22:18
Предупреждения: -1

Re: соединение 2х ардуин

Сообщение slom » 16 апр 2015, 23:02

ангел тебе не надоело?
Аватара пользователя
slom
 
Сообщения: 645
Зарегистрирован: 07 сен 2014, 19:29
Откуда: Севастополь
Skype: slom_3d
прог. языки: 3d max :)

Re: соединение 2х ардуин

Сообщение Scorpio » 17 апр 2015, 02:55

Я использую в таких случаях PCF8574
Аватара пользователя
Scorpio
 
Сообщения: 2681
Зарегистрирован: 30 сен 2008, 18:49
Откуда: Где-то в Латинской Америке

Re: соединение 2х ардуин

Сообщение Dmitry__ » 17 апр 2015, 06:32

slom писал(а):вас я бы угостил хорошим пивом или чем покрепче

Kxe, смотри, я злопамятный, ведь попрусь в Севастополь за пивом :D
А ты уверен, что после "наигрался" с этим джоем он тебя будет устраивать? Больше 15 метров управления на них не получить. Ну можно еще поколхозить внешние антенны, но это колхоз :)

Ок, ты можешь полностью повторит экскремент из своей же ссылки?
http://robocontroller.ru/news/besprovodnoj_dzhojstik_ot_playstation_arduino/2013-10-19-32
Т.е. ты должен залить скетч, запустить сервис/Монитор порта.
Там выставить скорость 57600. И убедиться что нажатия всяких кнопок на джое отображаются в терминалке. Химичь на дуине, которая не "TREX", шоб не угробить все и вся. У меня получилось так:
Код: Выделить всёРазвернуть
Found Controller, configured successful pressures = false
rumble = false
Try out all the buttons, X will vibrate the controller, faster as you press harder;
holding L1 or R1 will print out the analog stick values.
Note: Go to www.billporter.info for updates and to report bugs.
DualShock Controller found R2 pressed
R2 pressed
R2 pressed
L2 pressed
L2 pressed
Stick Values:116,255,128,255
Stick Values:255,255,255,255
Stick Values:255,255,128,255
Stick Values:120,255,128,255
Stick Values:211,255,128,255
L3 pressed
R3 pressed
L2 pressed
Stick Values:120,255,131,255
Stick Values:120,255,138,255
Stick Values:255,255,255,255



Кста, прикол, заработал беспроводной джойстик: новый Logitech. Я его не мог запустить года 3 назад. Т.к. мне не давали на длительный срок playstation для хака. А тут поиграл задержкой в скетче "delay(50);" и джой заработал :shock:
Аватара пользователя
Dmitry__
 
Сообщения: 8033
Зарегистрирован: 13 янв 2011, 15:25
Откуда: Санкт-Петербург

Re: соединение 2х ардуин

Сообщение slom » 17 апр 2015, 09:33

Dmitry__ писал(а):
slom писал(а):вас я бы угостил хорошим пивом или чем покрепче

Kxe, смотри, я злопамятный, ведь попрусь в Севастополь за пивом :D
А ты уверен, что после "наигрался" с этим джоем он тебя будет устраивать? Больше 15 метров управления на них не получить. Ну можно еще поколхозить внешние антенны, но это колхоз :)



да ради бога, что мне пива жалко... заезжайте :D

насчет 15 м то вполне устраивает. т.к это не самолет, и без камерный вариант управления. как раз для того чтобы делать что то вблизи(5-7 м) не дальше...
сейчас вообще телефоном управляю, через тот же блютус.

насчет проверки работоспособности так это первым же делом сделал:
Код: Выделить всёРазвернуть
Found Controller, configured successful pressures = false
rumble = false
Try out all the buttons, X will vibrate the controller, faster as you press harder;
holding L1 or R1 will print out the analog stick values.
Note: Go to www.billporter.info for updates and to report bugs.
Unknown Controller type found L2 pressed
Stick Values:127,109,127,128
Stick Values:127,109,127,128
Start is being held
Start is being held
Start is being held
Select is being held
Select is being held
Select is being held
Select is being held
Select is being held
Select is being held
Select is being held
L2 pressed
Stick Values:127,110,127,128
Stick Values:127,109,127,128
Stick Values:127,109,127,128
Stick Values:127,109,127,128
Stick Values:127,110,127,128
Stick Values:127,109,127,128
Stick Values:127,109,127,128
Stick Values:127,109,127,128
Stick Values:127,109,127,128
Stick Values:127,109,127,128
Stick Values:127,109,127,128
Stick Values:127,109,127,128
Stick Values:127,110,127,128
Stick Values:127,109,127,128
Stick Values:127,108,127,128
Stick Values:127,110,127,128
Stick Values:127,108,127,128
Stick Values:127,108,127,128
Stick Values:127,108,127,128
Stick Values:127,108,127,128
Stick Values:127,109,127,128
Stick Values:127,109,127,128
Stick Values:127,110,127,128
Stick Values:127,110,127,128
Stick Values:127,108,127,128
Stick Values:127,108,127,128
Stick Values:127,108,127,128
Stick Values:127,108,127,128
Stick Values:127,108,127,128
Stick Values:127,108,127,128
Stick Values:127,128,127,128
Stick Values:127,128,127,128
Stick Values:127,128,127,128
Stick Values:127,128,127,128
Stick Values:127,128,127,128
Stick Values:127,128,127,128
Stick Values:127,128,127,128
L2 pressed
Stick Values:127,128,127,128
Stick Values:127,128,127,128
Stick Values:127,128,127,128
Stick Values:127,128,127,128
Stick Values:127,128,127,128
Stick Values:127,128,127,128
Stick Values:127,128,127,128
Stick Values:127,128,127,128
Stick Values:127,128,127,128
Stick Values:127,128,127,128
Stick Values:127,128,127,128
Stick Values:127,128,127,128
Stick Values:127,128,127,128
Stick Values:127,128,127,128
Stick Values:127,128,127,128
Stick Values:127,128,127,128
Stick Values:127,128,127,128
Stick Values:127,128,127,128
Stick Values:127,128,127,128
Stick Values:127,128,127,128
Stick Values:127,128,127,128
Stick Values:127,128,127,128
Stick Values:127,128,127,128
Stick Values:127,128,127,128
Stick Values:127,128,127,128
Stick Values:127,128,127,128
Stick Values:127,128,127,128
Stick Values:127,128,127,128
Stick Values:127,128,127,128
Stick Values:127,128,127,128
Stick Values:127,128,127,128
Stick Values:127,128,127,128
Stick Values:127,128,127,128
Stick Values:127,128,127,128
Stick Values:127,128,127,128
Stick Values:127,128,127,128
Stick Values:127,128,127,128
Stick Values:127,128,127,128
Stick Values:127,128,127,128
Stick Values:127,128,127,128
Stick Values:127,128,127,128
Stick Values:127,128,127,128
Stick Values:127,128,127,128
Stick Values:127,128,127,128
Stick Values:127,128,127,128
R2 pressed
R2 pressed
Stick Values:127,128,127,128
Stick Values:127,128,127,128
Stick Values:127,128,127,128
Stick Values:127,128,127,128
Stick Values:127,128,127,128
Stick Values:127,128,127,128
Stick Values:127,128,127,128
Stick Values:127,128,0,128
Stick Values:127,128,0,128
Stick Values:127,128,0,128
Stick Values:127,128,0,128
R3 pressed
L3 pressed
R3 pressed
L3 pressed
Circle just pressed
Square just released
X just changed
X just changed
Triangle pressed
Stick Values:127,128,127,128
Stick Values:127,128,127,128
Stick Values:127,128,127,128
Stick Values:127,128,127,128
Stick Values:127,128,127,128
Stick Values:127,128,127,128
Stick Values:127,128,127,128
Stick Values:127,128,127,128
Stick Values:127,128,127,128
DOWN held this hard: 0
DOWN held this hard: 0
DOWN held this hard: 0
DOWN held this hard: 0
DOWN held this hard: 0
Up held this hard: 0
Up held this hard: 0
Up held this hard: 0
LEFT held this hard: 0
LEFT held this hard: 0
LEFT held this hard: 0
Right held this hard: 0
Right held this hard: 0
Right held this hard: 0
Select is being held
Select is being held
Select is being held
Start is being held
Start is being held
Start is being held
Start is being held
R3 pressed
Stick Values:127,107,127,128
Stick Values:127,107,127,128
Stick Values:127,107,127,128
Stick Values:127,107,127,128


правда при нажатии л1, р1 выдает такое
Код: Выделить всёРазвернуть
Stick Values:127,107,127,128
Stick Values:127,107,127,128
Stick Values:127,107,127,128
Stick Values:127,107,127,128


толи глюк толи так должно быть... ну и на короткое нажатие кнопки успевает проскочить 3-4 сообщения о ее нажатии :)

потом я пошел дальше и на левый стикер поставил управление 2мя сервами.
получился 2х осевой вращатель.
Код: Выделить всёРазвернуть
#include <PS2X_lib.h>  //спец библиотека для работы с пультом сони пс2 for v1.6
#include <Servo.h>
PS2X ps2x;
int PS2 = 0;
Servo LXservo;  // тут задаем имя сервы эта по оси х...
Servo LYservo;
#define L_dir 2   //пины для драйвера мотора
#define L_pwm 3
#define R_dir 4
#define R_pwm 5

int mass[4];      //здесь будем хранить значения для скоростей и направлений
                  //mass[0]   лев.напр.
                  //mass[1]   лев.скор.
                  //mass[2]   прав.напр.
                  //mass[3]   прав.скор.
                 
void setup(){
  LXservo.attach(8); //пины серв
  LYservo.attach(6);
 
  PS2 = ps2x.config_gamepad(13,11,10,12, true, true);   //Настройка выводов: (clock, command, attention, data, true, true)
  pinMode(L_dir, OUTPUT);
  pinMode(L_pwm, OUTPUT);
  pinMode(R_dir, OUTPUT);
  pinMode(R_pwm, OUTPUT);
}

void loop(){
  LXservo.write(map(ps2x.Analog(PSS_LX), 255, 0, 0, 180)); ; // мап - это интересная функция которая очень просто и без танцев с бубном переводит значения положения джойстика в градусы для вращения сервы.
delay(50);
  ps2x.read_gamepad(false, 0);
 
  LYservo.write(map(ps2x.Analog(PSS_LY), 0, 255, 0, 90)); ;
delay(50);
  ps2x.read_gamepad(false, 0);
 
 
    dir_pwm(ps2x.Analog(PSS_RY),2);   //обрабатываем правый джойстик, это вроде как для мотора на колеса...
  digitalWrite(R_dir, mass[2]);
  analogWrite(R_pwm, mass[3]);
}   

void dir_pwm(int Y, int n){         //Подпрограмма для обработки значений джойстика, тут непонятное чтото...
  if (Y == 128){
    mass[n+1] = 0;
  }
  if (Y >128){
    mass[n+1] = Y*2-255;
    mass[n] = 1;
  }
  if (Y <128){
    mass[n+1] = 255-Y*2;
    mass[n] = 0;
  }
}



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

у меня такое чувство что там всего несколько строчек ну максимум 10 дописать и все... но блин примеров не нашел :(

Добавлено спустя 3 минуты 3 секунды:
Scorpio писал(а):Я использую в таких случаях PCF8574


у вас он есть, в у меня его нету.
к тому же у меня ардуина с мощным шилдом, туда сразу без лишних проводов и соединений, втыкаю сервы и все работает, а у вас там только разветвитель сигналов, еще нужна куча проводов и дополнительный стабилизатор на сервы....
к томуже для такого разветвителя тоже нужен особый код, а с этим как раз таки и проблемы :D
Аватара пользователя
slom
 
Сообщения: 645
Зарегистрирован: 07 сен 2014, 19:29
Откуда: Севастополь
Skype: slom_3d
прог. языки: 3d max :)

Re: соединение 2х ардуин

Сообщение RootAdmin » 17 апр 2015, 15:07

Scorpio писал(а):Я использую в таких случаях PCF8574

Как расширитель портов - да, согласен.
Все равно колхозить стандартную билиотеку servo для случая когда серв больше двух - некомильфо ИМХО. Лучше уж таймер (один) и пара массивов. В одном очередность серв (номер сервы по возрастанию величины позиции, ширины импульса управления) , во втором - желаемая позиция.
Дым, идущий из всех устройств в помещении предвещает появление электрика.
RootAdmin
 
Сообщения: 1725
Зарегистрирован: 07 авг 2010, 21:29
Откуда: КМВ
прог. языки: C
ФИО: Андрей

Re: соединение 2х ардуин

Сообщение slom » 17 апр 2015, 15:44

а в чем проблема когда серв больше 2х? у меня работает 4 и никаких проблем не возникало.

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

вот что сейчас хочу получить:
Изображение

Добавлено спустя 4 минуты 41 секунду:
нашел интересную тему http://arduino.ru/forum/programmirovani ... sytransfer
там вроде бы то что нужно. только както под себя переделать надо :)
только как )))
Аватара пользователя
slom
 
Сообщения: 645
Зарегистрирован: 07 сен 2014, 19:29
Откуда: Севастополь
Skype: slom_3d
прог. языки: 3d max :)

Re: соединение 2х ардуин

Сообщение Dmitry__ » 17 апр 2015, 16:17

slom писал(а):насчет проверки работоспособности так это первым же делом сделал:

Ну, круто. Значит идем дальше.

slom писал(а):главный вопрос, как перенести выполнение этих функций на другую дуню...
тоесть сейчас оно работает на 1й ардуине. а надо чтобы с 1й шли команды на 2ю и там уже крутились сервы и моторы...


Теперь идем изучать протокол управления "TREX_controller". Открываем текстовым редактором скетч "Bluetooth.ino", достаем бубен и кальян :)
Код: Выделить всёРазвернуть
void Bluetooth()
{
  //============================================================= Bluetooth Control ===================================================

  static byte d,e;                                             // data and error bytes
  if(Serial.available()>2)                                     // Command is 3 bytes in length
  {
    d=Serial.read();                                           // read byte from buffer
    if(d!=startbyte)                                           // if byte is not a start byte (0x0F)
    {
      lmspeed=0;                                               // bad data received
      rmspeed=0;                                               // set motor speeds to 0
      e=0;                                                     // error flag reset
    }
    else
    {
      lmspeed=(int(Serial.read())-127)*2-1;                    // good data received
      rmspeed=(int(Serial.read())-127)*2-1;                    // read values for left and right motors
    }
  }
  else                                                         // less than 3 bytes in buffer
  {
    e++;                                                       // count program loops with less than 3 bytes in buffer
    if(e>100)                                                  // assume lost signal if buffer less than 3 bytes for too long
    {
      lmspeed=0;                                               // stop left motor
      rmspeed=0;                                               // stop right motor
      e=0;                                                     // reset error counter
    }
  }
  Motors();                                                    // update motors
}

И шо мы тут видим? А видим мы: если принято >2-х байт и первый байт 0x0F (старт байт), то след. 2 байта - это "lmspeed=(int(Serial.read())-127)*2-1; " и "rmspeed=(int(Serial.read())-127)*2-1;". Т.е. протокол: 1-й байт всегда 0x0f, 2-й байт - мощность левого мотора, 3-й байт - мощность правого мотора. Все! Бинго! :)

Теперь проверяем. Вешаем сообщение 0x0f,0x20,0x20 (старт байт, 0х20 на левый и правый мотор) на какую-нибудь кнопку, например на "L3". Ищем "L3 pressed" (ctrl f) в скетче "PS2X_Example_RUS.ino". Находим всего одно упоминание:
Код: Выделить всёРазвернуть
    if (ps2x.NewButtonState()) {        //будет TRUE если какая то кнопка изменила свой статус (Вкл. на Выкл. или Выкл. на Вкл.)
      if(ps2x.Button(PSB_L3))
        Serial.println("L3 pressed"); // L3 нажата
      if(ps2x.Button(PSB_R3))
        Serial.println("R3 pressed"); // R3 нажата
      if(ps2x.Button(PSB_L2))
        Serial.println("L2 pressed"); // L2 нажата
      if(ps2x.Button(PSB_R2))
        Serial.println("R2 pressed"); // R2 нажата
      if(ps2x.Button(PSB_TRIANGLE))
        Serial.println("Triangle pressed"); // Треугольник нажат     
    }

В яндексе находим "Serial.println"
http://arduino.ru/Reference/Serial/Println
и 2-ю (без ln)
http://arduino.ru/Reference/Serial/Print
и посылку байтов:
http://arduino.ru/Reference/Serial/Write
Запускаем калькулятор в инженерном режиме (для перевода hex в десятичный вид). Делаем глубокий вдох через кальян :)
И переводим 0x0f,0x20,0x20 в десятичный вид. Т.е. на калькуляторе жамкаем кнопку "hex", вбиваем "f", жамкаем кнопку "dec", получаем "15". Наше сообщение из: 0x0f,0x20,0x20 стало: 15,32,32. Теперь эти данные вбиваем в Serial.write:

Код: Выделить всёРазвернуть
Serial.write(15);
Serial.write(32);
Serial.write(32);

А еще лучче так (но это потом) :)
Код: Выделить всёРазвернуть
char MyBytes[3] = {15, 32, 32};    //массив из 3 байт со значениями 15,32,32
  Serial.write(MyBytes);           //выводит 3 символа с кодами 15,32,32

Т.к. в исходнике данные отправлялись одной функцией, а у нас получается куча строк, то эту кучу надо оформить гребаными фигурными скобочками. Т.е. получается так:
Код: Выделить всёРазвернуть
    if (ps2x.NewButtonState()) {        //будет TRUE если какая то кнопка изменила свой статус (Вкл. на Выкл. или Выкл. на Вкл.)
      if(ps2x.Button(PSB_L3))
      { // L3 нажата
        Serial.write(15);
        Serial.write(32);
        Serial.write(32);
      }
      if(ps2x.Button(PSB_R3))
        Serial.println("R3 pressed"); // R3 нажата
      if(ps2x.Button(PSB_L2))
        Serial.println("L2 pressed"); // L2 нажата
      if(ps2x.Button(PSB_R2))
        Serial.println("R2 pressed"); // R2 нажата
      if(ps2x.Button(PSB_TRIANGLE))
        Serial.println("Triangle pressed"); // Треугольник нажат     
    }


Компилим, заливаем, смотрим в терминалке, там будет хрень, т.к. данные стали не ASCII символы :) На будущее ищем хорошую терминалку, которая умеет отображать не только ASCII символу, но и любые байты. В линухе это moserial.
Шо мы получили? Мы отредактировали одну строку под наши нужды :)
Если теперь на 2-й дуине выкинуть блютуску, а tx первой дуины соединить с rx 2-й. То 2-я дуина начнет получать команды не через блютуску, а через 1-ю дуину в формате блютуски. Не забываем соединить земли обоих дуин. Осталось в первой дуине настроить скорость порта = скорости 2-й дуины. В PS2X_Example_RUS.ino заменить: "Serial.begin(57600);" на нужное значение, скорее всего на 9600. Жмем на джойстике кнопку влево и машинка резво (или нет) едет назад :)

Ой, чо-то сложно обьяснил :cry:
Аватара пользователя
Dmitry__
 
Сообщения: 8033
Зарегистрирован: 13 янв 2011, 15:25
Откуда: Санкт-Петербург

Re: соединение 2х ардуин

Сообщение Angel71 » 17 апр 2015, 17:26

:D ещё пару дней и доберётесь до пары строк на предыдущих страницах. там в первом варианте осталось добавить структуру, обьединение для сериализации и при желании перречисление для команд. во втором и добавлять ничего не нужно.
Последний раз редактировалось Angel71 17 апр 2015, 17:30, всего редактировалось 1 раз.
Аватара пользователя
Angel71
 
Сообщения: 10668
Зарегистрирован: 18 апр 2009, 22:18
Предупреждения: -1

Re: соединение 2х ардуин

Сообщение slom » 17 апр 2015, 17:55

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

вот под таким кодом:

Код: Выделить всёРазвернуть
// Скетч для управления через блютус, Wild Thumper 6WD, на ардуино совместимом контролере TREX controller. реализовано движение и стрельба с водомета, захват клешней манипулятором. 
// по вопросам и предложениям писать на почту slom1@list.ru
// новые фото и видео можно найти на www.шоуальянс.com

#include <BTCA2ALite.h>// Добавляем библиотеку блютус программы
#include <Servo.h> // Добавляем библиотеку серво

Servo myservoH; // Горизонтальная серва углы от 0 до 180 (центровка 89)
Servo myservoV; // Вертикальная серва углы от 1 до 45
Servo myservoZ; // серва Клешня
Servo myservoR; // серва рука клешни
const int Z_SERVO_PIN = 5; // добовляем пин захвата
const int R_SERVO_PIN = 6; // добовляем пин руки манипулятора
const int H_SERVO_PIN = 7; // Горизонтальная серва подключена к пину 7
const int V_SERVO_PIN = 8; //Пин вертикального сервопривода 8
const float Z_L_ANGLE = 116; // Максимальные угл поворота башни налево
const float Z_R_ANGLE = 45; // Максимальные угл поворота башни направо
const float Z_DEF_ANGLE = 50; // Дефолтный угол (центровка)
const float R_L_ANGLE = 178; // Максимальные угл поднятия руки
const float R_R_ANGLE = 3; // Максимальные угл наклона руки
const float R_DEF_ANGLE = 160; // Дефолтный угол руки
const float H_L_ANGLE = 180; // Максимальные угл поворота башни налево
const float H_R_ANGLE = 0; // Максимальные угл поворота башни направо
const float H_DEF_ANGLE = 84; // Дефолтный угол (центровка)
const float V_U_ANGLE = 140; // Максимальные угл поворота башни вверх
const float V_D_ANGLE = 45; // Максимальные угл поворота башни вниз
const float V_DEF_ANGLE = 60; // Дефолтный угол (центровка)
//Размер шага V_STEP и H_STEP побираем экспериментально для достижения нужной скорости поворота серв
const float V_STEP = 0.012; // Шаг - знаение отвечающее за скорость вращения по вертикали.
const float H_STEP = 0.012; // Шаг - знаение отвечающее за скорость вращения по горизонтали
const float Z_STEP = 0.012; // шаг захвата
const float R_STEP = 0.012; // шаг руки
float curVAngle = V_DEF_ANGLE; //Переменная текущего угла верт. сервы
float curHAngle = H_DEF_ANGLE; //Переменная текущего угла гор. сервы
float curZAngle = Z_DEF_ANGLE; //
float curRAngle = R_DEF_ANGLE; //
bool moveServoVUp = false; //Флаг движения верт. сервы вверх
bool moveServoVDown = false; //Флаг движения верт. сервы вниз
bool moveServoHLeft = false; //Флаг движения гор. сервы влево
bool moveServoHRight = false; //Флаг движения гор. сервы вправо
bool moveServoZLeft = false; //Флаг движения гор. сервы влево
bool moveServoZRight = false; //Флаг движения гор. сервы вправо
bool moveServoRLeft = false; //Флаг движения гор. сервы влево
bool moveServoRRight = false; //Флаг движения гор. сервы вправо

btca2aLite btca2aLite; // Конструктор btca2aLite


// задаем пины для левого мотора
#define Dir_L 2
#define Pwm_L 3
#define Brake_L 4
// задаем пины для правого мотора
#define Dir_R 10
#define Pwm_R 11
#define Brake_R 9

// Задаем скорости для движения
byte MaxSpeed = 230; // Максимальная скорость
byte MinSpeed = 90;  // Минимальная скорость

int forw_back = 0;
int righ_left = 0;

byte step_fb = 5;     // Шаг изменения скорости движения вперед - назад
byte step_stop = 10;  // Шаг изменения скорости остановки
byte step_rl =  10;    // Шаг изменения скорости движения вправо - влево
byte step_dir = 10;   // Шаг изменения скорости выравнивания



#define SHOT  12 // пин для водомета

enum States
{
    WAITING,
    READING,
    RUNNING,
    ERROR,
    TIMEOUT
};

States state;
States onWait();
States onRead();
States onRun();
States onError();

States onTimeout();

void performServo(); // добовляем сервы


void setup(){
    Serial.begin(9600); // Скорость BT и порта должна быть 9600
    //Моторы
    pinMode (Pwm_L, OUTPUT);
    pinMode (Dir_L, OUTPUT);
    pinMode (Brake_L, OUTPUT);
   
    pinMode (Pwm_R, OUTPUT);
    pinMode (Dir_R, OUTPUT);
    pinMode (Brake_R, OUTPUT);
   
    digitalWrite (Pwm_L, LOW);
    digitalWrite (Pwm_R, LOW);
   
    digitalWrite (Brake_L, LOW);
    digitalWrite (Brake_R, LOW);
 
pinMode(SHOT, OUTPUT); // задаем выход для стрельбы водой
   
    // устанавливаем пин как вывод управления сервой
    myservoH.attach(H_SERVO_PIN);
    myservoV.attach(V_SERVO_PIN);
    myservoZ.attach(Z_SERVO_PIN);
    myservoR.attach(R_SERVO_PIN);
    myservoH.write(curHAngle);
    myservoV.write(curVAngle);
    myservoZ.write(curZAngle);
    myservoR.write(curRAngle);
   
    //Светодиод
    pinMode(13, OUTPUT); // Инициализируем пин светодиода
    digitalWrite(13, HIGH); // Светодиод выключен
}

void loop(){
   
    btca2aLite.ReadCommand(); // Считывание принятых команд (кодов кнопок)
    //Вызываем функцию управление сервами
    performServo();
   
//этот код для меня темный лес, мне его дали для плавного старта и торможения моторов. если ехать вперед и резко нажать кнопку назад, машина продолжит ехать вперед, плавно остановиться и только потом поедет назад, это спасает редуктора от разрушения.
//если ктото знает что тут к чему, прокоментируйте пожалуйста, чтоб я тоже понимал :)
  static unsigned long pre_millis = 0;
  if(millis()-pre_millis > 50)
  {
    pre_millis = millis();
   
    if(btca2aLite.ButtonPressed(KEYCODE_DPAD_UP))
    {
      forw_back += step_fb;
      if(forw_back > 0 && forw_back < MinSpeed) forw_back = MinSpeed;
    }
    else if(btca2aLite.ButtonPressed(KEYCODE_DPAD_DOWN))
    {
      forw_back -= step_fb;
      if(forw_back < 0 && forw_back > MinSpeed*-1) forw_back = MinSpeed*-1;
    }
    else
    {
      if(forw_back < 0) forw_back += step_stop;
      else if(forw_back > 0) forw_back -= step_stop;
      if(abs(forw_back) < MinSpeed) forw_back = 0;
    }
    forw_back = constrain(forw_back, MaxSpeed*-1, MaxSpeed);


    if(btca2aLite.ButtonPressed(KEYCODE_DPAD_RIGHT))
    {
      righ_left += step_rl;
      if(righ_left > 0 && righ_left < MinSpeed) righ_left = MinSpeed;
    }
    else if(btca2aLite.ButtonPressed(KEYCODE_DPAD_LEFT))
    {
      righ_left -= step_rl;
      if(righ_left < 0 && righ_left > MinSpeed*-1) righ_left = MinSpeed*-1;
    }
    else
    {
      if(righ_left < 0) righ_left += step_dir;
      else if(righ_left > 0) righ_left -= step_dir;
      if(abs(righ_left) < MinSpeed) righ_left = 0;
    }
    righ_left = constrain(righ_left, MaxSpeed*-1, MaxSpeed);


    int pwm_l = forw_back + righ_left;
    int pwm_r = forw_back - righ_left;
    pwm_l = constrain(pwm_l, MaxSpeed*-1, MaxSpeed);
    pwm_r = constrain(pwm_r, MaxSpeed*-1, MaxSpeed);

    digitalWrite(Dir_L, (pwm_l<0)?0:1);
    digitalWrite(Dir_R, (pwm_r<0)?0:1);
    analogWrite(Pwm_L, abs(pwm_l));
    analogWrite(Pwm_R, abs(pwm_r));
  }
       
  //дальше идут кнопки управления
   
    //-------— включение насоса —-------------
   if (btca2aLite.ButtonPressed(KEYCODE_BUTTON_SELECT))
    {
     digitalWrite (SHOT, HIGH);
     }
    //-------— выключение насоса происходит автоматически после отпускания кнопки—-------------
   if(btca2aLite.ButtonReleased(KEYCODE_BUTTON_SELECT))
    {
   digitalWrite (SHOT, LOW);
    }
   
        if(btca2aLite.Button(KEYCODE_BUTTON_START)) // алгоритм автоматического хватания предметов
    {
       
/* шаг вперед, отключил....
      digitalWrite (Dir_L, HIGH);
      analogWrite (Pwm_L, 150);
      digitalWrite (Dir_R, HIGH);
      analogWrite (Pwm_R, 150);
      delay (100);
      // потом стоп
      analogWrite (Pwm_L, 0);
      analogWrite (Pwm_R, 0);
      delay (500);
*/
     
       myservoZ.write(45);; // Клешня разжимается
        myservoR.write(3);; // рука клешни опускаем
        delay(2000); /* ждем 2 секунды, */
         myservoZ.write(116);; // Клешня сжимаем
         delay(1000); /* ждем 1 секунду, */
          myservoR.write(170);; // рука клешни поднимаем
           delay(1000); /* ждем  */
           myservoZ.write(45);; // Клешня разжимаем
    }
   
   
    //--------— Повороты серв при нажатии кнопок —-------------
   
    if(btca2aLite.Button(KEYCODE_BUTTON_X)) // поворот водомета вниз
    {
        moveServoVDown = true;
             
    }
    if(btca2aLite.Button(KEYCODE_BUTTON_A)) // поворот водомета направо
    {
        moveServoHRight = true;
    }
    if(btca2aLite.Button(KEYCODE_BUTTON_B)) // поворот водомета вверх
    {
        moveServoVUp = true;
             
    }
   
    if(btca2aLite.Button(KEYCODE_BUTTON_Y)) // поворот водомета налево
    {
        moveServoHLeft = true;
    }
   
        if(btca2aLite.Button(KEYCODE_BUTTON_R1)) // зхахват сжать
    {
        moveServoZLeft = true;
    }
    if(btca2aLite.Button(KEYCODE_BUTTON_R2)) // захват разжать
    {
        moveServoZRight = true;
    }
   
   
           if(btca2aLite.Button(KEYCODE_BUTTON_L1)) // рука клешни вниз
    {
        moveServoRLeft = true;
    }
    if(btca2aLite.Button(KEYCODE_BUTTON_L2)) // рука клешни вверх
    {
        moveServoRRight = true;
    }
   
   
//--------— чтобы сервы не продолжали движения при отжатых кнопках —-------------   
if(btca2aLite.ButtonReleased(KEYCODE_BUTTON_X))
{
moveServoVDown = false;
}
if(btca2aLite.ButtonReleased(KEYCODE_BUTTON_B))
{
moveServoVUp = false;
}

if(btca2aLite.ButtonReleased(KEYCODE_BUTTON_A))
{
moveServoHRight = false;
}
if(btca2aLite.ButtonReleased(KEYCODE_BUTTON_Y))
{
moveServoHLeft = false;
}

if(btca2aLite.ButtonReleased(KEYCODE_BUTTON_R2))
{
moveServoZRight = false;
}
if(btca2aLite.ButtonReleased(KEYCODE_BUTTON_R1))
{
moveServoZLeft = false;
}   
   
if(btca2aLite.ButtonReleased(KEYCODE_BUTTON_L2))
{
moveServoRRight = false;
}
if(btca2aLite.ButtonReleased(KEYCODE_BUTTON_L1))
{
moveServoRLeft = false;
}       
   
   
    //----------------— Стоп —---------------------
   
    // Если не нажата ни одна кнопка курсора происходит остановка, скорость 0 для каждого мотора
    if (btca2aLite.ButtonReleased(KEYCODE_DPAD_UP) && btca2aLite.ButtonReleased(KEYCODE_DPAD_DOWN) && btca2aLite.ButtonReleased(KEYCODE_DPAD_LEFT) && btca2aLite.ButtonReleased(KEYCODE_DPAD_RIGHT)){
        analogWrite (Pwm_L, 0);
        analogWrite (Pwm_R, 0);
    }
}



//Функция управления сервоприводами (вызывается в теле loop на каждой итерации)
//Выполняет изменения положения серв на подобранный шаг согласно установленным флагам движения
//Флаги устанавливаются согласно поступившим символам управления сервами
void performServo()
{
    //Установлен флаг движения вверх и текущий угол не максимальный
    if (moveServoVUp && curVAngle + V_STEP <= V_U_ANGLE)
    {
        //К текущему верт. углу прибавляем шаг
        curVAngle += V_STEP;
    }
    //Установлен флаг движения вниз и текущий угол не минимален
    else if (moveServoVDown && curVAngle - V_STEP >= V_D_ANGLE)
    {
        //От текущего верт. угла отнимаем шаг
        curVAngle -= V_STEP;
    }
    //Установлен флаг движения влево и текущий угол не максимален
    if (moveServoHLeft && curHAngle + H_STEP <= H_L_ANGLE)
    {
        //К текущему гор. углу прибавляем гор. шаг
        curHAngle += H_STEP;
    }
    //Установлен флаг движения вправо и текущий угол не минимален
    else if (moveServoHRight && curHAngle - H_STEP >= H_R_ANGLE)
    {
        //От текущего угла отнимаем гор. шаг
        curHAngle -= H_STEP;
    }
   
    //Установлен
    if (moveServoZLeft && curZAngle + Z_STEP <= Z_L_ANGLE)
    {
        //К текущему гор. углу прибавляем гор. шаг
        curZAngle += Z_STEP;
    }
    //Установлен флаг движения вправо и текущий угол не минимален
    else if (moveServoZRight && curZAngle - Z_STEP >= Z_R_ANGLE)
    {
        //От текущего угла отнимаем гор. шаг
        curZAngle -= Z_STEP;
    }
   
   
        //Установлен
    if (moveServoRLeft && curRAngle + R_STEP <= R_L_ANGLE)
    {
        //К текущему гор. углу прибавляем гор. шаг
        curRAngle += R_STEP;
    }
    //Установлен флаг движения вправо и текущий угол не минимален
    else if (moveServoRRight && curRAngle - R_STEP >= R_R_ANGLE)
    {
        //От текущего угла отнимаем гор. шаг
        curRAngle -= R_STEP;
    }
   
    //Если было движние по вертикали
    if (moveServoVUp || moveServoVDown)
    {
        myservoV.write(curVAngle);
    }
    //Если было движение по горизонтали
    if (moveServoHLeft || moveServoHRight)
    {
        myservoH.write(curHAngle);
    }
   
    if (moveServoZLeft || moveServoZRight)
    {
        myservoZ.write(curZAngle);
    }
   
        if (moveServoRLeft || moveServoRRight)
    {
        myservoR.write(curRAngle);
    }
}



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

еще у меня был более простой код для моторов, даже с переключением скоростей :):

Код: Выделить всёРазвернуть
// Скетч для управления через блютус, Wild Thumper 6WD, на ардуино совместимом контролере TREX controller. реализовано движение и стрельба с водомета. 


#include <BTCA2ALite.h>// Добавляем библиотеку блютус программы
#include <Servo.h> // Добавляем библиотеку серво

Servo myservoH; // Горизонтальная серва углы от 0 до 180 (центровка 89)
Servo myservoV; // Вертикальная серва углы от 1 до 45
const int H_SERVO_PIN = 7; // Горизонтальная серва подключена к пину 7
const int V_SERVO_PIN = 8; //Пин вертикального сервопривода 8
const float H_L_ANGLE = 180; // Максимальные угл поворота башни налево
const float H_R_ANGLE = 0; // Максимальные угл поворота башни направо
const float H_DEF_ANGLE = 89; // Дефолтный угол (центровка)
const float V_U_ANGLE = 45; // Максимальные угл поворота башни вверх
const float V_D_ANGLE = 0; // Максимальные угл поворота башни вниз
const float V_DEF_ANGLE = 15; // Дефолтный угол (центровка)
//Размер шага V_STEP и H_STEP побираем экспериментально для достижения нужной скорости поворота серв
const float V_STEP = 0.012; // Шаг - знаение отвечающее за скорость вращения по вертикали.
const float H_STEP = 0.012; // Шаг - знаение отвечающее за скорость вращения по горизонтали
float curVAngle = V_DEF_ANGLE; //Переменная текущего угла верт. сервы
float curHAngle = H_DEF_ANGLE; //Переменная текущего угла гор. сервы
bool moveServoVUp = false; //Флаг движения верт. сервы вверх
bool moveServoVDown = false; //Флаг движения верт. сервы вниз
bool moveServoHLeft = false; //Флаг движения гор. сервы влево
bool moveServoHRight = false; //Флаг движения гор. сервы вправо

btca2aLite btca2aLite; // Конструктор btca2aLite

// Задаем скорости для движения
int Speed = 80; // Текущая максимальная скорость
int TSpeed = 150; // Скорость медленного мотора при повороте
int RLSpeed = 200; // Скорость танкоаого разворота

// задаем пины для левого мотора
#define Dir_L 2
#define Pwm_L 3
#define Brake_L 4
// задаем пины для правого мотора
#define Dir_R 10
#define Pwm_R 11
#define Brake_R 9

#define SHOT  12 // пин для водомета

enum States
{
    WAITING,
    READING,
    RUNNING,
    ERROR,
    TIMEOUT
};

States state;
States onWait();
States onRead();
States onRun();
States onError();

States onTimeout();

void performServo(); // добовляем сервы


void setup(){
    Serial.begin(9600); // Скорость BT и порта должна быть 9600
    //Моторы
    pinMode (Pwm_L, OUTPUT);
    pinMode (Dir_L, OUTPUT);
    pinMode (Brake_L, OUTPUT);
   
    pinMode (Pwm_R, OUTPUT);
    pinMode (Dir_R, OUTPUT);
    pinMode (Brake_R, OUTPUT);
   
    digitalWrite (Pwm_L, LOW);
    digitalWrite (Pwm_R, LOW);
   
    digitalWrite (Brake_L, LOW);
    digitalWrite (Brake_R, LOW);
 
pinMode(SHOT, OUTPUT); // задаем выход для стрельбы водой
   
    // устанавливаем пин как вывод управления сервой
    myservoH.attach(H_SERVO_PIN);
    myservoV.attach(V_SERVO_PIN);
    myservoH.write(curHAngle);
    myservoV.write(curVAngle);
   
   
    //Светодиод
    pinMode(13, OUTPUT); // Инициализируем пин светодиода
    digitalWrite(13, HIGH); // Светодиод выключен
}

void loop(){
   
    btca2aLite.ReadCommand(); // Считывание принятых команд (кодов кнопок)
    //Вызываем функцию управление сервами
    performServo();
   
   
   
    //--------— Движение Вперед —-------------
    if (btca2aLite.ButtonPressed(KEYCODE_DPAD_UP)) // Едет вперед если нажат курсор ВПЕРЕД
    {
        if (btca2aLite.ButtonPressed(KEYCODE_DPAD_RIGHT)){ // Поворот направо при нажатии курсора ВПЕРЕД и ВЛЕВО
            digitalWrite (Dir_L, HIGH);
            analogWrite (Pwm_L, TSpeed);
            digitalWrite (Dir_R, HIGH);
            analogWrite (Pwm_R, Speed);
        }
        if (btca2aLite.ButtonPressed(KEYCODE_DPAD_LEFT)){ // Поворот налево при нажатии курсора ВПЕРЕД и ВПРАВО
            digitalWrite (Dir_L, HIGH);
            analogWrite (Pwm_L, Speed);
            digitalWrite (Dir_R, HIGH);
            analogWrite (Pwm_R, TSpeed);
        }
        digitalWrite (Dir_L, HIGH);
        analogWrite (Pwm_L, Speed);
        digitalWrite (Dir_R, HIGH);
        analogWrite (Pwm_R, Speed);
    }
   
    //-------— Движение Назад —-------------
    if (btca2aLite.ButtonPressed(KEYCODE_DPAD_DOWN)) // Едет назад если нажат курсор НАЗАД
    {
        if (btca2aLite.ButtonPressed(KEYCODE_DPAD_RIGHT)){ // Поворот налево при нажатии курсора НАЗАД и ВЛЕВО
            digitalWrite (Dir_L, LOW);
            analogWrite (Pwm_L, TSpeed);
            digitalWrite (Dir_R, LOW);
            analogWrite (Pwm_R, Speed);
        }
        if (btca2aLite.ButtonPressed(KEYCODE_DPAD_LEFT)){ // Поворот направо при нажатии курсора НАЗАД и ВПРАВО
            digitalWrite (Dir_L, LOW);
            analogWrite (Pwm_L, Speed);
            digitalWrite (Dir_R, LOW);
            analogWrite (Pwm_R, TSpeed);
        }
        digitalWrite (Dir_L, LOW);
        analogWrite (Pwm_L, Speed);
        digitalWrite (Dir_R, LOW);
        analogWrite (Pwm_R, Speed);
    }
   
    //-------— Движение Влево (Танковый разворот) —-------------
    if (btca2aLite.ButtonPressed(KEYCODE_DPAD_LEFT )) // Едет вперед если нажат курсор ВПЕРЕД
    {
        digitalWrite (Dir_L, LOW);
        analogWrite (Pwm_L, RLSpeed);
        digitalWrite (Dir_R, HIGH);
        analogWrite (Pwm_R, RLSpeed);
    }
   
    //-------— Движение Вправо (Танковый разворот) —-------------
    if (btca2aLite.ButtonPressed(KEYCODE_DPAD_RIGHT)) // Едет вперед если нажат курсор ВПЕРЕД
    {
        digitalWrite (Dir_L, HIGH);
        analogWrite (Pwm_L, RLSpeed);
        digitalWrite (Dir_R, LOW);
        analogWrite (Pwm_R, RLSpeed);
    }
   
    //-------— движение в право —-------------
    if (btca2aLite.ButtonPressed(KEYCODE_DPAD_RIGHT)) // Едет вперед если нажат курсор ВПЕРЕД
    {
        digitalWrite (Dir_L, HIGH);
        analogWrite (Pwm_L, RLSpeed);
        digitalWrite (Dir_R, LOW);
        analogWrite (Pwm_R, RLSpeed);
    }
   
   
    //---------- Переключение скоростей —-------------


   if(btca2aLite.Button(KEYCODE_BUTTON_START)) // ТУРБО режимпри нажатии кнопки START
   {
   Speed = 200;
   }
   if(btca2aLite.Button(KEYCODE_BUTTON_R2)) // 4-я Скорость при нажатии кнопки R2
   {
   Speed = 150;
   }
   if(btca2aLite.Button(KEYCODE_BUTTON_R1)) // 3-я Скорость при нажатии кнопки R1
   {
   Speed = 120;
   }
   if(btca2aLite.Button(KEYCODE_BUTTON_L2)) // 2-я Скорость при нажатии кнопки L2
   {
   Speed = 90;
   }
   if(btca2aLite.Button(KEYCODE_BUTTON_L1)) // 1-я Скорость при нажатии кнопки L2
   {
   Speed = 70;
   }
   
    //-------— включение насоса —-------------
   if (btca2aLite.ButtonPressed(KEYCODE_BUTTON_SELECT))
    {
     digitalWrite (SHOT, HIGH);
     }
    //-------— выключение насоса происходит автоматически после отпускания кнопки—-------------
   if(btca2aLite.ButtonReleased(KEYCODE_BUTTON_SELECT))
    {
   digitalWrite (SHOT, LOW);
    }
   
   
    //--------— Повороты серв при нажатии кнопок —-------------
   
    if(btca2aLite.Button(KEYCODE_BUTTON_X)) // servoV вниз
    {
        moveServoVDown = true;
             
    }
    if(btca2aLite.Button(KEYCODE_BUTTON_A)) // servoH движется к 0
    {
        moveServoHRight = true;
    }
    if(btca2aLite.Button(KEYCODE_BUTTON_B)) // servoV вверх
    {
        moveServoVUp = true;
             
    }
   
    if(btca2aLite.Button(KEYCODE_BUTTON_Y)) // servoH движется к 180
    {
        moveServoHLeft = true;
    }
   
//--------— чтобы сервы не продолжали движения при отжатых кнопках —-------------   
if(btca2aLite.ButtonReleased(KEYCODE_BUTTON_X))
{
moveServoVDown = false;
}
if(btca2aLite.ButtonReleased(KEYCODE_BUTTON_B))
{
moveServoVUp = false;
}

if(btca2aLite.ButtonReleased(KEYCODE_BUTTON_A))
{
moveServoHRight = false;
}
if(btca2aLite.ButtonReleased(KEYCODE_BUTTON_Y))
{
moveServoHLeft = false;
}
   
   
    //----------------— Стоп —---------------------
   
    // Если не нажата ни одна кнопка курсора происходит остановка, скорость 0 для каждого мотора
    if (btca2aLite.ButtonReleased(KEYCODE_DPAD_UP) && btca2aLite.ButtonReleased(KEYCODE_DPAD_DOWN) && btca2aLite.ButtonReleased(KEYCODE_DPAD_LEFT) && btca2aLite.ButtonReleased(KEYCODE_DPAD_RIGHT)){
        analogWrite (Pwm_L, 0);
        analogWrite (Pwm_R, 0);
    }
}



//Функция управления сервоприводами (вызывается в теле loop на каждой итерации)
//Выполняет изменения положения серв на подобранный шаг согласно установленным флагам движения
//Флаги устанавливаются согласно поступившим символам управления сервами
void performServo()
{
    //Установлен флаг движения вверх и текущий угол не максимальный
    if (moveServoVUp && curVAngle + V_STEP <= V_U_ANGLE)
    {
        //К текущему верт. углу прибавляем шаг
        curVAngle += V_STEP;
    }
    //Установлен флаг движения вниз и текущий угол не минимален
    else if (moveServoVDown && curVAngle - V_STEP >= V_D_ANGLE)
    {
        //От текущего верт. угла отнимаем шаг
        curVAngle -= V_STEP;
    }
    //Установлен флаг движения влево и текущий угол не максимален
    if (moveServoHLeft && curHAngle + H_STEP <= H_L_ANGLE)
    {
        //К текущему гор. углу прибавляем гор. шаг
        curHAngle += H_STEP;
    }
    //Установлен флаг движения вправо и текущий угол не минимален
    else if (moveServoHRight && curHAngle - H_STEP >= H_R_ANGLE)
    {
        //От текущего угла отнимаем гор. шаг
        curHAngle -= H_STEP;
    }
   
    //Если было движние по вертикали
    if (moveServoVUp || moveServoVDown)
    {
        myservoV.write(curVAngle);
    }
    //Если было движение по горизонтали
    if (moveServoHLeft || moveServoHRight)
    {
        myservoH.write(curHAngle);
    }
}


эти оба кода запинены под тирекс. и управляються через блютус BTCA2A приложением в телефоне
Изображение

новый блютус модуль со старым кодом никак не связан, его я подцепил на ардуино нано.
для него идет спец библиотека... ну вы вкурсе...

насчет кода, смотрю на него как баран на апельсины, понимаю что наверное вкусно, но что бы шкурку почистить рук нет :D

терминалка у меня есть наз термите 3.1 - подойдет?

Код: Выделить всёРазвернуть
Ой, чо-то сложно обьяснил
:lol: не ну оно то все понятно, сама суть так скажем. то что можно обмануть тирекс контролер, посылая на него команды потипу как это делает обычный блютус модуль потипу hc-06
но не сложно ли это? я думал можно както попроще...
например при нажатии на джойстике кнопки вперед, посылать чтото типо текста "vpered" а на 2й дуине зарание задать список команд, если принятая "vpered" есть в списке то выполнить действие к ней привязанное...

как бы по сути тоже самое что у вас но без заморочки с калькулятором. к томуже подвох в том что те команды из TREX_controller у меня в него не залиты. он про них не в курсе. а заливать всю ту требуху на 100500 страниц кода, чтото нехочеться. т.к в нем в последствии я точно ничего не поменяю, там все сложно... :cry:



ангел - чертяка умный, но такой вредный... :ROFL:
ещё пару дней и доберётесь до тех несчастных пары строк на предыдущих страницах. в первом варианте там осталось только структуру сделать и обьединение для сериализации, во втором вообще ничего добавлять не нужно.


Добавлено спустя 18 минут 18 секунд:
а что насчет EasyTransfer.

http://arduino.ru/forum/programmirovani ... sytransfer

Добавлено спустя 9 минут 25 секунд:
вот что еще нашел. по сути то что надо?
ну почти, они 2мя кнопками на 1й дуине зажигают 2 светодиода на другой дуине...
http://www.bajdi.com/serial-communicati ... r-library/
Аватара пользователя
slom
 
Сообщения: 645
Зарегистрирован: 07 сен 2014, 19:29
Откуда: Севастополь
Skype: slom_3d
прог. языки: 3d max :)

Re: соединение 2х ардуин

Сообщение Dmitry__ » 17 апр 2015, 17:58

slom писал(а):но не сложно ли это? я думал можно както попроще...
например при нажатии на джойстике кнопки вперед, посылать чтото типо текста "vpered" а на 2й дуине зарание задать список команд, если принятая "vpered" есть в списке то выполнить действие к ней привязанное...

Протоколы пишут не дураки. Интерпретация данных простых на вид протоколов может быть в разы сложнее. Например твое изобретение "vpered" (а ведь следующее будет "nazad" :) ) будет иметь разную длину данных, вот тебе уже сложность интерпретации данных. А управление в трексе сделано правильно - 1 байт - одна переменная для одного двигателя. Среднее значение байта: 128 - двигатель остановлен. Все что <128 - движение назад с изменяемой мощностью. Все что >128 - соотв. движение вперед. Такие данные выдают аналоговые джойстики. Т.е. не надо перекодировать:
Код: Выделить всёРазвернуть
Данные: 128
128 - 128 = 0.
Значит посылаем команду "stop"
Данные: 129
129 - 128 = 1
Ага, число положительное, значит посылаем команду "wpered"
Потом посылаем "1"
Данные: 100
100 - 128
Ага, число отрицательно,  значит посылаем команду "nazad"
Теперь надо преобразовать данные из дополнительной формы или поменять порядок вычитаемых данных:
128 - 100 = 28
Послать 28

А теперь сравни это с:
Код: Выделить всёРазвернуть
Принять число от джойстика
Послать байт на 2-ю дуину.

Ну? Где лучче? :)
Это я еще не рассматриваю интерпретацию данных 2-й дуиной. Что проще? Написать свой протокол и его интерпретатор или выяснить какой протокол у приемной стороны? :)
Все начинающие программисты начинают с: "надо тут все сломать"
Аватара пользователя
Dmitry__
 
Сообщения: 8033
Зарегистрирован: 13 янв 2011, 15:25
Откуда: Санкт-Петербург

Re: соединение 2х ардуин

Сообщение slom » 17 апр 2015, 18:07

ладно убедили! но "vpered" смотрелось круче, и чтоб флаг развивался :)

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

Код: Выделить всёРазвернуть
/*This is an example of the EasyTransfer Library 2way communications. 

This sketch is for the Arduino with the servo attached to pin 9.

The other Arduino has a potentiometer attached to analog pin 0.
Both have a putton attached to pin 12 and output a status using the LED on pin 13.

The idea is each arduino will read the status of the button attached to it, and send it
to the other Arduino, which will toggle it's LED based on the others button. The button
should connect pin 12 to ground when pushed.

And the Arduino with the potentiometer will send it's value to the one with the servo.
The servo will move to the position based on the potentiometer.
*/

#include <Servo.h>
#include <EasyTransfer.h>

//create two objects
EasyTransfer ETin, ETout;
//create servo
Servo myservo;

struct RECEIVE_DATA_STRUCTURE{
  //put your variable definitions here for the data you want to receive
  //THIS MUST BE EXACTLY THE SAME ON THE OTHER ARDUINO
  int buttonstate;
  int servoval;
};

struct SEND_DATA_STRUCTURE{
  //put your variable definitions here for the data you want to receive
  //THIS MUST BE EXACTLY THE SAME ON THE OTHER ARDUINO
  int buttonstate;
};


//give a name to the group of data
RECEIVE_DATA_STRUCTURE rxdata;
SEND_DATA_STRUCTURE txdata;


void setup(){
  Serial.begin(9600);
  //start the library, pass in the data details and the name of the serial port. Can be Serial, Serial1, Serial2, etc.
  ETin.begin(details(rxdata), &Serial);
  ETout.begin(details(txdata), &Serial);
 
  pinMode(13, OUTPUT); 
  pinMode(12, INPUT);
  //enable pull-up
  digitalWrite(12, HIGH);
 
  myservo.attach(9);
}

void loop(){
 
  //first, lets read our button and store it in our data structure
  if(!digitalRead(12))
    txdata.buttonstate = HIGH;
  else
    txdata.buttonstate = LOW;
 
//then we will go ahead and send that data out
  ETout.sendData();
 
//there's a loop here so that we run the recieve function more often then the
//transmit function. This is important due to the slight differences in
//the clock speed of different Arduinos. If we didn't do this, messages
//would build up in the buffer and appear to cause a delay.

  for(int i=0; i<5; i++){
    //remember, you could use an if() here to check for new data, this time it's not needed.
    ETin.receiveData();
   
    //set our LED on or off based on what we received from the other Arduino
    digitalWrite(13, rxdata.buttonstate);
   
    //set our servo position based on what we received from the other Arduino
    //we will also map the ADC value to a servo value
    myservo.write(map(rxdata.servoval, 0, 1023, 0, 179));
   
    //delay
    delay(10);
  }
 
  //delay for good measure
  delay(10);
}
Аватара пользователя
slom
 
Сообщения: 645
Зарегистрирован: 07 сен 2014, 19:29
Откуда: Севастополь
Skype: slom_3d
прог. языки: 3d max :)

Re: соединение 2х ардуин

Сообщение Dmitry__ » 17 апр 2015, 18:20

Ты прекрати искать всякие коды. А то зайдет angel и выпилит тебя, кста за дело :)
Сядь у своей тарантайки, определись что должна делать основная плата и какой для нее есть самый полный код. Ведь у тебя явно не хватит опыта для грамотного управления двигателями. Или покажи свой вариант программы основной платы, которая не пойдет в помойку через 2 дня из-за морального устаревания. Обычно, люди помогают 1.5 раза, дальше энтузиазм иссякает, превед angel :)
Аватара пользователя
Dmitry__
 
Сообщения: 8033
Зарегистрирован: 13 янв 2011, 15:25
Откуда: Санкт-Петербург

Пред.След.

Вернуться в Arduino и другие Xduino

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 12