123Views5Replies

Author Options:

ARDUINO OSCILLOSCOPE? Answered

Hey there, I have been working on a recent project to build an Arduino Oscilloscope interfaced with a 4X4 keypad membrane with Nokia 5110 LCD display.I have successful individual code fragments/portions which
1)Generate waves interfaced with the keyboard 
2)Display the same on the Nokia LCD 5110

i am using the Arduino Due and the 1st part of my code generates waves on DAC1 with the code as follows:-




#include "Waveforms.h"
#include <Keypad.h>
#include <LiquidCrystal.h>




//Set the desired duty cycle in percentage

double dc,t,a,d;
long d_milli,d_micro,a_milli,a_micro,m,n;
int stage =0;


int sample_delay1;
LiquidCrystal lcd(A2, A3, A4, A5, A6, A7);
float sample_delay;
String num1,num2;
int wave1;
String wave_name;
double duty_cycle,k;
const byte ROWS = 4; //four rows
const byte COLS = 4; //four columns
//define the cymbols on the buttons of the keypads
char hexaKeys[ROWS][COLS] = {
  {'1','2','3','A'},
  {'4','5','6','B'},
  {'7','8','9','C'},
  {'.','0','#','D'}
};
byte rowPins[ROWS] = {23,25,27,29}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {31,33,35,37}; //connect to the column pinouts of the keypad
int i = 0;
int sample;
//initialize an instance of class NewKeypad
Keypad customKeypad = Keypad( makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS);
boolean in_setup = true;
void setup()
{
  Serial.begin(9600);
  analogWriteResolution(12);  // set the analog output resolution to 12 bit (4096 levels)
  analogReadResolution(12);
  lcd.begin(20,4);
  char key = customKeypad.getKey();
  lcd.setCursor(0, 0);
  lcd.print("choose wave: ");
  lcd.setCursor(0, 1);
  lcd.print("A=Sine");
  lcd.setCursor(8, 1);
  lcd.print("B=Triangular");
  lcd.setCursor(0, 2);
  lcd.print("C=Sawtooth");
  lcd.setCursor(11, 2);
  lcd.print("D=Square");

  while( true)
  {
        char key = customKeypad.getKey();
        if(stage == 0)
        {
              Serial.println("in stage 0");
              if(key == 'A' )
              {
                wave1 = 0;
                lcd.clear();
                lcd.setCursor(0,0);
                lcd.print(" Sine?      ");
                wave_name ="Sinusoidal";
                Serial.println(wave_name);

              }
              else if(key == 'B')
              {
                wave1 = 1;
                lcd.clear();
                lcd.setCursor(0,0);
                lcd.print("Triangular?");
                wave_name ="Triangular";
                Serial.println(wave_name);
              }
              else if(key == 'C')
              {
                wave1 = 2;
                lcd.clear();
                lcd.setCursor(0,0);
                lcd.print("Sawtooth?  ");
                wave_name ="Sawtooth";
                Serial.println(wave_name);
              }
              else if(key == 'D')
              {
                wave1 = 3;
                lcd.clear();
                lcd.setCursor(0,0);
                lcd.print("Square?    ");
                wave_name ="Square";
                Serial.println(wave_name);
               
              }
              else if(key == '#')
              {
                stage++;
                //lcd.clear();
                lcd.setCursor(0,1);
                lcd.print("Frequency=");
                Serial.println("Frequency=");
              }
        }
       else if(stage == 1)
        {
              if(key != NO_KEY &&(key=='1'||key=='2'||key=='3'||key=='4'||key=='5'||key=='6'||key=='7'||key=='8'||key=='9'||key=='0'))
              {
                num1 = num1 + key;
                //int numLength = num1.length();
                //to adjust one whitespace for operator
                lcd.setCursor(10,1);
                lcd.print(num1);
              }
             
              else if(key == '#')
              {
                    k = num1.toInt();
                    Serial.print(k);
                     
                  
                   
                          int sample_delay_int = 1000000/(k*120);
                          float sample_delay_float = 1000000/(k*120);
                          float difference= sample_delay_float-sample_delay_int;
                          sample_delay1 = sample_delay_int - 6;
                          if(difference > 0.5)
                          {
                            sample_delay1++;
                          }
                         
                         
                          Serial.println(sample_delay1);
                          lcd.clear();
                          lcd.print(wave_name);
                          lcd.setCursor(0,1);
                          lcd.print("Frequency=");
                          lcd.print(num1);
                          lcd.print(" Hz");              
                          break;
                   
                  }    
              }
             
      
       

       
       
   }
     
}


void loop()
  {
  analogWrite(DAC1, waveformsTable[wave1][i] ); 
  i++;
  if(i == maxSamplesNum)  // Reset the counter to repeat the wave
    i = 0;
  else


delayMicroseconds(sample_delay1);
           
      }



Next, I input these waves from DAC1 into analog input A0 to display on the LCD with code as below:-




#include <Adafruit_GFX.h>
#include <Adafruit_PCD8544.h>
#include <SPI.h>

#define DISPLAY_WIDTH 84
#define DISPLAY_HEIGHT 48

#define ARDUINO_PRECISION 1023.0
Adafruit_PCD8544 display = Adafruit_PCD8544(8,9,10,12,11);


//Analog Pins
int channelAI = A0;      // probe

#define DELAY_POTENTIMETER //disabled it I don't have it connected
#ifdef DELAY_POTENTIMETER
int delayAI = A1;       // delay potentiometer
#endif

float delayVariable = 0;
float scale = 0;
int xCounter = 0;
int yPosition = 0;
int readings[DISPLAY_WIDTH+1];
int counter = 0;

unsigned long drawtime = 0;
unsigned long lastdraw = 0;
int frames = 0;

void setup(void)
{
  display.begin();
  display.setContrast(30);// you might have a slightly different display so it might not be the optimal value for you
  display.clearDisplay();
}

void loop()

  #ifdef DELAY_POTENTIMETER
  delayVariable = analogRead(delayAI);
  delayVariable = (delayVariable/100);
  #endif
  scale = (float)(DISPLAY_HEIGHT-1)/ARDUINO_PRECISION;
 
  //record readings
  for(xCounter = 0; xCounter <= DISPLAY_WIDTH; xCounter++)
  {                                
    yPosition = analogRead(channelAI);
    readings[xCounter] = (yPosition*scale);
    #ifdef DELAY_POTENTIMETER
    delay (delayVariable);
    #endif
  }
 
  display.clearDisplay();

  //Draw Voltage Ref Lines
  display.drawLine( 10, 0, 10, DISPLAY_HEIGHT-1, BLACK);
  display.drawLine( 5, (DISPLAY_HEIGHT-1)-(.2 *ARDUINO_PRECISION * scale), 10, (DISPLAY_HEIGHT-1)-(.2 *ARDUINO_PRECISION * scale), BLACK);
  display.drawLine( 0, (DISPLAY_HEIGHT-1)-(.4 *ARDUINO_PRECISION * scale), 10, (DISPLAY_HEIGHT-1)-(.4 *ARDUINO_PRECISION * scale), BLACK);
  display.drawLine( 5, (DISPLAY_HEIGHT-1)-(.6 *ARDUINO_PRECISION * scale), 10, (DISPLAY_HEIGHT-1)-(.6 *ARDUINO_PRECISION * scale), BLACK);
  display.drawLine( 0, (DISPLAY_HEIGHT-1)-(.8 *ARDUINO_PRECISION * scale), 10, (DISPLAY_HEIGHT-1)-(.8 *ARDUINO_PRECISION * scale), BLACK);
  //display.drawLine( 5, (DISPLAY_HEIGHT-1)-(.84 *ARDUINO_PRECISION * scale), 10, (DISPLAY_HEIGHT-1)-(.84 *ARDUINO_PRECISION * scale), BLACK);
 
  //Draw Voltage Ref Numbers
  display.setCursor(0,((DISPLAY_HEIGHT-1)-(.2 *ARDUINO_PRECISION * scale))-3);
  display.print((int)(5.0*0.2));
  display.setCursor(0,((DISPLAY_HEIGHT-1)-(.4 *ARDUINO_PRECISION * scale))-3);
  display.print((int)(5.0*0.4));
  display.setCursor(0,((DISPLAY_HEIGHT-1)-(.6 *ARDUINO_PRECISION * scale))-3);
  display.print((int)(5.0*0.6));
  display.setCursor(0,((DISPLAY_HEIGHT-1)-(.8 *ARDUINO_PRECISION * scale))-3);
  display.print((int)(5.0*0.8));
 
  for(xCounter = 0; xCounter <= DISPLAY_WIDTH; xCounter++)
  {
    display.drawPixel(xCounter, (DISPLAY_HEIGHT-1)-readings[xCounter], BLACK);
    if(xCounter>1){
      display.drawLine(xCounter-1, (DISPLAY_HEIGHT-1)-readings[xCounter-1], xCounter, (DISPLAY_HEIGHT-1)-readings[xCounter], BLACK);
    }
  }
  //Draw FPS
  display.setCursor((DISPLAY_WIDTH-1)-11,0);
  display.print(frames);
 
  //Draw Voltage
  display.setCursor(((DISPLAY_WIDTH-1)/2),0);
  display.print(analogRead(channelAI)/ARDUINO_PRECISION*5.0);
 
  display.display();
 
  //Calculate FPS
  drawtime = micros();
  frames=1000000/*a second*//(drawtime-lastdraw);
  lastdraw = drawtime;
}



Now the problem arises when i try doing the 2 things on d same arduino due board.
I got perfect results when i used arduino due and arduino uno simultaneously but have not been able to generate waves on the LCD using the same board.
Is it possible to do the same. Can some1 help me incorporate the 2 programs into 1..Thanxx





Discussions

0
None
-max-

2 years ago

If you look at teardowns of real oscilloscopes, You might see that they have all sorts of high end hardware each doing a completely separate operation. Unlike a basic desktop computer, there is not really any central processor, The architecture is completely different. You may find a ARM processor doing the UI stuff and doing some analog switching and MUX stuff for different voltage settings and things, and a LCD driver chip to actually display and update the screen, but the heart of it would be a VERY VERY VERY fast DAC, coupled with VERY VERY VERY fast memory, generally about 100MB or less, and some VERY VERY VERY ASIC or FPGA to control the DAC and store that data right into the memory. From there it can be more slowly digested and processed by the still very beefy ARM processor (along the lines of what powers the raspberry pi platform.).

Trying to do this stuff with basic arduino is going to yield really crap results, you might be lucky to get 0.5 seconds per division, not enough for anything useful. You will probably need to program the arduino in assembly directly to interface the LCD and DAC hardware as directly and quickly as possible.

Try to first get a "sample," where the arduino enters a loop where it is doing nothing more than reading the DAC output and storing that data in an array or something, then have another loop with your code that converts each sample of data into a specified pixel value and write that to the screen. That will be a much slower process, so it will take it's time. Then once that is done and the data is displayed and stored into the LCD's buffer, then the arduino can get another sample.

0
None
-max--max-

Answer 2 years ago

Making something that logs voltage over time over much larger spans of time would be MUCH easier. While interning at NASA I did create a device that gathered information from all sorts of random sensors (temperature, pressure, light, humidity, etc.) and store it on an SD card, where I could then inport the CSV files into excell to see graphs of the data.