
Passive rpi hub75-adapter
hzeller/rpi-rgb-led-matrix
Controlling up to three chains of 64x64, 32x32, 16x32 or similar RGB LED displays using Raspberry Pi GPIO

A kapcsolási rajzot a KiCad 8.0.2 programmal hoztam létre. Középpontjában egy Arduino Nano Socket áll.
Hardware Test is an open-source printed circuit board by martinvichnal, from the martinvichnal/Hardware-Test repository on GitHub. It is a 2-layer board with 2 parts on 32 nets.
It belongs with the AVR (ATmega, ATtiny) boards of this library.
A kapcsolási rajzot a KiCad 8.0.2 programmal hoztam létre. Középpontjában egy Arduino Nano Socket áll.
A kapcsolási rajzon a J1-es jellel ellátott foglalaton kivezettem az Arduino UART lábait ezzel könnyedén debuggerelni lehet a kommunikációs rését a rendszernek.
| Neve | Jele | GPIO |
|---|---|---|
| Power | PW1 | - |
| UART | J1 | D0/D1 |
| Photoresistor | J2 | A0 |
| SRF-04 | J3 | D5/D4 |
| 1604 LCD | J4 | SDA/SCL |
| 1604 LCD | J5 | SDA/SCL |
| LED1 | J6 | D8 |
| LED2 | J7 | D7 |
| LED3 | J8 | D6 |
2 darab egységünk van a kapcsoláson, ami I2C-vel kommunikál. A J4 és J5 foglalatba tudjuk ezeket az LCD-ket bekötni.
Felhúzó ellenállások (R1, R2) is megtalálhatóak az SDA és SCL lábakon, mivel az I2C protokoll egy Open-Drain buszrendszeren alapúl.
A rendszeren belül 2 I2C cím jelenik meg, ezek a 0x70 és 0x7E címek. Ezeket a címeket fizikailag be lehet állítani a PCF8574A GPIO extender IC segítségével, mivel ezen keresztűl kommunikálunk az LCD kijelzőkkel.
A2 A1 A0 | READ WRITE
-----------------------
J4: L L L | 0x71 0x70
J5: H H H | 0x7F 0x7EA2-A0 ig ellátott jelölések fizikai réz lapokat jelölnek amikkel be lehet állítani, hogy az adott IC-nek milyen fizikai I2C címe legyen. Én esetemben kettőt válaszottam, ahol mind a 3 pad nincs összekötve és ahol mind a 3 pad össze van kötve.

A program 500ms-ként lekérdezi az összes szenzorról a kívánt adatokat, majd feldolgozza, és elküldi az üzenetet UART-on keresztűl. Eközben az LCD-re való kiírás is megtörténik a writeLCD() függvény segítségével.
A program folyamatosan frissíti a LED-ek állapotát, amit a handleLEDs() függvény kezel. Ebben a függvényben szimplán komparálja a távolságot az előre definiált konstans változókkal ledUpperLimit, ledBottomLimit.
A programban az 500ms-kénti lekérdezést úgy váltottam valóra, hogy a saját könyvtáramat hozzáadtam a programhoz. Ez akönyvtár az AntiDelay, amivel NON-BLOCKING delay-eket hozhatunk létre.
AntiDelay sensorReadings(500);Ezt az értéket a késöbbiekben könnyedén megváltoztathatjuk a void setInterval(unsigned long interval) belső függvény segítségével.
A program futtatása során lehetőség van belső debuggerelésre, ami szimplán kiírja a soros portra az értékeket, amiket a szenzorról olvas le. Ezt a funkciót #define DEBUG 1/0-val lehet ki és bekapcsolni. Az üzenetek kiküldése ugyan azon a porton keresztül történik meg amelyiken a Message adatcsomagot kiküldjük ezért érdemes kikapcsolva hagyni.
Mivel a fényérzékelő egy analóg GPIO-pinre (A0) megy rá, ezért könnyedén lekérdezhetjük az ADC értékét a beépített Arduino könyvtár segítségével.
photoCellValue = analogRead(PHOTOCELL);Az ultrahangos érzékelőnek csináltam egy class-t, ezzel a kódot letisztultabbá és rendszerezhetőbbé tettem. A classon belül 1 függvény van, ami szimplán megadja, hogy egy objektum milyen messze van, amit egy float típusú változóként küld vissza. 2 belső változója van, ami szimplán eltározza a GPIO lábak értékét.
Deklarálás:
Sonic sonicSensor(TRIGGER_PIN, ECHO_PIN);Távolság lekérése:
float sonicDistance = sonicSensor.getDistance();Az LCD vezérléséhez 2 függvényt hoztam létre. Az void initLCD() csupán inicializálja az I2C kommunikációt és beállítja az LCD alapbeállításait.
Adatok kiírása a void writeLCD() függvény segítségével történik meg.
Az I2C kommunikációs protokollt a két 1604-es LCD kijelző futtatására használom. A kommunikáció leegyszerűsítése kedvéért LiquidCrystal_I2C könyvtárat használtam.
A kommunikáció a PC-n lévő porgram és az Arduino között aszinkron adó-vevő (UART) protokollon keresztűl jut 1 bájtos adatcsomagokkal továbbításra.
Az üzenetkeret:
typedef struct
{
uint8_t start; // 1 byte - const 0x55
uint8_t sonicData[4]; // 4 bytes - Sonic sensor data (float)
uint8_t photoData[4]; // 2 bytes - Photo cell data (int)
uint8_t cs; // 1 byte - Check sum error handling
uint8_t end; // 1 byte - const 0xAA
} Message;Az üzenetkeretet a programokon belül egy struct-ban tárolom, tartalma a következő:
start: 1 bájt előre definiált konstans 0x55 érték ezzel jelezve a csomag kezdetétsonicData: 4 bájtos adat amiben az Ultrahangos érzékelő távolságát tartalmazza ami FLOAT típusúphotoData: 4 bájtos adat amiben a Fényérzékelő ADC értékét tartalmazza ami INT típusú (sok rendszerben változó az int típus nagysága ezért a biztonság kedvéért 4 bájt)cs: 1 bájtnyi Check Sum ami a kód integritás vizsgálására használatos.end: 1 bájt előre definiált konstans 0xAA érték ezzel jelezve a csomag végét
(A fájl megtalálható: Docs/UART data transfer.sal és megnyitható a Saleae Logic 2.4.14-es programmal)
Az UART kommunikációhoz fűződve 4 belső függvényt csináltam.
bool sendUARTMessage(Message *msg);
void convertToMessage(float fSonicData, int iPhotoData, Message *buffer);
bool decodeMessage(Message *buffer, float *fSonicData, int *iPhotoData);
uint8_t calculateCheckSum(Message *msg);Ezek segítségével a nyers adatokat át tudom konvertálni a Message struct bufferba, és fordítva. A sendUARTMessage függvény segítségével lehet kiküldeni az adattömböt az UART-ra. Egy biztonsági réteget is beleiktattam az adatcsomagba, ami egy egyszerű check sum funkció, ezzel ki lehet kerülni az esetlegesen megroncsolt adatok feldolgozását.
A program megvalósítása 2 féle programozási környezetben lett megvalósítva. A C++ alkalmazásban a felhasználó csak a terminálon keresztül tudja venni az Arduinótól jövő adatokat, amit kiír nyers adatként és feldolgozott Sonic és Photo adatként.
A python alkalmazás nem csak fogadja hanem ki is rajzolja (plotolja) a képernyőre.
Az adatok fogadása a def reciveData(ser): függvény felelős ami bytonként olvassa, majd a struct könyvtár segítségével megfelelő típusra konvertálja őket. A függvény visszatérési értékei a return sonicData, photoData. A program megvárja míg a start bit (0x55) megérkezik, majd csak akkor kerül az adatok további feldolgozásra.
Az értékek kirajzolása update_sonic_plot és update_photo_plot függvényeken keresztül történnek meg, amit itt hívunk meg:
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(8, 6))
ani1 = FuncAnimation(fig, update_sonic_plot, interval=20)
# ani2 = FuncAnimation(fig, update_photo_plot, interval=20)
plt.show()Sajnos ismeretlen okok miatt egyszerre a kettő érték kirajzolása nem megvalósítható, mivel a program nagyon belassul ilyenkor, ezért csak az egyiket lehet futtatni, a másikat ki kell kommentezni.


Az alaklamazásban két könyvtárat használtam. Az UART kommunikációért felelős: pip install pyserial és az értékek kirajzolásáért: pip install matplotlib
A C++-os megvalósításban mind terminálra való kiíratás és grafikus módon is ki kerül iratásra az adatok. Mivel a két megvalósítás (csak terminálra való kiíratés és a grafikus módon való kiíratás) teljesen más struktúrát igényelt ezért, ezért két mappa található meg a projektben: Program cpp v1 (csak terminál) és a Program cpp v2 (terminál és grafikus). Az alap funkciók, tehát a portkezelés teljesen megegyezik, csak a v2 projektben egy Draw classba gyűjtöttem minden egyes olcPixelGameEngine-hez szükséges funkciókat. Mivel a Draw classon belül használom a portkezelést, ezért azok is átkerültek oda mint belső (privát) függvények.
A funkciók és kódrészek nagy része átvehető volt az Arduino Firmware kódrészéből ezért a gyakorlati működése megegyezik az Arduinoéval.
A kódban csak akkor történik bufferbe adatok írása amikor a start bit (0x55) megérkezik, valamint hiba esetén (azaz a check sumok nem egyeznek meg) a parseMessage funkció 1-et küld vissza.


Portkezelésre írtam egy külön könyvtárat, ahol a windows.h beépített könyvtár tulajdonságait használom fel.
A portkezelés API formája nagyon megegyező az Arduinoóéhoz ezért könnyedén lehet használni.
int begin(const char* portName);
void close();
int read(const char* buffer, unsigned int bufferSize);
bool write(const char* buffer, unsigned int bufferSize);
bool isConnected();Ezek a függvények dokumentációja, értelmezése megtalálható a projekten belüli SerialHandler.cpp fájlban.
Grafikus megjelenítésért felelős könyvtár: OneLoneCoder/olcPixelGameEngine
A gyakorlatban is megépítettem a rendszert, ugyan azokkal a szenzor elemekkel, amik a feltételek között is szerepeltek. A rendszer minden elemét teszteltem, kivéve az LCD kijelzőt, mivel erre sajnos nem volt megfelelő elemem.

| Qty | Value | Footprint | References |
|---|---|---|---|
| 1 | Arduino_Nano_Socket | PCM_arduino-library:Arduino_Nano_Socket | A1 |
| 1 | Fényszenzor | Connector_PinSocket_2.54mm:PinSocket_1x02_P2.54mm_Vertical | J1 |
2 parts. The full list of its parts is on this page, with links to each part's symbol and footprint where PCBKit's library has them.
From the martinvichnal/Hardware-Test repository on GitHub, at the commit this page was made from: the board is Schematic/Schematic.kicad_pcb and its schematic Schematic/Schematic.kicad_sch. PCBKit opens the board in the browser, with nothing to install.
Its repository states no licence, so its author keeps all rights: ask martinvichnal before reusing the design.

hzeller/rpi-rgb-led-matrix
Controlling up to three chains of 64x64, 32x32, 16x32 or similar RGB LED displays using Raspberry Pi GPIO


adamws/kicad-kbplacer
KiCad plugin for automatic keyboard's key placement and routing

Luos-io/luos_engine
Open-source and real-time orchestrator for cyber-physical-systems, to easily design, test and deploy embedded applications and digital twins.

NVNTLabs/switch2-SDEX2M2
Micro SD Express to M.2 NVME Adapter for Nintendo Switch 2

BlueSCSI/BlueSCSI-v2
BlueSCSI v2/Ultra - an open source, open hardware, SCSI emulator using the Pi Pico PR2040 and Pico 2 RP2350

ohmtech-rdi/eurorack-blocks
Software to Hardware Prototyping for Eurorack using C++, Max/Gen~ or Faust
