Thread: global verses local variables for embeded systems

  1. #1
    Registered User
    Join Date
    Apr 2019
    Posts
    808

    global verses local variables for embeded systems

    my arduino project has a setup and loop functions. the idea as i understand it is the setup tells the arduino what you want initialized and the loop is continuously run. if i declare a variable i = 0; in the loop function then increment it in side an if it looses its value on the next iteration of the loop function.

    the only way round this i can see is to use a global variable and set it outside is the functions. this is alien to me as using global variables was stamped out of me.

    is this just the way it is or am i doing something wrong.

  2. #2
    Registered User
    Join Date
    May 2019
    Posts
    214
    Post the code in case something is wrong in the code and it just isn't obvious to you yet.

    On the other hand, I don't know arduino specifically, but no other embedded work I do ignores standard C syntax the way you describe.

    Let's look at what you have.

  3. #3
    Registered User
    Join Date
    Apr 2019
    Posts
    808
    Code:
    //www.elegoo.com
    //2016.12.9
    
    /* @file CustomKeypad.pde
    || @version 1.0
    || @author Alexander Brevig
    || @contact [email protected]
    ||
    || @description
    || | Demonstrates changing the keypad size and key values.
    || #
    */
    #include <Keypad.h>
    
    const byte ROWS = 4; //four rows
    const byte COLS = 4; //four columns
    //define the cymbols on the buttons of the keypads
    char hexaKeys[ROWS][COLS] = {
      {'1','2','3','A'},
      {'4','5','6','B'},
      {'7','8','9','C'},
      {'*','0','#','D'}
    };
    byte rowPins[ROWS] = {9, 8, 7, 6}; //connect to the row pinouts of the keypad
    byte colPins[COLS] = {5, 4, 3, 2}; //connect to the column pinouts of the keypad
    
    //initialize an instance of class NewKeypad
    Keypad customKeypad = Keypad( makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS); 
    int redled = 10;
    int yellowled = 11;
    int position = 0;
    
    void setup(){
      Serial.begin(9600);
      pinMode(redled, OUTPUT);
      pinMode(yellowled, OUTPUT);
      setLocked(true);
    }
      
    void loop()
    {
      char key = customKeypad.getKey();
      char secretCode[] = "1234";
      
      if (key == '*' || key == '#') {
        position = 0;
        setLocked(true);
      }
     
      if (key == secretCode[position]) {
        Serial.println("digit correct");
        position++;
      }
     
      if (position == 4) {
        setLocked(false);
      }
      //delay(50);
      Serial.println(position);
    }
     
    void setLocked(int locked)
    {
      if (locked) {
        digitalWrite(redled, HIGH);
        //digitalWrite(yellowled, LOW);
      }
      else {
        digitalWrite(redled, LOW);
        digitalWrite(yellowled, HIGH);
        delay(1000);
        digitalWrite(yellowled, LOW);
        digitalWrite(redled, HIGH);
      }
    }
    this works as it is with int position declared globally if i include it in the loop it keeps getting set to 0 every time the loop runs

  4. #4
    Registered User
    Join Date
    May 2019
    Posts
    214
    @cooper1200,

    Ok, I have to see how loop is called, and I need the version where position is not global

    I think I know what's happening, but I need to see that to know my theory is correct
    Last edited by Niccolo; 06-20-2019 at 05:14 PM.

  5. #5
    Registered User
    Join Date
    Feb 2019
    Posts
    1,078
    Quote Originally Posted by Niccolo View Post
    @cooper1200,

    Ok, I have to see how loop is called, and I need the version where position is not global

    I think I know what's happening, but I need to see that to know my theory is correct
    From Arduino IDE perspective that's it:

    setup() will be called at bootstrap and loop() is called after... No main() function!
    I do prefer my own bootstrap code and using GCC cross compiler, but that's not the "arduino" way...

  6. #6
    Registered User
    Join Date
    Dec 2017
    Posts
    1,626
    If you need the variable to keep its value across calls to loop, just declare it inside loop as static.
    A little inaccuracy saves tons of explanation. - H.H. Munro

  7. #7
    Registered User
    Join Date
    May 2019
    Posts
    214
    @flp1969 & @john.c have good points here.

    @cooper1200,

    The point I was trying to confirm by seeing your code is based on this assumption: you were likely declaring the int position inside the loop function.

    Naturally, that means it only has local scope, and can't possibly survive the function. That's standard C, and would happen in any C or C++ application with this design.

    Indeed, since "loop" is a single step in an infinite animation loop, the only simple way to handle any value that survives the function is static declaration or global declaration.

    However, a bit of research with a few professors who teach Arduino revealed one more direction to consider.

    You don't have to use the Arduino IDE. You can use Eclipse: Arduino Playground - Eclipse

    In doing that you can subsequently elect to change things a bit, from which you define your own main function (essentially taking over what Arduino is automating for you).

    A few professors consider this a significant advantage, and I see a number of good reasons to think about it, but not immediately. It is a more advanced approach to Arduino - you're taking control of the development environment, expanding in your own direction. It would be attractive to me, but that's just how I approach things. I can see how the Arduino IDE would be a simplification much like I see in other embedded platforms, especially where the users aren't actually programmers (or that's not their primary focus).

    The bottom line is that if you did take the Eclipse route, fashion your own main (and therefore your own "loop" design), you could establish variables with scope only inside main which pass to loop, and thus survive.

    For embedded work, however, that isn't common. Nor is it even all that beneficial. It is built on a simplified operating system, likely can only run one application at a time. Global values are actually part of the bargain there.
    Last edited by Niccolo; 06-20-2019 at 05:54 PM.

  8. #8
    TEIAM - problem solved
    Join Date
    Apr 2012
    Location
    Melbourne Australia
    Posts
    1,907
    I agree with John.c in that static is what you want.

    But why can't you make another inner loop that goes through the input one byte at a time - And if the key is incorrect, break the inner loop and let the Loop function start again

    Use what you've learned already about programme structure, breaking tasks into functions and loops
    Last edited by Click_here; 06-20-2019 at 10:40 PM.

  9. #9
    TEIAM - problem solved
    Join Date
    Apr 2012
    Location
    Melbourne Australia
    Posts
    1,907
    It is built on a simplified operating system, likely can only run one application at a time.
    The Arduino has no operating system - It is a free standing (or bare metal) environment.

  10. #10
    Registered User
    Join Date
    Apr 2019
    Posts
    808
    here is where im getting confused i think.
    Code:
    void main ()
    {
    int x = 0;
    }
    x will retain the value of 0 for he length of the program unless i change it of course

    with this
    Code:
    void loop()
    {
    int x = 0;
    
    x +=2
    }
    x gets declared as 0 then set to equal 2 but next iteration it goes back to 0.

    is the void loop not like main or any other function for that matter that hasn't finished its code. is void loop not the same as doing a while (1) in main?

    @flp I intend once i have mastered the basics of the arduino to start coding it properly at the bit level with avr dude etc and setting my own registers etc but that aways away as i dont have the first clue yet what im doing with all the grunt work hidden by the arduino ide

  11. #11
    TEIAM - problem solved
    Join Date
    Apr 2012
    Location
    Melbourne Australia
    Posts
    1,907
    Remember the other day when I said that it is like this...
    Code:
    int main(void) 
    {
      Setup();
    
      for(;;) 
      {
        Loop();
      } 
    
      return 0;
    }
    If you want a variable to keep its value declare it as...
    Code:
    static int i;

  12. #12
    Registered User
    Join Date
    May 2019
    Posts
    214
    @cooper1200,

    There is serious difference.

    "int main()" is a function that LASTS THROUGHOUT the execution of a standard C / C++ program.

    "void loop()" is a function that only lasts for one loop. It returns TO a main function and is repeated.

    There is no "magical" difference.

    If "int main" did not happen to run the entire time of execution, you'd have the same viewpoint.

    Put another way, behind the scenes there is a function that CALLS main. The variable you declare inside main EVAPORATES the moment "main" returns (which then executes a few cleanup functions before leaving).

    The subject is scope. We covered it in recursion and I thought it was clear, but you do need a review.

    Here's a clear demonstration:

    Code:
    void myloop( int n )
    {
     int li = n + 4;
    }
    
    
    int main()
    {
     int mi = 5;
    
     for( int x = 0; x < mi; ++x )
        {
         myloop( mi );
        }
    
     return 0;
    }
    In this contrived example, the integer "mi" is allocated ON THE STACK. That position on the stack BELONGS to MAIN.

    When "myloop" is called, the value of "mi" is passed as a parameter, and will last as long as "MAIN" lasts - because it belongs to MAIN.

    Inside "myloop", the integer "li" is allocated ON THE STACK. That position on the stack BELONGS to MYLOOP. It is unknown to MAIN.

    When "myloop" returns, it returns to MAIN (by popping the stack and getting the return to main, inside the for loop).

    At that point, "li" has evaporated. "myloop" is gone, it's position on the stack is gone, all variables declared in that local stack, that local scope belonging to "myloop" were destroyed.

    The loop in main continues, and calls "myloop" again.

    This time, "myloop" is new again (and again for 5 repetitions). Everything starts over. "li" is created again, is new again, with no awareness of it's former existence in the previous loop.

    This is the nature of function calls, and of the allocations performed on the stack. It is a stack oriented concept.

  13. #13
    Registered User
    Join Date
    Feb 2019
    Posts
    1,078
    Using GCC-AVR cross compiler to compile arguino code

    Notice the -R option on avr-objcopy. This is there to not touch the bootstrap code from your arduino (it is not really necessary, since, probably, your final executable won't have this section)...

    There are other sites showing how to use these options. Google it!

    To install (on Debian like distros):
    Code:
    $ sudo apt install avr-gcc avr-libc
    Of course, you will loose the "arduino" library and deal directly with AVR microcontroller... But not much... take a look at /usr/lib/avr/

    Why I do prefer GCC? It optimize the code better...
    Last edited by flp1969; 06-21-2019 at 09:05 AM.

  14. #14
    TEIAM - problem solved
    Join Date
    Apr 2012
    Location
    Melbourne Australia
    Posts
    1,907

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. How do the global and local variables use the RAM?
    By YuminZhao in forum C++ Programming
    Replies: 2
    Last Post: 09-04-2011, 10:45 AM
  2. Local vs Global Variables
    By BENCHMARKMAN in forum C++ Programming
    Replies: 5
    Last Post: 07-03-2007, 05:17 AM
  3. local and global variables???
    By geo_c in forum C Programming
    Replies: 5
    Last Post: 08-23-2004, 03:02 PM
  4. Global Vs Local Variables
    By Waldo2k2 in forum C++ Programming
    Replies: 17
    Last Post: 11-11-2002, 07:51 PM
  5. global and local variables
    By Unregistered in forum C++ Programming
    Replies: 2
    Last Post: 10-02-2001, 01:17 PM

Tags for this Thread