0

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

I tried playing around with my setup() and loop() and have reached a point where my program does everything ,ie takes keypad input ,displays options on the LCD ,takes in freq and generates a splashscreen but the only thing i'm missing out on is d wave display on the LCD (I'm able to see the selected wave on the DSO) ..So i guess i'm pretty close, and the edited code is as follows:-

#include "waveforms.h"
#include <Keypad.h>
#include <SPI.h>

#include <Adafruit_GFX.h>
#include <gfxfont.h>

#include <Adafruit_PCD8544.h>

 //Set the desired duty cycle in percentage
Adafruit_PCD8544 display = Adafruit_PCD8544(8, 9, 10, 12, 11);
double dc,t,a,d;
long d_milli,d_micro,a_milli,a_micro,m,n;
int stage =0;

int sample_delay1;
float sample_delay;
String num1,num2;
int wave1;
String wave_name;
double duty_cycle,k,Z;
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 t_sample;

#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;

#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;

//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);
  display.begin(20,4);

  char key = customKeypad.getKey();

  display.begin();
  display.display();
  display.setContrast(40);// you might have a slightly different display so it might not be the optimal value for you
  display.clearDisplay();

  display.setTextSize(1);
  display.setTextColor(BLACK);
  display.setCursor(0, 0);
  display.print("choose wave: ");
  display.display();
  display.setCursor(1, 8);
  display.print("A=Sine");
  display.display();
  display.setCursor(1,16);
  display.print("B=Triangular");
  display.display();
  display.setCursor(1,24);
  display.print("C=Sawtooth");
  display.display();
  display.setCursor(1,32);
  display.print("D=Square");
  display.display();

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

      }
      else if(key == 'B')
      {
        wave1 = 1;
        display.clearDisplay();
        display.setCursor(0,0);
        display.print("Triangular?");
        display.display();
        wave_name ="Triangular";
        Serial.println(wave_name);
      }
      else if(key == 'C')
      {
        wave1 = 2;
        display.clearDisplay();
        display.setCursor(0,0);
        display.print("Sawtooth?  ");
        display.display();
        wave_name ="Sawtooth";
        Serial.println(wave_name);
      }
      else if(key == 'D')
      {
        wave1 = 3;
        display.clearDisplay();
        display.setCursor(0,0);
        display.print("Square?    ");
        display.display();
        wave_name ="Square";
        Serial.println(wave_name);

      }
      else if(key == '#')
      {
       stage++;
       display.clearDisplay();
       display.setCursor(20, 8);
       display.println("Freq=");
       display.display();
       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
        display.setTextSize(1);
        display.setTextColor(BLACK);
        display.setCursor(48, 9);
        display.print(num1);
        display.display();
      }
      else if(key == '#')
      {
        stage++;
        k = num1.toInt();
        Serial.print(k);
        display.setTextSize(1);
        display.setTextColor(BLACK);
        display.display();
        display.setCursor(10, 1);

        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++;
        }

        display.display();
        Serial.println(sample_delay1);
        display.clearDisplay();
        display.print(wave_name);
        display.setCursor(1, 8);
        display.println("Freq=");
        display.print(num1);
        display.println(" Hz");
        break;
      }
    }
  }

  //record readings
  for(xCounter = 0; xCounter <= DISPLAY_WIDTH; xCounter++)
  {
    yPosition = analogRead(A0);
    readings[xCounter] = (yPosition*scale);
    #ifdef DELAY_POTENTIMETER
    delay (delayVariable);
    #endif
  }

  display.clearDisplay();

  #ifdef DELAY_POTENTIMETER
  delayVariable = analogRead(delayAI);
  display.display();
  delayVariable = (delayVariable/100);
  #endif
  scale = (float)(DISPLAY_HEIGHT-1)/ARDUINO_PRECISION;

  //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(A0)/ARDUINO_PRECISION*5.0);

  display.display();

  //Calculate FPS
  drawtime = micros();
  frames=1000000/(drawtime-lastdraw);
  lastdraw = drawtime;
  display.display();
}

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

  analogWrite(DAC0, waveformsTable[wave1][i] );
  i++;
  if(i == maxSamplesNum)  // Reset the counter to repeat the wave
    i = 0;
  else
    delayMicroseconds(sample_delay1);
}

Can some1 possibly tinker around with this ..It'll b a huge help!!

2
  • Can you reprogram your signal generator to work on timer interrupts, so the oscilloscope code (+ keypad handling) runs while being interrupted by the wave generation?
    – Mishony
    Commented Jun 29, 2016 at 17:15
  • Also, I believe you can slightly increase your FPS by moving the "static" part of the drawing in setup(), and greatly by not using the adafruit library - AFAIK it uses offscreen buffer on 5110 and redraws the entire screen. Instead you just write directly to the screen, one or 2 writes per column (one to erase the old samlple and one to draw the new one, unless they overlap - then it is one write) - just draw pixels (actually 8 pixels at once) for each column.
    – Mishony
    Commented Jun 29, 2016 at 17:17

1 Answer 1

0

You have two programs. One has a very complicated setup(), but a very quick loop(). The other has a very small setup(), but a very complicated loop(). And you want to merge the two programs?

That will be very, very difficult. Your first program loop() looks like this:

void loop() {
   analogWrite(...); // Very quick code
   i++;              // Very quick code
   if (..)           // Very quick code
      i = 0;         // Very quick code
   else              // ***BUG!!!*** This shoud not be here!
   delayMicroseconds(...); // Very specific timing delay
} // loop()

In other words, to produce the correct waveform it does very few instructions very quickly - and then waits a carefully calculated time.

Your other program's loop() does lots of things, and doesn't care about timing. The code is not time-sensitive at all - and writing to the display takes variable time anyway.

Your only choice is to set a timer to interrupt every sample_delay1 microseconds, and inside the timer interrupt handler do the analogWrite(...); call instead of having the loop() function do it. That is Advanced Arduino programming!

5
  • Thanx a lot @John Burger! I tried playing around with my setup() and loop() and have reached a point where my program does everything ,ie takes keypad input ,displays options on the LCD ,takes in freq and generates a splashscreen but the only thing i'm missing out on is d wave display on the LCD (I'm able to see the selected wave on the DSO) ..So i guess i'm pretty close, and the edited code is as follows:-
    – ranjana_1
    Commented Jun 30, 2016 at 6:07
  • I've included the edited code in my original question ..KIndly have a look,c if u can tinker around with the code! Thanx a lot
    – ranjana_1
    Commented Jun 30, 2016 at 6:51
  • The reason that you are not seeing the wave display is that you're not generating it in loop(). You do understand that setup() is performed once, and when that finishes loop() is called repeatedly. In your edited version you have drawn the wave display once in setup(). Your loop() only generates (now two) waveforms - it needs to also draw the wave, but that will disturb the timing of the waveforms. And now that you're generating two waveforms, why are you waiting sample_delay1 twice? You are also incrementing i twice. You've made it very complicated for yourself! Commented Jul 1, 2016 at 5:12
  • Yeah you're right!@John Burger! A possible solution to the problem dat i came across was parallel programming..I load 1st part of the code on arduino uno ,2nd part on the 'Due' and program them to run simultaneously.Bt is this feasible?? N do u have any idea of parallel programming possibly,coz i have absolutely no experience of it.
    – ranjana_1
    Commented Jul 1, 2016 at 10:32
  • There's no need to do the sort of "parallel programming" that you describe - unless you have the boards necessary, of course! Re-read my answer, paying particular attention to the final paragraph. You can do everything that you want with Timer Interrupts - but we can't give you a course on that from StackExchange! Read, read, read everything you can get your hands on... Commented Jul 1, 2016 at 10:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.