IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> 通过C#和Arduino实现软件示波器 -> 正文阅读

[嵌入式]通过C#和Arduino实现软件示波器


前言

??对于电子爱好者来说,示波器是一件不可或缺的神器。有了示波器的帮助,我们可以根据信号的实际变化来判断我们的电路或单片机程序的正确性。在有错误发生时,通过示波器我们也可以更容易的分析问题的产生点。

??但我们有没有想过,示波器本身就是一个电子电路,它的结构如何,又是如何工作的?作为一个电子电路的爱好者,我们是否可以搭建一个属于自己的示波器呢?下面作者就来通过Arduino作为信号采集电路来实现一个软件示波器。


一、作者对示波器的部分理解

??示波器,顾名思义是一个将信号的波形进行显示的仪器设备。最基本的示波器实际上只需要两个部分——1信号采集、2图像输出。我们直接对信号进行采集,然后将原始信号在屏幕上进行输出这本身已经是一个示波器了。

??但是如此简陋的示波器存在着巨大的问题:一方面,原始信号如果幅值很大或者很小,那么就会出现信号在屏幕上无法正常显示的问题——比如幅度很小的信号在屏幕上也许只是一条笔直的直线;另一方面,如果单纯的将各种信号进行连续的采集并展现在屏幕上,那么对于变化速度极高的信号我们肉眼很可能观看不到任何稳定的信号,只会觉得屏幕上的信号在不断的闪烁。
??要解决上面说到的两个问题,我们就需要对原始示波器的功能进行扩展。一方面,为了解决信号幅值的问题我们应当引入幅值调节;另一方面,为了解决高频率信号的显示问题我们应当引入触发功能

二、软件示波器

??我们在市场上购买的示波器一般是硬件示波器,它从硬件上包含了一台示波器应该具备的完整功能——信号的采集、处理、显示。

??硬件示波器有着完整的硬件结构,使得其成本相对较高。对于我们自己制作示波器而言,为了节约成本,可以选择软示波器——即采用硬件对信号进行采集,而对信号的处理和显示通过软件功能在电脑上进行实现。

??软件示波器,正如前文所提可以分为两个大的部分——一部分是基于电子电路的信号采集部分;另一部分是基于软件的信号处理和显示功能。

??而如果对整个流程进行描述,则是电子电路对原始信号进行采集(ADC),之后通过通信将采集到的数据发送给计算机里运行的软件。软件在接收到原始信号的数值后,对其幅值进行处理,并根据我们设定的触发方式将信号图形显示到图像区域,如下图。
在这里插入图片描述

三、软件示波器的实现

采集部分

??信号采集电路使用STM32F103C8T6最小系统作为基础硬件,通过它所自带的ADC功能来完成信号的采集。采集之后,则通过串口通信将采集到的原始信号传输给我们的软示波器软件。

??当然,也可以通过其它的电路及开发方式以相同的思路来实现这些功能。(如果你需要将手中的STM32F103C8T6配置为Arduino的开发方式,可以参照这篇文章STM32duino——依托Arduino框架玩转STM32(一): 开发环境的配置

第一种方式

??在采集和传输方式上,我们有两种选择:一种是,我们可以选择让Arduino每次采集一个ADC的值,然后通过串口传输,传输完成后再进行下一次的采集。采用这种方式,在编程上是极为简单的,但是在串口传输后再进行下一次的采集将导致采样的频率降低,使得我们无法采集到一些变化较快的信号。

??例如下图中,上半部分黑色实线是我们的原始信号,细点画线是采集发生的时刻;下半部分的点为对应的采集值。我们可以很容易的发现,对于变化频率较低的信号我们的采样基本可以正确的描述其原始状态,但是对于原始图形中出现的尖峰毛刺我们可能会不能正确的对其捕捉。

在这里插入图片描述

第二种方式

??另一种方式则是:连续的进行ADC采集,将采集到的数据存储于单片机的存储区,在存储区域满后进行连续的串口发送。采用这种方式的优点是提高了信号采集时的采集频率,可以将更高频率的信号变化采集出来。

??但这种方式也存在自己的缺点,就是采集是间歇性的,即连续的采集——连续的发送——连续的采集(如果采用STM32原生的DMA传输方式可以最大程度减小这种采集的不连续,但这不在我们此次的讨论范围之内)。第二种方式的采集效果可以参照下图,我们很容易的发现高频的毛刺信号可以被采集到了,但是由于传输阶段的存在,采集变得不再连续。
在这里插入图片描述

本次的选择

??咱本次的软示波器制作中,我们先采用第一种方式进行。但如果使用STM32的原生开发模式,更推荐使用DMA的方式来实现第二种采集方式,并将信号触发的功能也在单片机端实现,以实现示波器最佳的性能!!!

Arduino对模拟量的读取和传输

??Arduino中的代码相当简单。我们先声明一个int变量an用于存储每次模拟量读取的值,然后再setup中声明PA0引脚的工作模式为INPUT(输入模式,含数字量读取和模拟量读取),之后开启串口,并选择9600这个中规中矩的波特率。实际上波特率越高对于模拟示波器来说性能越好,当然也会带来一些问题。在此我们先选择9600这个中规中矩的波特率。

int an;

void setup() {
  pinMode(PA0,INPUT);
  Serial.begin(9600);
}

void loop() {
  an=analogRead(PA0);
  Serial.println(an);
  delay(1);
}

??之后,在Arduino程序的Loop中,我们依次进行模拟量的读取,串口的模拟量值传输,以及1ms的延时。就此,Arduino端的配置就完成了,当你把程序下载到电路板中后,打开Arduino的串口监视器你会看到一系列变化的数字——即PA0脚的模拟量电压(对于STM32F103来说3.3V对应4095),就像下图。
在这里插入图片描述

PC端程序

??在完成了Arduino的配置并能够正常的发送读取的模拟量之后,我们便可以开始PC端程序的设计了。PC端程序从功能上来说主要有三个部分,分别是:1串口读取、2数据处理和触发判断、3绘图。在有了这三部分的功能后,程序即可接收到电路板发出的模拟量数值,然后经过处理最终显示在屏幕上。

界面设计

??针对我们所需要的功能,界面上设计了串口的操作区域——包含串口的选择以及连接、断开操作。设计了触发和扫描方式操作区域,通过这个区域我们可以选择单次扫描(扫描一页图像后停止,在实际的示波器上我们通常用这个功能抓取要分析的信号流)、连续扫描,并设置扫描的触发方式和触发阈值。还加入了一个pictureBox用于显示扫描到的图像结果。

最终的界面设计如下:
在这里插入图片描述

串口读取

??在串口读取部分,我们除了对串口的波特率、较验方式、数据位和停止位进行设置外,最重要的就是绑定串口的接收事件sp.DataReceived += getValue。如此一来,每当电脑的串口接收到电路板发来的模拟量数据,便会触发getValue来进行处理。getValue会读取一行串口数据,然后将数据从字符串转换为int形式,并通过changeValue1来传递到主程序的value中(因为getValue被触发时是在单独的线程中活动的,对于跨线程的内容更改必须通过委托的形式)。

                sp.PortName = comboBox1.Text;//设置端口
                sp.BaudRate = 9600;//设置波特率
                sp.Parity = Parity.None;//设置校验
                sp.DataBits = 8;//设置数据位
                sp.StopBits = StopBits.One;//设置停止位
                sp.DataReceived += getValue;//绑定接收事件处理
                sp.Open();//打开串口
        private void getValue(object obj, SerialDataReceivedEventArgs e)
        {
            string tmp=sp.ReadLine();
            try
            {
                int tmp2 = int.Parse(tmp);
                changeValue1(tmp2);
            }
            catch (Exception)
            {

            }
        }
        private void changeValue1(int v)
        {
            if (InvokeRequired)
            {
                D1 d = new D1(changeValue1);
                this.Invoke(d, v);
            }
            else
            {
                value = v;
            }
        }

数据处理和绘图

??当扫描开始进行后,我们会开启一个单独的扫描线程,由改线程来进行数据的处理和绘图,以防止主界面的阻塞。

		th1 = new Thread(new ThreadStart(scan));//否则进行连续扫描
		th1.Start();

??扫描线程通过Sleep的方式控制两次采集的间隔,以此来达到水平缩放的目的。需要注意的是,实际的示波器的采集间隔是通过单片机定时器中断实现的。在我们的虚拟示波器中,这个功能实际上很不好用——因为我们的最高扫描速度本来就不快,已经没有缩放的必要了。这里依然做出此功能是为了让大家理解实际示波器的工作方式。

??由于在C#的pictureBox中,图像的Y坐标越大图像反而越低,所以我们采用600-valuev_mul600/4096这种方式来对图像进行垂直方向的颠倒。其中,600是我们的pictureBox的高度。

??之后我们通过Graphics对象来将读取到的所有点以直线的方式连续的画到画布(Bitmap)上,并通过changePic将pictureBox的图像内容变为我们的画布,由此完成图像的输出。

            while (true)
            {
                Thread.Sleep(h_mul);//通过延时来实现水平坐标的缩放功能,当h_mul越大,两次取点的间隔越大,实现了图像水平的缩小。在硬件示波器上,也是这样的原理,只是通过时钟中断来控制扫描取点的间隔
                values_tmp[count] = 600-value*v_mul*600/4096;
                count++;
                count2++;
                if (count == 1000)
                {
                    count = 0;
                }
                if (count2>1000)
                {
                    count2 = 1000;
                }
                bmp_tmp = new Bitmap(1000, 600);//创建新的画布
                g = Graphics.FromImage(bmp_tmp);//创建绘画对象
                for (int i = 1; i < count2; i++)//进行绘画
                {
                    g.DrawLine(p, new Point(i - 1, values_tmp[i - 1]), new Point(i, values_tmp[i]));//将每个采集点进行直线绘画
                }
                changePic(bmp_tmp);//更新显示的图像

            }

最终的效果

??打开程序,对串口进行连接,并开启扫描,便可以对PA0端口的电压进行采集并对波形绘图了。
在这里插入图片描述

源码

虚拟示波器的C#程序源码

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-03-21 21:07:25  更:2022-03-21 21:07:47 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 6:40:48-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码