Welcome to the Pycom forum Forum
    • \[\[global:header.categories\]\]
    • \[\[global:header.recent\]\]
    • \[\[global:header.tags\]\]
    • \[\[global:header.popular\]\]
    • Login

    Explore Pybytes | Official Documentation | Report a Firmware Bug/Issue | GitHub

    LoPy and nanogateway example: Inaccurate timing prevent OTAA join

    Scheduled Pinned Locked Moved LoPy
    lopyotaattntiming
    30 Posts 5 Posters 8.9k Views 6 Watching
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • robert-hhR Offline
      robert-hh
      last edited by robert-hh

      This is a continuation of this post https://forum.pycom.io/topic/2676/abp-mode-and-frame-counters/18
      It drifted away from the initial topic too far. The result form this topic was:
      The node had pretty good timing, but the gateway delivers downlink messages from the TTN server too late. Some further obervations:
      a) The downlink message form the TTN server with the join accept arrives at the gateway early enough (like 1 second before it's about to be sent)
      b) A simple timing test using utime.ticks_us() and and utime.ticks_diff() to create a 5000ms pulse creates a 5025ms pulse, too late for the tight TTN timing constraints.
      c) Additionally, the gateway determines time difference by subtracting time stamps, instead of using ticks_diff(). That may lead to lockouts. But that's another story.

      robert-hhR 1 Reply Last reply Reply Quote 1
      • robert-hhR Offline
        robert-hh @robert-hh
        last edited by

        @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.

        L 1 Reply Last reply Reply Quote 4
        • L Offline
          livius @robert-hh
          last edited by

          @robert-hh
          Really good finding as always

          think about people first, then computers

          1 Reply Last reply Reply Quote 0
          • D Offline
            daniel
            last edited by

            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-hhR 2 Replies Last reply Reply Quote 0
            • robert-hhR Offline
              robert-hh @daniel
              last edited by robert-hh

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

              1 Reply Last reply Reply Quote 0
              • robert-hhR Offline
                robert-hh @daniel
                last edited by

                @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.

                1 Reply Last reply Reply Quote 0
                • D Offline
                  daniel
                  last edited by

                  @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!

                  robert-hhR 1 Reply Last reply Reply Quote 0
                  • robert-hhR Offline
                    robert-hh @daniel
                    last edited by robert-hh

                    @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()

                    1 Reply Last reply Reply Quote 1
                    • K Offline
                      kiromn
                      last edited by

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

                      robert-hhR 1 Reply Last reply Reply Quote 0
                      • robert-hhR Offline
                        robert-hh @kiromn
                        last edited by

                        @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).

                        K 1 Reply Last reply Reply Quote 0
                        • K Offline
                          kiromn @robert-hh
                          last edited by kiromn

                          @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)

                          robert-hhR 1 Reply Last reply Reply Quote 0
                          • robert-hhR Offline
                            robert-hh @kiromn
                            last edited by robert-hh

                            @kiromn That's antoher effect, cause by the gateway being singel channel only. After joining, you have to delete in the node script every channel but the first. There was some communication about that in the forum, maybe hard to find. Like:

                            # remove all channels but the first
                            for i in range(1, 3):
                                lora.remove_channel(i)
                            

                            Edit: I changed the gateway script yesterday, such that the delay compensation adapts to different downlink message lengths.

                            K 1 Reply Last reply Reply Quote 0
                            • K Offline
                              kiromn @robert-hh
                              last edited by

                              No luck with disabling channels also.

                              robert-hhR 2 Replies Last reply Reply Quote 0
                              • robert-hhR Offline
                                robert-hh @kiromn
                                last edited by

                                @kiromn Interesting. I can try this evening again.
                                For my tests, I usually use ABP join, by transferring the device ID and keys from a previous OTAA join. The keys can be taken form the TTN server console.

                                1 Reply Last reply Reply Quote 0
                                • robert-hhR Offline
                                  robert-hh @kiromn
                                  last edited by

                                  @kiromn I can confirm your observation. After OTAA join, only few of the messages are captured by the Lopy gateway. A second gateway based on an IC880a receives all messages.
                                  using ABP activation and disabling all channels but one, all messages are receievd by the LoPy gateway.

                                  K 1 Reply Last reply Reply Quote 1
                                  • K Offline
                                    kiromn @robert-hh
                                    last edited by

                                    @robert-hh I have tried disabling channels, changing port, but it does not work. Do you think you will be able to fix it? I can help with testing :)

                                    robert-hhR 2 Replies Last reply Reply Quote 0
                                    • robert-hhR Offline
                                      robert-hh @kiromn
                                      last edited by

                                      @kiromn did you use OTAA join or ABP join?

                                      K 1 Reply Last reply Reply Quote 0
                                      • K Offline
                                        kiromn @robert-hh
                                        last edited by

                                        @robert-hh i use OTAA

                                        1 Reply Last reply Reply Quote 0
                                        • robert-hhR Offline
                                          robert-hh @kiromn
                                          last edited by robert-hh

                                          @kiromn I have again used OTAA join and have sent 10 packets. Below if a screen dump of the TTN console. Only 5 of the 10 packets were seen by my Lopy based gateway. The IC880A gateway has seen them all. You see, that the other packets have been sent at other frequencies, which have been submitted in the join response. At least its SF7BW125. So unless the node cannot be forced to ignore these other frequencies, the nanogateway will not catch them.

                                          0_1521753798322_gateway_log.jpg

                                          K 1 Reply Last reply Reply Quote 0
                                          • K Offline
                                            kiromn @robert-hh
                                            last edited by

                                            @robert-hh Yep i see. So, this gateway is not very usable.

                                            robert-hhR 1 Reply Last reply Reply Quote 0

                                            Hello! It looks like you're interested in this conversation, but you don't have an account yet.

                                            Getting fed up of having to scroll through the same posts each visit? When you register for an account, you'll always come back to exactly where you were before, and choose to be notified of new replies (either via email, or push notification). You'll also be able to save bookmarks and upvote posts to show your appreciation to other community members.

                                            With your input, this post could be even better 💗

                                            Register Login
                                            • 1
                                            • 2
                                            • 1 / 2
                                            • First post
                                              Last post

                                            Pycom on Twitter

                                            Pycom