View unanswered posts | View active topics It is currently Tue Oct 21, 2014 2:39 am






Reply to topic  [ 11 posts ] 
How to separate program into functions? 
Author Message
Rookie

Joined: Fri Mar 16, 2007 9:12 am
Posts: 26
Post 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.


Last edited by HoTWiReZ on Fri Mar 16, 2007 2:46 pm, edited 1 time in total.



Fri Mar 16, 2007 9:21 am
Profile
Site Admin
Site Admin

Joined: Wed Jan 24, 2007 10:44 am
Posts: 439
Location: Pittsburgh, PA
Post 
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.

_________________
Vu Nguyen
Software Training Development Team | Webmaster
Need more support? Use the ROBOTC Ticketing system

Robotc.net| Robomatter Store | Robotics Academy | CS2N


Fri Mar 16, 2007 11:58 am
Profile
Rookie

Joined: Fri Mar 16, 2007 9:12 am
Posts: 26
Post 
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.)


Fri Mar 16, 2007 12:08 pm
Profile
Site Admin
Site Admin

Joined: Wed Jan 24, 2007 10:44 am
Posts: 439
Location: Pittsburgh, PA
Post 
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.

_________________
Vu Nguyen
Software Training Development Team | Webmaster
Need more support? Use the ROBOTC Ticketing system

Robotc.net| Robomatter Store | Robotics Academy | CS2N


Fri Mar 16, 2007 12:12 pm
Profile
Rookie

Joined: Fri Mar 16, 2007 9:12 am
Posts: 26
Post 
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.


Fri Mar 16, 2007 12:27 pm
Profile
Site Admin
Site Admin

Joined: Wed Jan 24, 2007 10:44 am
Posts: 439
Location: Pittsburgh, PA
Post 
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.

_________________
Vu Nguyen
Software Training Development Team | Webmaster
Need more support? Use the ROBOTC Ticketing system

Robotc.net| Robomatter Store | Robotics Academy | CS2N


Fri Mar 16, 2007 1:21 pm
Profile
Rookie

Joined: Fri Mar 16, 2007 9:12 am
Posts: 26
Post 
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.


Last edited by HoTWiReZ on Sat Mar 17, 2007 1:52 am, edited 2 times in total.



Sat Mar 17, 2007 1:29 am
Profile
Novice

Joined: Sun Feb 04, 2007 12:48 am
Posts: 69
Location: Australia
Post 
Thanks vnguyen,

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

Thanks
James


Sat Mar 17, 2007 1:48 am
Profile
Rookie

Joined: Fri Mar 16, 2007 9:12 am
Posts: 26
Post 
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.)


Sat Mar 17, 2007 3:55 pm
Profile
Creator
Creator

Joined: Fri Feb 09, 2007 9:21 am
Posts: 615
Post 
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.


Fri Mar 23, 2007 3:30 pm
Profile
Rookie

Joined: Fri Mar 16, 2007 9:12 am
Posts: 26
Post 
Cool, good to hear that. Thanks.


Fri Mar 23, 2007 10:36 pm
Profile
Display posts from previous:  Sort by  
Reply to topic   [ 11 posts ] 

Who is online

Users browsing this forum: No registered users and 2 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  



Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group.
Designed by ST Software for PTF.