Waveshare

Kategória: Elektronika.

Áttekintés

Ezt a cikket 2025 szeptemberében írom. Ráfutottam a BangGood-on erre a fejlesztő lapkára:

waveshare.jpg

Pár hónappal korábban készítettem el az IdeaSpark leírást, ez ehhez hasonló. Megtetszett a viszonylag nagy méretű kijelzője, az árát (16.55$) pedig elfogadhatóak tartottam egy kísérletezéshez.

Az eszközt négyféle formában hozzák forgalomba: a lábakat forrasztva vagy forrasztás nélkül, ill. közvetlen USB bemenettel (A típus) valamint anélkül (C típus). Véletlenül a forrasztás nélküli A típust választottam, ami rossz döntés volt, ugyanis nagyon nehéz hozzáférni a házi forrasztáshoz. De egyszerű kísérletezéshez, melynek során nem kapcsolom össze más eszközökkel, ez is megteszi.

Beüzemelése

Áttekintés

A hivatalosnak tekinthető dokumentáció itt található: https://www.waveshare.com/wiki/RP2350-LCD-1.47-A. Háromféle módot mutat be:

  • Python fejlesztés a Thonny fejlesztőkörnyezetben.
  • C++ fejlesztés Visual Studio Code-ban
  • C++ fejlesztés Arduino IDE-ben

Előzetes fontos információ: a feltöltés a következőképpen működik:

  • A BOOT nyomógomb nyomva tartásával kell vagy az USB-be dugni, vagy ha már ott van, megnyomni a RST gombot, és csak ezt követően elengedi a BOOT gombot.
  • Ezzel D: meghajtóként jelenik meg, és oda kell feltölteni az uf2 kiterjesztésű fájlt.
  • A RST újbóli megnyomásával újraindul az eszköz.

Python

  • Töltsük le a https://www.waveshare.com/wiki/RP2350-LCD-1.47-A oldalon Thonny a Resources alatt a demót. Közvetlen link: https://files.waveshare.com/wiki/RP2350-LCD-1.47/RP2350-LCD-1.47.zip.
  • Egy USB-C adatkábellel (fontos, hogy NE töltőkábellel!) kapcsoljuk a fejlesztőlapkát a számítógéphez oly módon, hogy még csatlakozás előtt megnyomjuk és nyomva tartjuk a BOOT gombot alul, és csak akkor engedjük el, ha már hozzákapcsoltuk. (Alternatíva: rádugjuk, megnyomjuk és nyomva tartjuk a BOOT gombot, megnyomjuk majd elengedjük a RST gombot, és csak ezt követően engedjük el a RST gombot.)
  • Ekkor D meghajtóként megjelenik az eszköz.
  • A demóban (RP2350-LCD-1.47.zip) van egy ilyen fájl: Python/RPI_PICO2-20250415-v1.25.0.uf2; ezt másoljuk a D: gyökérbe. Ez teszi lehetővé azt, hogy futtassunk Python fájlokat.
  • Húzzuk ki az eszközt, és dugjuk vissza normál módban, tehát most NE nyomjuk meg indításkor egyik gombot se. (Vagy egyszerűen nyomjuk meg a RST gombot.)
  • Töltsük le a Thonny fejlesztőkörnyezetet a https://thonny.org/ oldalról (közvetlen link: https://github.com/thonny/thonny/releases/download/v3.3.3/thonny-3.3.3.exe), telepítsük fel és indítsuk el.
  • A jobb alsó sarokban kattintsunk a három vízszintes vonalra → Configure interpreter… Itt felül válasszuk ki a MicroPython (Raspberry Pi Pico) elemet. A Port on WebREPL meg kell, hogy találja ezt: Board CDC @ COM5} (ill megfelelő portszám), majd OK.
  • Felül kattintsunk a STOP gombra. Alul valami ilyesmit kell látnunk:
MicroPython v1.25.0 on 2025-04-15; Raspberry Pi Pico2 with RP2350
Type "help()" for more information.
>>> 

MPY: soft reboot
MicroPython v1.25.0 on 2025-04-15; Raspberry Pi Pico2 with RP2350

Type "help()" for more information.

>>>
  • Válasszuk ki ezt: View → Files. Bal oldalon megjelenik a könyvtárrendszer.
  • A demó fájlban 3 demó van. Válasszuk ki valamelyiket, pl. ezt: Python/01-LCD/RP2350-LCD-1.47.py, kattintsunk jobb egérgombbal, majd válasszuk ki ezt: Upload to /.
  • Kattintsunk duplán a fájlnévre, hogy megjelenjen a szerkesztőben. Ekkor kattintsunk fent a zöld indítás gombra. Ha minden rendben történt, megjelenik a program az eszközön.
  • Saját program írásához szükségünk van erre a példafájlra, viszont ahhoz, hogy importálni tudjuk, át kell neveznünk úgy, hogy ne tartalmazzon kötőjelet és pontot, pl. erre: RP2350_LCD_1_47.py. A könyvtár maradhat, mert az eszközön a gyökérbe kerül (ld. a fájlkezelő alatt). Ebben a formában is töltsük fel. (A másikat törölhetjük.)
  • Készítsük el a helloworld.py alkalmazást a következőképpen (mindegy, hogy hova kerül a saját gépünkön, mert az eszközön a gyökérbe kerül):
from machine import Pin, PWM
import RP2350_LCD_1_47
 
pwm = PWM(Pin(21))
pwm.freq(1000)
pwm.duty_u16(32768)
LCD = RP2350_LCD_1_47.LCD_1inch47()
LCD.fill(0xffff)
LCD.show()
LCD.write_text("Hello, Pico world!", 20, 50, 2, 0x0000)
LCD.show()
  • Töltsük fel és indítsuk el a fent bemutatott módon. Ha minden megfelelően működött, akkor a saját feliratunkat kell látnunk.
  • Ahhoz, hogy a fejlesztőkörnyezeten kívül is használni tudjuk, a fájlt át kell neveznünk erre: main.py. Ha így rákötjük egy USB töltőre (és ekkor már elég a töltő, nem kell az adatkábel), megjelenik a felirat.

Összefoglalva:

  • Először BOOT + kapcsolódás + elenged.
  • D:\ gyökérben uf2 másol
  • Utána normál módban kapcsol + Thonny-ban STOP, majd feltölt

C++ fejlesztés Arduino IDE-ben

Szükséges beállítások:

  • File → Preferences… → Additional board manager URLs: https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json (ha már van ott valami, akkor vesszővel elválaszthatjuk)
  • Tools → Board → Boards Manager… → a keresőbe írjuk be ezt: pico → telepítsük fel ezt: Raspberry Pi Pico/RP2040/RP2350 by Earle F. Philhower
  • Sketch → Include Library → Manage Libraries… → telepítsük fel az alábbiakat:
    • Adafruit NeoPixel by Adafruit
    • GFX Library for Arduino by Moon On Our Nation
  • Dugjuk rá a mikrovezérlőt.
  • Tools → Board → Raspberry Pi Pico/RP2040/RP2350 → Generic RP2350
  • Tools → Flash Size → 16MB (Sketch: 2MB, FS: 14MB)
  • Tools → Port → COMx

Másoljuk be az alábbi LED villogó programot:

#include <Adafruit_NeoPixel.h>
 
#define PIN_BACKLIGHT 21  // A kijelző világítása
#define PIN_NEOPIXEL  22  // Az RGB LED lába
#define NUMPIXELS     1
 
Adafruit_NeoPixel pixels(NUMPIXELS, PIN_NEOPIXEL, NEO_GRB + NEO_KHZ800);
 
void setup() {
  Serial.begin(115200);
 
  // 1. Kijelző háttérvilágítás bekapcsolása
  pinMode(PIN_BACKLIGHT, OUTPUT);
  digitalWrite(PIN_BACKLIGHT, HIGH); 
 
  // 2. NeoPixel indítása
  pixels.begin();
  pixels.setBrightness(50);
}
 
void loop() {
  // Piros fény
  pixels.setPixelColor(0, pixels.Color(150, 0, 0));
  pixels.show();
  Serial.println("LED: Piros");
  delay(1000);
 
  // Zöld fény
  pixels.setPixelColor(0, pixels.Color(0, 150, 0));
  pixels.show();
  Serial.println("LED: Zöld");
  delay(1000);
}

Felül kattintsunk az Upload ikonra. Ha minden rendben zajlott, a piros és a zöld fény váltakozik.

C++ fejlesztés Pico SDK segítségével

Ez az "anyanyelve" ennek az eszköznek. Telepítés és beállítás:

  • Telepítsük fel és indítsuk el a Visual Studio Code-ot (https://code.visualstudio.com/).
  • Telepítsük fel a Raspberry Pi Pico kiegészítőt (Extensions ikon bal oldalon → a keresőbe be kell írni a kiegészítő nevét).
  • Bal oldalon megjelenik Raspberry Pi Pico menü, egy mikrovezérlő ikonnal. Kattintsunk rá.
  • Válasszuk ki ezt: General → New C/C++ Project
  • Name: tetszőleges (pl. pico_test)
  • Board type: Pico 2
  • Select Pico SDK version: hagyjuk alapértelmezetten (nálam v2.2.0)
  • Lent válasszuk ki a Console over USB checkboxot, a többit hagyjuk alapértelmezetten.
  • Create

Ez először hosszabb ideig eltart. Ha végzett, bal oldalon a projekt nézetben látunk fájlokat. Nyissuk meg ezt CMakeLists.txt. Keressük meg ezt: target_link_libraries. Adjuk a hozzá ezt: hardware_spi. A többit hagyjuk meg alapértelmezettnek. Például a projekt neve pico_test, akkor (némi formázás után) így néz ki:

# Add the standard library to the build
target_link_libraries(
    pico_test
    pico_stdlib
    hardware_spi
)

A kód (a példában pico_test.c) a következő:

#include <stdio.h>
#include "pico/stdlib.h"
#include "hardware/spi.h"
 
int main() {
    stdio_init_all();
    sleep_ms(2000);
 
    printf("Hello az RP2350 SDK-bol!\n");
    printf("Architektura teszt indul...\n");
 
    while (true) {
        printf("A processzor dolgozik...\n");
        sleep_ms(1000);
    }
}

Ezt követően fordítsuk le a projektet. Ezt a következő lehetőségek valamelyikével tudjuk megtenni:

  • Bal oldalon válasszuk ki a Raspberry Pi Pico Project ikont → Compile Project
  • Alul, kissé jobbra kattintsunk a Compile-ra

A tapasztalatom szerint nagyon könnyen hibára futunk. Ilyenkor a lehetőségek:

  • Lépjünk ki a Visual Studio Code-ból, töröljük a build könyvtárat, majd indítsuk újra.
  • Kérdezzük valamelyik nagy nyelvi modellt.

Töltsük föl a programot az eszközre.

  • A BOOT gombot nyomva tartva dugjuk be az USB portba, vagy ha már be van dugva, akkor a BOOT gombot nyomva tartva nyomjuk meg a RESET gombot.
  • Ezzel megjelenik a D: meghajtó. Másoljuk rá a build könyvtárban található uf2 fájl a D: gyökérbe. Nálam ez az a fájl: c:\prog\pico-sdk\pico_test\build\pico_test.uf2.

Figyeljük a működést:

  • Bal oldalon kattintsunk a Raspberry Pi Pico Project ikonra.
  • Kattintsunk a Serial Monitor fülre.
  • A Port elvileg automatikusan ki van töltve a megfelelő értékre, pl. COM3.
  • A BAUD rate legyen (maradjon) 115200.
  • Kattintsunk a Start Monitoring-ra.

Ha minden rendben ment, akkor a következőt kell látnunk: A processzor dolgozik… Valójában ez már régóta írogatja, csak idáig nem olvastuk. Sajnos azok az üzenetek, amelyek nem monitorozza, elvesznek. Emiatt kell az elején a 2 másodperces szünet. Most, hogy nyitva van a Serial Monitor, nyomjuk meg a RESET gombot, és tartsuk nyomva. Ekkor a Start Monitor elhalványítva kell, hogy megjelenjen. Amint elengedtük és ismét kékké válik, minél gyorsabban kattintsunk rá. Ha elég gyorsak vagyunk, akkor az első két printf eredményét is látjuk.

Sebesség teszt

A sebesség tesztet a következőképpen hajtjuk végre:

  • Megvalósítjuk a prímellenőrzés oly módon, hogy 2-től a szám négyzetgyökéig megvizsgáljuk, hogy van-e osztója.
  • Megszámoljuk, hogy hány prímszám van 100000-ig.
  • Megmérjük, hogy mennyi idő alatt számolja ki.

Prímellenőrzés Pythonban

Másoljuk be a fent leírtak szerint előkészített Thonny fejlesztőkörnyezetbe az alábbi programot és futtassuk le:

import time
from machine import Pin
 
def is_prime(n):
    i = 2
    while i*i <= n:
        if n % i == 0:
            return False
        i += 1
    return True
 
def count_primes(limit):
    count = 0
    for i in range(2, limit + 1):
        if is_prime(i):
            count += 1
    return count
 
limit = 100000
print(f"Prim szamolas 1-tol {limit}-ig (MicroPython)...")
 
start_time = time.ticks_ms()
result = count_primes(limit)
end_time = time.ticks_ms()
 
duration = time.ticks_diff(end_time, start_time)
 
print(f"Talalt primek szama: {result}")
print(f"Idotartam: {duration} ms")

Eredmény:

Prim szamolas 1-tol 100000-ig (MicroPython)...
Talalt primek szama: 9592
Idotartam: 12613 ms

Prímellenőrzés Arduino C++-ban, RISC processzoron

A fent leírtak alapján kezdjük el a folyamatot. A következőt állítsuk be:

  • Tools → CPU Architecture → RISC-V

Másoljuk be az alábbi programot:

void setup() {
  Serial.begin(115200);
  while (!Serial);
 
  long limit = 100000;
  long count = 0;
 
  Serial.print("Prim szamolas 1-tol ");
  Serial.print(limit);
  Serial.println("-ig...");
 
  unsigned long start = millis();
 
  for (long n = 2; n <= limit; n++) {
    bool isPrime = true;
    for (long i = 2; i * i <= n; i++) {
      if (n % i == 0) {
        isPrime = false;
        break;
      }
    }
    if (isPrime) count++;
  }
 
  unsigned long end = millis();
 
  Serial.print("Talalt primek szama: ");
  Serial.println(count);
  Serial.print("Idotartam: ");
  Serial.print(end - start);
  Serial.println(" ms");
}
 
void loop() {}

Nyissuk meg a Serial Monitort (Tools → Serial Monitor, vagy jobb felső sarokban a Serial Monitor ikon). Jobb oldalon a Baud-ot állítsuk erre: 115200. Nagyjából ezt kell látnunk:

Prim szamolas 1-tol 100000-ig...
Talalt primek szama: 9592
Idotartam: 430 ms

Prímellenőrzés Arduino C++-ban, ARM processzoron

Mindent ugyanúgy kell csinálni, mint az előzőnél, viszont az ARM architektúrát kell kiválasztani:

  • Tools → CPU Architecture → ARM

Eredmény:

Prim szamolas 1-tol 100000-ig...
Talalt primek szama: 9592
Idotartam: 320 ms

Láthatjuk, hogy az ARM processzor segítségével gyorsabb a számolás.

Prímellenőrzés Pico SDK segítségével, RISC processzoron, egy magon

A fent leírt módon hozzunk létre egy projektet, válasszuk ki a RISC processzort, majd töltsük fel és futtassuk le az alábbi programot:

#include <stdio.h>
#include "pico/stdlib.h"
#include "pico/time.h"
 
bool is_prime(int n) {
    if (n < 2) return false;
    for (int i = 2; i * i <= n; i++) {
        if (n % i == 0) return false;
    }
    return true;
}
 
int main() {
    stdio_init_all();
    sleep_ms(2000);
 
    printf("\n--- RP2350 Natív SDK Prím Teszt ---\n");
    int limit = 100000;
    int count = 0;
 
    printf("Számolás 1-től %d-ig...\n", limit);
    uint64_t start = time_us_64();
 
    for (int n = 2; n <= limit; n++) {
        if (is_prime(n)) {
            count++;
        }
    }
    uint64_t end = time_us_64();
        uint64_t duration_us = end - start;
    float duration_ms = duration_us / 1000.0f;
 
    printf("Talált prímek száma: %d\n", count);
    printf("Időtartam: %llu us (kb. %.3f ms)\n", duration_us, duration_ms);
    printf("-----------------------------------\n");
 
    while (true) {
        tight_loop_contents();
    }
}

Az eredmény nálam ez lett:

--- RP2350 Natív SDK Prím Teszt ---
Számolás 1-től 100000-ig...
Talált prímek száma: 9592
Időtartam: 424329 us (kb. 424.329 ms)

Azaz egy picit gyorsabb mint az Arduino IDE-ben.

Prímellenőrzés Pico SDK segítségével, ARM processzoron, egy magon

Most hajtsuk végre ugyanezt, de ne legyen kiválasztva a RISC. Váltás az architektúrák között:

  • Jobbra lent kattintsunk a Board: pico2-re
  • Válasszuk ki ismét a pico2-t
  • Megkérdezi, hogy RISC-V-t szeretnénk-e. Itt ha Yes-t válaszolunk, akkor RISC-V lesz (marad), No esetén pedig átvált ARM-ra.

A CMakeLists.txt fájlban keressük meg ezt a sort RISC esetén:

set(toolchainVersion RISCV_ZCB_RPI_2_2_0_3)

Ill. ezt ARM esetén:

set(toolchainVersion 14_2_Rel1)

A kód ugyanaz. Fordítsuk újra a COmpile segítségével, majd töltsük fel a fent leírt módon. Eredmény:

--- RP2350 Natív SDK Prím Teszt ---
Számolás 1-től 100000-ig...
Talált prímek száma: 9592
Időtartam: 296860 us (kb. 296.860 ms)

Ez is picivel gyorsabb mint az ennek megfelelő Arduino IDE-ben.

Prímellenőrzés Pico SDK segítségével, RISC processzoron, két magon

Az ESP32 kétmagos processzort tartalmaz, most használjuk ki! Ehhez a CMakeLists.txt fájlban a target_link_libraries-hez adjuk hozzá ezt: pico_multicore.

target_link_libraries(
    pico_test
    pico_stdlib
    hardware_spi
    pico_multicore
)

Először RISK-V processzoron hajtsuk végre.

A megvalósításnál némi trükköt kell alkalmazni: a tesztek felét az egyik, a másik felét pedig a másik magon hajtjuk végre. Ahhoz, hogy nagyjából kiegyenlített legyen, nem azt a módszert alkalmazzuk, hogy az első ötvenezret az egyik, a második ötvenezret meg a másik ellenőrzi, viszont az se jó, hogy a párosakat az egyik a páratlanokat meg a másik, ugyanis a párosaknál gyorsan kiderül, hogy nem prím. Tehát az egyik a 3, 7, 11 stb. értékeket ellenőrzi, míg a másik az 5, 9, 13 stb. Ez olyan értelemben "csalás" a másikhoz képest, hogy eleve nem vesszük figyelembe a páros számokat, olyannyira, hogy a kettest ellenőrzés nélkül prímnek vesszük. De így tudtuk megvalósítani a práhuzamos futtatást. A kód:

#include <stdio.h>
#include "pico/stdlib.h"
#include "pico/multicore.h"
#include "pico/time.h"
 
bool is_prime(int n) {
    if (n < 2) return false;
    if (n == 2) return true;
    if (n % 2 == 0) return false;
    for (int i = 3; i * i <= n; i += 2) {
        if (n % i == 0) return false;
    }
    return true;
}
 
int limit = 100000;
 
// Core 1 feladata: 5, 9, 13, 17...
void core1_entry() {
    int count = 0;
    for (int n = 5; n <= limit; n += 4) {
        if (is_prime(n)) count++;
    }
    multicore_fifo_push_blocking(count);
}
 
int main() {
    stdio_init_all();
    sleep_ms(2000);
 
    printf("\n--- RP2350 BALANCED DUAL-CORE TEST ---\n");
    uint64_t start = time_us_64();
 
    multicore_launch_core1(core1_entry);
 
    // Core 0 feladata: 3, 7, 11, 15... 
    // Kezdőérték 1, mert a 2-est (páros prím) már idevesszük.
    int core0_count = 1; 
    for (int n = 3; n <= limit; n += 4) {
        if (is_prime(n)) core0_count++;
    }
 
    int core1_count = multicore_fifo_pop_blocking();
    uint64_t end = time_us_64();
 
    printf("Core 0 (3, 7, 11...) talált: %d\n", core0_count);
    printf("Core 1 (5, 9, 13...) talált: %d\n", core1_count);
    printf("Összesen: %d\n", core0_count + core1_count);
    printf("Időtartam: %llu us (kb. %.3f ms)\n", end - start, (end - start) / 1000.0f);
    printf("--------------------------------------\n");
 
    while (true) { tight_loop_contents(); }
}

Az eredmény:

--- RP2350 BALANCED DUAL-CORE TEST ---
Core 0 (3, 7, 11...) talált: 4809
Core 1 (5, 9, 13...) talált: 4783
Összesen: 9592
Időtartam: 104857 us (kb. 104.857 ms)

Prímellenőrzés Pico SDK segítségével, ARM processzoron, két magon

Végül hajtsuk végre a sebességtesztet ARM processzoron, két magon. A forráskód ugyanaz mint az előző, a processzor típus váltást pedig a fent leírtak szerint hajtsuk végre. Nélam ez lett az eredmény:

--- RP2350 BALANCED DUAL-CORE TEST ---
Core 0 (3, 7, 11...) talált: 4809
Core 1 (5, 9, 13...) talált: 4783
Összesen: 9592
Időtartam: 68704 us (kb. 68.704 ms)
--------------------------------------

Ez messze a legjobb.

Összefoglaló

A márt értékek az alábbiak:

Módszer Sebesség (ms)
Python 12613.000
Arduino C++ RISC 430.000
Arduino C++ ARM 320.000
Pico SDK RISC 424.329
Pico SDK ARM 296.860
Pico SDK RISC, 2 mag 104.857
Pico SDK ARM, 2 mag 68.704

Összefoglalás:

  • A C++ és a Python között óriási a szakadék.
  • Az ARM egyértelműen gyorsabb mint a RISC.
  • A Pico SDK egy nagyon picit gyorsabb mint az Arduino C++.
  • A kétmagos futtatás sokkal gyorsabb mint az egymagos.

Kipróbáltam az optimalizálást egymagos esetben is, és meglepő módon nem sokat javított (290.571 ms a 296.860 helyett). Ez amiatt furcsa, mert így töredékére csökkent a futásidő, pedig arra számítottam, hogy legjobb esetben felére fog visszaesni.

GUI példák

C++-ban sajnos nem sikerült olyan alkalmazást készíteni, ami kihasználja a képernyőt, így az alábbiak mindegyike Pythonban készült.

Színváltó

Az alábbi program a következő lehetőségeket mutatja be:

  • Kiírás a képernyőre.
  • Háttér LED világítás beállítása.
  • Nyomógomb.

Az alkalmazás úgy működik, hogy a háttér LED-et alapból pirosra állítja, és kiírja, hogy a szín piros, majd a BOOT gomb megnyomásával először kékre, majd zöldre, végül simét pirosra vált.

import machine
import time
import rp2
import RP2350_LCD_1_47
 
# --- PIO NEOPIXEL DRIVER (RGB SORRENDRE JAVITVA) ---
@rp2.asm_pio(sideset_init=rp2.PIO.OUT_LOW, out_shiftdir=rp2.PIO.SHIFT_LEFT, autopull=True, pull_thresh=24)
def ws2812():
    T1, T2, T3 = 2, 5, 3
    wrap_target()
    label("bitloop")
    out(x, 1)               .side(0)    [T3 - 1]
    jmp(not_x, "do_zero")   .side(1)    [T1 - 1]
    jmp("bitloop")          .side(1)    [T2 - 1]
    label("do_zero")
    nop()                   .side(0)    [T2 - 1]
    wrap()
 
# PIO inicializalasa a 22-es labon
sm = rp2.StateMachine(0, ws2812, freq=8_000_000, sideset_base=machine.Pin(22))
sm.active(1)
 
def set_led(r, g, b):
    # Itt tortent a javitas: r megy az elso 8 bitre, g a masodikra (RGB sorrend)
    dimmer = 0.2 # 20% fenyero
    data = (int(r*dimmer) << 16) | (int(g*dimmer) << 8) | int(b*dimmer)
    sm.put(data << 8)
 
# --- LCD ES VEZERLES ---
pwm = machine.PWM(machine.Pin(21))
pwm.freq(1000)
pwm.duty_u16(32768)
 
LCD = RP2350_LCD_1_47.LCD_1inch47()
 
# Szin lista es nevek (szigoruan ekezetmentesen a kodban)
szinek = [(255,0,0), (0,0,255), (0,255,0)]
nevek = ["PIROS", "KEK", "ZOLD"]
idx = 0
 
def frissit(i):
    # LED beallitasa
    set_led(*szinek[i])
 
    # Kijelzo frissitese
    LCD.fill(0xFFFF)
    LCD.write_text("SZINKRONIZALT LED", 20, 30, 2, 0x0000)
    LCD.write_text("SZIN: " + nevek[i], 20, 80, 2, 0xF800)
    LCD.show()
 
# Elso inditas
frissit(idx)
last_state = 0
 
print("Rendszer kesz. RGB sorrend beallitva.")
 
while True:
    curr_state = rp2.bootsel_button()
    if curr_state == 1 and last_state == 0:
        idx = (idx + 1) % 3
        print("Valtas ide:", nevek[idx])
        frissit(idx)
        time.sleep(0.2)
    last_state = curr_state
    time.sleep(0.01)

Reakcióidő mérő

A fentiek segítségével egy játékoz hozunk létre. A játék a BOOT gombbal indul. A háttérszín alapból piros. Amikor zöldre vált, akkor minél előbb meg kell nyomni a BOOT gombot. A játék kiírja a váltás és a nyomás között eltelt időt.

import machine
import time
import rp2
import random
import RP2350_LCD_1_47
 
# --- 1. PIO NEOPIXEL DRIVER (RGB SORREND) ---
@rp2.asm_pio(sideset_init=rp2.PIO.OUT_LOW, out_shiftdir=rp2.PIO.SHIFT_LEFT, autopull=True, pull_thresh=24)
def ws2812():
    T1, T2, T3 = 2, 5, 3
    wrap_target()
    label("bitloop")
    out(x, 1)               .side(0)    [T3 - 1]
    jmp(not_x, "do_zero")   .side(1)    [T1 - 1]
    jmp("bitloop")          .side(1)    [T2 - 1]
    label("do_zero")
    nop()                   .side(0)    [T2 - 1]
    wrap()
 
sm = rp2.StateMachine(0, ws2812, freq=8_000_000, sideset_base=machine.Pin(22))
sm.active(1)
 
def set_led(r, g, b):
    dimmer = 0.2
    # Az előző teszt alapján az RGB sorrend a megfelelő
    data = (int(r*dimmer) << 16) | (int(g*dimmer) << 8) | int(b*dimmer)
    sm.put(data << 8)
 
# --- 2. LCD ÉS HÁTTÉRVILÁGÍTÁS ---
pwm = machine.PWM(machine.Pin(21))
pwm.freq(1000)
pwm.duty_u16(32768)
 
LCD = RP2350_LCD_1_47.LCD_1inch47()
 
def uzenet(sor1, sor2="", szin=0x0000):
    LCD.fill(0xFFFF)
    LCD.write_text("REAKCIO MERO", 25, 20, 2, 0x001F) # Kék cím
    LCD.write_text(sor1, 15, 80, 2, szin)
    if sor2:
        LCD.write_text(sor2, 15, 120, 2, szin)
    LCD.show()
 
# --- 3. JÁTÉK LOGIKA ---
print("Reakcioido mero inditasa...")
 
while True:
    # Készenléti állapot
    set_led(0, 0, 255) # Kék
    uzenet("NYOMD MEG A", "BOOT GOMBOT!")
 
    # Várjuk a gomb megnyomását az indításhoz
    while not rp2.bootsel_button():
        time.sleep(0.01)
    # Várjuk meg, amíg felengedi
    while rp2.bootsel_button():
        time.sleep(0.01)
 
    # Felkészülés szakasz
    uzenet("KESZULJ...", "", 0xF800)
    set_led(255, 0, 0) # Piros
 
    # Véletlenszerű várakozás 2 és 5 másodperc között
    varakozas = random.uniform(2, 5)
    start_pont = time.ticks_ms()
    csalt = False
 
    while time.ticks_diff(time.ticks_ms(), start_pont) < (varakozas * 1000):
        if rp2.bootsel_button():
            csalt = True
            break
        time.sleep(0.01)
 
    if csalt:
        uzenet("TUL KORAN!", "PROBALD UJRA!", 0xF800)
        set_led(255, 255, 0) # Sárga (hiba)
        time.sleep(2)
        continue
 
    # RAJT szakasz
    set_led(0, 255, 0) # Zöld
    # uzenet("MOST!!!", "RAJT!", 0x07E0)
 
    stopper_start = time.ticks_ms()
 
    # Várjuk a reakciót (gombnyomást)
    while not rp2.bootsel_button():
        pass
 
    reakcio_ido = time.ticks_diff(time.ticks_ms(), stopper_start)
 
    # Eredmény megjelenítése
    set_led(255, 255, 255) # Fehér villanás
 
    # Ha 300ms alatt van, zölddel írjuk ki, egyébként feketével
    eredmeny_szin = 0x07E0 if reakcio_ido < 300 else 0x0000
    uzenet("IDOD:", str(reakcio_ido) + " ms", eredmeny_szin)
 
    print("Meres eredmenye:", reakcio_ido, "ms")
 
    # 3 másodperc várakozás a következő kör előtt
    time.sleep(3)

Óra

Az alábbi kód egy mutatós órát rajzol ki:

import machine
import time
import math
import RP2350_LCD_1_47
 
# LCD inicializalasa
pwm = machine.PWM(machine.Pin(21))
pwm.freq(1000)
pwm.duty_u16(32768)
LCD = RP2350_LCD_1_47.LCD_1inch47()
 
# Kozeppontok (Landscape driver beallitas alapjan)
CX, CY = 160, 86
RADIUS = 70
 
def rajzol_mutato(fok, hossz, szin):
    # Radian kalkulacio
    theta = (fok - 90) * 0.0174533
    step = 2
    for r in range(0, hossz, step):
        px = int(CX + r * math.cos(theta))
        py = int(CY + r * math.sin(theta))
        if 0 <= px < 320 and 0 <= py < 172:
            LCD.rect(px, py, 2, 2, szin)
 
while True:
    t = time.localtime()
    o, p, m = t[3], t[4], t[5]
    LCD.fill(0xFFFF)
 
    # Szamlap pontjai
    for i in range(0, 360, 30):
        theta = i * 0.0174533
        px = int(CX + RADIUS * math.cos(theta))
        py = int(CY + RADIUS * math.sin(theta))
        LCD.rect(px-1, py-1, 3, 3, 0x0000)
 
    # Masodperc: Piros, picit hosszabb
    rajzol_mutato(m * 6, 68, 0x0FF0) 
    # Perc: Fekete (0x0000)
    rajzol_mutato(p * 6, 58, 0x0000)
    # Ora: Fekete (0x0000), rovidebb
    rajzol_mutato((o % 12) * 30 + p * 0.5, 42, 0x0000)
 
    LCD.show()
    time.sleep(0.1)

Hőmérő

Hogy lássunk szenzor adatot is, az alábbi program egy hőmérő. Igazából az eszköz belső hőmérsékletét mutatja, amit szándékosan felfelé tolunk számítás intenzív műveletekkel.

import machine
import time
import _thread
import RP2350_LCD_1_47
 
# LCD inicializalasa
pwm = machine.PWM(machine.Pin(21))
pwm.freq(1000)
pwm.duty_u16(32768)
LCD = RP2350_LCD_1_47.LCD_1inch47()
 
# Szenzor beallitasa
sensor_temp = machine.ADC(4)
factor = 3.3 / 65535
 
# --- Core 1: CPU FUTES ---
def heater():
    while True:
        # Vegtelen ciklus matematikai muveletekkel
        _ = 500 * 500
        _ = _ / 2
 
_thread.start_new_thread(heater, ())
 
while True:
    # Meres
    reading = sensor_temp.read_u16() * factor
    # RP2350 homerseklet keplete
    temp = 27 - (reading - 0.706) / 0.001721
 
    LCD.fill(0xFFFF)
    LCD.write_text("CPU MONITOR", 20, 30, 2, 0x001F)
 
    # Szoftveres tizedes-megjelenites a NoneType hiba ellen
    egesz = int(temp)
    tizedes = int((temp * 10) % 10)
    temp_text = "Homerseklet: " + str(egesz) + "." + str(tizedes) + " C"
 
    LCD.write_text(temp_text, 10, 80, 2, 0xF800)
 
    # Vizualis sav (min 20C, max 60C)
    width = int((temp - 20) * 5)
    width = max(0, min(280, width))
    LCD.rect(20, 130, width, 30, 0x07E0)
 
    LCD.show()
    time.sleep(0.5)

Vélemény

Ígéretes, de nagyon nehézkes. Nagyon sok órám elment a beüzemeléssel, melynek során intenzíven használtam a Geminit és a saját tapasztalataimat is. Sajnos nem tudtam rögtön dokumentálni, és amikor később visszatértem rá, ismét sok órám elment vele. Ezt nagyin nehézkesnek tartom, és nem javaslom jó szívvel oktatási célra.

Rengeteget próbálkoztam a grafikus felület C++-ban történő programozásával, de sajnos nem sikerült.

A másik hiányosság a kevés nyomógomb. 2-3 általános célú gomb sokat dobna rajta.

Ígéretesen bizonyult a specifikációja alapján, de sajnos túlzottan nehézkes a használata.

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License