This menu sketch compiles but does not run

Greetings, I used this code by Dan Hostler and modified it to work with my Seeeduino XIAO and SSD1306 OLED display. Obviously, I am in dire need of some assistance as the code compiles but does not "run." As I am really just a hack/noob, I cannot trace the program sufficiently enough to find my error(s). I hope to get this core sketch functional so that I may populate it with a project of mine requiring a menu driven interface.

My deepest appreciation in advance to anyone who may be able to look over this code and point out to me what I am missing.

Respectfully - Baran

// Program written by Dan Hostler, October 2020.
// Feel free to use as you need to.
// PayPal donations appreciated at danhostler1985@yahoo.com

// I tried to Modify this sketch to "work" with a Seeeduino XIAO microprocessor and an SSD1306 display.
// by changing references from the LCD display to my OLED display and reducing strings to 10 characters.  

// LIBRARIES
#include "I2Cdev.h"                           // Used in my main program to control the I2C communications
                                              // My SSD1306 is an I2C display
#include <Wire.h>                             // deals with I2C connections as the sketch grows.
#include <Adafruit_GFX.h>                     // Calls up the OLED graphics folder.
#include <Adafruit_SSD1306.h>  // Calls up the OLED display folder. 


//DISPLAY SETUP
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 32
#define OLED_RESET -1                         
Adafruit_SSD1306 display(OLED_RESET);
#define LOGO16_GLCD_HEIGHT 32                  // Sets the display to 032 bits high
#define LOGO16_GLCD_WIDTH  128                 // Sets the display to 128 bits long

void i2cSetup() {
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
 { Wire.begin();}
#elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
{ Fastwire::setup(400, true);}
#endif
}


// MENU ARRAYS
String menuOption[] = {{"Setting 1"}, {"Setting 2"}, {"Setting 3"}, {"Setting 4"}, {"Setting 5"}};       // Text on the top line
String measurementType[] = {{"[DEG. FAHR]"}, {"[DEG. CEL]"}, {"[POUNDS]"}, {"[INCHES]"}, {"[MPH]"}};  // Text on the bottom line

// I/O PINS ON THE XIAO SEEEDUINO.
// MAKE THESE "CONST INT" VARIABLES AS THESE DO NOT CHANGE IN THE PROGRAM.
const int leftButtonPin = 3;       // Pin 3 for "Left" command
const int rightButtonPin = 6;      // Pin 6 for "Right" command
const int upButtonPin = 10;         // Pin 10 for "Up" command
const int downButtonPin = 8;       // Pin 8 for "Down" command
const int enterButtonPin = 9;      // Pin 9 for "Enter" command

// NUMBER COUNT OF BUTTON PRESSES AND COUNTER UNITS.
// MAKE THESE A "INT" VARIABLES TO ALLOW FOR NEGATIVE INTEGERS.
int setting1Counter = 0;    // Counters for settings 1 - 5
int setting2Counter = 0;
int setting3Counter = 0;
int setting4Counter = 0;
int setting5Counter = 0;
int directionPush = 0;      // This counter changes the menu option with each "left" or "right" button push.
int upPressCount = 0;       // This counter measures the amount of times the user pushes the "up" button.
int downPressCount = 0;     // This counter measures the amount of times the user pushes the "down" button.

// BUTTON PRESS STATES FOR EACH FUNCTION, ALL SET TO "LOW".
// MAKE THESE "BOOLEAN" VARIABLES AS THESE ONLY WILL BE "HIGH" OR "LOW".
boolean buttonStateLeft = LOW;            // Button states for the "Left" command
boolean lastButtonStateLeft = LOW;                
boolean currentButtonStateLeft = LOW;
boolean buttonStateRight = LOW;           // Button states for the "Right" command
boolean lastButtonStateRight = LOW;                
boolean currentButtonStateRight = LOW;
boolean buttonStateUp = LOW;              // Button states for the "Up" command
boolean lastButtonStateUp = LOW;                
boolean currentButtonStateUp = LOW;
boolean buttonStateDown = LOW;            // Button states for the "Down" command
boolean lastButtonStateDown = LOW;                
boolean currentButtonStateDown = LOW; 
boolean buttonStateEnter = LOW;           // Button states for the "Enter" command
boolean lastButtonStateEnter = LOW;                
boolean currentButtonStateEnter = LOW;


// DEBOUNCE VARIABLES TO MEASURE THE DEBOUNCING TIME OF A BUTTON PUSH.
// MAKE THESE "UNSIGNED LONG" VARIABLES AS THE NUMERICAL VALUE WILL HAVE AN EXTENDED SIZE.
unsigned long lastDebounceTime = 0;       // This variable takes a "snapshot" of time when any button is pushed.
unsigned long debounceDelay = 50;         // Delay time in milliseconds; the amount of time the button is pressed must be higher than the delay to register a push

// SETUP
void setup() {

  Serial.begin(115200);             //SET THE BAUD RATE AT 115200
  i2cSetup();
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C); 

  pinMode(leftButtonPin, INPUT);    // SETS THE leftButtonPin AS AN INPUT
  pinMode(rightButtonPin, INPUT);   // SETS THE rightButtonPin AS AN INPUT
  pinMode(upButtonPin, INPUT);      // SETS THE upButtonPin AS AN INPUT
  pinMode(downButtonPin, INPUT);    // SETS THE downButtonPin AS AN INPUT
  pinMode(enterButtonPin, INPUT);   // SETS THE enterButtonPin AS AN INPUT

  delay(1000);                      // I do not know why there is a delay here . . .

}



// MAIN LOOP
void loop() {

  int unitSetting[] = {setting1Counter, setting2Counter, setting3Counter, setting4Counter, setting5Counter};    // This variable holds the individual counters in one array
  
  display.setCursor(0,0);                           // Menu displayed on the LCD.
  display.println(menuOption[directionPush]);         // The menuOption that is displayed is determined by the left or right push.
  display.setCursor(0,1);    
  display.println(unitSetting[directionPush]);        // The setting counter that is displayed is determined by the left or right push.
  display.setCursor(5,1);                           // This cursor setting fixes the measurementType in one place, preventing offset
  display.println(measurementType[directionPush]);    // by the unitSetting.


  // The program at this point is waiting for a button press.
  currentButtonStateLeft = digitalRead(leftButtonPin);          
  currentButtonStateRight = digitalRead(rightButtonPin); 
  currentButtonStateUp = digitalRead(upButtonPin);          
  currentButtonStateDown = digitalRead(downButtonPin);    
  currentButtonStateEnter = digitalRead(enterButtonPin);   
  
  if (currentButtonStateLeft != lastButtonStateLeft || currentButtonStateRight != lastButtonStateRight || 
  currentButtonStateUp != lastButtonStateUp || currentButtonStateDown != lastButtonStateDown || currentButtonStateEnter != lastButtonStateEnter)        
  // If there is a button push on any of the buttons, the following routine runs to check if it was a valid press:
  {
  lastDebounceTime = millis();      // lastDebounceTime is set equal to the running millis() function.
  }  

  if ((millis() - lastDebounceTime) > debounceDelay)   
  // If the lastDebounceTime (aka. the "snapshot" time) minus the running millis() function is higher than the set debounce delay, the following routine
  // below runs and checks which button was pushed: 
  {                                             

    // The current state for each button is set not equal to the pressed state and when it changes, the pressed state becomes equal to the current state.
    
    // LEFT BUTTON PRESS
    if (currentButtonStateLeft != buttonStateLeft)       // Left button scrolls the menu options to the left.  
    { 
    buttonStateLeft = currentButtonStateLeft;  
                 
      if (buttonStateLeft == LOW)                        // Once the button is released, the push is registered and the code below runs.
      {                                                 
      directionPush--;                                   // Both the up and down press counts will be reset to zero when the left button is pushed.
      upPressCount = 0;
      downPressCount = 0;
      }
          
        if (directionPush < 0)                           // If the user tries to scroll below the first menu option,
        {                                                // the program will loop back to the last menu option.
        directionPush = 4;
        }
    display.clearDisplay();    
    }

    // RIGHT BUTTON PRESS
    if (currentButtonStateRight != buttonStateRight)     // Right button scrolls the menu options to the right.    
    { 
    buttonStateRight = currentButtonStateRight;  
                 
      if (buttonStateRight == LOW)                         
      {                                                 
      directionPush++;                                   // Both the up and down press counts will be reset to zero when the right button is pushed.
      upPressCount = 0;
      downPressCount = 0;
      }
  
        if (directionPush > 4)                           // If the user tries to scroll above the last menu option,
        {                                                // the program will loop back to the first menu option.
        directionPush = 0;
        }
    display.clearDisplay();
    }

    // UP BUTTON PRESS
    if (currentButtonStateUp != buttonStateUp)           // Up button scrolls the setting upward. 
    { 
    buttonStateUp = currentButtonStateUp;  
                 
      if (buttonStateUp == LOW && directionPush == 0)    // The first 5 times in which the "up" button is pushed, each push will add 1 increment to the setting.                       
      {                
      upPressCount++;     
      downPressCount = 0;                                // The downPressCount is reset to zero.    
      setting1Counter++;

        if (upPressCount > 5)                            // If the "up" button is pushed more than 5 times consecutively, the setting increment increases by 5
        {                                                // with every "up" button push and resets back when the down, left or right button is pushed.
        setting1Counter = setting1Counter + 4;
        }

        if (setting1Counter > 999)                       // Sets the setting counter limit to 999. The user cannot increase the counter beyond 999.
        {
        setting1Counter = 999;
        }
      }  
      
      if (buttonStateUp == LOW && directionPush == 1)                         
      {            
      upPressCount++;     
      downPressCount = 0;                                             
      setting2Counter++;

        if (upPressCount > 5)
        {
        setting2Counter = setting2Counter + 4;
        }

        if (setting2Counter > 999)                       // Sets the setting counter limit to 999. The user cannot increase the counter beyond 999.
        {
        setting2Counter = 999;
        }
      }  

      if (buttonStateUp == LOW && directionPush == 2)                         
      {     
      upPressCount++;     
      downPressCount = 0;                                                     
      setting3Counter++;

        if (upPressCount > 5)
        {
        setting3Counter = setting3Counter + 4;
        }

        if (setting3Counter > 999)                       // Sets the setting counter limit to 999. The user cannot increase the counter beyond 999.
        {
        setting3Counter = 999;
        }
      }  

      if (buttonStateUp == LOW && directionPush == 3)                         
      { 
      upPressCount++;     
      downPressCount = 0;                                                         
      setting4Counter++;

        if (upPressCount > 5)
        {
        setting4Counter = setting4Counter + 4;
        }

        if (setting4Counter > 999)                       // Sets the setting counter limit to 999. The user cannot increase the counter beyond 999.
        {
        setting4Counter = 999;
        }
      }  

      if (buttonStateUp == LOW && directionPush == 4)                         
      {    
      upPressCount++;     
      downPressCount = 0;                                                      
      setting5Counter++;

        if (upPressCount > 5)
        {
        setting5Counter = setting5Counter + 4;
        }

        if (setting5Counter > 999)                       // Sets the setting counter limit to 999. The user cannot increase the counter beyond 999.
        {
        setting5Counter = 999;
        }
      }  
    display.clearDisplay();  
    }


    // DOWN BUTTON PRESS
    if (currentButtonStateDown != buttonStateDown)        // Down button scrolls the setting downward.
    { 
    buttonStateDown = currentButtonStateDown;  
                 
      if (buttonStateDown == LOW && directionPush == 0)   // The first 5 times in which the "down" button is pushed, each push will subtract 1 increment to the setting.                      
      {                      
      downPressCount++;
      upPressCount = 0;                                   // The upPressCount is reset to zero.
      setting1Counter--;

        if (downPressCount > 5)                           // If the "down" button is pushed more than 5 times consecutively, the setting increment decreases by 5
        {                                                 // with every "down" button push and resets back when the up, left or right button is pushed.
        setting1Counter = setting1Counter - 4;
        }

        if (setting1Counter < -999)                       // Sets the setting counter limit to -999. The user cannot increase the counter beyond -999.
        {
        setting1Counter = -999;
        }
      }  

      if (buttonStateDown == LOW && directionPush == 1)                         
      {              
      downPressCount++;
      upPressCount = 0;                                         
      setting2Counter--;

        if (downPressCount > 5)
        {
        setting2Counter = setting2Counter - 4;
        }

        if (setting2Counter < -999)                       // Sets the setting counter limit to -999. The user cannot decrease the counter beyond -999.
        {
        setting2Counter = -999;
        }
      }  

      if (buttonStateDown == LOW && directionPush == 2)                         
      {     
      downPressCount++;
      upPressCount = 0;                                                     
      setting3Counter--;

        if (downPressCount > 5)
        {
        setting3Counter = setting3Counter - 4;
        }
      
        if (setting3Counter < 0)    // This code prevents the user from entering
        {                           // a number below "0".
        setting3Counter = 0;        // Remove this code if you want to allow in
        }                           // negative numbers on a setting.    
      }  

      if (buttonStateDown == LOW && directionPush == 3)                         
      {                          
      downPressCount++;
      upPressCount = 0;                                
      setting4Counter--;

        if (downPressCount > 5)
        {
        setting4Counter = setting4Counter - 4;
        }
      
        if (setting4Counter < 0)    // This code prevents the user from entering
        {                           // a number below "0".
        setting4Counter = 0;        // Remove this code if you want to allow in
        }                           // negative numbers on a setting.
      }  

      if (buttonStateDown == LOW && directionPush == 4)                         
      {                        
      downPressCount++;
      upPressCount = 0;                                  
      setting5Counter--;

        if (downPressCount > 5)
        {
        setting5Counter = setting5Counter - 4;
        }
      
        if (setting5Counter < 0)    // This code prevents the user from entering
        {                           // a number below "0".
        setting5Counter = 0;        // Remove this code if you want to allow in
        }                           // negative numbers on a setting.
      }  
      
    display.clearDisplay();
    }
     
  }  


    // ENTER BUTTON PRESS
    if (currentButtonStateEnter != buttonStateEnter)        
    { 
    buttonStateEnter = currentButtonStateEnter;  
                 
      if (buttonStateEnter == LOW && directionPush == 0)      // The Enter button simply enters the setting and flashes a brief message.                         
      {                                                       // Please feel free to expand on this code to add more functions.
      display.clearDisplay();
      display.setCursor(0,0); 
      display.println("DEGREES F.");
      display.setCursor(0,1);
      display.println("ENTERED");
      delay(2000); 
      }  

      if (buttonStateEnter == LOW && directionPush == 1)                         
      {                                                       
      display.clearDisplay();
      display.setCursor(0,0); 
      display.println("DEGREES C.");
      display.setCursor(0,1);
      display.println("ENTERED");
      delay(2000);
      }  

      if (buttonStateEnter == LOW && directionPush == 2)                         
      {                                                       
      display.clearDisplay();
      display.setCursor(0,0); 
      display.println("LBS WEIGHT");
      display.setCursor(0,1);
      display.println("ENTERED");
      delay(2000);
      }  

      if (buttonStateEnter == LOW && directionPush == 3)                         
      {                                                       
      display.clearDisplay();
      display.setCursor(0,0); 
      display.println("INCHES");
      display.setCursor(0,1);
      display.println("ENTERED");
      delay(2000);
      }  

      if (buttonStateEnter == LOW && directionPush == 4)                         
      {                                                       
      display.clearDisplay();
      display.setCursor(0,0); 
      display.println("MILES/HOUR");
      display.setCursor(0,1);
      display.println("ENTERED");
      delay(2000);
      }  
    display.clearDisplay();
    }


  // After a button is pushed and the count recorded, all the states reset back to LOW for the data to be processed correctly.
  lastButtonStateLeft = currentButtonStateLeft;       // resets the left button state to LOW
  lastButtonStateRight = currentButtonStateRight;     // resets the right button state to LOW
  lastButtonStateUp = currentButtonStateUp;           // resets the up button state to LOW
  lastButtonStateDown = currentButtonStateDown;       // resets the down button state to LOW
  lastButtonStateEnter = currentButtonStateEnter;     // resets the enter button state to LOW
  
}

Explain WHAT is not working, and how it SHOULD work. Also post your schematic.

1 Like

supplying a link to the code source and schematic will also help but you need to post your schematic as you have wired it, preferably in schematic form, not frizzy pictures. Be sure to show all connections.

I will do my best with the limited information I have. As I said, this sketch was designed by someone else who is credited in the comments s3ction. He designed it as a menu object that could be populated by someone else for specific purposes. What is NOT working is the sketch. How can I best describe a setup that fails to light up the display or respond to any switch prompts except to say that it "does not work." What does not work? EVERYTHING!!! How it should work is that the strings in quotes in display.print statements should show up on the display based upon the positioning of the 5-way-switch. Something, anything would be great. If it displayed something, I could troubleshoot it. As it is, I am relying on a coding expert who can look this over and find a logical error or omission of some kind.

I am attaching the schematic you requested in the hope that you may be able to help me. All it is here for is to verify my pinouts as called in the sketch. It is actually a redacted pictorial showing the wiring of the requisite parts.

I would be happy if I could see any kind of output on my SSD1306. If I did, as I said, I can troubleshoot but I do not have the skill to find my error. All those display.print statements and the program never gets around to even one.
Pictorial_Layout_5-way Switch Menu.pdf (1.8 MB)

well start by discovering if you can print something at the display. is the address correct ? 0x3C ? use any basic example sketch just to print. then if that works , compare to your sketch.

I apologize for offering a format that you disapprove of. As my "frizzy picture" shows EVERY connection point, there is absolutely NO DIFFERENCE between the information offered by my image or a schematic. Would you have me rewrite the schematic for your benefit at the risk of making, yet, another mistake? What is posted is what is sitting on my breadboard at the moment.

My problem is NOT a wiring issue, it is a coding issue. The "frizzy picture" PDF is the basis of many of my display projects and the wiring is solid, sound, and correct. Again, the schematic is just to show you that I am using the same pins for inputs that I call-out in my code.

So far, I have posted a complete code and received two replies - neither having to do with my issue but both "picking" on me for not providing the information in a way that they like. I doubt either will actually provide me any assistance, although I would be grateful for it.

Is there not a code expert or moderator out there who understands C++ code enough to simply look over the code and "see" the problem? I can find little errors like missing terminators or semi-colons but I am a beginner. Surely, there is someone who can read code like reading a newspaper and say "Oh, here's your problem?" I am not asking for someone to "FIX" my code, only to tell me why I have no text or strings displayed on my SSD1306. Please, someone, just throw me a bone and I will make my own soup but please stop demanding that I bend over backwards to provide redundant information that is not related to my issue.

Basically because we cant answer that.... For example u miss the address 0x3C on the oled ant it wont work....it will compile but wont work....
The idea is not asking for a working answer but asking for help in simple steps... For example u did not mention if u ever made one of the example sketches on the oled... Make simple stuff that works before diving deep.

I think the (0x3c) address issue may be a cue. I am used to I2C simply taking care of its own addressing , and there is no address reference in my working examples of other sketches using the SSD1306. This is the most reasonable issue - it is sending the display issue to the wrong address. Thank You!

1 Like

divide and you conquer ! plus.. when you divide we help you throughout...

Yes this is better than most frizzy pictures but where are the I2C pull up resistors? What do the dashed lines on the battery indicate? Your voltage range for the battery does not appear correct and I believe the part it connects to does not support a 5V input. Posting links to technical information for the hardware devices also helps. Also NOTE your "schematic" was not posted when I commented on your question also I am not the only one to ask for a schematic. Yes I and many others prefer schematics not frizzy pictures.

Got it! I am not presenting what you think is best but you are not even willing to look at my code so WTF, gilshultz? I am 62-years-old and I was probably drawing schematics before you were born. I prefer "Frizzy Pictures" as they give infinitely more information than a schematic, given what was included. Yeah, I left some stuff off but I wrote it in haste for THIS GROUP so I might get some help - I didn't!

I have never used pullup resistors for the I2C lines and never had problems - that's why they are missing. The battery is 3.7 VDC, regulated to 3.3 vdc (sorry, not shown) and all of the circuitry is 3.3 volts. GAWD, you want links to the devices in my frizzy picture and you won't even give my code the frickin' time of day? Does "anal-retentive" have a hyphen? (It does!)

So, IMHO, all you have asked for is an entire waste of my time and you have lent none of your time to me (at least until I jump through your hoops and I am sick of this mentality of "experts" (or not!) picking apart my request and making it difficult for me to get help. This is a coding forum, NOT a hardware forum. I told you repeatedly that the circuit I am using has served me more than once in the past. That should have been the end of the schematic/hardware request and the beginning of a conversation about my code, because that I what I was seeking.

I have seen this many times in the past where someone does not submit something just right and one or more of you jump on his or her ass when, often, what is being supplied is more than enough to solve the issue. Case in point: After all of these insipid conversations and back and forth about schematics and hardware, I found the (super simple) problem myself. Every group of lines of display code requires
a < display.display(); > line of code following it. I inserted that code and everything is working fine, now.

Well, YOU do! See my other contributor's points of view. The address was not the issue, rather, I neglected to follow groups of display code with the necessary line
< display.display(); > to initialize the supporting Adafruit library.

I was a stupid mistake, one of neglect, not logic or punctuation. Thanks for your support.

Sorry I was driving before you were a glint in your parents eye. You should look at the I2C specifications you will see why I recommend resistors. My recommendation is to take an anger management class.

1 Like

WOW @RamDog - You are a bit self entitled for someone looking for FREE support from voluteers! I suggest you never come back here with that attitude. Change it and you would be welcome.

Why do we ask for :
Schematic rather than fritzing diagrams - It's easier to follow a schematic & often in the process of making th eschematic, a missing or incorrect connection if found by the OP
Full Code - So many reasons (Out of scope variables, incorrect data types, missing function calls . . . )
Datasheets or links to items : Assumptions on hardware is not something most of us will do here, while you may think you know the device, there may be something we can see that you may have missed, or the device ay not operate how you expect.

As a rule, if this information is not presented correctly, I won't even look at the post. Without this information, most responses I would give would be guesses, and may even be dangerous to you or your device.

2 Likes

A useful approach to debugging such situations is to show the original code, and show the modifications you made.

If you treat a lot of programming as a huge game of spot-the-difference, you won't go far wrong.
There are even nifty tools to highlight the differences.

2 Likes

I understand your frustration. it happened to all of us. But I insist like i said. If u would have implemented a simple display example working sketch you wouldnt be were u are right now. How can u expect people will know libraries implementation function types arguments at first hand?

My second advice not being mad with u is why u dont program in assembler??? U wont need support from anyone. .....think about it. sometimes these high level programming approaches just make your living insipid like this...

1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.