Подключение джойстика к ардуино.

kadushkin
Offline
Зарегистрирован: 18.12.2011

Задача:

Подключить модуль управления КПП от Руля Logitech G27 (G25) к ардуино.

Нужно чтобы ардуино реагировал на события: нажатие кнопок и движение кулисы (ручки КПП)

Вот сам руль с педалями и КПП

Нужно подключить к ардуино только КПП:

Это грубо говоря несколько кнопок и подстроечных резисторов (на кулисе КПП)

С чего начать?

maksim
Offline
Зарегистрирован: 12.02.2012

Может поискать схему на это дело? 

kadushkin
Offline
Зарегистрирован: 18.12.2011

Вот внутренности:

Кулиса с потенциометрами (9 и 11):

Видео по разборке:

wn.com/How_to_mod_Logitech_G25_shifter_for_improved_feel!

Распиновка:

forums.logitech.com/t5/PC-Gaming/Will-the-G25-shifter-work-with-the-G27-pedals-wheel/m-p/691898/highlight/true#M9642

maksim
Offline
Зарегистрирован: 12.02.2012

Можно фото платы, желательно в хорошем качестве? 

kadushkin
Offline
Зарегистрирован: 18.12.2011

У меня его еще пока нет, вот купить хочу и приспособить как манипулятор.

maksim
Offline
Зарегистрирован: 12.02.2012

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

maksim
Offline
Зарегистрирован: 12.02.2012

По ссылке не распиновка, а не пойми что... 

kadushkin
Offline
Зарегистрирован: 18.12.2011

maksim
Offline
Зарегистрирован: 12.02.2012

Как раз нужна другая сторона, я хотел посмотреть, что там за микруха стоит. Так вы хотите все подключить или только рычаг?

 

maksim
Offline
Зарегистрирован: 12.02.2012

Просто там как я понял потенциометры рычага к плате разЪемом подключаются... 

kadushkin
Offline
Зарегистрирован: 18.12.2011

Я бы хотел все подключить и кнопки тоже.

Вот распиновка:

www.racingfr.com/forum/lofiversion/index.php/t41572.html

maksim
Offline
Зарегистрирован: 12.02.2012

Вот походу желтый и зеленый как раз эти потенциометры и есть.

maksim
Offline
Зарегистрирован: 12.02.2012

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

kadushkin
Offline
Зарегистрирован: 18.12.2011

Купил шифтер

Прозвонил, оказалась распиновка неверной, вот исправил...

Подключил к +5В и земле. Светодиоды загорелись. Красным обведено, то что проверено и не вызывает сомнений.

Не понятно как снять данные с контактов 2,3,7

Проследил, что они идут на 74HC165D (подписано красным)

На контакты 4, 8 приходит сигнал от потенциометров. Замерил сопротивление между выходом 4 и землей = ~8кОм - это когда двигаешь шифтер влево, вправо мультиметр не показал ничего (наверное -8кОм), если судить по вольтажу, то: 2В в центре, 1В влево, 3В вправо. Как сие подключить? Нужна ли внутр. подтяжка выхода ардуины?

Снимки платы

big-e.ru/files/P1020169.JPG

big-e.ru/files/P1020170.JPG

leshak
Offline
Зарегистрирован: 29.09.2011

 >если судить по вольтажу, то: 2В в центре, 1В влево, 3В вправо

Нет. Подтягивающие тут не нужны. просто в аналоговый пин и analogRead

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

>Проследил, что они идут на 74HC165D (подписано красным)

Тут, скорее всего без вчитывания даташита не получится. В общем виде там идея такая. К 74HC165D подключено 8-мь кнопок. Она "прочитывает их состоянии" , а выдает их последовательно на выход. Переход к "чтению следующей кнопки" происходит после "дрыга" ногой clock. То есть "прочитали выход" - это первая кнопка, дрыгнули clock - прочитали выход - это вторая и т.д.п.

Вот, может эта статья поможет http://easyelectronics.ru/podklyuchenie-klaviatury-k-mk-po-trem-provodam-na-sdvigovyx-registrax.html

Где-то, на этом сайте описывалось и принципы когда несколько сдвиговых регистром каскадом подключаеются (похоже ваш случай), но что-то не могу найти.

И вот еще статье на эту тему http://robocraft.ru/blog/arduino/520.html

Немного непонятно что означет ваш пин LOAD INPUT, но есть подозрение что это и есть нога SH/LD которая коммандует микрухе "прочитать свои входы".

P.S. А вообще - молодец. Правильный подход. Взял и пошел исследовать с тестером, а не кричать, как многие, - дайте мне готовую схему.

leshak
Offline
Зарегистрирован: 29.09.2011

 Вот нашел статью где каскад этих регистров описан http://robocraft.ru/blog/arduino/618.html

kadushkin
Offline
Зарегистрирован: 18.12.2011

Вот как правильно по даташит называются выводы 74HC165D:
Q7 = serial output from the last stage
PL = asynchronous parallel load input (active LOW)
CP = clock input (LOW-to-HIGH edge-triggered)

Это, что аналоги:

Master In Slave Out (MISO), переводится как "вход ведущего выход ведомого", используется для передачи данных от ведомого к ведущему.
Master Out Slave In (MOSI) — выход ведущего вход ведомого, для передачи данных от ведущего к периферийным устройствам.
Serial Clock (SCK) — синхронизирующая линия, синхросигнал генерируется ведущим устройством.

На Arduino Mega — 50 (MISO), 51 (MOSI), 52 (SCK), и 53 (SS).

На 50ый вход подключаю контакт 2, на 51 -3, на 52 - 7.

Так?

 

 

 

leshak
Offline
Зарегистрирован: 29.09.2011

 Микруха работает как "фотоапарат". Вначале вы придавливаете PL в ноль. Он делает "фотографию" своих входов. Запоминает внутри себя их состояния, на момент когда PL=0. Потом вы поднимаете PL в 1. B он начинает "рассказывать" на SQ7 состояние этих входов.

То есть

  1. PL=0 - прочитал
  2. PL=1 - перешли в режим рассказа
  3. Прочитали Q7 - это состояние первого входа (на момент PL=0)
  4. CP=0, CP1 - перешли на следующий вход
  5. Прочитали Q7 - это состояние второго входа (на момент PL=0)
  6. CP=0, CP1 - перешли на следующий вход
  7. Прочитали Q7 - это состояние третьего входа (на момент PL=0)
  8. и т.п.

Так вы постепенно вычитываете состояние всех входов в какой-то один момент времени. Несмотря на то что сам процесс последовательного чтения - не одновременен.

Начиная с пункта 3 и дальше. (дергать CP, читать Q7, собирать биты в байты) - не обязательно руками. У ардуины есть аппаратныя функция для этого. SPI (вернее она немного для более широкого применения, но можно использовать и ее). Во второй ссылке - пример как это делать.

P.S. Все что я рассказал - есть в ссылках выше. Мои знания - оттуда. Там, кстати прямо в комментах указано "/* Выставим на защёлке сначала низкий, потом - высокий уровни.
* Сдвиговый регистр запомнит уровни сигналов на входах и сможет
* их нам потом отдать бит за битом.
*/

"

 

leshak
Offline
Зарегистрирован: 29.09.2011

 >На Arduino Mega — 50 (MISO), 51 (MOSI), 52 (SCK), и 53 (SS).

Не совсем. Сдвиговый регистр - это не полноценный SPI. Это такой "грязноках" использовать ЧАСТЬ пинов этого интерфейса что-бы облегчить себе работу.

Там же в комментах скетча есть "MOSI не подключена". И REG_LATCH они дергают руками (в скетче это 8-мой пин, но можно любой цифровой использовать).

leshak
Offline
Зарегистрирован: 29.09.2011

> на 51 -3

Нет. 3-тий пин разъема на какой-нибудь  другой пин ардуины. Например D8. и потом, перед чтением делать digitalWrite(8,LOW); digitalWrite(8,HIGH);

kadushkin
Offline
Зарегистрирован: 18.12.2011

Да, я это понимаю.

Не совсем понятно к каким выводам ардуины подключить?

50(MISO) - 2 (SERIAL OUTPUT)

52(SCK) - 7 (CLOCK)

8(Защелка) - 3 (LOAD INPUT)

#include <SPI.h>

enum { REG_LATCH = 8 };


void setup()
{
  /* Включаем UART и SPI */
  Serial.begin(9600);
  SPI.begin();
  /* Включаем защёлку */
  digitalWrite(REG_LATCH, LOW);
  digitalWrite(REG_LATCH, HIGH);

}


void loop()
{
  static uint32_t last_input_states = 0;

  /* Выставим на защёлке сначала низкий, потом - высокий уровни.
   * Сдвиговый регистр запомнит уровни сигналов на входах и сможет
   * их нам потом отдать бит за битом.
   */
  digitalWrite(REG_LATCH, LOW);
  digitalWrite(REG_LATCH, HIGH);

  /* Читаем запомненные состояния входов. Ноль шлём просто потому,
   * что transfer() одновременно и шлёт, и принимает. Да и вообще,
   * MOSI не подключена (:
   */
  uint32_t states = SPI.transfer(0);

  /* Если состояние любого входа изменилось, расскажем по UART */
  if (states != last_input_states)
  {
    /* Старый добрый XOR даст нам битовую разницу между старым и новым состояниями. */
    uint32_t changed = states ^ last_input_states;
    last_input_states = states; // запоминаем текущие состояния

    for (int i = 0; i < 32; ++i)
    {
      if (changed & 1) // если состояние кнопки изменилось…
      {
        Serial.print("#");
        Serial.print(i); // шлём номер кнопки
        Serial.print(" -> ");
        Serial.println(states & 1); // … и новое состояние
      }

      /* Сдвигаем биты вправо. Теперь первый бит
       * будет указывать состояние следующей кнопки.
       */
      changed >>= 1;
      states >>= 1;
    }
  }
}

 

 

 

leshak
Offline
Зарегистрирован: 29.09.2011

 А зачем вы REG_LATCH переименовали в CLK_INPUT? Ну то есть имя конечно рояля не играет, но зачем же запутываться искуственно?

CLK - это CLOCK, по этому сигналу мы читаем следующий бит. А REG_LATCH - это защелка.

Ну вот смотрите, есть же схема:

 

Всего три проводка к дуине идут (во истину, в трех соснах).

Итак что мы имеем (слева ноги чипа, справа пины дуины)  SH-LD -->D8, CLK --> SCLK(13), QH --> MISO(12)

Переводим "на наш язык" вначале левую часть. Заменяем ноги чипа на аналоги вашего разъема, получаем

3(LOAD INPUT) --> D8,    7 (CLOCK) -> SCLK  , 2 (SERIAL OUTPUT) --> MISO

Теперь нужно выяснить на каких ногах у меги SCLK и MISO (D8 он и в африке D8). Смотрим http://arduino.cc/en/Reference/SPI

" SPI bus uses pins 10 (SS), 11 (MOSI), 12 (MISO), and 13 (SCK). On the Arduino Mega, this is 50 (MISO), 51 (MOSI), 52 (SCK), and 53 (SS)

Видим что нам нужно перевести 12(MISO) и 13(SCK) в меговские 50(MISO) и 52(SCK)

Итого, в итоге:  

  1. 3(LOAD INPUT) ==> D8,  
  2. 7 (CLOCK) ==> D52 (SCLK), 
  3. 2 (SERIAL OUTPUT) ==> D50 (MISO)
leshak
Offline
Зарегистрирован: 29.09.2011

 А в строке 42 откуда у вас взялась цифра 32? Либо 8 либо 16-ть :)

А вообще, вместо строк 35-58-мь. Я бы, для теста, рекомендовал сделать тупейший

Serial.println(states,BIN);

И глазами просто посмотрел, нажимая на кнопки как нули и единицу меняются.

И еще. То что вы помениля типа states на uint32_t не означает что  SPI.transfer(0); начнет читать сразу по четере байти (хотя вообще-то нужно два). Он прочитает только один байт, а остальное заполнится нулями. Так что нужно либо

uint8_t states1 = SPI.transfer(0);
uint8_t states2 = SPI.transfer(0);

Либо что-то типа

uint32_t states= (SPI.transfer(0) <<8 ) | SPI.transfer(0)

Пробовать.

 

leshak
Offline
Зарегистрирован: 29.09.2011

 А еще лучше. ПРосто взять скет из статьи и запустить. Без собственных модификаций. Он вычиет только один регистр. То есть часть кнопок должна начать работать. Убедитесь что подключено правильно. А ж потом будете подкручивать его для чтения второго регистра.

kadushkin
Offline
Зарегистрирован: 18.12.2011

Спасибо, все отлично заработало...

#include <SPI.h>

enum { REG_LATCH = 26 };
int Shiter_ArrayButtons_Status[12]; //массив статусов кнопок шифтера

void setup()
{
  /* Включаем UART и SPI */
  Serial.begin(115200);
  SPI.begin();
  /* Включаем защёлку */
  pinMode(REG_LATCH, OUTPUT);
  digitalWrite(REG_LATCH, HIGH);
}


void loop()
{
Read_ShifterButtonsStatus();  
}  

  uint16_t Read_ShifterButtonsStatus() 
  {
    //Serial.println(analogRead(0)); //Y
  // Serial.println(analogRead(1)); //X

  static uint16_t last_input_Buttons_States = 0; // статус четырех нижних (красных) кнопок и восьми верхних и средних (черных) кнопок

  digitalWrite(REG_LATCH, LOW);  //Выставим на защёлке сначала низкий, потом - высокий уровни.
  digitalWrite(REG_LATCH, HIGH); //Сдвиговый регистр запомнит уровни сигналов на входах и сможет их нам потом отдать бит за би

  uint16_t states= (SPI.transfer(0) <<8 ) | SPI.transfer(0); //Читаем запомненные состояния четырех нижних (красных) кнопок и восьми верхних и средних (черных) кнопок

  if (states != last_input_Buttons_States)
  {
    uint16_t changed = states ^ last_input_Buttons_States;
    last_input_Buttons_States = states; // запоминаем текущие состояния

    for (int i = 0; i < 16; ++i)
    {
      if (changed & 1) // если состояние кнопки изменилось…
      {
        Serial.print("#");
        Serial.print(i); // шлём номер кнопки
        Serial.print(" -> ");
        Serial.println(states & 1); // … и новое состояние
      }

      changed >>= 1; // Сдвигаем биты вправо
      states >>= 1; // Сдвигаем биты вправо
    }
  }
   
// return result;  
}

 

kadushkin
Offline
Зарегистрирован: 18.12.2011

leshak Огромный респект, за огромный вклад.

Функции конечно не окончательные и будут дописаны.

Подключено все к ардуине напрямую. Пока все отлично пашет. Я надеюсь перегрузку по питанию это не создаст. Что-то не нашел сколько 74HC165D потребляет, но думаю минимум.

leshak
Offline
Зарегистрирован: 29.09.2011

 >Я надеюсь перегрузку по питанию это не создаст.

Да нет. Откуда? Там же нет ничего тяжеловесного. Я думаю их десятками вешать можно, если не сотнями. В крайнем случае можете, для спокойствия, взять амперметр и померять :)

>Пока все отлично пашет.

Я бы, еще, что-бы уж до конца разобратся, попробовал-бы сам прочитать, не через SPI. Все-таки он у дуины всего один, и вполне реально может оказатся, в другом проекте, занятым под что-то более важное. Что невозможно передвинуть на другие пины.

Как я понимаю это как-то так делается (вместо строки 32).

states=0;
for(byte i=0;i<16;i++){

  state= (state<<1) | digitalRead(50); // читаем текущий вход

  // дергаем clock, для перехода к следующими входу
  digitalWrite(52,LOW);
  digitalWrite(52,HIGH);
}

 

Воозможно еще получится готовую библиотеку найти. Сходу находится только для out регистров, но возможно и для input попадется.