'on_ledBackItemSelected' was not declared in this scope

Hi,
This ERROR seems strange?
There do have a: void on_ledBackItemSelected(BackMenuItem* p_menu_item) in the code.

Thanks for help.
Adam

/* https://www.youtube.com/watch?v=wU_NfRFDRE0
 *  
 *  
 */
#include <MenuSystem.h>
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Streaming.h>
#include <PinChangeInterrupt.h>
#include <Servo.h>
#include "MyRenderer.h"
#include "MyRenderer.cpp"
#include "ToggleMenuItem.h"
#include "ToggleMenuItem.cpp"
#include "NumericDisplayMenuItem.h"
#include "NumericDisplayMenuItem.cpp"


//###############PIN CONFIG############
const uint8_t knobPbPin = 8;
const uint8_t knobAPin = 4;
const uint8_t knobBPin = 2;

//############Serial Config############
const uint32_t serialBaudRate = 115200;

//############LED Pin CONFIG###############
const uint8_t redLEDpin = 6;
const uint8_t greenLEDpin = 3;
const uint8_t blueLEDpin = 5;

//###########Photo Transistor Pin#########
uint8_t photoTransistorPin = A0;

//############Servo Pin Config#########
uint8_t servoPin = 11;

//#############OLED CONFIG#################
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 32 // OLED display height, in pixels

// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET     4 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

const uint8_t textRows = 4;


//############Menu#########
const uint16_t updateMenuInterval = 200;
MyRenderer my_renderer(&display, textRows);
MenuSystem ms(my_renderer);

Menu ledMenu("LED MENU", nullptr);
BackMenuItem ledBackItem("Back", &on_ledBackItemSelected, &ms);
ToggleMenuItem ledPowerItem("LED Power - ", nullptr, "ON", "OFF", false);
NumericMenuItem ledRedItem("Red", nullptr,0,0,255);
NumericMenuItem ledGreenItem("Green", nullptr, 0, 0, 255);
NumericMenuItem ledBlueItem("Blue", nullptr, 0, 0, 255);
NumericDisplayMenuItem photoTransistorItem("Sensor", nullptr, 0);
Menu servoMenu("Servo Menu", nullptr);
BackMenuItem servoBackItem("Back", on_servoBackItemSelected, &ms);
ToggleMenuItem servoPowerItem("Servo Power - ", &on_servoPowerItemSelected, "ON", "OFF", false);
NumericMenuItem servoAngleItem("Set Angle", nullptr, 0, 0, 180);

//##############Servo ###############
Servo myServo;

void setup()
{
	Serial.begin(serialBaudRate);
	initializeDisplay();
	initializeMenu();
	initializeKnob();
	initializePhotoTransistor();
}


void loop()
{
	updateMenu();
	updateLEDs();
	updateServo();
	updatePhotoTransistorValue();
	delay(100);
}

void on_ledBackItemSelected(BackMenuItem* p_menu_item)
{
	ms.back();
}

void on_servoBackItemSelected(BackMenuItem* p_menu_item)
{
	ms.back();
}

void on_servoPowerItemSelected(ToggleMenuItem* p_menu_item)
{
	if (p_menu_item->get_state())
		myServo.attach(servoPin);
	else
		myServo.detach();
}

//#######Encoder knob Functions###############
void initializeKnob()
{
	pinMode(knobAPin, INPUT_PULLUP);
	pinMode(knobBPin, INPUT_PULLUP);
	pinMode(knobPbPin, INPUT_PULLUP);
	attachPinChangeInterrupt(digitalPinToPinChangeInterrupt(knobBPin), knob_isr, CHANGE);
	attachPinChangeInterrupt(digitalPinToPinChangeInterrupt(knobPbPin), pbPressed, FALLING);
}

void knob_isr()
{
	//if the encoder knob was rotated, the dirction of motion
	//can be decoded as following
	if (digitalRead(knobAPin))
	{
		if (digitalRead(knobBPin)) //knob moved CW
			ms.next();
		else if (!digitalRead(knobBPin)) //knob moved CCW
			ms.prev();
	}

}

//button pushed interrupt
void pbPressed()
{
	ms.select();
}

//############Update LED##############
void updateLEDs()
{
	if (ledPowerItem.get_state())
	{
		analogWrite(redLEDpin, ledRedItem.get_value());
		analogWrite(greenLEDpin, ledGreenItem.get_value());
		analogWrite(blueLEDpin, ledBlueItem.get_value());
	}
	else
	{
		analogWrite(redLEDpin, 0);
		analogWrite(greenLEDpin, 0);
		analogWrite(blueLEDpin, 0);
	}
	
}
//#######Phototransistor Functions####
void initializePhotoTransistor()
{
	pinMode(photoTransistorPin, INPUT_PULLUP);
}
void updatePhotoTransistorValue()
{
	photoTransistorItem.set_value(analogRead(photoTransistorPin));
}
//###########Servo Functions###############
void updateServo()
{
	myServo.write(servoAngleItem.get_value());
}
//#######Display Functions###############
void initializeDisplay()
{
	// SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
	if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3C for 128x32
		Serial.println(F("SSD1306 allocation failed"));
		for (;;); // Don't proceed, loop forever
	}
	display.clearDisplay();
	display.setTextColor(WHITE, BLACK);
	display.setTextSize(1);
}
//#######Menu Functions##################
void initializeMenu()
{
	Serial << servoAngleItem.get_formatted_value() << endl;
	//add menus to root 
	ms.get_root_menu().add_menu(&ledMenu);
	ledMenu.add_item(&ledBackItem);
	ledMenu.add_item(&ledPowerItem);
	ledMenu.add_item(&ledRedItem);
	ledMenu.add_item(&ledGreenItem);
	ledMenu.add_item(&ledBlueItem);
	ledMenu.add_item(&photoTransistorItem);
	ms.get_root_menu().add_menu(&servoMenu);
	//servoMenu.add_item(&backItem);
	servoMenu.add_item(&servoBackItem);
	servoMenu.add_item(&servoPowerItem);
	servoMenu.add_item(&servoAngleItem);

	//initialize menu update service
	ms.display();
}

void updateMenu()
{
	ms.display();
}

ERROR:

Arduino: 1.8.3 (Windows 7), Board: "Arduino Nano, ATmega328"

MenuTest:57: error: 'on_ledBackItemSelected' was not declared in this scope

 BackMenuItem ledBackItem("Back", &on_ledBackItemSelected, &ms);

                                   ^

MenuTest:64: error: 'on_servoBackItemSelected' was not declared in this scope

 BackMenuItem servoBackItem("Back", on_servoBackItemSelected, &ms);

                                    ^

MenuTest:65: error: 'on_servoPowerItemSelected' was not declared in this scope

 ToggleMenuItem servoPowerItem("Servo Power - ", &on_servoPowerItemSelected, "ON", "OFF", false);

                                                  ^

Multiple libraries were found for "Servo.h"
 Used: C:\Users\HUA.DELLV-PC\Documents\Arduino\libraries\Servo
 Not used: C:\Users\HUA.DELLV-PC\Documents\Arduino\libraries\Servo-master
 Not used: E:\ENGINEERING\DIY\Electronic\ARDUINO\arduino-1.8.3-windows\arduino-1.8.3\libraries\Servo
exit status 1
'on_ledBackItemSelected' was not declared in this scope

This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.

The IDE automatically generates function prototypes as part of the build process and inserts them into the code. Sometimes it doesn't get it correct.

Add this line before line 57

void on_ledBackItemSelected(BackMenuItem*);
1 Like

Great!
Thank you.

It's my understanding that functions with arguments do not auto-prototype.

Not true. The prototype generation takes place but where it gets inserted into the entire comgoleration of .ino files into one .cpp file is usually the issue. This is especially true with arguments or retrurn values that are user/library defined.

OK, I'll rephrase:
It's my experience that functions with arguments must be prototyped.

Thanks for the useful discuss, I guess I have to give up this sketch, because of too many problems and nested.
say this Tab3 compiled ERROR 'NumericDisplayMenuItem' has not been declared, but the code obviously already #include "NumericDisplayMenuItem.h" why?
CODE Tab3:

/*
   An example of a custom NumericMenuItem.
   It tries to display some ASCII graphics in edit mode.
   This can be useful if you want to give the end user an overview of the value limits.

   Copyright (c) 2016 arduino-menusystem
   Licensed under the MIT license (see LICENSE)
*/

#ifndef _MY_RENDERER_H
#define _MY_RENDERER_H
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <MenuSystem.h>
#include "ToggleMenuItem.h"
#include "NumericDisplayMenuItem.h"

class CustomNumericMenuItem;

class MyRenderer : public MenuComponentRenderer
{
  public:
    MyRenderer(Adafruit_SSD1306* display, uint16_t lines);
    virtual void render(Menu const& menu) const;
    virtual void render_menu_item(MenuItem const& menu_item) const;
    virtual void render_back_menu_item(BackMenuItem const& menu_item) const;
    virtual void render_numeric_menu_item(NumericMenuItem const& menu_item) const;
    virtual void render_toggle_menu_item(ToggleMenuItem const& menu_item) const;

    virtual void render_numeric_display_menu_item(NumericDisplayMenuItem const& menu_item) const;
    virtual void render_menu(Menu const& menu) const;
  private:
    Adafruit_SSD1306* _display;
    uint16_t _lines;
};

#endif

CODE NumericDisplayMenuItem.h:

#ifndef NUMERIC_DISPLAY_MENU_ITEM_H
#define NUMERIC_DISPLAY_MENU_ITEM_H
#include <MenuSystem.h>
#include "MyRenderer.h"

class NumericDisplayMenuItem : public MenuItem {
public:
	//! \brief Callback for formatting the numeric value into a String.
	//!
	//! \param value The value to convert.
	//! \returns The String representation of value.
	using FormatValueFnPtr = const String(*)(const float value);

public:
	//! Constructor
	//!
	//! @param name The name of the menu item.
	//! @param select_fn The function to call when this MenuItem is selected.
	//! @param value Default value
	//! @param format_value_fn The custom formatter. If nullptr the String
	//!                        float formatter will be used.
	NumericDisplayMenuItem(const char* name, SelectFnPtr select_fn,
		float value,FormatValueFnPtr format_value_fn = nullptr);

	//!
	//! \brief Sets the custom number formatter.
	//!
	//! \param numberFormat the custom formatter. If nullptr the String float
	//!                     formatter will be used (2 decimals)
	//!
	void set_number_formatter(FormatValueFnPtr format_value_fn);

	float get_value() const;

	void set_value(float value);

	String get_formatted_value() const;

	virtual void render(MenuComponentRenderer const& renderer) const;

protected:
	float _value;
	FormatValueFnPtr _format_value_fn;
};

#endif 

ERROR:

Arduino: 1.8.3 (Windows 7), Board: "Arduino Nano, ATmega328"

In file included from sketch\NumericDisplayMenuItem.h:4:0,

                 from sketch\NumericDisplayMenuItem.cpp:1:

MyRenderer.h:31: error: 'NumericDisplayMenuItem' has not been declared

     virtual void render_numeric_display_menu_item(NumericDisplayMenuItem const& menu_item) const;

                                                   ^

sketch\NumericDisplayMenuItem.cpp: In member function 'virtual void NumericDisplayMenuItem::render(const MenuComponentRenderer&) const':

NumericDisplayMenuItem.cpp:17: error: no matching function for call to 'MyRenderer::render_numeric_display_menu_item(const NumericDisplayMenuItem&) const'

  my_renderer.render_numeric_display_menu_item(*this);

                                                    ^

sketch\NumericDisplayMenuItem.cpp:17:52: note: candidate is:

In file included from sketch\NumericDisplayMenuItem.h:4:0,

                 from sketch\NumericDisplayMenuItem.cpp:1:

sketch\MyRenderer.h:31:18: note: virtual void MyRenderer::render_numeric_display_menu_item(const int&) const

     virtual void render_numeric_display_menu_item(NumericDisplayMenuItem const& menu_item) const;

                  ^

sketch\MyRenderer.h:31:18: note:   no known conversion for argument 1 from 'const NumericDisplayMenuItem' to 'const int&'

exit status 1
'NumericDisplayMenuItem' has not been declared

This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.

You can't put #include in a tab. Includes, defines, global definitions and object declarations have to be in the main tab. The tabs get squished into one source file for the compiler to work on.

You can put objects into tabs, but that is advanced coding beyond my understanding.

Thinking of how the compiler squishes the tabs into one source file, have you tried putting the .h before the .cpp tabs?

Generally, I only put functions in the other tabs.

You can put anything you want into the tabs, but you have to understand how the Arduino IDE works. Your .cpp file is compiled as a separate unit and is included at link time. All of the .ino files are combined into one large .cpp file, prototypes are generated and inserted and then the whole thing is compiled and everything is linked together.