Calibration value out of range

I am trying to interface DS3231 RTC module with the OpenMV cam. When calibrating the RTC using some code I found here https://github.com/peterhinch/micropython-samples/tree/master/DS3231, I encountered this error “ValueError: calibration value out of range”

Any suggestion?

Just read the python code and debug it…

Thanks for your response. Was able to figure it out and everything is working fine now.
But I am now encountering a challenge, to get the RTC working, I needed to add the library to the IDE. When the library is in the internal memory of the OpenMV Cam, the time is always accurate with no problem. However, when I insert SD card, I am not able to access the library from the internal memory, so I will need to add it to the SD card. But when I access the library from the SD, the time will no longer be correct, there will be an offset of about a day and some hours. After resetting the time, it will be fine, but after disconnecting and reconnecting the board, the problem of time offset will happen again. I tried adding it to document folder of the OpenMV IDE, but when accessing it from the IDE, it will still need to be added to the SD card first.

I am therefore considering two options,

  1. A way to save the library in the internal memory such that it will remain there permanently, that way I will not need to access the library from the SD card.
  2. A way to frozen the module and add it to the firmware so that it will be added to the list of inbuilt modules/functions so that I can access it.

Any suggestions on how to do this or other potential solutions to help resolve this problem will be appreciated. Thanks.

Yes, you can freeze modules into our firmware such that they are part of the binary. See our github to compile the firmwar.e

Thanks for the response, will look into it.

I don’t know why it would make any difference where the module is, and I don’t have the RTC to test with, so it falls on you to try to figure it out (maybe try asking peterhinch). There’s no easy way to freeze a module in the firmware, you have to edit the top manifest and rebuild the firmware.

Thanks for the comment.
Yeah, I guess the problem will be solved if I can find a way to permanently make the micropython local time to be same as the actual calendar time (I mean to make it read the current time).
Because whenever I run this, time.localtime(), the time is usually around 2015. I don’t know if there is a way to make this to read the current year and time permanently.

maybe set it in boot.py

Thanks.
Sorry, how do I do that?
Because I usually use this line of code to set it from the IDE

import pyb
import utime as time
rtc = pyb.RTC()
rtc.datetime((2021,9,10,2,11,11,0,0)) #year, month, day, weekday, hours, minutes, seconds, subseconds
now = time.time()
print(rtc.datetime()) 
print(time.localtime(now))

If you need to set something once at boot time, put it in a boot.py script just like main.py in storage and it will run once at boot. I don’t think you need to set the RTC every time you use it, if it has a backup battery, otherwise what’s the point of using it.

Oh I see the issue now, no clue how to fix it. Both time and rtc modules read the internal RTC, and need to be set from the external one every time.

Oh now I get. So technically even with the RTC module, the time still needs to be set every time I am to use it. Yeah, so going back to your second to the last comment, seems using RTC module is of no much use since it still need to set every time except there is a way to permanently synchronize the internal RTC with the actual time.

Yes and I think your issue is the calibration value gets lost because it’s stored in volatile backup memory:

You should try this:

Beyond that there’s nothing more I can help with.

Yeah that was what I tried to do initially and it was the reason I opened this discussion. When I run the following code to do the calibration, the calibration is usually not successful, it gives an error saying the calibration value is out of range.

from ds3231_pb import DS3231
import machine
i2c = machine.I2C(2)  # Connected on 'Y' side Y9 clk Y10 data
ds3231 = DS3231(i2c)
ds3231.save_time()  # Set DS3231 to match Pyboard RTC
ds3231.calibrate()

I asked peterhinch and he said the calibration is specific to Pyboards, that since OpenMV Cam H7 uses different hardware and different firmware, it maybe the reason why it is not working.

I just hope that there could be way to use RTC module with the OpenMV Cam for better time keeping rather than having to set the time every time.

That’s because the value is out of range, it can be calibrated by ±512 see: https://docs.micropython.org/en/latest/librar/pyb.RTC.html?highlight=rtc#pyb.RTC.calibration
Try printing the calibration value first see what values it’s trying to set, in ds3231_pb.py

    def calibrate(self, minutes=5):
        cal = self.getcal(minutes)
        print(cal)

Maybe you need to set the internal RTC/datetime first then calibrate it.

EDIT: Why do you want to set or calibrate the internal RTC ? You can always just read the time from the external RTC and it will always be accurate and it’s battery backed, I guess I still don’t understand what you’re trying to do.

What I’m trying to do is simple, I want to be able to set the internal RTC time to the current date and time permanently, so that I do not need to set every time. When I read from the internal RTC, the time is always showing

(2015, 1, 1, 4, 0, 0, 16, 230)

And to set the RTC module time, it need to read the internal RTC time, therefore the need to first set the internal RTC every time before setting the RTC module’s time.

That’s not possible, it will reset unless there’s a backup battery connected to VBAT which is not accessible and always tied up to 3.3v from the regulator.

Why do you even want to read it from the internal RTC ? Just don’t use the internal RTC use the external one, easy.

Meaning, don’t use the rtc or time modules:

print(rtc.datetime()) 
print(time.localtime(now))

And use this instead:

ds3231.get_time()

If you still want to use it to set the internal RTC, you need to figure out why the calibration value is out of range.

Thanks for your response.

I was setting the internal RTC because this function definition depends on the internal RTC. Therefore, when I run it, the date and time is same as that of the internal RTC. Only after I have set the internal RTC then will that function returns the correct time and date. So because the function depends on the internal RTC, the only way to get the right time, is to see that the internal RTC is right.

This is Not true, it has nothing to do with the internal RTC, unless you call with set_rtc=True, and even then it only tries to set the time from the external one…Here’s the code for that function:

Thanks for your comment.
Well, then I guess something is wrong which is not clear, which I do not seem to understand. Because when i run this example code to get the time from the RTC, the time does not correspond to the current time and date until after I have set the internal RTC time and run it again, then the time will be correct.

from ds3231_port import DS3231
from machine import Pin, I2C
i2c = I2C(sda = Pin('P8'), scl=Pin('P7'))
ds3231 = DS3231(i2c)
ds3231.get_time()
print("DS3231 RTC Time:",ds3231.get_time())