Chief Delphi

Chief Delphi (http://www.chiefdelphi.com/forums/index.php)
-   Programming (http://www.chiefdelphi.com/forums/forumdisplay.php?f=51)
-   -   Random behavior (http://www.chiefdelphi.com/forums/showthread.php?t=44731)

RedBarons 25-02-2006 01:57

Random behavior
 
I am experience some seriously "out there" behavior. I am essentially trying to get the robot into autonomous mode, drive for XXs, and shoot balls.

When I turn on the robot, nothing happens. If I hit 'reset', then the motors start spinning for XXs, and then stop (which makes me really happy: that's what I want to do :) ). However, if I reset the robot again, only one of the left or right drive motors may start, sometimes the robot starts shooting balls for no reason, sometimes the motors start spinning but never stop, etc. It's just driving me insane.... It seems completely undeterministic.

If you guys have any idea what's going on, let me know...

1. I use a interrupt based timer to know when to stop driving. The interrupt is handled as follows:

void Timer_1_Int_Handler()
{

static unsigned int timer1_count = 0; // initialized at compile time

// Make sure we still enforce a 50ms loop
TMR1L = 0xF4;
TMR1H = 0x24;

if (timer1_count < TIMER_1_CNT)
{
timer1_count++; // Timer1 counter incremented every 50ms
drive_period_expired = false;
}
else
{
drive_period_expired = true;
T1CONbits.TMR1ON = 0; // stop timer
PIE1bits.TMR1IE = 0; // disable interrupt
}

}


drive_period_expired is an unsigned char global variable that is initialized to false.

The timer is initialized in user_routines.c, in the user_initialization() function.

2. I am essentially trying to jumper out into autonomatic mode right off the bat in main.c:


if (statusflag.NEW_SPI_DATA)
{
Process_Data_From_Master_uP();

// ####################
// Kick start autonomous mode
// ####################
autonomous_mode = 1;

if (autonomous_mode)
{
User_Autonomous_Code();
}
}


3. In user_routines_fast, I initiate the timer (Autonom_Code_Init()) and then call a state machine (Autonom_Code_Handler())

void User_Autonomous_Code(void)
{
/* Initialize all PWMs and Relays when entering Autonomous mode, or else it
will be stuck with the last values mapped from the joysticks. Remember,
even when Disabled it is reading inputs from the Operator Interface.
*/
pwm01 = pwm02 = pwm03 = pwm04 = pwm05 = pwm06 = pwm07 = pwm08 = 127;
pwm09 = pwm10 = pwm11 = pwm12 = pwm13 = pwm14 = pwm15 = pwm16 = 127;
relay1_fwd = relay1_rev = relay2_fwd = relay2_rev = 0;
relay3_fwd = relay3_rev = relay4_fwd = relay4_rev = 0;
relay5_fwd = relay5_rev = relay6_fwd = relay6_rev = 0;
relay7_fwd = relay7_rev = relay8_fwd = relay8_rev = 0;

/* Initialize autonomous code */
Autonom_Code_Init();

while (autonomous_mode) /* DO NOT CHANGE! */
{
if (statusflag.NEW_SPI_DATA) /* 26.2ms loop area */
{
Getdata(&rxdata); /* DO NOT DELETE, or you will be stuck here forever! */

/* Add your own autonomous code here. */
Autonom_Code_Handler();

Generate_Pwms(pwm13,pwm14,pwm15,pwm16);

Putdata(&txdata); /* DO NOT DELETE, or you will get no PWM outputs! */
}
}
}


Autonom_Mode_Init():
void Autonom_Code_Init()
{
T1CONbits.TMR1ON = 1; // enable timer
}


Autonom_Mode_Handler():
Essentially, if drive_period_enabled == FALSE (see step 1), then the pwms for the drive motors are set to 127, else, they are set 254.

void Autonom_Code_Handler()
{

static unsigned char autonom_state = AUTONOM_STATE_DRIVE;

switch(autonom_state)
{
case(AUTONOM_STATE_DRIVE):
pwm01 = 254; // left motor
pwm02 = 254; // right motor

// Next state
if (drive_period_expired == true)
{
autonom_state = AUTONOM_STATE_SHOOT;
}

break;

case(AUTONOM_STATE_SHOOT):
pwm01 = 127;
pwm02 = 127;

default:


break;
}

}

Eldarion 25-02-2006 02:02

Re: Random behavior
 
Without looking at the code, I wonder if you are running into the high-priority interrupt problem.
Are you using the new library files from IFI's website?

Chriszuma 25-02-2006 02:03

Re: Random behavior
 
I would be interested if anyone knows an answer to this, because before we shipped my code was exhibiting similarly random behaviors. I have a decision structure that checks the value of an OI button and a limit switch and gives one motor a value if the button is down but the limit swith isn't. I am definitely just assigning different values to the same pwm output, but for some reason it moves two different motors depending on the OI switch. It could just be some deeply-nested logical error, but I would really hope that there's something in the camera or tracking code that's causing this.

RedBarons 25-02-2006 02:13

Re: Random behavior
 
Quote:

Originally Posted by Eldarion
Without looking at the code, I wonder if you are running into the high-priority interrupt problem.
Are you using the new library files from IFI's website?

Thanks for your reply. I am using older libraries (10/2005), but the timer relies on low priority interrupt.

RedBarons 25-02-2006 02:23

Re: Random behavior
 
Quote:

Originally Posted by Chriszuma
I would be interested if anyone knows an answer to this, because before we shipped my code was exhibiting similarly random behaviors. I have a decision structure that checks the value of an OI button and a limit switch and gives one motor a value if the button is down but the limit swith isn't. I am definitely just assigning different values to the same pwm output, but for some reason it moves two different motors depending on the OI switch. It could just be some deeply-nested logical error, but I would really hope that there's something in the camera or tracking code that's causing this.

In prior efforts, I had some motors starting spinning while their pwm cmd is not even used anywhere in the code !! That adds a black magic sort of twist to the robot. Beautiful.

RedBarons 25-02-2006 02:30

Re: Random behavior
 
I'll add that, reading an other post on this forum, I added the line:
#pragma interruptlow InterruptHandlerLow save=PROD,section(".tmpdata"),section("MATH_DATA")

We ended up shipping a stripped down version of our control SW, but I'd like to nail down what the problem is.

Alan Anderson 25-02-2006 11:03

Re: Random behavior
 
Quote:

Originally Posted by RedBarons
2. I am essentially trying to jumper out into autonomatic mode right off the bat in main.c:

Code:

if (statusflag.NEW_SPI_DATA) 
{                               
      Process_Data_From_Master_uP(); 

          // ####################
          // Kick start autonomous mode
          // ####################
          autonomous_mode = 1;

      if (autonomous_mode)
      {
        User_Autonomous_Code();     
      }
}

3. In user_routines_fast, I initiate the timer (Autonom_Code_Init()) and then call a state machine (Autonom_Code_Handler())

Code:

  ...
  while (autonomous_mode)  /* DO NOT CHANGE! */
  {
    if (statusflag.NEW_SPI_DATA)      /* 26.2ms loop area */
    {
        Getdata(&rxdata);  /* DO NOT DELETE, or you will be stuck here forever! */

        /* Add your own autonomous code here. */
                Autonom_Code_Handler();

        Generate_Pwms(pwm13,pwm14,pwm15,pwm16);

        Putdata(&txdata);  /* DO NOT DELETE, or you will get no PWM outputs! */
    }
  }
}


The call to Getdata() will change the value of autonomous_mode to reflect the state of the pin on the competition port. Without a dongle connected, the while loop in User_Autonomous_Code() will execute once and exit. Your main loop will end up calling Process_Data_From_Master_uP(), then User_Autonomous_Code(), repeatedly.

The Lucas 25-02-2006 14:03

Re: Random behavior
 
Quote:

Originally Posted by Alan Anderson
The call to Getdata() will change the value of autonomous_mode to reflect the state of the pin on the competition port. Without a dongle connected, the while loop in User_Autonomous_Code() will execute once and exit. Your main loop will end up calling Process_Data_From_Master_uP(), then User_Autonomous_Code(), repeatedly.

Remove the statement autonomous_mode = 1;. There are 2 ways to test autonomous code
1.You could test your code using a dongle (build instructions here ).
2. The quick and dirty solution is to your team number to 0000 by setting the dip switches on the OI to 0000 and tethering it to the Robot Controller. Warning: This will ALWAYS run autonomous. Run it on blocks so the robot doesn’t get away from you. Don’t leave the team number at 0000 because some unsuspecting team member may turn it on and the robot will attack them. :ahh:

Quote:

Originally Posted by RedBarons
// Make sure we still enforce a 50ms loop
TMR1L = 0xF4;
TMR1H = 0x24;

Quote:

Originally Posted by PIC18F8722 manual pg169
A write to the high byte of Timer1 must also take place
through the TMR1H Buffer register. The Timer1 high
byte is updated with the contents of TMR1H when a
write occurs to TMR1L. This allows a user to write all
16 bits to both the high and low bytes of Timer1 at once.

I don't think this keeps a 50ms timer. TMR1H is a buffer register and only writes to the actual high byte of the register when TMR1L is written. I think you need to write to TMR1H first and TMR1L second.

It would be far easier to just increment a counter in the 26.2 ms area of the Autonomous loop like so:
Code:

static int auto_counter=0;
while (autonomous_mode)  /* DO NOT CHANGE! */
  {
    if (statusflag.NEW_SPI_DATA)      /* 26.2ms loop area */
    {
        Getdata(&rxdata);  /* DO NOT DELETE, or you will be stuck here forever! */
        auto_counter++;

2 counts will give you ~50 ms and it will be synchronized to the rest of your autocode (timer interrupts are not synchronized to the 26.2ms auto loop)

If you still have this problem or any other problems, I will be at the Pittsburgh Regional which is your first regional (I assume you are on Team 63 Red Barons). I should be working at the Robot Inspection table.

steven114 25-02-2006 18:59

Re: Random behavior
 
That loop is not guaranteed to be 26.2ms - it can go for many times that length before you trigger a blinking red light. Using the timers is a much more reliable way to get time.

RedBarons 25-02-2006 23:03

Re: Random behavior
 
Quote:

Originally Posted by Alan Anderson
The call to Getdata() will change the value of autonomous_mode to reflect the state of the pin on the competition port. Without a dongle connected, the while loop in User_Autonomous_Code() will execute once and exit. Your main loop will end up calling Process_Data_From_Master_uP(), then User_Autonomous_Code(), repeatedly.

Thanks. Man does it sound like a stupid mistake...


All times are GMT -5. The time now is 03:15.

Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.
Copyright © Chief Delphi