Function delaration problem in mikroC Pro for PIC

Status
Not open for further replies.
Yes, I can understand structures now...

Good. Structures are not difficult to use or understand.

... I think I know what you are up to using ISR. Using ISR I can keep running in the main function right?, and constantly check all the variables.

Yes, you are beginning to see the bigger picture.

So I must first connect std to interrupt pin right?

The RB0 is an external interrupt pin and you already have STD connected to it.

Any intterupt will call the dtmfToNumber function if std = 1.

Sort of, we will write a lite version dtmfToNumber(), the ISR can handle a number of interrupt events. And with a mechanized device such as your design, you might need them.

The important concept to remember with ISRs is keep is short and sweet, no heavy lifting, get in and get out. All you want to do is record an event occurred, store data, etc.



Yes, but I have another trick up my sleeve to handle the Mode Routine Modules.

I'm introducing you to the real power of the C language, a side of C most people never learn or use.

I would like for you to study pointers in C. When you learn and understand pointers, you will have taken the first step in really mastering C. We'll being using them a lot in the future revisions of your program.

Some tutorials on pointers in C:

Pointers in C

Everything you need to know about pointers in C

Structures in C - Covers a little on structure pointers

Programs as Data: Function Pointers - a glimpse into the future

I'll work on the ISR later today.

BigDog
 
Reactions: wolf12

    wolf12

    Points: 2
    Helpful Answer Positive Rating
I tested the project with recursive functions. You are correct. It's not responding.
 

For background information.

Are you testing this on real hardware or in simulation?

Do you have a schematic of the design?


BigDog
 

For background information.

Are you testing this on real hardware or in simulation?

Do you have a schematic of the design?


BigDog

Not really. Just assembled in a breadboard. And the Schematic is not complete. Anyway I'll post it. The MT8870 circuit is assembled according to its datasheet.
ImageShack® - Online Photo and Video Hosting
MT8870 Datasheet.
http://www.datasheetcatalog.org/datasheets/228/268107_DS.pdf
And I'm testing with a dtmf encorder software. Tones are given via from PC audio jack.
 

I did a little change to code again. No recursion now.
Code:
void modeSelection(struct CTRL *pCtrl)
{
    Pwm1_Set_Duty(0); //stop the robot

    while(1)
    {
          dtmfToNumber(pCtrl);
          if(pCtrl->number == 1)
          {
           pCtrl->mode = 1;
           manualMode(pCtrl);
          }
}
void manualMode(struct CTRL *pCtrl)  // manual mode
{ 
   lm1 = 1; // returning to this function will make the robot go forward
   lm2 = 0;
   rm1 = 1;
   rm2 = 0;
  while(1)
  {  
   if(pCtrl->number == 2)   accelerate(pCtrl);
   if(pCtrl->number == 4)   turnLeft(pCtrl);
   if(pCtrl->number == 5)   decelerate(pCtrl);
   if(pCtrl->number == 6)   turnRight(pCtrl);
   if(pCtrl->number == 11)  return;     // instead of calling the modeSelection function, return from the function
  }
}
Now that I don't constantly polling on std line and using the interupt on every rising edge, how can I check whether the user released the button or not? I mean the user wouldn't want the robot to keep turning when he releases the button right? So again I must start polling on each of those routines I think.
Code:
void turnLeft(struct CTRL *pCtrl)
{
     while(std == 1 && pCtrl->number == 4)
     {
         lm1 = 0;
         lm2 = 0;
         rm1 = 1;
         rm2 = 0;
     }
         return;
}
 

For the navigation mode, I need to decrement a distance counter. Now that I used the interupt pin for the std line, I can think of two options,
1. Use tmr0 and increment it by the motor encorder signal, and do a calculation of the distance entered by the user like,
rounds = distance % 255 + distance / 255
here the distance / 255 is the number of 255 rounds you need to pass and distance % 255 is the remainder.
So I have to constantly check whether 255s are over and at last if they are over,
check whether the remainder = distance % 255
and stop the robot.
2. I can connect the encorder via a diode to the interupt pin, then power on the encorder only when the navigation mode is used, increment a counter and compair the distance, assuming the user wont press a button till the robot gets to position. Or I can also swich off the std line using a transistor. And I can check for a combination to force stop the robot, like if the user press *.
Which way is better? I think the 2nd way is good.

---------- Post added at 19:36 ---------- Previous post was at 18:49 ----------

Code:
//navigational mode
void navigationalMode(struct CTRL *pCtrl)
{
   pCtrl->number = 0;
    //add a .25S delay
   //add a beep to prompt for distance
   j = 0;
   while(1)
   {  // order of the digits - d1,d2,d3  983 - d1 = 9 d2 = 8 d3 = 3
      if(j=1)
      {
      pCtrl->d1 = pCtrl->number;
      }
      if(j=2)
      {
      pCtrl->d2 = pCtrl->number;
      }
      if(j=3)
      {
      pCtrl->d3 = pCtrl->number;
      break;
      }
   }
   j=0;
   pCtrl->distance = (pCtrl->d1)*100+(pCtrl->d2)*10+(pCtrl->d3);
   //add a .25S delay
   // add a beep to prompt for direction
   while(1)
   {
     if(std = 1)
     {
      pCtrl->direction = pCtrl->number;
      break;
     }
   }
   //add a .25S delay
   // add a beep to prompt for drive
   while(1)
   {
     if(std == 1 && pCtrl->number == 12)
     {
     drive(pCtrl);
     }
   }
 
}

void interupt()
{
 INTCON.GIE = 0;
 if(INTCON.INTF)
 {
     if(control.mode == 1)
     {
     dtmfToNumber(&control); //which address should I give? control is not a local variable.
     INTCON.INTF = 0;
     }
     if(control.mode == 2)
     {
     j++;
     }
 INTCON.GIE = 1;
 }
}
Drive mode and interrupt routine are not complete yet, I will set the encorder first. If you give me example of function pointers now, I mean how and where I should use them, I think I can continue.
Thank you.
 

For the navigation mode, I need to decrement a distance counter. Now that I used the interrupt pin for the std line, I can think of two options...

Your first option appears to be the best solution. However, rather than constantly check the value, subtract the maximum value of the timer from your calculated value and load the timer with the remainder. When the timer overflow occurs, the number of revolutions have been achieved and an interrupt occurs. When using an external clock source for the timer you can prescale the input by various ratios from 1:2 to 1:256.

Are you using or plan to both CCP modules?

If not, I've found the best way to deal with encoders is the use of one of the PIC's CCP modules used in either capture or compare mode.

In your case most likely the compare mode. You calculate distance in terms of encoder pulses load the resulting value into a TMRX and when the CCP CCPRX count matches that of the calculated value in TMRX an interrupt occurs. The above technique simplifies the process and lets the hardware do most of the work, leaving the PIC to handle other tasks.

Drive mode and interrupt routine are not complete yet, I will set the encorder first. If you give me example of function pointers now, I mean how and where I should use them, I think I can continue.

I'm still working on the design scheme, just write any additional modes using the control structure's pointer as the only function argument and the conversion will be simple. You can add or delete any types from the structure you desire to fit your needs.

BigDog
 
Reactions: wolf12 and FvM

    FvM

    Points: 2
    Helpful Answer Positive Rating

    wolf12

    Points: 2
    Helpful Answer Positive Rating
Yes, using compare mode seems most suitable.
But how can I put a 16 bit value in these two CCPR2H CCPR2L registers separately?
Also I thought to create two Arrays to keep 9 distances and directions in que. These distances are integers. When the capture flag is set microcontroller turn the robot to the direction and it will put the next distance on the CCPR2H CCPR2L registers.
 

Found how to do that,
CCPR2H = pCtrl->distance / 255;
CCPR2L = pCtrl->distance % 255;
 

When I accelerate to maximum and then when I try to decelerate the microcontroller doesn't respond sometimes. Why is that?
structure pointer is defined as a extern variable because I can't get the pointer to ISR.

Code:
void manualMode(struct CTRL *pCtrl)  // manual mode
{

//Any combination will exit the function and return with the undefined number.

  while(1)
  {
   if(pCtrl->number == 2)   accelerate(pCtrl);
   if(pCtrl->number == 4)   turnLeft(pCtrl);
   if(pCtrl->number == 5)   decelerate(pCtrl);
   if(pCtrl->number == 6)   turnRight(pCtrl);
   if(pCtrl->number == 11)  return;     // returns to modeSelection func
  }

}

void accelerate(struct CTRL *pCtrl)
{
         lm1 = 1;         //left motor positive
         lm2 = 0;         //left motor negative
         rm1 = 1;
         rm2 = 0;

         while(std == 1 && pCtrl->current_duty < 255 && pCtrl->number == 2)
         {
             pCtrl->current_duty++;
             Pwm1_Set_Duty(pCtrl->current_duty);
             Delay_ms(30);    // this delay is used to slow down rate of acceleration
         }
         pCtrl->number = 10;  // assign a non defined number to stop automatically coming back to this func even when key is released.
         return;
}

void decelerate(struct CTRL *pCtrl)
{
         lm1 = 1;
         lm2 = 0;
         rm1 = 1;
         rm2 = 0;
         while(std == 1 && pCtrl->current_duty > 0 && pCtrl->number == 5)
         {
             pCtrl->current_duty--;
             Pwm1_Set_Duty(pCtrl->current_duty);
             Delay_ms(30);
         }
         pCtrl->number = 10;
         return;
}

void interrupt()
{
   INTCON.GIE = 0;

   if(INTCON.INTF)
   {
       if(control.mode == 1)
       {
        dtmfToNumber(&control); //which address should I give? control is not a local variable. Had to declare control as extern
       }
       if(control.mode == 2)
       {
        dtmfToNumber(&control);
        j++;               //increment navigation digit
       }
       if(control.mode == 4)  //login mode
       {
        dtmfToNumber(&control);
        i++;              //increment password digit
       }
       INTCON.INTF = 0;
   }

   if(PIR2.CCP2IF)        //ccp2 compare intterupt
   {
        n++;              //move to next data in Array (drive mode que)
        PIR2.CCP2IF = 0; // if you want forget about interrupt and check the ccp2 pin in drive mode

   }
   INTCON.GIE = 1;

}
 
Last edited:

Status
Not open for further replies.

Similar threads

Cookies are required to use this site. You must accept them to continue using the site. Learn more…