Raspberry Pi není třeba představovat. Je to výborný minipočítač třeba pro řízení nějakého menšího výrobního procesu nebo testeru ve výrobě. Potřebuje ale k sobě ještě nějakou „bižuterii“ aby se dal začlenit mezi komponenty v průmyslovém prostředí. Dá se sice koupit hromada rozšiřujících desek a modulů, ale já jsem potřeboval vytvořit jeden kompaktní modul, kde by bylo vše potřebné na jedné desce a to ještě s dotykovým displejem a dalo se to jednoduše připevnit na panel. Tato základní deska je toho výsledkem.
Popis:
Deska obsahuje napájecí zdroj z 24V, který je částečně zálohovaný trojicí elektrolytických kondenzátorů. Stalo se mi několikrát, že při vypnutí napájecího napětí, když byl spuštěn systém, poškodil se souborový systém na SD kartě a systém už znovu nenaběhnul. Dále nějaké analogové a digitální vstupy, výstupy kontaktů relé a galvanicky oddělené komunikační rozhraní RS-485. Na základní desce je pomocný MCU který obsluhuje tyto periférie a s Raspberry komunikuje přes SPI. Součástí kódu MCU je i funkcionalita, která vypne korektně Raspberry příkazem při výpadku napájecího napětí. Popsané je to detailně v dokumentaci. Na základní desce je také RTC připojené přes I2C.
Dotykový displej je na zvláštní kapitolu. V roce 2015 (rok návrhu a realizace) byly prakticky nesehnatelné displeje s MIPI-DSI rozhraním, kterým disponuje Raspberry. Většinou se používají převodníky z HDMI na parallel RGB24. Je to sice trochu krkolomné, ale funguje to. Převodník na čipu se dá sehnat a většina displejů s paralelním rozhraním také. V konfiguračním souboru systému se jenom nastaví patřičné rozlišení displeje. Tato koncepce je použitá i v tomto případě. Dnes už je situace asi trochu jiná. Na pravé straně PCB (titulní obrázek) ve výřezu pro konektory Raspberry jsou na ulamovacích můstkách dva motivy pro výrobu propojovacího HDMI adaptéru. Ten slouží k zavedení HDMI signálu z Raspberry do základní desky, kde je osazen zmíněný převodník na parallel RGB24. Jeho výstup je dále přiveden do displeje přes FPC konektor. Tato “displejová” část funguje samostatně od části periferií, kterou má na starosti již zmíněný pomocný MCU. Typ použitého kontroléru odporového dotykového panelu je celkem rozšířený a existují na něj už napsané ovladače.
Samostatně též funguje obvod RTC, který je zálohovaný CR “knoflíkem”.
Vše ostatní je patrné z dokumentace, která je k dispozici na konci tohoto článku.
Základní vlastnosti:
- Napájecí napětí v rozsahu 9 až 24 V DC
- Rozsah pracovní teploty 0 – 70 °C
- Rozměry 135 x 96 mm
- Displej s rozlišením 800(RGB)*480 a velikostí 5 palců s odporovýn dotykovým panelem
- 2x RS-485 Full-duplex galvanicky oddělené
- 4x vstup přes optočlen
- 3x analogový vstup
- 2x výstup relé NC NO
- Zálohované RTC
- EEPROM
- SWJ-DP serial wire debug port
- Stavová LED
Pohled na osazenou desku s Raspberry Pi:
Přední strana s displejem:
Integrace v systému:
Příklad kódu zodpovědného za komunikaci s podřízeným MCU na základní desce:
/** ****************************************************************************** * @file bridge.h * @author René Široký (WISER) * @company Wide Servis * @version V1.0.0 * @date 03/2016 * @brief Header for bridge.c ****************************************************************************** */ /* Define to prevent recursive inclusion -------------------------------------*/ #ifndef __BRIDGE_H__ #define __BRIDGE_H__ #ifdef __cplusplus extern "C" { #endif /* Includes ------------------------------------------------------------------*/ #include "bcm2835.h" #include "crc.h" /* Extern variables ----------------------------------------------------------*/ /* User define ---------------------------------------------------------------*/ //#define BRIDGE_USE_SPI #define BRIDGE_USE_GPIO #define BRIDGE_CS_PIN RPI_V2_GPIO_P1_24 #define BRIDGE_RECRQ_PIN RPI_V2_GPIO_P1_15 #define BRIDGE_SCLK_PIN RPI_V2_GPIO_P1_22 #define BRIDGE_MISO_PIN RPI_V2_GPIO_P1_18 #define BRIDGE_MOSI_PIN RPI_V2_GPIO_P1_16 /* Exported types ------------------------------------------------------------*/ /* Exported constants --------------------------------------------------------*/ /* Exported macro ------------------------------------------------------------*/ /* Exported functions ------------------------------------------------------- */ uint8_t BRIDGE_init(void); uint8_t BRIDGE_sendReceiveFrame(uint8_t* sendData, uint16_t sSize, uint8_t* recvData, uint16_t* rSize); #ifdef __cplusplus } #endif #endif /* __BRIDGE_H__ */ /******************************************************************************/ /** * End Of File bridge.h */
/** ****************************************************************************** * @file bridge.c * @author René Široký (WISER) * @company Wide Servis * @version V1.0.0 * @date 03/2016 * @brief ****************************************************************************** */ /* Includes ------------------------------------------------------------------*/ #include "bridge.h" /* Private define ------------------------------------------------------------*/ #define BRIDGE_FRAME_TIMEOUT 500 /*ms*/ /* Private macro -------------------------------------------------------------*/ /* Private typedef -----------------------------------------------------------*/ /* Private constants ---------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/ /* Private function prototypes -----------------------------------------------*/ static uint8_t _gpio_spi_transferByte(uint8_t byte); static void _gpio_spi_transfern(char* buf, uint32_t len); static void _gpio_spi_transfernb(char* tbuf, char* rbuf, uint32_t len); /* Private functions ---------------------------------------------------------*/ /******************************************************************************/ /** * @brief _gpio_spi_transferByte * @param Byte for transmit * @retval Received byte */ static uint8_t _gpio_spi_transferByte(uint8_t txByte) { uint8_t bitIndex; uint8_t rxByte = 0; for (bitIndex = 8; bitIndex > 0; bitIndex--) { /* transmit byte */ bcm2835_gpio_clr(BRIDGE_SCLK_PIN); if ((txByte >> (bitIndex - 1)) & 1) { bcm2835_gpio_set(BRIDGE_MOSI_PIN); } else { bcm2835_gpio_clr(BRIDGE_MOSI_PIN); } bcm2835_gpio_set(BRIDGE_SCLK_PIN); /* receive byte */ if (bcm2835_gpio_lev(BRIDGE_MISO_PIN) == HIGH) { rxByte |= (1 << (bitIndex - 1)); } } return rxByte; } /******************************************************************************/ /** * @brief _gpio_spi_transfern * @param None * @retval None */ static void _gpio_spi_transfern(char* buf, uint32_t len) { _gpio_spi_transfernb(buf, buf, len); } /******************************************************************************/ /** * @brief _gpio_spi_transfernb * @param None * @retval None */ static void _gpio_spi_transfernb(char* tbuf, char* rbuf, uint32_t len) { uint8_t bytIndex; bcm2835_gpio_clr(BRIDGE_CS_PIN); bcm2835_delayMicroseconds(10); for (bytIndex = 0; bytIndex < len; bytIndex++) { rbuf[bytIndex] = _gpio_spi_transferByte(tbuf[bytIndex]); } bcm2835_delayMicroseconds(10); bcm2835_gpio_set(BRIDGE_CS_PIN); } /* Exported functions --------------------------------------------------------*/ /******************************************************************************/ /** * @brief Inicializace SPI komunikace * @param None * @retval Návratová hodnota chyby, 1 = chyba inicializace knihovny bcm2835 */ uint8_t BRIDGE_init(void) { /*initialise the library*/ if (!bcm2835_init()) { return 1; } #ifdef BRIDGE_USE_SPI /*setup SPI pins*/ bcm2835_spi_begin(); /*set CS pins polarity to low*/ bcm2835_spi_setChipSelectPolarity(BCM2835_SPI_CS0, 0); /*set SPI clock speed 16 = 64ns = 15.625MHz*/ bcm2835_spi_setClockDivider(BCM2835_SPI_CLOCK_DIVIDER_16); /*set SPI data mode*/ bcm2835_spi_setDataMode(BCM2835_SPI_MODE3); /*set with CS pin to use for next transfers*/ bcm2835_spi_chipSelect(BCM2835_SPI_CS0); /*set input on RPi pin GPIO 22 (pin 15)*/ #endif #ifdef BRIDGE_USE_GPIO /* configure CS pin */ bcm2835_gpio_set(BRIDGE_CS_PIN); bcm2835_gpio_fsel(BRIDGE_CS_PIN, BCM2835_GPIO_FSEL_OUTP); /* configure SCLK pin */ bcm2835_gpio_set(BRIDGE_SCLK_PIN); bcm2835_gpio_fsel(BRIDGE_SCLK_PIN, BCM2835_GPIO_FSEL_OUTP); /* configure MISO pin */ bcm2835_gpio_fsel(BRIDGE_MISO_PIN, BCM2835_GPIO_FSEL_INPT); /* configure MOSI pin */ bcm2835_gpio_fsel(BRIDGE_MOSI_PIN, BCM2835_GPIO_FSEL_OUTP); #endif /* configure RECRQ pin */ bcm2835_gpio_fsel(BRIDGE_RECRQ_PIN, BCM2835_GPIO_FSEL_INPT); return 0; } /******************************************************************************/ /** * @brief Vyslání a příjem dat * @param Pointer pole a velikost vysílaných a přijímaných dat * @retval Návratová hodnota chyby, 1 = timeout, 2 = chyba crc */ uint8_t BRIDGE_sendReceiveFrame(uint8_t* sendData, uint16_t sSize, uint8_t* recvData, uint16_t* rSize) { uint8_t sendBuffer[260]; uint16_t index; uint16_t timeout = BRIDGE_FRAME_TIMEOUT; uint8_t recevedCrc, calculatedCrc; /*reset size received frame*/ *rSize = 0; /*prepare send buffer*/ for (index = 0; index < sSize; index++) { sendBuffer[index] = sendData[index]; } /*adding crc*/ sendBuffer[index] = CRC(&sendBuffer[0], 1, index); /*send frame*/ #ifdef BRIDGE_USE_SPI bcm2835_spi_transfern((char*) &sendBuffer[0], index + 1); #endif #ifdef BRIDGE_USE_GPIO _gpio_spi_transfern((char*) &sendBuffer[0], index + 1); #endif /*delay on response STM32*/ bcm2835_delayMicroseconds(10); /*wait if GPIO 22 (pin 15) is low*/ while (bcm2835_gpio_lev(BRIDGE_RECRQ_PIN) == LOW) { if (--timeout == 0) { return 1; } bcm2835_delay(1); } /*clear send buffer*/ for (index = 0; index < 260; index++) { sendBuffer[index] = 0; } /*receive first two bytes (the second byte contains the length of data)*/ #ifdef BRIDGE_USE_SPI bcm2835_spi_transfernb((char*) &sendBuffer[0], (char*) &recvData[0], 2); #endif #ifdef BRIDGE_USE_GPIO _gpio_spi_transfernb((char*) &sendBuffer[0], (char*) &recvData[0], 2); #endif /*delay on response STM32*/ bcm2835_delayMicroseconds(10); /*receive full frame*/ #ifdef BRIDGE_USE_SPI bcm2835_spi_transfernb((char*) &sendBuffer[0], (char*) &recvData[0], (recvData[1] + 3)); #endif #ifdef BRIDGE_USE_GPIO _gpio_spi_transfernb((char*) &sendBuffer[0], (char*) &recvData[0], (recvData[1] + 3)); #endif /*received crc*/ recevedCrc = recvData[recvData[1] + 2]; /*calculate crc*/ calculatedCrc = CRC(&recvData[0], 0, recvData[1] + 2); /*comparison crc*/ if (recevedCrc != calculatedCrc) { return 2; } /*set size received frame*/ *rSize = recvData[1] + 2; return 0; } /******************************************************************************/ /** * End Of File bridge.c */
Dokumentace projektu:
Dokumentace obsahuje elektrické schéma zapojení, osazovací plán součástek, vyobrazení jednotlivých vrstev plošných spojů, seznam použitých součástek, realistické náhledy a 3D zobrazení osazené desky.
Důležité upozornění: Tento dokument je určen pouze pro vlastní osobní potřebu. Společnost WIDE SERVIS a provozovatel těchto stránek nenesou žádnou zodpovědnost za případné finanční ztráty, škody na majetku a zdraví vzniklé při použití tohoto dokumentu.
W150708.01 - RPI Board