I'll just give explanation number ## on how to use millis for timing (this has been repeated half a dozen times in the past month now, but oh well):
millis() returns an unsigned long, this is a number that can count in milliseconds and go for over a month without reaching its limit.
The 'unsigned' part says that it can't go into negative numbers, it will always be positive (without unsigned, half of your capacity will be used to allowing negative numbers).
If the number would reach its maximum, it will turn back to 0 (called 'roll-over'), more on this later, it goes to 0 because it is unsigned (can't go negative, otherwise it goes to the lowest possible number).
This is all fine and dandy, but how to use it?
millis() returns the time the arduino has been running in milliseconds.
If with each iteration of loop, or each call to your function, you save the current time (in an unsigned long), you can compare the times.
currentTime - pastTime = timePassed.
Remember the roll-over thing? even if pastTime is a very large number, and currentTime is very tiny, you'd end up with a very large negative number.. but it can't handle negative, which makes it 'roll over' again, producing a small number, which is the correct number of milliseconds that have passed, so it is safe against roll-over.
Ok, now you have the number of milliseconds that have passed since the previous call of loop, or the function, how to use this?
If you save the number of milliseconds it has to wait in a variable, and you remember at what part of the process you were, it is easy to proceed, no?
A small example in code (please copy-paste in your editor to get all the text and such lined up properly) using a technique called a 'state engine', it is as simple as seen, you can check it on wiki if you want to know more, anyways.. the code:
unsigned long currentTime = 0; //this variable will be overwritten by millis() each iteration of loop
unsigned long pastTime = 0; //no time has passed yet
int currentState = 0; //the default state
int wait = 0; //no need to wait, nothing has happened yet
pinMode(13, OUTPUT); //the LED we're going to blink.. I just put 13 in as a magic number so it doesn't spoil the view of the worthwhile millis code
pastTime = currentTime; //currentTime at this point is the current time from the previous iteration, this should now be pastTime
currentTime = millis(); //currentTime is now the current time (again).
unsigned long timePassed = currentTime - pastTime; //this is roll-over proof, if currentTime is small, and pastTime large, the result rolls over to a small positive value, the time that has passed
if(timePassed >= wait) //part1 of the state engine
switch(currentState) //part2 of the state engine, its this simple, an if and a switch
case 0: //the default state.. turn the led on!
digitalWrite(13, HIGH); //light the LED up!
wait = 500; //wait 500 milliseconds before doing something from this state engine again
currentState = 1; //the next state that should be executed is 1
break; //break out of the switch, else it'll execute the case below this one too
digitalWrite(13, LOW); //turn the LED off again
wait = 500; //wait 500 milliseconds again before turning the LED on again
currentState = 0; //turning the LED on again is done in state 0
I hope this was helpful and easy to follow, comments are welcome..