Joystik для ПК на базе Arduino

9e5f409ae602c8014880d08034a94a60

Перво-наперво необходимо было научиться считывать и обрабатывать сигналы со стиков и управлять курсором напрямую с Arduino Pro Micro.

#include 

const int X1_Pin = A0;
const int Y1_Pin = A1;
const int X2_Pin = A2;
const int Y2_Pin = A3;

const int SW1_Pin = 3;
const int SW2_Pin = 2;

int SW1_Stage;
int SW2_Stage;

int SW1;
int SW2;

const int Sp = 5;

void setup() {
  Serial.begin(9600);

  Mouse.begin();

  pinMode(SW1_Pin, INPUT_PULLUP);
  pinMode(SW2_Pin, INPUT_PULLUP);
  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);

}

void loop() {
  //Доп пины питания
  digitalWrite(8, HIGH);
  digitalWrite(9, HIGH);

  //Чтение портов
  int x1 = analogRead(X1_Pin);
  int y1 = analogRead(Y1_Pin);
  int x2 = analogRead(X2_Pin);
  int y2 = analogRead(Y2_Pin);

  SW1_Stage = digitalRead(SW1_Pin);
  SW2_Stage = digitalRead(SW2_Pin);

  int x1pos, y1pos;
  int x2pos, y2pos;

  //Фильтр XY1
  if (x1 > 450 and x1 < 550)
    x1pos = 0;
  if (x1 >= 550)
    x1pos = map(x1, 550, 1023, 0, Sp);
  if (x1 <= 450)
    x1pos = map(x1, 450, 0, 0, -Sp);
  if (y1 > 450 and y1 < 550)
    y1pos = 0;
  if (y1 >= 550)
    y1pos = map(y1, 550, 1023, 0, Sp);
  if (y1 <= 450)
    y1pos = map(y1, 450, 0, 0, -Sp);

  //Обработка кнопки ЛКМ
  if (SW1_Stage == LOW)
    SW1 = 1;
  else
    SW1 = 0;

  //Фильтр XY2
  if (x2 > 450 and x2 < 550)
    x2pos = 0;
  if (x2 >= 550)
    x2pos = map(x2, 550, 1023, 0, Sp);
  if (x2 <= 450)
    x2pos = map(x2, 450, 0, 0, -Sp);
  if (y2 > 450 and y2 < 550)
    y2pos = 0;
  if (y2 >= 550)
    y2pos = map(y2, 550, 1023, 0, Sp);
  if (y2 <= 450)
    y2pos = map(y2, 450, 0, 0, -Sp);

  //Обработка кнопки ПКМ
  if (SW2_Stage == LOW)
    SW2 = 1;
  else
    SW2 = 0;

  //Управление курсором
  Mouse.move(x1pos, y1pos);

  if (SW1) {
    Mouse.press(MOUSE_LEFT);
  } else {
    Mouse.release(MOUSE_LEFT);
  }
  if (SW2) {
    Mouse.press(MOUSE_RIGHT);
  } else {
    Mouse.release(MOUSE_RIGHT);
  }
  /*/Отладка
    Serial.print(x1pos);
    Serial.print(":");
    Serial.print(y1pos);
    Serial.print(":");
    Serial.println(SW1_Stage);
    Serial.print(":");
    Serial.print(x2pos);
    Serial.print(":");
    Serial.print(y2pos);
    Serial.print(":");
    Serial.println(SW2_Stage);
   /*/
  delay(10);

}

А теперь самое интересное! Объединить эти два кода. Не обошлось и без плясок с бубном, и убегающим в «самоволку» курсором.

TX:

#include 
#include "nRF24L01.h"
#include "RF24.h"

RF24 radio(9, 10);        //Создать модуль на пинах 9 и 10

byte address[][6] = {"1Node", "2Node", "3Node", "4Node", "5Node", "6Node"};   //возможные номера труб

const int XL_Pin = A0;    //Аналоговый вход левого стика ось X
const int YL_Pin = A1;    //Аналоговый вход левого стика ось Y
const int XR_Pin = A2;    //Аналоговый вход правого стика ось X
const int YR_Pin = A3;    //Аналоговый вход правогоо стика ось Y
byte LBM_Pin = 2;         //Цифровой вход ЛКМ
byte RBM_Pin = 3;         //Цифровой вход ПКМ

byte transmit_data[6];    //Массив, хранящий передаваемые данные
byte latest_data[6];      //Массив, хранящий последние переданные данные

boolean flag;             //Флаг отправки данных

void setup() {
  Serial.begin(9600);               //Открываем порт для связи с ПК

  pinMode(XL_Pin, INPUT);           //Настройка порта левого стика ось X
  pinMode(YL_Pin, INPUT);           //Настройка порта левого стика ось Y
  pinMode(XR_Pin, INPUT);           //Настройка порта правого стика ось X
  pinMode(YR_Pin, INPUT);           //Настройка порта правого стика ось Y
  pinMode(LBM_Pin, INPUT_PULLUP);   //Настройка порта ЛКМ
  pinMode(RBM_Pin, INPUT_PULLUP);   //Настройка порта ЛКМ

  pinMode(7, OUTPUT);               //Доп питание
  pinMode(8, OUTPUT);               //Доп питание
  digitalWrite(7, HIGH);            //Доп пин питания левого стика
  digitalWrite(8, HIGH);            //Доп пин питания правого стика

  radio.begin();                        //Активировать модуль
  radio.setAutoAck(1);                  //Режим подтверждения приёма, 1 вкл 0 выкл
  radio.setRetries(0, 15);              //Время между попыткой достучаться, число попыток
  radio.enableAckPayload();             //Разрешить отсылку данных в ответ на входящий сигнал
  radio.setPayloadSize(32);             //Размер пакета, в байтах
  radio.openWritingPipe(address[0]);    //Труба 0, открыть канал для передачи данных
  radio.setChannel(0x70);               //Выбираем канал (в котором нет шумов!)

  radio.setPALevel (RF24_PA_MAX);       //Уровень мощности передатчика. На выбор RF24_PA_MIN, RF24_PA_LOW, RF24_PA_HIGH, RF24_PA_MAX
  radio.setDataRate (RF24_250KBPS);     //Скорость обмена. На выбор RF24_2MBPS, RF24_1MBPS, RF24_250KBPS должна быть одинакова на приёмнике и передатчике!при самой низкой скорости имеем самую высокую чувствительность и дальность!!

  radio.powerUp();                      //Начать работу
  radio.stopListening();                //Не слушаем радиоэфир, мы передатчик

}

void loop() {

  //Чтение портов

  transmit_data[0] = map(analogRead(XL_Pin), 0, 1023, 0, 255);    //Записать значение XL на 1 место в массиве
  transmit_data[1] = map(analogRead(YL_Pin), 0, 1023, 0, 255);    //Записать значение YL на 2 место в массиве
  transmit_data[2] = map(analogRead(XR_Pin), 0, 1023, 0, 255);    //Записать значение XR на 3 место в массиве
  transmit_data[3] = map(analogRead(YR_Pin), 0, 1023, 0, 255);    //Записать значение YR на 4 место в массиве
  transmit_data[4] = !digitalRead(LBM_Pin);                       //Записать сигнал ЛКМ на 5 место в массиве
  transmit_data[5] = !digitalRead(RBM_Pin);                       //Записать сигнал ПКМ на 5 место в массиве

  radio.powerUp();                                      // включить передатчик
  radio.write(&transmit_data, sizeof(transmit_data));   // Отправить по радио
  for (int i = 0; i < 6; i++) {                         // В цикле от 0 до числа каналов
    if (transmit_data[i] != latest_data[i]) {           // Если есть изменения в transmit_data
      flag = 1;                                         // Поднять флаг отправки по радио
      latest_data[i] = transmit_data[i];                // Запомнить последнее изменение
    }
  }

  if (flag == 1) {
    radio.powerUp();                                      // Включить передатчик
    radio.write(&transmit_data, sizeof(transmit_data));   // Отправить по радио
    flag = 0;                                             // Опустить флаг
    radio.powerDown();                                    // Выключить передатчик
  }
  /*/Отладка, проверка сигнала на A0,A1,A2,A3
      Serial.print(analogRead(XL_Pin));
      Serial.print(":");
      Serial.print(analogRead(YL_Pin));
      Serial.print(":");
      Serial.println(!digitalRead(2));
      Serial.print("\n");
      Serial.print(analogRead(XR_Pin));
      Serial.print(":");
      Serial.print(analogRead(YR_Pin));
      Serial.print(":");
      Serial.println(!digitalRead(3));
      delay(10);
  */

}
//Список занятых пинов: A0,A1,A2,A3,1,2,3,4,7,8,9,10,11,12,13
//Список передаваемых пинов: A0,A1,A2,A3,2,3
//Список доп пинов питания 7,8 (В итоговой версии необходимо объединить на 5V, Gnd объединить)

RX:

#include 
#include "nRF24L01.h"
#include "RF24.h"
#include 

RF24 radio(9, 10);      //Создать модуль на пинах 9 и 10

byte recieved_data[6];  //Массив принятых данных

byte XLP;               //Значения левого стика ось X
byte YLP;               //Значения левого стика ось Y
byte XRP;               //Значения правого стика ось X
byte YRP;               //Значения правого стика ось Y
int LBMP;               //Значения ЛКМ
int RBMP;               //Значения ПКМ

const int Sp = 30;      //Скорость курсора (10,20,30,40,50,60,70) чем больше, тем медленне

byte address[][6] = {"1Node", "2Node", "3Node", "4Node", "5Node", "6Node"}; //возможные номера труб

void setup() {
  Serial.begin(9600);   //Открываем порт для связи с ПК

  Mouse.begin();

  radio.begin();  //Активировать модуль
  radio.setAutoAck(1);                    // Режим подтверждения приёма, 1 вкл 0 выкл
  radio.setRetries(0, 15);                // Время между попыткой достучаться, число попыток)
  radio.enableAckPayload();               // Разрешить отсылку данных в ответ на входящий сигнал
  radio.setPayloadSize(32);               // Размер пакета, в байтах
  radio.openReadingPipe(1, address[0]);   // Слушаем трубу 0
  radio.setChannel(0x70);                 // Выбираем канал (в котором нет шумов!)

  radio.setPALevel (RF24_PA_MAX);         // Уровень мощности передатчика. На выбор RF24_PA_MIN, RF24_PA_LOW, RF24_PA_HIGH, RF24_PA_MAX
  radio.setDataRate (RF24_250KBPS);       // Скорость обмена. На выбор RF24_2MBPS, RF24_1MBPS, RF24_250KBPS должна быть одинакова на приёмнике и передатчике! Gри самой низкой скорости имеем самую высокую чувствительность и дальность!!

  radio.powerUp();                        // Начать работу
  radio.startListening();                 // Начинаем слушать эфир, мы приёмный модуль

}

void loop() {
  byte pipeNo;
  while ( radio.available(&pipeNo)) {                     // Есть входящие данные
    radio.read(&recieved_data, sizeof(recieved_data));    // Читаем входящий сигнал

    XLP = recieved_data[0];   //Читаем входящие данные оси X левого стика и записываем значение
    YLP = recieved_data[1];   //Читаем входящие данные оси Y левого стика и записываем значение
    XRP = recieved_data[2];   //Читаем входящие данные оси X правого стика и записываем значение
    YRP = recieved_data[3];   //Читаем входящие данные оси Y правого стика и записываем значение
    LBMP = recieved_data[4];  //Читаем входящие данные ЛКМ и записываем значение
    RBMP = recieved_data[5];  //Читаем входящие данные ПКМ и записываем значение

  }

  int xLpos, yLpos;
  int xRpos, yRpos;

  //Фильтр XYL
  if (XLP > 120 and XLP < 130)
    xLpos = 0;
  if (XLP >= 130)
    xLpos = map(XLP, 130, 255, 0, 80);
  if (XLP <= 120)
    xLpos = map(XLP, 120, 0, 0, -80);

  if (YLP > 120 and YLP < 130)
    yLpos = 0;
  if (YLP >= 130)
    yLpos = map(YLP, 130, 255, 0, 80);
  if (YLP <= 120)
    yLpos = map(YLP, 120, 0, 0, -80);

  //Фильтр XYR
  if (XRP > 120 and XRP < 130)
    xRpos = 0;
  if (XRP >= 130)
    xRpos = map(XRP, 130, 255, 0, 80);
  if (XRP <= 120)
    xRpos = map(XRP, 120, 0, 0, -80);

  if (YRP > 120 and YRP < 130)
    yRpos = 0;
  if (YRP >= 130)
    yRpos = map(YRP, 130, 255, 0, 80);
  if (YRP <= 120)
    yRpos = map(YRP, 120, 0, 0, -80);

  //Управление курсором
  Mouse.move(xRpos / Sp, yRpos / Sp);

  if (LBMP) {
    Mouse.press(MOUSE_LEFT);
  } else {
    Mouse.release(MOUSE_LEFT);
  }
  if (RBMP) {
    Mouse.press(MOUSE_RIGHT);
  } else {
    Mouse.release(MOUSE_RIGHT);
  }
  /*//Отладка A0,A1,A2,A3
    Serial.print(XLP);
    Serial.print(":");
    Serial.print(YLP);
    Serial.print(":");
    Serial.println(LBMP);
    Serial.print("\n");
    Serial.print(XRP);
    Serial.print(":");
    Serial.print(YRP);
    Serial.print(":");
    Serial.println(RBMP);
    Serial.print("\n");
    Serial.print(xRpos);
    Serial.print(":");
    Serial.print(yRpos);
    delay(5);
  */
}
//Список занятых пинов: 9,10,14,15,16
//Список передаваемых пинов: A0,A1,A2,A3,2,3

//LBM-LeftButtonMouse(ЛКМ) RBM-RightButtonMouse(ПКМ)

© Habrahabr.ru