文章

[應用] 以 STM32 晶片的 ADC 為基礎, 設計一個簡易示波器

圖片
目的         以 ADC 模組為基礎,設計一個簡易示波器觀察訊號變化,同時能記錄每筆資料以便數值分析。 設計         使用 STM32 系列晶片內的 ADC 模組,將類比訊號轉換成數位資料,然後將整筆數據從網路傳送到 PC 端,再由 PC 程式接收後繪製成曲線圖。開發過程,利用前面一文 「 以 STM32 晶片的 DAC 為架構設計一個訊號產生器 」 所產生的方波當做待測訊號源,此訊號源輸入到 ADC 接腳,如下圖一所示。 圖一:設計完整示波器的方塊圖 STM32F207        下圖是程式碼設定 ADC 的參數,第一個要先設定 ADC 取樣率的刻度,再來設定取樣率,如下面紅線標示。取樣率跟晶片的 operating clock 有關,從系統的高速時脈降頻到 ADC 的取樣率。第二個是選定 ADC 轉換資料的精密度,精密度越高,資料量則越大。最後,設定 ADC 轉換完畢後產生中斷通知 CPU,每次 ADC 轉換資料後,中斷的 IRQ 便會把數值從暫存器搬到記憶體裡。在設計裡,我們宣告兩塊 buffer 存放數值。 圖二:ADC 參數設定         下圖是在 PC 端寫一個網路接收資料的程式,並把資料繪製成曲線圖。當 ADC 取樣率為 15.2KHz時,從PC端看到的圖形比較像弦波,當我把 ADC 取樣率提高為 48KHz 時,PC端看到的圖形就像一個方波了。不過,取樣率高低對設計來說是一項架構問題,取樣率越高,代表資料量越高,傳輸速率越大,所需要的網路頻寬要夠,還要晶片的CPU有足夠的效能才行。 圖三-1:ADC 取樣率 15.2K 所顯示的方波 圖三-2:ADC 取樣率為 48K 所顯示的方波 問題         DMA資料搬運過程不穩定,當取樣率越高的時候,DMA搬運出現資料錯亂的情況。將這個問題放到 StackOverflow 網站尋求解答,連結如下「 ADC 與 DMA 資料搬運的問題 」。所以,在上面的測試過程,我們都採用 ADC 中斷的方式搬運資料到記憶體,而不是 DMA...

[應用] 以 STM32 晶片的 DAC 為架構設計一個訊號產生器

圖片
目的:產生方波或正弦波的訊號 設計:以 STM32 系列內建的 DAC 模組為架構,搭配內部的 Timer 當做取樣率,讓 DAC 輸出週期性訊號。         我們設計訊號產生器靠 DAC 模組將數值轉換成類比訊號,接著產生一個週期性訊號需要使用 Timer,利用它產生的 event 通知我們產生一個訊號數值,簡單說就是一個取樣點,而取樣率就是 Timer 的參數設置。這裡會有個效能的問題,如果取樣速率越高,那麼系統核心每次要 DAC 轉換數值的頻率就會增加,這會占用到系統 CPU 的運算時間。因此,DAC 需要配合 DMA 模組以達到系統效能。         圖一所示為上述三個模組的運作流程圖,第一步 Timer 產生取樣點的事件,驅動第二步的 DAC 模組,因為設定 DAC 與 DMA 搭配合作,第三步 DAC 會對 DMA 發出一個請求,要求 DMA 將波形訊號數值搬到 DAC 暫存器裡面,最後 DMA 執行這個請求。 圖一:STM32 DAC 運作的流程圖         圖二和圖三所示為程式碼的說明,首先要宣告一塊記憶體存放波形資料,這陣列代表一個波形的完整週期。接著,我們要初始化 Timer 、 DAC 、 DMA 模組,Timer 設定取樣率,DMA 和 DAC 要設定資料搬運的位址與長度。設計到這裡,比較困難的地方在怎麼計算適當的取樣率,它會影響到波形的週期大小。我們以 STM32F207 晶片為例,Timer 模組的 clock 是 60MHz,當 TIM_Period 設定為 500 時,每個取樣點產生的頻率為 120KHz = 60MHz/500,再來看一個完整波形的週期需要 30 個取樣點,所以這個波形頻率為 4KHz = 120KHz/30,其週期為 250us 。程式在 STM32F207 板卡上運行的結果顯示在最後一張圖。 圖二:波形資料的定義 圖三:每個模組參數的初始化

[概念] 兩個程序以 IPC 方式建立一個能互相通訊的共享空間

圖片
        在同一Windows系統內的兩個程序要互傳資料,可以用建立內部 TCP 連線方式傳送,不過這種方式不適合大量資料的存取。還有一種方式稱為 IPC (Inter Process Communication),兩個程序之間建立一個共享的空間,透過這塊空間互傳資料互相通訊,參考[1],我們可以把這塊空間看成是一個虛擬檔案,類似開啟檔案的步驟來讀寫它。         首先,雙方有一方要建立共享空間,另一方則是開啟共享空間,如下圖一所示。建立的這方要對這塊空間命名,如果沒有命名,另一方就無法開啟正確的空間。如果我們建立一個很大的空間時,要先讀取目前系統的 available page file 還剩多少,如果不足,那就要加大系統的記憶體容量,參考[2]。當雙方能成功取得這塊共享空間的控制權後,這樣才能利用 MapViewOfFile 函數獲得位址,要留意的一點是位址的 alignment,這塊空間並不是想要指定 到某一位址就能任一指定,它有限制位址必須對齊系統的 AllocationGranularity,所以在規劃空間內部的資料結構時就要先設計安排妥當。         接著,因為存取資料是一個共享空間,所以我們要設計一個互斥鎖保護資料,避免雙方同時存取同一位址而產生資料錯亂,如下圖所示,同樣地建立的互斥鎖也要命名。最後,建立一個事件通知也是需要的,總不能雙方都要輪詢方式來查看資料有沒有更新吧? 當一方寫完資料後,發個事件通知告訴對方,再由對方來讀取,這樣效率會比較好。 圖一:IPC 操作所調用的相關API 參考資料 [1]  Interprocess Communication Between 32-bit and 64-bit Applications [2]  Creating Named Shared Memory

[筆記] Visual Studio 遠端偵錯的設定步驟

圖片
        通常我們用微軟Visual Studio IDE開發程式並且在本機上運行與除錯,但隨著開發系統越來越複雜,程式運行在某台服務器上而不是自己的機器,這時候需要進行遠端程式的除錯,架構如下圖一所示。自己的主機要安裝微軟的Visual Studio 2017 IDE,待測的機器上面要有Remote Debugger工具,雙方透過網路的連線進行除錯。 圖一:遠端除錯與待測機器 [步驟]: 1) 在自己主機上的Visual Studio目錄下面找Remote Debugger這個工具目錄,然後把Remote Debugger工具複製到待測機器上。 2) 程式的除錯屬性要設定正確,屬性頁的遠端Windows偵測工具,如下圖二所示。我們必須設定遠端命令 、 工作目錄 、 遠端機器IP 、連接是否驗證...等等,連線的權限要配合遠端機器的設定。 3) 在遠端機器上的Remote Debugger目錄,開啟 msvsmon.exe,這時只要到工具選單設定連線的權限,如下圖三所示。圖中是設為無權限的方式,不需要驗證使用者。 4) 在VS IDE環境運行遠端Windows偵錯工具,如果發現遠端機器上出現錯誤,錯誤的原因是缺少某些 dll 檔案,如:msvcp140D.dll 、ucrtbased.dll... 。我們在本地主機上找找看這些缺少的檔案,應該能找到,然後再複製到遠端機器的 \Windows\System32 目錄底下。 5) 最後,編譯我們的程式後,要再把exe 、 pdb檔案複製到遠端機器的工作目錄上。接著,運行我們的程式遠端 debug,這樣就可以一步步看著遠端機器上的程式怎麼執行了。 C++遠程偵錯 圖二:C++程式的遠端屬性設定 圖三:遠端機器的連線權限設定 C#遠程偵錯 圖四:C# 程式的遠端偵錯設定

[應用] USB host 轉換到 RS-232 的解決方案

圖片
        最近遇上一個問題,工業儀器設備越來越多採用USB介面取代RS-232,造成原本RS-232設備無法對接。就介面標準來看,在工業使用上 RS-232 是點對點的通訊協定,沒有主從分別的傳輸介面,傳輸距離數十公尺遠,如果再轉成 RS-485 傳輸距離更遠。相對於USB,具有主從架構的傳輸介面,因為來自電腦介面的標準,傳輸線距離僅數公尺遠。然而,坊間看到的 USB To RS232 轉換線只是 USB slave,必須接到電腦 (USB host),這種傳輸線無法直接接 USB儀器 (USB slave),所以我先要找到一個 USB host 轉換中介,再寫一個轉換程式後,才能把 USB儀器的數據轉到 RS-232 設備上。         目前找到的 USB host 開發平台有 FTDI VNC2 和 樹莓派 ...等方法,FTDI VNC2具有 USB host 接口功能,就像小型嵌入式系統,兼具體積小的特點,不過我們必須用 FTDI 專用的 IDE 來開發程式。而樹莓派本身就是一個以 Linux 為核心的操作平台,猶如一台小型電腦,可直接在上面以 C++ 語言來開發轉換程式,相較來說比較便利。底下我採用樹莓派的轉換方案,圖一是設備之間的方塊圖,中間以樹莓派系統當作轉換的中介,圖右邊的USB工業儀器接到樹莓派之後,樹莓派的操作系統便能辨識出 USB 裝置當作一個 ttyUSB 串口,我們開發一個轉換程式將從這個串口接收到的數據轉傳到圖左邊的串口。網路上有很多 ttyUSB 串口傳輸的程式,可以下載研究看看,圖三是我程式開發的流程圖。 圖一:解決方案方塊圖 圖二:實際操作的照片 圖三:程式設計的流程圖 int main(int argc, char **argv) { int i; char outBuf[32]; pthread_t threads[4]; memset( Buffer, 0 , sizeof(Buffer) ); for(i = 0; i < 4; i++) { usbPort[i] = fd[i] = -1; threads[i] = -1; ...

[應用] 中文語音合成+語音辨識 以百度的AI開放平台 in Python 開發

圖片
語音技術介紹         語音合成 (Text-To-Speech) 和語音辨識 (Speech Recognition) 的技術存在數十年,不過近年來將這語音的技術應用在蘋果的Siri和亞馬遜的echo設備裡。對開發者而言,語音技術最麻煩的是各種語言、不特定人的字庫辭庫訓練,光要建立這龐大且精準的訓練庫就不是短時間能完成的。最近,發現百度(Baidu)提供 中文 語音合成和語音辨識的服務,網站如下: AI開放平台 ,裡面不只有語音技術服務,還有其他技術。調用百度各項技術的SDK,建立網路連結後,連上AI開放平台,便能取得合成的結果或者辨識的結果。另外,SDK也有提供各種程式語法的範例,如:Java、C++、C#、Python、Node.js ... 等等,以滿足各類程式開發者的需求。底下我以Python語法為例,開發一個中文語音合成+語音辨識的測試程式。 合成技術的開發         在語音合成的過程,我們輸入中文字,如果調用成功,百度平台會返回一個語音binary,這時我們再儲存成wave file或者mp3格式,然後撥放這個音檔。語音辨識的使用正好相反,我們必須提供一個wave file傳給百度平台,如果成功,它會返回辨識的結果。因此,在python開發時,我們需要能錄音和播放音檔的模組,稱為pyaudio,安裝這個模組的方式如下圖所示。安裝後,還需要安裝百度的模組,透過 pip 方式安裝,"pip install baidu-aip"。 圖一:安裝 pyaudio 模組         使用百度的開放平台之前,需要註冊一個百度帳號,然後在這帳號裡創建一個應用,如圖二所示,在這應用裡面我們可自行選擇想要載入的技術。下圖的MySpeechTest是我所創建的一個語音應用,這個應用選用了百度的語音合成和語音識別。一旦創建,在這個欄位上會出現三個參數:AppID、API Key和Secret Key數值,之後調用SDK,我們需要使用這三個參數。 圖二:註冊一個百度的應用連結         圖三是以python語法所開發的語音合成和語音識別,圖的右半邊為p...

[筆記] Raspberry Pi 樹莓派的 I/O 介面開發 in Python

圖片
         前面文章 使用C語言控制樹莓派的周邊介面,需要安裝WringPi的介面函式庫。同樣地,使用Python語言也需要一套介面函式庫,稱為 smbus 。樹莓派上的介面,如:I2C、SPI...必須借用smbus函式庫接口來控制這些通訊介面,參考底下的連結,有詳細的說明與使用。 RPi.GPIO Library Raspberry Pi 硬體控制 Using I2C LCD on Raspberry Pi         樹莓派3B+上面的操作系統已經內建smbus函式庫了,當我把I2C LCM1602模組接上後,在命令列輸入sudo i2cdetect -y 1,工具便能搜尋到模組的位址在0x27,表示smbus已經成功在系統內了。接下來,繼續用Python來開發LCM模組的控制,如下圖所示。 圖一:LCM1602 in Python