本文來自極術社區聆思CSK6視覺AI開發套件試用活動文章。作者用聆思CSK6芯片支持的手勢識別能力結合8X8點陣實現一款剪子包袱錘的游戲。
一 開發環境搭建
1.1 硬件環境
如下圖所示,本次產品有聆思的CSK6011-NanoKit視覺開發套件和8*8點陣組成,CSK6011-NanoKit負責手勢的識別,點陣負責圖形的顯示,兩者通過SPI總線連接在一起。
1.2 軟件環境
軟件開發環境搭建可以參考CSK6環境搭建,聆思很貼心的提供了完整的打包開發環境,利用lisa工具可以完成項目的創建、編譯和下載,此外廠商還基于VSCODE插件的方式提供了完整的IDE開發環境。
二 點陣的使用
2.1 硬件連接
8x8點陣的主控是GC7219(完全兼容MAX7219),其典型的應用圖如下所示:
芯片可以通過GPIO或者SPI來驅動,官方提供了SPI的參考demo,本次將基于其實現對點陣的控制。將GC7219(點陣)與CSK6011的SPI0連接,利用板載的3.3V管腳供電,相關管腳的連接示意圖如下:
2.2 圖標建模
由于CSK6011目前支持5種手勢,分別為LIKE()、OK()、STOP()、YES()、SIX(),采用相似原則,取LIKE=錘,STOP=包袱,YES=剪刀。相關示圖標建模(共陰)如下:
2.3 驅動開發
2.3.1 建立SPI開發工程
參見SPI參考工程的實現,搭建SPI驅動開發工程。
2.3.2 GC7219的適配
由GC7219的手冊可知,其支持MSB模式,且最高頻率只有10M,因此spi的Config需要做如下修改。
/* spi master 8bit, LSB first*/ spi_cfg.operation = SPI_WORD_SET(8) | SPI_OP_MODE_MASTER | SPI_TRANSFER_LSB; spi_cfg.frequency = 10 * 1000000UL;
改為:
/* spi master 8bit, MSB first*/ spi_cfg.operation = SPI_WORD_SET(8) | SPI_OP_MODE_MASTER | SPI_TRANSFER_MSB; spi_cfg.frequency = 5 * 1000000UL;
2.3.3 添加點陣驅動
如圖2.2所示,GC7219支持共陰點陣,各圖像的數組定義如下代碼片段。
unsigned char jiandao_table[8][2] = { {0x01,0x24},{0x02,0x24},{0x03,0x24},{0x04,0x7E}, {0x05,0x7E},{0x06,0x7E},{0x07,0x7E},{0x08,0x00} }; unsigned char shitou_table[8][2] = { {0x01,0x00},{0x02,0x40},{0x03,0x40},{0x04,0x7C}, {0x05,0x7C},{0x06,0x7C},{0x07,0x7C},{0x08,0x00} }; unsigned char bu_table[8][2] = { {0x01,0x08},{0x02,0x1C},{0x03,0x1E},{0x04,0x1E}, {0x05,0x5E},{0x06,0x7E},{0x07,0x7E},{0x08,0x00} };
由zephr的API調用可知,其發送函數spi_write需要傳入一個數據鏈表,然后會按照列表逐一發送相關數據,完整的代碼如下:
/* * SPDX-License-Identifier: Apache-2.0 */ #include#include #include #include #include #include #include unsigned char work_state[2]={0x0C, 0x1}; // normal work mode unsigned char test_state[2]={0x0F, 0x0}; // no test mode unsigned char decode_cfg[2]={0x09, 0x0}; // no decode unsigned char scan_range[2]={0x0B, 0x7}; // scan 0-7 unsigned char jiandao_table[8][2] = { {0x01,0x24},{0x02,0x24},{0x03,0x24},{0x04,0x7E}, {0x05,0x7E},{0x06,0x7E},{0x07,0x7E},{0x08,0x00} }; unsigned char shitou_table[8][2] = { {0x01,0x00},{0x02,0x40},{0x03,0x40},{0x04,0x7C}, {0x05,0x7C},{0x06,0x7C},{0x07,0x7C},{0x08,0x00} }; unsigned char bu_table[8][2] = { {0x01,0x08},{0x02,0x1C},{0x03,0x1E},{0x04,0x1E}, {0x05,0x5E},{0x06,0x7E},{0x07,0x7E},{0x08,0x00} }; #define TX_PACKAGE_MAX_CNT 8 void main(void) { int idx=0; const struct device *spi; struct spi_config spi_cfg = {0}; struct spi_buf_set tx_set; unsigned char digit[2]={0}; printk("spi master example "); spi = DEVICE_DT_GET(DT_NODELABEL(spi0)); if (!device_is_ready(spi)) { printk("SPI device %s is not ready ", spi->name); return; } /* spi master 8bit, LSB first*/ spi_cfg.operation = SPI_WORD_SET(8) | SPI_OP_MODE_MASTER | SPI_TRANSFER_MSB; spi_cfg.frequency = 5 * 1000000UL; /* Make spi transaction package buffers */ struct spi_buf *tx_package = k_calloc(TX_PACKAGE_MAX_CNT, sizeof(struct spi_buf)); if (tx_package == NULL) { printk("tx_package calloc failed "); return; } /* Init 7219 */ tx_package[0].buf = work_state; tx_package[0].len = 2; tx_package[1].buf = test_state; tx_package[1].len = 2; tx_package[2].buf = decode_cfg; tx_package[2].len = 2; tx_package[3].buf = scan_range; tx_package[3].len = 2; tx_set.buffers = tx_package; tx_set.count = 4; printk("Init 7219 ... "); spi_write(spi, &spi_cfg, &tx_set); do { k_msleep(1000); printk("spi master sending jiandao_table data ... "); for (idx=0; idx<8; idx++) { ? ? ? ? ? ?digit[0]=jiandao_table[idx][0]; ? ? ? ? ? ?digit[1]=jiandao_table[idx][1]; ? ? ? ? ? ?tx_package[0].buf = digit; ? ? ? ? ? ?tx_package[0].len = 2; ? ? ? ? ? ?tx_set.buffers ? ?= tx_package; ? ? ? ? ? ?tx_set.count ? ? ?= 1; ? ? ? ? ? ?spi_write(spi, &spi_cfg, &tx_set); ? ? ? ?} ? ? ? ?k_msleep(1000); ? ? ? ?printk("spi master sending shitou_table data ... "); ? ? ? ?for (idx=0; idx<8; idx++) { ? ? ? ? ? ?digit[0]=shitou_table[idx][0]; ? ? ? ? ? ?digit[1]=shitou_table[idx][1]; ? ? ? ? ? ?tx_package[0].buf = digit; ? ? ? ? ? ?tx_package[0].len = 2; ? ? ? ? ? ?tx_set.buffers ? ?= tx_package; ? ? ? ? ? ?tx_set.count ? ? ?= 1; ? ? ? ? ? ?spi_write(spi, &spi_cfg, &tx_set); ? ? ? ?} ? ? ? ?k_msleep(1000); ? ? ? ?printk("spi master sending bu_table data ... "); ? ? ? ?for (idx=0; idx<8; idx++) { ? ? ? ? ? ?digit[0]=bu_table[idx][0]; ? ? ? ? ? ?digit[1]=bu_table[idx][1]; ? ? ? ? ? ?tx_package[0].buf = digit; ? ? ? ? ? ?tx_package[0].len = 2; ? ? ? ? ? ?tx_set.buffers ? ?= tx_package; ? ? ? ? ? ?tx_set.count ? ? ?= 1; ? ? ? ? ? ?spi_write(spi, &spi_cfg, &tx_set); ? ? ? ?} ? ?} while (1); }
2.3.4 搭建AI工程
參考文檔AI能力-視覺的相關步驟搭建AI工程,這里主要說明一下遇到的幾個問題和注意事項。
1)因為此處使用的是最新git工程,所以打印可能與文檔有出入,git版本和打印對應如下:
2)如果直接下載git工程編譯升級,PC端工具無法正常使用,需要執行如下兩條命令,參考連接一鍵拉取-sample-和-sdk-異常解決方法,然后再執行編譯燒寫操作。
lisa zep init-app lisa zep update
3)基于Edge瀏覽器如果直接打開在線PC工具,點擊"Windows系統"會出現404錯誤,所以建議直接下載pc工具工程到本地離線使用。
git clone https://cloud.listenai.com/zephyr/applications/csk_view_finder_spd.git
4)執行"lisa zep flash"后如果立即執行如下資源下載命令可能會失敗,這時候建議拔插一下DAP口或者檢查一下串口是否被占用。
經過上述步驟以后,通過PC端工具查看效果如下:
2.3.5 識別和顯示
將SPI-GC7219的工程和AI手勢識別的工程融合在一起,程序流程如下:
三 效果展示
效果如下,機器會根據人類的出拳來出拳,用來給做簡單的演示還是挺有意思的。
四 總結
整體體驗下來,感覺聆思在SOM的易用性、接口的完整性、文檔的豐富度、和支持的及時性上做的都不錯,按照文檔一步步做下來,很快就可以入門做一些簡單的產品。美中不足的是目前聆思的AI訓練和調參工具還沒有面向大眾開放,可能是因為技術性比較強,但因此少了一部分趣味性,在手勢AI識別的demo中也能夠感覺到光照和距離對識別的準確性影響很大,但是在如此低的功耗和性能下做到這樣的程度已經很棒了。最后祝聆思科技的產品越做越棒,極術社區越做越大帶給廣大開發興趣人員更多豐富的活動。
轉自 | 安謀科技學堂
審核編輯:湯梓紅
-
手勢識別
+關注
關注
8文章
225瀏覽量
47850 -
AI
+關注
關注
87文章
31493瀏覽量
270182 -
開發環境
+關注
關注
1文章
230瀏覽量
16689 -
GPIO
+關注
關注
16文章
1216瀏覽量
52344 -
開發套件
+關注
關注
2文章
157瀏覽量
24327
原文標題:【聆思CSK6視覺AI開發套件試用】基于AI手勢識別的剪子包袱錘游戲
文章出處:【微信號:Ithingedu,微信公眾號:安芯教育科技】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論