OpenGL和pcDuino搭建數字示波器

看到大神們用Arduino、AVR作示波器,感受很好玩,手頭的pcDuino能不能作呢?一不作二不休,如今咱們就本身用pcDuino作一個。html

硬件清單:
pcDuino一塊
杜邦線若干
軟件環境:
一、pcDuino板載ubuntu
二、GCC 4.6
四、OpenGL:qt library自帶
五、Arduino SDK(c_enviroment): https://github.com/pcduino/c_enviroment
 
照例先來捋一下思路,因爲手頭沒有LCD模塊,只能用顯示器來充當示波器的屏幕了(27寸的示波器,哇咔咔~)。由於涉及到繪圖,這裏我使用OpenGL做爲繪圖工具,雖然有點炮打蚊子的感受,可是。。。還有什麼比OpenGL更好的跨平臺圖形庫呢?同時逼格也獲得提高,何了樂而不爲。嘿嘿~
實現原理很簡單,經過pcDuino的analogRead函數讀取信號源的電壓變化,再用OpenGL構建一個座標系,X軸表明時間,Y軸表明電壓,持續繪製電壓隨時間的變化曲線,就獲得咱們須要的波形圖像了。
QT和OpenGL的環境搭建請參照這個帖子,這裏再也不贅述: http://www.oschina.net/question/1174645_121352
下面來看關鍵的GLWidget類代碼,完整的QT項目源碼稍後奉上,或經過郵件和微信與我聯繫索取:)。 
#include "OpenGLwidget.h"
#include <QTimer>
#include <QKeyEvent>
#include <math.h>
#include <iostream>
#include <GL/glu.h>
#include <Arduino.h>
#include <Serial.h>
#include <wiring_private.h>
 
//出於性能考慮宏定義一些必要的常量計算
//step定義opengl的x軸步長,即把x軸的-1到1均分紅窗口的寬度(像素)
#define STEP 2/800.0
//units定義了窗口的x軸有800個點
#define UNITS 800
//pcduino的12bits ADC範圍是0~4095,正負各4095
#define ANALOGVALUE 4095*2
 
//定義opengl的頂點二維數組,800個點,每一個點由兩個float組成
GLfloat ver[UNITS][2];
//定義了x軸的起步值,-1.0即屏幕的最左邊
GLfloat xstep = -1.0;
 
//openglwidget的構造器,設置了窗口大小、窗口標題和更新opengl畫布的signal
OpenGLWidget::OpenGLWidget( QWidget* parent)
    : QGLWidget(parent){
    setGeometry( 0, 30, 800, 600 );
    setWindowTitle("Joker's OpenGL Framework");
    t = new QTimer(this);
    connect(t, SIGNAL(timeout()), this, SLOT(updateGL()));
    t->start(0);
}
 
OpenGLWidget::~OpenGLWidget(){
 
}
 
//opengl的初始化函數
void OpenGLWidget::initializeGL(){
    glShadeModel( GL_SMOOTH );
    //設置顏色清空顏色,參數依次爲RGBA,這裏是一個我以爲比較帥氣的灰色:)
    glClearColor( 0.3, 0.3, 0.3, 1.0 );
    glClearDepth( 1.0 );
    //開啓深度測試
    glEnable( GL_DEPTH_TEST );
    glDepthFunc( GL_LEQUAL );
    glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST );
    //開啓opengl的反鋸齒
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glEnable(GL_BLEND);
    glEnable(GL_POINT_SMOOTH);
    glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);
    glEnable(GL_LINE_SMOOTH);
    glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
    glEnable(GL_POLYGON_SMOOTH);
    glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);
 
}
 
//opengl的繪製函數,調用一次繪製一幀畫面
void OpenGLWidget::paintGL(){
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
     glLoadIdentity();
     //清空顏色緩衝區
     glClear(GL_COLOR_BUFFER_BIT);
     //定義視點、原點和視角俯仰,因爲這個例子只是2d繪圖,能夠忽略
     gluLookAt (0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
     //繪製兩條直線表明x和y座標軸
     glBegin(GL_LINES);
     glColor3f(0.5,0.5,0.5);
     //這兩個點能夠畫x軸
     glVertex2f(-1.0f, 0.0f);
     glVertex2f(1.0f, 0.0f); 
     //這兩個點能夠畫y軸
     glVertex2f(0.0f, -1.0f);
     glVertex2f(0.0f, 1.0f); 
     glEnd();
     //繪製波形,用opengl的一個line strip定義,line strip其實就是一組點連成的線
     glBegin(GL_LINE_STRIP);
     //定義line strip的顏色,這裏也是我認爲比較帥氣的綠色,哈哈
     glColor3f(0.0,1.0,0.0);
     //這個循環會經過analogRead取得電壓數值,並把這個電壓值轉換成波形的y值,寫入頂點數組
     for(int i=0;i<UNITS;i++){
         *(ver[i]) = xstep+=STEP;
         *(ver[i]+1) = analogRead(5)/ANALOGVALUE;
         glVertex2fv(ver[i]);
     }
     //std::cout<<analogRead(5)/4095.0*2<<std::endl;
     glEnd();
     //把頂點數據壓入opengl的渲染管道,開始繪圖
     glFlush();
}
//窗口大小變化的回調函數
void OpenGLWidget::resizeGL( int width, int height ){
    //std::cout<<width<<"*"<<height<<std::endl;
    if ( height == 0 )
    {
        height = 1;
    }
    glViewport(0,0,(GLint)width,(GLint)height );
    glMatrixMode( GL_PROJECTION );
    glLoadIdentity();
    //gluPerspective( 45.0, (GLfloat)width/(GLfloat)height, 0.1, 100.0 );
    glMatrixMode( GL_MODELVIEW );
    glLoadIdentity();
}
//鍵盤按鍵的回調函數,按esc退出
void OpenGLWidget::keyPressEvent(QKeyEvent *e){
    switch ( e->key() ){
      case Qt::Key_Escape:
        close();
    }
}

編譯運行,因爲手頭沒有信號發生器,我就拿pcduino的PWM信號簡單測試一下:ios

PWM輸出的200Hz的方波,彷佛很工整
opengl joker pcduino
 
 
咱們加快頻率到800,縮短佔空比
opengl joker pcduino
 
實測個人寫法只能支持2kHz左右的帶寬,求大神優化:)
看膩了方波工整的信號,我索性輸入一個音頻信號,你們猜猜是哪首歌?猜對有獎:) 
opengl

 

 做者博客原文:http://blog.jokerjewel.com/articles/2013/12/21/1387628153495.htmlgit

相關文章
相關標籤/搜索