Button declared but stating Button isn't declared

I am not too sure what is wrong but I whenever I try to compile my code its says that B2utton is not delcared in this scope" when as far as i can tell it is declared in the scope. and it is declared before any functions. but I am still new and am at the moment guessing i have made a rooky mistake somewhere and wanted to get some other eyes on it to help me see my potential mistakes.

here is my code. for reference i am trying to create a lcd dashboard that measures a vehicles RPM, Coolant temp and gear through CANbus and also to run a clock that uses the inbuilt RTC RAM. the idea is to bring it in and out of deep sleep mode rather than just turning it off and on again cause i want the RTC to keep the time rather than reset each time it comes "on".

thank you

#include <Wire.h>
#include <LiquidCrystal.h>
#include <driver/twai.h>
//#include <OneWire.h>
//#include <DallasTemperature.h>
#include <esp_sleep.h>
#include <time.h>


#define LCD_RS 13
#define LCD_EN 10
#define LCD_D4 8
#define LCD_D5 6
#define LCD_D6 4
#define LCD_D7 2

#define BTN1_PIN 40
#define BTN2_PIN 38

#define ACC_PIN 1

#define CAN_TX 36
#define CAN_RX 17

static bool editModeEntered = false;
bool inClockEditMode = false;
bool editingHours = true;
int currenthour = 0, currentminute = 0;
bool blinkState = true;
unsigned long lastBlinkTime = 0;
const unsigned long blinkInterval = 500;

unsigned long lastAccCheck = 0;
const unsigned long accDebounceTime = 1000; //milliseconds

int editHour = 0;
int editMinute = 0;

int gearValue = -1;
int rpmValue = 0;
int coolantTemp = 0;

RTC_DATA_ATTR int bootCount = 0;

bool lastAccState = HIGH;
unsigned long accLastChangeTime = 0;

bool isAccStableLow() {
  bool reading = digitalRead(ACC_PIN);

  if (reading != lastAccState) {
    accLastChangeTime = millis();
    lastAccState = reading;
  }
  
  return (reading == LOW && (millis() - accLastChangeTime) > 1000);
}

struct Button {
  uint8_t pin;
  bool lastState = HIGH;
  unsigned long lastDebounceTime = 0;
  const unsigned long debounceDelay = 50;
};

Button btn1 = {BTN1_PIN};
Button btn2 = {BTN2_PIN};

bool checkButton(Button &btn) {
  bool reading = digitalRead(btn.pin);

  if (reading != btn.lastState) {
    btn.lastDebounceTime = millis();
  }

  if((millis() - btn.lastDebounceTime) > btn.debounceDelay) {
    if (reading == LOW && btn.lastState == HIGH) {
      btn.lastState = reading;
      return true;
    }
  }

  btn.lastState = reading;
  return false;
}

void iniTime() {
  configTime(0, 0, NULL);
}

LiquidCrystal lcd(LCD_RS, LCD_EN, LCD_D4, LCD_D5, LCD_D6, LCD_D7);

void initCAN() {
  twai_general_config_t g_config = TWAI_GENERAL_CONFIG_DEFAULT((gpio_num_t)CAN_RX, (gpio_num_t)CAN_TX, TWAI_MODE_NORMAL);
  twai_timing_config_t t_config = TWAI_TIMING_CONFIG_500KBITS();
  twai_filter_config_t f_config = TWAI_FILTER_CONFIG_ACCEPT_ALL();

  if (twai_driver_install(&g_config, &t_config, &f_config) == ESP_OK) {
    twai_start();
  } else {
    lcd.setCursor(0, 1);
    lcd.print("CAN init failed");
  }
}

void prepareForSleep() {
  esp_sleep_enable_ext0_wakeup((gpio_num_t)ACC_PIN, 1);
  esp_deep_sleep_start();
}


void enterClockEditMode() {
  struct tm timeinfo;
  getLocalTime(&timeinfo);
  editHour = timeinfo.tm_hour;
  editMinute = timeinfo.tm_min;

  if (!getLocalTime(&timeinfo)) {
    Serial.println("Failed to obtain time");
}

  inClockEditMode = true;
  editingHours = true;
  blinkState = true;
  lastBlinkTime = millis();
}

void handleClockEdit() {
  if (millis() - lastBlinkTime > blinkInterval) {
    blinkState = !blinkState;
    lastBlinkTime = millis();
  }

  if (checkButton(btn1)) {
    if (editingHours) editHour = (editHour + 1) % 24;
    else editMinute = (editMinute + 1) % 60;
  }

  if (checkButton(btn2)) {
    if (editingHours) editHour = (editHour + 23) % 24;
    else editMinute = (editMinute + 59) % 60;
  }

  bool b1 = checkButton(btn1);
bool b2 = checkButton(btn2);

if (b1 && b2) {
  if (editingHours) {
    editingHours = false;
  } else {
    setClock(editHour, editMinute);
    inClockEditMode = false;
  }
}


  displayClockEdit(); 

}

void setClock(int hour, int minute) {
  struct tm t;
  getLocalTime(&t);
  
  t.tm_hour = hour;
  t.tm_min = minute;
  t.tm_sec = 0;

  time_t newTime = mktime(&t);
  struct timeval now = { .tv_sec = newTime };
  settimeofday(&now, NULL);
  
}

void displayClockEdit() {
  lcd.setCursor(0, 1);
  if (editingHours) {
    if (blinkState) lcd.print("  ");
    else lcd.print((editHour < 10 ? "0" : "") + String(editHour));
    lcd.print(":");
    lcd.print((editMinute < 10 ? "0" : "") + String(editMinute));
  } else {
    lcd.print((editHour < 10 ? "0" : "") + String(editHour));
    lcd.print(":");
    if (blinkState) lcd.print("  ");
    else lcd.print((editMinute < 10 ? "0" : "") + String(editMinute));
  }

}

/*void checkCANMessages() {
  twai_message_t message;

  while (twai_receive(&message, 0) == ESP_OK) {
    if (message.identifier == 0x312 && message.data_length_code >=4 && message.data[0] == 0x00 && message.data[1] == 0x00) {

      gearValue = message.data[3];

    }

    rpmValue = 1234;
    coolantTemp = 85;
  }
}*/

/*void readCAN() {

  twai_message_t message;

  while(twai_receive(&message, 0) == ESP_OK) {
    if (message.identifier == 0x312 && message.data_length_code >= 3) {
      uint8_t pid = message.data[2];

      if (pid == 0x05) {
        coolantTemp = message.data[3] - 40;
      } else if (pid == 0x0C && message.data_length_code >= 5) {
        rpmValue = ((message.data[3] << 8) | message.data[4]) / 4;
      }
    }
  }
}*/

void readCAN() {
  twai_message_t message;

  while (twai_receive(&message, 0) == ESP_OK) {
    if (message.identifier == 0x312) {
      if (message.data_length_code >= 4 && message.data[0] == 0x00 && message.data[1] == 0x00) {
        gearValue = message.data[3];
      }

      if (message.data_length_code >= 3) {
        uint8_t pid = message.data[2];

        if (pid == 0x05 && message.data_length_code >= 4) {
          coolantTemp = message.data[3] - 40;
        } else if ( pid == 0x0C && message.data_length_code >= 5) {
          rpmValue = ((message.data[3] << 8) | message.data[4]) / 4;
        }
      }
    }
  }
}

void updateLCD(int hour, int minute) {
  // Gear display
  lcd.setCursor(0, 0);
  lcd.print("Gear: ");
  if (gearValue >= 0 && gearValue <= 9) {
    lcd.print(gearValue);
    lcd.print("  "); // Clear potential leftover digits
  } else {
    lcd.print("--  "); // Unknown or invalid gear
  }

  // Coolant Temp
  lcd.setCursor(10, 0);
  lcd.print("CT:");
  if (coolantTemp >= -40 && coolantTemp <= 150) {
    if (coolantTemp < 10) lcd.print(" "); // Padding for 1-digit temps
    lcd.print(coolantTemp);
    lcd.print(" "); // Clear trailing digit if temp drops from 3 digits to 2
  } else {
    lcd.print("-- ");
  }

  // Time display
  lcd.setCursor(0, 1);
  if (hour < 10) lcd.print("0");
  lcd.print(hour);
  lcd.print(":");
  if (minute < 10) lcd.print("0");
  lcd.print(minute);

  // RPM display (right side of line 2)
  lcd.setCursor(9, 1);
  lcd.print("RPM:");
  if (rpmValue >= 0 && rpmValue <= 9999) {
    char rpmStr[6];  // "9999\0"
    snprintf(rpmStr, sizeof(rpmStr), "%-4d  ", rpmValue); // left-align with padding
    lcd.print(rpmStr);
  } else {
    lcd.print("----");
  }
}

void setup() {
  Serial.begin(115200); //for debugging into the serial display

  //initializing the LCD screen.
  lcd.begin(16, 2);
  lcd.setCursor(0, 0);
  lcd.print("Initizializing...");

  // set up the pin modes for the buttons.
  pinMode(BTN1_PIN, INPUT_PULLDOWN);
  pinMode(BTN2_PIN, INPUT_PULLDOWN);
  pinMode(ACC_PIN, INPUT);

  //setting up initial button states.
  btn1.lastState = digitalRead(BTN1_PIN);
  btn2.lastState = digitalRead(BTN2_PIN);

  // initialize the RTC with the inbuilt RTC ram
  configTime(0, 0, NULL);

  //boot counter
  bootCount++;

  //check ACC state
  if (isAccStableLow()) {
    prepareForSleep(); //sends the controller to sleep if the ACC pin is LOW
  }

  initCAN();

  lastAccState = digitalRead(ACC_PIN);

  delay(1000);
  lcd.clear();

}

void loop() {
  if(isAccStableLow()) {
    prepareForSleep();
  }

  /*if (checkButton(btn1) && checkButton(btn2)) {
    enterClockEditMode();
  }*/

  if (!editModeEntered && digitalRead(BTN1_PIN) == LOW && digitalRead(BTN2_PIN) == LOW) {
    enterClockEditMode();
    editModeEntered = true;
  } else if (digitalRead(BTN1_PIN) == HIGH || digitalRead(BTN2_PIN) == HIGH) {
    editModeEntered = false;
  }

  if (inClockEditMode) {
    handleClockEdit();
    return;
  }

  struct tm timeinfo;
  getLocalTime(&timeinfo);
  currenthour = timeinfo.tm_hour;
  currentminute = timeinfo.tm_min;

  //checkCANMessages();

  readCAN();

  updateLCD(currenthour, currentminute);
}


Welcome to the forum

As your topic does not relate directly to the installation or operation of the IDE it has been moved to the Programming category of the forum

Please post the full error message, using code tags when you do

This is the full Error code i get

C:\Users\User1\OneDrive\Documents\Arduino\lcd_trial_RTC_clock_button_2_\lcd_trial_RTC_clock_button_2_.ino:69:18: error: 'Button' was not declared in this scope
   69 | bool checkButton(Button &btn) {
      |                  ^~~~~~
C:\Users\User1\OneDrive\Documents\Arduino\lcd_trial_RTC_clock_button_2_\lcd_trial_RTC_clock_button_2_.ino:69:26: error: 'btn' was not declared in this scope
   69 | bool checkButton(Button &btn) {
      |                          ^~~
C:\Users\User1\OneDrive\Documents\Arduino\lcd_trial_RTC_clock_button_2_\lcd_trial_RTC_clock_button_2_.ino:69:29: error: 'bool checkButton(Button&)' redeclared as different kind of entity
   69 | bool checkButton(Button &btn) {
      |                             ^
C:\Users\User1\OneDrive\Documents\Arduino\lcd_trial_RTC_clock_button_2_\lcd_trial_RTC_clock_button_2_.ino:69:6: note: previous declaration 'bool checkButton'
   69 | bool checkButton(Button &btn) {
      |      ^~~~~~~~~~~
C:\Users\User1\OneDrive\Documents\Arduino\lcd_trial_RTC_clock_button_2_\lcd_trial_RTC_clock_button_2_.ino: In function 'void handleClockEdit()':
C:\Users\User1\OneDrive\Documents\Arduino\lcd_trial_RTC_clock_button_2_\lcd_trial_RTC_clock_button_2_.ino:134:18: error: 'checkButton' cannot be used as a function
  134 |   if (checkButton(btn1)) {
      |       ~~~~~~~~~~~^~~~~~
C:\Users\User1\OneDrive\Documents\Arduino\lcd_trial_RTC_clock_button_2_\lcd_trial_RTC_clock_button_2_.ino:139:18: error: 'checkButton' cannot be used as a function
  139 |   if (checkButton(btn2)) {
      |       ~~~~~~~~~~~^~~~~~
C:\Users\User1\OneDrive\Documents\Arduino\lcd_trial_RTC_clock_button_2_\lcd_trial_RTC_clock_button_2_.ino:144:24: error: 'checkButton' cannot be used as a function
  144 |   bool b1 = checkButton(btn1);
      |             ~~~~~~~~~~~^~~~~~
C:\Users\User1\OneDrive\Documents\Arduino\lcd_trial_RTC_clock_button_2_\lcd_trial_RTC_clock_button_2_.ino:145:22: error: 'checkButton' cannot be used as a function
  145 | bool b2 = checkButton(btn2);
      |           ~~~~~~~~~~~^~~~~~
exit status 1

Compilation error: 'Button' was not declared in this scope

try
(why are you defining initial values in the struct)?

struct Button {
    uint8_t             pin;
    bool                lastState;
    unsigned long       lastDebounceTime;
    const unsigned long debounceDelay;
};


Button btn1 = { BTN1_PIN, HIGH, 0, 50 };

Use a better constructor, just declare the variables then set the pin from setup():

struct Button {
  uint8_t pin;
  bool lastState = HIGH;
  unsigned long lastDebounceTime = 0;
  const unsigned long debounceDelay = 50;
};

Button btn1;
Button btn2;
...
void setup() {
  Serial.begin(115200); //for debugging into the serial display

  // set up the pin modes for the buttons.
  pinMode(BTN1_PIN, INPUT_PULLDOWN);
  pinMode(BTN2_PIN, INPUT_PULLDOWN);
  pinMode(ACC_PIN, INPUT);

  btn1.pin = BTN1_PIN;
  btn2.pin = BTN2_PIN;

I would make the const data member static and then no matter how many buttons get declared there is only one static value saved.

It's been so many years since I wrote serious C++ that I can't say I have the syntax down, some other member should check this as to initializing the value... I can't see initializing a const during runtime.

compiled ok on my laptop

#include <stdint.h>

#define BTN1_PIN 40
#define BTN2_PIN 38

struct Button {
    uint8_t             pin;
    bool                lastState;
    unsigned long       lastDebounceTime = 0;
    const unsigned long debounceDelay = 50;
};


Button btn1 = { BTN1_PIN };
Button btn2 = { BTN2_PIN, 1, 50 };

bool checkButton(Button &btn) {
    return btn.lastDebounceTime == btn.debounceDelay;
}

#include <stdio.h>

int
main ()
{
    printf (" %s\n", checkButton (btn1) ? "true" : "false");
    printf (" %s\n", checkButton (btn2) ? "true" : "false");
    return 0;
}

Right, and you can't change the fourth item. IDK why you'd set the last debounce time other than to show you can.

20th century C did not have static struct members, it would have been an error to say you wanted.

static in the C++ struct is the one for all thing, one wonders if a modern compiler would optimize that away some how.

It would mean containing the variable and the value to the struct definition, that's a 6/6 kinda style thing.

a7

Automatic prototype generation has failed here; it has placed the checkButton prototype before the Button definition. Adding the prototype yourself fixes the problem.

bool checkButton(Button &btn);
bool checkButton(Button &btn) { 
...

this managed to work for me. thank you. now that my sketch is uploaded i have reached a different problem xD

but thank you from the rest of you, you all have been very helpful

The const in your example is set during compile.

Making it static, there would be one instance for the class.
Not static gets one instance per object.

I don't recall there being a printf() in AVR LibC ... years ago.
I also see for AVR's, printf_P() where the format string is in PROGMEM which is woohoo.