switch case jump to another loop function

Hi all,

Tried a few iterations of this without success. Can anyone see why it wont go to my other loop. I'm not a pro programmer mostly learning at the moment.
tks

//Look For errors and Halt
    byte Error = bitRead(LTC1325Status, 7);
    switch (Error) {
      case 0:
        //continue
        break;
      case 1:
        void Shutdown();
        break;
    }

Maybe the bit is always 0. How do you know that it isn't. Your best debugging tool is the serial print.

      case 1:
        void Shutdown();
        break;

The compiler should be showing an error because you cannot declare a function inside another function. Remove the "void" before "Shutdown()" .

Maybe the bit is always 0. How do you know that it isn't. Your best debugging tool is the serial print

serial shows 1

The compiler should be showing an error because you cannot declare a function inside another function. Remove the "void" before "Shutdown()" .

Without the void I get
LCDML_display_menuFunction:409:18: error: too few arguments to function 'void Shutdown(uint8_t)'
Shutdown();
^
LCDML_display_menuFunction.ino:756:6: note: declared here
void Shutdown(uint8_t param)
^~~~~~~~

 //Look For errors and Halt
    byte Error = bitRead(LTC1325Status, 7);
    Serial.println(Error);
    switch (Error) {
      case 0:
        //continue
        break;
      case 1:
        Shutdown();
        break;

The Shutdown() function requires an argument that you are failing to supply. Is that function part of a library?

Post the whole code.

Ok attached in full, the Bit of code is in menu_Fonction tab. It is not part of a library.
Really appreciate the help

BatteryChargerV3.zip (12.8 KB)

lucatz:
Ok attached in full, the Bit of code is in menu_Fonction tab. It is not part of a library.
Really appreciate the help

I believe your LCDML thing is a library and should be treated that way:

In the LCDML_display_menuFunction, you see this:

// *********************************************************************
void Shutdown(uint8_t param)
// *********************************************************************
{
  if (LCDML.FUNC_setup())         // ****** SETUP *********
  {
    // remmove compiler warnings when the param variable is not used:
    LCDML_UNUSED(param);   <--- this line

As the comment suggest, the intent here is to make the compiler not care that you’ve not passed a parameter to it. The macro is defined in LCDMenuLib2.h:

    // this makro is for unused variables which exists for compatibility tings ...
    #define LCDML_UNUSED(expr) do { (void)(expr); } while (0)

I can’t vouch for the efficacy of the macro. I find it odd that LCDMenuLib2.h is not included a the top of LCDML_display_menuFunction.ino.

As a remedy to the immediate problem, you might try changing Shutdown() to:

// *********************************************************************
void Shutdown( void ) // <--- change to void parameters
// *********************************************************************
{
  if (LCDML.FUNC_setup())         // ****** SETUP *********
  {
    // remmove compiler warnings when the param variable is not used:
    //LCDML_UNUSED(param);   <--- comment out
.
.
.

I tried your recommendation which passes compilation but it still will not jump to shutdown loop. Had also tried if/else with goto but read it was not best way to go about it. It also did not jump to shutdown.

serial.println prints constant 1 in monitor so case 1 should trigger

tks

// Set CS Pin LOW
    digitalWrite(CS_Pin, LOW); // Activate the CS line (CS is active LOW)
    delay(1);

    //Send Command Bytes to LTC1325
    SPI.transfer(0b00000010); // Send First byte
    SPI.transfer(0b00100100); // Send Second byte
    SPI.transfer(0b00000011); // Send Third byte
    LTC1325ADC = SPI.transfer16(0b1100000000000000); // Send TX4&TX5 get RX4&RX5 result and place in LTC1325ADC
    LTC1325Status = SPI.transfer(0b00000000); // Send TX6 get RX6 result and place in LTC1325Status
    //Set CS_Pin High
    digitalWrite(CS_Pin, HIGH); // Enable internal pull-up

    //Look for Errors and Halt
    byte Error = bitRead(LTC1325Status, 7);
    Serial.println(Error);
    switch (Error) {
      case 0:
        Shutdown();
        break;
      case 1:
        Shutdown();
        break;
    }



    //if (Error == 1) {
    //  lcd.clear();
    //  lcd.setCursor(1, 0);
    //  lcd.print("Error Encountered");
    //goto Shutdown();
    //}

    //else {
    //continue
    // }

    //ADC Result
    ADCResult = LTC1325ADC * (3.06 / 1024);
    lcd.clear();
    lcd.setCursor(1, 0);
    lcd.print("Charging");
    lcd.setCursor(1, 1);
    lcd.print("Vbat=");
    lcd.print(ADCResult);
    lcd.print("V");
    lcd.setCursor(1, 2);
    lcd.print("Status");
    lcd.setCursor(1, 3);
    lcd.print(LTC1325Status, BIN);
// *********************************************************************
void Shutdown( void )
// *********************************************************************
{
  if (LCDML.FUNC_setup())         // ****** SETUP *********
  {
    // remmove compiler warnings when the param variable is not used:
    //LCDML_UNUSED(param);

    // setup function
    lcd.setCursor(0, 0);
    lcd.print(F("To close this"));
    lcd.setCursor(0, 1);
    lcd.print(F("function press"));
    lcd.setCursor(0, 2);
    lcd.print(F("any button or use"));
    lcd.setCursor(0, 3);
    lcd.print(F("back button"));
  }

  if (LCDML.FUNC_loop())          // ****** LOOP *********
  {
    // loop function, can be run in a loop when LCDML_DISP_triggerMenu(xx) is set
    // the quit button works in every DISP function without any checks; it starts the loop_end function
    if (LCDML.BT_checkAny()) { // check if any button is pressed (enter, up, down, left, right)
      // LCDML_goToMenu stops a running menu function and goes to the menu
      LCDML.FUNC_goBackToMenu();
    }
  }

  if (LCDML.FUNC_close())     // ****** STABLE END *********
  {
    // you can here reset some global vars or do nothing
  }
}

Can you add a debug-print in Shutdown() such as:

void Shutdown( void )
// *********************************************************************
{
    Serial.println( "In Shutdown" );
.
.
.

before any of the 'if' statements and report back?

hmm... :frowning: my debug skills are week, but I am learning :slight_smile:

So it is going to the shutdown but it is not displaying on lcd...

13:27:30.775 -> In Shutdown

13:27:32.768 -> 1

13:27:32.768 -> In Shutdown

13:27:34.110 -> 1

13:27:34.110 -> In Shutdown

david_2018:

      case 1:
    void Shutdown();
    break;


The compiler should be showing an error because you cannot declare a function inside another function.

No, that’s just a function prototype.

But yes, lose the “void”

Ok
I will correct the Shutdown loop and will drop the void.

Can you guys confirm once it hits Case1 and goes to shutdown that it stays in there and never goes back to where it came from?

I see it goes to Shutdown so I think it works now

Thanks to all of you truly appreciated
Luca

lucatz:
hmm… :frowning: my debug skills are week, but I am learning :slight_smile:

So it is going to the shutdown but it is not displaying on lcd…

13:27:30.775 → In Shutdown

13:27:32.768 → 1

13:27:32.768 → In Shutdown

13:27:34.110 → 1

13:27:34.110 → In Shutdown

The only condition in Shutdown that puts anything to the LCD appears to be:

if (LCDML.FUNC_setup())         // ****** SETUP *********
  {
    // remmove compiler warnings when the param variable is not used:
    //LCDML_UNUSED(param);

    // setup function
    lcd.setCursor(0, 0);
    lcd.print(F("To close this"));
    lcd.setCursor(0, 1);
    lcd.print(F("function press"));
    lcd.setCursor(0, 2);
    lcd.print(F("any button or use"));
    lcd.setCursor(0, 3);
    lcd.print(F("back button"));
  }

So why does LCDML.FUNC_setup() not return a non-zero value?

Checking the source for that function in the library:

/* ******************************************************************** */
bool LCDMenuLib2::FUNC_setup(void)
/* ******************************************************************** */
{
    // debug information
    DBG_println(LCDML_DBG_function_name_FUNC, F("LCDML.FUNC_setup - check"));

    if(actMenu_id != _LCDML_NO_FUNC)
    {
        // function active
        if(bitRead(REG_MenuFunction, _LCDML_REG_MenuFunction_setup) == 0) 
        {
            // debug information
            DBG_println(LCDML_DBG_function_name_FUNC, F("LCDML.FUNC_setup - check: true"));

            bitSet(REG_MenuFunction, _LCDML_REG_MenuFunction_setup); // run setup
            DISP_clear();
            REG_button = 0;
            return true;
        }
        else
        {
            // debug information
            DBG_println(LCDML_DBG_function_name_FUNC, F("LCDML.FUNC_setup - check: false"));
            return false;
        }
    }
    else
    {
        bitClear(REG_MenuFunction, _LCDML_REG_MenuFunction_setup); // run setup
 
        return false;
    }
}

There’s only one way to return non-zero from that function:

  if(actMenu_id != _LCDML_NO_FUNC)
    {
        // function active
        if(bitRead(REG_MenuFunction, _LCDML_REG_MenuFunction_setup) == 0) 
        {
            // debug information
            DBG_println(LCDML_DBG_function_name_FUNC, F("LCDML.FUNC_setup - check: true"));

            bitSet(REG_MenuFunction, _LCDML_REG_MenuFunction_setup); // run setup
            DISP_clear();
            REG_button = 0;
            return true;

Follow the if’s and determine which condition is failing. It’s probably a menu initialization thing or something.

The compiler should be showing an error because you cannot declare a function inside another function.

“No, that's just a function prototype”

What’s the difference between a function prototype and a function declaration?

TIA

a7

alto777:
The compiler should be showing an error because you cannot declare a function inside another function.

“No, that's just a function prototype”

What’s the difference between a function prototype and a function declaration?

TIA

a7

The semicolon at the end instead of the body of the function I would think.

I Modified the Shutdown Loop...But I still see in serial monitor the output from Error byte.

In the Charging Loop I have...

//Look for Errors and Halt
    byte Error = bitRead(LTC1325Status, 7);
    Serial.println(Error);

Then

switch (Error) {
      case 1:
        Shutdown();
        break;
    }

So at this point it should be in Shutdown loop but I still see in serial monitor the output from serial.println
so I'm thinking it never actually leaves the Charging loop...could that be?

We can’t see your code

TheMemberFormerlyKnownAsAWOL:
We can't see your code

From Post 15? I see it...

lucatz:
I Modified the Shutdown Loop…

Can you see post #16?

TheMemberFormerlyKnownAsAWOL:
Can you see post #16?

Ok I see what you mean... :slight_smile:
Charging Loop

// *********************************************************************
void Charging(uint8_t param)
// *********************************************************************
{
  if (LCDML.FUNC_setup())         // ****** SETUP *********
  {
    //LCD Print
    lcd.clear();


    //SPI for LTC1325
    pinMode(CS_Pin, OUTPUT); // set the slaveSelectPin as an output:
    pinMode(53, OUTPUT); //Insure Mega is Master
    digitalWrite(CS_Pin, HIGH); // Activate the CS line (CS is active Low)
    SPI.begin();
    SPI.beginTransaction(SPISettings(125000, MSBFIRST, SPI_MODE0));
    delay(100); //Let things stabalize




    // remmove compiler warnings when the param variable is not used:
    LCDML_UNUSED(param);
    // setup
    // is called only if it is started

    // starts a trigger event for the loop function every 100 milliseconds
    LCDML.FUNC_setLoopInterval(2000);

    // uncomment this line when the menu should go back to the last called position
    // this could be a cursor position or the an active menu function
    // GBA means => go back advanced
    LCDML.FUNC_setGBA();

    //
  }

  if (LCDML.FUNC_loop())          // ****** LOOP *********
  {
    // Set CS Pin LOW
    digitalWrite(CS_Pin, LOW); // Activate the CS line (CS is active LOW)
    delay(1);

    //Send Command Bytes to LTC1325
    SPI.transfer(0b00000010); // Send First byte
    SPI.transfer(0b00100100); // Send Second byte
    SPI.transfer(0b00000011); // Send Third byte
    LTC1325ADC = SPI.transfer16(0b1100000000000000); // Send TX4&TX5 get RX4&RX5 result and place in LTC1325ADC
    LTC1325Status = SPI.transfer(0b00000000); // Send TX6 get RX6 result and place in LTC1325Status
    //Set CS_Pin High
    digitalWrite(CS_Pin, HIGH); // Enable internal pull-up

    //Look for Errors and Halt
    byte Error = bitRead(LTC1325Status, 7);
    Serial.println(Error);
    switch (Error) {
      case 1:
        Serial.println("In Case One");
        LCDML.FUNC_close();
        Shutdown();
        break;
    }


    //ADC Result
    ADCResult = LTC1325ADC * (3.06 / 1024);
    lcd.clear();
    lcd.setCursor(1, 0);
    lcd.print("Charging");
    lcd.setCursor(1, 1);
    lcd.print("Vbat=");
    lcd.print(ADCResult);
    lcd.print("V");
    lcd.setCursor(1, 2);
    lcd.print("Status");
    lcd.setCursor(1, 3);
    lcd.print(LTC1325Status, BIN);


    // loop
    // is called when it is triggered
    // - with LCDML_DISP_triggerMenu( milliseconds )
    // - with every button or event status change

    // uncomment this line when the screensaver should not be called when this function is running
    // reset screensaver timer
    LCDML.SCREEN_resetTimer();

    // check if any button is pressed (enter, up, down, left, right)
    if (LCDML.BT_checkAny()) {
      LCDML.FUNC_goBackToMenu();
    }
  }

  if (LCDML.FUNC_close())     // ****** STABLE END *********
  {
    // loop end
    // you can here reset some global vars or delete it
    // this function is always called when the functions ends.
    // this means when you are calling a jumpTo ore a goRoot function
    // that this part is called before a function is closed
  }
}


//* ===================================================================== *

Shutdown Loop

// *********************************************************************
void Shutdown(void)
// *********************************************************************
{
  Serial.println("In Shutdown");
  if (LCDML.FUNC_setup())         // ****** SETUP *********
  {
    //LCD Print
    lcd.clear();


    //SPI for LTC1325
    pinMode(CS_Pin, OUTPUT); // set the slaveSelectPin as an output:
    pinMode(53, OUTPUT); //Insure Mega is Master
    digitalWrite(CS_Pin, HIGH); // Activate the CS line (CS is active Low)
    SPI.begin();
    SPI.beginTransaction(SPISettings(125000, MSBFIRST, SPI_MODE0));
    delay(100); //Let things stabalize


    // remmove compiler warnings when the param variable is not used:
    //LCDML_UNUSED(param);
    // setup
    // is called only if it is started

    // starts a trigger event for the loop function every 100 milliseconds
    LCDML.FUNC_setLoopInterval(2000);

    // uncomment this line when the menu should go back to the last called position
    // this could be a cursor position or the an active menu function
    // GBA means => go back advanced
    LCDML.FUNC_setGBA();

    //
  }

  if (LCDML.FUNC_loop())          // ****** LOOP *********
  {

    lcd.clear();
    lcd.setCursor(0, 1);
    lcd.print("Shutdown");
    delay(2000);
    /* Set CS Pin LOW
      digitalWrite(CS_Pin, LOW); // Activate the CS line (CS is active LOW)
      delay(1);

      //Send Command Bytes to LTC1325
      SPI.transfer(0b00000010); // Send First byte
      SPI.transfer(0b00100100); // Send Second byte
      SPI.transfer(0b00000011); // Send Third byte
      LTC1325ADC = SPI.transfer16(0b1100000000000000); // Send TX4&TX5 get RX4&RX5 result and place in LTC1325ADC
      LTC1325Status = SPI.transfer(0b00000000); // Send TX6 get RX6 result and place in LTC1325Status
      //Set CS_Pin High
      digitalWrite(CS_Pin, HIGH); // Enable internal pull-up

      //Look for Errors and Halt
      byte Error = bitRead(LTC1325Status, 7);
      Serial.println(Error);
      switch (Error) {
      case 0:
        Shutdown();
        break;
      case 1:
        Shutdown();
        break;
      }



      //ADC Result
      ADCResult = LTC1325ADC * (3.06 / 1024);
      lcd.clear();
      lcd.setCursor(1, 0);
      lcd.print("Charging");
      lcd.setCursor(1, 1);
      lcd.print("Vbat=");
      lcd.print(ADCResult);
      lcd.print("V");
      lcd.setCursor(1, 2);
      lcd.print("Status");
      lcd.setCursor(1, 3);
      lcd.print(LTC1325Status, BIN);
    */

    // loop
    // is called when it is triggered
    // - with LCDML_DISP_triggerMenu( milliseconds )
    // - with every button or event status change

    // uncomment this line when the screensaver should not be called when this function is running
    // reset screensaver timer
    LCDML.SCREEN_resetTimer();

    // check if any button is pressed (enter, up, down, left, right)
    if (LCDML.BT_checkAny()) {
      LCDML.FUNC_goBackToMenu();
    }
  }

  if (LCDML.FUNC_close())     // ****** STABLE END *********
  {
    // loop end
    // you can here reset some global vars or delete it
    // this function is always called when the functions ends.
    // this means when you are calling a jumpTo ore a goRoot function
    // that this part is called before a function is closed
  }
}


//* ===================================================================== *

I Suspect that it is not exiting the Charging loop with this code...

switch (Error) {
      case 1:
        Serial.println("In Case One");
        LCDML.FUNC_close();
        Shutdown();
        break;

I think the only way to exit the loop is to call the LCDML.Func_Close , which is at the end of all loops. But It still does not work as I envisioned.

Serial shows the following...
16:33:27.475 -> 1
16:33:27.475 -> In Case One
16:33:27.475 -> In Shutdown
16:33:29.524 -> 1
16:33:29.524 -> In Case One
16:33:29.524 -> In Shutdown
16:33:31.528 -> 1
16:33:31.528 -> In Case One
16:33:31.528 -> In Shutdown
16:33:33.531 -> 1
16:33:33.531 -> In Case One
16:33:33.578 -> In Shutdown

tks