SolderedElectronics / Inkplate-Arduino-library

Inkplate family Arduino library. The easiest way to add e-paper to your project.
https://inkplate.readthedocs.io/en/latest/arduino.html
GNU Lesser General Public License v3.0
250 stars 78 forks source link

No RTC Wake Up #211

Open okklar opened 1 year ago

okklar commented 1 year ago

No RTC wake up after deep sleep.

examples/Inkplate6COLOR/Advanced/DeepSleep/Inkplate6COLOR_RTC_Alarm_With_Deep_Sleep/Inkplate6COLOR_RTC_Alarm_With_Deep_Sleep.ino

I am trying to use this example but with no success. Board goes to deepsleep but never wakes up. Used battery for RTC, RTC works in other context. Are there any known issues?

Any help would be great. Thank you!

rsoric commented 1 year ago

Hi @okklar

Thanks for reporting it, dropping by to let you know we're investigating this and will let you know ASAP what the cause might be.

rsoric commented 1 year ago

@okklar , So I just ran the example, and I'm getting an interrupt and the screen refreshes, in the example, there don't seem to be any other sources of wakeup so I imagine it's GPIO_NUM_39 (RTC interrupt) causing the wakeup.

I ran the Inkplate6COLOR_RTC_Alarm_With_Deep_Sleep example on the latest version of the Inkplate library main branch. The board definition for Inkplate 6COLOR shouldn't have changed in time, so the one you have is fine.

Could you please check if you have the latest version of the library? Could you check if your Inkplate 6COLOR uses the PCAL or by any chance MCP GPIO expander? You can see this on the back of the device - the gpio expander pins are next to the device's logo printed on the PCB and they should be labeled with the name of the expander.

okklar commented 1 year ago

Hi @rsoric thank you so much for you help and investigating that issue for me. Unfortunately I had the same result as before, after I tried your suggestions. The Inkplate Library is on version 8.0.0, I didn't find a later one. Also I copied the code from github, just to double check I didn't change the local copy of the example code by accident. No success so far.

I am not sure if I found the right GPIO Expander but if I am not mistaken it says NXP L16A 0303 ZSD201A. I will attach an picture of it. I also see the GPIO 39 pinout on the side with the GPIO pins that are labeled with Esp32.

Once again, thanks for your help!

image

rsoric commented 1 year ago

I see, that would be the PCAL GPIO expander, I just wanted to rule out the possibility that this was causing the error.

Having a look at the schematic, could you somehow check the connection on Jumper 5 - if it's fully connected to GPIO39?

Here's how it looks in the schematic:

image

As you can see, it's what connects the RTC's interrupt to the ESP32. This could be a potential cause of the error.

Here's where it is on the board:

image

The middle pad should be connected to the left pad.

okklar commented 1 year ago

Hi @rsoric . Thank you very much for your help!

No, it is not connected, sorry, my bad – I wasn't aware of that. So I can simply connect those two pads by soldering them? Just to double check, it these two pads, right?

254801543-698bc787-46a8-4538-9d19-87f19ae44d46

rsoric commented 1 year ago

@okklar Yes, those are the ones that should be connected - they ought to be connected by default on the PCB but it doesn't hurt to reinforce this connection so we can rule it out as a possible fault.

okklar commented 1 year ago

Hi @rsoric , I connected the pad this evening and I also can confirm now that they were already connected as you said. But nothing changed unfortunately. The code is the same, but the board still doesn't wake up after the 60 seconds. Do you have any further things that I could check.

Sorry for that stress.

Thank you

rsoric commented 1 year ago

@okklar please don't worry, we're always happy to help Inkplate users get things working :)

I'm gonna try a couple more things later today to figure out what could be causing this issue.

rsoric commented 1 year ago

@okklar Sorry for the delayed reply, could you please open a support ticket with the same info you've provided here via our contact form: so we can help solve your issue

rsoric commented 11 months ago

@okklar, could you please give this branch a try on your device: https://github.com/SolderedElectronics/Inkplate-Arduino-library/tree/ip6ColorSleepFix

This has an updated driver for Inkplate 6COLOR which could fix this issue, we're currently testing it. If you're going to test it with your code, note that you have to call

display.sleepColorPanel();

just before

esp_deep_sleep_start();
rcassani commented 11 months ago

Hi @rsoric, I'm was having the same trouble with the the Inkplate6COLOR_RTC_Alarm_With_Deep_Sleep example on the Inkplate6COLOR. I did these two things and now it is working

PS. My board is different from the ones in the pictures above. I got it in the CrowdSupply campaign. image

EDIT: It is working properly.

rcassani commented 11 months ago

@rsoric, After some tests, I figured out (may it is obvious) that it necessary to upload another program (let's call it reset_rtc) to reset the RTC before uploading the Inkplate6COLOR_RTC_Alarm_With_Deep_Sleep example code to make it work properly (setting the RTC). This is to say:

  1. Upload the reset_rtc code
  2. Upload the Inkplate6COLOR_RTC_Alarm_With_Deep_Sleep example
  3. It works as expected (update every 60 seconds) ✅

This is the code I'm using for reset_rtc:

#ifndef ARDUINO_INKPLATECOLOR
#error "Wrong board selection for this example, please select Soldered Inkplate 6COLOR in the boards menu."
#endif

#include "Inkplate.h"      // Include Inkplate library to the sketch
#include "driver/rtc_io.h" // Include ESP32 library for RTC pin I/O (needed for rtc_gpio_isolate() function)
#include <rom/rtc.h>       // Include ESP32 library for RTC (needed for rtc_get_reset_reason() function)

Inkplate display; // Create an object on Inkplate library

void setup() {
  // put your setup code here, to run once:
  display.begin(); // Init Inkplate library (you should call this function ONLY ONCE)
  display.rtcReset();
  display.setCursor(50, 250);
  display.setTextSize(3);
  display.setTextColor(INKPLATE_BLACK, INKPLATE_WHITE); // Set text color and background
  display.print("RTC has been reset");
  display.display();
}

void loop() {
  // put your main code here, to run repeatedly:

}

However, there is a problem that I cannot figure out, the interruption does not work if I change the date in the RTC. For example following these steps:

  1. Upload the reset_rtc code
  2. Modify the year in the line display.rtcSetDate(1, 5, 12, 2022); to be 2023.
  3. Upload the modified Inkplate6COLOR_RTC_Alarm_With_Deep_Sleep
  4. It does not update anymore ❌

Am I missing something?

rcassani commented 11 months ago

Reply to my own question:

Yes, I was missing this: Beside changing the year, it is necessary to also change the day, as it was different. 5-dec-2023 was Tuesday (week of the day = 2). Thus, the proper date setting is display.rtcSetDate(2, 5, 12, 2022);

rsoric commented 10 months ago

Hi @rcassani ,

sorry about the delayed reply, a lot of us were on holiday for a while. Thanks for letting us know about this, we're going to make sure it's clear in a later update

-Rob

rcassani commented 5 months ago

Hi @rsoric, from my side everything is working fine. Tested with the latest release 10.0.0 If the RTC wake is working as well for @okklar, this issue could be closed

okklar commented 2 months ago

Hi @rsoric sorry for that very very late reply – this is literally the first day, I could test the code with the new board.

So I tested the board with the code that you flashed onto it, before sending to me – it worked fine. It woke up after 60 seconds. Then I uploaded another inkplate example code for display test. After that I came back to the RTC Wake Up Code again and ran into the same issue I had last year. It didn't wake up anymore. But I know it worked, when I powered up the board with your code. So I found a thing.

If I set the time with "rtcSetTime()" and "rtcSetDate()" it sets up and displays the time and date correctly, but it doesn't enable the wake up alarm. If i use the "rtcSetEpoch()" to set up the time and date, the alarm is enabled correctly and it works fine again.

At the moment I have no clue, what could be the reason for that, but that is what I investigated so far. But maybe for someone who is smater than me, that already makes perfect sense. –T

rsoric commented 2 months ago

@BornaBiro, could you have a look at this, "rtcSetTime()" and "rtcSetDate()" apparently don'tt set up the alarm correctly but "rtcSetEpoch()" does.

BornaBiro commented 2 months ago

@okklar I don't see how one would enable or disable the RTC alarm. By looking at the rtcSetTime(), rtcSetDate and rtcSetEpoch it just sends data directly to the RTC IC. Only difference is that rtcSetEpoch() sends all time and data at one, while rtcSetTime() and rtcSetDate() splits them.

There is note in the datasheet page 22. stating that it good to read/write all time and date in one go due possible corruption. But they also said that all R/W must be done within one seconds which does happen, so this should not be a issue, especially since you can read the RTC T&D correctly. We can make a method for writing time and date at once and see the behavior.

Is this our example or your own code? Did you try to reset RTC between testing with rtcSetEpoch() and rtcSetTime()/rtcSetDate()?

mfasold commented 1 month ago

I am running into the same issue - the example does not work for me. I note that rtcSetAlarm works fine. Also, the epoch advances in time correctly, if I monitor it with rtcGetEpoch. Like in the example, I set the time using rtcSetTime and rtcSetDate (as I want to use the corresponding times/date as provided). I noted that the resulting epoch is many years in the future. But that is tolerable, since I just want to use rtcSetAlarmEpoch based on relative changes.

I bought the Inkplate6Color complete with everything and added the RTC battery. Any ideas?

rsoric commented 4 weeks ago

Hi @mfasold , we're going to take some time to investigate your specific RTC issue and the others listed here in the near future, when our schedule clears a bit. Will report back here when we have some new information

-Rob

rsoric commented 2 weeks ago

Hi @mfasold,

just tested a couple things. First I wanted to test RTC_Alarm (so, without deep sleep) which worked with a time difference of ~2 mins. Then i tried the RTC deep sleep example and I ran into some issues. First of all, the year wasn't displaying right when I was printing it back, which was concerning. I then tried to create a version of this sketch which works.

Here's the sketch I used.

And this is the output:

RTC data: 
rtc_seconds: 0 
rtc_minutes: 5 
rtc_hour: 12 
rtc_day: 6 
rtc_weekday: 4 
rtc_month: 11 
rtc_year: 24 
epoch: 3245659500 
RTC set alarm data: 
rtc_alarm_seconds: 14 
rtc_alarm_minutes: 37 
rtc_alarm_hour: 5 
rtc_alarm_day: 1 
rtc_alarm_weekday: 4

The data written to the RTC is correct, we can read it back. But the epoch received is not correct and thus also the alarm time is incorrect (because it's being set via the epoch). So, at the moment, unsure why this happens, I'm investigating this next.

So then I tried to set the alarm time via other function, and this worked. The epoch printed is still incorrect, but if I set the alarm manually via seconds, hours etc. it seems to work. I'll have to investigate the two epoch functions.

-Rob

mfasold commented 2 weeks ago

Thank you for the investigation. That is more or less the conclusion I also arrived at. But setting the alarm in such away quickly becomes difficult, for example when using day + 1 on day 30.

rsoric commented 2 weeks ago

Aboslutely, I'll try to somehow publish a quick fix for this now that we know the cause, hopefully during this or next week. Will keep you posted once you can download from the dev branch and try again.

mfasold commented 2 weeks ago

Thank you.

Also, I have a small suggestion. My aim is to set the RTC alarm to run at certain times each day. The interface of the function is void rtcSetAlarm(uint8_t rtcAlarmSecond, uint8_t rtcAlarmMinute, uint8_t rtcAlarmHour, uint8_t rtcAlarmDay, uint8_t rtcAlarmWeekday). So besides the time, there is the day of the month and day of the week, but neither month nor year. The next day of the month is not easy to calculate. Therefore, it would be very convenient to have an interface without day of month, maybe even without day of week.

rsoric commented 2 weeks ago

Hi @mfasold , I believe that is where the epoch function comes in, and it has a second parameter where you can select to match the following:

RTC_ALARM_MATCH_SS
RTC_ALARM_MATCH_MMSS
RTC_ALARM_MATCH_HHMMSS
RTC_ALARM_MATCH_DHHMMSS
RTC_ALARM_MATCH_WHHMSS

so, if you just match the hour, minute, and seconds you can trigger the alarm daily at a certain time. It's possible that I'm misunderstanding your comment so please correct me if this is a different feature which you wish be added. Of course this will only be fully functional once we publish the fix for epoch.

-Rob

rsoric commented 2 weeks ago

Hi again @mfasold , I've had luck with this exact example, I just uploaded it to several Inkplate 10's and it worked fine, woke up every 60 seconds and the time data printed back was OK

// Include Inkplate library to the sketch
#include "Inkplate.h"

// Create an object on Inkplate library and also set library into 1-bit mode (BW)
Inkplate display(INKPLATE_1BIT);

void setup() {
  Serial.begin(115200);
  delay(1000); // Wait a second

  Serial.println("Woken up, code begin");
  // Init Inkplate library (you should call this function ONLY ONCE)
  display.begin();

  // Clear alarm flag from any previous alarm
  display.rtcClearAlarmFlag();

  // Set the time and date
  display.rtcSetTime(16, 00, 00);  // 24H mode, ex. 6:54:00
  display.rtcSetDate(4, 7, 11, 2024);  // 0 for Sunday, 1 for Monday, ... for example Tuesday, 21.3.2023.

  // Serial.print current rtc data
   display.rtcGetRtcData();
  Serial.println("rtc get epoch:");
  Serial.println(display.rtcGetEpoch());
  Serial.print("rtc get hour:");
  Serial.println(display.rtcGetHour());
  Serial.print("rtc get minute:");
  Serial.println(display.rtcGetMinute());
  Serial.print("rtc get seconds:");
  Serial.println(display.rtcGetSecond());
  Serial.print("rtc get weekday:");
  Serial.println(display.rtcGetWeekday());
  Serial.print("rtc get day:");
  Serial.println(display.rtcGetDay());
  Serial.print("rtc get month:");
  Serial.println(display.rtcGetMonth());
  Serial.print("rtc get year:");
  Serial.println(display.rtcGetYear());

  // Set RTC alarm 60 seconds from now
  display.rtcSetAlarmEpoch(display.rtcGetEpoch() + 60, RTC_ALARM_MATCH_DHHMMSS);

  // Enable wakup from deep sleep on gpio 39 where RTC interrupt is connected
  esp_sleep_enable_ext0_wakeup(GPIO_NUM_39, 0);

  // Put ESP32 into deep sleep. Program stops here.
  esp_deep_sleep_start();
}

void loop() {
}

Could you try it please? I genuinely don't know how come it started working now, maybe it's the specific date time values I'm writing. I've also tried commenting out calls to set time and set date to see if it makes a difference and my inkplate still wakes fine. Pretty weird it just randomly started working, I checked and this was on a version of the library with no modifications.

mfasold commented 2 weeks ago

I checked this code (replacing the line Inkplate display;) and can confirm that it works with that exact example. But when I tried first using my correct time, it did not work. I presume the solution cannot be to set this exact time, and on every program start :)

And regarding the previous comment: yes, if the epoch function works, it can be used in principle. But it is still less convenient, as any specific alarm time first needs to be translated that into the correct epoch, for which there is no function in the library.

rsoric commented 2 days ago

Hi @mfasold,

I've just made this test sketch and tried all these different times and all worked fine - i didn't compare seconds as potentially a second passed between reading and writing time:

// Include Inkplate library to the sketch
#include "Inkplate.h"

// Create an object on Inkplate library and also set library into 1-bit mode (BW)
Inkplate display(INKPLATE_3BIT);

// Define test data for various times and dates
struct RtcTest {
  int hour;
  int minute;
  int second;
  int weekday;
  int day;
  int month;
  int year;
};

RtcTest testCases[10] = {
  { 12, 5, 0, 4, 6, 11, 2024 },     // Noon, problematic date
  { 12, 30, 0, 0, 1, 1, 2025 },     // Noon, New Year's Day
  { 18, 45, 50, 5, 15, 6, 2025 },   // Evening
  { 23, 59, 59, 3, 28, 2, 2026 },   // Midnight transition
  { 6, 0, 0, 1, 10, 8, 2024 },      // Early morning
  { 16, 30, 15, 4, 25, 12, 2023 },  // Afternoon
  { 10, 15, 0, 6, 18, 9, 2024 },    // Morning
  { 20, 20, 20, 2, 2, 2, 2024 },    // Evening
  { 5, 5, 5, 5, 5, 5, 2023 },       // Early morning
  { 22, 22, 22, 7, 7, 7, 2023 }     // Late evening
};

void setup() {
  Serial.begin(115200);
  delay(1000);  // Wait a second

  Serial.println("Woken up, code begin");

  // Init Inkplate library (you should call this function ONLY ONCE)
  display.begin();
  display.display();

  for (int i = 0; i < 10; i++) {
    Serial.printf("Testing case #%d: %02d:%02d:%02d on %d/%d/%d (Weekday: %d)\n", i + 1,
                  testCases[i].hour, testCases[i].minute, testCases[i].second,
                  testCases[i].day, testCases[i].month, testCases[i].year, testCases[i].weekday);

    // Set time and date
    display.rtcSetTime(testCases[i].hour, testCases[i].minute, testCases[i].second);
    display.rtcSetDate(testCases[i].weekday, testCases[i].day, testCases[i].month, testCases[i].year);

    delay(200);
    display.rtcGetRtcData();
    delay(200);

    // Read back the values
    int readHour = display.rtcGetHour();
    int readMinute = display.rtcGetMinute();
    int readSecond = display.rtcGetSecond();
    int readWeekday = display.rtcGetWeekday();
    int readDay = display.rtcGetDay();
    int readMonth = display.rtcGetMonth();
    int readYear = display.rtcGetYear();

    // Compare read-back values with expected values
    bool match = (readHour == testCases[i].hour && readMinute == testCases[i].minute && readWeekday == testCases[i].weekday && readDay == testCases[i].day && readMonth == testCases[i].month && readYear == testCases[i].year);

    if (match) {
      Serial.println("RTC read-back SUCCESS: Values match!");
    } else {
      Serial.println("\n!!! RTC read-back MISMATCH detected !!!");
      Serial.println("Expected:");
      Serial.printf("Time: %02d:%02d:%02d, Date: %d/%d/%d, Weekday: %d\n",
                    testCases[i].hour, testCases[i].minute, testCases[i].second,
                    testCases[i].day, testCases[i].month, testCases[i].year,
                    testCases[i].weekday);
      Serial.println("Actual:");
      Serial.printf("Time: %02d:%02d:%02d, Date: %d/%d/%d, Weekday: %d\n",
                    readHour, readMinute, readSecond,
                    readDay, readMonth, readYear,
                    readWeekday);
      Serial.println("*********************************************");
    }
    Serial.println();
    Serial.println();
    Serial.println();
    delay(1000);  // Small delay between tests
  }

  // Enable wakup from deep sleep on gpio 39 where RTC interrupt is connected
  esp_sleep_enable_ext0_wakeup(GPIO_NUM_39, 0);

  // Put ESP32 into deep sleep. Program stops here.
  esp_deep_sleep_start();
}

void loop() {
}

Could you please tell me the problematic time which didn't work so I can test that too? This was tested on Inkplate 10 and Inkplate 5, both worked.

mfasold commented 2 days ago

Thanks for the suggestion. I would believe that this sketch will also work on my Inkplate 10. However, the problem occurs when using display.rtcSetAlarmEpoch(display.rtcGetEpoch() + 60, RTC_ALARM_MATCH_DHHMMSS); after the RTC time has already been set. For certain times, it does not wake up from deep sleep.