Go to Post quick everyone find everything in the whole world that sells for $125 so we can get an edge on our building 2 days before kick off.....ready...go! - Greg Needel [more]
Home
Go Back   Chief Delphi > Technical > Programming
CD-Media   CD-Spy  
portal register members calendar search Today's Posts Mark Forums Read FAQ rules

 
Closed Thread
Thread Tools Rate Thread Display Modes
  #1   Spotlight this post!  
Unread 07-12-2006, 20:05
teh_pwnerer795 teh_pwnerer795 is offline
Registered User
AKA: !!Mitch!!
FRC #1392
Team Role: Programmer
 
Join Date: Nov 2006
Rookie Year: 2006
Location: Ajax, Canada
Posts: 142
teh_pwnerer795 is just really niceteh_pwnerer795 is just really niceteh_pwnerer795 is just really niceteh_pwnerer795 is just really nice
Send a message via MSN to teh_pwnerer795 Send a message via Yahoo to teh_pwnerer795
Auto mode... need help

Hey guys,

ok i doign some stuff in automode.. nothing tooo cool.. but its a start. Basicaly all i am doing is driving the robot forward and backwards. Now.. i have it program in "if" statements

example.

if (count == 1)
{
pwm01 = 254;
}

sooo... i need a timer. count is what the time is. Sorta confusing but at 1 second its goign to go forward. But the problem i am having is creating code for the timer. Does the orignal code have a timer programmed already ? or should i make my own. let me know
__________________
Great Art is Created; Master Pieces are Stolen

[n00b]Teh_Foxdonut teh_pwnerer795 - CounterStrike:Source
  #2   Spotlight this post!  
Unread 07-12-2006, 20:39
EHaskins EHaskins is offline
Needs to change his user title.
AKA: Eric Haskins
no team (CARD #6 (SCOE))
Team Role: College Student
 
Join Date: Jan 2006
Rookie Year: 2006
Location: Elkhorn, WI USA
Posts: 998
EHaskins has a reputation beyond reputeEHaskins has a reputation beyond reputeEHaskins has a reputation beyond reputeEHaskins has a reputation beyond reputeEHaskins has a reputation beyond reputeEHaskins has a reputation beyond reputeEHaskins has a reputation beyond reputeEHaskins has a reputation beyond reputeEHaskins has a reputation beyond reputeEHaskins has a reputation beyond reputeEHaskins has a reputation beyond repute
Send a message via MSN to EHaskins
Re: Auto mode... need help

The easiest way to do this is to increment a variable every time you get new data from the master processor.

Default Autonomous:
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. */

        Generate_Pwms(pwm13,pwm14,pwm15,pwm16);

        Putdata(&txdata);   /* DO NOT DELETE, or you will get no PWM outputs! */
    }
  }
The first thing you need to do is create a static variable to use as a counter.

Code:
static int i;
Then you need to increment the variable. The easiest way to do this is to increment the counter each time you get new data.

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! */

        i++; // this will increment the 'i' variable by 1.

        /* Add your own autonomous code here. */

        Generate_Pwms(pwm13,pwm14,pwm15,pwm16);

        Putdata(&txdata);   /* DO NOT DELETE, or you will get no PWM outputs! */
    }
  }
Now you can calculate the time by multiplying the time span(26.2) by the number if times(i) to get the actual time.

Code:
int time;

  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! */
        i++; // this will increment the 'i' variable by 1.
        time =  (i * 262)/2500 // if you avoid the decimal, by multiplying the time span by 10, your code will execute faster because it will not use a floatig points.
        // I divide the time(in 10000enths of a second) by 2500 so I get a result in 1/4 of a second

        Generate_Pwms(pwm13,pwm14,pwm15,pwm16);

        Putdata(&txdata);   /* DO NOT DELETE, or you will get no PWM outputs! */
    }
  }
Example code to drive forward 1 second, then reverse for 1 second.

Code:
int time;

  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! */
        i++; // this will increment the 'i' variable by 1.
        time =  (i * 262)/2500 // if you avoid the decimal, by multiplying the time span by 10, your code will execute faster because it will not use a floatig points.
        // I divide the time(in 10000enths of a second) by 2500 so I get a result in 1/4 of a second

        //drive code\\
        if (time < 4) pwm01 = pwm02 = 255; //forward
        else if(time < 8) pwm01 = pwm02 = 0; //reverse
        else if(time > 8) pwm01 = pwm02 = 127;//stop

        Generate_Pwms(pwm13,pwm14,pwm15,pwm16);

        Putdata(&txdata);   /* DO NOT DELETE, or you will get no PWM outputs! */
    }
  }
I think that is what your looking for.

Hope this helps, and sorry for the long post.
__________________
Eric Haskins KC9JVH
  #3   Spotlight this post!  
Unread 07-12-2006, 20:53
chris31 chris31 is offline
Team 2021 Captain
AKA: Chris Davidson
FRC #2021 (FA Robotics)
Team Role: Mentor
 
Join Date: Nov 2005
Rookie Year: 2006
Location: Atlanta, GA/ Fredericksburg,VA
Posts: 949
chris31 has a reputation beyond reputechris31 has a reputation beyond reputechris31 has a reputation beyond reputechris31 has a reputation beyond reputechris31 has a reputation beyond reputechris31 has a reputation beyond reputechris31 has a reputation beyond reputechris31 has a reputation beyond reputechris31 has a reputation beyond reputechris31 has a reputation beyond reputechris31 has a reputation beyond repute
Send a message via AIM to chris31
Re: Auto mode... need help

That assumes that your code will take the same time as the default code does. Maybe you have some intensive stuff and each loops takes longer than the 26.2 ms loop. Your code works effectivly for most things though. teh_pwnerer795, if you wanted to use the chips timer post back and ill post code for using that.
  #4   Spotlight this post!  
Unread 07-12-2006, 20:56
EHaskins EHaskins is offline
Needs to change his user title.
AKA: Eric Haskins
no team (CARD #6 (SCOE))
Team Role: College Student
 
Join Date: Jan 2006
Rookie Year: 2006
Location: Elkhorn, WI USA
Posts: 998
EHaskins has a reputation beyond reputeEHaskins has a reputation beyond reputeEHaskins has a reputation beyond reputeEHaskins has a reputation beyond reputeEHaskins has a reputation beyond reputeEHaskins has a reputation beyond reputeEHaskins has a reputation beyond reputeEHaskins has a reputation beyond reputeEHaskins has a reputation beyond reputeEHaskins has a reputation beyond reputeEHaskins has a reputation beyond repute
Send a message via MSN to EHaskins
Re: Auto mode... need help

I used a simpler approach this year and had no issue with it.

I would doubt that you could tax the processor to the point that the autonomous code would take longer than 26.2ms
__________________
Eric Haskins KC9JVH
  #5   Spotlight this post!  
Unread 07-12-2006, 21:03
prograid's Avatar
prograid prograid is offline
Registered User
AKA: Ben Cherian
FRC #0254 (The Cheesy Poofs)
Team Role: Alumni
 
Join Date: Oct 2004
Rookie Year: 2004
Location: San Jose
Posts: 80
prograid will become famous soon enough
Re: Auto mode... need help

Quote:
Originally Posted by EHaskins
I would doubt that you could tax the processor to the point that the autonomous code would take longer than 26.2ms
I would agree that this normally wouldn't be a problem. In fact, the way the RC works is that if the master processor doesn't get data back in 26.2 ms, your robot gets disabled. Therefore, it is possible that the loop will runner faster than 26.2 ms.

I would suggest using real timers.
For more information, take a look at IFI's white-paper (PDF).

They have a very nice explanation of how to use the timers built into the PIC.
  #6   Spotlight this post!  
Unread 07-12-2006, 21:35
teh_pwnerer795 teh_pwnerer795 is offline
Registered User
AKA: !!Mitch!!
FRC #1392
Team Role: Programmer
 
Join Date: Nov 2006
Rookie Year: 2006
Location: Ajax, Canada
Posts: 142
teh_pwnerer795 is just really niceteh_pwnerer795 is just really niceteh_pwnerer795 is just really niceteh_pwnerer795 is just really nice
Send a message via MSN to teh_pwnerer795 Send a message via Yahoo to teh_pwnerer795
Re: Auto mode... need help

Awesome.

I know rite now my code isnt very intensive at the moment.. but i do tend to have long code.. lol my engineering program for turing was 1500 lines when someppls were 100. but got it down to 150 once i got some logic into it!!...but ye i'll keep u posted if it works or not...
__________________
Great Art is Created; Master Pieces are Stolen

[n00b]Teh_Foxdonut teh_pwnerer795 - CounterStrike:Source
  #7   Spotlight this post!  
Unread 07-12-2006, 22:44
teh_pwnerer795 teh_pwnerer795 is offline
Registered User
AKA: !!Mitch!!
FRC #1392
Team Role: Programmer
 
Join Date: Nov 2006
Rookie Year: 2006
Location: Ajax, Canada
Posts: 142
teh_pwnerer795 is just really niceteh_pwnerer795 is just really niceteh_pwnerer795 is just really niceteh_pwnerer795 is just really nice
Send a message via MSN to teh_pwnerer795 Send a message via Yahoo to teh_pwnerer795
Re: Auto mode... need help

Code:
int time;

  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! */
        i++; // this will increment the 'i' variable by 1.
        time =  (i * 262)/2500 // if you avoid the decimal, by multiplying the time span by 10, your code will execute faster because it will not use a floatig points.
        // I divide the time(in 10000enths of a second) by 2500 so I get a result in 1/4 of a second

        Generate_Pwms(pwm13,pwm14,pwm15,pwm16);

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

no problem for the post... im sorta confused.. if the computer cycles at 26.2 ms... will it not cycle rougly 38 times in a second?

if so... your code.. where 'i' is increased by 1 every cycle, when it reaches 1 second.. i == 38.....

if so... time == 4 roughly at 1 second... shouldnt u divide it by 4? to get 1 second??? srry if i confused you


lol srry just trying to understand the logic behind 'time'
__________________
Great Art is Created; Master Pieces are Stolen

[n00b]Teh_Foxdonut teh_pwnerer795 - CounterStrike:Source
  #8   Spotlight this post!  
Unread 07-12-2006, 22:50
teh_pwnerer795 teh_pwnerer795 is offline
Registered User
AKA: !!Mitch!!
FRC #1392
Team Role: Programmer
 
Join Date: Nov 2006
Rookie Year: 2006
Location: Ajax, Canada
Posts: 142
teh_pwnerer795 is just really niceteh_pwnerer795 is just really niceteh_pwnerer795 is just really niceteh_pwnerer795 is just really nice
Send a message via MSN to teh_pwnerer795 Send a message via Yahoo to teh_pwnerer795
Re: Auto mode... need help

Quote:
Originally Posted by teh_pwnerer795

no problem for the post... im sorta confused.. if the computer cycles at 26.2 ms... will it not cycle rougly 38 times in a second?

if so... your code.. where 'i' is increased by 1 every cycle, when it reaches 1 second.. i == 38.....

if so... time == 4 roughly at 1 second... shouldnt u divide it by 4? to get 1 second??? srry if i confused you


lol srry just trying to understand the logic behind 'time'

OMG i am such an idiot I GET IT NOW SOO SRRY hm.. another question... how do i round? i remember doing it in java... not suer if its the same in C
__________________
Great Art is Created; Master Pieces are Stolen

[n00b]Teh_Foxdonut teh_pwnerer795 - CounterStrike:Source
  #9   Spotlight this post!  
Unread 07-12-2006, 23:51
Matt Krass's Avatar
Matt Krass Matt Krass is offline
"Old" and Cranky. Get off my lawn!
AKA: Dark Ages
FRC #0263 (Sachem Aftershock)
Team Role: Mentor
 
Join Date: Oct 2002
Rookie Year: 2002
Location: Long Island, NY
Posts: 1,187
Matt Krass has a reputation beyond reputeMatt Krass has a reputation beyond reputeMatt Krass has a reputation beyond reputeMatt Krass has a reputation beyond reputeMatt Krass has a reputation beyond reputeMatt Krass has a reputation beyond reputeMatt Krass has a reputation beyond reputeMatt Krass has a reputation beyond reputeMatt Krass has a reputation beyond reputeMatt Krass has a reputation beyond reputeMatt Krass has a reputation beyond repute
Send a message via AIM to Matt Krass
Re: Auto mode... need help

Quote:
Originally Posted by EHaskins
I used a simpler approach this year and had no issue with it.

I would doubt that you could tax the processor to the point that the autonomous code would take longer than 26.2ms

Actually the problem as mentioned before is its very unlikely to take that long. If memory serves it loops as fast as possible, so it could run anywhere from about 12ms to 26.2 and it will change depending on your autonomous code, if its really time sensitive, you should use the hardware timer, and its just good to know how to use that anyway.
__________________
Matt Krass
If I suggest something to try and fix a problem, and you don't understand what I mean, please PM me!

I'm a FIRST relic of sorts, I remember when we used PBASIC and we got CH Flightsticks in the KoP. In my day we didn't have motorized carts, we pushed our robots uphill, both ways! (Houston 2003!)
  #10   Spotlight this post!  
Unread 08-12-2006, 10:57
Dave Scheck's Avatar
Dave Scheck Dave Scheck is offline
Registered User
FRC #0111 (WildStang)
Team Role: Engineer
 
Join Date: Feb 2003
Rookie Year: 2002
Location: Arlington Heights, IL
Posts: 574
Dave Scheck has a reputation beyond reputeDave Scheck has a reputation beyond reputeDave Scheck has a reputation beyond reputeDave Scheck has a reputation beyond reputeDave Scheck has a reputation beyond reputeDave Scheck has a reputation beyond reputeDave Scheck has a reputation beyond reputeDave Scheck has a reputation beyond reputeDave Scheck has a reputation beyond reputeDave Scheck has a reputation beyond reputeDave Scheck has a reputation beyond repute
Re: Auto mode... need help

Quote:
Originally Posted by teh_pwnerer795
how do i round? i remember doing it in java... not suer if its the same in C
What are you trying to round? If you're using int variables, there is no decimal part and all math operations will result in truncation of the decimal (i.e. 1/4 => 0, 5/2 => 2).

If you really needed the decimal part, you could use the float type instead of int. There are some problems with doing this discussed here, and I wouldn't really recommend doing this on the RC.

EHaskins offered up some good suggestions, but there is a slight annoyance with it. What happens if you have a 10 step time based routine and you need to change the first duration to be a little longer or shorter? You have to change them all.

One way to fix it would be to use constants, and make them relative to each other.
Code:
#define AUTO_STEP1_END    (10)
#define AUTO_STEP2_END    (AUTO_DURATION_STEP1 + 5)
.....
if(i <= AUTO_STEP1_END)
{
....
}
else if(i <= AUTO_STEP2_END)
{
...
}
...
If you want to make things a little more advanced, you could do something like this.
Code:
#define NOT_DONE           0
#define DONE               1
...
#define MAX_AUTO_STEP  3
...
enum
{
  PROG_STEP1,
  PROG_STEP2,
  PROG_STEP3,
  PROG_STEP_LAST = PROG_STEP2,
};
...
static int prog_done = NOT_DONE;
static int prog_step = 0;
...
int ret;
if(prog_step < PROG_STEP_LAST)
{
  switch prog_step
  {
    case PROG_STEP1:
      ret = do_step1(); // These function names could be more specific
      break;
    case PROG_STEP2:
      ret = do_step2(); // These function names could be more specific
      break;
    case PROG_STEP3:
      ret = do_step3(); // These function names could be more specific
      break;
    default:
      // Bad step number, exit now
      prog_step = PROG_STEP_LAST;
      break;
  }

  if(ret == DONE)
  {
    // Step is complete, move on
    prog_step++;
  }
}
else
{
  // Set all pwms to 127 to terminate the run
}
....
// Then you would define your program step functions to do what you needed

int do_step1(void)
{
   static int i = 0;
   int status = NOT_DONE;

   if(i >= 40)
   {
       // Set PWM values here
   }
   else
   {
     status = DONE;
   }
   
   return stats;
}

int do_step2(void)
{
   static int i = 0;
   int status = NOT_DONE;

   if(i >= 30)
   {
       // Set PWM values here
   }
   else
   {
     status = DONE;
   }
   
   return stats;
}

int do_step3(void)
{
.....
}
The benefit to this is maintainability. Each step is a self-containted program of its own residing within a function called from your autonomous loop. This gives you the advantage of not relying on absolute time. Each step can know how many loops to run for and report that it's done.

Here's another perk. If you want to add a delay between step 2 and 3, you could change the enum to have PROG_STEP_2A between PROG_STEP_2 and 3. Then, in your switch, you could do something like
Code:
...
case PROG_STEP_2A:
  ret = do_wait(100);
  break;
...

int do_wait(int loops)
{
  static int i = 0;
  int ret = NOT_DONE;

  if(i >= loops)
  {
    i = 0; // Leave the loop counter ready to go the next time.
    ret = DONE;
  }
  else
  {
    // Turn PWMs off
    i++;
  }
  return ret;
}
Now you have a nice reusable chunk of code that turns the motors off and waits for a certain number of loops before advancing. If all of a sudden you don't need that step anymore, you can simply comment you the function call and set ret to DONE. You burn a loop, but that shouldn't matter in most cases.
Code:
...
case PROG_STEP_2A:
  ret = DONE;
  // ret = do_wait(100);
  break;
...

Last edited by Dave Scheck : 08-12-2006 at 11:10.
  #11   Spotlight this post!  
Unread 08-12-2006, 15:02
Donut Donut is offline
The Arizona Mentor
AKA: Andrew
FRC #2662 (RoboKrew)
Team Role: Engineer
 
Join Date: Mar 2005
Rookie Year: 2004
Location: Goodyear, AZ
Posts: 1,313
Donut has a reputation beyond reputeDonut has a reputation beyond reputeDonut has a reputation beyond reputeDonut has a reputation beyond reputeDonut has a reputation beyond reputeDonut has a reputation beyond reputeDonut has a reputation beyond reputeDonut has a reputation beyond reputeDonut has a reputation beyond reputeDonut has a reputation beyond reputeDonut has a reputation beyond repute
Re: Auto mode... need help

Quote:
Originally Posted by Dave Scheck
EHaskins offered up some good suggestions, but there is a slight annoyance with it. What happens if you have a 10 step time based routine and you need to change the first duration to be a little longer or shorter? You have to change them all.

One way to fix it would be to use constants, and make them relative to each other.
I know this won't matter too much if this is just an off season thing, but what Dave just mentioned can be VERY helpful at competition. If you need to adjust one of your autonomous actions by 1/2 or 1 second, this makes it so much more convenient and doable (especially if that time comes during the playoffs in between matches where you have maybe 5 minutes to do it tops).
__________________
FRC Team 498 (Peoria, AZ), Student: 2004 - 2007
FRC Team 498 (Peoria, AZ), Mentor: 2008 - 2011
FRC Team 167 (Iowa City, IA), Mentor: 2012 - 2014
FRC Team 2662 (Tolleson, AZ), Mentor: 2014 - Present
  #12   Spotlight this post!  
Unread 08-12-2006, 16:21
aaeamdar's Avatar
aaeamdar aaeamdar is offline
Post-A-Holic
AKA: Paul Dennis
FRC #1719 (The Umbrella Corp)
Team Role: College Student
 
Join Date: Jan 2006
Rookie Year: 2005
Location: Baltimore, MD
Posts: 231
aaeamdar has a brilliant futureaaeamdar has a brilliant futureaaeamdar has a brilliant futureaaeamdar has a brilliant futureaaeamdar has a brilliant futureaaeamdar has a brilliant futureaaeamdar has a brilliant futureaaeamdar has a brilliant futureaaeamdar has a brilliant futureaaeamdar has a brilliant futureaaeamdar has a brilliant future
Re: Auto mode... need help

Quote:
Originally Posted by Matt Krass
If memory serves it loops as fast as possible, so it could run anywhere from about 12ms to 26.2 and it will change depending on your autonomous code, if its really time sensitive, you should use the hardware timer, and its just good to know how to use that anyway.
No, that's the entire point. It doesn't loop as quickly as possible. It does its calculations and idles for the remaining part of the loop time. While I'm not at all sure about your robot being disabled if you don't get data within 26.2 ms, it could be true. However, no reasonable code for your robot would go beyond the 26.2 ms loop. You're not calculating pi to the 500th decimal place, you're not using the cubic formula, and you certainly shouldn't be using an loop except an iteration loop. Therefore, 26.2 ms is a safe figure by design.

Hope this helps,
Paul
  #13   Spotlight this post!  
Unread 08-12-2006, 16:38
EHaskins EHaskins is offline
Needs to change his user title.
AKA: Eric Haskins
no team (CARD #6 (SCOE))
Team Role: College Student
 
Join Date: Jan 2006
Rookie Year: 2006
Location: Elkhorn, WI USA
Posts: 998
EHaskins has a reputation beyond reputeEHaskins has a reputation beyond reputeEHaskins has a reputation beyond reputeEHaskins has a reputation beyond reputeEHaskins has a reputation beyond reputeEHaskins has a reputation beyond reputeEHaskins has a reputation beyond reputeEHaskins has a reputation beyond reputeEHaskins has a reputation beyond reputeEHaskins has a reputation beyond reputeEHaskins has a reputation beyond repute
Send a message via MSN to EHaskins
Re: Auto mode... need help

Quote:
Originally Posted by Donut
I know this won't matter too much if this is just an off season thing, but what Dave just mentioned can be VERY helpful at competition. If you need to adjust one of your autonomous actions by 1/2 or 1 second, this makes it so much more convenient and doable (especially if that time comes during the playoffs in between matches where you have maybe 5 minutes to do it tops).
I agree. What I posted above was a quick way to get started, but as with anything there's room for improvement.
__________________
Eric Haskins KC9JVH
  #14   Spotlight this post!  
Unread 11-12-2006, 16:42
JBotAlan's Avatar
JBotAlan JBotAlan is offline
Forever chasing the 'bot around
AKA: Jacob Rau
FRC #5263
Team Role: Mentor
 
Join Date: Sep 2004
Rookie Year: 2004
Location: Riverview, MI
Posts: 723
JBotAlan has a reputation beyond reputeJBotAlan has a reputation beyond reputeJBotAlan has a reputation beyond reputeJBotAlan has a reputation beyond reputeJBotAlan has a reputation beyond reputeJBotAlan has a reputation beyond reputeJBotAlan has a reputation beyond reputeJBotAlan has a reputation beyond reputeJBotAlan has a reputation beyond reputeJBotAlan has a reputation beyond reputeJBotAlan has a reputation beyond repute
Send a message via AIM to JBotAlan Send a message via Yahoo to JBotAlan
Re: Auto mode... need help

I have to say, after a season and a half of asking the strategy guy how long he wants it to go out, then stepping into Calculator, then punching the wrong numbers, then typing the wrong number I just calculated into my code (now converted to 26.2ms cycles), then seeing it totally mess up when I put it on the field...having a *real* timer is SO nice. I implemented the hardware timer, so now I have a Windows-style GetTickCount() type function, and it works very accurately. The scouts tell me that the bot needs to be in front of the other bot in 2 seconds: I give them 2 seconds. Not 2000ms / 26.2ms = 76 cycles--blech. Those never worked right for me.

What I haven't solved yet is the overflow issue. What data type do I use to hold the huge number? I have no idea. I can't reset the tick count to 0 each time it hits the upper limit my code is waiting for because I have more than one part of my code using this tick count. I think I'll use the hugest data type I can get--I'll have to look it up; I don't know C in and out.

JBot
__________________
Aren't signatures a bit outdated?
  #15   Spotlight this post!  
Unread 11-12-2006, 17:07
mluckham's Avatar
mluckham mluckham is offline
Registered User
FRC #0758 (Sky Robotics)
Team Role: Mentor
 
Join Date: Mar 2006
Rookie Year: 2006
Location: Ontario, Canada
Posts: 116
mluckham will become famous soon enoughmluckham will become famous soon enough
Re: Auto mode... need help

Here's some code for an interrupt-driven timer.

Call Timer_1_Initialize() in the User_Initialization routine in user_routines.c, add the call to the interrupt handler to user_routines_fast.c. Time is in the timer_ variables.

Mike


Code:
/*******************************************************************************
*
*	TITLE:		wallclock.h 
*
*	VERSION:	0.1 (Beta)
*
*	DATE:		23-Sep-2006
*
*	AUTHOR:		Mike Luckham
*				sunrise@sunsys.net
*
********************************************************************************
*
*				You are free to use this source code for any non-commercial
*				use. Please do not make copies of this source code, modified
*				or un-modified, publicly available on the internet or
*				elsewhere without permission. Thanks.
*
*				Copyright ©2006-2007 Mike Luckham. All rights are reserved.
*
********************************************************************************
*
*	CHANGE LOG:
*
*	DATE         REV  DESCRIPTION
*	-----------  ---  ----------------------------------------------------------
*	23-Sep-2006  0.1  Mike Luckham - Original code.
*
*******************************************************************************/

#ifndef _WALLCLOCK_H
#define _WALLCLOCK_H

typedef struct {
    unsigned int hours;
	unsigned int minutes;
	unsigned int seconds;
	unsigned int msec;
	unsigned int usec;
	unsigned long timestamp;
} WallTime;

//  Do not write to any of these variables

extern volatile unsigned long timer_msecClock;				// milliseconds since system start (overflows after 49.7 days)

extern unsigned long Timer_1_MicrosecondsTimestamp(void);

#define timer_usecClock	Timer_1_MicrosecondsTimestamp()		// microseconds since system start (overflows after about 71 minutes)

// current time decoded

#define timer_microseconds	Timer_1_Microseconds()	
extern volatile unsigned int timer_milliseconds;
extern volatile unsigned int timer_100msec;
extern volatile unsigned int timer_seconds;
extern volatile unsigned int timer_minutes;
extern volatile unsigned int timer_hours;

extern void Timer_1_Reset(void);
extern void Timer_1_Initialize(void);
extern void Timer_1_Int_Handler(void);
extern void Timer_1_Load_Prescale(void);
extern unsigned int Timer_1_Microseconds(void);

extern void Timer_1_ReadTimeStruct(WallTime *);


#endif


Code:
/*******************************************************************************
*
*	TITLE:		wallclock.c 
*
*	VERSION:	0.1 (Beta)
*
*	DATE:		23-Sep-2006
*
*	AUTHOR:		Mike Luckham
*				sunrise@sunsys.net
*
*	COMMENTS:	This source code in this file implements a clock that is useful
*				for tracking time at millisecond resolution.  A timestamp value
*				is useful for comparing the time between events.  The timestamp
*				is decoded into hours/minutes/seconds/milliseconds, and the
*				current time can be read at microsecond resolution.
*
*				Since the clock is interrupt-driven, it runs independently and
*				maintains correct time between calls to user_routines.c by the master
*				scheduler.
*
*				To use the code, include wallclock.h in the user_routines.c and
*				user_routines_fast.c source files, and:
*
*				1) call Timer_1_Initialize() from user_routines.c in User_Initialization()
*
*				2) add the following to user_routines_fast.c in InterruptHandlerLow():
*
*					if (PIR1bits.TMR1IF && PIE1bits.TMR1IE)
*					{
*						PIR1bits.TMR1IF = 0;		// clear the interrupt flag
*				    	Timer_1_Int_Handler();
*					}
*
*				3) when you need to measure elapsed time, store timer_msecClock into
*				an unsigned long variable at the beginning of the interval, then subtract
*				timer_msecClock from the saved value at the end of the interval to obtain
*				the number of milliseconds which have elapsed.
*
*				If you need the microsecond portion of the time, store the value returned
*				by the timer_microseconds macro into an unsigned long variable.  Probably this
*				is of limited usefulness, although it could be useful in a busy-loop.
*
*				The decoded time is available in the timer_ variables.  Here is an example of
*				how to use them:
*
*					printf("%u:%u:%u.%u.%u\n", timer_hours, timer_minutes, timer_seconds, timer_milliseconds, timer_microseconds);
*
*
********************************************************************************
*
*				You are free to use this source code for any non-commercial
*				use. Please do not make copies of this source code, modified
*				or un-modified, publicly available on the internet or
*				elsewhere without permission. Thanks.
*
*				Copyright ©2006-2007 Mike Luckham. All rights are reserved.
*
********************************************************************************
*
*	CHANGE LOG:
*
*	DATE         REV  DESCRIPTION
*	-----------  ---  ----------------------------------------------------------
*	23-Sep-2006  0.1  Mike Luckham - Original code.
*
*******************************************************************************/


#include "ifi_aliases.h"
#include "ifi_default.h"
#include "wallclock.h"


/********** GLOBAL CLOCK VARIABLES ***********************************************/

volatile unsigned long timer_msecClock = 0L;		// milliseconds since system start (overflows after 49.7 days)

// current wall-clock time

volatile unsigned int timer_100msec = 0;			// increments once every 100 milliseconds
volatile unsigned int timer_milliseconds = 0;	// increments once per millisecond
volatile unsigned int timer_seconds = 0;			// increments once per second
volatile unsigned int timer_minutes = 0;			// increments once per minute
volatile unsigned int timer_hours = 0;			// increments once per hour

// for the current microseconds count, use Timer_1_Microseconds

WallTime wTime;


// preload the timer so that the interrupt-on-overflow occurs 1000 microseconds later
// for microprocessor clock crystal 40MHz/4 = 10MHz tick rate = 65535 - 10000 (0xD8EF)

#define PRELOAD_LOW	 0xD8
#define PRELOAD_HIGH 0xEF



/*******************************************************************************
* FUNCTION NAME: Timer_1_Reset
* PURPOSE:       resets clock variables to zero
* CALLED FROM:   user_routines.c
* ARGUMENTS:     none
* RETURNS:       real-time clock variables are reset
*******************************************************************************/
void Timer_1_Reset(void)
{
	timer_msecClock = 0L;
	timer_milliseconds = 0;
	timer_seconds = 0;
	timer_minutes = 0;
	timer_hours = 0;
}

/*******************************************************************************
* FUNCTION NAME: Timer_1_Load_Prescale
* PURPOSE:       preload the timer to overflow after 1000 microseconds
* CALLED FROM:   user_routines_fast.c, user_routines.c
* ARGUMENTS:     none
* RETURNS:       Timer1 is preloaded
*******************************************************************************/
void Timer_1_Load_Prescale(void)
{
					// NOTE:  Timer specification requires MUST write high byte
					//        first, then low byte

	TMR1H = PRELOAD_LOW;	// preload the timer so that the interrupt-on-overflow occurs 1000 microseconds later
	TMR1L = PRELOAD_HIGH;	// for microprocessor clock crystal 40MHz/4 = 10MHz tick rate = 65535 - 10000 (0xD8EF)
}


/*******************************************************************************
* FUNCTION NAME: Timer_1_Int_Handler
* PURPOSE:       Updates the real time clock variables
* CALLED FROM:   user_routines_fast.c
* ARGUMENTS:     none
* RETURNS:       real-time clock variables are updated
*******************************************************************************/
void Timer_1_Int_Handler(void)
{
	// update the millisecond-counter
	// probably will be more useful than the msec/sec/min/hours/days variables

	// avoid calling a function from within the Interrupt handler, other register
	// context will need to be saved with a #pragma in user_routines_fast.c
	//  Timer_1_Load_Prescale();

	TMR1H = PRELOAD_LOW;	// reload the timer so that the interrupt-on-overflow occurs 1000 microseconds later
	TMR1L = PRELOAD_HIGH;	// for microprocessor clock crystal 40MHz/4 = 10MHz tick rate = 65535 - 10000 (0xD8EF)

	timer_msecClock++;

	timer_milliseconds++;
	if (timer_milliseconds > 999)
	{
		timer_milliseconds = 0;

		if (++timer_seconds > 59)
		{
			timer_seconds = 0;

			if(++timer_minutes > 59)
			{
				timer_minutes = 0;

				timer_hours++;
			}
		}
	}

	if ((timer_milliseconds % 100) == 0)
		timer_100msec++;
}


/***********************************************************************************
* FUNCTION NAME: Timer_1_Microseconds
* PURPOSE:       fetch the number of microseconds since the timer last interrupted
* CALLED FROM:   user_routines.c
* ARGUMENTS:     none
* RETURNS:       microseconds since the last interrupt
***********************************************************************************/
unsigned int Timer_1_Microseconds(void)
{
	unsigned int tmr1;

					// NOTE:  Timer specification requires MUST read low byte
					//        first, then high byte

	tmr1 = (unsigned int) TMR1L + ((unsigned int) TMR1H << 8);	// convert to 16-bit, then negate

	tmr1 = ~tmr1 + 1;				// (2's complement) to get remaining ticks until overflow

	// scale to the clock frequency - see Timer_1_Load_Prescale() comments for the number
	// of ticks per microsecond

	return (tmr1 / 10);
}


/***********************************************************************************
* FUNCTION NAME: Timer_1_MicrosecondsTimestamp
* PURPOSE:       fetch a timestamp which includes the number of microseconds
* CALLED FROM:   user_routines.c
* ARGUMENTS:     none
* RETURNS:       microseconds since the last interrupt
***********************************************************************************/
unsigned long Timer_1_MicrosecondsTimestamp(void)
{
	// WARNING: this is quite expensive to call, probably not very useful

	return (timer_msecClock * 1000) + (unsigned long) Timer_1_Microseconds();
}



/*******************************************************************************
* FUNCTION NAME: Timer_1_Initialize
* PURPOSE:       configure the Timer1 interrupt to overflow and interrupt after
*				 1000 microseconds
* CALLED FROM:   user_routines.c
* ARGUMENTS:     none
* RETURNS:       Timer1 is configured and TMR1IF interrupt enabled
*******************************************************************************/
void Timer_1_Initialize(void)
{
  T1CONbits.TMR1ON = 0;		// disable the clock while programming it

  T1CONbits.TMR1CS = 0;		// use internal clock (10 MHz)
  T1CONbits.T1CKPS0 = 0;	// set prescaler to 1:1, or OSC/4.  A 40 MHz crystal divided by 4 gives 10 ticks per microsecond.
  T1CONbits.T1CKPS1 = 0;
  T1CONbits.RD16 = 0;		// read timer using two 8-bit reads of TMR1L followed by TMR1H
							// reading the timer and subtracting it's value from FFFFh gives the number of microseconds
							//  since the timer was last loaded

  Timer_1_Load_Prescale();

  Timer_1_Reset();			// reset time variables

  T1CONbits.TMR1ON = 1;		// enable the clock
  PIE1bits.TMR1IE = 1;		// enable the Timer1 overflow interrupt
}




/*******************************************************************************
* FUNCTION NAME: Timer_1_ReadTimeStruct
* PURPOSE:       safely read the time values without disturbance from the
*				 interrupt service routines
* CALLED FROM:   user_routines.c
* ARGUMENTS:     none
* RETURNS:       pointer to WallTime structure
*******************************************************************************/
void Timer_1_ReadTimeStruct(WallTime * wTime)
{
	int intEnabled;

	intEnabled = PIE1bits.TMR1IE;	// disable timer interrupts while loading structure

	if (intEnabled != 0)
		PIE1bits.TMR1IE = 0;		// disable the Timer1 overflow interrupt

	wTime->hours = timer_hours;
	wTime->minutes = timer_minutes;
	wTime->seconds = timer_seconds;
	wTime->msec = timer_milliseconds;
	wTime->usec = Timer_1_Microseconds();
	wTime->timestamp = Timer_1_MicrosecondsTimestamp();

	if (intEnabled != 0)
		PIE1bits.TMR1IE = 1;		// enable the Timer1 overflow interrupt

}

Add this to the InterruptHandlerLow() routine in user_routines_fast.c


Code:
	
if (PIR1bits.TMR1IF && PIE1bits.TMR1IE)	// wallclock.c timer interrupt?
	{
		PIR1bits.TMR1IF = 0;		// clear the interrupt flag
	    Timer_1_Int_Handler();
	}
Closed Thread


Thread Tools
Display Modes Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
10 ball auto mode nuggetsyl Scouting 22 27-02-2006 20:39
Sending variables to Auto Mode Adrien Programming 4 19-02-2006 21:51
auto mode nuggetsyl General Forum 12 13-02-2006 19:45
Auto mode help..... Moloch Programming 2 18-02-2005 09:18
Auto. mode!!! skitz547 Rules/Strategy 1 09-03-2003 22:37


All times are GMT -5. The time now is 02:06.

The Chief Delphi Forums are sponsored by Innovation First International, Inc.


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