Chief Delphi

Chief Delphi (http://www.chiefdelphi.com/forums/index.php)
-   Programming (http://www.chiefdelphi.com/forums/forumdisplay.php?f=51)
-   -   New C18 3.0+ Compatible FRC Code (http://www.chiefdelphi.com/forums/showthread.php?t=60377)

Guy Davidson 12-02-2008 15:50

Re: New C18 3.0+ Compatible FRC Code
 
Quote:

Originally Posted by billbo911 (Post 697425)
Just a thought, here is a quote from the header of the gyro.c/Process_Gyro_Data

Here's the code to my Process_Gyro_Data (it isn't the latest revision with the input character):

Code:

void Process_Gyro_Data(void)
{
        int temp_gyro_rate;

        // fresh ADC data available?
        if(Get_ADC_Result_Count())
        {       
                // should the completed sample set be used to calculate the gyro bias?
                if(calc_gyro_bias == 1)
                {
                        // put the ADC reading on the circular queue
                        Gyro_Queue[Gyro_Queue_Index] = Get_ADC_Result(GYRO_CHANNEL);
               
                        // increment the write pointer
                        Gyro_Queue_Index++;
               
                        // is the circular queue now full?
                        if(Gyro_Queue_Index == GYRO_QUEUE_SIZE-1)
                        {
                                // update the gyro bias status
                                Gyro_Bias_Status = GYRO_BIAS_BUFFER_FULL;
                        }

                        // If the index pointer overflowed, cut-off the high-order bit. Doing this
                        // every time is quicker than checking for overflow every time with an if()
                        // statement and only then occasionally setting it back to zero. For this
                        // to work, the queue size must be a power of 2 (e.g., 16,32,64,128).
                        Gyro_Queue_Index &= GYRO_QUEUE_INDEX_MASK;
                }
                else
                {
                        // get the latest measured gyro rate
                        temp_gyro_rate = (int)Get_ADC_Result(GYRO_CHANNEL) - gyro_bias;
       
                        // update reported gyro rate and angle only if
                        // measured gyro rate lies outside the deadband
                        if(temp_gyro_rate < -GYRO_DEADBAND || temp_gyro_rate > GYRO_DEADBAND)
                        {
                                // update the gyro rate
                                gyro_rate = temp_gyro_rate;
       
                                // integrate the gyro rate to derive the heading
                                gyro_angle += (long)temp_gyro_rate;
                        }
                        else
                        {
                                gyro_rate = 0;
                        }
                }
               
                left_pot_value = Convert_ADC_to_mV(Get_ADC_Result(2));
                right_pot_value = Convert_ADC_to_mV(Get_ADC_Result(3));

                Reset_ADC_Result_Count();
        }               
}


Kevin Watson 12-02-2008 17:06

Re: New C18 3.0+ Compatible FRC Code
 
Quote:

Originally Posted by sumadin (Post 697409)
Kevin,

What is the procedure for adding additional analog sensors with the gyro code? I changed the number of ADC channels, plugged the (pots, in my case) in to channels 2 and 3, and added the code to read them in the Process_Gyro_Data function.

While I've been able to read the values (by converting the number to milivolts, as otherwise I'm not exactly sure what I'm seeing), the gyro has since been going crazy. I wired the gyro to an oscilloscope, and it still works, but the code (after given time to initialize and computing the bias) sees crazy values. Any idea what I'm doing wrong? Is there any readme to using the gyro with other analog values I'm missing?

Thanks.

Yeah, I'm a knucklehead for changing how Process_Gyro_Data() works. I'll post some code to show you how to use the other ADC channels. While waiting, you should go grab a copy of the code Bill mentions above.

-Kevin

Kevin Watson 12-02-2008 22:05

Re: New C18 3.0+ Compatible FRC Code
 
Quote:

Originally Posted by sumadin (Post 697409)
Kevin,

What is the procedure for adding additional analog sensors with the gyro code? I changed the number of ADC channels, plugged the (pots, in my case) in to channels 2 and 3, and added the code to read them in the Process_Gyro_Data function.

While I've been able to read the values (by converting the number to milivolts, as otherwise I'm not exactly sure what I'm seeing), the gyro has since been going crazy. I wired the gyro to an oscilloscope, and it still works, but the code (after given time to initialize and computing the bias) sees crazy values. Any idea what I'm doing wrong? Is there any readme to using the gyro with other analog values I'm missing?

Thanks.

This code works for me:

Code:

void Teleop_Spin(void)
{
    Process_Gyro_Data(FALSE); // <- Note the change to "FALSE"
 
    // fresh ADC data available?
    if(Get_ADC_Result_Count())
    {
          left_pot_value = Convert_ADC_to_mV(Get_ADC_Result(2));
          right_pot_value = Convert_ADC_to_mV(Get_ADC_Result(3));
 
          Reset_ADC_Result_Count();// <- Make sure to call this when finished
    }
}

-Kevin

Joe Ross 13-02-2008 13:03

Re: New C18 3.0+ Compatible FRC Code
 
It looks like C18 3.16 has been released. The release notes claim to have fixed the ADC header file issue.

Kevin Watson 13-02-2008 13:10

Re: New C18 3.0+ Compatible FRC Code
 
Quote:

Originally Posted by Joe Ross (Post 698080)
It looks like C18 3.16 has been released. The release notes claim to have fixed the ADC header file issue.

I haven't done much testing, but my code builds with 3.16.

-Kevin

Ken Streeter 13-02-2008 17:10

Re: New C18 3.0+ Compatible FRC Code
 
Sub-Subject: Using PWM() for a 100Hz Control Loop

I'm trying to understand how to use the PWM() function in order to implement a 100Hz PID control loop (rather than the default ~38.2 Hz).

I believe I understand the previous postings, but I'm getting stuck on when (and how often) PWM() needs to be called in order to generate output values. I have five questions below, buried in the posting. Answers (or any help, for that matter) to these questions would greatly aid my understanding. Thanks!

The "pwm_readme.txt" file says the following:

Code:

PWM()
Each time this function is called, one and only one pulse is
generated on each of the four outputs. This function is
called from ifi_frc.c/main() with an update rate of just over
thirty-eight hertz. PWM() can be called from other sections
of your code for higher control rates...

Looking into the code in PWM.c, I see where the pulse is commenced near the end of PWM():

Code:

// setup CCP hardware for compare mode (each PWM output
// transitions from low to high at this point)
CCP2CON = 0x09;
CCP3CON = 0x09;
CCP4CON = 0x09;
CCP5CON = 0x09;

However, I don't see where the transition from high to low occurs. (I know nothing about "CCP".) Is the high-low transition performed automatically somehow at a later time? (Q#1) Is there an interrupt service routine associated with the timer being used (timer3) or is no ISR needed for this style of usage? (Q#2)

Assuming that the high-low transition is occurring automatically with the CCP hardware, when does the next low-high transition occur? (Q#3)

It sounds from the one line in the pwm_readme.txt that the next low-high transition will not occur until PWM() is again called. This implies that I need to call PWM() repeatedly, even if we aren't changing the pwm values. Could we just call PWM() as fast we possibly can? (i.e. in every loop in Teleop_Spin() or Autonomous_Spin()) (Q#4).

If it would be bad to call PWM() as fast as we possibly can (because something would break), then presumably we need to call PWM() from Teleop_Spin() and/or Autonomous_Spin() at no more than about a 100Hz rate. If so, then do we need to take out the calls to PWM() in ifi_frc.c so that we're not actually calling PWM() 138 times a second? (Q#5) (100 times from our 100Hz section of *_Spin() and an additional 38 times a second in the block of code in ifi_frc.c which calls Autonomous() or Teleop())

I realize that these are almost surely "newbie" questions for anybody experienced with CCP, but that's where I am in my understanding of this right now. I ask your forgiveness for the "newbie" questions but don't know where else to turn to help, as I'm having trouble finding these answers in the documentation.

Thanks,
--ken

Ken Streeter 13-02-2008 17:33

Re: New C18 3.0+ Compatible FRC Code
 
In a previous message in this thread regarding the setup of a timer for a 100Hz loop, the following question was asked:

Quote:

Originally Posted by sumadin (Post 677729)
EDIT 2: Timer 0 does not seem to have the support to run to a predetermined value like timers 2,3,4. Should we use timer 2 instead? Another question. None of these timers actually allow us to run a 100hz cycle, even with 1:16 pre- and post-scalers. The slowest we can do is 150hz. Am I missing a way to do it, without using a second flag, or should we just use 150hz (or a double flag)?

I looked through the thread for an answer to this question, but couldn't find one. Does anybody have a code snippet which configures a timer for 100Hz?

Thanks!
--ken

Kevin Watson 13-02-2008 18:07

Re: New C18 3.0+ Compatible FRC Code
 
Quote:

Originally Posted by Ken Streeter (Post 698250)
In a previous message in this thread regarding the setup of a timer for a 100Hz loop, the following question was asked:



I looked through the thread for an answer to this question, but couldn't find one. Does anybody have a code snippet which configures a timer for 100Hz?

Thanks!
--ken

Yes, this is certainly possible. Set a timer to go off at 100Hz, but don't set the interrupt enable bit to one. Now craft a piece of code that will execute in one or more of the fast loops. In that code you should test to see if the timer interrupt flag gets raised, and if so, do your PID calculations and then call PWM() at the end. You'll need to comment out the call to PWM() in main() if you're using my code.

-Kevin

Kevin Watson 15-02-2008 00:56

Re: New C18 3.0+ Compatible FRC Code
 
I've created drop-in replacement code for timer.c and timer.h that implements a millisecond system clock using timer 2. The code is available here: http://kevin.org/frc/ifi_clock.zip.

-Kevin

cliff451 15-02-2008 17:54

Re: New C18 3.0+ Compatible FRC Code
 
We have been using the new code with great success, but whenever we set NUM_ADC_CHANNELS above 3, the analog input values including the gyro become unreliable. We also tried to adjust the sampling rates some, but this did not seem to help the problem. What have we missed?

Guy Davidson 15-02-2008 18:04

Re: New C18 3.0+ Compatible FRC Code
 
Quote:

Originally Posted by cliff451 (Post 699714)
We have been using the new code with great success, but whenever we set NUM_ADC_CHANNELS above 3, the analog input values including the gyro become unreliable. We also tried to adjust the sampling rates some, but this did not seem to help the problem. What have we missed?

We've been running into a similar issue - the gyro seems to drift way more when additional ADC channels are enabled. Is there any workaround?

Kevin Watson 16-02-2008 12:57

Re: New C18 3.0+ Compatible FRC Code
 
Quote:

Originally Posted by cliff451 (Post 699714)
We have been using the new code with great success, but whenever we set NUM_ADC_CHANNELS above 3, the analog input values including the gyro become unreliable. We also tried to adjust the sampling rates some, but this did not seem to help the problem. What have we missed?

Quote:

Originally Posted by sumadin (Post 699722)
We've been running into a similar issue - the gyro seems to drift way more when additional ADC channels are enabled. Is there any workaround?

I suspect the KOP gyro can't drive the sample-and-hold capacitor fast enough. If you have additional channels, those channels could drive the capacitor to very different voltages than what you gyro is sending out. When the ADC circuit switches to the gyro input, the gyro has very little time to push or pull charge into or out of the capacitor. The end result could be inaccurate gyro readings. As an experiment, sample the additional channels, but don't connect anything to those inputs. If the gyro works better, my theory starts looking good. Assuming my theory is correct, try using the adc_8520.c code instead as it should give the gyro additional time to charge the capacitor before the analog to digital conversion begins. If you're handy building circuits, you can also try using a very simple op-amp based voltage follower to better drive the capacitance. If you try these potential solutions, please report back here with your results.

EDIT: Another possibility is that you're not allowing enough time to calculate the bias. See my next message.

-Kevin

baop858 17-02-2008 22:21

Re: New C18 3.0+ Compatible FRC Code
 
Hey Kevin, I'm testing the 2007 gyro with your latest code. It works great when NUM_ADC_CHANNELS is one. But when I set it to four, I get a gyro bias of like 1660 - instead of the usual 2080- and then a constant rate when it's not moving. I don't have anything besides the gyro connected to the RC i'm testing it with. Is it possible this has something to do with the calculation of the gyro bias?


Edit: Could it be because I'm using the default gyro testing code in teleop.c which does not have enough time to fill the Gyro_Queue. I plan to test this theory tomorrow, and is there any reason why I shouldn't make the ADC_SAMPLE_RATE 3200HZ?

Kevin Watson 17-02-2008 23:51

Re: New C18 3.0+ Compatible FRC Code
 
Quote:

Originally Posted by baop858 (Post 701227)
Is it possible this has something to do with the calculation of the gyro bias?

Possibly. What may be happening is that you've added four channels, which means it takes four times longer to acquire the 64 updates (remember update rate = sample rate/samples per update) necessary to calculate the bias. Use the Get_Gyro_Bias_Status()
function to determine when it's safe to call Stop_Gyro_Bias_Calc() function. Here's info from the header:

Code:

/*******************************************************************************
*
* FUNCTION:  Get_Gyro_Bias_Status()
*
* PURPOSE:  Returns status of a gyro bias calculation.
*
* CALLED FROM:
*
* PARAMETERS:  None
*
* RETURNS:  GYRO_BIAS_NOT_DONE if a gyro bias has not been calculated.
*
*    GYRO_BIAS_IN_PROCESS after Start_Gyro_Bias_Calc() has been
*    called and data is being collected
*
*    GYRO_BIAS_BUFFER_FULL if the circular buffer is full,
*    indicating that it is safe to call Stop_Gyro_Bias_Calc().
*
*    GYRO_BIAS_READY if a gyro bias has been calculated.
*
* COMMENTS:
*
*******************************************************************************/

-Kevin

baop858 18-02-2008 00:05

Re: New C18 3.0+ Compatible FRC Code
 
I think that's it because I just did the calculations for a 800hz sampling rate and 16 samples per update. It takes 5.12 seconds to fill the gyro queue and the testing code only calculates the bias for 4 seconds. If I'm just reading some pots during the 26.2 ms loop, is there any reason I should reset adc result count in my own code as opposed to doing in the gyro code?

Edit:
Would the bias be any more accurate if the gyro_queue replaced some of it's first values it got from start up?


All times are GMT -5. The time now is 14:27.

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