Джойстик. Урок 18. Ардуино

джойстик
Джойстик и светодиодная матрица
Джойстик и светодиодная матрица

Привет! В прошлый раз мы начали говорить про светодиодные матрицы. А как можно использовать матрицу лучше всего? Конечно управлять светодиодами используя джойстик.

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

Для того, чтобы выполнить этот урок нам понадобиться

  • Ардуино UNO
  • Перемычки
  • Макетная плата
  • Светодиодная матрица
  • Резистор 220 Ом
  • Джойстик
  • Кабель USB

Джойстик KY-023

Джойстик KY-023 это небольшой модуль готовый к подключению к Ардуино. У него 5 контактов. По контактам данных VRX и VRY передаются аналоговые значения от двух потенциометров. Они определяют положение джойстика по осям X и Y.

При нажатии на ручку, срабатывает кнопка. Ее контакт SW передает цифровой сигнал.

Если мы отпустим ручку, то потенциометры вернуться в центральное положение. При этом они будут отправлять аналоговое значение около 512. Имейте в виду, что ровно 512, скорее всего, не будет.

В моем случае, ось Х в центральном положении выдавала 535. А Y все время менялась между 532-540. Этот момент придется учесть в программе.

Подключение

У джойстика 5 контактов. Питание 5 вольт, земля, цифровой контакт для кнопки и два аналоговых контакта потенциометров.

Принципиальная схема подключения джойстика
Принципиальная схема подключения джойстика
  • GND — земля
  • +5v — питание 5 вольт
  • VRX — аналоговый пин
  • VRY — аналоговый пин
  • SW — цифровой пин

Получаем данные от джойстика

Для начала проверим работу джойстика и попробуем получить от него данные и вывести их в монитор порта.

Загрузим простой скетч и откроем монитор. Считаем состояния кнопки и потенциометров и выведем их в монитор порта.

#define pinX    A2
#define pinY    A1
#define swPin    2

void setup() {
  Serial.begin(9600);
  
  pinMode(ledPin, OUTPUT);
  pinMode(pinX, INPUT);
  pinMode(pinY, INPUT);
  pinMode(swPin, INPUT);
  digitalWrite(swPin, HIGH);
}
 
void loop() {
  boolean Button = digitalRead(swPin);

  int X = analogRead(pinX);          
  int Y = analogRead(pinY);     

  Serial.print(X);                
  Serial.print("\t");
  Serial.print(Y);
  Serial.print("\t");
  Serial.println(Button); 
}

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

Данные от джойстика в мониторе
Данные от джойстика в мониторе

Управляем матрицей

Теперь объединим знания о светодиодной матрице и джойстике в небольшое подобие игры. Зажжем один из светодиодов на матрице и будем управлять им с помощью джойстика. А при клике на кнопку будем изменять цвет светодиода.

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

#include <FastLED.h>

//matrix settings
#define NUM_LEDS 256
#define DATA_PIN 3
#define BRIGHTNESS 8

//joystick settings
#define pinX    A2  // X 
#define pinY    A1  // Y
#define swPin    2  // Button

int red, green, blue; //colors

int row;            // row number
int col;            // column number

int lastDirection = 127; // start position
int newDirection;
CRGB leds[NUM_LEDS];

Инициализируем библиотеки и пины. И отобразим светодиод в начальной позиции.

void setup() {
  
  red = random(0, 255);
  green = random(0, 255);
  blue = random(0, 255);

  Serial.begin(9600);
  pinMode(ledPin, OUTPUT);
  pinMode(pinX, INPUT);
  pinMode(pinY, INPUT);
  pinMode(swPin, INPUT);
  digitalWrite(swPin, HIGH);
  
  FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);
  FastLED.setBrightness(BRIGHTNESS);
    leds[snakeDirection].setRGB(red, green, blue);
  FastLED.show();
}

Поскольку светодиоды на нашей матрице спаяны последовательно и конец одного ряда — это начало следующего. Нам понадобиться рассчитать переходы между рядами для нашего светодиода. Для этого напишем специальную функцию.

Она получит предыдущее состояние светодиода, а также координаты движений с джойстика. И вычислит следующий светодиод, который нужно зажечь.

int Snakedirection(int last, int dX, int dY ){
  dX = map(dX, 0, 1000, -1, 1);
  dY = map(dY, 0, 1000, -1, 1);
  int newDirection = last;
  
  if( dX != 0 ){ // moving in X direction
    
    if ( row&1 ){
      newDirection = last + dX; // четная
    } else {
      newDirection = last - dX; // не четная
    }
    
  } 
  
  if( dY < 0){ // moving in Y DOWN direction
    if ( row&1 ){
      newDirection = last + (col*2)+1; // четная
    } else {
      newDirection = last + (16-col-1)+(16-col); // не четная
    }
  } 
  if( dY > 0){ // moving in Y UP direction
    if ( row&1 ){
      newDirection = last - (last - 16*row) - (16 - col); // четная
    } else {
      newDirection = last - (col*2)-1; // не четная
    }
  }

  Serial.print(newDirection);
  Serial.print('\t');
  Serial.print(newDirection);
  Serial.print('\t');

  
  return newDirection;
}

Еще одна функция будет отвечать за перерисовку светодиодов. Она получит номер светодиода, который надо зажечь в данный момент.

int snakeMove(int snakeDirection){
  FastLED.clear();
    leds[snakeDirection].setRGB(red, green, blue);
  FastLED.show();

  row = (int)(snakeDirection/16);  // row number 
  if ( row&1 ){
    col = (row+1) * 16 - snakeDirection - 1;
  } else {
    col = snakeDirection - row * 16;
  }
  
  Serial.print(snakeDirection);
  Serial.print('\t');
  Serial.print(row);
  Serial.print('\t');
  Serial.println(col);
  
  return snakeDirection;
}

Функция color() будет менять цвет светодиода на случайный. По умолчанию кнопка на модуле отправляет 1, поэтому добавим в условие знак !

void color(boolean sw){
  if(!sw){

    red = random(0,255);
    green = random(0,255);
    blue = random(0,255);
    
  }
}

А в управляющем цикле просто соединим эти функции и установим небольшую задержку.

void loop() {
  color( digitalRead(swPin) );
  newDirection = Snakedirection(lastDirection, analogRead(pinX), analogRead(pinY));
  lastDirection = snakeMove(newDirection);
  delay(100);
}
Управляем матрицей с помощью джойстика
Управляем матрицей с помощью джойстика

Полный текст программы

#include <FastLED.h>

//maatrix settings
#define NUM_LEDS 256
#define DATA_PIN 3
#define BRIGHTNESS 8

//joystick settings
#define pinX    A2  // ось X джойстика
#define pinY    A1  // ось Y джойстика
#define swPin    2  // кнопка джойстика

int row;            // row number
int col;            // column number

int lastDirection = 127; // start direction
int newDirection;

int red, green, blue; //colors
CRGB leds[NUM_LEDS];

void setup() {

  red = random(0, 255);
  green = random(0, 255);
  blue = random(0, 255);
  
  Serial.begin(9600);
  pinMode(pinX, INPUT);
  pinMode(pinY, INPUT);
  pinMode(swPin, INPUT);
  digitalWrite(swPin, HIGH);
  
  FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);
  FastLED.setBrightness(BRIGHTNESS);
  leds[lastDirection].setRGB(red, green, blue);
  FastLED.show();
}

int Snakedirection(int last, int dX, int dY ){
  dX = map(dX, 0, 1000, -1, 1);
  dY = map(dY, 0, 1000, -1, 1);
  int newDirection = last;
  
  if( dX != 0 ){ // moving in X direction
    
    if ( row&1 ){
      newDirection = last + dX; // четная
    } else {
      newDirection = last - dX; // не четная
    }
    
  } 
  
  if( dY < 0){ // moving in Y DOWN direction
    if ( row&1 ){
      newDirection = last + (col*2)+1; // четная
    } else {
      newDirection = last + (16-col-1)+(16-col); // не четная
    }
  } 
  if( dY > 0){ // moving in Y UP direction
    if ( row&1 ){
      newDirection = last - (last - 16*row) - (16 - col); // четная
    } else {
      newDirection = last - (col*2)-1; // не четная
    }
  }

  Serial.print(newDirection);
  Serial.print('\t');
  Serial.print(newDirection);
  Serial.print('\t');

  
  return newDirection;
}

int snakeMove(int snakeDirection){
  FastLED.clear();
  leds[snakeDirection].setRGB(red, green, blue);
  FastLED.show();

  row = (int)(snakeDirection/16);  // row number 
  if ( row&1 ){
    col = (row+1) * 16 - snakeDirection - 1;
  } else {
    col = snakeDirection - row * 16;
  }
  
  Serial.print(snakeDirection);
  Serial.print('\t');
  Serial.print(row);
  Serial.print('\t');
  Serial.println(col);
  
  return snakeDirection;
}

void color(boolean sw){
  if(!sw){

    red = random(0,255);
    green = random(0,255);
    blue = random(0,255);
    
  }
}

void loop() {
  color( digitalRead(swPin) );
  newDirection = Snakedirection(lastDirection, analogRead(pinX), analogRead(pinY));
  lastDirection = snakeMove(newDirection);
  delay(100);
}

Заключение

Мы рассмотрели использование джойстика для Ардуино. И соединили его со светодиодной матрицей. Наверное, вы обратили внимание, что готовый проект похож на игру змейка из старых телефонов. Что ж, попробуем реализовать ее в будущем.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *