[NXC] How important is the order of Voids?
[NXC] How important is the order of Voids?
I'm modifying a complex NXC program and all is going well.
I'm now at the stage of insterting a few last subroutines (voids) and I ran into a couple of problems, one I've solved.
1st of all, there is a core Void routine that does all the work. I'd built all the mechanical subroutines (voids) below it, and tested them all manually )I tested them by calling them from "main" void which is right at the bottom. All was fine.
Then I moved the calls to these routines to the main code which is much further up.
When I inserted the calls to the "below" voids, the compiler (Brixcc) started moaning about unidentified references. i.e. in my primary void (not main btw) I called xxxxx(); which was physically below in the code. Easy to solve, I moved the subroutine voids above the primary routine and all works fine. I was a little surprised as I though the program jumped from void to void as commanded and picked up variables as it went.
The compiler was complaining about missing void names, not variables.
Now, I'm modifying some of the void subroutines that i've moved up to the top, referencing variables that are created much further down in lower voids, and of course have run into the same problem (even though, in the correct running order of the program (logically) the variables are set in earlier code. I can't move the voids back down lower as I just moved them up to solve problem numer one.
Do I need to define all of these variables in advance at the very top of the program with #defines? even if their contents will be purely ficticious at the beginning.
I'd show the code but it's far too long
I'm now at the stage of insterting a few last subroutines (voids) and I ran into a couple of problems, one I've solved.
1st of all, there is a core Void routine that does all the work. I'd built all the mechanical subroutines (voids) below it, and tested them all manually )I tested them by calling them from "main" void which is right at the bottom. All was fine.
Then I moved the calls to these routines to the main code which is much further up.
When I inserted the calls to the "below" voids, the compiler (Brixcc) started moaning about unidentified references. i.e. in my primary void (not main btw) I called xxxxx(); which was physically below in the code. Easy to solve, I moved the subroutine voids above the primary routine and all works fine. I was a little surprised as I though the program jumped from void to void as commanded and picked up variables as it went.
The compiler was complaining about missing void names, not variables.
Now, I'm modifying some of the void subroutines that i've moved up to the top, referencing variables that are created much further down in lower voids, and of course have run into the same problem (even though, in the correct running order of the program (logically) the variables are set in earlier code. I can't move the voids back down lower as I just moved them up to solve problem numer one.
Do I need to define all of these variables in advance at the very top of the program with #defines? even if their contents will be purely ficticious at the beginning.
I'd show the code but it's far too long
Re: [NXC] How important is the order of Voids?
EDIT SOLVED. SEE LAST POST
OK, I'm totally foxed now. Let me explain with some code (It's a cube solver if you couldn't work it our from the code )
Here is a chunk of the main routine that works fine...
It's not all of it - it just goes on an on the same. It works. The variable "token" is a single letter or number extracted from a string of letters and numbers received from a PC app (cube solution). As the above stands, it works. The TextOut section "Main Loop Token" is a debugging section.
(there is a bit of converting the token string to numbers as the original author used algebra to calculate cube rotations and positions. I've left it in there for now so I can remove it carefully when I'm fully debugged)
The RotatexxxFace(); voids that are called after each else if statement are above this in my program. They are simple voids that pass commands to motors to do a cube move. Works fine.
Now the next step is to modify the RotatexxxFace voids to check if token[0] is a number, or Upper case letter, or Lower case letter. It then rotates 90, 180, or 90CCW accordingly. Should be simple. In another post here it was kindly explained how to do this and I inserted the code into the above section as a debug test (though I had it text out messages instead of turn motors) and it worked perfectly.
The problem is when I insert the case and number checking of "token" into the RotatexxxFace() voids. Example below....
The 1st thing that happens is that the compiler complains that token doesnt exist. So At the very top oif my program I put "string token". This allowed me to compile. But the program runs and acts as if "token" is blank when it gets to the RotatexxxFace void/routine. I tried adding textout debugs in the section above but any waits and button waits I put in get ignored.
From what's happening so far I get the feeling that variables are reset/removed when you call a subroutine from within another subroutine? is that the case?
I'm slightly perplexed. Everything works until I start farming out tasks to subroutines.
They key point here for me is "token[0]" is perfect when in the main code I posted 1st, but as soon as I step out and call another void as a subroutine , that called subroutines can't find "token[0]". I assumed it would be held in memory.
OK, I'm totally foxed now. Let me explain with some code (It's a cube solver if you couldn't work it our from the code )
Here is a chunk of the main routine that works fine...
Code: Select all
sub ReceiveSolution(){
string buffer = " ";
string orient = "RBD";
string token;
short i;
ClearScreen();
TextOut(0,LCD_LINE2,"waiting solution");
until(StrLen(buffer)>2) {
until(ReceiveMessage(PC_INBOX, true, buffer) == NO_ERR);
}
token = SubStr(buffer,0,2);
nActions = StrToNum(token);
ClearScreen();
for (i = 0; i<nActions; i++) {
token = SubStr(buffer,(3+2*i),1);
solution[i] = StringToActionCode(token);
// THIS IS WHERE I INSERT THE MAIN ROUTINE READING "token"
char ch = token[0];
if ((ch = "U")||(ch = "u")||(ch = "1"))
{
if (orient == "FUR") {
RotateUpFace();
orient = "FUR"; }
else if (orient == "RUB") {
RotateUpFace();
orient = "RUB"; }
else if (orient == "BUL") {
RotateUpFace();
orient = "BUL"; }
else if (orient == "LUF") {
RotateUpFace();
orient = "LUF"; }
else if (orient == "UBR") {
RotateFrontFace();
orient = "FUR"; }
else if (orient == "RBD") {
TextOut (0, LCD_LINE3, "Main Loop Token");
TextOut (0,LCD_LINE4, token[0]);
WaitButton(BTNCENTER);
RotateLeftFace();
orient = "FDL"; }
else if (orient == "DBL") {
RotateBackFace();
orient = "FDL"; }
(there is a bit of converting the token string to numbers as the original author used algebra to calculate cube rotations and positions. I've left it in there for now so I can remove it carefully when I'm fully debugged)
The RotatexxxFace(); voids that are called after each else if statement are above this in my program. They are simple voids that pass commands to motors to do a cube move. Works fine.
Now the next step is to modify the RotatexxxFace voids to check if token[0] is a number, or Upper case letter, or Lower case letter. It then rotates 90, 180, or 90CCW accordingly. Should be simple. In another post here it was kindly explained how to do this and I inserted the code into the above section as a debug test (though I had it text out messages instead of turn motors) and it worked perfectly.
The problem is when I insert the case and number checking of "token" into the RotatexxxFace() voids. Example below....
Code: Select all
void RotateLeftFace()
{
LiftUpRotate();
RotateMotorPID(SPINNER, 80, -88, 50, 60, 120); //permanent non-grab spin
Wait(100);
LiftReset();
RotateMotor(FLIPPER,-30,93);
LiftUpBottomRow();
char ch = token[0];
TextOut (0, LCD_LINE3, "Rotate Sub Token");
TextOut(0,LCD_LINE4, token[0]);
Wait (5000);
if(isdigit(ch))
{
Rotate180CW();
}
else if(isupper(ch))
{
Rotate90CW();
}
else if(islower(ch))
{
Rotate90CCW();
}
//Rotate90CW(); //or 180 or ccw
FlipperReset();
LiftReset();
SpinnerReset();
}
The 1st thing that happens is that the compiler complains that token doesnt exist. So At the very top oif my program I put "string token". This allowed me to compile. But the program runs and acts as if "token" is blank when it gets to the RotatexxxFace void/routine. I tried adding textout debugs in the section above but any waits and button waits I put in get ignored.
From what's happening so far I get the feeling that variables are reset/removed when you call a subroutine from within another subroutine? is that the case?
I'm slightly perplexed. Everything works until I start farming out tasks to subroutines.
They key point here for me is "token[0]" is perfect when in the main code I posted 1st, but as soon as I step out and call another void as a subroutine , that called subroutines can't find "token[0]". I assumed it would be held in memory.
Last edited by dodgey on 25 Sep 2011, 18:42, edited 1 time in total.
Re: [NXC] How important is the order of Voids?
Small update, I've learnt a bit about global variables but am still getting nowhere.
Now I'm reading that you can attach variables to calls to subroutines and then the subroutine can read that variable. I'm failing on the syntax tho.
As far as I understand you can have things like
void main ();
{
testsub(80)
}
void testsub (int number)
{
textout (0,LCD_LINE1, number)
}
which should text out "80".
I'm trying this with my variable string "ch"
so my call is "RotateUpFace(ch); //lets call this line A
the actual routine starts like:
Void RotateUpFace(string ch);
I get a compile error saying that the "line A" - "sting constant or variable of type string expected"
I gather my syntaxt is wrong?
Now I'm reading that you can attach variables to calls to subroutines and then the subroutine can read that variable. I'm failing on the syntax tho.
As far as I understand you can have things like
void main ();
{
testsub(80)
}
void testsub (int number)
{
textout (0,LCD_LINE1, number)
}
which should text out "80".
I'm trying this with my variable string "ch"
so my call is "RotateUpFace(ch); //lets call this line A
the actual routine starts like:
Void RotateUpFace(string ch);
I get a compile error saying that the "line A" - "sting constant or variable of type string expected"
I gather my syntaxt is wrong?
Re: [NXC] How important is the order of Voids?
SOLVED:
syntax syntaxt! Well I've learnt about NXC ordering of code, and I've learnt about global variables. I thought that making a variable global would be as simple as defining it at the top of my program, but it seems you need to make a copy as such, and use that global variable.
So now I have the char variable "ch" in my main program, and in the line below it I say "globalch = ch" (I declared globalch as a char at the top of my program)
Then in the subroutine I use globalch.
It seems that declaring ch as a global doesn't work, because it's created within a void routine, and therefore, despite my declaration, treated as local, as that is where is was created... does that make sense?
syntax syntaxt! Well I've learnt about NXC ordering of code, and I've learnt about global variables. I thought that making a variable global would be as simple as defining it at the top of my program, but it seems you need to make a copy as such, and use that global variable.
So now I have the char variable "ch" in my main program, and in the line below it I say "globalch = ch" (I declared globalch as a char at the top of my program)
Then in the subroutine I use globalch.
It seems that declaring ch as a global doesn't work, because it's created within a void routine, and therefore, despite my declaration, treated as local, as that is where is was created... does that make sense?
Re: [NXC] How important is the order of Voids?
Uh... TL;DR, but glad you fixed your problem!
Commit to LEGO Mindstorms Robotics Stack Exchange:
bit.ly/MindstormsSE
Commit to LEGO Stack Exchange: bit.ly/Area51LEGOcommit
Re: [NXC] How important is the order of Voids?
Well, it helps to talk to yourself sometimes
Re: [NXC] How important is the order of Voids?
Another technique to make the order of your functions less important is through the use of function prototypes. I've written a quick nonsensical program to demonstrate what I mean:
Once the function prototypes have been declared at the top of the file, it doesn't matter in what order you end up implementing them.
Btw, they are not called "voids" but functions. A void type function is one that doesn't return anything. People also refer to these as subroutines.
- Xander
Code: Select all
// Declare prototypes of your functions
void foo();
void baz();
task main () {
foo();
baz();
}
// implement them later!
void foo() {
int hello = 1;
baz();
}
void baz() {
int howdy = 0;
}
Btw, they are not called "voids" but functions. A void type function is one that doesn't return anything. People also refer to these as subroutines.
- Xander
| My Blog: I'd Rather Be Building Robots (http://botbench.com)
| RobotC 3rd Party Driver Suite: (http://rdpartyrobotcdr.sourceforge.net)
| Some people, when confronted with a problem, think, "I know, I'll use threads,"
| and then two they hav erpoblesms. (@nedbat)
| RobotC 3rd Party Driver Suite: (http://rdpartyrobotcdr.sourceforge.net)
| Some people, when confronted with a problem, think, "I know, I'll use threads,"
| and then two they hav erpoblesms. (@nedbat)
Re: [NXC] How important is the order of Voids?
YES! Please use the terms "functions" or "subroutines" when referring to the functions that you write. void is just a keyword indicating that a function does not return anything.Btw, they are not called "voids" but functions. A void type function is one that doesn't return anything. People also refer to these as subroutines.
John Hansen
Multi-platform LEGO MINDSTORMS programming
http://bricxcc.sourceforge.net/
http://bricxcc.sourceforge.net/
Re: [NXC] How important is the order of Voids?
Wondeful! Thanks guys.
And yes, subroutines and functions they are from now on. (I learn OS's from tinkering and it's only now that I'm really getting stuck into the NXC guide)
Robot is working well and just needs a little more debugging
And yes, subroutines and functions they are from now on. (I learn OS's from tinkering and it's only now that I'm really getting stuck into the NXC guide)
Robot is working well and just needs a little more debugging
Re: [NXC] How important is the order of Voids?
Haha, you assume the debugging ends at some point? By the time you're done fixing one bug, you'll have added some new features to it that come with a whole new set of bugs. Trust me, this is a never-ending cycle (and that's what keeps it fun!)Robot is working well and just needs a little more debugging
- Xander
| My Blog: I'd Rather Be Building Robots (http://botbench.com)
| RobotC 3rd Party Driver Suite: (http://rdpartyrobotcdr.sourceforge.net)
| Some people, when confronted with a problem, think, "I know, I'll use threads,"
| and then two they hav erpoblesms. (@nedbat)
| RobotC 3rd Party Driver Suite: (http://rdpartyrobotcdr.sourceforge.net)
| Some people, when confronted with a problem, think, "I know, I'll use threads,"
| and then two they hav erpoblesms. (@nedbat)
Who is online
Users browsing this forum: Semrush [Bot] and 0 guests