Skip to the content
PCBKitNew board
2 layersHardware Test, the printed circuit board in 3D

A kapcsolási rajzot a KiCad 8.0.2 programmal hoztam létre. Középpontjában egy Arduino Nano Socket áll.

Copper layers
2
Thickness
1.6 mm
Parts
2
Nets
32
Pads
36
Tracks, vias
0, 0
Routed
Not yet
KiCad
KiCad 8.0 (file 20240108)
Created
8 May 2024
Updated
12 May 2024

Overview

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.

README

README.md

Table of Content

Kapcsolási rajz

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.

GPIO

NeveJeleGPIO
PowerPW1-
UARTJ1D0/D1
PhotoresistorJ2A0
SRF-04J3D5/D4
1604 LCDJ4SDA/SCL
1604 LCDJ5SDA/SCL
LED1J6D8
LED2J7D7
LED3J8D6

I2C

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.

text
A2 A1 A0 | READ WRITE
-----------------------
J4: L L L | 0x71 0x70
J5: H H H | 0x7F 0x7E

A2-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.

Address Table

Firmware

Működése

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.

C++
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.

Változók

Fényérzékelő

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.

C++
photoCellValue = analogRead(PHOTOCELL);

Ultrahangos érzékelő

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.

Class használata

Deklarálás:

C++
Sonic sonicSensor(TRIGGER_PIN, ECHO_PIN);

Távolság lekérése:

C++
float sonicDistance = sonicSensor.getDistance();

1602 LCD

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.

Kommunikáció

I2C

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.

UART

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:

C++
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ét
  • sonicData: 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

UART Logic Analysator (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.

C++
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.

Könyvtárak

johnrickman/LiquidCrystal_I2C

martinvichnal/AntiDelay

Program

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.

Python

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:

Python
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.

Fényszenzor plot

Ultrahang plot

Könyvtárak

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

C++

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.

Kiíratás terminálra

Grafikus megjelenítés

Portkezelés

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.

API

A portkezelés API formája nagyon megegyező az Arduinoóéhoz ezért könnyedén lehet használni.

C++
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.

Könyvtárak

Grafikus megjelenítésért felelős könyvtár: OneLoneCoder/olcPixelGameEngine

Gyakorlati megvalósítás

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.

Gyakorlati megvalósítás

Parts

2
QtyValueFootprintReferences
1Arduino_Nano_SocketPCM_arduino-library:Arduino_Nano_SocketA1
1FényszenzorConnector_PinSocket_2.54mm:PinSocket_1x02_P2.54mm_VerticalJ1

Questions

What parts does the Hardware Test use?

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.

Where can I download the Hardware Test KiCad files?

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.

Can I use the Hardware Test design in my own project?

Its repository states no licence, so its author keeps all rights: ask martinvichnal before reusing the design.

Similar boards

  • 2 layers37 × 19 mmPassive rpi hub75-adapter, the printed circuit board in 3D

    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

    2 parts4.4kGPL-2.0
  • 2 layersDiode template, the printed circuit board in 3D

    Diode template

    adamws/kicad-kbplacer

    KiCad plugin for automatic keyboard's key placement and routing

    2 parts547GPL-3.0
  • 2 layers20.3 × 15.2 mmL0 button, the printed circuit board in 3D

    L0 button

    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.

    2 parts546MIT
  • 2 layers35.1 × 46.8 mmSDEX2M2 Breakout Board, the printed circuit board in 3D

    SDEX2M2 Breakout Board

    NVNTLabs/switch2-SDEX2M2

    Micro SD Express to M.2 NVME Adapter for Nintendo Switch 2

    2 parts542GPL-3.0
  • 2 layers59.3 × 36.6 mmExpansionBoardTemplate, the printed circuit board in 3D

    ExpansionBoardTemplate

    BlueSCSI/BlueSCSI-v2

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

    2 parts459GPL-3.0
  • 2 layersAlpha.9mm.wire, the printed circuit board in 3D

    Alpha.9mm.wire

    ohmtech-rdi/eurorack-blocks

    Software to Hardware Prototyping for Eurorack using C++, Max/Gen~ or Faust

    2 parts410
  • 2 layers26.7 × 64 mmGpu power, the printed circuit board in 3D

    Gpu power

    dennisss/dacha

    Monorepo for awesome tools/projects/libraries

    2 parts397Apache-2.0