I can't find the way to make work the code(Errors on topic)

hello everybody,how are you?I hope very well,i want to share with you something that i can't sort out by myself.if you want to check it out here is the trouble..
i'm working at a "new"code(i'm trying to get out all the delays i had and replace for "mydelays"librery...)
the fist part of the code is the same as in the code that works (with delays),i only change the delay stuff how i said ,but...my code doesn't compile,and i can't find the way to see what it's happening.
First of all I want to warn that I am a newbie in arduino ... and that I am doing my best to make a homemade "game dispenser" work, the menu is probably not solved in the best way, but it is what I could do with the knowledge that I have.

the code is this:





#include <Servo.h>
#include <MyDelay.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h> 


LiquidCrystal_I2C lcd(0x27,2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
Servo servo1;
Servo servo2;
MyDelay fourmsec(400);
MyDelay halfsec(500);
MyDelay sixmsec(600);
MyDelay onesec(1000);
MyDelay onehalfsec(1500);
MyDelay twosec(2000);
MyDelay fivehalfsec(5500);


bool init1 = false;
bool init2 = false;
bool init3 = false;
bool init4 = false;
bool init5 = false;
bool init6 = false;
bool init7 = false;
bool init8 = false;
bool init9 = false;
bool init10 = false;

const int op_cnt = 15;
int current_id;
bool operation;
bool onoff;
struct menu_item {
  int id; //id of menu item (might be same as number in array
  int parent;  //id of upper level menu item
  int sub;  //id of sub menu item, "0" means operation
  int next; //id of next menu item at same level
  int npp;  //not used
  String text; //menu item text
  int operation; //operation code
} ;

menu_item menus[op_cnt];

// initialize the library with the numbers of the interface pins

String lcd_line1;
String lcd_line2;
int show_data;
unsigned long times;
int button_flag;

//Custom arrow char
byte arrow[8] = {
  B00000,
  B00000,
  B01110,
  B01110,
  B01110,
  B01110,
  B00000,
  B00000
};


void setup() {
  servo1.attach(10);// pin servo1
  servo2.attach(11);//pin servo2
  digitalWrite(6, 1); // high state to be able to command the relay with low
  digitalWrite(7, 1); //  high state to be able to command the relay with low
  digitalWrite(8, 1); // high state to be able to command the relay with low
  digitalWrite(9, 1); //  high state to be able to command the relay with low


  pinMode(6, OUTPUT); //Relay Pump NÂş1
  pinMode(7, OUTPUT); //Relay Pump NÂş2
  pinMode(8, OUTPUT); //Relay Pump nÂş3
  pinMode(9, OUTPUT); //Relay Pump NÂş4


  lcd.begin(20, 4);
  lcd.createChar(8, arrow);
  lcd.backlight();
  lcd.clear();
  lcd.print("Toca boton abajo");
  lcd.setCursor(0, 1);
  lcd.print("para empezar..");
  delay(2000);

  times = 0;
  current_id = 0;
  operation = false;

  menus[0].id = 0;
  menus[0].parent = 0;
  menus[0].npp = 0;
  menus[0].next = 0;
  menus[0].sub = 1;
  menus[0].text = "Bienvenido!!!                                Presione>>>";
  menus[0].operation = 0;


  menus[1].id = 1; menus[1].parent = 0; menus[1].npp = 1; menus[1].next = 2; menus[1].sub = 3; menus[1].text = " MANUAL"; menus[1].operation = 0;

  menus[2].id = 2; menus[2].parent = 0; menus[2].npp = 2; menus[2].next = 1; menus[2].sub = 11; menus[2].text = " AUTOMATICO"; menus[2].operation = 0;


  menus[3].id = 3; menus[3].parent = 1; menus[3].npp = 1; menus[3].next = 4; menus[3].sub = 0; menus[3].text = "  NARANJA"; menus[3].operation = 110;

  menus[4].id = 4; menus[4].parent = 1; menus[4].npp = 2; menus[4].next = 3; menus[4].sub = 0; menus[4].text = "  POMELO"; menus[4].operation = 120;



  menus[11].id = 11; menus[11].parent = 2; menus[11].npp = 1; menus[11].next = 12; menus[11].sub = 0; menus[11].text = "2 VASOS 70% 30% "; menus[11].operation = 210;
  menus[12].id = 12; menus[12].parent = 2; menus[12].npp = 2; menus[12].next = 11; menus[12].sub = 0; menus[12].text = "4 VASOS 70% 30% "; menus[12].operation = 220;


  button_flag = 0;






}


void loop() {

  int val;
  val = analogRead(1);

  if (val > 1000 && button_flag == 0) {
    button_up();
    button_flag = 1;
  };
  if (val > 900 && val < 1000 && button_flag == 0) {
    button_down();
    button_flag = 1;
  };
  if (val > 870 && val < 900 && button_flag == 0) {
    button_back();
    button_flag = 1;
  };
  if (val > 800 && val < 850 && button_flag == 0) {
    button_ok();
    button_flag = 1;
  };
  if (val < 100 && button_flag == 1) { //reset button flag
    button_flag = 0;
  }


}

void button_up() {
  if (operation == false) {
    //get previous id and set menu
    for (int i = 0; i < op_cnt; i++) {
      if (menus[i].next == current_id) {
        current_id = i;
        break;
      };
    };
    draw_menu(current_id);
  };
}

void button_down() {
  //get next id and set menu
  if (operation == false) {
    //get previous id and set menu
    current_id = menus[current_id].next;
    draw_menu(current_id);
  };
}

void button_back() {
  //get parent and set menu
  if (menus[current_id].parent == current_id) {
    //turn off screen
    lcd.noDisplay();
    onoff = false;
  }
  else {
    if (operation == true) {
      draw_menu(current_id);
      operation = false;
    } else {
      if (operation == false) {
        //get previous id and set menu
        current_id = menus[current_id].parent;
        draw_menu(current_id);
      };
    };
  };
}

void button_ok() {
  if (onoff == false) {
    onoff = true;
    lcd.display();

  } else {
    //get sub or operation and set menu
    if (operation == false && menus[current_id].sub != 0) {
      current_id = menus[current_id].sub;
      draw_menu(current_id);}
    } else {
      if (operation == false && menus[current_id].sub == 0) {
        //handle operations
        show_function(menus[current_id].operation);
        operation = true;
      } else {
        if (operation == true) {
          trigger_operation(menus[current_id].operation);
        };
      };
    };
  };
}
  }

void draw_menu(int id) {
  lcd.clear();
  lcd_line1 = menus[id].text;
  if (menus[id].next != id) {
    lcd_line2 = menus[menus[id].next].text;
  } else lcd_line2 = "";

  lcd.setCursor(0, 0);
  lcd.print(lcd_line1);
  lcd.setCursor(0, 1);
  lcd.print(lcd_line2);
  lcd.setCursor(0, 0);
}

void show_function(int function) {
  lcd.clear();
  lcd.setCursor(0, 0);
  switch (function) {
    case 110:
      lcd.noBlink();
      lcd.print(" Servir NARANJA");
      lcd.setCursor(0, 1);
      lcd.print (" Presione  >>>");
      lcd.blink();

      return;

      break;

    case 120:
      lcd.noBlink();
      lcd.print(" Servir MARACUYA");
      lcd.setCursor(0, 1);
      lcd.print(" Presione >>> ");
      lcd.blink();

      break;

    case 210:
      lcd.noBlink();
      lcd.print("Sirviendo  2 vasos 70%30");
      lcd.setCursor(0, 1);
      lcd.print("Espere por favor");
      servo1.write(2);//

      if (init1 == false) {
        onesec.start();
        init1 = true;
      }

      if (onesec.update() ) {
        onesec.stop(); // wait 1 second to get top
      }

      digitalWrite(6, 0); //first  time pump F on
      if (init2 == false) {
        sixmsec.start();
        init2 = true;
      }
      if (sixmsec.update() ) {
        digitalWrite(6, 1);
        sixmsec.stop();// first time pump 0,6 sec F off
      }

      if (init3 == false) {
        twosec.start();
        init3 = true;
      }
      if (twosec.update() ) {
        twosec.stop();//waiting time(0,5 seg)
      }

      digitalWrite(7, 0); // first time pump C on
      if (init4 == false) {
        fivehalfsec.start();
        init2 = true;
      }

      if (fivehalfsec.update() ) {
        digitalWrite(7, 1);
        fivehalfsec.stop(); //first time pump 5,5sec C off
      }
      if (init5 == false) {
        fourmsec.start();
        init5 = true;
      }
      if (fourmsec.update() ) {
        fourmsec.stop();//waiting time 2 (0,4seg)
      }

      digitalWrite(6, 0); //second time pump F on
      if (init6 == false) {
        halfsec.start();
        init6 = true;
      }
      if (halfsec.update() ) {
        digitalWrite(6, 1);
        half.stop();// second time pump 0,6 sec F off
      }
      for (int  ang1 = 2; ang1 < 78 ; ang1++ )
      { MiServo.write(ang1);
        delay(50);//the cup is down here
      }
      digitalWrite(7, 0); // second time pump C on
      if (init7 == false) {
        onehalfsec.start();
        init7 = true;
      }

      if (onehalfsec.update() ) {
        digitalWrite(7, 1);
        onehalfsec.stop(); //second time pump 1,5 sec C off
      }



      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("Trago finalizado");
      lcd.setCursor(0, 1);
      lcd.print("Presione <<<<");

      init1 = false;
      init2 = false;
      init3 = false;
      init4 = false;
      init5 = false;
      init6 = false;
      init7 = false;
      lcd.blink();
      break;
  }
}



case 220:
lcd.noBlink();
lcd.print("Sirviendo  4 vasos 70%30");
lcd.setCursor(0, 1);
lcd.print("Espere por favor");
servo1.write(2);//
servo2.write(2);//
if (init1 == false) {
  onesec.start();
  init1 = true;
}

if (onesec.update() ) {
  onesec.stop(); // wait 1 second to get top
}

digitalWrite(6, 0); //first  time pump1 F on
digitalWrite(8, 0);// first  time pump2 F on
if (init2 == false) {
  sixmsec.start();
  init2 = true;
}
if (sixmsec.update() ) {
  digitalWrite(6, 1);// first time pump1 0,6 sec F off
  digitalWrite(8, 1);// first time pump2 0,6 sec F off
  sixmsec.stop();
}

if (init3 == false) {
  twosec.start();
  init3 = true;
}
if (twosec.update() ) {
  twosec.stop();//waiting time(2 seg)
}

digitalWrite(7, 0); // first time pump1 C on
digitalWrite(9, 0); // first time pump2 C on
if (init4 == false) {
  fivehalfsec.start();
  init2 = true;
}

if (fivehalfsec.update() ) {
  digitalWrite(7, 1);//first time pump1 5,5sec C off
  digitalWrite(9, 1);//first time pump2 5,5sec C off
  fivehalfsec.stop(); 
}
if (init5 == false) {
  fourmsec.start();
  init5 = true;
}
if (fourmsec.update() ) {
  fourmsec.stop();//waiting time 2 (0,4seg)
}

digitalWrite(6, 0); //second time pump1 F on
digitalWrite(8, 0); //second time pump2 F on
if (init6 == false) {
  halfsec.start();
  init6 = true;
}
if (halfsec.update() ) {
  digitalWrite(6, 1);// second time pump1 0,6 sec F off
  digitalWrite(8, 1);// second time pump2 0,6 sec F off
  half.stop();
}
for (int  ang1 = 2; ang1 < 78 ; ang1++ )
{ servo1.write(ang1);
  servo2.write(ang1);
  delay(50);//the cup is down here
}
digitalWrite(7, 0); // second time pump1 C on
digitalWrite(9, 0);//  second time pump2 C on
if (init7 == false) {
  onehalfsec.start();
  init7 = true;
}

if (onehalfsec.update() ) {
  digitalWrite(7, 1);//second time pump1 1,5 sec C off
  digitalWrite(9, 0);//second time pump2 1,5 sec C off
  onehalfsec.stop(); 
}



lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Trago finalizado");
lcd.setCursor(0, 1);
lcd.print("Presione <<<<");

init1 = false;
init2 = false;
init3 = false;
init4 = false;
init5 = false;
init6 = false;
init7 = false;
lcd.blink();
break;
}
}




}
}

void trigger_operation(int function) {
  const String on = "ON";
  const String off = "OFF";
  lcd.setCursor(0, 1);
  switch (function) {
    case 110:
      valor_potenciometro_1 = analogRead(A0);
      valor_potenciometro_1 = map(valor_potenciometro_1, 0, 1023, 2, 78);
      servo1.write(valor_potenciometro_1);
      while (analogRead(A1) > 110 && analogRead(A1) < 200) { //when the "button ok"is press the pump works

        digitalWrite(6, 0);
        valor_potenciometro_1 = analogRead(A0);
        valor_potenciometro_1 = map(valor_potenciometro_1, 0, 1023, 2, 78);
        servo1.write(valor_potenciometro_1);


      }{


        digitalWrite(6, 1);
        valor_potenciometro_1 = analogRead(A0);
        valor_potenciometro_1 = map(valor_potenciometro_1, 0, 1023, 2, 78);
        servo1.write(valor_potenciometro_1);


        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print(" Si ha terminado");
        lcd.setCursor(0, 1);
        lcd.print (" presione <<<");

      }

      break;
     
   case 120:
      valor_potenciometro_1 = analogRead(A0);
      valor_potenciometro_1 = map(valor_potenciometro_1, 0, 1023, 2, 78);
      servo1.write(valor_potenciometro_1);
      while (analogRead(A1) > 110 && analogRead(A1) < 200) { //when the "button ok"is press the pump works

        digitalWrite(7, 0);
        valor_potenciometro_1 = analogRead(A0);
        valor_potenciometro_1 = map(valor_potenciometro_1, 0, 1023, 2, 78);
        servo1.write(valor_potenciometro_1);


      }{


        digitalWrite(7, 1);
        valor_potenciometro_1 = analogRead(A0);
        valor_potenciometro_1 = map(valor_potenciometro_1, 0, 1023, 2, 78);
        servo1.write(valor_potenciometro_1);


        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print(" Si ha terminado");
        lcd.setCursor(0, 1);
        lcd.print (" presione <<<");

      }

      break;
}




bool switch_relay(int port) {
  digitalWrite(port, !digitalRead(port));
  return true;
};

and the error is this:

Arduino:1.8.15 (Windows 8.1), Tarjeta:"Arduino Uno"





















D:\Pruebadelaymaquinanueva\Pruebadelaymaquinanueva.ino: In function 'void button_up()':

Pruebadelaymaquinanueva:170:5: error: 'draw_menu' was not declared in this scope

     draw_menu(current_id);

     ^~~~~~~~~

D:\Pruebadelaymaquinanueva\Pruebadelaymaquinanueva.ino: In function 'void button_down()':

Pruebadelaymaquinanueva:179:5: error: 'draw_menu' was not declared in this scope

     draw_menu(current_id);

     ^~~~~~~~~

D:\Pruebadelaymaquinanueva\Pruebadelaymaquinanueva.ino: In function 'void button_back()':

Pruebadelaymaquinanueva:192:7: error: 'draw_menu' was not declared in this scope

       draw_menu(current_id);

       ^~~~~~~~~

Pruebadelaymaquinanueva:198:9: error: 'draw_menu' was not declared in this scope

         draw_menu(current_id);

         ^~~~~~~~~

D:\Pruebadelaymaquinanueva\Pruebadelaymaquinanueva.ino: In function 'void button_ok()':

Pruebadelaymaquinanueva:213:7: error: 'draw_menu' was not declared in this scope

       draw_menu(current_id);}

       ^~~~~~~~~

Pruebadelaymaquinanueva:214:7: error: 'else' without a previous 'if'

     } else {

       ^~~~

Pruebadelaymaquinanueva:217:9: error: 'show_function' was not declared in this scope

         show_function(menus[current_id].operation);

         ^~~~~~~~~~~~~

Pruebadelaymaquinanueva:221:11: error: 'trigger_operation' was not declared in this scope

           trigger_operation(menus[current_id].operation);

           ^~~~~~~~~~~~~~~~~

D:\Pruebadelaymaquinanueva\Pruebadelaymaquinanueva.ino:221:11: note: suggested alternative: 'operation'

           trigger_operation(menus[current_id].operation);

           ^~~~~~~~~~~~~~~~~

           operation

D:\Pruebadelaymaquinanueva\Pruebadelaymaquinanueva.ino: At global scope:

Pruebadelaymaquinanueva:226:1: error: expected declaration before '}' token

 }

 ^

exit status 1

'draw_menu' was not declared in this scope





Use the IDE autoformat tool (ctrl-t or Tools, Auto Format) to indent the code and you can see where your curly brackets are not right. Your curly brackets are all over the place. And you have }; in many places where they do not belong.

One real problem starts around line 414 where there is a bunch of code outside of a function.

Nice You You supplied the code. But, please regard the request from
@ groundFungus

Just before You define "draw_menu" it looks like kaos with curly brackets. Therefore the compiler is tumbling around in space.

The "MyDelays" library is NOT a replacement for the "delay()" function.

well, this is embarrassing ... because I base ALL the modification thinking that it would be like this, I wanted to eliminate the delays because I understand that they are not ideal to manage the times, but even if I try, I can not understand the use of millis that I think it would be ideal..so look for an alternative ...
Separate paragraph, is that although it is probably written horrible, the brackets show me that each one closes a function, in fact, the code that I use as a base to replace the delays and in fact it compiles and I have it loaded in the arduino for the first tests .

Delays and while/for loops are bad if you want the sketch to be doing something else at the same time. It looks like you are running pumps to mix liquids. If there is nothing else that needs to happen while your sketch is pumping liquids then the delays are fine.

Please, before you go much further, give the I/O pins names, and use them.

okey!that 's very useful in my case,so i'll work harder to create a more "clean"code..thanks you so much.
Wol,thank you for you apreciation,i 'll try to modify it.

Also, everywhere you have a literal string constant like this

use

lcd.print(F("Toca boton abajo"));

instead, and save a ton of precious RAM

Thanks You so much,but honestly i don't know the diferente between both...it is the f in the start?

Thanks!!

No, not 'f', but 'F'

Ok,i don't know this comand or how i have to use,i Will serch about that thanks!!

I'm pretty sure it is described in the language reference, in the section on Serial / print, but it is applicable to most other print methods.

It ensures the string stays in flash memory.

The use of "F()" is pretty easy

  Serial.println("Hello World");
  Serial.println("My Demo-Text");
  Serial.println("abc");

//becomes

  Serial.println( F("Hello World") );
  Serial.println( F("My Demo-Text") );
  Serial.println( F("abc") );

just put a F( before the first double-hyphen
and a ) behind the second double-hyphen

That's all.

best regards Stefan

as an allday example with easy to follow numbers
delay() is blocking. As long as the delay is "delaying" nothing else of the code can be executed.
Now there is a technique of non-blocking timing.
The basic principle of non-blocking timing is fundamental different from using delay()

You have to understand the difference first and then look into the code.

otherwise you might try to "see" a "delay-analog-thing" in the millis()-code which it really isn't
Trying to see a "delay-analog-thing" in millis() makes it hard to understand millis()
Having understood the basic principle of non-blocking timing based on millis() makes it easy to understand.

imagine baking a frosted pizza
the cover says for preparation heat up oven to 200°C
then put pizza in.
Baking time 10 minutes

You are estimating heating up needs 3 minutes
You take a look onto your watch it is 13:02 (snapshot of time)
You start reading the newspaper and from time to time looking onto your watch
watch shows 13:02. 13:02 - 13:02 = 0 minutes passed by not yet time
watch shows 13:03. 13:03 - 13:02 = 1 minute passed by not yet time
watch shows 13:04. 13:04 - 13:02 = 2 minutes passed by not yet time

watch shows 13:05 when did I start 13:02? OK 13:05 - 13:02 = 3 minutes time to put pizza into the oven

New basetime 13:05 (the snapshot of time)
watch 13:06 not yet time
watch 13:07 not yet time
watch 13:08 not yet time (13:08 - 13:05 = 3 minutes is less than 10 minutes
watch 13:09 not yet time
watch 13:10 not yet time
watch 13:11 not yet time
watch 13:12 not yet time
watch 13:13 not yet time
watch 13:14 not yet time (13:14 - 13:05 = 9 minutes is less than 10 minutes
watch 13:15 when did I start 13:05 OK 13:15 - 13:05 = 10 minutes time to eat pizza (yum yum)

You did a repeated comparing how much time has passed by
This is what non-blocking timing does

In the code looking at "How much time has passed by" is done

currentTime - startTime >= bakingTime

bakingTime is 10 minutes

13:06 - 13:05 = 1 minute >= bakingTime is false
13:07 - 13:05 = 2 minutes >= bakingTime is false
...
13:14 - 13:05 = 9 minutes >= bakingTime is false
13:15 - 13:05 = 10 minutes >= bakingTime is TRUE time for timed action!!

So your loop() is doing

void loop()
// doing all kinds of stuff like reading the newspaper

if (currentTime - previousTime >= period) {
previousTime = currentTime; // first thing to do is updating the snapshot of time
// time for timed action
}

it has to be coded exactly this way because in this way it manages the rollover from Max back to zero
of the function millis() automatically

baldengineer.com has a very good tutorial about timing with function millis() too .

There is one paragraph that nails down the difference between function delay() and millis() down to the point:

The millis() function is one of the most powerful functions of the Arduino library. This function returns the number of milliseconds the current sketch has been running since the last reset. At first, you might be thinking, well that’s not every useful! But consider how you tell time during the day. Effectively, you look at how many minutes have elapsed since midnight. That’s the idea behind millis()!

Instead of “waiting a certain amount of time” like you do with delay(), you can use millis() to ask “how much time has passed”?

best regards Stefan

1 Like

Sorry for the delay in answering, I was somewhat busy with time.
awol, thank you very much for the information.
Stefan, the explanation was super clear and exemplary, thanks for making it understandable and giving me the examples and comparisons with real time, I assure you that it will help me understand and internalize a little more in this wonderful world of arduino and programming, I will look at the tutorial that you sent me, thank you very much!

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