Android实现简易示波器

教你将android手机变成蓝牙无线示波器,Android手机+蓝牙扩展电路=示波器 本帖最后由 kejiren123 于 2012-5-15 10:10 编辑强烈建议logicgreen 大移植到LGT单片机上,如果能出套件相信很多人会买。我愿意出100元买一个LGT单片机的示波器套件(预估材料成本在40-60元)。我看了,代码不复杂。以下为全部源码。************************************Bluetooth Oscilloscopeyus - p... 阅读详情

用SurfaceView简易的实现一个示波器,这需求估计玩电子的比较需要吧。

这里学到一个接口蛮有意思的,简单的说一下。

holder.lockCanvas(null),就是锁住整张画布,绘画完成后也更新整张画布的内容到屏幕上,这个没有什么疑惑。而 lockCanvas(Rect dirty)就是锁住画布中的某个区域,绘画完成后也只更新这个区域的内容到屏幕。使用后一接口的初衷是只更新必要的画面内容以节省时间,提高程序运行的效率,适用于大动态画面的场景。

示波器的实现也非常简单,在显示曲线之前要布置黑色背景、白色网格和坐标轴:

private void drawBackGround(SurfaceHolder holder) {
        Canvas canvas = holder.lockCanvas();
        // 绘制黑色背景
        canvas.drawColor(Color.BLACK);
        Paint p = new Paint();
        p.setColor(Color.WHITE);
        p.setStrokeWidth(2);

        // 画网格8*8
        Paint mPaint = new Paint();
        mPaint.setColor(Color.GRAY);// 网格为黄色
        mPaint.setStrokeWidth(1);// 设置画笔粗细
        int oldY = 0;
        for (int i = 0; i <= 8; i++) {// 绘画横线
            canvas.drawLine(0, oldY, WIDTH, oldY, mPaint);
            oldY = oldY + WIDTH/8;
        }
        int oldX = 0;
        for (int i = 0; i <= 8; i++) {// 绘画纵线
            canvas.drawLine(oldX, 0, oldX, HEIGHT, mPaint);
            oldX = oldX + HEIGHT/8;
        }

        // 绘制坐标轴
        canvas.drawLine(X_OFFSET, centerY, WIDTH, centerY, p);
        canvas.drawLine(X_OFFSET, 40, X_OFFSET, HEIGHT, p);
        holder.unlockCanvasAndPost(canvas);
        holder.lockCanvas(new Rect(0, 0, 0, 0));
        holder.unlockCanvasAndPost(canvas);
    }

首先是正余弦线的画法:

    /**
     * 正余弦曲线函数
     */
    private void showSineCord(final View view){
        drawBackGround(holder);
        cx = X_OFFSET;
        if (task != null) {
            task.cancel();
        }
        task = new TimerTask() {

            @Override
            public void run() {
                // 根据是正玄还是余玄和X坐标确定Y坐标
                int cy = view.getId()==R.id.btnShowSin?
                        centerY- (int) (100 * Math.sin((cx - 5) * 2 * Math.PI/ 150))
                        :centerY- (int) (100 * Math.cos((cx - 5) * 2 * Math.PI/ 150));

                Canvas canvas = holder.lockCanvas(new Rect(cx, cy - 2,
                        cx + 2, cy + 2));
                // 根据X,Y坐标画点
                canvas.drawPoint(cx, cy, paint);
                cx++;
                // 超过指定宽度,线程取消,停止画曲线
                if (cx > WIDTH) {
                    task.cancel();
                    task = null;
                }
                // 提交修改
                holder.unlockCanvasAndPost(canvas);
            }
        };
        timer.schedule(task, 0, 30);
    }

最后是折线曲线的实现:

/**
     * 折线曲线
     */
    private void showBrokenLine(){

        drawBackGround(holder);
        cx = X_OFFSET;
        if (task != null) {
            task.cancel();
        }
        task = new TimerTask() {
            int startX = 0;
            int startY = 200;
            Random random = new Random();
            @Override
            public void run() {

                int cy = random.nextInt(100)+200;

                Canvas canvas = holder.lockCanvas(new Rect(cx-10, cy - 900,
                        cx + 10, cy + 900));

                // 根据X,Y坐标画线
                canvas.drawLine(startX, startY ,cx, cy, paint);

                //结束点作为下一次折线的起始点
                startX = cx;
                startY = cy;

                cx+=10;
                // 超过指定宽度,线程取消,停止画曲线
                if (cx > WIDTH) {
                    task.cancel();
                    task = null;
                }
                // 提交修改
                holder.unlockCanvasAndPost(canvas);
            }
        };
        timer.schedule(task, 0, 300);
    }

就这么简单,运行结果演示:
这里写图片描述

代码也不多,所以就全部贴出来,懒得打包了,MainActivity的代码:

public class MainActivity extends ActionBarActivity implements OnClickListener {
    private SurfaceHolder holder;
    private SurfaceView showSurfaceView;

    private Button btnShowSin;
    private Button btnShowCos;
    private Button btnShowBrokenLine;

    private Paint paint;

    private int HEIGHT;
    // 要绘制的曲线的水平宽度
    private int WIDTH;
    // 离屏幕左边界的起始距离
    private final int X_OFFSET = 5;
    // 初始化X坐标
    private int cx = X_OFFSET;
    // 实际的Y轴的位置
    private int centerY ;
    private Timer timer = new Timer();
    private TimerTask task = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // 获得SurfaceView对象
        showSurfaceView = (SurfaceView) findViewById(R.id.showSurfaceView);
        btnShowSin = (Button) findViewById(R.id.btnShowSin);
        btnShowCos = (Button) findViewById(R.id.btnShowCos);
        btnShowBrokenLine = (Button) findViewById(R.id.btnShowBrokenLine);

        btnShowSin.setOnClickListener(this);
        btnShowCos.setOnClickListener(this);
        btnShowBrokenLine.setOnClickListener(this);

        InitData();

        // 初始化SurfaceHolder对象
        holder = showSurfaceView.getHolder();
        paint = new Paint();
        paint.setColor(Color.GREEN);
        paint.setStrokeWidth(3);
    }

    private void InitData() {
        Resources resources = this.getResources();
        DisplayMetrics dm = resources.getDisplayMetrics();
        //获取屏幕的宽度作为示波器的边长
        HEIGHT = dm.widthPixels;
        WIDTH = dm.widthPixels;
        //Y轴的中心就是高的一半
        centerY = HEIGHT / 2;

    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
        case R.id.btnShowSin:
            showSineCord(view);
            break;
        case R.id.btnShowCos:
            showSineCord(view);
            break;
        case R.id.btnShowBrokenLine:
            showBrokenLine();
            break;
        }

    }

    /**
     * 折线曲线
     */
    private void showBrokenLine(){

        drawBackGround(holder);
        cx = X_OFFSET;
        if (task != null) {
            task.cancel();
        }
        task = new TimerTask() {
            int startX = 0;
            int startY = 200;
            Random random = new Random();
            @Override
            public void run() {

                int cy = random.nextInt(100)+200;

                Canvas canvas = holder.lockCanvas(new Rect(cx-10, cy - 900,
                        cx + 10, cy + 900));

                // 根据X,Y坐标画线
                canvas.drawLine(startX, startY ,cx, cy, paint);

                //结束点作为下一次折线的起始点
                startX = cx;
                startY = cy;

                cx+=10;
                // 超过指定宽度,线程取消,停止画曲线
                if (cx > WIDTH) {
                    task.cancel();
                    task = null;
                }
                // 提交修改
                holder.unlockCanvasAndPost(canvas);
            }
        };
        timer.schedule(task, 0, 300);
    }

    /**
     * 正余弦曲线函数
     */
    private void showSineCord(final View view){
        drawBackGround(holder);
        cx = X_OFFSET;
        if (task != null) {
            task.cancel();
        }
        task = new TimerTask() {

            @Override
            public void run() {
                // 根据是正玄还是余玄和X坐标确定Y坐标
                int cy = view.getId()==R.id.btnShowSin?
                        centerY- (int) (100 * Math.sin((cx - 5) * 2 * Math.PI/ 150))
                        :centerY- (int) (100 * Math.cos((cx - 5) * 2 * Math.PI/ 150));

                Canvas canvas = holder.lockCanvas(new Rect(cx, cy - 2,
                        cx + 2, cy + 2));
                // 根据X,Y坐标画点
                canvas.drawPoint(cx, cy, paint);
                cx++;
                // 超过指定宽度,线程取消,停止画曲线
                if (cx > WIDTH) {
                    task.cancel();
                    task = null;
                }
                // 提交修改
                holder.unlockCanvasAndPost(canvas);
            }
        };
        timer.schedule(task, 0, 30);
    }

    private void drawBackGround(SurfaceHolder holder) {
        Canvas canvas = holder.lockCanvas();
        // 绘制黑色背景
        canvas.drawColor(Color.BLACK);
        Paint p = new Paint();
        p.setColor(Color.WHITE);
        p.setStrokeWidth(2);

        // 画网格8*8
        Paint mPaint = new Paint();
        mPaint.setColor(Color.GRAY);// 网格为黄色
        mPaint.setStrokeWidth(1);// 设置画笔粗细
        int oldY = 0;
        for (int i = 0; i <= 8; i++) {// 绘画横线
            canvas.drawLine(0, oldY, WIDTH, oldY, mPaint);
            oldY = oldY + WIDTH/8;
        }
        int oldX = 0;
        for (int i = 0; i <= 8; i++) {// 绘画纵线
            canvas.drawLine(oldX, 0, oldX, HEIGHT, mPaint);
            oldX = oldX + HEIGHT/8;
        }

        // 绘制坐标轴
        canvas.drawLine(X_OFFSET, centerY, WIDTH, centerY, p);
        canvas.drawLine(X_OFFSET, 40, X_OFFSET, HEIGHT, p);
        holder.unlockCanvasAndPost(canvas);
        holder.lockCanvas(new Rect(0, 0, 0, 0));
        holder.unlockCanvasAndPost(canvas);
    }

}

其布局文件的代码:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center_horizontal"
        android:orientation="horizontal" >

        <Button
            android:id="@+id/btnShowSin"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="click"
            android:text="正玄曲线" />

        <Button
            android:id="@+id/btnShowCos"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="click"
            android:text="余玄曲线" />

        <Button
            android:id="@+id/btnShowBrokenLine"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="click"
            android:text="折线曲线" />
    </LinearLayout>

    <SurfaceView
        android:id="@+id/showSurfaceView"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</LinearLayout>
Android串口示波器,解读一个超赞的开源串口虚拟示波器项目 大家好,今天给大家推荐一个开源的串口虚拟示波器项目,可以实时显示串口传输的数据,非常直观,当然也可以做二次开发,非常的灵活。基本功能双击放大项目地址:https://github.com/CieNTi/serial_port_plotter这是一个Windows应用程序,可显示来自串行端口的实时数据,使用Qt和QCustomPlot库构建。具体有哪些功能:范围无限制:新的通道数据会创建一个新图形并... 阅读详情

相关推荐

虚拟示波器介绍

提到示波器,大部分硬件工程师,都会想到这些: 这种台式数字示波器,推翻并取代CRT显像管的模拟示波器的主导地位,已经几十年了。毫无争议地,在相当长的未来,它还会继续主导测量仪器市场,直到虚拟示波器崛起。 但是得承认,在很多专业领域,虚拟示波器无法取代台式的数字示波器产品,示波器厂商大佬们完全不用担心。 目前,虚拟示波器主要定位在零售价3001000元左右的散客市场,避开了台式示波器的1500几万元的市场。所以目前虚拟示波器和台式数字示波器的竞争冲突不严重,甚至还会互相补充。但是虚拟示波器

一路带飞的博客 3403

labwindows/cvi 多线程绘制曲线

labwindows/cvi通过多线程将数据绘制成曲线,并动态显示。

Android提高第十一篇之模拟信号示波器_android 模拟信号示波器示例代码

ClsOscilloscope.java是实现示波器的类库,包含AudioRecord操作线程和SurfaceView绘图线程的实现,两个线程同步操作,代码如下:// 线程控制标记/*** X轴缩小的比例*//*** Y轴缩小的比例*//*** Y轴基线*//*** 初始化*//*** 开始* AudioRecord的MinBufferSize*/// 开始录制线程// 开始绘制线程/*** 停止*/// 清除/**

2401_86022387的博客 734

LabWindows/CVI学习总结——前言

小白最近刚刚开始了研究生的学习生活(苦行僧般的生活),面临的第一个挑战就是学习NI公司的LabWindows/CVI软件(后面都简称CVI)。CVI软件是一种交互式的C语言开发环境,主要是用于开发检测系统啊、数据采集系统啊、过程监控系统啊、虚拟仪器啊等等吧,还有好多好多工业应用小白也说不上来,反正就是功能很强大啦~ 但是小白在学习的过程中发现,无论是学校推荐的参考教材还是网上的教程...

weixin_40161724的博客 3779

LOTO 示波器安卓手机示波器如何使用?

LOTO 示波器安卓手机示波器如何使用? 本文主要介绍LOTO示波器手机版本的使用。在之前的文章中,我们介绍了windows系统下它的使用,但他其实也可以支持安卓手机,而且必须是带OTG功能的安卓手机。 安卓版本的示波器,可以在安卓系统或者windows系统下操作。但是购买windows版本的示波器,是只支持windows系统下操作的。 客户买到手后,首先要确认,是M型号的,M就是mobilephone的缩写。还有其他的型号比如F,是全功能版的,也支持安卓手机。但是有的客户买了手机版的,但又加了其他的拓展

LOTO2018的博客 1728

Android之模拟信号示波器

原文链接(http://blog.csdn.net/hellogv/article/details/6032046) 上次简单地介绍了AudioRecord和AudioTrack的使用,这次就结合SurfaceView实现一个Android版的手机模拟信号示波器(PS:以前也讲过J2ME版的手机示波器)。最近物联网炒得很火,作为手机软件开发者,如何在不修改手机硬件电路的前提下实现与第三方

R0CK Y0U的博客 1441

创意小发明:超牛的Android手机加蓝牙扩展电路等于示波器 图纸、程序、安卓apk安装包

Android手机加蓝牙扩展电路等于示波器 Android系统的手机是智能手机家族里面的新宠,而且大有成为龙头老大之势。   开发人员纷纷投身Android,开发了很多精彩的应用。   下面就介绍一个比较新奇的应用。它利用一块dsPIC电路采集信号,处理后通过蓝牙发送给Android系统上的程序,将手机变身为简易示波器。      实物图    电路原理图 实际效果图 最后,如果有什么意见或者...

从零开始学单片机的博客 1757

Android语音信号波形显示

简单地介绍了AudioRecord和AudioTrack的使用,这次就结合SurfaceView实现一个Android版的手机模拟信号示波器(PS:以前也讲过J2ME版的手机示波器)。最近物联网炒得很火,作为手机软件开发者,如何在不修改手机硬件电路的前提下实现与第三方传感器结合呢?麦克风就是一个很好的ADC接口,通过麦克风与第三方传感器结合,再在软件里对模拟信号做相应的处理,就可以提供更丰富的传感...

weixin_33901926的博客 664

安卓手机用蓝牙示波器:实时监测与分析的利器

安卓手机用蓝牙示波器:实时监测与分析的利器 去发现同类优质开源项目:https://gitcode.com/ 项目核心功能/场景 安卓手机用蓝牙示波器实现波形数据实时监测与分析。 项目介绍 在科技飞速发展的今天,便捷的测试工具成为工程师们的迫切需求。安卓手机用蓝牙示波器,一套开源的解决方案,由国外研发团队精心打造。它包括硬件接收器、蓝牙数据传输以及手机端显示程序,为工程师们提供了一个实时监测与分...

gitblog_06789的博客 792

Android手机变身蓝牙无线示波器的完整实战项目

现代电子测量技术正朝着便携化、智能化方向快速发展,将Android手机与外部硬件结合构建低成本、高灵活性的蓝牙无线示波器,已成为嵌入式开发与移动应用融合的重要实践方向。本章从整体系统视角出发,深入剖析蓝牙无线示波器的核心构成与工作原理,明确其“感知—传输—处理—显示”四位一体的技术链条。系统由前端模拟信号采集模块、ADC模数转换电路、蓝牙串行传输单元(SPP/UART)、Android终端的数据接收服务以及实时波形渲染界面五大功能块组成。为便于手机端解析,需制定结构化帧协议。

weixin_42581846的博客 1270

android蓝牙示波器,Android-Bluetoot

Android手机变成蓝牙无线示波器/Android/AndroidBluetoothOscilloscope.apk将Android手机变成蓝牙无线示波器/Android/src/org/projectproto/yuscope/BluetoothOscilloscope.java将Android手机变成蓝牙无线示波器/Android/src/org/projectproto/yuscope/...

weixin_29587015的博客 1370

SurfaceView实现示波器效果

前言 SurfaceView内嵌在Activity的视图树里提供一块用于绘制的表层。提供它的主要目的之一就是方便其他线程更新界面,对于UI有大量用户操作需要不断更新界面的需求提供了方便。Android中的自定义View也支持自定义绘制,然而View只支持在UI线程中更新界面,如果需要像游戏那样做大量的运算会导致界面卡顿。SurfaceView就不同了,它允许用户在非UI线程中更新界面,同时天然的

xingzhong128的博客 805

基于STM32单片机和Android的便携式数字示波器设计

本文设计了一种基于STM32和Android平台的便携式数字示波器系统。论文首先分析了数字示波器的原理和技术指标,比较了数字与模拟示波器的差异。系统采用STM32作为主控制器,通过高速A/D转换和程控放大电路实现信号采集,采用蓝牙无线传输方式将数据发送至Android终端显示。硬件设计包括信号调理、A/D转换、频率测量等电路模块;软件部分实现了波形处理算法和Android端蓝牙通信及波形绘制功能。系统具有低成本、便携性强等特点,充分利用Android设备的显示和交互优势,实现了5MHz以下信号的测量与显示功

毕业作品网站 3606

安卓手机变身简易示波器:蓝牙模块+调理电路+开源APP全套方案

用普通安卓手机搭配HC-05或HC-06这类常见蓝牙模块,加上简单的信号调理电路(可焊在洞洞板或通用PCB上),就能实现基础示波功能。资源包里包含已编译好的APK安装文件(AndroidBluetoothOscilloscope.apk),直接装到手机就能用;还有完整的Java源码(在src目录),方便修改界面、调整通信协议或增加新功能;dsPIC主控的固件代码打包在dsPIC.rar中,负责模拟信号采集与串口蓝牙转发;电路图以JPG形式提供(Android手机加蓝牙改装的示波器电路图.jpg),含手绘版和

uber9的博客 282

安卓手机用蓝牙示波器(含程序和硬件原理图)

安卓手机用蓝牙示波器(含程序和硬件原理图) 去发现同类优质开源项目:https://gitcode.com/ 简介 本资源是一套开源的安卓手机蓝牙示波器解决方案,由国外研发团队开发。该方案包括硬件接收器、蓝牙数据传输以及手机端显示程序。用户可以通过该方案,将采集到的波形数据显示在安卓手机上,方便进行实时监测与分析。 功能特点 硬件接收器小巧便携,易于连接测量对象 通过蓝牙传输数据,实现手机端波形...

gitblog_06760的博客 468

Android版的手机模拟信号示波器

本文来自http://blog.csdn.net/hellogv/ ,引用必须注明出处!        上次简单地介绍了AudioRecord和AudioTrack的使用,这次就结合SurfaceView实现一个Android版的手机模拟信号示波器(PS:以前也讲过J2ME版的手机示波器)。最近物联网炒得很火,作为手机软件开发者,如何在不修改手机硬件电路的前提下实现与第三方传感器结合呢?麦克

mydots的专栏 4489

android+模拟示波器,模拟示波器

模拟示波器,采用的是模拟电路(示波管,其基础是电子枪)电子枪向屏幕发射电子,发射的电子经聚焦形成电子束,并打到屏幕上,屏幕的内表面涂有荧光物质,这样电子束打中的点就会发出光来。中文名模拟示波器外文名Analog oscilloscope原理电子束偏转用途测量信号幅度模拟示波器简介如何校正模拟示波器示波器与其它仪器一样(如万用表等),在使用之前都必需要先对其进行校正。而所谓对示波器的...

weixin_26913055的博客 1099
上一篇: RecyclerView的基本使用
下一篇: 简单的入门Android开发
LayneYao
博客等级 码龄10年 449粉丝 130原创
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值