-
Notifications
You must be signed in to change notification settings - Fork 3
RDC Phase optimization
The contiki radio duty cycle (RDC) layer interfaces between the network stack and the radio driver. The radio is kept off as much as possible, briefly turning on to check for packets to be received. Typically this "channel check" is done at 4 or 8 Hz so as not to compromise response time. However the power savings for the receiver will be shifted to increased power requirements for the transmitter unless there is a mechanism for the tx to keep track of the rx wake periods. The rx RDC can be turned off by the application, one example being a USB-powered border router which is always listening, but it should still use the same RDC as all the nodes for network efficiency (else it would retransmit many times until the receiver wakes and ACKs the packet).
Conceptually this is not hard to accomplish, simply give both sides the same channel check interval and have the tx keep track of the phase of the rx based on the last successful transmission. The next tx can then be delayed until the rx is known to be awake. In practice different clock rates between the two adds complication. Unless both are crystal controlled the parameters for phase optimization need to be adjusted based on the observed phase drift.
Fortunately most PCs ping at a precise 1Hz rate, so sending a short ping (1 RF packet) will result in an ACK with precise time intervals.
Here is an example of the phase drift between a Raven and Econotag over 100 pings. The Econotag runs at 18778 rtimer ticks per second, thus an 8Hz RDC results in a 2347.25 tick phase window. At 8 Hz the Raven wakes for 500 microseconds based on its 7812 rtimer ticks per second, which is derived from the internal RC clock of the 1284p MCU. The Econotag strobes the ping packet until the Raven responds with an ACK, and the timing of the ACK relative to the Econotag rtimer shows the relative clock rates.
Here is the plot of phase, modulo 1 second, that shows the Raven clock loses 1/4 second in just about 20 seconds. The Econotag sends up to 32 packets over 2348 ticks, the number of those is shown in red. Blue shows the rtimer count when the ACK is received form the Raven.
1% accuracy is considered pretty good for the internal RC oscillator, but as can be seen if the Econotag started strobing at the last Raven phase, it would send 3 packets before the Raven wakes. If +/- 1% accuracy is considered it would have to start 1/80th of a second early with a 6 packet cost. Since the average number of strobes is only ~17 when no phase optimization is used, that gives only a 50% further reduction in Econotag tx power usage.
files/raven_channel_check_phase.png
The data was obtained using print in contikimac:
#if WITH_PHASE_OPTIMIZATION if(is_known_receiver && got_strobe_ack) { PRINTF("no miss %d wake-ups %d\n", packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[0], strobes); } if(!is_broadcast) { printf("%d %d\n",strobes,encounter_time%RTIMER_ARCH_SECOND); <------------------- if(collisions == 0 && is_receiver_awake == 0) { phase_update(&phase_list, packetbuf_addr(PACKETBUF_ADDR_RECEIVER), encounter_time, ret); } } #endif /* WITH_PHASE_OPTIMIZATION */
but the actual Econotag phase delay was disabled in order to see the drift. Keeping it disabled, but adding a print to the phase delay routine to show what the default would be:
if(!RTIMER_CLOCK_LT(expected, now)) { /* Wait until the receiver is expected to be awake */ printf("%d ",expected%cycle_time); // while(RTIMER_CLOCK_LT(RTIMER_NOW(), expected)); } return PHASE_SEND_NOW;
gives
files/raven_channel_check_phase_and_guard.png
The tx would have started at the previous phase less the "guard" time. In contikimac the default guard time is set to 10 * CHECK_TIME + CHECK_TIME_TX; for the econotag in this example CHECK_TIME is 8 rtimer ticks and CHECK_TIME_TX is 24 ticks giving a guard time of 104 ticks. That is the vertical distance between the light blue opposing arrow symbol and the dark blue box for the previous data point.
Starting the strobes at this point should give about 8 strobes per ping. Let's enable the actual tx delay and see:
files/raven_channel_check_phase_with_deferred_turnon.png
Voila! The bad news is that the minimum number of strobes is also 8 because of the forced early turnon even when the phase would have been correct. Obviously we want to tighten the guard time.
What does a web page load look like? As you might expect, after longer delays the number of strobes goes up because of the increased clock drift:
So let's try a first order drift correction to the estimated phase time. We save the time difference between the last two encounters in e->drift, then calculate the phase change per cycle:
#if DRIFT_CORRECTION { int32_t s; s = e->drift%cycle_time/(e->drift/cycle_time); //drift per cycle s = s*(now-sync)/cycle_time; //estimated drift to now sync += s; //add it in } #endif s = sync%cycle_time - now%cycle_time; //now compute estimated phase if (s > 0) wait = (rtimer_clock_t) s; else wait = (rtimer_clock_t) (cycle_time + s);
That indeed allows reducing the guard time, but not too much or failures will occur. The Raven does two channel checks spaced 500 microseconds apart so the encounter times can suddenly shift by that much (e.g.1014 seconds).
These spaced web page loads also show the failure, caused by two close packets that had the 500 microsecond shift followed by a longer delay over which that apparent drift was applied.
Of course the average packet delivery delay will still be half the channel check interval, plus the guard time (occasionally the transmitter will have to wait almost an entire channel check interval to ensure that minimum delay). In the below the green triangles are the actual delay in econtag rtimer ticks, 2347 ticks = 125 milliseconds)
Finally in real life the transmission will not always be successful within one channel check interval. RF traffic or noise detected by the CCA can cause a tx delay and a missed rx window. Insufficient guard time will make this more likely, as well as increasing the failures from drift extrapolation. This will add additional check intervals to the delivery delay:
Of course the timing could be more precise if everything was crystal controlled. The Raven has a 32768 watch crystal used for the 128 tick/second clock, however the fast rtimer is clocked by the less stable 1284p internal RC oscillator. Conversely the Econotag uses a 24MHz crystal for the rtimer and clock ticks are obtained through a low power ring oscillator that is calibrated at each startup. The stability of all the oscillators is easy to measure using a host computer, e.g by printing the times periodically in the main loop
#define STAMPS 100 if ((clocktime%STAMPS)==0) { printf("%lu %u\n",clocktime,RTIMER_NOW()); }
and using serial-log.pl to log the output to a file with host PC time stamps:
$ ~/contiki/tools/serial-log.pl -s -l econotag Starting econotag.log.on 12/04/2011 at 11:10:22 0009 30 622458 0019 40 811653 0029 50 1000860 0039 60 1190042 ...
Plotting and fitting the clock (red) and rtimer (blue) shows the low-power clock is slow by 540ppm. This may change each startup but does not matter for our purposes, it is the precise rtimer ticks are used for radio turnon. We pick 18897 ticks per second; the maximum accuracy we are going to get is ~0.5/18897 = 27ppm since that is the tick spacing. We might want to change that up or down one depending on the observed drift betwen it and the Raven. Note the above used 18778 ticks/second; that was based on an erroneous comparison to the low-power clock.
A similar log shows the Raven watch crystal is 65 ppm fast. On the Raven the rtimer can be phase-locked to the crystal using negative feedback through the RC oscillator frequency (OSCCAL), e.g. once per second during the clock tick interrupt.
So the rtimer has a similar long term accuracy. Note the Raven 16 bit rtimer overflows every 8 seconds!
Now we try the 100 pings:
The jags are undoubtedly the phase corrections on the Raven side. But we know the Raven is phase locked to a pretty good crystal, so the downward drift suggests the Econotag is sampling too fast. Increasing RTIMER_ARCH_SECOND to 18898:
That is about as good as we can hope for. It corresponds to a drift of ~1/16 second over 100 seconds, about 650 ppm short term.