Weable Ghostbusters diplay prop- the Belt Gizmo

Hi folks. I created this project for my Ghostbusters costume, and I want to share it with others.
I used an Arduino Uno from Elegoo and a DFrobot LCD display shield.

It's an interactive display that prints timed readouts of fictional ghost readings to wear on the belt of a Ghostbusters costume. It has 5 different modes activated by the buttons on the display shield.

It's a pretty simple sketch, so maybe useful if you're doing a different kind of art piece but just want to change the text.

Scroll down for the newest version of the code.

/*
Arduino 2x16 LCD - SPENGLER G-METER
September 24, 2021
by Bruce Wright
Free use for fans.  Change whatever you want.  Share for free only.
*/


//at the top of the program, I'm setting up some variables.  A list of messages to print
//and some values I'll need deeper in teh program

//This is a string array.  It's a list of all the bottom line text that each mode prints.;
//There are 4 sets of 10 messages.  message 0-9 for the bottom button, 10-19 right, 20-29 top, 30-39 left;

char *myString1[] = {"  212-555-2368  ", "ghostbusters.com", " no job too big ", " no FEE too big ",
                     "?STrAnGe NoIsEs?", "??CoLd SpOtS?!??", "?FeAr or dREaD?!", " Ready2BelieveU ",
                     "WHO U GONNA CALL", " 24 HOURS CALL: ",
                     "EMF:     nominal", "EVP LvL:   quiet", "EVP LvL:   quiet", "EVP LvL:    BUMP",
                     "ECTO COUNT:  low", "ECTO COUNT:  low", "ECTO COUNT:  med", "  >>SCANNING<<  ",
                     " >>>SCANNING<<< ", ">>>>SCANNING<<<<",
                     "CYCLOTRON:    OK", "NUTRONA:    FULL", "IONIZATION:  85%", "SLIME CHARGE:3++",
                     "SLIME Lvl:RISING", "CONTAINMENT:  OK", "TWINKIE:     BIG", "MESONS:  NOMINAL",
                     "SLO-BLO:     OFF", "N-FILTER: VENTED",
                     "Apparition     2", "----DETECTING---", "Full Torso     5", "----DETECTING---",
                     "Free-Floating  6", "----DETECTING---", "Spectral mist  1", "UNKNOWN      UNK",
                     "NonCorporeal   3", "----DETECTING---"
                    };


//each mode allows you to change the speed setting.  That's the speed it prints at. Here we start at speed 2
//smaller numbers are faster.  I guess I should have called it myDelay instead!!!
int mySpeed =2;



// first cycling mode will be printing pke numbers.  So I turn that mode on with this variable
int numbers =1;


//in order to drive the LCD shield, you'll need to include the LiquidCrystal library
// THIS SHOULD ALREADY BE PART OF YOUR ARDUINO LIBRARIES 
// if not, go to Tools>ManageLibraries and search and install LiquidCrystal

#include <LiquidCrystal.h>
//LCD pin to Arduino
const int pin_RS = 8; 
const int pin_EN = 9; 
const int pin_d4 = 4; 
const int pin_d5 = 5; 
const int pin_d6 = 6; 
const int pin_d7 = 7; 
const int pin_BL = 10; 
LiquidCrystal lcd( pin_RS,  pin_EN,  pin_d4,  pin_d5,  pin_d6,  pin_d7);



//the void setup here runs ONCE on startup and then the rest of the program loops forever.
//first things I'm doing in this are just animating the boot up messages
//all these messages and the "boot up" process is just for fun.  the system is all booted up already!

void setup() {
 lcd.begin(16, 2);
 lcd.setCursor(0,0);
 lcd.print("              ");
  delay(1900);
 
 lcd.setCursor(0,0);
 lcd.print("  speng_v3.34b");
  delay(1900);
 
 lcd.setCursor(0,1);
 lcd.print("booting     wait");
  delay(500);

 lcd.setCursor(0,1);
 lcd.print("booting>");
 delay(500);
 lcd.setCursor(0,1);
 lcd.print("booting->");
 delay(500);
 lcd.setCursor(0,1);
 lcd.print("booting-->");
 delay(500);
 lcd.setCursor(0,1);
 lcd.print("booting--->");
 delay(500); 
 lcd.setCursor(0,1);
 lcd.print("booting---->");
 delay(500); 
 lcd.setCursor(0,1);
 lcd.print("booting----->");
 delay(500);
 lcd.setCursor(0,1);
 lcd.print("booting------>");
 delay(500);
 lcd.setCursor(0,1);
 lcd.print("booting------->");
 delay(500);
 lcd.setCursor(0,1);
 lcd.print("booting-------->");
 delay(500);
 lcd.setCursor(0,1);
 lcd.print("   starting up  ");
 delay(500);
 lcd.setCursor(0,1);
 lcd.print("                ");
 lcd.setCursor(0,0);
 lcd.print("                ");
  
  // Turn off the backlight:
  lcd.noDisplay();
  digitalWrite(pin_BL, LOW);
  pinMode(pin_BL, OUTPUT);
  delay(1200);
  
  // Turn on the backlight:
  lcd.display();
  digitalWrite(pin_BL, LOW);
  pinMode(pin_BL, INPUT);
  delay(900);
  
 lcd.setCursor(0,0);
 lcd.print("SPENGLER G-METER");
 delay(1900);

 lcd.setCursor(0,1);
 lcd.print("c2016 jHoltzmann");
 delay(3900);


 lcd.setCursor(0,1);
 lcd.print("                ");
 lcd.setCursor(0,0);
 lcd.print("                ");
 // Turn off the display:
 lcd.noDisplay();
 delay(600);
 // Turn on the display:
 lcd.display();
  
  
 lcd.setCursor(0,0);
 lcd.print("PKE LEVEL:");


}

//okay, that's the whole "startup sequence"  When it's done, it's printing PKE numbers. 
//that way, when you turn it on, it's aready "doing something".

//here I'm initializing two counters I'll need later for the bottom line messages. 
// b is which group of messages, i is which message in that group
// for instance b=0 i=9 finds the value "WHO U GONNA CALL" from the string array at the top 
// whereas b=20 i=0 finds "CYCLOTRON:    OK"
//in computer programs, when we count, we start with zero.  You probably already knew that.

int i = 0;
int b = 0;


//This is the always running part of the program. Once the startup sequence is done this next part loops forever

void loop() {



//This big part is all about reading the button presses and what to do when a button is pressed.
// first, just read the botton press, and put that value into the variable x
  
  int x;
  x = analogRead (0);
  lcd.setCursor(0,0);


 //check if the right button was pushed   if so, do this
 if (x < 60) {
   b=10;
   i=0;
   numbers =0;
   lcd.print ("                ");
   lcd.setCursor(0,1);
   lcd.print ("                ");
  
    // Turn off the display:
    lcd.noDisplay();
    delay(500);
  // Turn on the display:
    lcd.display();
    lcd.setCursor(0,0);
    lcd.print ("   MULTISCAN");
    lcd.setCursor(0,1);
    lcd.print ("----SCANNING----");
    delay(400);
    lcd.setCursor(0,1);
    lcd.print ("--->SCANNING<---");
    delay(400);
    lcd.setCursor(0,1);
    lcd.print ("-->>SCANNING<<--");
    delay(400);
    lcd.setCursor(0,1);
    lcd.print ("->>>SCANNING<<<-");
    delay(400);
    lcd.setCursor(0,1);
    lcd.print (">>>>SCANNING<<<<");
    delay(400);
    //set the print speed of the multiscanner mode here
    mySpeed =7;  
 }




//check if the top button was pushed   if so, do this
 else if (x < 400) {
      b=20;
      i=0;
      numbers =0;
      lcd.print ("                ");
      lcd.setCursor(0,1);
      lcd.print ("                ");
 
      // Turn off the display:
      lcd.noDisplay();
      delay(500);
      // Turn on the display:
      lcd.display();
 
      lcd.setCursor(0,0);
      lcd.print ("    SYSTEMS     ");
      lcd.setCursor(0,1);
      lcd.print ("*RUN DIAGNOSTIC*");
      delay(400);
      lcd.setCursor(0,1);
      lcd.print ("+RUN DIAGNOSTIC+");
      delay(400);
      lcd.setCursor(0,1);
      lcd.print ("|RUN DIAGNOSTIC|");
      delay(400);
      lcd.setCursor(0,1);
      lcd.print ("-RUN DIAGNOSTIC-");
      delay(400);
      lcd.setCursor(0,1);
      lcd.print (" RUN DIAGNOSTIC ");
      delay(400);
//here I set the speed of the bottom text for the dignostic messages.  Don't like it?  Change it!
      mySpeed =14; 
 }





//check if the bottom button was pushed.  If so, do this

 else if (x < 600){
    b=0;
    i=0;
    numbers =0;
    lcd.print ("                ");
    lcd.setCursor(0,1);
    lcd.print ("                ");
 
    // Turn off the display:
    lcd.noDisplay();
    delay(500);
    // Turn on the display:
    lcd.display();
 
    lcd.setCursor(0,0);
    lcd.print ("  GHOSTBUSTERS  ");
    delay(700);
    lcd.setCursor(0,1);
    lcd.print ("      WHO       ");
    delay(350);
    lcd.setCursor(0,1);
    lcd.print ("      YOU       ");
    delay(350);
    lcd.setCursor(0,1);
    lcd.print ("     GONNA      ");
    delay(350);
    lcd.setCursor(0,1);
    lcd.print ("     CALL?      ");
    delay(350);
 // here I set the speed of the bottom text for the advertising messages.  Don't like it?  Change it! 
    mySpeed =30;   
 }





 //check if the bottom button was pushed.  If so, do this
 
 else if (x < 800){
    b=30;
    i=0;
    numbers =0;
    lcd.print ("                ");
    lcd.setCursor(0,1);
    lcd.print ("                ");
 
    // Turn off the display:
    lcd.noDisplay();
    delay(500);
    // Turn on the display:
    lcd.display();
    
    for (int j = 1; j<=17; j++){
      lcd.setCursor(17-j,0);
      lcd.print ("DETECTING       ");
      delay(250);
    }
    
    lcd.print ("                ");
    lcd.setCursor(0,0);
    lcd.print ("ENTITY     CLASS");
    lcd.setCursor(0,1);
    lcd.print ("----DETECTING---");

 
 // here I set the speed of the bottom text for the advertising messages.  Don't like it?  Change it!
 // WARNING, don't set mySpeed much higher than this.  Because of a rounding error, higher settings may never print  
      mySpeed =120;
  }
 



//check if the "select" button was pushed.  If so, do this

 else if (x < 1000){
   b=0;
   numbers =1;
   lcd.setCursor(0,0);
   lcd.print ("                ");
   lcd.setCursor(0,1);
   lcd.print ("                ");
 
   // Turn off the display:
   lcd.noDisplay();
   delay(500);
   // Turn on the display:
   lcd.display();
 
   lcd.setCursor(0,0);
   lcd.print ("PKE LEVEL:");
   mySpeed =2;
 }



//OKAY THAT'S DONE  WE CHECKED ALL 5 BUTTONS!!!

//The last part of the program is just printing the bottom line text in each mode



 //check and see if it's time to print a bottom line
 if (millis() % (200 *mySpeed) ==0){

// if so, check and see if we're printing pke numbers, and if so, print them!

    if(numbers==1){
      lcd.setCursor(15,1);
      lcd.print("%");
      lcd.setCursor(10,1);
      
      //this part generates the numbers for the pke meter
      float pke= (millis()*.00007);
      pke = sin(pke)*100;
      pke = map(pke, -99, 100, 6802, 9834);
      pke = pke*.01;
  
      float pkeMult= (millis()*.00003);
      pkeMult = sin(pkeMult+60)*100;
      pkeMult = map(pkeMult, -99, 100, 20, 100);
      pkeMult = pkeMult*.01;
      
      lcd.print(pke*pkeMult);
    }

  //if we're not printing numbers, get the appropriate message from the string array at the top, and print it
    else if (numbers==0){
      lcd.setCursor(0,1);
      lcd.print((myString1)[i+b]);
      i++;
      if(i>=10){
        i=0;
      }
    }
  }
} 

Needs more F()

Here's an updated version that adds some animated scanning graphics.

/*
Arduino 2x16 LCD - SPENGLER G-METER
September 24, 2021  Version 2 with animated scanner top line graphics added
by Bruce Wright
Free use for fans.  Change whatever you want.  Share for free only.
*/


//at the top of the program, I'm setting up some variables.  A list of messages to print
//and some values I'll need deeper in the program

//This is a string array.  It's a list of all the bottom line text that each mode prints.;
//There are 4 sets of 10 messages.  message 0-9 for the bottom button, 10-19 right, 20-29 top, 30-39 left;

char *myString1[] = {"  212-555-2368  ", "ghostbusters.com", " no job too big ", " no FEE too big ",
                     "?STrAnGe NoIsEs?", "??CoLd SpOtS?!??", "?FeAr or dREaD?!", " Ready2BelieveU ",
                     "WHO U GONNA CALL", " 24 HOURS CALL: ",
                     "EMF:     nominal", "EVP LvL:   quiet", "EVP LvL:   quiet", "EVP LvL:    BUMP",
                     "ECTO COUNT:  low", "ECTO COUNT:  low", "ECTO COUNT:  med", "ECTO COUNT:  med",
                     "ECTO COUNT: HIGH", "ECTO COUNT:  med",
                     "CYCLOTRON:    OK", "NUTRONA:    FULL", "IONIZATION:  85%", "SLIME CHARGE:3++",
                     "SLIME Lvl:RISING", "CONTAINMENT:  OK", "TWINKIE:     BIG", "MESONS:  NOMINAL",
                     "SLO-BLO:     OFF", "N-FILTER: VENTED",
                     "Apparition     2", "----DETECTING---", "Full Torso     5", "----DETECTING---",
                     "Free-Floating  6", "----DETECTING---", "Spectral mist  1", "UNKNOWN      UNK",
                     "NonCorporeal   3", "----DETECTING---"
                    };

char *myString2[] = {"----SCANNING----", "--->SCANNING<---", "-->>SCANNING<<--", "->>>SCANNING<<<-",
                     ">>>>SCANNING<<<<", ">>>-SCANNING-<<<", ">>--SCANNING--<<", ">---SCANNING---<"
                    };

//each mode allows you to change the speed setting.  That's the speed it prints at. Here we start at speed 2
//smaller numbers are faster.  I guess I should have called it myDelay instead!!!
int mySpeed =2;



// first cycling mode will be printing pke numbers.  So I turn that mode on with this variable
int numbers =1;

//initialize top animated text to be on
int scanning = 1;


//in order to drive the LCD shield, you'll need to include the LiquidCrystal library
// THIS SHOULD ALREADY BE PART OF YOUR ARDUINO LIBRARIES 
// if not, go to Tools>ManageLibraries and search and install LiquidCrystal

#include <LiquidCrystal.h>
//LCD pin to Arduino
const int pin_RS = 8; 
const int pin_EN = 9; 
const int pin_d4 = 4; 
const int pin_d5 = 5; 
const int pin_d6 = 6; 
const int pin_d7 = 7; 
const int pin_BL = 10; 
LiquidCrystal lcd( pin_RS,  pin_EN,  pin_d4,  pin_d5,  pin_d6,  pin_d7);



//the void setup here runs ONCE on startup and then the rest of the program loops forever.
//first things I'm doing in this are just animating the boot up messages
//all these messages and the "boot up" process is just for fun.  the system is all booted up already!

void setup() {
 lcd.begin(16, 2);
 lcd.setCursor(0,0);
 lcd.print("              ");
  delay(1900);
 
 lcd.setCursor(0,0);
 lcd.print("  speng_v3.34b");
  delay(1900);
 
 lcd.setCursor(0,1);
 lcd.print("booting     wait");
  delay(500);

 lcd.setCursor(0,1);
 lcd.print("booting>");
 delay(500);
 lcd.setCursor(0,1);
 lcd.print("booting->");
 delay(500);
 lcd.setCursor(0,1);
 lcd.print("booting-->");
 delay(500);
 lcd.setCursor(0,1);
 lcd.print("booting--->");
 delay(500); 
 lcd.setCursor(0,1);
 lcd.print("booting---->");
 delay(500); 
 lcd.setCursor(0,1);
 lcd.print("booting----->");
 delay(500);
 lcd.setCursor(0,1);
 lcd.print("booting------>");
 delay(500);
 lcd.setCursor(0,1);
 lcd.print("booting------->");
 delay(500);
 lcd.setCursor(0,1);
 lcd.print("booting-------->");
 delay(500);
 lcd.setCursor(0,1);
 lcd.print("   starting up  ");
 delay(500);
 lcd.setCursor(0,1);
 lcd.print("                ");
 lcd.setCursor(0,0);
 lcd.print("                ");
  
  // Turn off the backlight:
  lcd.noDisplay();
  digitalWrite(pin_BL, LOW);
  pinMode(pin_BL, OUTPUT);
  delay(1200);
  
  // Turn on the backlight:
  lcd.display();
  digitalWrite(pin_BL, LOW);
  pinMode(pin_BL, INPUT);
  delay(900);
  
 lcd.setCursor(0,0);
 lcd.print("SPENGLER G-METER");
 delay(1900);

 lcd.setCursor(0,1);
 lcd.print("c2016 jHoltzmann");
 delay(3900);


 lcd.setCursor(0,1);
 lcd.print("                ");
 lcd.setCursor(0,0);
 lcd.print("                ");
 // Turn off the display:
 lcd.noDisplay();
 delay(600);
 // Turn on the display:
 lcd.display();
  
  
 lcd.setCursor(0,1);
 lcd.print("PKE LEVEL:");


}

//okay, that's the whole "startup sequence"  When it's done, it's printing PKE numbers. 
//that way, when you turn it on, it's aready "doing something".

//here I'm initializing two counters I'll need later for the bottom line messages. 
// b is which group of messages, i is which message in that group
// for instance b=0 i=9 finds the value "WHO U GONNA CALL" from the string array at the top 
// whereas b=20 i=0 finds "CYCLOTRON:    OK"
//in computer programs, when we count, we start with zero.  You probably already knew that.

int i = 0;
int b = 0;
int j=0;

//This is the always running part of the program. Once the startup sequence is done this next part loops forever

void loop() {



//This big part is all about reading the button presses and what to do when a button is pressed.
// first, just read the botton press, and put that value into the variable x
  
  int x;
  x = analogRead (0);
  lcd.setCursor(0,0);


 //check if the right button was pushed   if so, do this
 if (x < 60) {
   b=10;
   i=0;
   numbers =0;
   scanning=1;
   lcd.print ("                ");
   lcd.setCursor(0,1);
   lcd.print ("                ");
  
    // Turn off the display:
    lcd.noDisplay();
    delay(500);
  // Turn on the display:
    lcd.display();
    lcd.setCursor(0,0);
    lcd.print ("    MULTISCAN   ");
    delay(600); 
    lcd.setCursor(0,0);
    lcd.print ("                ");
    delay(250);   
    lcd.setCursor(0,0);
    lcd.print ("CALIBRATING     ");
    delay(400);
    lcd.setCursor(0,1);
    lcd.print ("<-------------->");
    delay(150); 
    for (int f = 1; f<=14; f++){
      lcd.setCursor(f,1);
      lcd.print ("=");
      delay(200);
    }


    
    //set the print speed of the multiscanner mode here
    mySpeed =7;  
 }




//check if the top button was pushed   if so, do this
 else if (x < 400) {
      b=20;
      i=0;
      numbers =0;
      scanning=0;
      lcd.print ("                ");
      lcd.setCursor(0,1);
      lcd.print ("                ");
 
      // Turn off the display:
      lcd.noDisplay();
      delay(500);
      // Turn on the display:
      lcd.display();
 
      lcd.setCursor(0,0);
      lcd.print ("    SYSTEMS     ");
      lcd.setCursor(0,1);
      lcd.print ("*RUN DIAGNOSTIC*");
      delay(400);
      lcd.setCursor(0,1);
      lcd.print ("+RUN DIAGNOSTIC+");
      delay(400);
      lcd.setCursor(0,1);
      lcd.print ("|RUN DIAGNOSTIC|");
      delay(400);
      lcd.setCursor(0,1);
      lcd.print ("-RUN DIAGNOSTIC-");
      delay(400);
      lcd.setCursor(0,1);
      lcd.print (" RUN DIAGNOSTIC ");
      delay(400);
//here I set the speed of the bottom text for the dignostic messages.  Don't like it?  Change it!
      mySpeed =14; 
 }





//check if the bottom button was pushed.  If so, do this

 else if (x < 600){
    scanning=0;
    b=0;
    i=0;
    numbers =0;
    lcd.print ("                ");
    lcd.setCursor(0,1);
    lcd.print ("                ");
 
    // Turn off the display:
    lcd.noDisplay();
    delay(500);
    // Turn on the display:
    lcd.display();
 
    lcd.setCursor(0,0);
    lcd.print ("  GHOSTBUSTERS  ");
    delay(700);
    lcd.setCursor(0,1);
    lcd.print ("      WHO       ");
    delay(350);
    lcd.setCursor(0,1);
    lcd.print ("      YOU       ");
    delay(350);
    lcd.setCursor(0,1);
    lcd.print ("     GONNA      ");
    delay(350);
    lcd.setCursor(0,1);
    lcd.print ("     CALL?      ");
    delay(350);
 // here I set the speed of the bottom text for the advertising messages.  Don't like it?  Change it! 
    mySpeed =30;   
 }





 //check if the left button was pushed.  If so, do this
 
 else if (x < 800){
    scanning=0;
    b=30;
    i=0;
    numbers =0;
    lcd.print ("                ");
    lcd.setCursor(0,1);
    lcd.print ("                ");
 
    // Turn off the display:
    lcd.noDisplay();
    delay(500);
    // Turn on the display:
    lcd.display();
    
    for (int j = 1; j<=13; j++){
      lcd.setCursor(17-j,0);
      lcd.print ("DETECTING       ");
      delay(300);
    }
    delay(600);
    lcd.print ("                ");
    lcd.setCursor(0,0);
    lcd.print ("ENTITY     CLASS");
    lcd.setCursor(0,1);
    lcd.print ("----DETECTING---");

 
 // here I set the speed of the bottom text for the advertising messages.  Don't like it?  Change it!
 // WARNING, don't set mySpeed much higher than this.  Because of a rounding error, higher settings may never print  
      mySpeed =120;
  }
 



//check if the "select" button was pushed.  If so, do this

 else if (x < 1000){
   scanning=1;
   b=0;
   numbers =1;
   lcd.setCursor(0,0);
   lcd.print ("                ");
   lcd.setCursor(0,1);
   lcd.print ("                ");
 
   // Turn off the display:
   lcd.noDisplay();
   delay(500);
   // Turn on the display:
   lcd.display();
 
   lcd.setCursor(0,1);
   lcd.print ("PKE LEVEL:");
   mySpeed =2;
 }



//OKAY THAT'S DONE  WE CHECKED ALL 5 BUTTONS!!!


//this next part prints the animated scanning top line graphic, if the mode calls for it

 //check and see if it's time to print a TOP line
 if (millis() % (104 *1) ==0){

// if so, check and see if we're printing the scanning graphic and print it

    if (scanning==1){
      
    
      lcd.setCursor(0,0);
      lcd.print((myString2)[j]);
      j++;
      if(j>=8){
        j=0;
      }
    }


 }





//The last part of the program is just printing the bottom line text in each mode



 //check and see if it's time to print a bottom line
 if (millis() % (200 *mySpeed) ==0){

// if so, check and see if we're printing pke numbers, and if so, print them!

    if(numbers==1){
      lcd.setCursor(15,1);
      lcd.print("%");
      lcd.setCursor(10,1);
      
      //this part generates the numbers for the pke meter
      float pke= (millis()*.00007);
      pke = sin(pke)*100;
      pke = map(pke, -99, 100, 6802, 9834);
      pke = pke*.01;
  
      float pkeMult= (millis()*.00003);
      pkeMult = sin(pkeMult+60)*100;
      pkeMult = map(pkeMult, -99, 100, 20, 100);
      pkeMult = pkeMult*.01;
      
      lcd.print(pke*pkeMult);
    }

  //if we're not printing numbers, get the appropriate message from the string array at the top, and print it
    else if (numbers==0){
      lcd.setCursor(0,1);
      lcd.print((myString1)[i+b]);
      i++;
      if(i>=10){
        i=0;
      }
    }
  }
} 

See reply #3

Hi Bruce great work i have ordered the display and have an Uno i can try but. Do you have any details - photos of how it all fits together please ?

Regards

Chris

Thanks, Chris. I’m not using any pins not used by the shield itself. So plugging in the shield is the only connecting to do.

I HAVE mounted it on some blank perf-board I had, using Sugru (or any non-conducting glue/cement you want to use). That allows me to easily secure it in the leather belt-holder that I use.

1 Like

This forum will only allow me to post one image per post. SIGH.

1 Like

That fits in the leather holster that is a tape-measure holder. I’ve cut the front strap off it, and re-riveted it back on a little lower and tighter, so that it stretches right under the momentary switches on the shield. The left over stubs where I cut the strap function well (which is why I didn’t remove them). They keep the sides of my mounting board tucked securely in the holder.

1 Like

Hi Bruce, many thanks for the update that is great. So not wanting to sound stupid once the shield comes i just pug it into the top of the Uno Board ? I assume it only fits one way / location ? This is the Uno i have just opened the package to take the photo. I reckon if i can do this and work out how to programme the code (YouTube here we come) anyone can do this.

well i have tried to upload even tried 3 boards just get this

     System wide configuration file is "C:\Program Files\WindowsApps\ArduinoLLC.ArduinoIDE_1.8.51.0_x86__mdqgnx93n4wtt\hardware\tools\avr/etc/avrdude.conf"

Problem uploading to board. See Upload – Arduino Help Center for suggestions.

     Using Port                    : COM1

     Using Programmer              : arduino

     Overriding Baud Rate          : 115200

avrdude: stk500_recv(): programmer is not responding

it complies ok but wont uplaod i have been on the internet but it means noting to me i have tried all three com ports also. Looks like i have a no go PLEASE can someone help ?

What happens when you try to load any code at all? Like the default sketches in the arduino program? Try Blink for example.

I’d try each suggestion on this link, in order.
https://support.arduino.cc/hc/en-us/sections/360003198300

Hi Bruce, I tried it on my Laptop uploaded 1st time ?
I need to check the PC settings against my Laptop next.
Sorry to have troubled You.

The Screen has arrived and installed just waiting on my 9V lead an box then i can see it it works.

Cool!! I recommend watching this guy’s video tutorials and following along to begin using arduino. Arduino Tutorial 1: Setting Up and Programming the Arduino for Absolute Beginners - YouTube

Okay, brand new deluxe version of the Ghostbusters G-Meter with SOUND!!!! I added a piezo speaker to the rig, and now it beeps and buzzes and plays tunes.
I've also added new on-screen effects to the different modes.

Here's the new, updated version of the code.

/*
Arduino 2x16 LCD - SPENGLER G-METER
October 14, 2021  Version 4 with animated scanner and SOUNDS!!
by Bruce Wright
Free use for fans.  Change whatever you want.  Share for free only.
*/


//at the top of the program, I'm setting up some variables.  A list of messages to print
//and some values I'll need deeper in the program

int spea = 12;
float tempo =.5;


// make some custom characters:
byte ball0[8] = {
  0b00000,
  0b11111,
  0b01110,
  0b00100,
  0b00100,
  0b01110,
  0b11111,
  0b00000
};

byte ball1[8] = {
  0b00000,
  0b00100,
  0b01100,
  0b11100,
  0b01101,
  0b00110,
  0b00100,
  0b00000
};

byte ball2[8] = {
  0b00000,
  0b00000,
  0b10001,
  0b11011,
  0b11011,
  0b10001,
  0b00000,
  0b00000
};

byte ball3[8] = {
  0b00000,
  0b00100,
  0b00110,
  0b00111,
  0b10110,
  0b01100,
  0b00100,
  0b00000
};






//This is a string array.  It's a list of all the bottom line text that each mode prints.;
//There are 4 sets of 10 messages.  message 0-9 for the bottom button, 10-19 right, 20-29 top, 30-39 left;

char *myString1[] = {"  212-555-2368  ", "ghostbusters.com", " no job too big ", " no FEE too big ",
                     "?STrAnGe NoIsEs?", "??CoLd SpOtS?!??", "?FeAr or dREaD?!", " Ready2BelieveU ",
                     "WHO U GONNA CALL", " 24 HOURS CALL: ",
                     "EMF:     nominal", "EVP LvL:   quiet", "EVP LvL:   quiet", "EVP LvL:    BUMP",
                     "ECTO COUNT:  low", "ECTO COUNT:  low", "ECTO COUNT:  med", "ECTO COUNT:  med",
                     "ECTO COUNT: HIGH", "ECTO COUNT:  med",
                     "CYCLOTRON: 13khz", "NUTRONAWAND: 73%", "POWER CELL:  85%", "SLIME CHARGE:3++",
                     "SLIME Lvl:RISING", "CONTAINMENT: 30%", "TWINKIE:     BIG", "INJECTORS: CLEAR",
                     "SLO-BLO: OFFLINE", "N-FILTER: VENTED",
                     "Apparition     2", "----DETECTING---", "Full Torso     5", "----DETECTING---",
                     "Free-Floating  6", "----DETECTING---", "Spectral mist  1", "UNKNOWN      UNK",
                     "NonCorporeal   3", "----DETECTING---"
                    };

char *myString2[] = {"----SCANNING----", "--->SCANNING<---", "-->>SCANNING<<--", "->>>SCANNING<<<-",
                     ">>>>SCANNING<<<<", ">>>-SCANNING-<<<", ">>--SCANNING--<<", ">---SCANNING---<"
                    };

char *myString3[] = {"--GHOSTBUSTERS--", "--GHOSTBUSTERS--", "-<GHOSTBUSTERS>-", "-<GHOSTBUSTERS>-",
                     "<<GHOSTBUSTERS>>", "<<GHOSTBUSTERS>>", "<-GHOSTBUSTERS->", "<-GHOSTBUSTERS->"
                    };

//each mode allows you to change the speed setting.  That's the speed it prints at. Here we start at speed 2
//smaller numbers are faster.  I guess I should have called it myDelay instead!!!
int mySpeed =2;



// first cycling mode will be printing pke numbers.  So I turn that mode on with this variable
int numbers =1;

//initialize top animated text to be on
int scanning = 1;

//initialize typing animated text to be off
int typing = 0;
int pkeInt = 0;


#include "pitches.h" // must include open source pitches.h found online in libraries folder or make a new tab => https://www.arduino.cc/en/Tutorial/toneMelody




int playGb1(float tempo){

  int quarter = 2000 * tempo;
  int eighth = 1000 * tempo;
  int sixteenth = 500 * tempo;
  int thirtysecond = 250* tempo;
  int rest1 = 260* tempo;
  int rest2 = 400 * tempo;
  int rest3 = 800 * tempo;

  tone(spea,NOTE_B5,thirtysecond);
  delay(rest1);
  tone(spea,NOTE_B5,thirtysecond);
  delay(rest1);
  tone(spea,NOTE_DS6,sixteenth);
  delay(rest2);
  tone(spea,NOTE_B5,sixteenth);
  delay(rest2);
    tone(spea,NOTE_CS6,sixteenth);
  delay(rest2);

  tone(spea,NOTE_A4,sixteenth);
  delay(rest2);

  delay(rest2);
  delay(rest2);
  delay(rest2);
  delay(rest1);
  delay(rest1);
  
  tone(spea,NOTE_B5,thirtysecond);
  delay(rest1);
    tone(spea,NOTE_B5,thirtysecond);
  delay(rest1);
    tone(spea,NOTE_B5,thirtysecond);
  delay(rest1);
    tone(spea,NOTE_B5,thirtysecond);
  delay(rest1);
    tone(spea,NOTE_A4,eighth);
  delay(rest1);
    delay(rest1);
    tone(spea,NOTE_B5,sixteenth);
  delay(rest2);

}

int playGb2(float tempo){
    int quarter = 2000 * tempo;
    int eighth = 1000 * tempo;
    int sixteenth = 500 * tempo;
    int thirtysecond = 250* tempo;
    int rest1 = 260* tempo;
    int rest2 = 400 * tempo;
    int rest3 = 800 * tempo;
   tone(spea,NOTE_B4,eighth);
   delay(rest2);
   tone(spea,NOTE_A5,eighth);
   delay(rest2);
   tone(spea,NOTE_GS5,eighth);
   delay(rest2);
   tone(spea,NOTE_F5,eighth);
   delay(rest2);

}

int playGb3(float tempo){

    int quarter = 2000 * tempo;
    int eighth = 1000 * tempo;
    int sixteenth = 500 * tempo;
    int thirtysecond = 250* tempo;
    int rest1 = 260* tempo;
    int rest2 = 400 * tempo;
    int rest3 = 800 * tempo;
   tone(spea,NOTE_E5,quarter);
   delay(rest2);
   tone(spea,NOTE_F6,quarter);
   delay(rest2);
   tone(spea,NOTE_CS6,eighth);
   delay(rest2);
}

int playGb4(float tempo){

    int half = 4000 * tempo;
    int quarter = 2000 * tempo;
    int eighth = 1000 * tempo;
    int sixteenth = 500 * tempo;
    int thirtysecond = 250* tempo;
    int rest1 = 260* tempo;
    int rest2 = 400 * tempo;
    int rest3 = 800 * tempo;

    
   tone(spea,NOTE_C5,sixteenth);
   delay(rest3);
   //delay(rest1);
  
   tone(spea,NOTE_C5,eighth);
   delay(rest3);
  

   tone(spea,NOTE_DS5,eighth);
   delay(rest2);
   tone(spea,NOTE_E5,eighth);
   delay(rest2);
   tone(spea,NOTE_F5,half);
   delay(rest2);
   delay(rest2);
   tone(spea,NOTE_GS5,eighth);
   delay(rest3);
   delay(rest3);
   tone(spea,NOTE_G5,eighth);
   delay(rest3);
   delay(tempo*900);
}

int playGb5(float tempo){

    int half = 4000 * tempo;
    int quarter = 2000 * tempo;
    int eighth = 1000 * tempo;
    int sixteenth = 500 * tempo;
    int thirtysecond = 250* tempo;
    int rest1 = 260* tempo;
    int rest2 = 400 * tempo;
    int rest3 = 800 * tempo;

    
   tone(spea,NOTE_C5,sixteenth);
   delay(rest3);

  
   tone(spea,NOTE_C5,eighth);
   delay(rest3);
  

   tone(spea,NOTE_DS5,eighth);
   delay(rest2);
   tone(spea,NOTE_E5,eighth);
   delay(rest2);
   tone(spea,NOTE_F5,half);
   delay(rest2);
   delay(rest2);
   tone(spea,NOTE_GS5,sixteenth);
   delay(rest3);
   tone(spea,NOTE_GS5,sixteenth);
   delay(rest3);
   tone(spea,NOTE_G5,eighth);
   delay(rest3);
   delay(tempo*900);
}


int scannerNote(int input){
    int note = 932;
    if (input>33){
       note = 988;     
    }

    if (input>66){
       note = 1047;     
    }
    if (input>70){
       note = 1109;     
    }
     if (input>75){
       note = 1175;     
    }
        if (input>80){
       note = 1319;     
    }
        if (input>85){
       note = 1397;     
    }
            if (input>90){
       note = 1760;     
    }

  return note;

  
}

//in order to drive the LCD shield, you'll need to include the LiquidCrystal library
// THIS SHOULD ALREADY BE PART OF YOUR ARDUINO LIBRARIES 
// if not, go to Tools>ManageLibraries and search and install LiquidCrystal

#include <LiquidCrystal.h>
//LCD pin to Arduino
const int pin_RS = 8; 
const int pin_EN = 9; 
const int pin_d4 = 4; 
const int pin_d5 = 5; 
const int pin_d6 = 6; 
const int pin_d7 = 7; 
const int pin_BL = 10; 
LiquidCrystal lcd( pin_RS,  pin_EN,  pin_d4,  pin_d5,  pin_d6,  pin_d7);


//the void setup here runs ONCE on startup and then the rest of the program loops forever.
//first things I'm doing in this are just animating the boot up messages
//all these messages and the "boot up" process is just for fun.  the system is all booted up already!

void setup() {
 
 
 // create a new character
  lcd.createChar(0, ball0);
  lcd.createChar(1, ball1);
  lcd.createChar(2, ball2);
  lcd.createChar(3, ball3);
 
//Serial.begin(9600);

  pinMode(spea, OUTPUT);
 lcd.begin(16, 2);
   // Turn off the backlight:
  lcd.noDisplay();
  digitalWrite(pin_BL, LOW);
  pinMode(pin_BL, OUTPUT);
  delay(200);
  
  // Turn on the backlight:
  lcd.display();
  digitalWrite(pin_BL, LOW);
  pinMode(pin_BL, INPUT);
  delay(100);
  
 lcd.setCursor(0,0);
 lcd.print("              ");
  delay(1100);
 
 lcd.setCursor(0,0);
 lcd.print("  speng_v3.35b");
  delay(1900);
 
 lcd.setCursor(0,1);
 lcd.print("booting     wait");
  delay(500);

 lcd.setCursor(0,1);
 lcd.print("booting>");
 delay(500);
 lcd.setCursor(0,1);
 lcd.print("booting->");
 delay(500);
 lcd.setCursor(0,1);
 lcd.print("booting-->");
 delay(500);
 lcd.setCursor(0,1);
 lcd.print("booting--->");
 delay(500); 
 lcd.setCursor(0,1);
 lcd.print("booting---->");
 delay(500); 
 lcd.setCursor(0,1);
 lcd.print("booting----->");
 delay(500);
 lcd.setCursor(0,1);
 lcd.print("booting------>");
 delay(500);
 lcd.setCursor(0,1);
 lcd.print("booting------->");
 delay(500);
 lcd.setCursor(0,1);
 lcd.print("booting-------->");
 delay(500);
 lcd.setCursor(0,1);
  int a;
  a = analogRead (0);

 //check if the right button was pushed   if so, do this
 if (a < 1000) {
   tone(spea,NOTE_D5,50);
    lcd.setCursor(0,1);
    lcd.print("SSHHHHHHHH!!!!!!");
    spea = 11;
     if (a < 800 && a>600) {
          delay(500);
          lcd.setCursor(0,0);
          lcd.print("G-Meter Made By ");
          lcd.setCursor(0,1);
          lcd.print("  Bruce Wright  ");
          spea = 12;
            playGb4(.3);
            playGb4(.3);
            playGb4(.3);
            playGb5(.3);
           
          delay(1000);
          spea = 11;
     }
 }



 
     Serial.print(a);
     Serial.println();

 
 lcd.print("   starting up  ");
 delay(500);
 lcd.setCursor(0,1);
 lcd.print("                ");
 lcd.setCursor(0,0);
 lcd.print("                ");
  
  // Turn off the backlight:
  lcd.noDisplay();
  digitalWrite(pin_BL, LOW);
  pinMode(pin_BL, OUTPUT);
  delay(1200);
  
  // Turn on the backlight:
  lcd.display();
  digitalWrite(pin_BL, LOW);
  pinMode(pin_BL, INPUT);

  delay(900);
  
 lcd.setCursor(0,0);

 lcd.print("SPENGLER G-METER");
      // Play startup song
 
 playGb2(1.3);
 delay(100);


 lcd.setCursor(0,1);
 lcd.print("c2016 jHoltzmann");
 // Play startup song
  
 playGb3(1.3);

 delay(3900);


 lcd.setCursor(0,1);
 lcd.print("                ");
 lcd.setCursor(0,0);
 lcd.print("                ");
 // Turn off the display:
 lcd.noDisplay();
 delay(600);
 // Turn on the display:
 lcd.display();
  
  
 lcd.setCursor(0,1);
 lcd.print("PKE LEVEL:");


}

//okay, that's the whole "startup sequence"  When it's done, it's printing PKE numbers. 
//that way, when you turn it on, it's aready "doing something".

//here I'm initializing three counters I'll need later for the printed array messages. 
// b is which group of messages, i is which message in that group
// for instance b=0 i=9 finds the value "WHO U GONNA CALL" from the string array at the top 
// whereas b=20 i=0 finds "CYCLOTRON:    OK"
//in computer programs, when we count, we start with zero.  You probably already knew that.

int i = 0;
int b = 0;
int j=0;
int echo = 0;
int myC=0;
//This is the always running part of the program. Once the startup sequence is done this next part loops forever

void loop() {



//This big part is all about reading the button presses and what to do when a button is pressed.
// first, just read the botton press, and put that value into the variable x
  
  int x;
  x = analogRead (0);
  lcd.setCursor(0,0);


 //check if the right button was pushed   if so, do this
 if (x < 60) {
   tone(spea,NOTE_D5,50);
   b=10;
   i=0;
   numbers =0;
   scanning=1;
   typing = 0;
   lcd.print ("                ");
   lcd.setCursor(0,1);
   lcd.print ("                ");
  
    // Turn off the display:
    lcd.noDisplay();
    delay(500);
  // Turn on the display:
    lcd.display();

    lcd.setCursor(0,0);
    lcd.print ("    MULTISCAN   ");
    delay(600); 
    lcd.setCursor(0,0);
    lcd.print ("                ");
    delay(250);   
    lcd.setCursor(0,0);
    lcd.print ("CALIBRATING     ");
    delay(400);
    lcd.setCursor(0,1);
    lcd.print ("<-------------->");
    delay(150); 
    for (int f = 1; f<=14; f++){
      lcd.setCursor(f,1);
      lcd.print ("=");
      int  sound = max(0,map(f,1,14,631,3000));
      tone(spea,sound,20);
      delay(200);
    }


    
    //set the print speed of the multiscanner mode here
    mySpeed =7;  
 }




//check if the top button was pushed   if so, do this
 else if (x < 400) {
      tone(spea,NOTE_D5,50);
      b=20;
      i=0;
      numbers =0;
      scanning=0;
      typing = 1;
      lcd.print ("                ");
      lcd.setCursor(0,1);
      lcd.print ("                ");
 
      // Turn off the display:
      lcd.noDisplay();
      delay(500);
      // Turn on the display:
      lcd.display();
      
      lcd.setCursor(0,0);
  
      lcd.print (" RUN DIAGNOSTIC ");
      delay(200);

      for(int p =0; p<10; p++){
        lcd.setCursor(0,0);
        lcd.write(byte(p%4)); // when calling lcd.write() '0' must be cast as a byte
        lcd.setCursor(15,0);
        lcd.write(byte(p%4)); // when calling lcd.write() '0' must be cast as a byte
        tone(spea,random(60,2000),35);
        delay(100);
        tone(spea,random(60,2000),35);
        delay(100);
        tone(spea,random(60,2000),35);
        delay(100);

      }
        lcd.setCursor(0,0);
        lcd.print (" ");
        lcd.setCursor(15,0);
        lcd.print (" ");
        
     tone(spea,NOTE_C7,235);
      lcd.setCursor(0,1);
      lcd.print (" CHECK COMPLETE ");
     
      
      delay(3000);
      lcd.setCursor(0,0);
      lcd.print ("                ");
      lcd.setCursor(0,1);
      lcd.print ("                ");
      delay(500);
      lcd.setCursor(0,0);
      tone(spea,NOTE_F6,100);
      lcd.print ("    SYSTEMS     ");
      lcd.setCursor(0,1);
      lcd.print ("________________");

//here I set the speed of the bottom text for the dignostic messages.  Don't like it?  Change it!
      mySpeed =24; 
 }





//check if the bottom button was pushed.  If so, do this

 else if (x < 600){
    tone(spea,NOTE_D5,50);
    //playGb4(.3);
    scanning=2;
    typing = 0;
    b=0;
    i=0;
    numbers =0;
    lcd.print ("                ");
    lcd.setCursor(0,1);
    lcd.print ("                ");
 
    // Turn off the display:
    lcd.noDisplay();
    delay(500);
    // Turn on the display:
    lcd.display();
 
    lcd.setCursor(0,0);
    lcd.print ("  GHOSTBUSTERS  ");
    delay(700);
    playGb4(.3);
    lcd.setCursor(0,1);
    lcd.print ("      WHO       ");
    delay(350);
    lcd.setCursor(0,1);
    lcd.print ("      YOU       ");
    delay(350);
    lcd.setCursor(0,1);
    lcd.print ("     GONNA      ");
    delay(350);
    lcd.setCursor(0,1);
    lcd.print ("     CALL?      ");
    
    delay(350);
     playGb1(.5);
 // here I set the speed of the bottom text for the advertising messages.  Don't like it?  Change it! 
    mySpeed =30;   
 }





 //check if the left button was pushed.  If so, do this
 
 else if (x < 800){
    tone(spea,NOTE_D5,50);
    scanning=0;
    typing = 1;
    b=30;
    i=0;
    numbers =0;
    lcd.print ("                ");
    lcd.setCursor(0,1);
    lcd.print ("                ");
 
    // Turn off the display:
    lcd.noDisplay();
    delay(500);
    // Turn on the display:
    lcd.display();
 
    String topLine = (" TOBIN'S SPIRIT ");
    String bottomLine = ("    DATABASE    ");
    
    for (int d = 0; d<=15; d++){
          lcd.cursor();
          lcd.setCursor(d,0);
          delay(100);
          lcd.print((topLine.substring(d,d+1)));
          tone(spea,NOTE_B6,7);
          //tone(spea,random(60,3000),7);
           lcd.noCursor();
    }
    for (int d = 0; d<=15; d++){
          lcd.cursor();
          lcd.setCursor(d,1);
          delay(100);
          lcd.print((bottomLine.substring(d,d+1)));
          tone(spea,NOTE_B6,7);
          //tone(spea,random(60,3000),7);
           lcd.noCursor();
    }
    playGb2(1.0);

    


    delay(3000);
    lcd.print ("                ");
    lcd.setCursor(0,0);
    lcd.print ("ENTITY     CLASS");
    lcd.setCursor(0,1);
    lcd.print ("----DETECTING---");

 
 // here I set the speed of the bottom text for the detecting messages.  Don't like it?  Change it!
 // WARNING, don't set mySpeed much higher than 120.  Because of a rounding error, higher settings may never print  
      mySpeed =90;
  }
 



//check if the "select" button was pushed.  If so, do this

 else if (x < 1000){
   tone(spea,NOTE_D5,50); 
   scanning=1;
   typing = 0;
   b=0;
   numbers =1;
   lcd.setCursor(0,0);
   lcd.print ("                ");
   lcd.setCursor(0,1);
   lcd.print ("                ");
 
   // Turn off the display:
   lcd.noDisplay();
   delay(500);
   // Turn on the display:
   lcd.display();
 
   lcd.setCursor(0,1);
   lcd.print ("PKE LEVEL:");
   mySpeed =2;
 }



//OKAY THAT'S DONE  WE CHECKED ALL 5 BUTTONS!!!


//this next part prints the animated scanning top line graphic, if the mode calls for it

 //check and see if it's time to print a TOP line
 if ((millis()) % (204) <=0){

      
// if so, check and see if we're printing the scanning graphic and print it

    if (scanning==1){
      
    
      lcd.setCursor(0,0);
      lcd.print((myString2)[j]);
      if(j==2){
        if(numbers==1){
          tone(spea,scannerNote(pkeInt),(scannerNote(pkeInt)/30));  
        }
        else if (numbers==0){
          tone(spea,1047,20);
        }
      }
      j++;
      if(j>=8){
        j=0;
      }
    }
    
    if (scanning==2){
          
        
          lcd.setCursor(0,0);
          lcd.print((myString3)[j]);
          j++;
          if(j>=8){
            j=0;
          }
        }

 }



//The last part of the program is just printing the bottom line text in each mode



 //check and see if it's time to print a bottom line
 if (millis() % (200 *mySpeed) ==0){

// if so, check and see if we're printing pke numbers, and if so, print them!

    if(numbers==1){
      lcd.setCursor(15,1);
      lcd.print("%");
      lcd.setCursor(10,1);
      
      //this part generates the numbers for the pke meter
      float pke= (millis()*.00007);
      pke = sin(pke)*100;
      pke = map(pke, -99, 100, 6802, 9834);
      pke = pke*.01;
  
      float pkeMult= (millis()*.00003);
      pkeMult = sin(pkeMult+60)*100;
      pkeMult = map(pkeMult, -99, 100, 20, 100);
      pkeMult = pkeMult*.01;
      
      lcd.print(pke*pkeMult);
      pkeInt = (pke*pkeMult);

    }

  //if we're not printing numbers, get the appropriate message from the string array at the top, and print it
    else if (numbers==0){
      if(typing==0){
        lcd.setCursor(0,1);
        lcd.print((myString1)[i+b]);
        i++;
        if(i>=10){
          i=0;
        }
      }
      else if (typing==1){
        String thisLine = ((myString1)[i+b]);
        i++;
        if(i>=10){
          i=0;
        }
        
        lcd.setCursor(0,1);
        lcd.print("                ");
        for (int d = 0; d<=15; d++){
          lcd.cursor();
          lcd.setCursor(d,1);
          //tone(spea,NOTE_B6,50);
          delay(100);
          lcd.print((thisLine.substring(d,d+1)));
          tone(spea,NOTE_B6,7);
           lcd.noCursor();

  

          
        }
        
      }
      }
    }
} 

In order for that to work, you'll need to copy and paste this sound library into a second tab in your sketch.

In your sketch window, look for the little tab menu. open that up and click New Tab.
Then put these tones in that tab, and save your project.

/*************************************************

 * Public Constants

 *************************************************/

#define NOTE_B0  31
#define NOTE_C1  33
#define NOTE_CS1 35
#define NOTE_D1  37
#define NOTE_DS1 39
#define NOTE_E1  41
#define NOTE_F1  44
#define NOTE_FS1 46
#define NOTE_G1  49
#define NOTE_GS1 52
#define NOTE_A1  55
#define NOTE_AS1 58
#define NOTE_B1  62
#define NOTE_C2  65
#define NOTE_CS2 69
#define NOTE_D2  73
#define NOTE_DS2 78
#define NOTE_E2  82
#define NOTE_F2  87
#define NOTE_FS2 93
#define NOTE_G2  98
#define NOTE_GS2 104
#define NOTE_A2  110
#define NOTE_AS2 117
#define NOTE_B2  123
#define NOTE_C3  131
#define NOTE_CS3 139
#define NOTE_D3  147
#define NOTE_DS3 156
#define NOTE_E3  165
#define NOTE_F3  175
#define NOTE_FS3 185
#define NOTE_G3  196
#define NOTE_GS3 208
#define NOTE_A3  220
#define NOTE_AS3 233
#define NOTE_B3  247
#define NOTE_C4  262
#define NOTE_CS4 277
#define NOTE_D4  294
#define NOTE_DS4 311
#define NOTE_E4  330
#define NOTE_F4  349
#define NOTE_FS4 370
#define NOTE_G4  392
#define NOTE_GS4 415
#define NOTE_A4  440
#define NOTE_AS4 466
#define NOTE_B4  494
#define NOTE_C5  523
#define NOTE_CS5 554
#define NOTE_D5  587
#define NOTE_DS5 622
#define NOTE_E5  659
#define NOTE_F5  698
#define NOTE_FS5 740
#define NOTE_G5  784
#define NOTE_GS5 831
#define NOTE_A5  880
#define NOTE_AS5 932
#define NOTE_B5  988
#define NOTE_C6  1047
#define NOTE_CS6 1109
#define NOTE_D6  1175
#define NOTE_DS6 1245
#define NOTE_E6  1319
#define NOTE_F6  1397
#define NOTE_FS6 1480
#define NOTE_G6  1568
#define NOTE_GS6 1661
#define NOTE_A6  1760
#define NOTE_AS6 1865
#define NOTE_B6  1976
#define NOTE_C7  2093
#define NOTE_CS7 2217
#define NOTE_D7  2349
#define NOTE_DS7 2489
#define NOTE_E7  2637
#define NOTE_F7  2794
#define NOTE_FS7 2960
#define NOTE_G7  3136
#define NOTE_GS7 3322
#define NOTE_A7  3520
#define NOTE_AS7 3729
#define NOTE_B7  3951
#define NOTE_C8  4186
#define NOTE_CS8 4435
#define NOTE_D8  4699
#define NOTE_DS8 4978

Connect the pin 12 to a 10 ohm resistor, and then that to the positive side of the buzzer. Connect the negative side to the GND (ground) plug.

OKAY, here's the same version but with NO SOUND. So if you want the screen graphic updates but don't want to do the wiring to add the speaker, you can use this version. You won't need to add that additional tab with the sound definitions for this version.

/*
Arduino 2x16 LCD - SPENGLER G-METER
October 14, 2021  Version 4S with new scanner animation but NO SOUND
by Bruce Wright
Free use for fans.  Change whatever you want.  Share for free only.
*/


//at the top of the program, I'm setting up some variables.  A list of messages to print
//and some values I'll need deeper in the program

int spea = 12;
float tempo =.5;


// make some custom characters:
byte ball0[8] = {
  0b00000,
  0b11111,
  0b01110,
  0b00100,
  0b00100,
  0b01110,
  0b11111,
  0b00000
};

byte ball1[8] = {
  0b00000,
  0b00100,
  0b01100,
  0b11100,
  0b01101,
  0b00110,
  0b00100,
  0b00000
};

byte ball2[8] = {
  0b00000,
  0b00000,
  0b10001,
  0b11011,
  0b11011,
  0b10001,
  0b00000,
  0b00000
};

byte ball3[8] = {
  0b00000,
  0b00100,
  0b00110,
  0b00111,
  0b10110,
  0b01100,
  0b00100,
  0b00000
};






//This is a string array.  It's a list of all the bottom line text that each mode prints.;
//There are 4 sets of 10 messages.  message 0-9 for the bottom button, 10-19 right, 20-29 top, 30-39 left;

char *myString1[] = {"  212-555-2368  ", "ghostbusters.com", " no job too big ", " no FEE too big ",
                     "?STrAnGe NoIsEs?", "??CoLd SpOtS?!??", "?FeAr or dREaD?!", " Ready2BelieveU ",
                     "WHO U GONNA CALL", " 24 HOURS CALL: ",
                     "EMF:     nominal", "EVP LvL:   quiet", "EVP LvL:   quiet", "EVP LvL:    BUMP",
                     "ECTO COUNT:  low", "ECTO COUNT:  low", "ECTO COUNT:  med", "ECTO COUNT:  med",
                     "ECTO COUNT: HIGH", "ECTO COUNT:  med",
                     "CYCLOTRON: 13khz", "NUTRONAWAND: 73%", "POWER CELL:  85%", "SLIME CHARGE:3++",
                     "SLIME Lvl:RISING", "CONTAINMENT: 30%", "TWINKIE:     BIG", "INJECTORS: CLEAR",
                     "SLO-BLO: OFFLINE", "N-FILTER: VENTED",
                     "Apparition     2", "----DETECTING---", "Full Torso     5", "----DETECTING---",
                     "Free-Floating  6", "----DETECTING---", "Spectral mist  1", "UNKNOWN      UNK",
                     "NonCorporeal   3", "----DETECTING---"
                    };

char *myString2[] = {"----SCANNING----", "--->SCANNING<---", "-->>SCANNING<<--", "->>>SCANNING<<<-",
                     ">>>>SCANNING<<<<", ">>>-SCANNING-<<<", ">>--SCANNING--<<", ">---SCANNING---<"
                    };

char *myString3[] = {"--GHOSTBUSTERS--", "--GHOSTBUSTERS--", "-<GHOSTBUSTERS>-", "-<GHOSTBUSTERS>-",
                     "<<GHOSTBUSTERS>>", "<<GHOSTBUSTERS>>", "<-GHOSTBUSTERS->", "<-GHOSTBUSTERS->"
                    };

//each mode allows you to change the speed setting.  That's the speed it prints at. Here we start at speed 2
//smaller numbers are faster.  I guess I should have called it myDelay instead!!!
int mySpeed =2;



// first cycling mode will be printing pke numbers.  So I turn that mode on with this variable
int numbers =1;

//initialize top animated text to be on
int scanning = 1;

//initialize typing animated text to be off
int typing = 0;
int pkeInt = 0;



//in order to drive the LCD shield, you'll need to include the LiquidCrystal library
// THIS SHOULD ALREADY BE PART OF YOUR ARDUINO LIBRARIES 
// if not, go to Tools>ManageLibraries and search and install LiquidCrystal

#include <LiquidCrystal.h>
//LCD pin to Arduino
const int pin_RS = 8; 
const int pin_EN = 9; 
const int pin_d4 = 4; 
const int pin_d5 = 5; 
const int pin_d6 = 6; 
const int pin_d7 = 7; 
const int pin_BL = 10; 
LiquidCrystal lcd( pin_RS,  pin_EN,  pin_d4,  pin_d5,  pin_d6,  pin_d7);


//the void setup here runs ONCE on startup and then the rest of the program loops forever.
//first things I'm doing in this are just animating the boot up messages
//all these messages and the "boot up" process is just for fun.  the system is all booted up already!

void setup() {
 
 
 // create a new character
  lcd.createChar(0, ball0);
  lcd.createChar(1, ball1);
  lcd.createChar(2, ball2);
  lcd.createChar(3, ball3);
 

 lcd.begin(16, 2);
   // Turn off the backlight:
  lcd.noDisplay();
  digitalWrite(pin_BL, LOW);
  pinMode(pin_BL, OUTPUT);
  delay(200);
  
  // Turn on the backlight:
  lcd.display();
  digitalWrite(pin_BL, LOW);
  pinMode(pin_BL, INPUT);
  delay(100);
  
 lcd.setCursor(0,0);
 lcd.print("              ");
  delay(1100);
 
 lcd.setCursor(0,0);
 lcd.print("  speng_v3.35b");
  delay(1900);
 
 lcd.setCursor(0,1);
 lcd.print("booting     wait");
  delay(500);

 lcd.setCursor(0,1);
 lcd.print("booting>");
 delay(500);
 lcd.setCursor(0,1);
 lcd.print("booting->");
 delay(500);
 lcd.setCursor(0,1);
 lcd.print("booting-->");
 delay(500);
 lcd.setCursor(0,1);
 lcd.print("booting--->");
 delay(500); 
 lcd.setCursor(0,1);
 lcd.print("booting---->");
 delay(500); 
 lcd.setCursor(0,1);
 lcd.print("booting----->");
 delay(500);
 lcd.setCursor(0,1);
 lcd.print("booting------>");
 delay(500);
 lcd.setCursor(0,1);
 lcd.print("booting------->");
 delay(500);
 lcd.setCursor(0,1);
 lcd.print("booting-------->");
 delay(500);
 lcd.setCursor(0,1);
  int a;
  a = analogRead (0);

 //check if the right button was pushed   if so, do this
 if (a < 1000) {
   
    lcd.setCursor(0,1);
    lcd.print("????????????????");
   
     if (a < 800 && a>600) {
          delay(500);
          lcd.setCursor(0,0);
          lcd.print("G-Meter Made By ");
          lcd.setCursor(0,1);
          lcd.print("  Bruce Wright  ");

           
          delay(1000);

     }
 }



 
     Serial.print(a);
     Serial.println();

 
 lcd.print("   starting up  ");
 delay(500);
 lcd.setCursor(0,1);
 lcd.print("                ");
 lcd.setCursor(0,0);
 lcd.print("                ");
  
  // Turn off the backlight:
  lcd.noDisplay();
  digitalWrite(pin_BL, LOW);
  pinMode(pin_BL, OUTPUT);
  delay(1200);
  
  // Turn on the backlight:
  lcd.display();
  digitalWrite(pin_BL, LOW);
  pinMode(pin_BL, INPUT);

  delay(900);
  
 lcd.setCursor(0,0);

 lcd.print("SPENGLER G-METER");

 delay(100);


 lcd.setCursor(0,1);
 lcd.print("c2016 jHoltzmann");


 delay(3900);


 lcd.setCursor(0,1);
 lcd.print("                ");
 lcd.setCursor(0,0);
 lcd.print("                ");
 // Turn off the display:
 lcd.noDisplay();
 delay(600);
 // Turn on the display:
 lcd.display();
  
  
 lcd.setCursor(0,1);
 lcd.print("PKE LEVEL:");


}

//okay, that's the whole "startup sequence"  When it's done, it's printing PKE numbers. 
//that way, when you turn it on, it's aready "doing something".

//here I'm initializing three counters I'll need later for the printed array messages. 
// b is which group of messages, i is which message in that group
// for instance b=0 i=9 finds the value "WHO U GONNA CALL" from the string array at the top 
// whereas b=20 i=0 finds "CYCLOTRON:    OK"
//in computer programs, when we count, we start with zero.  You probably already knew that.

int i = 0;
int b = 0;
int j=0;
int myC=0;
//This is the always running part of the program. Once the startup sequence is done this next part loops forever

void loop() {



//This big part is all about reading the button presses and what to do when a button is pressed.
// first, just read the botton press, and put that value into the variable x
  
  int x;
  x = analogRead (0);
  lcd.setCursor(0,0);


 //check if the right button was pushed   if so, do this
 if (x < 60) {
   b=10;
   i=0;
   numbers =0;
   scanning=1;
   typing = 0;
   lcd.print ("                ");
   lcd.setCursor(0,1);
   lcd.print ("                ");
  
    // Turn off the display:
    lcd.noDisplay();
    delay(500);
  // Turn on the display:
    lcd.display();

    lcd.setCursor(0,0);
    lcd.print ("    MULTISCAN   ");
    delay(600); 
    lcd.setCursor(0,0);
    lcd.print ("                ");
    delay(250);   
    lcd.setCursor(0,0);
    lcd.print ("CALIBRATING     ");
    delay(400);
    lcd.setCursor(0,1);
    lcd.print ("<-------------->");
    delay(150); 
    for (int f = 1; f<=14; f++){
      lcd.setCursor(f,1);
      lcd.print ("=");
      
      delay(200);
    }


    
    //set the print speed of the multiscanner mode here
    mySpeed =7;  
 }




//check if the top button was pushed   if so, do this
 else if (x < 400) {
      
      b=20;
      i=0;
      numbers =0;
      scanning=0;
      typing = 1;
      lcd.print ("                ");
      lcd.setCursor(0,1);
      lcd.print ("                ");
 
      // Turn off the display:
      lcd.noDisplay();
      delay(500);
      // Turn on the display:
      lcd.display();
      
      lcd.setCursor(0,0);
  
      lcd.print (" RUN DIAGNOSTIC ");
      delay(200);

      for(int p =0; p<10; p++){
        lcd.setCursor(0,0);
        lcd.write(byte(p%4)); // when calling lcd.write() '0' must be cast as a byte
        lcd.setCursor(15,0);
        lcd.write(byte(p%4)); // when calling lcd.write() '0' must be cast as a byte
        delay(100);
        delay(100);
        delay(100);

      }
        lcd.setCursor(0,0);
        lcd.print (" ");
        lcd.setCursor(15,0);
        lcd.print (" ");
        

      lcd.setCursor(0,1);
      lcd.print (" CHECK COMPLETE ");
     
      
      delay(3000);
      lcd.setCursor(0,0);
      lcd.print ("                ");
      lcd.setCursor(0,1);
      lcd.print ("                ");
      delay(500);
      lcd.setCursor(0,0);
      lcd.print ("    SYSTEMS     ");
      lcd.setCursor(0,1);
      lcd.print ("________________");

//here I set the speed of the bottom text for the dignostic messages.  Don't like it?  Change it!
      mySpeed =24; 
 }





//check if the bottom button was pushed.  If so, do this

 else if (x < 600){
    scanning=2;
    typing = 0;
    b=0;
    i=0;
    numbers =0;
    lcd.print ("                ");
    lcd.setCursor(0,1);
    lcd.print ("                ");
 
    // Turn off the display:
    lcd.noDisplay();
    delay(500);
    // Turn on the display:
    lcd.display();
 
    lcd.setCursor(0,0);
    lcd.print ("  GHOSTBUSTERS  ");
    delay(700);
    lcd.setCursor(0,1);
    lcd.print ("      WHO       ");
    delay(350);
    lcd.setCursor(0,1);
    lcd.print ("      YOU       ");
    delay(350);
    lcd.setCursor(0,1);
    lcd.print ("     GONNA      ");
    delay(350);
    lcd.setCursor(0,1);
    lcd.print ("     CALL?      ");
    
    delay(350);
 // here I set the speed of the bottom text for the advertising messages.  Don't like it?  Change it! 
    mySpeed =30;   
 }





 //check if the left button was pushed.  If so, do this
 
 else if (x < 800){
    scanning=0;
    typing = 1;
    b=30;
    i=0;
    numbers =0;
    lcd.print ("                ");
    lcd.setCursor(0,1);
    lcd.print ("                ");
 
    // Turn off the display:
    lcd.noDisplay();
    delay(500);
    // Turn on the display:
    lcd.display();
 
    String topLine = (" TOBIN'S SPIRIT ");
    String bottomLine = ("    DATABASE    ");
    
    for (int d = 0; d<=15; d++){
          lcd.cursor();
          lcd.setCursor(d,0);
          delay(100);
          lcd.print((topLine.substring(d,d+1)));
          lcd.noCursor();
    }
    for (int d = 0; d<=15; d++){
          lcd.cursor();
          lcd.setCursor(d,1);
          delay(100);
          lcd.print((bottomLine.substring(d,d+1)));
           lcd.noCursor();
    }

    


    delay(3000);
    lcd.print ("                ");
    lcd.setCursor(0,0);
    lcd.print ("ENTITY     CLASS");
    lcd.setCursor(0,1);
    lcd.print ("----DETECTING---");

 
 // here I set the speed of the bottom text for the detecting messages.  Don't like it?  Change it!
 // WARNING, don't set mySpeed much higher than 120.  Because of a rounding error, higher settings may never print  
      mySpeed =90;
  }
 



//check if the "select" button was pushed.  If so, do this

 else if (x < 1000){
   scanning=1;
   typing = 0;
   b=0;
   numbers =1;
   lcd.setCursor(0,0);
   lcd.print ("                ");
   lcd.setCursor(0,1);
   lcd.print ("                ");
 
   // Turn off the display:
   lcd.noDisplay();
   delay(500);
   // Turn on the display:
   lcd.display();
 
   lcd.setCursor(0,1);
   lcd.print ("PKE LEVEL:");
   mySpeed =2;
 }



//OKAY THAT'S DONE  WE CHECKED ALL 5 BUTTONS!!!


//this next part prints the animated scanning top line graphic, if the mode calls for it

 //check and see if it's time to print a TOP line
 if ((millis()) % (204) <=0){

      
// if so, check and see if we're printing the scanning graphic and print it

    if (scanning==1){
      
    
      lcd.setCursor(0,0);
      lcd.print((myString2)[j]);
      if(j==2){
        if(numbers==1){
            
        }
        else if (numbers==0){
        
        }
      }
      j++;
      if(j>=8){
        j=0;
      }
    }
    
    if (scanning==2){
          
        
          lcd.setCursor(0,0);
          lcd.print((myString3)[j]);
          j++;
          if(j>=8){
            j=0;
          }
        }

 }



//The last part of the program is just printing the bottom line text in each mode



 //check and see if it's time to print a bottom line
 if (millis() % (200 *mySpeed) ==0){

// if so, check and see if we're printing pke numbers, and if so, print them!

    if(numbers==1){
      lcd.setCursor(15,1);
      lcd.print("%");
      lcd.setCursor(10,1);
      
      //this part generates the numbers for the pke meter
      float pke= (millis()*.00007);
      pke = sin(pke)*100;
      pke = map(pke, -99, 100, 6802, 9834);
      pke = pke*.01;
  
      float pkeMult= (millis()*.00003);
      pkeMult = sin(pkeMult+60)*100;
      pkeMult = map(pkeMult, -99, 100, 20, 100);
      pkeMult = pkeMult*.01;
      
      lcd.print(pke*pkeMult);
      pkeInt = (pke*pkeMult);

    }

  //if we're not printing numbers, get the appropriate message from the string array at the top, and print it
    else if (numbers==0){
      if(typing==0){
        lcd.setCursor(0,1);
        lcd.print((myString1)[i+b]);
        i++;
        if(i>=10){
          i=0;
        }
      }
      else if (typing==1){
        String thisLine = ((myString1)[i+b]);
        i++;
        if(i>=10){
          i=0;
        }
        
        lcd.setCursor(0,1);
        lcd.print("                ");
        for (int d = 0; d<=15; d++){
          lcd.cursor();
          lcd.setCursor(d,1);
          delay(100);
          lcd.print((thisLine.substring(d,d+1)));
           lcd.noCursor();

  

          
        }
        
      }
      }
    }
}