Подключение к р/у автомобилю Arduino, а также USB-руля и педалей Logitech Momo Racing 2004

Тема в разделе "Arduino & Shields", создана пользователем M0ln1a, 11 фев 2017.

  1. mcureenab

    mcureenab Гуру

    Дополнительные контакты сделаны для подключения модулей типа таких https://store.arduino.cc/product/K000001

    У Амперки другой стандарт модулей. Так что все зависит от того, какие модули вам больше нравятся. В прочем эти разъемы только дублируют стандартные пины.
     
  2. M0ln1a

    M0ln1a Гик

    Ладно... Российскую или китайскую плату посоветуете?
     
  3. M0ln1a

    M0ln1a Гик

    Вскрыл я руль, обнаружил там лишние детали) Похоже, что его можно регулировать, переставляя ручку КП справа налево и наоборот! Итог: 2 лишние кнопки и шлейф из проводов)
    Вообще конструкция интересная: как я понял, руль сначала проверяется на то, стоит ли он ровно, и если он отклонен, то только тогда проверяет куда именно. Фото кидаю в общую папку! https://drive.google.com/open?id=0Bx6XCuT9H9a3b3duMzRTOUdVU2s
     
  4. M0ln1a

    M0ln1a Гик

    [​IMG]
    Шлейфы:
    справа 2 3ех проводных шлейфа, верхний к датчику у руля, а нижний к рычагу КП
    левее 5ти проводной - ведет к датчику около мотора в левой половине руля
    10ти проводной к самому рулю
    левее 2ух проводной - питание мотора
    крайний левый - питание руля
    5ти проводной сверху - usb
     
  5. M0ln1a

    M0ln1a Гик

    Фото не открывается... Фотография 0022 в папке
     
  6. M0ln1a

    M0ln1a Гик

    После вскрытия понял... Вы были правы! Педали к рулю подсоединяются, а от руля уже к компьютеру по USB
    Извиняюсь за неверные данные...
     
  7. mcureenab

    mcureenab Гуру

    Ну и отлично! Руль к ПК подключается и определяется как USB HID устройство?
    https://ru.wikipedia.org/wiki/USB_HID
     
  8. mcureenab

    mcureenab Гуру

    Пока вижу такие пути.
    1. Рисовать драйвер для Arduino с USB Host шилдом и управлять пультом машинки. Пока я вижу темный лес.
    2. Подключать руль и ардуино к компьютеру. Программой на компьютере через стандартный драйвер принимать данные от руля и через ардуино рулить пультом машинки. Тут будет проще найти руководства и примеры, потому как на уровне USB мало кто работает.

    PS. Судя по пульту у самой машинки есть только руль и курок газ-тормоз. Вероятно самым простым будет подключить датчики руля и педалей вместо датчиков руля и курка на пульте машинки через согласующие схемы. Руль и курок на пульте скорее всего обычные потенциометры с которых снимается напряжение.
    Педаль тоже потенциометр. Руль не знаю.
     
  9. M0ln1a

    M0ln1a Гик

    На пульте также стоит 2 регулятора:
    1) начальное направление
    2) максимальная скорость

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

    M0ln1a Гик

    Как я понял, дело это сложное... Нехочется с компьютера управлять, в том то и дело... А драйвера вообще возможно так создать?
     
  11. M0ln1a

    M0ln1a Гик

    Оо, вот что я в книге нашел про это дело: в библиотеке USB_Host есть пример USB_HID_Desc.pde, с помощью которого можно сделать description report hid-устройства!
    С помощью этого примера и создали скетч под руль Defender.
    Даже драйвера получается не нужны...
    Вот только теперь бы этот код разобрать, я его пролистываю, и ничего пока что серьёзного не понял
     
  12. M0ln1a

    M0ln1a Гик

    Вот код для приема команд (у меня не такой передатчик)
    Код (C++):
    // передатчик - HK-T6A
    // приемник :
    // Ch1 - Rudder (руль направления, рыскание, YAW)
    // Ch2 - Elevator (тангаж, PITCH)
    // Ch3 - Throttle (газ)
    // Ch4 - Aileron (элероны, ROLL)


    unsigned long Ch1Value,Ch2Value,Ch3Value,Ch4Value;
    unsigned long last1,last2,last3,last4;
    int pinCh1=11;
    int pinCh2=10;
    int pinCh3=9;
    int pinCh4=8;

    void setup()
    {
      Serial.begin(9600);
      Serial.println("Ready");
      pinMode (pinCh1, INPUT); // вход Rx channel 1 на чтение
      pinMode (pinCh2, INPUT); // вход Rx channel 2 на чтение
      pinMode (pinCh3, INPUT); // вход Rx channel 3 на чтение
      pinMode (pinCh4, INPUT); // вход Rx channel 4 на чтение
      last1 = pulseIn (pinCh1, HIGH); //чтение данных RC channel 1
      last2 = pulseIn (pinCh2, HIGH); //чтение данных RC channel 2
      last3 = pulseIn (pinCh3, HIGH); //чтение данных RC channel 3
      last4 = pulseIn (pinCh4, HIGH); //чтение данных RC channel 4
      }

    void loop()
    {
      //
      Ch1Value = pulseIn (pinCh1, HIGH, 20000); //чтение данных RC channel 1
      if (Ch1Value == 0) {Ch1Value = last1;}
      else {last1 = Ch1Value;}
      Serial.print ("  Ch1: ");Serial.print (Ch1Value);
      //
      Ch2Value = pulseIn (pinCh2, HIGH, 20000); //чтение данных RC channel 2
      if (Ch2Value == 0) {Ch2Value = last2;}
      else {last2 = Ch2Value;}
      Serial.print("  Ch2: ");Serial.print (Ch2Value);
      //
      Ch3Value = pulseIn (pinCh3, HIGH, 20000); //чтение данных RC channel 3
      if (Ch3Value == 0) {Ch3Value = last3;}
      else {last3 = Ch3Value;}
      Serial.print("  Ch3: ");Serial.print (Ch3Value);
      //
      Ch4Value = pulseIn (pinCh4, HIGH, 20000); //чтение данных RC channel 4
      if (Ch4Value == 0) {Ch4Value = last4;}
      else {last4 = Ch4Value;}
      Serial.print("  Ch4: ");Serial.print (Ch4Value);
      Serial.println("");

    }
    Вот это для руля:
    Код (C++):
    #include <avr/pgmspace.h>

    #include <avrpins.h>
    #include <max3421e.h>
    #include <usbhost.h>
    #include <usb_ch9.h>
    #include <Usb.h>
    #include <usbhub.h>
    #include <avr/pgmspace.h>
    #include <address.h>
    #include <hid.h>
    #include <hiduniversal.h>

    #include "hidjoystickrptparser.h"

    #include <printhex.h>
    #include <message.h>
    #include <hexdump.h>
    #include <parsetools.h>

    USB                                             Usb;
    USBHub                                          Hub(&Usb);
    HIDUniversal                                    Hid(&Usb);
    JoystickEvents                                  JoyEvents;
    JoystickReportParser                            Joy(&JoyEvents);



    #include <SPI.h>
    #include <Mirf.h>
    #include <nRF24L01.h>
    #include <MirfHardwareSpiDriver.h>
    #define MAX_BUFF 32 //Буфер приёма-передачи

    void setup()
    {
      Serial.begin( 115200 );
      Serial.println("Start");

      if (Usb.Init() == -1)
          Serial.println("OSC did not start.");
       
      delay( 200 );

      if (!Hid.SetReportParser(0, &Joy))
          ErrorMessage<uint8_t>(PSTR("SetReportParser"), 1  );


      Mirf.spi = &MirfHardwareSpi;
      Mirf.init();

      Mirf.setRADDR((byte *)"defender"); //Хдесь задаём адрес
      Mirf.payload = MAX_BUFF; //Здесь задаём буфер
      Mirf.channel = 10;
    //Это канал приёма-передачи - должен
    //быть одинаковым у устройств.
      Mirf.config();

      Serial.println("Start..");
    }

    char buff[MAX_BUFF];
    int c_count = 0;



    void loop()
    {
        Usb.Task();
        //if()
          //{
          Serial.print(JoyEvents.X,HEX);Serial.print(" ");
          Serial.print(JoyEvents.Y,HEX);Serial.print(" ");
          Serial.print(JoyEvents.Z1,HEX);Serial.print(" ");
          Serial.print(JoyEvents.Z2,HEX);Serial.print(" ");
          Serial.print(JoyEvents.Rz,HEX);Serial.print(" ");
          Serial.println();//}
          buff[0]=map(JoyEvents.X,0,255,1,100);
          buff[1]=map(JoyEvents.Y,0,255,1,100);;
          buff[2]=map(JoyEvents.Z1,0,255,1,100);
          buff[3]=map(JoyEvents.Z2,0,255,1,100);
          buff[4]=JoyEvents.Rz+1;
          buff[5]=0;
        Mirf.setTADDR((byte *)"automobile1"); //Адрес!
        Serial.print(">");
        Mirf.send((uint8_t *)buff);
        while(Mirf.isSending()){
        }
        Serial.println(buff);
       
        delay(300);
    }
    Код (C++):
    #include <SPI.h>
    #include <Mirf.h>
    #include <nRF24L01.h>
    #include <MirfHardwareSpiDriver.h>
    #define MAX_BUFF 32 //Буфер приёма-передачи

    void setup(){
      Serial.begin(9600);
      Mirf.spi = &MirfHardwareSpi;
      Mirf.init();

      Mirf.setRADDR((byte *)"automobile1"); //Здесь задаём адрес
      Mirf.payload = MAX_BUFF; //Здесь задаём буфер
      Mirf.channel = 10;
    //Это канал приёма-передачи - должен
    //быть одинаковым у устройств.
      Mirf.config();

      // настраиваем выводы для моторов
      pinMode(3, OUTPUT);
      pinMode(4, OUTPUT);
      pinMode(5, OUTPUT);
      pinMode(6, OUTPUT);
      Serial.println("Start..");
    }

    char buff[MAX_BUFF];

    void loop(){
      delay(10);
      //receiving
      if(Mirf.dataReady()) {
        Mirf.getData((uint8_t *)buff);
        int fb1=buff[0];
        int lr=buff[1];
        go12(fb1,lr1);
      }
      delay(100);
    }
    //
    void go12(int fb,int lr)
      {
      //вперед-назад
      if(fb>50)
         {digitalWrite(3,HIGH);digitalWrite(4,LOW);
          digitalWrite(5,HIGH);digitalWrite(6,LOW);}
      else if(fb<50)
         {digitalWrite(3,LOW);digitalWrite(4,HIGH);
          digitalWrite(5,LOW);digitalWrite(6,HIGH);}
      else
         {digitalWrite(3,LOW);digitalWrite(4,LOW);
          digitalWrite(5,LOW);digitalWrite(6,LOW);}
      //влево-вправо
      int lr1=map(abs(50-lr),1,50,1,255);
      int fb1=map(abs(50-fb),1,50,1,255);
      if(lr<50)
        {int left=min(255,max(0,fb1-lr1/2));
         int right=min(255,fb1+lr1/2)}
      else
        {int right=min(255,max(0,fb1-lr1/2));
         int left=min(255,fb1+lr1/2)}
      analogWrite(9, left);
      analogWrite(10, right);
      }
    Код (C++):
    #include <SoftwareSerial.h>
    SoftwareSerial mySerial(4,5);

    #include <PS3USB.h>
    USB Usb;
    PS3USB PS3(&Usb);
    Button Btarr[16]={UP,RIGHT,DOWN,LEFT,SELECT,START,L3,R3,L2,R2,L1,R1,TRIANGLE,CIRCLE,CROSS,SQUARE};
    AnalogHat Joyarr[4]={LeftHatX,LeftHatY,RightHatX,RightHatY};

    int status_buttons[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
    long millis_buttons[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
    long millis_buttons1[16]={500,500,500,500,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000};

    int status_joys[4]={0,0,0,0};
    int millis_joys[4]={0,0,0,0};
    int map_joys[4]={2000,-500,2000,-500};
    int dHatLeft=0;
    int dHatRight=0;

    void setup() {
      Serial.begin(115200);
      if (Usb.Init() == -1) {
        Serial.print(F("\r\nOSC did not start"));
        while(1); //halt
      }
      Serial.print(F("\r\nPS3 USB Library Started"));

    }
    void loop() {
      Usb.Task();

       // joys
      for(int i=0;i<4;i++)
        {
        if((PS3.getAnalogHat(Joyarr[i]) != status_joys[i]) && (millis()-millis_joys[i]>200))
          {
           millis_joys[i]=millis();status_joys[i]=PS3.getAnalogHat(Joyarr[i]);
           int hat=map(PS3.getAnalogHat(Joyarr[i]),0,255,map_joys[i]*(-1),map_joys[i]);
           if(i<2) dHatLeft=1;
           else dHatRight=1;
           }
         }
       if(dHatLeft>0)
         {dHatLeft=0;}
       if(dHatRight>0)
         {dHatRight=0;
          go_irobot(status_joys[3],status_joys[2]);}
      // buttons
      for(int i=0;i<16;i++)
        {
        if(PS3.getButtonPress(Btarr[i]) && status_buttons[i]==0)
          {
           millis_buttons[i]=millis();status_buttons[i]=1;
           put_actions(i);
           }
        else
          {if(millis()-millis_buttons[i]>millis_buttons1[i]) status_buttons[i]=0;}
        }
    }

    void put_actions(int btn1)
    {Serial.println(btn1);
    switch(btn1)
      {
      case 4: mySerial.write(128);
           break;
      // start
      case 5: mySerial.write(132);
           break;
      // led
      case 8: mySerial.write((int)139);mySerial.write((int)8);mySerial.write((int)255);mySerial.write((int)255);
           break;
      case 10: mySerial.write(139);mySerial.write(4);mySerial.write((byte)0);mySerial.write(255);
           break;
      // music 6
      case 9: mySerial.write(141);mySerial.write(6);
           break;
    // 40 см и останов
      case 12: mySerial.write(152);mySerial.write(13);
           mySerial.write(137);mySerial.write(1);mySerial.write(44);mySerial.write(128);mySerial.write((byte)0);
           mySerial.write((int)156);mySerial.write((int)1);mySerial.write((int)144);
           mySerial.write(137);mySerial.write((byte)0);mySerial.write((byte)0);mySerial.write((byte)0);mySerial.write((byte)0);
           mySerial.write(153);
          break;
    // music 5
      case 11: mySerial.write(141);mySerial.write(5);
           break;
      case 13: mySerial.write(152);mySerial.write(17);
           mySerial.write(137);mySerial.write(1);mySerial.write(44);mySerial.write(128);mySerial.write((byte)0);
           mySerial.write((int)156);mySerial.write((int)1);mySerial.write((int)144);
           mySerial.write(137);mySerial.write(1);mySerial.write(44);mySerial.write((byte)0);mySerial.write(1);
           mySerial.write((int)157);mySerial.write((byte)0);mySerial.write(90);
           mySerial.write(153);
           mySerial.write(153);
           break;
      default:
           break;
      }
    }
    // отправка команд для движения робота
    void go_irobot(int v1,int r1)
      {
       int v2,r2,lf1,rt1;
       if(v1<128 && r1<128)
          {lf1=v1+abs(r1-128)/2;rt1=max(0,v1-abs(r1-128)/2);}
       else if(v1<128 && r1>=128)
          {lf1=max(0,v1-abs(r1-128)/2);rt1=v1+abs(r1-128)/2;}
       else if(v1>=128 && r1<128)
          {lf1=v1-abs(r1-128)/2;rt1=min(255,v1+abs(r1-128)/2);}
       else if(v1>=128 && r1>=128)
          {lf1=min(255,v1+abs(r1-128)/2);rt1=v1-abs(r1-128)/2;}
       else
          ;    
       //v2=map(v1,0,255,map_joys[3]*(-1),map_joys[3]);
       //r2=map(r1,0,255,map_joys[2]*(-1),map_joys[2]);
       lf1=map(lf1,0,255,250,-250);
       rt1=map(rt1,0,255,250,-250);
       mySerial.write(145);
       mySerial.write(highByte(rt1));mySerial.write(lowByte(rt1));
       mySerial.write(highByte(lf1));mySerial.write(lowByte(lf1));
      }
    Вот... Теперь если это разберем, и я поправлю пару вещей, то сможем закончить проект
     
  13. mcureenab

    mcureenab Гуру

    По идее все рули должны придерживаться стандарта USB HID. Иначе игры их не будут понимать.
     
  14. M0ln1a

    M0ln1a Гик

    Тоже верно... Тогда я куплю себе этот шилд, и попытаюсь так ввести код! Если не выйдет, обращусь сюда)
     
  15. M0ln1a

    M0ln1a Гик

    Тогда последнее что осталось решить - как передать эту информацию на пульт? Как найти коды для Nrf2401? Получать данные с пульта с сериал -порта, записать их и отправлять на машинку?
     
  16. mcureenab

    mcureenab Гуру

    Думаю, проще выкинуть пульт и мозги машинки и заменить их на свои с радио интерфейсом.

    Думаете в вашем пульте Nrf2401?

    Хотя, можно поискать литературу про пульты для машинок. Наверняка тоже стандартные. Только радио частоты могут быть разными, чтобы несколько машинок могли одновременно работать рядом. Поэтому радио модуль должен быть с настройкой частоты и соответствующей модуляцией сигнала а может быть и протокола.
     
  17. mcureenab

    mcureenab Гуру

    Интересно, руль как джойстик... А и в самом деле - две педали - две оси X и Y. И сама баранка - ось Z.
     
  18. mcureenab

    mcureenab Гуру

    Микроконтроллер BK2461 в пульте машинки: http://bbs.hwrf.com.cn/down52/BT-WiFi-52rf5541.pdf

    * Integrated 2.4G RF transceiver

    13 BK2461 RF transceiver

    BK-RF is a GFSK transceiver operating in the world wide ISM frequency band at 2400-2483.5 MHz Burst mode transmission and up to 2Mbps air data rate

    The frequency is set by the RF_CH register in register bank 0 according to the following formula: F0= 2400 + RF_CH (MHz). The resolution of the RF channel frequency is 1MHz.

    Что в мозгах прошито ХЗ. Если приемник собрать, то можно разобраться в кодах. Но радио модули в основном реализуют проприетарный протокол. Не факт что он совместим с протоколом трансивера BK2461. И в продаже BK2461 я не вижу, чтобы его запрограммировать.
     
  19. serg_admin

    serg_admin Гик

    Вообще схема работы ресивера очень сильно напоминает RF24L01 только длинна адреса до 5 байт (для RF24L01 от 1 до 6 байт) и вроде мощность передатчика у RF24L01 поменьше.
    Частоты, режимы работы, большая часть функционала совпадают. Даже адресация основных регистров похожая.