
前回はローカルXBeeで受信したフレームのFrames LogのTimeの欄の時間ズレについて解説しましたが、今回はこの時間ズレについてもう少し深く解説していきます。
前回の解説ではローカルXBeeで検出される不規則な時間ズレは通信レイヤの遅延によるものと考えられ、CSMA/CA(チャネル利用可否確認)やACK待ち時間・リトライ及び通信混雑や干渉が原因と思われることを解説しました。
今回はリモートXBeeからの送信側のタイミング詳しく調べるため、3軸加速度センサKXR94-2050モジュールからX,Y,Z軸方向の加速度データを読み出す際にtimestampを付けて確認することにしました。以下のコードをリモートXBeeのMicroPython Terminalで実行します。4行目のCOORDINATOR_64BIT_ADDRはご自分のローカルXBeeのシリアルナンバーに変更してください。
import xbee
import utime
from machine import Pin, ADC
COORDINATOR_64BIT_ADDR = b'\x00\x13\xA2\x00\x41\xAE\x36\x69'
# Initialize ADC for DIO0, DIO1, DIO2
adc_pin0 = Pin("D0", Pin.IN, Pin.PULL_UP)
adcx = ADC(adc_pin0)
adc_pin1 = Pin("D1", Pin.IN, Pin.PULL_UP)
adcy = ADC(adc_pin1)
adc_pin2 = Pin("D2", Pin.IN, Pin.PULL_UP)
adcz = ADC(adc_pin2)
print("Starting data transmission to coordinator...")
def precise_delay_ms(delay_ms):
start = utime.ticks_ms()
while utime.ticks_diff(utime.ticks_ms(), start) < delay_ms:
pass
while True:
start_time = utime.ticks_ms()
voltage_mv = xbee.atcmd('%V')
supply_voltage_v = voltage_mv / 1000.0
rssi_val = xbee.atcmd("DB")
rssi_dbm = -rssi_val
timestamp = utime.ticks_ms()
raw_adcx_value = adcx.read()
raw_adcy_value = adcy.read()
raw_adcz_value = adcz.read()
adcx_voltage = (raw_adcx_value / 4095.0) * supply_voltage_v
adcy_voltage = (raw_adcy_value / 4095.0) * supply_voltage_v
adcz_voltage = (raw_adcz_value / 4095.0) * supply_voltage_v
adcx_voltage = adcx_voltage - supply_voltage_v / 2
adcy_voltage = adcy_voltage - supply_voltage_v / 2
adcz_voltage = adcz_voltage - supply_voltage_v / 2
accelx = adcx_voltage / 0.66
accely = adcy_voltage / 0.66
accelz = adcz_voltage / 0.66
data_payload = "{:08d},Vref: {:.3f}V, RSSI: {:d}dBm, Accel_x: {:.3f}g, Accel_y: {:.3f}g, Accel_z: {:.3f}g".format(
timestamp, supply_voltage_v, rssi_dbm, accelx, accely, accelz
)
print("\n--- Sending Data ---")
print("Payload: {}".format(data_payload))
try:
xbee.transmit(COORDINATOR_64BIT_ADDR, data_payload.encode('utf8'))
print("Data sent successfully.")
except Exception as e:
print("Error sending data: {}".format(e))
precise_delay_ms(100) # ディレイ
end_time = utime.ticks_ms()
loop_time = utime.ticks_diff(end_time, start_time)
print("Loop time: {} ms".format(loop_time))
ここで、timestamp を取得するため使用したutime.ticks_ms()に関して解説します。utime.ticks_ms()は呼出し時点での稼働時間をミリ秒単位で返す機能があります。稼働時間は最大値に達するとラップアラウンドし、一周して最低値に戻ります。ラップアラウンド値はDigiから公開されていません。
上記のコードを実行した際のリモートXBeeのMicroPython Terminalのダイアログです。Payloadの直後に示されている値がtimestampです。また、前回のtimestamp入れる前の周期が約134msでしたが、今回のtimestampを加えた周期の平均が208msとなっていることから、timestamp の取得には約70msの時間を要していることが分かります。この値を確認するLoop timeと整合性が取れていることが分かります。

次にローカルXBeeに送信されたフレームを示します。フレームの時間差をFrames LogのTimeから読み取った一例を示します。単位はmsで表示しています。時間差にはゆらぎが確認できます。
204, 217, 229, 207, 164, 227, 218, 186, 207, 218, 207, 223, 182, 218, 206
この時間差の平均が207.5msであることから、送信側のローカルXBeeの周期の平均値である208msと整合していることがわかります。
送信フレームの時間間隔の精度を確認するためにtimestampを用いて検証した結果、加速度データのサンプリングには数ミリ秒程度のわずかなばらつきは見られたものの、大きな揺らぎはなく、全体として正確に計測されていることが確認できました。
