Go Down

Topic: How to return a value from a void function and use it inside the void loop? (Read 28158 times) previous topic - next topic

0011

Goal:
I want the variable tweet (which outputs either HIGH or LOW inside the void print() function) to turn on and off the LED_BUILTIN.

Restriction:
The if statement "producing" the tweet must run outside of the void loop().

Problem:
It seems that the void print() function does not return / expose the variable tweet inside the void loop(). The only thing what the serial monitor shows is Serial.println(val); which is 0.
What am I missing / misunderstanding here? Thank you for your help.


Code: [Select]
int intPressure = 11; 
int tweet = 0;
int val = 0;

void setup() {
}


void print() {
 
  if(intPressure != 0)
  { 
    Serial.println("HIGH");
    tweet = HIGH;
  }
  else
  {
    Serial.println("LOW");
    tweet = LOW;
  }

}

void loop() {

  void print();
 
  val = digitalRead(LED_BUILTIN);
  digitalWrite(LED_BUILTIN, tweet);
  Serial.println("---");
  Serial.println(val);
  Serial.println("---");

}

KeithRB

You have an endless loop when you call print() from the print() function. (It is called in the return statement)

Delta_G

By defining the function to return void, you CANNOT return a value.  If you want to return a value, then you wouldn't use a function returning void. 

If you want to return LOW or HIGH then have the function return int.

Code: [Select]

int print() {
 
  if(intPressure != 0)
  { 
    Serial.println("HIGH");
    tweet = HIGH;
  }
  else
  {
    Serial.println("LOW");
    tweet = LOW;
  }

  return tweet;

}


And then to use it in the loop function you'd have to assign that return value to something or use it somewhere it is useful.  Like:

Code: [Select]
int someVariableName = print();

or even:

Code: [Select]
if(print()){
    // code for when tweet was HIGH
}
else {
    //code for when tweet was LOW
}
|| | ||| | || | ||  ~Woodstock

Please do not PM with technical questions or comments.  Keep Arduino stuff out on the boards where it belongs.

0011

@KeithR
Thanks, I removed the return print() from the If statement inside the void print() function.

@Delta_G

Thank you for your suggestions.

I followed your examples

Code: [Select]

int intPressure = 12; 
int tweet = 0;
int val = 0;

void setup() {
}


void print() {
 
  if(intPressure != 0)
  { 
    Serial.println("HIGH");
    tweet = HIGH;
  }
  else
  {
    Serial.println("LOW");
    tweet = LOW;
  }
   return tweet;
}

void loop() {

  int tweetStatus = print();
 
  val = digitalRead(LED_BUILTIN);
  digitalWrite(LED_BUILTIN, tweetStatus);
  Serial.println("---");
  Serial.println(val);
  Serial.println("---");


}


 

and got 2 error messages :


Code: [Select]
Error A:
In function 'void print()':
test_bed:21: error:
return-statement with a value, in function returning 'void' [-fpermissive]
    return tweet;
           ^

Error B:
In function 'void loop()':
test_bed:26: error:
void value not ignored as it ought to be
   int tweetStatus = print();
                           ^
exit status 1
return-statement with a value, in function returning 'void' [-fpermissive]



Despite the explanations regarding the error messages below, I don't understand them quite, yet:


Error A
It means a function is declared to return nothing (void) but you are assigning the return code to a variable.

source: http://www.cplusplus.com/forum/unices/13109/


Error B
The error means that in your function:
void* foo(...);
You have a statement:
return;
But the compiler expects a value to be provided:
return myVoidPtr;



source: http://stackoverflow.com/questions/18024406/error-return-statement-with-no-value-in-function-returning-void-fpermissi



Are the error messages saying that the return statement return tweet returns something that is not there?


Delta_G

Go look at the function i wrote again.  It doesn't say "void" anywhere in it. 

PS.  It did for a few seconds.  I had to edit and fix it. 
|| | ||| | || | ||  ~Woodstock

Please do not PM with technical questions or comments.  Keep Arduino stuff out on the boards where it belongs.

Delta_G

I didn't realize that tweet was global.  You don't need any return statement then and the function can be a void function.  Just alter tweet in print and use it from loop.  It will keep whatever value you last gave it.  Global variables are available for use anywhere in your code. 
|| | ||| | || | ||  ~Woodstock

Please do not PM with technical questions or comments.  Keep Arduino stuff out on the boards where it belongs.

0011

@Delta_G

Your correction made the code work, thanks.

And the global variable thing made me think about how to go on with the next problem, thank you.



I just tried to implement this code in another greater code block.

Code: [Select]
// Print the data extracted from the JSON
void printUserData(const struct UserData* userData) {
  
  int tweet = 0;
  int number = 1023;
    
  Serial.print("data = ");
  Serial.println(userData->pressure);

  int intPressure = atoi(userData->pressure);
  Serial.print("intPressure = ");
  Serial.println(intPressure);
  
  //if (*(userData->pressure) == number)  // ==number brings HIGH and !=number brings LOW
  
  int print() {
  
  if(intPressure != 0)
  {  
    Serial.println("HIGH");
    tweet = HIGH;
  }
  else
  {
    Serial.println("LOW");
    tweet = LOW;
  }
   return tweet;

}




void loop() {


  int tweetStatus = print();
  val = digitalRead(LED_BUILTIN);

  // tweetStatus makes LED_BUILTIN either HIGH or LOW

  digitalWrite(LED_BUILTIN, tweetStatus);
  Serial.println("---");
  Serial.println(val);
  Serial.println("---");

  ...

}




The output is the following error message:

Code: [Select]
test_bed: In function 'void printUserData(const UserData*)':
test:175: error: a function-definition is not allowed here before '{' token
  
               ^
test_bed:239: error: expected '}' at end of input
 
   ^
exit status 1
a function-definition is not allowed here before '{' token



According to the error above, you cannot place the function int(print(){} ) inside the function  void printUserData(const struct UserData* userData){}. Generally speaking, you cannot put a function inside a function. I chose the if statement  if(intPressure != 0)|{}  to be inside the void printUserData function because I wanted this if statement to use the variable int intPressure = atoi(userData->pressure); . This variable decides about whether the LED_BUILTIN is LOW or HIGH.

Maybe one way to solve this is to make int intPressure = atoi(userData->pressure); to a global variable, so that it can be easily accessed by any function, particularly the void loop() function? This way, I could also just move the If statement if(intPressure != 0)|{}  to the void loop() function. If this a good way to go, how would you do that?

Delta_G

You already have a global variable named intPressure.  I'm not sure I understand what you are getting at. 

Perhaps you should go to google and search for "C++ variable scope" and read some of the articles it finds.  I think that may help to clear up some of your confusion. 
|| | ||| | || | ||  ~Woodstock

Please do not PM with technical questions or comments.  Keep Arduino stuff out on the boards where it belongs.

gfvalvo

Also, personally, I would not name a function that I wrote 'print'. It appears to be a keyword in Arduino. At least the IDE makes it a different color and that makes me nervous.
No technical questions via PM. They will be ignored. Post your questions in the forum so that all may learn.

Delta_G

Also, personally, I would not name a function that I wrote 'print'. It appears to be a keyword in Arduino. At least the IDE makes it a different color and that makes me nervous.
Whether or not the IDE makes a word orange has nothing to do with its being a keyword or not.  It only means that it is listed in a keywords.txt file in some library.  The only purpose is to make some words turn orange.  It serves no other real purpose.  What's worse is that the library only needs to be in your folder to have this effect.  It happens even for libraries not included in the current code.  If you want the colors of words to actually mean anything, then you have to use a more grown-up IDE like Eclipse. 
|| | ||| | || | ||  ~Woodstock

Please do not PM with technical questions or comments.  Keep Arduino stuff out on the boards where it belongs.

KeithRB

Yes, but if someone else went to the trouble of putting it in keywords.txt it would make me nervous if my function name turned orange.

Delta_G

Yeah but way too many library writers try to claim really common terms for themselves. I could write a library with a dictionary and you'd have to start picking random strings of letters.

If the IDE only did the orange thing for libraries included in the current sketch then I'd be a little more apt to agree. But it doesn't. It pulls any file it can find with that name and starts just willy-nilly orangish all the words it finds and that gets confusing. One of the big reasons I don't use the IDE to write my code.
|| | ||| | || | ||  ~Woodstock

Please do not PM with technical questions or comments.  Keep Arduino stuff out on the boards where it belongs.

0011

@Delta_G

Clarification of my 2nd problem:
I wanted to make the local variable tweet from function printUserData to a global variable so this local variable can be accessed by the void loop() function. I learned that this is not a good practice, making local variables to global ones:

New programmers are often tempted to use lots of global variables, because they are easy to work with, especially when many functions are involved. However, use of non-const global variables should generally be avoided altogether!

source: http://www.learncpp.com/cpp-tutorial/42-global-variables/


Back to my 2nd and last problem here:

In order to make a variable from another function available inside the void loop() function you may do the following:
I am using the data type byte to make tweet as a byte variable. Inside the printUserData function tweet will return the value also to the void loop function(), since its stored inside byte tweet. This worked for me.

source: https://www.arduino.cc/en/Reference/Byte


Code: [Select]


byte printUserData(const struct UserData* userData) {
  
  byte tweet = 0; // will return the value of this variable

    
  Serial.print("data = ");
  Serial.println(userData->pressure);

  int intPressure = atoi(userData->pressure);
    
  int print() {
  
  if(intPressure != 0)
  {  
    Serial.println("HIGH");
    tweet = HIGH;
  }
  else
  {
    Serial.println("LOW");
    tweet = LOW;
  }
   return tweet;

}


void loop() {

  byte tweet=0;

  val = digitalRead(LED_BUILTIN);


  digitalWrite(LED_BUILTIN, tweet);
  Serial.println("---");
  Serial.println(val);
  Serial.println("---");

  ...

}



Thank you for your help.

Delta_G

Code: [Select]

void loop() {

  byte tweet=0;

  val = digitalRead(LED_BUILTIN);


  digitalWrite(LED_BUILTIN, tweet);
  Serial.println("---");
  Serial.println(val);
  Serial.println("---");

  ...

}


Since you don't call your print function anywhere in loop, no you're not going to get the value of tweet from that function here.  Here you have another local variable in loop that just happens to have the same name, tweet, as the local variable in the print function.  But the two have absolutely nothing to do with one another.  So when you call that digitalWrite tweet will still be 0 and the led will always be off. 

Now you might have this in loop:

Code: [Select]
tweet = print();

and that will call print and return the value of tweet from print and store it in the tweet variable in loop. 


Quote
New programmers are often tempted to use lots of global variables, because they are easy to work with, especially when many functions are involved. However, use of non-const global variables should generally be avoided altogether!
That's good advise for bigger programs.  But for most Arduino code it is safely ignored advise.  Typically these projects are written by one or two people and are small enough to tell when you shadow a variable.  Sure, it's better to avoid globals, but I wouldn't get too bent out of shape about getting rid of them all.  They're not going to hurt most of the time. 
|| | ||| | || | ||  ~Woodstock

Please do not PM with technical questions or comments.  Keep Arduino stuff out on the boards where it belongs.

stuart0

According to the error above, you cannot place the function int(print(){} ) inside the function  void printUserData(const struct UserData* userData){}. Generally speaking, you cannot put a function inside a function.
Absolutely correct. And yet in your current code you are still doing ...
Code: [Select]
byte printUserData(const struct UserData* userData) {
 
  byte tweet = 0; // will return the value of this variable

   
  Serial.print("data = ");
  Serial.println(userData->pressure);

  int intPressure = atoi(userData->pressure);
   
  int print() {
  ....


Can you explain why you're still doing this, when way back in your reply #6 you so clearly told us that you understood that you cannot?

Go Up