logo elektroda
logo elektroda
X
logo elektroda

How to Implement a Clock in OpenBeken Devices Without Using NTP Protocol

max4elektroda 4134 95
ADVERTISEMENT
  • #91 21640158
    divadiow
    Level 35  
    ECR6600 1.18.156
    How to Implement a Clock in OpenBeken Devices Without Using NTP Protocol

    ECR6600 1768_merge_cf30e28012eb ✅
    How to Implement a Clock in OpenBeken Devices Without Using NTP Protocol
  • ADVERTISEMENT
  • #92 21640213
    p.kaczmarek2
    Moderator Smart Home
    Regarding counter role - calling Channel_Add from ISR is not probably a good idea. I will need to fix it tomorrow. Probably store deltas and collect them in quick tick...
    Helpful post? Buy me a coffee.
  • ADVERTISEMENT
  • #93 21640278
    max4elektroda
    Level 20  
    p.kaczmarek2 wrote:
    Probably store deltas and collect them in quick tick...

    Btw, anyone knows in which periods quickticks are called in real life?
    If I understood it right, it will get the real time in Beken and ESP and else assume 25ms?
    We might even here go for the "right time" with xticks and possibly even set g_secondsElapsed while at it?
    Just thinking out loud...

    Added after 1 [hours] 58 [minutes]:

    max4elektroda wrote:
    Using this for now - working on W800, will test with others soon ...

    Code: text Expand Select all Copy to clipboarddiff --git a/src/user_main.c b/src/user_main.c
    index a0ea6322..dbee5483 100644
    --- a/src/user_main.c
    +++ b/src/user_main.c
    @@ -583,6 +583,11 @@ float g_wifi_temperature = 0;
     static byte g_secondsSpentInLowMemoryWarning = 0;
     void Main_OnEverySecond()
     {
    +#if PLATFORM_W600 || PLATFORM_W800
    +#define TimeOut_t xTimeOutType 
    +#endif
    +       TimeOut_t myTimeout;    // to get uptime from xTicks 
    +
            int newMQTTState;
            const char* safe;
            int i;
    @@ -754,8 +759,9 @@ void Main_OnEverySecond()
                            }
                    }
            }
    -
    -       g_secondsElapsed++;
    +//     g_secondsElapsed++;
    +       vTaskSetTimeOutState( &myTimeout );
    +       g_secondsElapsed = (int)((((uint64_t) myTimeout.xOverflowCount << (sizeof(portTickType)*8) | myTimeout.xTimeOnEntering)*portTICK_RATE_MS ) / 1000 );
            if (bSafeMode) {
                    safe = "[SAFE] ";
            }


    Tested over night with BL602, BK7238, BK7231N, ESP32, W800, LN882H:

    How to Implement a Clock in OpenBeken Devices Without Using NTP Protocol


    For LN882H its 3 seconds off after 15 hours, rest ~ 1 second (plus there's a small gap in how exactly time was set).
    Only "big" difference on ESP32, which is 12 minutes(!) off.
    Maybe @insmod xTicks are "second choice" and I should try to use esp_timer_get_time() , like for quickticks?
  • ADVERTISEMENT
  • #94 21640422
    p.kaczmarek2
    Moderator Smart Home
    My only worry is that now Main_OnEverySecond may either:
    - be called twice with the same g_secondsElapsed value
    - skip g_secondsElapsed values
    still, if it's not breaking anything, then acceptable?

    Related: Counter_f works on BK7238 https://www.elektroda.com/rtvforum/viewtopic.php?p=21640407#21640407
    Probably need to check on other platforms. Seems to crash on ESP32 for me?
    Helpful post? Buy me a coffee.
  • ADVERTISEMENT
  • #95 21640471
    max4elektroda
    Level 20  
    p.kaczmarek2 wrote:
    - be called twice with the same g_secondsElapsed value
    - skip g_secondsElapsed values

    both is possible, I think, but at least we will never "go back in time".

    Did a quick check, I can't see a "big" breaking point:
    
    .../OpenBeken/main/OpenBK7231T_App$ find src/ -name "*.[ch]" | xargs grep g_secondsElapsed
    src/httpserver/new_http.c:   hprintf255(request, "<br>Online for <span id=\"onlineFor\" data-initial=\"%i\">-</span>", g_secondsElapsed);
    src/httpserver/json_interface.c:   format_time(g_secondsElapsed, buff, sizeof(buff));
    src/httpserver/json_interface.c:   JSON_PrintKeyValue_Int(request, printer, "UptimeSec", g_secondsElapsed, true);
    src/httpserver/json_interface.c:   JSON_PrintKeyValue_Int(request, printer, "Uptime", g_secondsElapsed, true);
    src/httpserver/json_interface.c:   if (NTP_GetCurrentTimeWithoutOffset() > g_secondsElapsed) {   // would be negative else, leading to unwanted results when converted to (unsigned) time_t 
    src/httpserver/json_interface.c:      ntpTime = (time_t)NTP_GetCurrentTimeWithoutOffset() - (time_t)g_secondsElapsed;
    src/httpserver/rest_interface.c:   hprintf255(request, "{\"uptime_s\":%d,", g_secondsElapsed);
    src/driver/drv_ds1820_full.c:   // if (dsread == 1 && g_secondsElapsed % 5 == 2) {
    src/driver/drv_ds1820_full.c:            float t_float = 20.0 + i/10.0 + (float)(g_secondsElapsed%100)/100.0;
    src/driver/drv_ds1820_full.c:               lastconv = g_secondsElapsed;
    src/driver/drv_ds1820_full.c:               lastconv = g_secondsElapsed;
    src/driver/drv_ds1820_full.c:         if(dsread == 0 && (g_secondsElapsed % ds18_conversionPeriod == 0 || lastconv == 0))
    src/driver/drv_dht_internal.c:   uint32_t currenttime = g_secondsElapsed;
    src/driver/drv_tm_gn_display_shared.c:      segments[i] = g_digits[(g_secondsElapsed + i) % 10];
    src/driver/drv_tm_gn_display_shared.c:      segments[i] = g_digits[(g_secondsElapsed + i) % 10];
    src/driver/drv_bl_shared.c:          cJSON_AddNumberToObject(root, "uptime", g_secondsElapsed);
    src/driver/drv_ntp.c:      if (g_secondsElapsed < 60) {
    src/driver/drv_ds1820_simple.c:   hprintf255(request, "<h5>DS1820 Temperature: %.2f C (read %i secs ago)</h5>", (float)t / 100, g_secondsElapsed - lastconv);
    src/driver/drv_ds1820_simple.c:   // if (dsread == 1 && g_secondsElapsed % 5 == 2) {
    src/driver/drv_ds1820_simple.c:      lastconv = g_secondsElapsed;
    src/driver/drv_ds1820_simple.c:   if(g_secondsElapsed % ds18_conversionPeriod == 0 || lastconv == 0) //dsread == 0
    src/mqtt/new_mqtt.c:      sprintf(dataStr, "%d", g_secondsElapsed);
    src/new_common.h:extern int g_secondsElapsed;
    src/cmnds/cmd_if.c:   return g_secondsElapsed;
    src/cmnds/cmd_test.c:      cJSON_AddNumberToObject(root, "uptime", g_secondsElapsed);
    src/user_main.c:int g_secondsElapsed = 0;
    src/user_main.c:      if(g_secondsElapsed < 30)
    src/user_main.c:      if (g_secondsElapsed < 30) {
    src/user_main.c:   if (g_timeSinceLastPingReply != -1 && g_secondsElapsed > 60)
    src/user_main.c:   g_secondsElapsed++;
    src/user_main.c:         safe, g_secondsElapsed, idleCount, xPortGetFreeHeapSize(), bMQTTconnected,
    src/user_main.c:         safe, g_secondsElapsed, idleCount, xPortGetFreeHeapSize(),g_bHasWiFiConnected, g_timeSinceLastPingReply, LWIP_GetActiveSockets(), LWIP_GetMaxSockets(),
    src/user_main.c:   if (!(g_secondsElapsed % 10))
    src/user_main.c:      if (g_secondsElapsed > bootCompleteSeconds)
    src/user_main.c:   if (g_secondsElapsed < 5)
    src/hal/w800/hal_main_w800.c:   //actually starts shifting g_secondsElapsed. To compensate, we are checking how much
    


    new_http.c only printing value
    json_interface.c only printing value

    drv_ds1820_full.c used for "fake windows temperatures (no problem)
    --> we might skip one read, if we skip a second dividable by our period

    drv_dht_internal.c used as currenttime in if (!force && ((currenttime - dht->_lastreadtime) < 3)) { return dht->_lastresult; ...
    --> we might be one second late for reading

    drv_tm_gn_display_shared.c display value only
    -> display might "jump" one second if we skipped one value

    drv_ds1820_simple.c
    --> we might skip one read, if we skip a second dividable by our period

    new_mqtt.c only printing value
    cmd_if.c only printing value
    cmd_test.c only printing value
    main.c only checking against limits
    hal_main_w800.c only in comment

    Added after 27 [minutes]:

    p.kaczmarek2 wrote:
    Seems to crash on ESP32 for me?

    Is this with "Add_Channel"? I crashed ESP32 in ISR, too by using addLogAdv in it (which worked fine on W800 with much more logging during debugging)
  • #96 21640503
    p.kaczmarek2
    Moderator Smart Home
    Well if there are no drawbacks then we can merge your changes really soon. I also saw @insmod has nothing against them... so I guess we'll have them in a release :D

    I am still thinking what else can I cover with self tests for clock stuff, but not sure for now.

    Hm, addLogAdv crashes ESP? This may be it! That is with Add_Channel channel in ISR routine. I am not sure if we can just "silently" add to channel, since we also want to do MQTT publish. Maybe I will just create some kind of int addToChannels[MAX_CHANNELS] table and add it in quick ticks...
    Helpful post? Buy me a coffee.

Topic summary

The discussion revolves around implementing a local clock in OpenBeken devices without relying on the NTP protocol. The initial approach involved using a variable to track the time since startup, allowing for time calculations based on elapsed seconds. While this method lacks the accuracy provided by NTP, it offers advantages such as independence from network connectivity and reduced resource requirements. Participants provided feedback on code structure, suggested improvements for compatibility, and discussed the potential for using real-time clocks (RTC) for enhanced accuracy. Testing across various platforms, including LN882H, BL602, and W600, was conducted to evaluate the clock's performance and reliability. The conversation also touched on daylight saving time adjustments and the possibility of remote clock synchronization.
Summary generated by the language model.
ADVERTISEMENT