Controlling motor speed through interrupts

Hey, I am working with a Vex kit for the first time, using MPLAB and C18. I am trying to build a robot which can detect and pick up objects. One problem that has me stuck for a long time is that I cannot modify the motor speed (pwm01 to pwm08) from my interrupt service routines(ISR). I have line sensors on the interrupt ports 1-3 which I have confirmed are working. I have also confirmed that the interrupt is triggered using a printf statement in the ISR. However I still cannot change the pwm value from the ISR.

Please help me out! I dont know what to do next!

Hi,

It’s difficult to know what’s really happening without seeing the while program but there is a possibility you are suffering from one of the most common mistakes I have done (and others) when setting up a multi input control programs and that would be having 2 or more points in the code which set the motor values overwriting each other. If as I suspect you are setting the motor control in your main program and then trying to change it in an interrupt routine, it will likely be reset to the value it was before the interrupt was called and it would appear that no change was made when really the motors are being set by 2 routines which execute really fast, only one of the results are going to be seen on the output.

if for example you are setting the motor output port in your main code to a value of say 80, they interrupt fires and sets the value to 127, then when the interrupt returns and the main code takes over it sets the motor value back to 80. to a human observer it might appear no change was made when the interrupt fired. but in reality it was set and reset very quickly. often more quickly than the motor update function in the robot controller.

You’ll want to review your code and ensure there is only one possible control input at a given time. If you’d like to post your whole code here, someone might be able to spot this is the case or what the real root cause is for the behavior.

I’m not familiar with MPLAB but I have worked with Easy C and Robot C for both a PIC and Cortex Robot controller.

Which Robot controller are you using? is it a PIC?

Cheers Kb

Hey
Firstly thanks a lot for your reply.
The code is as follows, to ensure that the motors are off for an observable period I used a loop in the ISR to delay the process. But I can still see no change in the motor speed.

The Interrupt code is below:
else if (INTCONbits.RBIF && INTCONbits.RBIE) /* DIG I/O 3-6 (RB4, RB5, RB6, or RB7) changed. /
{
printf(“interrupt”);
for(i=0; i<500; i++)
{
Getdata(&rxdata);
pwm01 = pwm03 = 127;
Putdata(&txdata);
}
int_byte = PORTB; /
You must read or write to PORTB /
INTCONbits.RBIF = 0; /
and clear the interrupt flag /
} /
to clear the interrupt condition. */

I have attached the files with the entire code as well.
user_routines.c (10.2 KB)
user_routines_fast.c (3.9 KB)

I am using a Vex PIC controller and MPLAB to program it.

I’m not an MPLAB user but I had a quick look at the VEX default code and libraries. I get the feeling that Getdata and Putdata should not be called from an interrupt and certainly should not be called in a tight loop. They are designed to be called once about every 18.5 mS (on the cortex they are the equivalent of the SPI comms between master and user cpus). Have you tried without using those two calls? something like this (remove that loop as well).


    printf("interrupt");
    pwm01 = pwm03 = 127;
    int_byte = PORTB;          /* You must read or write to PORTB */
    INTCONbits.RBIF = 0;     /*     and clear the interrupt flag         */

In your autonomous code

void User_Autonomous_Code(void)
{ 
  while (autonomous_mode)   /* DO NOT CHANGE! */
  {
    
  if (statusflag.NEW_SPI_DATA)      /* 18.5ms loop area */
    {
    Getdata(&rxdata);   /* Get fresh data from the master microprocessor. DO NOT DELETE, or you will be stuck here forever! */
  
    pwm01 = 77;
    pwm03 = 177;
     	
    printf("\bPWM_1&3:%2u, PWM_6&8:%2u, Sharp:%2u, Reflective:%u, compass:hex %x (%x%x%x%x)\n\n",(int)pwm01,(int)pwm06,(unsigned int)sharp_sensor,(unsigned int)rc_dig_in04,
    (unsigned int)compass,(unsigned int)rc_dig_in12,(unsigned int)rc_dig_in11,(unsigned int)rc_dig_in10,(unsigned int)rc_dig_in09);  /* printf EXAMPLE */
 		
 		
    Putdata(&txdata);             /* DO NOT CHANGE! or DELETE, or you will get no PWM outputs! */
    }
  }
}

you are also setting pwm01 an pwm03, this will override what you did in the interrupt code. So remove those two lines as well, final auton code should be.

void User_Autonomous_Code(void)
{ 
  while (autonomous_mode)   /* DO NOT CHANGE! */
  {
    
   if (statusflag.NEW_SPI_DATA)      /* 18.5ms loop area */
    {
    Getdata(&rxdata);   /* Get fresh data from the master microprocessor. DO NOT DELETE, or you will be stuck here forever! */
  
    Putdata(&txdata);             /* DO NOT CHANGE! or DELETE, or you will get no PWM outputs! */
    }
  }
}

and the interrupt code perhaps.

void InterruptHandlerLow ()     
{                               
  unsigned char int_byte;       
  if (INTCON3bits.INT2IF && INTCON3bits.INT2IE)       /* The INT2 pin is RB2/DIG I/O 1. */
    { 
    INTCON3bits.INT2IF = 0;
    }
  else if (INTCON3bits.INT3IF && INTCON3bits.INT3IE)  /* The INT3 pin is RB3/DIG I/O 2. */
    {
    INTCON3bits.INT3IF = 0;
    }
  else if (INTCONbits.RBIF && INTCONbits.RBIE)  /* DIG I/O 3-6 (RB4, RB5, RB6, or RB7) changed. */
    {
    // stop motors
    pwm01 = pwm03 = 127;
    
    int_byte = PORTB;          /* You must read or write to PORTB */
    INTCONbits.RBIF = 0;     /*     and clear the interrupt flag         */
    }                                        /*     to clear the interrupt condition.  */
}

Where are the motors started ? If you want to start them in auton then (sorry yet more code) do this.

void User_Autonomous_Code(void)
{ 
  // start motors
  pwm01 = 77;
  pwm03 = 177;
  while (autonomous_mode)   /* DO NOT CHANGE! */
  {
    // motors will be stopped by detecting something in the interrupt code
    if (statusflag.NEW_SPI_DATA)      /* 18.5ms loop area */
       {
       Getdata(&rxdata);   /* Get fresh data from the master microprocessor. DO NOT DELETE, or you will be stuck here forever! */	
       Putdata(&txdata);             /* DO NOT CHANGE! or DELETE, or you will get no PWM outputs! */
       }
  }
}

All of the above is guessing having never done MPLAB development on the PIC, however, it all seems reasonable, Have fun.