|
示波器是电子工程师或制造商的工作台上可以找到的最重要的工具之一。它主要用于查看波形并确定其输入端可能随时间变化的信号的电压电平、频率、噪声和其他参数。嵌入式软件开发人员还使用它进行代码调试,技术人员在维修期间对电子设备进行故障排除。这些原因使得示波器成为任何工程师必备的工具。唯一的问题是它们非常昂贵,实现最基本的功能、精度最低的示波器大约需要45美元到100美元,而更先进和高效的示波器则需要超过150美元。今天我将演示如何使用Arduino和一个软件,它将用我最喜欢的编程语言Python开发,制作一个低成本的4通道Arduino示波器,能够执行部署廉价示波器的任务,比如波形的显示和信号电压电平的确定。
工作原理 该项目分为两部分;
1. 数据转换器 2. 绘图仪
示波器通常涉及应用于其输入通道的模拟信号的视觉表示。为此,我们需要首先将信号从模拟转换为数字,然后绘制数据。对于转换,我们将利用Arduino使用的atmega328p微控制器上的ADC(模数转换器)将信号输入的模拟数据转换为数字信号。转换后,每次的值通过UART从Arduino发送到PC,其中使用python开发的绘图仪软件将通过绘制每个数据与时间的关系将输入的数据流转换为波形。
所需的组件 制作该项目需要以下组件:
● Arduino Uno开发板 ● 面包板 ● 10k电阻 ● LDR ● 连接导线
● Arduino IDE ● Python ● Python库:Pyseria、Matplotlib、Drawnow
原理图 Arduino示波器的原理图很简单。我们需要做的就是将要检查的信号连接到Arduino的指定模拟引脚。然而,我们将在简单的分压器设置中使用LDR来生成待检查的信号,使得生成的波形将基于LDR周围的光强度来描述电压电平。
按照下面的原理图连接组件;
连接后,设置应如下图所示。
完成连接后,我们可以继续编写代码。
Arduino示波器代码 我们将为这两个部分中的每一部分编写代码。对于前面提到的绘图仪,我们将编写一个python脚本,通过UART和Plots接受来自Arduino的数据,而对于转换器,我们将编写一个Arduino草图,从ADC接收数据并将其转换为发送到绘图仪的电压电平。
Python(绘图仪)脚本 由于python代码更复杂,我们将从它开始。
我们将使用几个库;如前所述,使用python脚本绘制了drawow、Matplotlib和Pyserial。 Pyserial允许我们创建一个可以通过串口进行通信的python脚本,Matplotlib使我们能够从通过串口接收的数据生成图,而drawow为我们提供了实时更新图的方法。
有几种方法可以在PC上安装这些软件包,最简单的方法是通过pip。 Pip可以通过Windows或Linux机器上的命令行安装。 PIP与python3一起打包,所以我建议你安装python3并检查关于将python添加到路径的方框。如果您在安装pip时遇到问题,请查看官方python网站获取提示。
安装pip后,我们现在可以安装我们需要的其他库。
windows用户打开命令提示符,linux用户打开终端,输入以下内容; 完成后,使用以下代码安装matplotlib; Drawnow有时和matplotlib一起安装但是为了确定,运行以下代码; 安装完成后,我们现在可以编写python脚本了。
我们首先导入代码所需的所有库; - import time
- import matplotlib.pyplot as plt
- from drawnow import *
- import pyserial
复制代码
接下来,我们创建并初始化将在代码中使用的变量。数组val将用于存储从串行端口接收的数据,cnt将用于计数。每50个数据计数后,将删除位置0处的数据。这样做是为了保持数据显示在示波器上。 接下来,我们创建串行端口对象,Arduino将通过它与我们的python脚本进行通信。确保下面指定的com端口与Arduino板与IDE通信的com端口相同。上面使用的115200波特率用于确保与Arduino的高速通信。为防止出错,还必须启用Arduino串行端口以与此波特率通信。 - port = serial.Serial('COM4', 115200, timeout=0.5)
复制代码接下来,我们使用绘图交互; 我们需要创建一个函数来根据接收到的数据生成绘图,创建我们预期的上限和下限,在这种情况下,基于Arduino ADC的分辨率为1023。我们还设置标题,标记每个轴并添加图例以便于识别绘图。 - #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')
复制代码
完成此操作后,我们现在可以编写主loop函数,在可用时从串行端口获取数据并绘制它。为了与Arduino同步,通过python脚本将握手数据发送到Arduino,以指示其准备读取数据。当Arduino收到握手数据时,它会回复来自ADC的数据。没有这种握手,我们将无法实时绘制数据。 - 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 sketch草图,用于获取表示来自ADC的信号的数据,然后等待从绘图仪软件接收握手信号。一旦收到握手信号,它就会通过UART将获取的数据发送到绘图仪软件。
我们首先声明将应用信号的Arduino的模拟引脚的引脚。 接下来,我们初始化并启动波特率为115200的串行通信 - void setup() {
- // initialize serial communication at 115200 bits per second to match that of the python script:
- Serial.begin(115200);
- }
复制代码最后,void loop()函数处理数据的读取,并通过串行将数据发送到绘图仪。 - 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脚本。您应该看到数据通过python命令行开始流入,并且绘图随光强度变化,如下图所示。
|