RP2350 - úvod: Rozdiel medzi revíziami

Zo stránky 3D liga wiki
Prejsť na navigáciu Prejsť na vyhľadávanie
Sebastian (diskusia | príspevky)
Sebastian (diskusia | príspevky)
Bez shrnutí editace
Riadok 51: Riadok 51:
=== Zapisovanie do pamäte ===
=== Zapisovanie do pamäte ===


Doska má 520 kB SRAM, do ktorej sa zapisuje kód, ktorý sa po zapnutí spustí. Ďalej má 4 MB flash pamäte, do ktorej môžeme zapisovať dáta.
Doska má 520 kB SRAM, do ktorej sa zapisuje kód, ktorý sa po zapnutí spustí. Ďalej má 4 MB flash pamäte, do ktorej môžeme zapisovať dáta, a to dvoma spôsobmi – podrobný návod a ukážkový kód pre každý z nich nájdeš na jeho podstránke:
 
Dáta môžeme zapisovať dvoma spôsobmi:
 
# Cez EEPROM knižnicu – jednoduché a pre malé množstvo dát (do 4 kB, jeden súbor)
# Cez súborový systém (LittleFS) zložitejšie a pre viac dát so štruktúrou (viac ako 4 kB, dlhodobé snímanie)
 
==== EEPROM ====
 
Aby sme mohli s pamäťou pracovať, musíme si ju najprv rezervovať (alokovať). Rezervovať si ju môžeme po bajtoch, až do 4096 bajtov, čo je jeden blok pamäte. Do tohto bloku nám nič nemôže zasahovať okrem nášho programu.
 
Je to podobné, ako keby sme si v hoteli rezervovali izbu – môžeme si v nej robiť, čo chceme, a jedine my máme kľúč od izby, takže sa do nej nedostane nikto iný.
 
Keď si pamäť rezervujeme, môžeme do nej zapisovať, čo chceme – napríklad namerané vzdialenosti z ultrazvukového senzora.
 
Treba dávať pozor na to, že rezervovanú pamäť máme aj adresovanú, a to od bajtu 0 po náš zvolený bajt − 1. Každé číslo, znak či dátový typ pritom v pamäti zaberá inú veľkosť:


{| class="wikitable"
{| class="wikitable"
! Dátový typ !! Veľkosť
! Spôsob !! Na čo sa hodí
|-
| bool, byte, char || 1 bajt
|-
| short || 2 bajty
|-
| int, unsigned int || 4 bajty
|-
|-
| long, unsigned long || 4 bajty
| [[RP2350-Zero/EEPROM|EEPROM]] || Jednoduché, pre malé množstvo dát (do 4 kB, jeden súbor)
|-
|-
| float || 4 bajty
| [[RP2350-Zero/LittleFS|LittleFS]] || Skutočný súborový systém, pre viac dát so štruktúrou (viac ako 4 kB, dlhodobé snímanie)
|-
| double || 8 bajtov
|}
|}


Ak si nie si istý veľkosťou konkrétneho typu, over si ju priamo v kóde príkazom <code>sizeof(premenná)</code>.
=== Dve jadrá a dve architektúry (Arm / RISC-V) ===


Všetky testovacie programy nájdeš v File → Examples → EEPROM.
RP2350 má vo vnútri celkovo štyri jadrá – dvojicu '''Arm Cortex-M33''' a dvojicu '''RISC-V (Hazard3)''' – naraz je ale možné použiť len jednu z týchto dvoch dvojíc, nie všetky štyri súčasne.


'''Zápis'''
'''Voľba architektúry (Arm alebo RISC-V)'''


<syntaxhighlight lang="cpp">
Ktorá dvojica jadier sa použije, sa nastavuje v Arduino IDE cez '''Tools → CPU Architecture → Arm''' alebo '''RISC-V'''. Nejde o prepínanie za behu programu – ide o nastavenie pre celý sketch, takže po zmene treba program nahrať odznova.
#include <EEPROM.h>


void setup() {
Pre bežné použitie (a takmer všetky knižnice v našej stavebnici) postačí predvolený Arm režim. RISC-V je skôr na experimentovanie – niektoré knižnice pod ním zatiaľ nemusia fungovať (napr. FreeRTOS).
  Serial.begin(115200);
  EEPROM.begin(256);      // rezervuje 256 bajtov "EEPROM" priestoru vo flashi (max. 4096)


  EEPROM.write(0, 123);  // zapíše hodnotu 123 na adresu 0
'''Použitie oboch jadier naraz (multicore)'''
  EEPROM.commit();        // POVINNÉ – reálne zapíše do flashe (inak zostane len v RAM cache)


  byte hodnota = EEPROM.read(0);
Bez ohľadu na zvolenú architektúru vie RP2350 spúšťať kód na oboch jadrách naraz. Popri známych funkciách <code>setup()</code>/<code>loop()</code> (tie bežia na jadre 0) stačí do sketchu pridať funkcie <code>setup1()</code>/<code>loop1()</code> – tie automaticky pobežia paralelne na jadre 1:
  Serial.print("Zapísaná hodnota: ");
  Serial.println(hodnota);
}
 
void loop() {
}
</syntaxhighlight>
 
Ak chceme zapisovať aj viacbajtové typy (napr. <code>int</code> alebo <code>float</code>), nemusíme ich rozkladať na jednotlivé bajty ručne – knižnica má na to funkcie <code>EEPROM.put()</code> a <code>EEPROM.get()</code>, ktoré si samy poradia so správnym počtom bajtov podľa typu premennej:


<syntaxhighlight lang="cpp">
<syntaxhighlight lang="cpp">
#include <EEPROM.h>
// Jadro 0 - hlavna logika (napr. citanie senzorov)
 
int adresa = 0;
 
void setup() {
void setup() {
   Serial.begin(115200);
   Serial.begin(115200);
  EEPROM.begin(256);
  float vzdialenost = 23.5;
  EEPROM.put(adresa, vzdialenost);      // zapíše všetkých sizeof(float) = 4 bajty naraz
  EEPROM.commit();
  adresa += sizeof(float);
  vzdialenost += 10;
  EEPROM.put(adresa, vzdialenost);
  EEPROM.commit();
  float nacitanaHodnota;
  EEPROM.get(adresa, nacitanaHodnota);  // prečíta správny počet bajtov automaticky
  Serial.print("Načítaná hodnota: ");
  Serial.println(nacitanaHodnota);
}
void loop() {
}
</syntaxhighlight>
'''Čítanie'''
Ak chceš z pamäte iba čítať (napríklad po reštarte dosky, keď chceš zistiť naposledy uloženú hodnotu):
<syntaxhighlight lang="cpp">
#include <EEPROM.h>
int adresa = 0;
void setup() {
  Serial.begin(115200);
  EEPROM.begin(256);
  byte hodnota = EEPROM.read(ardesa);
  Serial.print("Hodnota na adrese 0: ");
  Serial.println(hodnota);
}
}


void loop() {
void loop() {
}
   Serial.println("Jadro 0 bezi...");
</syntaxhighlight>
 
'''Vynulovanie'''
 
Ak chceš celú rezervovanú pamäť vynulovať (napríklad pred novým meraním):
 
<syntaxhighlight lang="cpp">
#include <EEPROM.h>
 
void setup() {
  EEPROM.begin(256);
 
  for (int i = 0; i < 256; i++) {
    EEPROM.write(i, 0);  // 0 používame ako "prázdnu" hodnotu
  }
  EEPROM.commit();        // bez tohto sa vynulovanie neuloží natrvalo
 
  Serial.begin(115200);
   Serial.println("Pamäť vynulovaná.");
}
 
void loop() {
}
</syntaxhighlight>
 
==== LittleFS ====
 
Na rozdiel od EEPROM (jeden blok bajtov, adresovaný číslom) je LittleFS skutočný '''súborový systém''' – vieš v ňom mať viacero súborov s vlastnými menami, prípadne aj priečinky, podobne ako na počítači. Hodí sa vtedy, keď chceš uložiť viac dát (viac ako 4 kB) alebo dáta so štruktúrou (napr. samostatný súbor pre každé meranie).
 
'''Nastavenie dosky'''
 
Skôr než LittleFS použiješ, treba vo flash pamäti vyhradiť miesto pre súborový systém – v Arduino IDE to nastavíš cez '''Tools → Flash Size''', kde zvolíš rozdelenie, ktoré obsahuje aj časť pre FS (napríklad niečo ako "2MB (Sketch: 1MB, FS: 1MB)" – presné položky menu sa môžu podľa verzie balíka pre RP2350 líšiť, tak si over aktuálny zoznam priamo v IDE). Bez tohto nastavenia LittleFS nemá kde fyzicky existovať a <code>begin()</code> zlyhá.
 
[[File: Flash-size.png | 400px]]
 
'''Štruktúra súborov'''
 
Všetky cesty v LittleFS začínajú od koreňového priečinka <code>/</code> – napríklad súbor <code>data.txt</code> uložený priamo v koreni má cestu <code>/data.txt</code>. LittleFS podporuje aj podpriečinky, takže si vieš dáta usporiadať napríklad takto:
 
<pre>
/
├── config.txt
└── logs/
    ├── log_01.txt
    └── log_02.txt
</pre>
 
Priečinok si vytvoríš pomocou <code>LittleFS.mkdir("/logs")</code>, súbor v ňom potom otvoríš cestou <code>/logs/log_01.txt</code>.
 
Pred prvým použitím treba súborový systém "nabehnúť" (a pri prvom spustení na novej doske sa automaticky naformátuje):
 
<syntaxhighlight lang="cpp">
#include <LittleFS.h>
 
void setup() {
  Serial.begin(115200);
   delay(1000);
   delay(1000);
  if (!LittleFS.begin()) {
    Serial.println("LittleFS sa nepodarilo spustit!");
    return;
  }
  Serial.println("LittleFS pripraveny.");
}
void loop() {
}
</syntaxhighlight>
'''Vytvorenie a zápis súboru'''
Mód <code>"w"</code> súbor vytvorí (ak neexistuje) alebo prepíše jeho obsah (ak existuje):
<syntaxhighlight lang="cpp">
File f = LittleFS.open("/data.txt", "w");
if (f) {
  f.println("Prvy riadok dat");
  f.println("Druhy riadok dat");
  f.close();
  Serial.println("Zapisane.");
} else {
  Serial.println("Nepodarilo sa otvorit súbor na zapis!");
}
}
</syntaxhighlight>


'''Čítanie súboru'''
// Jadro 1 - bezi paralelne s jadrom 0 (napr. blikanie LED)
 
void setup1() {
Mód <code>"r"</code> otvorí súbor len na čítanie – <code>f.available()</code> hovorí, či ešte zostávajú nejaké neprečítané bajty:
   pinMode(LED_BUILTIN, OUTPUT);
 
<syntaxhighlight lang="cpp">
File f = LittleFS.open("/data.txt", "r");
if (f) {
   while (f.available()) {
    Serial.write(f.read());
  }
  f.close();
} else {
  Serial.println("Súbor neexistuje!");
}
}
</syntaxhighlight>


'''Appendovanie (pripájanie na konec)'''
void loop1() {
 
  digitalWrite(LED_BUILTIN, HIGH);
Mód <code>"a"</code> na rozdiel od <code>"w"</code> existujúci obsah nevymaže – nový text sa pripíše na koniec súboru. Hodí sa napríklad na priebežné logovanie:
  delay(200);
 
   digitalWrite(LED_BUILTIN, LOW);
<syntaxhighlight lang="cpp">
   delay(200);
File f = LittleFS.open("/data.txt", "a");
if (f) {
   f.println("Dalsi zaznam, ktory sa priplete na koniec");
   f.close();
}
}
</syntaxhighlight>
</syntaxhighlight>


'''Poznámka:''' pred otvorením súboru sa oplatí overiť, či existuje, pomocou <code>LittleFS.exists("/data.txt")</code> – napríklad ak chceš pri prvom spustení vytvoriť súbor len raz a pri ďalších spusteniach doňho už len appendovať.
Pár vecí, na ktoré si treba dať pozor:
* Obe jadrá si delia len 8 kB zásobníka (stack) – pri multicore sa rozdelí na 4 kB + 4 kB (namiesto plných 8 kB pre jedno jadro), takže vo <code>setup1()</code>/<code>loop1()</code> netreba používať príliš veľké lokálne premenné či polia.
* Nie je bezpečné volať tú istú perifériu (napr. <code>Serial.print()</code>) súčasne z oboch jadier bez synchronizácie – môže to spôsobiť nepredvídateľné správanie.
* Ak treba jadro 1 reštartovať alebo pozastaviť, dajú sa použiť funkcie <code>rp2040.restartCore1()</code> a <code>rp2040.resumeOtherCore()</code> (názov "rp2040" v knižnici ostáva zachovaný aj na RP2350 kvôli spätnej kompatibilite).


__notoc__
__notoc__

Verzia z 19:43, 8. september 2026

Späť do zoznamu| HW príprava RP2350-zero

Opis

RP2350-Zero je malá vývojová doska od firmy Waveshare, postavená na čipe RP2350 (rovnaký čip ako v novšom Raspberry Pi Pico 2). Ide o kompaktnú alternatívu k bežnému Pico formátu – je výrazne menšia, a preto sa hodí presne tam, kde je málo miesta, ako je to aj v našej stavebnici.

Hlavné vlastnosti:

  • Čip RP2350 s dvoma jadrami, ktoré je možné prepnúť medzi Arm Cortex-M33 a RISC-V (Hazard3) – pre bežné použitie postačí predvolený Arm režim
  • Takt do cca 150 MHz
  • 520 kB SRAM priamo na čipe + externá 4 MB flash pamäť na uloženie programu (a prípadne aj vlastných súborov)
  • USB-C konektor (napájanie aj nahrávanie firmvéru)
  • Tlačidlo BOOT (na prepnutie do režimu nahrávania firmvéru) a tlačidlo RESET
  • Jedna onboard RGB LED (WS2812/NeoPixel), ovládateľná jediným pinom
  • Podpora PIO (Programmable I/O) – špeciálna periféria RP2350, ktorá vie v hardvéri "napodobniť" takmer akýkoľvek komunikačný protokol


V našej stavebnici je RP2350-Zero "mozog" robota – riadi servá, číta senzory a komunikuje cez USB s počítačom.

Pre účely variability našej stavebnice sme k RP2350-Zero vybrali aj expanznú podložku s vyvedenými VCC a GND pinmi. Má aj svoj vlastný držiak, ktorý sa pomocou M2 skrutiek priskrutkuje k expanznej podložke.

Poznámka: presné číslovanie pinov a niektoré detaily (napr. veľkosť flash pamäte na konkrétnej revízii dosky) si over v oficiálnej dokumentácii Waveshare – ide o pomerne nový produkt a údaje sa medzi revíziami môžu líšiť.

GPIO piny

GPIO (General Purpose Input/Output) sú piny, cez ktoré doska komunikuje s okolitým svetom – môžu fungovať ako digitálny vstup (čítanie stavu, napr. tlačidlo), digitálny výstup (zapínanie/vypínanie, napr. LED) alebo majú aj špeciálne funkcie.

Nasledujú typy funkcií, ktoré piny na RP2350 zvládajú (nie každý pin vie všetko naraz – funkciu si vždy nastavuje program). Podrobné vysvetlenie a testovací kód pre jednotlivé protokoly nájdeš na ich podstránkach – klikni na názov funkcie v tabuľke:

Funkcia Na čo slúži Príklad z našej stavebnice
Digitálny vstup/výstup Zapnutie/vypnutie, čítanie stavu tlačidla alebo spínača Joystick tlačidlo
PWM (Pulse Width Modulation) Riadenie servomotorov, stmievanie LED Servo, LED modul
ADC (analógový vstup) Čítanie analógovej hodnoty (napätia) Joystick, mikrofón
I2C Komunikácia so senzormi/displejmi cez 2 vodiče (SDA, SCL) Gyroskop BNO055, laser VL53L0X
UART Sériová komunikácia (napr. debug výpisy medzi dvoma doskami alebo LCD displejom) Zatiaľ nevyužité
SPI Rýchlejšia komunikácia, napr. SD karta Zatiaľ nevyužité

Zapisovanie do pamäte

Doska má 520 kB SRAM, do ktorej sa zapisuje kód, ktorý sa po zapnutí spustí. Ďalej má 4 MB flash pamäte, do ktorej môžeme zapisovať dáta, a to dvoma spôsobmi – podrobný návod a ukážkový kód pre každý z nich nájdeš na jeho podstránke:

Spôsob Na čo sa hodí
EEPROM Jednoduché, pre malé množstvo dát (do 4 kB, jeden súbor)
LittleFS Skutočný súborový systém, pre viac dát so štruktúrou (viac ako 4 kB, dlhodobé snímanie)

Dve jadrá a dve architektúry (Arm / RISC-V)

RP2350 má vo vnútri celkovo štyri jadrá – dvojicu Arm Cortex-M33 a dvojicu RISC-V (Hazard3) – naraz je ale možné použiť len jednu z týchto dvoch dvojíc, nie všetky štyri súčasne.

Voľba architektúry (Arm alebo RISC-V)

Ktorá dvojica jadier sa použije, sa nastavuje v Arduino IDE cez Tools → CPU Architecture → Arm alebo RISC-V. Nejde o prepínanie za behu programu – ide o nastavenie pre celý sketch, takže po zmene treba program nahrať odznova.

Pre bežné použitie (a takmer všetky knižnice v našej stavebnici) postačí predvolený Arm režim. RISC-V je skôr na experimentovanie – niektoré knižnice pod ním zatiaľ nemusia fungovať (napr. FreeRTOS).

Použitie oboch jadier naraz (multicore)

Bez ohľadu na zvolenú architektúru vie RP2350 spúšťať kód na oboch jadrách naraz. Popri známych funkciách setup()/loop() (tie bežia na jadre 0) stačí do sketchu pridať funkcie setup1()/loop1() – tie automaticky pobežia paralelne na jadre 1:

// Jadro 0 - hlavna logika (napr. citanie senzorov)
void setup() {
  Serial.begin(115200);
}

void loop() {
  Serial.println("Jadro 0 bezi...");
  delay(1000);
}

// Jadro 1 - bezi paralelne s jadrom 0 (napr. blikanie LED)
void setup1() {
  pinMode(LED_BUILTIN, OUTPUT);
}

void loop1() {
  digitalWrite(LED_BUILTIN, HIGH);
  delay(200);
  digitalWrite(LED_BUILTIN, LOW);
  delay(200);
}

Pár vecí, na ktoré si treba dať pozor:

  • Obe jadrá si delia len 8 kB zásobníka (stack) – pri multicore sa rozdelí na 4 kB + 4 kB (namiesto plných 8 kB pre jedno jadro), takže vo setup1()/loop1() netreba používať príliš veľké lokálne premenné či polia.
  • Nie je bezpečné volať tú istú perifériu (napr. Serial.print()) súčasne z oboch jadier bez synchronizácie – môže to spôsobiť nepredvídateľné správanie.
  • Ak treba jadro 1 reštartovať alebo pozastaviť, dajú sa použiť funkcie rp2040.restartCore1() a rp2040.resumeOtherCore() (názov "rp2040" v knižnici ostáva zachovaný aj na RP2350 kvôli spätnej kompatibilite).