LoPy and nanogateway example: Inaccurate timing prevent OTAA join



  • @robert-hh Thanks for the reply. Now the client associates with the gateway, but after that the packets are not relayed to the network. I get like every 16th packet relayed. The gateway and the client are 5 meters away and the client works with other gateways without issues (esp8266+RN2483A)
    In the gateway console i cant see the packet from the client.
    Also there is no Window_compensation in the code.
    The only related code here is:
    UDP_THREAD_CYCLE_MS = const(10)
    WDT_TIMEOUT = const(120000)
    COMPENSATION_SLOPE = const(-4176)
    COMPENSATION_OFFSET = const(-1667)



  • @kiromn The timing issue in the firmware should be solved in V1.17.3.b1. At least that one works for me. It needs the updated nanogateway example form the lib repository, which according to my tests is still off by 10 ms.
    You can also try the version I am using myself, which is here:
    https://github.com/robert-hh/pycom-libraries/blob/nanogateway/examples/lorawan-nano-gateway/nanogateway.py
    You might have to adapt it to your region. There is a definition of WINDOW_COMPENSATION at the begin, which is set to -10ms, to cope with the 10 ms delay I see. The standard code would have that set to 0 (if it would exist).



  • Can you please tell me which file should i change for the gateway ?
    This issue drives me mad in the last half an year.



  • @daniel @jmarcelino Jose suggested another approach for the ticks_us() function, similar to the ticks_ms() one, which is:

    STATIC mp_obj_t time_ticks_us(void) {
        struct timeval tv;
        gettimeofday(&tv, NULL);
        return mp_obj_new_int_from_uint(((tv.tv_sec * 1000000) + tv.tv_usec));
    }
    

    But since that one is already implemented in esp32_mphal.c, one could simply use:

    STATIC mp_obj_t time_ticks_us(void) {
        return mp_obj_new_int_from_uint(mp_hal_ticks_us());
    }
    

    As simple loop test, creating square wave with 5 s period, resulted in period times of 5.00015 to 5.00020 s for all three variants. Besides the extra call level, then using what's already there seems most elegant.
    The test with the nanogateway also succeeded.
    Edit: There are also a mp_hal_ticks_ms() and mp_hal_ticks_s()



  • @daniel Yes, these are the two places which I changed too.

    You are right, I read it too quickly and missed it.

    @daniel While changing tick_us(), we could also change ticks_ms() to be based on the same timer. It's a 64 bit quantity, so the basic timer will not overflow, before ticks_ms() does. Actually, it will not overflow within ~ 14000 years, at which time it might not matter.

    Makes sense!



  • @daniel While changing tick_us(), we could also change ticks_ms() to be based on the same timer. It's a 64 bit quantity, so the basic timer will not overflow, before ticks_ms() does. Actually, it will not overflow within ~ 14000 years, at which time it might not matter.



  • @daniel Yes, these are the two places which I changed too.



  • Hi Robert,

    That is awesome, thanks for the investigation. I guess the change also needs to be applied here:

    https://github.com/pycom/pycom-micropython-sigfox/blob/master/drivers/sx127x/sx1272/sx1272.c#L1076

    and here:

    https://github.com/pycom/pycom-micropython-sigfox/blob/master/drivers/sx127x/sx1276/sx1276.c#L1241

    Correct?

    Cheers,
    Daniel



  • @robert-hh
    Really good finding as always



  • @robert-hh @jmarcelino Problem solved. The reason was the inaccurate timing of ticks_us(). I changed that to use the CPU clock. It reads now as:

    #define CLK_FREQ (APB_CLK_FREQ / 2)
    STATIC mp_obj_t time_ticks_us(void) {
        return mp_obj_new_int_from_uint((uint32_t)(get_timer_counter_value()/(CLK_FREQ / 1000000)));
    }
    STATIC MP_DEFINE_CONST_FUN_OBJ_0(time_ticks_us_obj, time_ticks_us);
    

    Since the sx127x drivers need the same clock source, these drivers also have to be changed accordingly. As a result, join now works even with the default 10ms RxError setting.
    Picture below. Greed is the receive window, with the raising edge at the start of the 26 ms window (since join is successful, it does not go low). Yellow is the RF at the gateway antenna.
    0_1519760968060_otaa_10ms_good.jpg
    There is still some variation, but all joins worked, at least at the second attempt.



Pycom on Twitter