示波器是任何電子工程師或制造商的工作臺上最重要的工具之一。它主要用于查看波形并確定施加在其輸入端的信號的電壓電平、頻率、噪聲和其他參數(shù),這些參數(shù)可能會隨時間變化。嵌入式軟件開發(fā)人員還使用它進行代碼調(diào)試,技術(shù)人員使用它在維修期間對電子設備進行故障排除。這些原因使示波器成為任何工程師的必備工具。唯一的問題是它們可能非常昂貴,以最低精度執(zhí)行最基本功能的示波器可能高達 45 至 100 美元,而更先進和更高效的示波器的成本超過 150 美元。今天,我將演示如何使用Arduino和一款軟件,該軟件將使用我最喜歡的編程語言Python開發(fā),以構(gòu)建低成本的4通道Arduino示波器,該示波器能夠執(zhí)行部署一些廉價示波器的任務,例如顯示波形和確定信號的電壓電平。
這個項目有兩個部分;
數(shù)據(jù)轉(zhuǎn)換器
繪圖儀
示波器通常涉及施加到其輸入通道的模擬信號的視覺表示。為此,我們需要首先將信號從模擬轉(zhuǎn)換為數(shù)字,然后繪制數(shù)據(jù)。對于轉(zhuǎn)換,我們將利用Arduino使用的atmega328p微控制器上的ADC(模數(shù)轉(zhuǎn)換器)將信號輸入的模擬數(shù)據(jù)轉(zhuǎn)換為數(shù)字信號。轉(zhuǎn)換后,每次的值通過UART從Arduino發(fā)送到PC,在那里,將使用python開發(fā)的繪圖儀軟件將通過繪制每個數(shù)據(jù)與時間的關(guān)系將傳入的數(shù)據(jù)流轉(zhuǎn)換為波形。
必需組件
生成此項目需要以下組件;
Arduino Uno(可以使用任何其他板)
面包板
10k 電阻器 (1)
LDR (1)
跳線
所需軟件
Arduino IDE
蟒
Python 庫:Pyserial、Matplotlib、Drawnow
圖表
Arduino示波器的原理圖很簡單。我們需要做的就是將要檢查的信號連接到Arduino的指定模擬引腳。但是,我們將在簡單的分壓器設置中使用LDR來生成要檢查的信號,以便生成的波形將根據(jù)LDR周圍的光強度描述電壓電平。
按照下面的原理圖連接組件;
連接后,設置應如下圖所示。
完成所有連接后,我們可以繼續(xù)編寫代碼。
ArduinoOsclloscopeCode
我們將為這兩個部分中的每一個編寫代碼。對于前面提到的繪圖儀,我們將編寫一個python腳本,通過UART和Plots接受來自Arduino的數(shù)據(jù),而對于轉(zhuǎn)換器,我們將編寫一個Arduino草圖,該草圖從ADC接收數(shù)據(jù)并將其轉(zhuǎn)換為發(fā)送到繪圖儀的電壓電平。
Python(繪圖儀)腳本
由于 python 代碼更復雜,我們將從它開始。
我們將使用幾個庫,包括;drawnow,Matplotlib和Pyserial使用前面提到的python腳本。Pyserial 允許我們創(chuàng)建一個可以通過串行端口進行通信的 python 腳本,Matplotlib 使我們能夠從通過串行端口接收的數(shù)據(jù)生成繪圖,drawnow 為我們提供了一種實時更新繪圖的方法。
有幾種方法可以在您的 PC 上安裝這些軟件包,最簡單的是通過pip。Pip 可以通過命令行安裝在 Windows 或 Linux 機器上。PIP 與 python3 打包在一起,所以我建議您安裝 python3 并選中有關(guān)將 python 添加到路徑的框。如果您在安裝 pip 時遇到問題,請查看 Python 官方網(wǎng)站以獲取提示。
安裝 pip 后,我們現(xiàn)在可以安裝所需的其他庫。
打開Windows用戶的命令提示符,Linux用戶的終端,然后輸入以下內(nèi)容;
pip install pyserial
完成此操作后,請使用以下命令安裝 matplotlib;
pip install matplotlib
Drawnow 有時與 matplotlib 一起安裝,但可以肯定的是,運行;
pip install drawnow
安裝完成后,我們現(xiàn)在可以編寫 python 腳本了。
我們首先導入代碼所需的所有庫;
import time import matplotlib.pyplot as plt from drawnow import *
import pyserial
接下來,我們創(chuàng)建并初始化將在代碼期間使用的變量。數(shù)組 val 將用于存儲從串行端口接收的數(shù)據(jù),cnt 將用于計數(shù)。每 50 個數(shù)據(jù)計數(shù)后,位置 0 處的數(shù)據(jù)將被刪除。這樣做是為了保持示波器上顯示的數(shù)據(jù)。
val = [ ] cnt = 0
接下來,我們創(chuàng)建串行端口對象,Arduino 將通過該對象與我們的 python 腳本進行通信。確保下面指定的 COM 端口與 Arduino 板與 IDE 通信的 COM 端口相同。上面使用的115200波特率用于確保與Arduino的高速通信。為防止錯誤,還必須啟用 Arduino 串行端口才能與此波特率通信。
port = serial.Serial('COM4', 115200, timeout=0.5)
接下來,我們使用;
plt.ion()
我們需要創(chuàng)建一個函數(shù)來從收到的數(shù)據(jù)生成繪圖,創(chuàng)建我們期望的上限和最小限制,在這種情況下,基于 Arduino's ADC 的分辨率為 1023。我們還設置了標題,標記了每個軸并添加了圖例,以便于識別情節(jié)。
#create the figure function def makeFig(): plt.ylim(-1023,1023) plt.title('Osciloscope') plt.grid(True) plt.ylabel('ADC outputs') plt.plot(val, 'ro-', label='Channel 0') plt.legend(loc='lower right')
完成此操作后,我們現(xiàn)在準備編寫主循環(huán),該循環(huán)在可用時從串行端口獲取數(shù)據(jù)并繪制它。為了與Arduino同步,python腳本將握手數(shù)據(jù)發(fā)送到Arduino,以指示其準備讀取數(shù)據(jù)。當Arduino收到握手數(shù)據(jù)時,它會回復來自ADC的數(shù)據(jù)。沒有這種握手,我們將無法實時繪制數(shù)據(jù)。
while (True):
port.write(b's') #handshake with Arduino
if (port.inWaiting()):# if the arduino replies
value = port.readline()# read the reply
print(value)#print so we can monitor it
number = int(value) #convert received data to integer
print('Channel 0: {0}'.format(number))
# Sleep for half a second.
time.sleep(0.01)
val.append(int(number))
drawnow(makeFig)#update plot to reflect new data input
plt.pause(.000001)
cnt = cnt+1
if(cnt>50):
val.pop(0)#keep the plot fresh by deleting the data at position 0
Arduino 代碼
第二個代碼是Arduino草圖,用于從ADC獲取表示信號的數(shù)據(jù),然后等待從繪圖儀軟件接收握手信號。一旦收到握手信號,它就會通過UART將采集的數(shù)據(jù)發(fā)送到繪圖儀軟件。
我們首先聲明將應用信號的Arduino模擬引腳的引腳。
int sensorpin = A0;
接下來,我們初始化并開始波特率為 115200 的串行通信
void setup() {
// initialize serial communication at 115200 bits per second to match that of the python script:
Serial.begin(115200);
}
最后,voidloop() 函數(shù)處理數(shù)據(jù)的讀取,并通過串行將數(shù)據(jù)發(fā)送到繪圖儀。
void loop() {
// read the input on analog pin 0:
float sensorValue = analogRead(sensorpin);
byte data = Serial.read();
if (data == 's')
{
Serial.println(sensorValue);
delay(10); // delay in between reads for stability
}
}
完整的 Arduino 示波器代碼在下面以及本文末尾給出,如下所示。
int sensorpin = A0;
void setup() {
// initialize serial communication at 115200 bits per second to match that of the python script:
Serial.begin(115200);
}
void loop() {
// read the input on analog pin 0:########################################################
float sensorValue = analogRead(sensorpin);
byte data = Serial.read();
if (data == 's')
{
Serial.println(sensorValue);
delay(10); // delay in between reads for stability
}
}
Arduino 示波器的實際應用
將代碼上傳到Arduino設置并運行python腳本。您應該看到數(shù)據(jù)開始通過python命令行流入,并且繪圖隨光強度而變化,如下圖所示。
Python Code:
import time
import matplotlib.pyplot as plt
from drawnow import *
import serial
val = [ ]
cnt = 0
#create the serial port object
port = serial.Serial('COM4', 115200, timeout=0.5)
plt.ion()
#create the figure function
def makeFig():
plt.ylim(-1023,1023)
plt.title('Osciloscope')
plt.grid(True)
plt.ylabel('data')
plt.plot(val, 'ro-', label='Channel 0')
plt.legend(loc='lower right')
while (True):
port.write(b's') #handshake with Arduino
if (port.inWaiting()):# if the arduino replies
value = port.readline()# read the reply
print(value)#print so we can monitor it
number = int(value) #convert received data to integer
print('Channel 0: {0}'.format(number))
# Sleep for half a second.
time.sleep(0.01)
val.append(int(number))
drawnow(makeFig)#update plot to reflect new data input
plt.pause(.000001)
cnt = cnt+1
if(cnt>50):
val.pop(0)#keep the plot fresh by deleting the data at position 0
Arduino Code:
int sensorpin = A0;
void setup() {
// initialize serial communication at 115200 bits per second to match that of the python script:
Serial.begin(115200);
}
void loop() {
// read the input on analog pin 0:########################################################
float sensorValue = analogRead(sensorpin);
byte data = Serial.read();
if (data == 's')
{
Serial.println(sensorValue);
delay(10); // delay in between reads for stability
}
}
-
示波器
+關(guān)注
關(guān)注
113文章
6264瀏覽量
185283 -
python
+關(guān)注
關(guān)注
56文章
4798瀏覽量
84798 -
Arduino
+關(guān)注
關(guān)注
188文章
6471瀏覽量
187303
發(fā)布評論請先 登錄
相關(guān)推薦
評論