[071] Mysz w świecie Arduino - cz. 2

[071] Mysz w świecie Arduino - cz. 2

Sokoro już znamy podstawy rozmów Arduino z myszą, czas na nieco bardziej zaawansowaną konwersację, choć nadal tylko będącą modułem, który można wykorzystać we własnych rozwiązaniach. Wkrótce przedstawię przykład takiej aplikacji, a dziś – kolejny szkic, w którym istotne informacje wyświetlimy na wyświetlaczu wbudowanym w płytkę edukacyjną TME. Dlatego potrzebujemy bibliotek wspierających działanie takiego wyświetlacza pracującego na szynie I2C. Pisałem już o tym kilka razy, między innymi w artykułach, w których pracowałem z tym wyświetlaczem.


#include <Wire.h>                                                      // Biblioteka obsługująca magistralę I2C
#include <hd44780.h>                                                   // Biblioteka obsługująca wyświetlacze 44780
#include <hd44780ioClass/hd44780_I2Cexp.h>                             // Dodatek obsługujący wyświetlacze podłączone do ekspandera I2C
#include <PS2MouseHandler.h>                                           // Biblioteka obsługi myszy PS/2
#define MOUSE_DATA 5                                                   // Linia DATA
#define MOUSE_CLOCK 6                                                  // Linia CLCK
hd44780_I2Cexp lcd(0x20, I2Cexp_MCP23008, 7, 6, 5, 4, 3, 2, 1, HIGH);  // Konfiguracja połączeń wyświetlacza LCD
PS2MouseHandler mouse(MOUSE_CLOCK, MOUSE_DATA, PS2_MOUSE_REMOTE);      // Inicjuj bibliotekę.

int pozycjaX;  // Pozycja myszy (X)
int pozycjaY;  // Pozycja myszy (X)
int scrollV;   // Ilość impulsów z rolki V
int scrollH;   // Ilość impulsów z rolki H

void setup() {
  lcd.begin(16, 2);                         // Inicjuj wyświetlacz LCD
  if (mouse.initialise() != 0) {            // Inicjuj mysz.
    Serial.println("Nierozpoznana mysz.");  // Komunikat błędu.
  }
}
void loop() {
  mouse.get_data();  // Pobierz status myszy.

  if (mouse.button(1) == 1) {  // Zeruj wartości pozycji i ilości impulsów z rolek.
    lcd.clear();               // Przy okazji czyść ekran.
    pozycjaX = 0;
    pozycjaY = 0;
    scrollV = 0;
    scrollH = 0;
  }
  lcd.setCursor(0, 0);         // Ustaw kursor na wybranej pozycji wyświetlacza.
  lcd.print(mouse.button(0));  // Wyświetl stan przycisku pierwszego.

  lcd.setCursor(0, 1);
  lcd.print(mouse.button(2));  // Wyświetl stan przycisku trzeciego.

  switch (mouse.z_movement()) {  // Dekoduj informację o ruchach rolek.
    case 1:                      // 1 to ruch w dół rolki V
      scrollV--;
      break;
    case -1:  // -1 to ruch w górę rolki V
      scrollV++;
      break;
    case 2:  // 2 to ruch w dół rolki H
      scrollH--;
      break;
    case -2:  // -2 to ruch w górę rolki H
      scrollH++;
  }

  lcd.setCursor(2, 0);  // Wyświetl licznik impulsów rolki V
  lcd.print(F("V"));
  lcd.print(scrollV);
  lcd.print(F(" "));

  lcd.setCursor(2, 1);  // Wyświetl licznik impulsów rolki H
  lcd.print(F("H"));
  lcd.print(scrollH);
  lcd.print(F(" "));

  pozycjaX = pozycjaX + mouse.x_movement();  // Dodaj do zmiennej pozycji X dane o szybkości w osi X
  lcd.setCursor(9, 0);
  lcd.print(F("X"));
  lcd.print(pozycjaX);  // Wyświetl pozycję X
  lcd.print(F("     "));

  pozycjaY = pozycjaY + mouse.y_movement();  // Dodaj do zmiennej pozycji Y dane o szybkości w osi Y
  lcd.setCursor(9, 1);
  lcd.print(F("Y"));
  lcd.print(pozycjaY);  // Wyświetl pozycję Y
  lcd.print(F("     "));

  delay(50);  // Dobierz opóźnienie.
}

Wstęp zawiera odniesienia do bibliotek i deklaracje wstępne. Potrzebny nam będzie także zestaw czterech zmiennych, gdyż tym razem dane z myszy będziemy przeliczać na bardziej użyteczną postać. Początek jest podobny: inicjujemy mysz, wyświetlacz, a na początku pętli pobieramy dane z myszy – ja poprzednio, instrukcją mouse.get_data()

if (mouse.button(1) == 1) {  // Zeruj wartości pozycji i ilości impulsów z rolek.
  lcd.clear();               // Przy okazji czyść ekran.
  pozycjaX = 0;
  pozycjaY = 0;
  scrollV = 0;
  scrollH = 0;
}

I od razu wprowadzam funkcję resetującą wartości, o których zaraz powiem, co wymaga wciśnięcia drugiego, czyli środkowego przycisku myszy. W większości wypadków znajduje się on pod rolką.

Następnie mamy dwie bliźniacze instrukcje, które wyświetlają na początku wyświetlacza stany przycisków pierwszego i trzeciego:

lcd.setCursor(0, 0);         // Ustaw kursor na wybranej pozycji wyświetlacza.
lcd.print(mouse.button(0));  // Wyświetl stan przycisku pierwszego.

lcd.setCursor(0, 1);
lcd.print(mouse.button(2));  // Wyświetl stan przycisku trzeciego.

Wymyśliłem sobie, że zamiast wyświetlać fakt kręcenia rolkami, lepiej ukazywać ilości impulsów, które te rolki wygenerowały. Z uwzględnieniem obracania w tył, co powoduje zmniejszanie tych stanów. Tylko że niefortunnie ruchy rolek myszy ze zdjęcia zakodowano na jednym bajcie, więc będziemy musieli je wyłuskać, co najprostsze w realizacji okazało się przy użyciu instrukcji switch/case.

switch (mouse.z_movement()) {  // Dekoduj informację o ruchach rolek.
  case 1:                      // 1 to ruch w dół rolki V
    scrollV--;
    break;
  case -1:  // -1 to ruch w górę rolki V
    scrollV++;
    break;
  case 2:  // 2 to ruch w dół rolki H
    scrollH--;
    break;
  case -2:  // -2 to ruch w górę rolki H
    scrollH++;
}

Każda w wartości: 1, -1, 2 i -2 daje informacje o rolce i kierunku. W każdym wypadku będziemy zwiększać lub zmniejszać stan zmiennych scroll, które zaraz potem będziemy wyświetlać. Ponieważ używamy typów INT, szesnastobitowe wartości są zawijane, lecz są na tyle duże, że niczemu to nie przeszkadza.

No i w końcu czas wyświetlić położenie. Tutaj sprawa jest prosta: do wartości bieżącej będziemy dodawać wartości przychodzące z myszy.

pozycjaX = pozycjaX + mouse.x_movement();  // Dodaj do zmiennej pozycji X dane o szybkości w osi X
lcd.setCursor(9, 0);
lcd.print(F("X"));
lcd.print(pozycjaX);  // Wyświetl pozycję X
lcd.print(F("     "));

pozycjaY = pozycjaY + mouse.y_movement();  // Dodaj do zmiennej pozycji Y dane o szybkości w osi Y
lcd.setCursor(9, 1);
lcd.print(F("Y"));
lcd.print(pozycjaY);  // Wyświetl pozycję Y
lcd.print(F("     "));

To najprostsza konwersja ruchu na położenie absolutne, choć daleka od doskonałości. Po pierwsze, nawet malutkie ruchy znacząco zwiększają te wartości. Po drugie, zależność jest liniowa. W praktyce potrzebujemy wykładniczej, która daje precyzję przy niewielkich ruchach i mocne zmiany przy ruchach znacznych. Należałoby zatem analizować wielkości poprzednie i w zależności od interwału wprowadzać odpowiednie dzielniki, by delikatne ruchy nie dawały takich mocnych przyrostów. Ale o tym już opowiem przy innej okazji. Elementy tego szkicu można już wykorzystać do zadań praktycznych, czy to w typowych aplikacjach wyświetlania kursora, czy do sterowań światłem, robotem lub innymi peryferiami. Ale o tym napiszę w kolejnym artykule.

Powiązane tematy

Płytka edukacyjna TME-EDU-ARD-2Płytka edukacyjna TME-EDU-ARD-2Sprawdź tutaj

Przeczytaj również

Nasi partnerzy

TMETech Master EventTME EducationPoweredby
Copyright © 2024 arduino.pl