ROBOTC.net forums
http://www.robotc.net/forums/

How to separate program into functions?
http://www.robotc.net/forums/viewtopic.php?f=1&t=84
Page 1 of 1

Author:  HoTWiReZ [ Fri Mar 16, 2007 9:21 am ]
Post subject:  How to separate program into functions?

Hi, I've been trying to make a simple program I based on the motortest.c into a function to use as part of a main program. I created a file, Procedures.h, that contains the function declaration for the method,
int FindAngle(int& distance). I made a main.c, which is short enough to show here:
Code:
#include "Procedures.h"
task main()
{
   int distance = 0;
   int Angle =   FindAngle(distance);
   nxtDisplayTextLine(1,"Angle Found:%d",Angle);
   nxtDisplayTextLine(2,"Distance:%d",distance);
   wait10Msec(1000);
}


I get this RCX Exception Violation Report when the debugger gets to the 2nd line inside of main..

Byte Code Interpreter Exception:

Program Slot: 0, Task ID: main[0]
Error at PC: BAD-LOC +0xD51C
Task PC: Task offset 000E,
TaskState: 'Exception'
Exception Type: 'Invalid opcode(11)'

Also, I tried to just include the function above the main as a free function, but the same error happens when it's called. Here's the whole thing when I do it this way, just in case there is comething else wrong with this that's causing the error..
Code:
//This function should be called when the robot encounters an obstacle.
//It will check left and right for an edge up to 75 degrees away from
//center.  The function returns the angle from center (left is +, right
//is -) and returns the distance at which the edge was measured as it
//is passed by reference.
int FindAngle(int& distance)
{

//Declared as RAM values
   int nMoveSize     = 5;
  int nSpeed        = 100;
  int nDelay        = 500;
  int SensorVal         = 255;
  int SensorValOld   = 255;
  bool FoundEdge      = false;
  int LeftEdge         = 0;
  int RightEdge         = 0;
  int LeftDistance   = 0;
  int RightDistance   = 0;
  int sumVals            = 0;
  int i                     = 0; //Loop counter
  const tSensors sonarSensor          = (tSensors) S4;   //sensorSONAR9V
  const tSensors lightSensor          = (tSensors) S3;   //reflected Light Sensor
  SensorType[sonarSensor]=sensorSONAR9V;
  SensorType[lightSensor]=sensorLightActive;
  bFloatDuringInactiveMotorPWM = false;
  nMotorEncoder[motorA] = 0;
   //Checking to the left for an edge
  while (nMotorEncoder[motorA] < 75 && FoundEdge==false)
   {
      nMotorEncoderTarget[motorA]=nMoveSize;
     motor[motorA]=nSpeed;
      wait1Msec(nDelay/2);
      SensorValOld=SensorVal;
      //Trying to normalize values here to help avoid bad values..
      sumVals = 0;
      for (i=0; i<100; i++)
      {
         sumVals+=SensorRaw(sonarSensor);
      }
      SensorVal=sumVals/100;
      wait1Msec(nDelay/2);
      if (SensorVal>=SensorValOld+10)
      {
         FoundEdge=true;
         LeftEdge=nMotorEncoder[motorA];
         LeftDistance=SensorValOld;
      }
   }
   //Move back to center, ignoring Sonar values
   while (nMotorEncoder[motorA] > 0)
   {
      nMotorEncoderTarget[motorA]=nMoveSize;
      motor[motorA]=nSpeed*(-1);
      wait1Msec(nDelay);
   }
   //Return SensorVals to defaults..
   SensorVal=255;
   SensorValOld=255;
   FoundEdge=false;
   //Find edge on Right side
  while (nMotorEncoder[motorA] > -75 && FoundEdge==false)
   {
      nMotorEncoderTarget[motorA]=nMoveSize;
     motor[motorA]=nSpeed*(-1);
      wait1Msec(nDelay/2);
      SensorValOld=SensorVal;
      //Trying to normalize values here to help avoid bad values..
      sumVals = 0;
      for (i=0; i<100; i++)
      {
         sumVals+=SensorRaw(sonarSensor);
      }
      SensorVal=sumVals/100;
      wait1Msec(nDelay/2);
      if (SensorVal>=SensorValOld+10)
      {
         FoundEdge=true;
         RightEdge=nMotorEncoder[motorA];
         RightDistance=SensorValOld;
      }
   }
   //Return to 0 degrees and return SensorVals to defaults
    while (nMotorEncoder[motorA] < 0)
   {
      nMotorEncoderTarget[motorA]=nMoveSize;
     motor[motorA]=nSpeed;
      wait1Msec(nDelay);
   }
   SensorVal=255;
   SensorValOld=255;
   if ((RightEdge*-1)<LeftEdge)
   {
      distance=RightDistance;
      return RightEdge;
   }
   else if (LeftEdge<(RightEdge*-1))
   {
      distance=LeftDistance;
      return LeftEdge;
   }
}


task main()
{
   int distance = 0;
   int Angle =   FindAngle(distance);
   nxtDisplayTextLine(1,"Angle Found:%d",Angle);
   nxtDisplayTextLine(2,"Distance:%d",distance);
   wait10Msec(1000);
}

I'm assuming that this means that I can't do what I'm trying to do? If I can, what am I doing wrong here? If not, is there an equivalent way to handle this?
Thanks.

Author:  vnguyen [ Fri Mar 16, 2007 11:58 am ]
Post subject: 

I usually tend to keep a "functions.c" file to keep all of the common functions I create when I make a program. For example:

Here would be my "task main" using one of my funcitons: "move" which wants two params... a motor level for 2 motors, and a time

Code:


task main()
{

   wait1Msec(2000);
   move(100, 2000);


}


And here's an example of what would be in my "functions.c" file:

Code:
void move(int plevel, int timetoperform)
{

   motor[motorC] = plevel;
   motor[motorB] = plevel;
   if(timetoperform < 10000){
      wait1Msec(timetoperform);
   }
   else
   {
      timetoperform = timetoperform/10;
      wait10Msec(timetoperform);
   }
   motor[motorC] = 0;
   motor[motorB] = 0;

}

void turnleft(int plevel, int timetoperform)
{

   motor[motorC] = -plevel;
   motor[motorB] = plevel;
   if(timetoperform < 10000){
      wait1Msec(timetoperform);
   }
   else
   {
      timetoperform = timetoperform/10;
      wait10Msec(timetoperform);
   }
   motor[motorC] = 0;
   motor[motorB] = 0;

}

void turnright(int plevel, int timetoperform)
{

   motor[motorC] = plevel;
   motor[motorB] = -plevel;
   if(timetoperform < 10000){
      wait1Msec(timetoperform);
   }
   else
   {
      timetoperform = timetoperform/10;
      wait10Msec(timetoperform);
   }
   motor[motorC] = 0;
   motor[motorB] = 0;

}


I hope this helps.

Author:  HoTWiReZ [ Fri Mar 16, 2007 12:08 pm ]
Post subject: 

Thanks, that does help. Just to be sure, are pass by reference arguments allowed? Also, functions with return values are allowed by the compiler, but I haven't seen any in an example. If this shouldn't be allowed, is there a way to return values from the functions other than using pass by reference that is allowed? (I try to use it first because of simplicity.)

Author:  vnguyen [ Fri Mar 16, 2007 12:12 pm ]
Post subject: 

You should be able to create a function with a return value by replacing what I have with "int" or what kind of return type you want.

I'm going to have to pass on the passing by reference question to the language software development dept... so let me drop them an email.

Author:  HoTWiReZ [ Fri Mar 16, 2007 12:27 pm ]
Post subject: 

Thanks a bunch! In the meantime I'll try the function without the pass by reference stuff to see if it at least runs. I will need it to return 2 values eventually though.

Edit: The function works (is ran) if I remove the & from the function definition.

Author:  vnguyen [ Fri Mar 16, 2007 1:21 pm ]
Post subject: 

That's a good sign.. I'm still waiting for a reply, but I think they're just going to answer straight on this topic so we shall await.

Author:  HoTWiReZ [ Sat Mar 17, 2007 1:29 am ]
Post subject: 

I'm not quite sure why, but for some reason it started working with the pass by reference.. I downloaded the firmware with this version (previously I had the firmware from 1.0 on my NXT, but I don't think the versions for the firmwares changed..) I also found some mistakes in my code where I was doing a bitwise shift instead of a value comparison.. (oops.) I'm not sure what fixed it, but it's working now. Although, I do randomly get Byte Code Interpreter Exceptions. My latest one is:

Program Slot: 0, Task ID: main[0]
Error at PC: BAD-LOC +0xDB1C
Task PC: Sub move +0x0008,
TaskState: 'Exception'
Exception Type: 'Unknown(69)'

Is there some way to read this easily - i.e. to translate these into English? These errors only occur during the exectution of a function. In this case, the function is:
Code:
void move(int distance)
{
  bFloatDuringInactiveMotorPWM = false;
  nMotorEncoder[motorB]       = 0;  //Error occurs here..
   int mov = 0;
   float wheelCirc = 2*PI*2.25;
  //nMotorEncoderTarget[motorB] = 0;
   nSyncedMotors            = synchBC; 
  nSyncedTurnRatio         = 100;
  nPidUpdateInterval       = 10;     
  mov=(distance/wheelCirc)*360;
  if (distance>0)
  {
  nMotorEncoderTarget[motorB] = mov;       
  motor[motorB]               = 100;      
   }
   else
   {
      nMotorEncoderTarget[motorB] = mov*-1;
      motor[motorB]                        = -100;
   }
  while (nMotorRunState[motorB] != runStateIdle)
   {}
   wait1Msec(300);                     

}


The error seems to come up at this instruction: nMotorEncoder[motorB] = 0;

At least I think I'm starting to get the hang of this IDE. It's pretty nice, and the debugging interface is very helpful as well.

Author:  JamesD [ Sat Mar 17, 2007 1:48 am ]
Post subject: 

Thanks vnguyen,

Your example on how to pull other standard/commonly used functions into any other program is very helpful.

Thanks
James

Author:  HoTWiReZ [ Sat Mar 17, 2007 3:55 pm ]
Post subject: 

I think I solved this one this morning.. It seems that if you give nMotorEncoder[motorxx] a value while nSyncedMotors != synchNone, then it throws an exception.. I modified all of my functions that used the nSyncedMotors to set that to synchNone before exiting, and it seems to have gotten rid of the exceptions. I'm still not sure about why the pass by reference wasn't working initially, but it definitely works just fine now. (Just in case anyone else is interested to know this stuff.)

Author:  Dick Swan [ Fri Mar 23, 2007 3:30 pm ]
Post subject: 

Regarding pass by reference. They were just fully implemented recently and you probably initiallly started with a version that may have had a few bugs which were corrected when you upgraded.

Improving the exception handling message i ssomething that I'll do real soon.

Author:  HoTWiReZ [ Fri Mar 23, 2007 10:36 pm ]
Post subject: 

Cool, good to hear that. Thanks.

Page 1 of 1 All times are UTC - 5 hours [ DST ]
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
http://www.phpbb.com/