Log in

View Full Version : sleep()


Yellow Eyes
20-02-2004, 21:38
In our code, we want to use the sleep() function. When we try to compile we get an error saying it can't find the function sleep(). What would we need to include in order to get this to work?

KenWittlief
20-02-2004, 21:40
I dont think you want to use any of the sleep modes - there is code that has to run for the RC to function correctly - the code runs in one continious loop - if you put the uP to sleep, it will stop till an interrupt occurs - I think it would cause the RC to lock up or reset on you.

Sleep modes are normally for low power applications, like PDAs or cell phone - your bot will be drawing 50 to 100 amps during a match, so whats 0.1 Amps more or less going to accomplish?

Yellow Eyes
20-02-2004, 21:43
what about a pause function? Same results?

KenWittlief
20-02-2004, 21:48
same problem, you have to let the main loop run, or the code that is buried in the RC (that we dont see) will say "hey, the user code stopped running, turn off all the victors and relays until it comes back"

( of course it says that in binary: 00011000101010101101101 :c)

Yellow Eyes
20-02-2004, 22:06
I was just informed it will be sleep(1); will that 1 millisecond make a difference and cause those problems?

SeanCassidy
20-02-2004, 23:33
What you could do(for autononmous) was have a start time and an end time to all things. Sort of like this:
//Autonomous code
go(1,0,18); //Go forward (1 = fwd, 2 = rev), start at 0, and end at 1800ms
turn(1,19,25); //Turn (1 = left, 2 = right), start at 1900ms end at 2500ms
//Notice the 1000ms delay!
moveArm(2,35,40); //Move arm ( 1 = up, 2 = down), start at 3500ms end at 4000ms

Of course, you'll need to use interrupts (use the white paper from Innovation First), and add a static counter to the t100msDelay, for increments of 100ms. More precision that using seconds. But, the way you should do it is it just sets a pwm (or whatever) equal to the correct value, and move on, when it comes back (you'll have to make it know that it already completed one and it's time to finish up) just set it to 127 or whatever. Very useful and very effective.

Astronouth7303
21-02-2004, 21:33
So is there a way to 'wait' while still having interrupts going? this would be the easiest way to write a Autonomous Script. You know, Left=255;Right=255;Wait(600);.

mtrawls
22-02-2004, 10:14
So is there a way to 'wait' while still having interrupts going? this would be the easiest way to write a Autonomous Script. You know, Left=255;Right=255;Wait(600);.

I'm sorry, but I don't understand what the advantage is of waiting. Why would you need to pause at a specific instruction for some amount of time? What would you need to do in auton mode that couldn't be accomplished by having a state where the drive motors are sent neutral values? You could just be sitting still "waiting" for some input to come your way ... but you don't need to mess with timer's at all. I just don't see the need, so please explain if I am mistaken ...

ChrisA
22-02-2004, 12:31
There's something called a "FOR LOOP". In this loop, you can specify how long it stays in the loop. You could increment a variable there if you wanted to 'wait' for a certain amount of time. Or, you could use what we like to call a "TIMER". Timers count time. Time can be used for waiting.

Maybe you should be a little more specific on what you're trying to do.

deltacoder1020
22-02-2004, 12:43
There's something called a "FOR LOOP". In this loop, you can specify how long it stays in the loop. You could increment a variable there if you wanted to 'wait' for a certain amount of time. Or, you could use what we like to call a "TIMER". Timers count time. Time can be used for waiting.

Maybe you should be a little more specific on what you're trying to do.

but do remember that you need to call putdata every 26.2ms or so, or else the processor will shut down, which would not be a good thing in the middle of a match.

Ryan M.
22-02-2004, 14:51
There's something called a "FOR LOOP". In this loop, you can specify how long it stays in the loop. You could increment a variable there if you wanted to 'wait' for a certain amount of time. Or, you could use what we like to call a "TIMER". Timers count time. Time can be used for waiting.

Maybe you should be a little more specific on what you're trying to do.If you care, the struture of the for loop is this:

for(initiazation; test; increment)
{
// body of loop
}


It is more flexible than that form indicates, but that would be the most common way to use it. A quick example of it actually being used as a "pause."

// Somewhere at the top
unsigned int i;

// Later on
for(i = 0; i < 10; i++)
{
// Do nothing
}

This code would cause it to loop ten times and then continue.

Note that if you were using this as a timer, it would be different at different battery charges as the controller would run slower.

Anyways, if anyone cares, there it is.

jacob_dilles
22-02-2004, 15:18
instead of going to sleep, i would count loops till the required delay has passed. stoping a program is a bad thing, just because of the way the program loop is structured. if that doesnt work, i would use a timer with an inturupt.

KenWittlief
22-02-2004, 18:56
Note that if you were using this as a timer, it would be different at different battery charges as the controller would run slower.



?!?!?!?! :ahh:

the microprocessor runs on 5V, regulated from the 12 or 7.2V batteries - and the timing is controlled by a crystal that doesnt care what the battery voltages are

the execution of uP instruction cycles will be dead accurate repeatable, no matter what the state of your battery is, until the battery drops far enough to cause a reset.

I think the people that are contemplating wait states, for loops, do loops or while loops in their code really need to get the default users manaul and get a grasp on how this SW runs

the program takes in inputs from the operator
then it does your processing
then it outputs the results of your processing to the victors and spikes

those three major tasks repeat continiously - you DONT want to pause or stop or put timing delays in your processing area - you want the code to continue to run and loop as fast as it can

so if you are waiting for something to happen, and it hasnt happend yet, then do nothing and check again on the next 'pass' of the SW.

Putting wait states or delays in your code is one of the surest ways to make the controller lock up, and set all your outputs to 'off' - when this happens your bot will go dead and you will have a very expensive, very fancy statue sitting on the field infront of 3000 people.

kristen
22-02-2004, 20:00
Ok, you'll need two global variables (put them in user_routines_fast.c, or something):
Code:
unsigned int delay_count = 0;
unsigned int delay_constant = 0;
enum {PROGRAM_RUNNING, PROGRAM_DELAY} program_state = PROGRAM_RUNNING;

Have a function:
Code:
void delay(unsigned int count)
{
if (!delay_constant) {
delay_constant = count;
delay_count = 0;
program_state = PROGRAM_DELAY;
}
if (delay_count >= delay_constant) {
delay_constant = delay_count = 0;
program_state = PROGRAM_RUNNING;
} else {
delay_count += 26;
}
}
This function should be called something like this: (in user_routines_fast.c)
Code:
Getdata(&rxdata); /* DO NOT DELETE, or you will be stuck here forever! */

if (PROGRAM_RUNNING == program_state) {
/* Add your own autonomous code here. */
} else {
delay(0);
}

Putdata(&txdata); /* DO NOT DELETE, or you will get no PWM outputs! */
}
Now, anytime you want to set a delay, simply have a call to delay(milliseconds) somewhere in the autonomous code.

Most of this might not compile.

.. A certain programmer on my team who is unnamed is tooo shy to post this himself! ;D

Astronouth7303
22-02-2004, 20:50
My thought was that after it's done waiting, you set a new value. And just do a putdata and a getdata in the loop.

jacob_dilles
22-02-2004, 20:53
im sorry that i have to reiterate this, but you CAN NOT stop the program code from looping! no matter if it is with a non exastant "wait()" command or a for loop that devides PI by 100 million 50 thousand times, dont do it! it is much better, and perhaps the only viable solutuion, if you count the loops rather then trying to stop in the middle of one. each loop is ~26 ms. its not that hard to make 1 variable. comon guys.

Astronouth7303
22-02-2004, 21:12
It's not that, it's that the main loop has different iteration times depending on what is executed. Besides, It'd be so much cooller if we got it to work.

And like I said, just put calls to putdata and getdata in the loop.

KevinB
22-02-2004, 21:21
Note that if you were using this as a timer, it would be different at different battery charges as the controller would run slower.
Ken was right when he said that the timer will always run at the same speed. Texan probably meant that the motors being controlled by the timer would run slower ... which is true.

Getting back to the original focus of this post ... why do you want a sleep function? If you post the reason for your request for a sleep function, you'll probably get much better help.

jacob_dilles
22-02-2004, 21:22
if your going to the point where the diffrence between 23 and 26 ms matters, then use a timer inturupt. this is not a basic stamp lol

Astronouth7303
22-02-2004, 21:33
Any wait/pause code is the basis of a DriveForTime() Routine

jacob_dilles
22-02-2004, 21:35
Any wait/pause code is the basis of a DriveForTime() Routine
yesm. i think were arguing the same thing here.

mtrawls
22-02-2004, 21:56
Any wait/pause code is the basis of a DriveForTime() Routine

What? DriveForTime should do some driving for a given time ... but I don't see how any waiting is implicit in the function. Am I grossly mistaken? You can use a timer interrupt to drive for the specified amount of time, all you do is say:

if (time_from_start < time_to_drive) { put code to drive here }
else { as you are done driving, move on to the next thing }


Where's the need to wait? If you are 'pausing' (stuck in the loop for some reason), you sure aren't driving. Care to elaborate your thinking on the matter?

KevinB
23-02-2004, 00:00
Although there are easy ways to make the processor "pause" or "wait" as described above, they are probably not the best way to implement this function on the IFI Controller. The Master processor expects to receive a data packet from the user processor every 26.2ms.

This means you cannot pause the controller for longer than 26.2ms at a time and still have the control system function.

The best bet is to increment a counter every time a new data packet is received from the master processor. If you need finer control than that, use a timer interrupt.

gnormhurst
23-02-2004, 17:06
It's not that, it's that the main loop has different iteration times depending on what is executed.

Do you mean "execution times"? I take "iteration time" to be the time between iterations of the 26.2 ms loop area. I actually measured this with a scope on Saturday, it was very interesting:

while (1) /* This loop will repeat indefinitely. */
{

if (statusflag.NEW_SPI_DATA) /* 26.2ms loop area */
{ /* I'm slow! I only execute every 26.2ms because */
/* that's how fast the Master uP gives me data. */
rc_dig_out17 = 1; // take pin 17 high
Process_Data_From_Master_uP(); /* You edit this in user_routines.c */

if (autonomous_mode) /* DO NOT CHANGE! */
{
User_Autonomous_Code(); /* You edit this in user_routines_fast.c */
}
}
Process_Data_From_Local_IO(); /* You edit this in user_routines_fast.c */
rc_dig_out17 = 0; // clear pin 17 /* I'm fast! I execute during every loop.*/
} /* while (1) */

This made a pulse of about 4 ms in duration (the "exectution time" of my code), with a (measured) cycle time ("iteration time") of about 26 ms. Hitting certain buttons would change the 4 ms to something else like 3 ms as my code changed modes, but the period remained 26 ms. It seemed pretty rock-solid. Except when very strange things were happening; see my earlier post (http://www.chiefdelphi.com/forums/showthread.php?t=25776) on that. But that was something broken.

One reason a delay might be useful is to reduce the frequency of calls to Generate_Pwms(). See the reply from Kevin Watson to the post mentioned above.

-Norm

KenWittlief
23-02-2004, 17:12
Ive been wanting to scope the loop myself, but havent got to it yet- thanks for instrumenting your RC.

One thing I have not been able to figure out. The main loop looks for new input from the OI, and if it doesnt see it, it call the user_fast code

I dont see anything in the fast code to throttle it back - can you put your toggles at the beginning and end of the fast section and see how fast it runs with your scope for us?

I thought they said it runs every 4mS or so, and you have to be carefull not to overwhelm the pwms by changing them too fast - I also think you cannot do a get_analog_value... too quickly either?

but does anyone know - is the fast code loop timed by some event (the get or put data maybe?)

and is its period consistant?

BTW - if you are looking at timing be sure to comment out all your printf statements - there seems to be a whole library of code behind them, I think they will make a drastic reduction in your loop speed.

mtrawls
23-02-2004, 22:22
BTW - if you are looking at timing be sure to comment out all your printf statements - there seems to be a whole library of code behind them, I think they will make a drastic reduction in your loop speed.

I can say from experience that the printf libraries do make a difference. All the "horror" stories my SICP instructor told me a couple of years ago about debug statements causing or removing bugs (the act of observing disturbs the observed?) have come true. Using the timing interrupts and for our auton code (on the EduBot at least), I've come across situations where putting a printf statement causes problems .. and then where it removes them. Needless to say, it was a pain figuring out that the printf statement caused it -- luckily my old teacher had warned me, or I wouldn't have even thunk it.

velocipenguin
23-02-2004, 22:30
All the "horror" stories my SICP instructor told me a couple of years ago about debug statements causing or removing bugs (the act of observing disturbs the observed?) have come true.

Bugs like those are colloquially known as "Heisenbugs", after Heisenberg's Uncertainty Principle, which states that observing something will alter that which you are trying to observe. They're ever-so-fun to track down.

KenWittlief
24-02-2004, 07:42
putting debug statements in code is a significant change to its content.

HW guys have it even worse - Every HW engineer I know can tell you about some circuit they worked on that they were testing with a scope, and as long as the scope was connected, the circuit worked, but when you remove the probe it stopped working

all due to the slight capacitance of the probe altering the circuit they were trying to see.

gnormhurst
24-02-2004, 10:05
I've been wanting to scope the loop myself, but havent got to it yet- thanks for instrumenting your RC.

Thanks, but I got the idea from someone on this forum.

One thing I have not been able to figure out. The main loop looks for new input from the OI, and if it doesnt see it, it call the user_fast code.


That took me a little time to figure out. The fast code (Process_Data_From_Local_IO()) is called every loop of the while(1) loop. The "slow" user code is called in addition very occasionally in the while(1) loop when new data is ready (if (statusflag.NEW_SPI_DATA) ).

Don't see anything in the fast code to throttle it back - can you put your toggles at the beginning and end of the fast section and see how fast it runs with your scope for us?

I did that, too, at the time, just to see. I didn't measure the rate, but it looked like hundreds of times for each call of Process_Data_From_Local_IO(). An easier, non-scope way would be to run a counter in the main while( 1 ) loop, then print it and reset it just before calling Process_Data_From_Local_IO().

...I was doing integer division in a few places in my joystick calculations and I was worried that my code was too slow, but was relieved to see that it runs in only 4 ms. Whew!

deltacoder1020
24-02-2004, 11:10
Don't worry - for the most part, integer division is just fine. It's only when you get into floating-point numbers that math operations start to kill you.