The delay() function will give you at least 1/2 second delay, then your program will be again sharing the OS.
If you use delay(500) however, there will be a problem that you have used 1/2 your second, and now must run something from your program, and have the OS do it's thing, AND then turn the led back on, for the other 1/2 second.
That's not going to happen.
What you're going to want is something like delay(430) to (480), so with the small amount of time left over, the OS can have some, your program can have some, and the delay will actually wind up being closer to 1/2 second.
Have you tried having your program monitor the ticks of the clock, directly, as the program is running? Explicit control like that might give you finer timing control.
It would be just like you were timing something normally, but you wouldn't divide the answering ticks by ticks_per_second. You'd want that fine tick count number.
If you had the time, you could make your program self-adjusting, with this. So it would notice that the last led ON was on a 1/10th of a second too long, so it would shorten the next led period (the OFF), by 1/9th or 1/10th of a second.