Joystick & Display

Hej og velkommen tilbage til vores elektronik-blogserie! Dette er blog 5 og i denne blog vil vi udforske et praktisk projekt. Vi skal kigge på hvordan man kan bruge et joystick til at skrive og redigere tekst på et LCD-display. Dette er en interaktiv måde at lære de grundlæggende koncepter inden for elektronik og programmering.

Vi vil gøre brug af et populært I2C LCD-display (det samme LCD som fra Ultrasound & Display bloggen) og et joystick til at skabe vores interaktive skrivemiljø. Ved hjælp af Arduino-platformen og og lidt programmering vil vi kunne bevæge os rundt på skærmen og skrive, redigere og slette tekst ved hjælp af joysticket.

 

Dette projekt er perfekt til alle, der ønsker at udforske grundlæggende koncepter som input- og output-enheder, analoge og digitale signaler samt brugen af biblioteker og funktioner i Arduino-miljøet. Så kom med os på denne spændende rejse ind i elektronikens verden. Lad os komme i gang!
Komponenter, der bruges i dette projekt

Arduino UNO
KY-023 Joystick
20x4 LCD
hun hun kabler
Jumper-ledninger
Breadboard

 

Her er en kort forklaring over de komponenter, der skal bruges i projektet:

  1. 20x4 LCD-display: Et 20x4 LCD-display er en alfanumerisk skærm med 4 linjer og 20 tegn pr. linje. Det smarte ved dette LCD er at det kan bruge I2C-kommunikation til at forbinde med Arduino-boardet og viser tekst og symboler. Dette gør tilkoblingen simplere. 
  2. Arduino Uno: Arduino Uno er en populær mikrocontroller, der, igen igen, fungerer som hjernen i vores projekt. Den styrer LCD-displayet og behandler input fra joysticken ved hjælp af den programmerbare logik.
  3. Hun-hun kabler: Disse kabler bruges til at etablere forbindelsen mellem LCD-displayet og Arduino Uno. De har hunstik i begge ender og gør det nemt at forbinde de to enheder.
  4. Normale jumper-ledninger: Disse ledninger bruges til at oprette forbindelse mellem Arduino Uno og joysticken samt eventuelle andre forbindelser, der er nødvendige for projektet. De er fleksible og lette at tilslutte og frakoble.
  5. Joystick KY-023: Joysticken er vores primære inputenhed i dette projekt. Den bruger analoge signaler til at registrere bevægelser i x- og y-retning samt en digital knap til yderligere interaktion. Vi bruger en joystick fra en PS2-controller, der er nem at tilslutte og betjene.
  6. Breadboard: Et breadboard er en prototypingplatform, der tillader midlertidige forbindelser mellem elektroniske komponenter. Det giver en nem og fleksibel måde at organisere og tilslutte komponenter under udviklingen af vores pro

Disse komponenter er tilstrækkelige til at oprette vores skriveværktøj og begynde at udforske skrive- og redigeringsfunktionerne ved hjælp af joysticken og LCD-displayet.

KY-023

nu vil vi gerne se lidt nærmere på joysticket, som vi benytter i vores projekt. Joysticket, vi anvender, er en KY-023 joystick. Det er et kompakt og alsidigt inputenhed, der giver os mulighed for at styre vores elektroniske system ved hjælp af to akser og en trykknap.

 

Joysticket har to analoge akser, VRx og VRy, der registrerer joystickens horisontale og vertikale bevægelser. Disse akser genererer variable spændingsniveauer, der afhænger af joystickens position. Ved at læse disse spændinger kan vi bestemme, i hvilken retning joysticket bevæger sig.

Derudover har joysticket også en trykknap, kendt som SW, som fungerer som en digital indgang. Denne knap giver os mulighed for at registrere, om knappen er trykket ned eller ej. Vi kan programmere vores system til at udføre bestemte handlinger, når knappen aktiveres.

 

  1. 5V: Dette er forsyningspinden, der skal tilsluttes til en +5V strømkilde på Arduino-boardet eller et andet strømforsyningsmodul. Det giver strøm til joysticket.
  2. VRx: Denne pin er den analoge x-akse-udgang. Den leverer en variabel spænding, der er afhængig af joystickens horisontale position. Denne pin skal forbindes til en analog indgangspin på Arduino-boardet.
  3. VRy: Dette er den analoge y-akse-udgang. Den leverer en variabel spænding baseret på joystickens vertikale position. Denne pin skal også forbindes til en analog indgangspin på Arduino-boardet.
  4. SW: SW står for switch (knap). Denne pin fungerer som en digital indgang og leverer en logisk lav (GND) eller logisk høj (+5V) afhængig af, om knappen er trykket ned eller ej. Denne pin skal tilsluttes til en digital indgangspin på Arduino-boardet.


Nu, hvor vi har fået en bedre forståelse af joysticket, vil vi dykke dybere ned i kredsløbet for vores projekt og forklare, hvordan det hele er forbundet. Lad os komme i gang!

 

Projektets Kredsløb

Kredsløbet for dette projekt er ikke særlig kompliceret. Vi kan oprette forbindelse mellem vores 20x4 LCD-display og Arduino Uno på samme måde, som vi tidligere har lært i vores blog om at måle afstand med ultrasound-sensoren. Displayets forbindelse til Arduino Uno gør det muligt for os at skrive og vise tekst på displayet i realtid.

Når det kommer til joysticket, har vi nogle simple forbindelser, der skal laves. Først forbinder vi joystickets SW-pin til pin 2Arduino Uno. Dette giver os mulighed for at registrere tryk på joysticketens knap.

For at give strøm til joysticket forbinder vi VCC-pinnen på joysticket til 5V-pinnen på Arduino Uno. Dette sikrer, at joysticket får den nødvendige forsyningsspænding.

Endelig forbinder vi joysticket's VRx-pin til A0-pinnenArduino Uno og VRy-pinnen til A1-pinnenArduino Uno. Disse forbindelser giver os mulighed for at læse de analoge værdier, der genereres af joystickens bevægelser. Nedenfor ses en figur af kredsløbet.

 


Koden

Selvom kredsløbet for dette projekt måske ikke er særlig kompliceret, er koden faktisk den mest avancerede og komplekse kode, vi har arbejdet med hidtil. Koden er ansvarlig for at styre og håndtere input fra joysticket samt styre LCD-displayet i realtid. Denne kode gør brug af forskellige koncepter og teknikker inden for programmering, herunder analoge input, betingede udsagn, loop-strukturer og håndtering af LCD-displayet

Her er koden. Vi vil gå igennem den linje for linje.

#include <Wire.h>               // Inkluderer Wire biblioteket, der bruges til I2C kommunikation
#include <LiquidCrystal_I2C.h>  // Inkluderer LiquidCrystal_I2C biblioteket til styring af I2C LCD

LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7);  // Initialiserer et LiquidCrystal_I2C objekt til at styre LCD

const int VRx = 0;        // Definerer VRx pinnummeret til joystickens x-retning
const int VRy = 1;        // Definerer VRy pinnummeret til joystickens y-retning
const int switchPin = 2;  // Definerer switchPin pinnummeret til joystickens knap
int LCDpos80 = 0;         // Initialiserer variablen LCDpos80 til at holde styr på LCD positionen
bool flip = true;         // En variabel til at skifte mellem at vise og skjule markøren


char line[80][21] = {
  // En todimensional array til at opbevare teksten til hver række på LCD
  "|Hello!             ",  // Første række
  "|You can            ",  // Anden række
  "|write anything     ",  // Tredje række
  "|on this display    "   // Fjerde række
};


void setup() {
  lcd.begin(20, 4);                  // Initialiserer LCD-displayet med 20 tegn pr. linje og 4 linjer
  lcd.setBacklightPin(3, POSITIVE);  // Sætter bagbelysningspin til ben 3 og polaritet som positiv
  lcd.setBacklight(HIGH);            // Tænder for bagbelysningen
  pinMode(switchPin, INPUT);         // Sætter switchPin til input-tilstand
  digitalWrite(switchPin, HIGH);     // Aktiverer den interne pull-up modstand på switchPin

  line[0][19] = '|';  // Indsætter et lodret linjetegn i slutningen af første række
  line[1][19] = '|';  // Indsætter et lodret linjetegn i slutningen af anden række
  line[2][19] = '|';  // Indsætter et lodret linjetegn i slutningen af tredje række
  line[3][19] = '|';  // Indsætter et lodret linjetegn i slutningen af fjerde række
}


void checkJoy() {
  static unsigned long buttonPressStartTime = 0;
  bool buttonPressed = (digitalRead(switchPin) == LOW);

  // Justér positionen til venstre eller højre baseret på VRx-værdien
  if (analogRead(VRx) < 175 && LCDpos80 > 0) {
    LCDpos80--;
  } else if (analogRead(VRx) > 530 && LCDpos80 < 79) {
    LCDpos80++;
  }

  // Justér værdien i den aktuelle placeholder op eller ned baseret på VRy-værdien
  if (LCDpos80 >= 0 && LCDpos80 <= 79) {
    if (analogRead(VRy) < 175 && line[LCDpos80 / 20][LCDpos80 % 20] < 127) {
      line[LCDpos80 / 20][LCDpos80 % 20]++;
    } else if (analogRead(VRy) > 530 && line[LCDpos80 / 20][LCDpos80 % 20] > 32) {
      line[LCDpos80 / 20][LCDpos80 % 20]--;
    }
  }

  // Hvis knappen er trykket ned, gemmes starttiden for knaptrykket
  if (buttonPressed && buttonPressStartTime == 0) {
    buttonPressStartTime = millis();  // Gem starttiden for knaptrykket
  }

  // Hvis knappen er sluppet og der er registreret en starttid for knaptrykket
  if (!buttonPressed && buttonPressStartTime != 0) {
    unsigned long buttonPressDuration = millis() - buttonPressStartTime;
    buttonPressStartTime = 0;  // Nulstil starttiden for knaptrykket


    // Hvis knappen er holdt nede i mindst 1 sekund
    if (buttonPressDuration >= 1000) {
      // Ryd hele displayet
      for (int i = 0; i < 4; i++) {
        for (int j = 0; j < 20; j++) {
          line[i][j] = ' ';
        }
      }
    }
    // Hvis knappen slippes inden for 1 sekund og positionen er inden for gyldigt område
    else if (buttonPressDuration < 1000 && LCDpos80 >= 0 && LCDpos80 <= 79) {
      // Ryd den aktuelle placeholder
      line[LCDpos80 / 20][LCDpos80 % 20] = ' ';
    }
  }
}


void LCD() {                // Funktion til at opdatere LCD-displayet
  int row = LCDpos80 / 20;  // Beregn rækken baseret på værdien af LCDpos80
  int col = LCDpos80 % 20;  // Beregn kolonnen baseret på værdien af LCDpos80

  lcd.setCursor(0, 0);  // Sæt markøren til (0, 0) (øverste venstre hjørne)
  lcd.print(line[0]);   // Udskriv indholdet af line[0] i LCD-displayet

  lcd.setCursor(0, 1);  // Sæt markøren til (0, 1) (anden række)
  lcd.print(line[1]);   // Udskriv indholdet af line[1] i LCD-displayet

  lcd.setCursor(0, 2);  // Sæt markøren til (0, 2) (tredje række)
  lcd.print(line[2]);   // Udskriv indholdet af line[2] i LCD-displayet

  lcd.setCursor(0, 3);  // Sæt markøren til (0, 3) (fjerde række)
  lcd.print(line[3]);   // Udskriv indholdet af line[3] i LCD-displayet

  if (flip) {
    lcd.setCursor(col, row);  // Sæt markøren til den aktuelle position (col, row)
    lcd.print('_');           // Udskriv et understregningstegn i LCD-displayet på den aktuelle position
  }

  flip = !flip;  // Skift værdien af flip-variablen
  delay(100);    // Vent i 100 millisekunder
}


void switchCategory() {
  static unsigned long pressStartTime = 0;
  unsigned long currentTime = millis();  // Deklarér variablen currentTime

  // Tjek om knappen er trykket ned og om den aktuelle placeholder er tom
  bool buttonPressed = (analogRead(VRy) > 530 && line[LCDpos80 / 20][LCDpos80 % 20] == ' ');

  // Hvis knappen er trykket ned og det er første gang, gemmes starttiden for trykket
  if (buttonPressed && pressStartTime == 0) {
    pressStartTime = currentTime;  // Gem starttiden for trykket
  }

  // Hvis knappen slippes og der er registreret en starttid for trykket
  if (!buttonPressed && pressStartTime != 0) {
    unsigned long pressDuration = currentTime - pressStartTime;  // Beregn varigheden af trykket
    pressStartTime = 0;                                          // Nulstil starttiden for trykket

    // Bestem kategorien baseret på trykkets varighed
    if (pressDuration >= 0 && pressDuration < 1000) {
      line[LCDpos80 / 20][LCDpos80 % 20] = 'A';  // Kategori A
    } else if (pressDuration >= 1000 && pressDuration < 2000) {
      line[LCDpos80 / 20][LCDpos80 % 20] = 'a';  // Kategori a
    } else if (pressDuration >= 2000 && pressDuration < 3000) {
      line[LCDpos80 / 20][LCDpos80 % 20] = '1';  // Kategori 1
    } else if (pressDuration >= 3000 && pressDuration < 4000) {
      line[LCDpos80 / 20][LCDpos80 % 20] = '.';  // Kategori .

      // Tilføj flere betingelser for yderligere kategorier efter behov
    }
  }
}


void loop() {        // Hovedløkken for programmet
  checkJoy();        // Kald checkJoy-funktionen for at håndtere joystick-input
  LCD();             // Kald LCD-funktionen for at opdatere LCD-displayet
  switchCategory();  // Kald switchCategory-funktionen for at skrive hurtigere
}

 

Lad os kigge lidt nærmere på koden...

#include <Wire.h>           	// Vi inkluderer Wire-biblioteket, som giver os mulighed for at kommunikere via I2C-protokollen.
#include <LiquidCrystal_I2C.h>  // Vi inkluderer LiquidCrystal_I2C-biblioteket, der giver os funktioner til at styre vores I2C-LCD.

LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7);  // Vi initialiserer et LiquidCrystal_I2C-objekt med den specifikke I2C-adresse (0x27) og tilsluttede pins på Arduinoen (2, 1, 0, 4, 5, 6, 7). Dette objekt vil blive brugt til at styre vores LCD-display

Denne del af koden inkluderer de nødvendige biblioteker for at kunne kommunikere med vores I2C-LCD og initialisere et objekt, lcd, af typen LiquidCrystal_I2C. Vi specificerer også de relevante tilsluttede pins på Arduinoen. Ved at inkludere disse biblioteker og initialisere objektet, er vi klar til at styre vores LCD-display og vise tekst på det.

 

 

const int VRx = 0;    	// Vi definerer VRx som variabel og tildeler den pinnummeret (0) til joystickens x-retning.
const int VRy = 1;    	// Vi definerer VRy som variabel og tildeler den pinnummeret (1) til joystickens y-retning.
const int switchPin = 2;  // Vi definerer switchPin som variabel og tildeler den pinnummeret (2) til joystickens knap.
int LCDpos80 = 0;     	// Vi initialiserer variablen LCDpos80 til 0 for at holde styr på LCD'ens position.
bool flip = true;     	// Vi opretter en boolsk variabel ved navn "flip" og tildeler den værdien "true". Denne variabel bruges til at skifte mellem at vise og skjule markøren.

Disse linjer med kode definerer og initialiserer de nødvendige variable til vores joystick og LCD-display. VRx repræsenterer pinnummeret til joystickens x-retning, VRy repræsenterer pinnummeret til joystickens y-retning, og switchPin repræsenterer pinnummeret til joystickets knap.

 

Variablen LCDpos80 bruges til at holde styr på positionen på LCD-displayet. Den vil blive brugt senere i koden til at placere markøren korrekt.

flip er en boolsk variabel, der starter med værdien true. Denne variabel vil blive brugt til at skifte mellem at vise og skjule markøren på LCD-displayet senere i koden.

 

char line[80][21] = {
  // En todimensional array til at opbevare teksten til hver række på LCD
  "|Hello!         	",  // Første række
  "|You can        	",  // Anden række
  "|write anything 	",  // Tredje række
  "|on this display	"   // Fjerde række
};
Denne del af koden opretter en todimensionel array ved navn line. Denne array bruges til at opbevare teksten, der skal vises på hver række af LCD-displayet.

Arrayet har en størrelse på 80 rækker og hver række har en størrelse på 21 tegn. Det giver os mulighed for at gemme op til 80 forskellige tekstlinjer på displayet, hvor hver linje kan have op til 21 tegn.

I eksemplet er der allerede indtastet tekst til de fire første rækker i arrayet. Hver række er omgivet af anførselstegn (") og afsluttes med komma (,). Dette repræsenterer en tekstlinje, der skal vises på LCD-displayet.

Du kan tilpasse eller tilføje dine egne tekster til hver række ved blot at redigere arrayet. Vær opmærksom på, at hver tekstlinje skal have en længde på højst 20 tegn (plus det ekstra tegn til terminering af strengen).

Med andre ord så, denne del af koden giver os mulighed for at initialisere vores LCD-display med foruddefineret tekst, som vi kan arbejde med og manipulere senere i koden.


 

void setup() {
  lcd.begin(20, 4);              	// Initialiserer LCD-displayet med 20 tegn pr. linje og 4 linjer
  lcd.setBacklightPin(3, POSITIVE);  // Sætter bagbelysningspin til ben 3 og polaritet som positiv
  lcd.setBacklight(HIGH);        	// Tænder for bagbelysningen
  pinMode(switchPin, INPUT);     	// Sætter switchPin til input-tilstand
  digitalWrite(switchPin, HIGH); 	// Aktiverer den interne pull-up modstand på switchPin

  line[0][19] = '|';  // Indsætter et lodret linjetegn i slutningen af første række
  line[1][19] = '|';  // Indsætter et lodret linjetegn i slutningen af anden række
  line[2][19] = '|';  // Indsætter et lodret linjetegn i slutningen af tredje række
  line[3][19] = '|';  // Indsætter et lodret linjetegn i slutningen af fjerde række
}
2 / 2
I setup()-funktionen udføres den indledende konfiguration og initialisering af vores projekt. Lad os gennemgå koden linje for linje:
cpp
void setup() {
  lcd.begin(20, 4);                  // Initialiserer LCD-displayet med 20 tegn pr. linje og 4 linjer
  lcd.setBacklightPin(3, POSITIVE);  // Sætter bagbelysningspin til ben 3 og polaritet som positiv
  lcd.setBacklight(HIGH);            // Tænder for bagbelysningen
  pinMode(switchPin, INPUT);         // Sætter switchPin til input-tilstand
  digitalWrite(switchPin, HIGH);     // Aktiverer den interne pull-up modstand på switchPin

  line[0][19] = '|';  // Indsætter et lodret linjetegn i slutningen af første række
  line[1][19] = '|';  // Indsætter et lodret linjetegn i slutningen af anden række
  line[2][19] = '|';  // Indsætter et lodret linjetegn i slutningen af tredje række
  line[3][19] = '|';  // Indsætter et lodret linjetegn i slutningen af fjerde række
}

I setup()-funktionen gør vi følgende:

  1. lcd.begin(20, 4);: Vi initialiserer LCD-displayet ved at kalde begin()-metoden på vores lcd-objekt. Vi angiver, at displayet har 20 tegn pr. linje og 4 linjer i alt.
  2. lcd.setBacklightPin(3, POSITIVE);: Vi angiver, at bagbelysningspinden er tilsluttet ben 3 på Arduino og polariteten er positiv. Dette fortæller LCD-biblioteket, hvor bagbelysningen er forbundet.
  3. lcd.setBacklight(HIGH);: Vi tænder for bagbelysningen på LCD-displayet ved at kalde setBacklight()-metoden og give den argumentet HIGH.
  4. pinMode(switchPin, INPUT);: Vi indstiller switchPin til input-tilstand ved at kalde pinMode()-funktionen og angive pinnummeret og tilstanden.
  5. digitalWrite(switchPin, HIGH);: Vi aktiverer den interne pull-up modstand på switchPin ved at kalde digitalWrite()-funktionen og angive pinnummeret og værdien HIGH. Dette sikrer, at knapens input er højt, når den ikke er blevet trykket ned.

De fire sidste linjer i setup()-funktionen er beregnet til at demonstrere, hvordan man kan manipulere den indledende tekst på LCD-displayet, når enheden booter. Ved at tilføje et lodret linjetegn (|) i slutningen af hver af de fire rækker i line-arrayet ændrer vi den oprindelige tekst, der vises på displayet under opstart. Dette giver os mulighed for at tilføje en visuel adskillelse mellem teksterne på displayet og tilpasse den indledende præsentation af information. Du kan eksperimentere med at ændre teksten og layoutet for at opnå den ønskede visuelle effekt på LCD-displayet.

 

 

void checkJoy() {
  static unsigned long buttonPressStartTime = 0;
  bool buttonPressed = (digitalRead(switchPin) == LOW);

  // Justér positionen til venstre eller højre baseret på VRx-værdien
  if (analogRead(VRx) < 175 && LCDpos80 > 0) {
	LCDpos80--;
  } else if (analogRead(VRx) > 530 && LCDpos80 < 79) {
	LCDpos80++;
  }

checkJoy()-funktionen er ansvarlig for at overvåge og håndtere joystickens bevægelser og knaptryk. Først oprettes en statisk variabel buttonPressStartTime, som bruges til at holde styr på starttiden for et knaptryk.

Derefter oprettes en boolsk variabel buttonPressed, der kontrollerer, om knappen er blevet trykket ned. Dette gøres ved at læse tilstanden af switchPin og sammenligne den med LOW-tilstanden.

Herefter følger en betingelsesblok. Hvis joystickens VRx-værdi (x-retningen) er mindre end 175 og LCDpos80 (LCD-displayets position) er større end 0, justeres LCDpos80 til venstre ved at formindskes med 1. Dette giver en flytning af markøren mod venstre på LCD-displayet.

På samme måde, hvis VRx-værdien er større end 530 og LCDpos80 er mindre end 79, justeres LCDpos80 til højre ved at øges med 1. Dette flytter markøren mod højre på LCD-displayet.

Denne del af koden giver brugeren mulighed for at styre markørens position på displayet ved at bevæge joystickens x-retning til venstre eller højre.

Bemærk, at værdierne 175 og 530 kan justeres efter behov for at tilpasse joystickens bevægelsesfølsomhed og markørens bevægelseshastighed på displayet.

 

 

// Justér værdien i den aktuelle placeholder op eller ned baseret på VRy-værdien 
if (LCDpos80 >= 0 && LCDpos80 <= 79) 
 { if (analogRead(VRy) < 175 && line[LCDpos80 / 20][LCDpos80 % 20] < 127) { line[LCDpos80 / 20][LCDpos80 % 20]++; } 
 else if (analogRead(VRy) > 530 && line[LCDpos80 / 20][LCDpos80 % 20] > 32) { line[LCDpos80 / 20][LCDpos80 % 20]--;
 } 
}

I ovenstående del af koden i checkJoy()-funktionen behandles joystickens VRy-værdi (y-retningen) for at justere værdien i den aktuelle placeholder (tegnposition) på LCD-displayet.

Først kontrolleres det, om LCDpos80 er inden for det tilladte område af placeholder-positionsintervallet (0-79). Dette sikrer, at ændringer kun finder sted, når markøren er placeret inden for det synlige område på LCD-displayet.

Derefter følger en betingelsesblok, der håndterer forskellige situationer afhængigt af joystickens VRy-værdi. Hvis VRy-værdien er mindre end 175 og den aktuelle placeholder-værdi (line[LCDpos80 / 20][LCDpos80 % 20]) er mindre end 127 (ASCII-værdien for det højeste tegn), øges placeholder-værdien med 1. Dette skifter tegnet til det næste i ASCII-tegnkoden og øger dets værdi.

På samme måde, hvis VRy-værdien er større end 530 og den aktuelle placeholder-værdi er større end 32 (ASCII-værdien for det laveste tegn), formindskes placeholder-værdien med 1. Dette skifter tegnet til det forrige i ASCII-tegnkoden og mindsker dets værdi.

Disse justeringer i placeholder-værdien giver brugeren mulighed for at ændre det aktuelle tegn på LCD-displayet opad eller nedad ved at bevæge joystickens y-retning.


tegn på LCD-displayet opad eller nedad ved at bevæge joystickens y-retning.
// Hvis knappen er trykket ned, gemmes starttiden for knaptrykket
  if (buttonPressed && buttonPressStartTime == 0) {
	buttonPressStartTime = millis();  // Gem starttiden for knaptrykket
  }

  // Hvis knappen er sluppet og der er registreret en starttid for knaptrykket
  if (!buttonPressed && buttonPressStartTime != 0) {
	unsigned long buttonPressDuration = millis() - buttonPressStartTime;
	buttonPressStartTime = 0;  // Nulstil starttiden for knaptrykket
	// Hvis knappen er holdt nede i mindst 1 sekund
	if (buttonPressDuration >= 1000) {
  	// Ryd hele displayet
  	for (int i = 0; i < 4; i++) {
    	for (int j = 0; j < 20; j++) {
      	line[i][j] = ' ';
    	}
  	}
	}
	// Hvis knappen slippes inden for 1 sekund og positionen er inden for gyldigt område
	else if (buttonPressDuration < 1000 && LCDpos80 >= 0 && LCDpos80 <= 79) {
  	// Ryd den aktuelle placeholder
  	line[LCDpos80 / 20][LCDpos80 % 20] = ' ';
	}
  }
}

I den sidste del af checkJoy()-funktionen håndteres knaptryk og deres varighed. Her er en gennemgang af koden:

Først kontrolleres det, om knappen er trykket ned (buttonPressed) og om der allerede er gemt en starttid for knaptrykket (buttonPressStartTime == 0). Hvis dette er tilfældet, gemmes den aktuelle tid ved hjælp af millis()-funktionen.

Derefter kontrolleres det, om knappen er blevet sluppet (!buttonPressed) og om der er en gyldig starttid for knaptrykket (buttonPressStartTime != 0). Hvis dette er tilfældet, beregnes varigheden af knaptrykket ved at trække starttiden fra den aktuelle tid (millis() - buttonPressStartTime). Derefter nulstilles starttiden for knaptrykket (buttonPressStartTime = 0).

Hvis knappen er blevet holdt nede i mindst 1 sekund (buttonPressDuration >= 1000), slettes hele indholdet på displayet. Dette opnås ved at gennemgå hver række og hver placeholder og sætte dem til mellemrumstegnet (' ').

Hvis knappen derimod slippes inden for 1 sekund (buttonPressDuration < 1000) og markøren er inden for det gyldige område (LCDpos80 >= 0 && LCDpos80 <= 79), slettes kun det aktuelle tegn i placeholderen ved at sætte det til mellemrumstegnet (' ').

Denne del af koden giver mulighed for at reagere på knaptryk og udføre forskellige handlinger afhængigt af knappens varighed og markørens position på LCD-displayet.

 

 

void LCD() {            	// Funktion til at opdatere LCD-displayet
  int row = LCDpos80 / 20;  // Beregn rækken baseret på værdien af LCDpos80
  int col = LCDpos80 % 20;  // Beregn kolonnen baseret på værdien af LCDpos80
  lcd.setCursor(0, 0);  // Sæt markøren til (0, 0) (øverste venstre hjørne)
  lcd.print(line[0]);   // Udskriv indholdet af line[0] i LCD-displayet
  lcd.setCursor(0, 1);  // Sæt markøren til (0, 1) (anden række)
  lcd.print(line[1]);   // Udskriv indholdet af line[1] i LCD-displayet
  lcd.setCursor(0, 2);  // Sæt markøren til (0, 2) (tredje række)
  lcd.print(line[2]);   // Udskriv indholdet af line[2] i LCD-displayet

  lcd.setCursor(0, 3);  // Sæt markøren til (0, 3) (fjerde række)
  lcd.print(line[3]);   // Udskriv indholdet af line[3] i LCD-displayet
  if (flip) {
	lcd.setCursor(col, row);  // Sæt markøren til den aktuelle position (col, row)
	lcd.print('_');       	// Udskriv et understregningstegn i LCD-displayet på den aktuelle position
  }
  flip = !flip;  // Skift værdien af flip-variablen
  delay(100);	// Vent i 100 millisekunder
}
LCD()-funktionen bruges til at opdatere LCD-displayet med teksten fra arrayet line[]. Her er en forklaring af koden:

Først beregnes den aktuelle række og kolonne baseret på værdien af LCDpos80. Rækken beregnes som LCDpos80 / 20, og kolonnen som LCDpos80 % 20.

Derefter bruges lcd.setCursor()-funktionen til at angive markørens position på LCD-displayet. For hver række (0 til 3) angives markøren til den korrekte række (0 til 3) og derefter udskrives indholdet af den tilsvarende række i line[] ved hjælp af lcd.print()-funktionen.

Efter udskrivningen af linjerne tjekkes værdien af flip. Hvis den er sand, sættes markøren til den aktuelle position (col, row) ved hjælp af lcd.setCursor(), og et understregningstegn ('_') udskrives på den aktuelle position ved hjælp af lcd.print().

Til sidst skifter værdien af flip ved at negere den (flip = !flip), så markøren skifter position ved hver opdatering af LCD-displayet. Der ventes i 100 millisekunder ved hjælp af delay(100) for at skabe en visuel effekt.

Denne funktion sikrer, at teksten fra line[]-arrayet vises korrekt på LCD-displayet, og at en markør ('_') blinker ved den aktuelle position for at angive, hvor brugeren kan redigere teksten.

 

void switchCategory() {
  static unsigned long pressStartTime = 0;
  unsigned long currentTime = millis();  // Deklarér variablen currentTime

  // Tjek om knappen er trykket ned og om den aktuelle placeholder er tom
  bool buttonPressed = (analogRead(VRy) > 530 && line[LCDpos80 / 20][LCDpos80 % 20] == ' ');

  // Hvis knappen er trykket ned og det er første gang, gemmes starttiden for trykket
  if (buttonPressed && pressStartTime == 0) {
	pressStartTime = currentTime;  // Gem starttiden for trykket
  }

  // Hvis knappen slippes og der er registreret en starttid for trykket
  if (!buttonPressed && pressStartTime != 0) {
	unsigned long pressDuration = currentTime - pressStartTime;  // Beregn varigheden af trykket
	pressStartTime = 0;                                      	// Nulstil starttiden for trykket

	// Bestem kategorien baseret på trykkets varighed
	if (pressDuration >= 0 && pressDuration < 1000) {
  	line[LCDpos80 / 20][LCDpos80 % 20] = 'A';  // Kategori A
	} else if (pressDuration >= 1000 && pressDuration < 2000) {
  	line[LCDpos80 / 20][LCDpos80 % 20] = 'a';  // Kategori a
	} else if (pressDuration >= 2000 && pressDuration < 3000) {
  	line[LCDpos80 / 20][LCDpos80 % 20] = '1';  // Kategori 1
	} else if (pressDuration >= 3000 && pressDuration < 4000) {
  	line[LCDpos80 / 20][LCDpos80 % 20] = '.';  // Kategori .

  	// Tilføj flere betingelser for yderligere kategorier efter behov
	}
  }
}

switchCategory()-funktionen bruges til at skifte kategori for den aktuelle placeholder baseret på trykket på joystickens knap. Her er en forklaring af koden:

Først initialiseres en variabel pressStartTime til at gemme starttiden for knaptrykket, og currentTime opdateres med den aktuelle tid ved hjælp af millis()-funktionen.

Derefter kontrolleres det, om knappen er trykket ned (buttonPressed) og om den aktuelle placeholder er tom (line[LCDpos80 / 20][LCDpos80 % 20] == ' ').

Hvis knappen er trykket ned og det er første gang, der registreres et tryk (pressStartTime == 0), gemmes starttiden for trykket (pressStartTime = currentTime).

Når knappen slippes (!buttonPressed) og der er en gyldig starttid for trykket (pressStartTime != 0), beregnes varigheden af trykket ved at trække starttiden fra den aktuelle tid (currentTime - pressStartTime). Derefter nulstilles starttiden for trykket (pressStartTime = 0).

Herefter bestemmes kategorien baseret på trykkets varighed. Hvis varigheden er mellem 0 og 1000 millisekunder, sættes placeholderen til 'A' (kategori A). Hvis varigheden er mellem 1000 og 2000 millisekunder, sættes placeholderen til 'a' (kategori a), og så videre for yderligere kategorier. Du kan tilføje flere betingelser for at definere flere kategorier efter behov.

Denne funktion giver mulighed for at skifte kategori for den aktuelle placeholder ved at trykke på joystickens knap i forskellige tidsintervaller. Det kan bruges til at organisere og gruppere information på LCD-displayet.

void loop() {    	// Hovedløkken for programmet
  checkJoy();    	// Kald checkJoy-funktionen for at håndtere joystick-input
  LCD();         	// Kald LCD-funktionen for at opdatere LCD-displayet
  switchCategory();  // Kald switchCategory-funktionen for at skrive hurtigere
}

 

loop()-funktionen er den hovedløkke, hvor programmet kører kontinuerligt. Her er en forklaring af koden:

I loop()-funktionen kaldes tre forskellige funktioner:

  1. checkJoy()-funktionen kaldes for at håndtere input fra joysticket. Denne funktion kontrollerer, om joysticket bevæges i x-retningen for at justere positionen til venstre eller højre. Den kontrollerer også joysticket i y-retningen for at justere værdien i den aktuelle placeholder op eller ned. Desuden håndterer den knaptryk og reaktioner på knaptrykket som beskrevet tidligere.
  2. LCD()-funktionen kaldes for at opdatere LCD-displayet. Denne funktion indstiller markørens position og udskriver indholdet af hver linje fra line[]-arrayet på det tilsvarende sted på LCD-displayet. Den sørger også for, at markøren blinker ved den aktuelle position.
  3. switchCategory()-funktionen kaldes for at muliggøre hurtigere skrivning ved at skifte kategorien for den aktuelle placeholder på LCD-displayet. Denne funktion registrerer knaptryk og beregner varigheden af trykket. Baseret på trykkets varighed bestemmes en kategori, og den aktuelle placeholder på LCD-displayet opdateres med den tilsvarende værdi.

Disse tre funktioner kaldes i loopet for at sikre, at input fra joysticket håndteres, LCD-displayet opdateres, og hurtig skrivning muliggøres i programmet. Loopet fortsætter med at køre i en kontinuerlig cyklus, hvilket giver en responsiv og interaktiv brugeroplevelse.


Med denne guide har vi gennemgået et projekt, hvor vi har brugt et KY-023 joystick til at interagere med et LCD-display ved hjælp af en Arduino. Selvom kredsløbet for dette projekt måske ikke er særlig kompliceret, har koden vist sig at være den mest udfordrende og spændende del i dag. Vi har udforsket forskellige funktioner som at justere markørens position, ændre værdien i placeholders og skifte kategorier, alt sammen ved hjælp af input fra joysticket.

Vi håber, at du har nydt denne guide og fundet den nyttig. Joysticks kan åbne døren til mange spændende muligheder, og vi opfordrer dig til at udforske og eksperimentere med dem. God kodning og sjov og vi ses til det næste projekt!

Skriv kommentar!

Relevante produkter

TS101 digital loddekolbeTS101 digital loddekolbe i hånd
TS101 digital loddekolbe med USB C forsyning
Tilbudspris Fra 699,00 kr
27 på lager
TS80P USB-C Loddekolbe kitTS80P Loddekolbe
TS80P USB-C Loddekolbe kit
Tilbudspris Fra 799,00 kr
10 på lager
bruge Loddekolbe Renser til at rengøre loddekolbespidsenLoddekolbe Renser
Luksus Loddekolbe renser
Tilbudspris 89,00 kr
13 på lager