背景:
對於一些需要快速驗證傳感器性能,或者某些實驗需要快速采集數據並且需要直觀顯示成波形或者圖片, 搭建一個簡易方便的數據采集分析系統是有必要的.
本文主要介紹以下幾個方面:
數據采集整體框架.
Pc使用python設定相關參數: fs, 采樣點數 采樣時間 etc..
MCU使用自帶ADC 根據pc設定的采樣率fs進行采集后通過uart將數據回傳.
Python可以直接對數據簡單處理,或者保存成csv方便導入matlab進行更進一步數據分析.
Ex1: ADC規則組同時采集 ADC dual channel mode cfg.(strict sample multiple channel at same time)
Ex2: ADC采樣率自動配置 adc sample rate automatic cfg.
Py & mcu 自定簡易通信協議. eg:
- Py send ‘#f=1000’, ‘#sc=1024’ (此處表示采樣率1000hz, 采樣點數1024)
- Mcu 解析uart接收的命令. 配置參數后進行采樣. 在采樣完成的DMA傳輸完成IRQ里(使用DMA可以提高最大采樣速率)將數據上傳upload.
串口助手抓到的數據格式(字符串, 假設我這里是2個通道同時采樣)
采集adc值 + 換行
adc1 , adc2 + ’\r\n’
123,333 124,334 120,330 xxx,xxx
Python實現簡易串口讀寫與存儲.
1. 環境搭建: (打開命令行cmd.exe, 輸入以下命令安裝serial模塊)
pip install serial
2. 開始寫代碼: 打開串口, 讀寫操作
包含頭文件 import serial
import serial ser = serial.Serial('com19', 115200) #按照參數打開串口
ser.set_buffer_size(rx_size=20480) #為了設置合適的緩沖區
if ser.isOpen(): #檢查打開成功
print('open port successful') data = b'f=' + bytes(fs, encoding='ascii') + b'\r\n' ser.write(data) # only bytes array is supported.
lines = '' #所有的行
while True: # 在這里阻塞2s等待, 讀取rx buffer的數據
time.sleep(2) cnt = ser.inWaiting() # bytes to read in rx buffer
if (cnt > 0): data = ser.read(cnt) lines = str(data, encoding='ascii') # 轉碼成字符串
break
3. 保存成csv . 用於存檔或者導入MATLAB等其他數據分析處理軟件
csv_file = open(f_name + '.csv' , 'w') # 創建並打開一個文件
csv_file.write(lines) # 如果接收時已經是csv格式可以直接寫入
for i in range(len(adc1)): # 或者解析成list后再按需存入
csv_file.write(adc1[i] + ',' + adc2[i] + '\n') csv_file.close() # 寫完記得關閉.
4.簡單的python繪圖 - matplotlib
0. 安裝matplotlib
pip install matplotlib
1.導入並使用它的pylab來繪圖
import matplotlib.pylab as pl lines = str(lines, encoding='ascii').splitlines() #.split('\r\n')
light_cnt = len(lines) # 光強數據長度
print('cnt = ', light_cnt) light_data = [] # 光強數據
for line in lines: # 分割成一行一行, 每行2個數據
# if line is not '':
light_data.append(int(line)) print(int(line)) N = light_cnt axis_x = np.linspace(1, N, num=N) pl.plot(axis_x, light_data) pl.title('charge time= %dms' % charge_time) pl.show()
更詳細繪圖代碼參考 https://www.jianshu.com/p/78ba36dddad8
簡單操作 - matlab 繪多個子圖相關
1. 同一張圖繪制多條曲線:
plot(y1);
Hold on;
plot(y2);
2. 同一個頁面繪制多張圖用於對比:
figure(1); %創建畫布.
subplot(1, 2, 1);%在1行*2列里,畫第1個圖
subplot(1, 2, i);
%在1行*2列的格子畫第i個圖 ,1<i<=總數
例如subplot(2, 3, i)就是這樣的.i=1~6
簡單操作 - matlab 讀取 csv文件
M = csvread(csv_name); %返回M是一個矩陣. M(:,1) %可以取第一列.(ch1的數據) :表示所有行 M(:,2) %可以取第二列, 以此類推. plot(M); %按默認 畫出圖 title( ['f=' num2str(freq)]) %畫圖后title函數用於加上格式化的標題
Ex1: ADC dual channel mode cfg.(strictly sample multiple channel at same time)
多ADC同時規則采樣配置(嚴格的同時,同一時鍾邊沿采樣)步驟 (單ADC在同一時間最多只能采樣1個channel)
- stm32f4支持最多3ADC同時采樣,稱為dual mode/ triple mode.
- 多ADC時, ADC1=master, ADC2/3 = slave.
只可能存在2種搭配,dual:ADC1+ADC2. Triple:ADC1+ADC2+ADC3.
多ADC無法同時采集同一個pin.
3. 如果開啟DMA傳輸, 只需要為master(也就是ADC1) 配置即可.
Slave會由master進行觸發轉換.
DMA的src data addr 配置成專門的ADC-CDR 寄存器.
單個data size = word. 在dual mode時, 相當於ADC1+ADC2分別在高半字和低半字
Ex2: adc sample rate automatic cfg.
要計算ADC采樣率, 需要單次轉換所需時鍾周期tc cycle和ADC時鍾頻率 fa.
單次轉換cycle = sampling cycle + n-bit resolution cycle.
例如配置為 3 sampling cycle, 12bit采樣時, 總共需要的轉換時間= 15cycle.也就是每15個ADC clock 可以采樣一次.
然后對於STM32F4, ADC clock 來自APB2 clock. 於是fa與APB2分頻值APB2_clk_div以及ADC配置的ADC_CLK_DIV相關.
將這些所有可能的分頻值adc_div, apb2_clk_div與單次轉換周期tc組合起來,可以構成i*j*k種組合方式,用for來遍歷計算.然后取手冊上可行的ADC clock范圍(0.6M~36Mhz)來計算可以所有算出可配置的ADC采樣率fs.