1

A NOTE ON THE PROJECT AND PROGRAM STRUCTURE

I am developing an open source Smart Watch project using Arduino. The code can be found here: https://github.com/shivangsgangadia/SmartWatch The code is too large and divided into multiple files, hence I cannot paste it here within the question, hence I request you to look into the github repo.

So far I have interfaced an OLED (128 X 64 SSD1306) and RTC (DS3231 in ZS-042). I have written libraries for both, which have been included in Github repo.

The program structure allows to add multiple "Modules" which are basically like apps. There is a static State class that holds the program state such as modules to be serviced, and time from RTC. Each "Module" can be a "App" or "Overlay". Overlays are always visibles, there can be mutiple overlays active, but only 1 app can exist at a time.

WHAT I AM TRYING TO DO ?

  1. Read RTC into State class's static variables
  2. Display once
  3. Attach interrupt to set boolean flag when the RTC gives interrupt (alarm set to 1 minute) Service interrupt in loop by:

    • Read RTC into State class's static variables
    • Reset alarm for RTC
    • Update display

WHAT IS THE PROBLEM ?

The program works fine 2-3 times, i.e. does what's expected after servicing 2-3 interrupts (hence 2-3 minutes), but after that the print on the OLED becomes mangled and the program stops altogether.

WHAT HAVE I TRIED TO SOLVE IT ?

With Serial.println() in many areas such as before and after OLED::writeString is called in respective classes, I concluded that the RTC is not the issue, but the OLED somehow causes the program to stop.

Removing OLED::writeString statements does allow the rest of the printing to continue for more than 2-3 times, but the program eventually does stop. I have tried replacing the wires and the breadboard, but nothing seems to have any effect.

| improve this question | | | | |
  • I can't see anything immediately obvious (kudos to you for your tidy programming style and your lack of anything String related). Chances are it's the I2C communication. It's not great over wires or with breadboards. You can try adding smaller (1kΩ) pullup resistors on the I2C wires. – Majenko Apr 7 at 11:30
  • Thanks for the compliment ! I tried adding 1k pullups and passing the OLED connections through the ZS04 module's extra pinouts and it still doesn't work. – Shivang Gangadia Apr 7 at 12:42
4

This is wrong in many ways:

String input = Serial.readString();
serialInputBuffer = new char[input.length()];
input.toCharArray(serialInputBuffer, input.length());

What's fatal is that you later don't free the memory allocated with new. Don't use String and new. Both use heap memory and will fragment it with these small allocations until there is no space for the next allocation. I see you have dynamic allocation in other parts of the sketch and there it looks like you have a delete, but they still cause the fragmentation problem.

Use a global buffer like char serialInputBuffer[64]; and use:

int l = Serial.readBytes(serialInputBuffer, sizeof(serialInputBuffer));
serialInputBuffer[l] = 0;

In the scale function, there is a dynamically allocated array. Replace it with a class variable, which acts as a buffer which can hold the maximum number of bytes you expect the use to scale their byte to.

Again, dynamic allocations will cause fragmentation even if the memory is released properly.

| improve this answer | | | | |
  • I have tried commenting out the whole Serial piece, and it still has no effect. – Shivang Gangadia Apr 7 at 12:10
  • @ShivangGangadia, you have multiple dynamic allocations in other parts of the sketch and there it looks like you have a delete, but they still cause the fragmentation problem. – Juraj Apr 7 at 12:11
  • I replaced all dynamic allocations with statics within modules. Still, has no effect at all – Shivang Gangadia Apr 7 at 12:23
  • @ShivangGangadia, why do you use pgm_read_word to read bytes? – Juraj Apr 7 at 18:22
  • Because the bytes that I need, that is font, are in PROGMEM – Shivang Gangadia Apr 7 at 18:24
-1

Don't use the Wire library. If you look closely at twi.c, you'll find it has blocking calls with (potentially) infinite loops. Eventually a condition will occur that causes one of the blocking calls to hang forever.

See this post and this post for details

Use something like SBWire

Frank

| improve this answer | | | | |
  • 1
    I replaced the Wire library with SBWire. Still no improvement. – Shivang Gangadia Apr 7 at 19:33
  • 1
    OK, so now you are back to basic troubleshooting. Temporarily abandon your project, and create a new one with just the Arduino and the OLED - nothing else - and the simplest possible code to drive it. – user3765883 Apr 7 at 23:22
  • Once you have this simple project working, you'll know right away if the OLED and it's driver are the problem – user3765883 Apr 7 at 23:23
  • Did the step by step, will accept the answer by Juraj – Shivang Gangadia Apr 8 at 8:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.