Vizic Technologies
Published

SmartGPU2 - Arduino Oscilloscope

Using a smart GPU2, a smart SHIELD and Arduino we created a simple touchscreen oscilloscope!

BeginnerShowcase (no instructions)1 hour32,451
SmartGPU2 - Arduino Oscilloscope

Things used in this project

Hardware components

Arduino UNO
Arduino UNO
×1
SmartGPU2 - 4.3" LCD480x272
×1
SmartSHIELD - Easily connect any Vizic Technologies tool to arduino
×1

Story

Read more

Code

SmartGPU2 Arduino oscilloscope

C/C++
A simple yet functional arduino oscilloscope at a very affordable price!
/*********************************************************
VIZIC TECHNOLOGIES. COPYRIGHT 2014.
THE DATASHEETS, SOFTWARE AND LIBRARIES ARE PROVIDED "AS IS." 
VIZIC EXPRESSLY DISCLAIM ANY WARRANTY OF ANY KIND, WHETHER 
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO, THE IMPLIED 
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
OR NONINFRINGEMENT. IN NO EVENT SHALL VIZIC BE LIABLE FOR 
ANY INCIDENTAL, SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES, 
LOST PROFITS OR LOST DATA, HARM TO YOUR EQUIPMENT, COST OF 
PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, 
ANY CLAIMS BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO 
ANY DEFENCE THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION,
OR OTHER SIMILAR COSTS.
*********************************************************/

/********************************************************
 IMPORTANT : This Example is created for the Arduino 1.0 Software IDE
 -------------MINIMUM INPUT VOLTAGE IS 0 VOLTS--------------------
--------------MAX INPUT VOLTAGE IS 3.3 VOLTS----------------------
********************************************************/

#include <SMARTGPU2.h>                     //include the SMARTGPU2 library!

SMARTGPU2 lcd;                             //create our object called LCD

#define GRAY 0x528A                        //GRAY colour of the grid

//OSCILLOSCOPE DEFINES
#define WIN_HORIZONTAL_START 10            //start pixel for the horizontal window
#define WIN_VERTICAL_START   25            //start pixel for the vertical window
#define WIN_HORIZONTAL_END  LCD_WIDTH-10   //size in pixels of the vertical window
#define WIN_VERTICAL_END    LCD_HEIGHT-25  //size in pixels of the vertical window

#define PROBE_INPUT         A0             //select the input pin for the oscilloscope - A0 analog pin
#define MAX_INPUT_VOLTAGE   3.3            //maximum input voltage to the PROBE_INPUT pin
#define MAX_SAMPLES         WIN_HORIZONTAL_END - WIN_HORIZONTAL_START  //must be the substraction of those 2 numbers

#define NUMBEROFVOLTSVALUES       6
#define NUMBEROFMILLISECVALUES    6
const float         voltsPerDivValues[NUMBEROFVOLTSVALUES]           = {0.1, 0.25, 0.5, 1.0, 1.5, 2.0};
const unsigned long millisecondsPerDivValues[NUMBEROFMILLISECVALUES] = {10, 50, 100, 250, 500, 1000};
unsigned char       voltsPerDivPointer=3, millisecondsPerDivPointer=3; //default start values 1voltPerDiv and 250mSecPerDiv

unsigned int sampleBuffer[MAX_SAMPLES];                                //array to store ADC probe samples

/*********************************************************/
void initSampleBuffer(void){
  unsigned int i;
  for(i=0; i < MAX_SAMPLES; i++) sampleBuffer[i] = WIN_VERTICAL_END;
  sampleBuffer[0]= getScaledSample();  //get first sample
}

/*********************************************************/
void showIntro(void){
  int aux=5,xs,ys,i, time=50;

  lcd.setTextSize(FONT4);
  lcd.string(2,2,MAX_X_LANDSCAPE,MAX_Y_LANDSCAPE,"SmartGPU 2 : Simple Oscilloscope", 0);
  lcd.setTextSize(FONT2);
  lcd.string(20,MAX_Y_LANDSCAPE-35,MAX_X_LANDSCAPE,MAX_Y_LANDSCAPE,"Vizic Technologies 2014(c)", 0);
  while(time--){
    //draw next circle
    xs=(sin(((aux*24)*3.14)/180)) * 40;
    ys=(cos(((aux*24)*3.14)/180)) * 40;
    lcd.drawCircle((LCD_WIDTH/2)+xs,(LCD_HEIGHT/2)-ys,2,BLUE,FILL); 
    //erase previous circle
    xs=(sin((((aux-5)*24)*3.14)/180)) * 40;
    ys=(cos((((aux-5)*24)*3.14)/180)) * 40;
    lcd.drawCircle((LCD_WIDTH/2)+xs,(LCD_HEIGHT/2)-ys,3,BLACK,FILL);    
    //increase vaiable aux
    if(aux++ > 13) aux=0;        
    delay(100);
  }
  lcd.erase();               //erase screen before exit 
}

/*********************************************************/
void wait_milliseconds_and_process_touch(void){ //wait the millisecondsPerDivValues[] parameter and process touch in the while
  POINT point;
  
  TCNT1=0;               //reset timer counter - timer counts one step every 4 microseconds 
  while(TCNT1 < ((millisecondsPerDivValues[millisecondsPerDivPointer]*(1000/4)) / ((MAX_SAMPLES)/5))){    //wait to reach scaled time
    if((lcd.touchScreen(&point)==VALID) && (point.y > WIN_VERTICAL_END)){    //if a touch is received and if touch on volts per div or in mSec per div strings
      if(point.x < (LCD_WIDTH/2)){        //if touch on volts per div(left half of the screen)
        if(++voltsPerDivPointer >= NUMBEROFVOLTSVALUES) voltsPerDivPointer = 0;
      }else{                              //touch on mSec per div(right half of the screen)
        if(++millisecondsPerDivPointer >= NUMBEROFMILLISECVALUES) millisecondsPerDivPointer = 0;
      }
      lcd.drawRectangle(0,MAX_Y_LANDSCAPE-20,MAX_X_LANDSCAPE,MAX_Y_LANDSCAPE,GREEN,FILL);  //erase previous strings
      lcd.string(20,MAX_Y_LANDSCAPE-20,MAX_X_LANDSCAPE,MAX_Y_LANDSCAPE,"Volts/Div:",0);
      lcd.printNumber(110,MAX_Y_LANDSCAPE-20,voltsPerDivValues[voltsPerDivPointer]);
      lcd.string(MAX_X_LANDSCAPE-140,MAX_Y_LANDSCAPE-20,MAX_X_LANDSCAPE,MAX_Y_LANDSCAPE,"mSec/Div:",0);
      lcd.printNumber(MAX_X_LANDSCAPE-50,MAX_Y_LANDSCAPE-20,millisecondsPerDivValues[millisecondsPerDivPointer]);   
      delay(250);
    }   
  }
}

/*********************************************************/
unsigned int getScaledSample(void){                        //get a sample and return a value scaled into window vertical size
  float value;
  value = analogRead(PROBE_INPUT);                         //Take a sample from the PROBE
  value = value * MAX_INPUT_VOLTAGE;                       //scale to max input voltage
  value = value / 1023;                                    //divide by the max input value of ADC
  value = value * ((WIN_VERTICAL_END - WIN_VERTICAL_START) / 5); //multiply value by the grid division value in pixels
  value = value / voltsPerDivValues[voltsPerDivPointer];   //finally divide the value by the volts per division parameter
  if(value > (WIN_VERTICAL_END - WIN_VERTICAL_START)) return WIN_VERTICAL_START;
  return WIN_VERTICAL_END - value;                         //return window vertical end substracting the scaled value
}

/*********************************************************/
void drawGrid(){
 unsigned int i;
 for(i=WIN_HORIZONTAL_START; i<=WIN_HORIZONTAL_END; i+=(WIN_HORIZONTAL_END - WIN_HORIZONTAL_START)/5)
   lcd.drawLine(i,WIN_VERTICAL_START,i,WIN_VERTICAL_END,GRAY);
 for(i=WIN_VERTICAL_START; i<=WIN_VERTICAL_END; i+=(WIN_VERTICAL_END - WIN_VERTICAL_START)/5)
   lcd.drawLine(WIN_HORIZONTAL_START,i,WIN_HORIZONTAL_END,i,GRAY);
}

/*********************************************************/
void updateScreen(void){
  static int drawPointer= 0;
  sampleBuffer[drawPointer+1]= getScaledSample();                                              //store a scaled sample
  lcd.drawLine(drawPointer+WIN_HORIZONTAL_START, sampleBuffer[drawPointer], drawPointer+WIN_HORIZONTAL_START+1, sampleBuffer[drawPointer+1], YELLOW);        //draw fresh sample
  drawPointer++;
  if((drawPointer+2) >= MAX_SAMPLES){
    drawGrid();                                                                              //re-draw Grid
    drawPointer = 0;  
  }
  lcd.drawLine(drawPointer+WIN_HORIZONTAL_START+1, sampleBuffer[drawPointer+1], drawPointer+WIN_HORIZONTAL_START+2, sampleBuffer[drawPointer+2], BLACK);         //erase old sample
}

/*********************************************************/
void drawInterface(void){
  lcd.drawGradientRect(0, 0, MAX_X_LANDSCAPE, MAX_Y_LANDSCAPE, BLUE, GREEN, VERTICAL);                              //draw background
  lcd.drawRectangle(WIN_HORIZONTAL_START, WIN_VERTICAL_START, WIN_HORIZONTAL_END, WIN_VERTICAL_END, BLACK, FILL);   //draw plotting area
  drawGrid();
  lcd.setTextSize(FONT1);
  lcd.string(2,2,MAX_X_LANDSCAPE,30,"SmartGPU 2 - Simple Oscilloscope", 0);
  lcd.setTextColour(BLACK);
  lcd.drawRectangle(0,MAX_Y_LANDSCAPE-20,MAX_X_LANDSCAPE,MAX_Y_LANDSCAPE,GREEN,FILL);
  lcd.string(20,MAX_Y_LANDSCAPE-20,MAX_X_LANDSCAPE,MAX_Y_LANDSCAPE,"Volts/Div:",0);
  lcd.printNumber(110,MAX_Y_LANDSCAPE-20,voltsPerDivValues[voltsPerDivPointer]);
  lcd.string(MAX_X_LANDSCAPE-140,MAX_Y_LANDSCAPE-20,MAX_X_LANDSCAPE,MAX_Y_LANDSCAPE,"mSec/Div:",0);
  lcd.printNumber(MAX_X_LANDSCAPE-50,MAX_Y_LANDSCAPE-20,millisecondsPerDivValues[millisecondsPerDivPointer]);     
}

/*********************************************************/
/*********************************************************/
void setup() { //initial setup
  //Those two functions must always be called for SMARTGPU2 support
  lcd.init();  //configure the serial and pinout of arduino board for SMARTGPU2 support
  lcd.start(); //initialize the SMARTGPU2 processor
  
  //oscilloscope configurations
  //set analog reference as EXTERNAL to avoid damage to arduino boards when using smartGPU2 as shield, this is already done in the smartGPU2 library
  //analogReference(EXTERNAL); //which AREF is connected to 3.3V of SmartGPU2 board
  pinMode(PROBE_INPUT, INPUT);
  
  // Timer/Counter 1 initialization
  // Clock source: System Clock
  // Clock value: 250.000 kHz
  // Mode: Normal top=0xFFFF
  TCCR1A=0x00;
  TCCR1B=0x03;  //timer will increase count one step every 4 microseconds
}

/*********************************************************/
/*********************************************************/
/*********************************************************/
/*********************************************************/
void loop() { //main loop draw random colour, size and fill Ellipses    
  lcd.baudChange(BAUD7); //for fast drawing we need a big baudRate
  
  showIntro();           //a Small intro  
  drawInterface();       //draws all the oscilloscope body and interface
  initSampleBuffer();    //initialize the sample Buffer to lowest value possible
   
  while(1){//forever
    wait_milliseconds_and_process_touch();       
    updateScreen(); 
  }
}

Credits

Vizic Technologies

Vizic Technologies

2 projects • 22 followers
Vizic Technologies is an embedded electronics design company that designs, and manufactures high end, quality and Intellectual property processors and modules.

Comments