RTCZero.h and I2S.h Apparent Conflict

Hello all,

I'm trying to program my MKR1010 to sound an alarm at a time pulled from an API but it seems that the RTCZero library, which I use to fetch the current time and display it on the seven-segment displays, is conflicting with the I2S library, which I'm using to generate the alarm tone. I know that there is a conflict because when I comment out the rtc.begin(); function call the sound works. I'm including three files in this post to illustrate; main.h, getTime.h, and sound.h.

Is there a way to avoid this conflict? Or maybe there are other libraries that I could use that don't clash? I read in another post that both the libraries I'm using use a time.h file that could be causing the problem.

Please help!

Thank you in advance!

Eli

//main.h:

#include "wifiConnect.h"
#include "httpClient.h"
#include "getTime.h"
#include "sound.h"

#include <ArduinoJson.h>

//create memory pool for json response
StaticJsonDocument<200> doc;

void setup()
{
  Serial.begin(9600);

  //connect to wifi
  wifiConnect();

  //clock init
  rtc.begin(); //THIS IS THE LINE THAT CAUSES THE PROBLEM

  // //get time in epoch format
  getEpoch();

  // //backpack init
  matrix.begin(0x70);
  // ringtone_1();
}

void loop(){

  hour = rtc.getHours();
  minute = rtc.getMinutes();
  second = rtc.getSeconds();

  //Adjust for timezone
  if(hour > 4){
    hour += GMT;
  }else{
    hour += 24 + GMT;
  }

  //Print to serial monitor
  Serial.println("----------------------");
  printDate();
  printTime();

  //WRITE TO LED
  writeHours(hour);
  writeMinutes(minute);
  matrix.drawColon(second % 2 == 0);
  matrix.writeColon();

  String str = createClient();
  deserializeJson(doc, str);

  //get json and parse
  // DeserializationError error =  deserializeJson(doc, str);

  // if(error){
  //   Serial.print("Deserialization failed. Error code: ");
  //   Serial.println(error.c_str);
  //   while(1);
  // }

  alarmHour = doc["alarmHour"];
  alarmMinute = doc["alarmMinute"];
  sound = doc["sound"]; 
  volume = doc["volume"];

  Serial.print("alarmHour: ");
  Serial.println(alarmHour);
  Serial.print("alarmMinute: ");
  Serial.println(alarmMinute);
  Serial.print("sound: ");
  Serial.println(sound);
  Serial.print("volume: ");
  Serial.println(volume);

  if(alarmHour == hour && minute >= alarmMinute){
    ringtone_1();
  }
  delay(5000);
}

////////////////

//getTime:

#include <RTCZero.h>
#include <WiFiNINA.h>

//seven segment includes:
#include <Wire.h>
#include <Adafruit_LEDBackpack.h>

//seven segment matrix object
Adafruit_7segment matrix = Adafruit_7segment();

//clock object
RTCZero rtc;

int hour, minute, second, alarmHour, alarmMinute;
const int GMT = -4; //change this to adapt it to your time zone

void getEpoch(){
  unsigned long epoch = 0;
  int numberOfTries = 0, maxTries = 15;

  Serial.print("Getting current time");
  while(epoch == 0 && numberOfTries < maxTries){

    epoch = WiFi.getTime();
    delay(1000);
    Serial.print(".");
    numberOfTries++;
  }

  Serial.println();

  if (epoch == 0) {
    Serial.print("NTP unreachable!!");
    while (1);
  }
  else {
    Serial.print("Epoch received: ");
    Serial.println(epoch);
    rtc.setEpoch(epoch);

    Serial.println();
  }
}

void writeHours(int num){

  if(num > 12) num = num -12;

  if(num > 9){

    int n = num - 10;
    matrix.writeDigitNum(0, 1, 0);
    matrix.writeDigitNum(1, n, 0);
  }else{
    matrix.writeDigitNum(0, 0, 0);
    matrix.writeDigitNum(1, num, 0);
  }
}

void writeMinutes(int num){

  if(num > 9){

    int n1 = num % 10;
    int n2 = num / 10;
    matrix.writeDigitNum(3, n2, 0);
    matrix.writeDigitNum(4, n1, 0);
  }else{
    matrix.writeDigitNum(3, 0, 0);
    matrix.writeDigitNum(4, num, 0);
  }

  matrix.writeDisplay();
}

void print2digits(int number) {
  if (number < 10) {
    Serial.print("0");
  }
  Serial.print(number);
}

void printTime(){

  // if(hour > 12) hour = hour - 12;

    print2digits(hour);
    Serial.print(":");
    print2digits(minute);
    Serial.print(":");
    print2digits(second);
    Serial.println();
  }

void printDate(){
  Serial.print(rtc.getDay());
  Serial.print("/");
  Serial.print(rtc.getMonth());
  Serial.print("/");
  Serial.print(rtc.getYear());

  Serial.print(" ");
}

////////////

sound.h:

#include <I2S.h>

int frequency; //in Hz
int sampleRate; //in Hz
int amplitude;
bool octave;
int halfWavelength; // half wavelength of square wave

int sound;
int volume;


void ringtone_1(){

  frequency = 1000;
  sampleRate = 8000;
  octave = true;
  short sample; // current sample value
  int count = 0;

  // start I2S at the sample rate with 16-bits per sample
  if (!I2S.begin(I2S_PHILIPS_MODE, sampleRate, 16)) {
    Serial.println("Failed to initialize I2S!");
    while (1); // do nothing
  }

  Serial.println("ALARM!!!");

  while(1){
    if(count > 1000){
        sample = 0;
    }else{
      sample = 2000;
      if(octave){
        octave = false;
        frequency *= 2;
      }else{
        octave = true;
        frequency /= 2;
      }
    }

    halfWavelength = (sampleRate / frequency);

    if (count % halfWavelength == 0) {
      // invert the sample every half wavelength count multiple to generate square wave
      sample = -1 * sample;
    }

    // write the same sample twice, once for left and once for the right channel
    I2S.write(sample);
    I2S.write(sample);

    // increment the counter for the next sample
    count++;

    if(count >= 2001){ count = 0;}
  }
}

Try to underestand BlinkWithoutDelay and implement just that delay-free timing in your code. It's a bad idea to print much text to Serial and display with every iteration of loop(), and stop the controller for 5 seconds to reduce the amount of printed text.

Why do you name your sketch as main.h, where everybody else names it *.ino?

Thank you for your response.

I will implement dealy-free timing on my code, thanks for the suggestion.

Regarding my main problem which is the conflict between the RTCZero and the I2S library, are you able to help?

Thanks again,

Eli

Fix the indicated issues and most trouble has gone away.

Hi, I have implemented delay-free timing on my main.cpp code and the problem persists. As I said before, the problem seems to be when I initialize the clock with rtc.begin(). The RTCZero library is conflicting with the I2C library.

//main.cpp:

#include "wifiConnect.h"
#include "httpClient.h"
#include "getTime.h"
#include "sound.h"

#include <ArduinoJson.h>

//create memory pool for json response
StaticJsonDocument<200> doc;

const long callInterval = 15000;
unsigned long previousMillis;

const int localAlarmHour = 21;
const int localAlarmMinute = 50;

void setup()
{
  Serial.begin(9600);

  //connect to wifi
  wifiConnect();

  //clock init
  rtc.begin(); // <- HERE'S THE PROBLEM

  // //get time in epoch format
  getEpoch();

  // //backpack init
  matrix.begin(0x70);
  // ringtone_1();
}

void loop(){

  hour = rtc.getHours();
  minute = rtc.getMinutes();
  second = rtc.getSeconds();

  //Adjust for timezone
  if(hour > 4){
    hour += GMT;
  }else{
    hour += 24 + GMT;
  }

  //WRITE TO LED
  writeHours(hour);
  writeMinutes(minute);
  matrix.drawColon(second % 2 == 0);
  matrix.writeColon();

  unsigned long currentMillis = millis();

  if(currentMillis - previousMillis >= callInterval){
    previousMillis = currentMillis;

    //Print to serial monitor
    Serial.println("----------------------");
    printDate();
    printTime();

    String str = createClient();
    deserializeJson(doc, str);

    alarmHour = doc["alarmHour"];
    alarmMinute = doc["alarmMinute"];
    sound = doc["sound"]; 
    volume = doc["volume"];

    Serial.print("alarmHour: ");
    Serial.println(alarmHour);
    Serial.print("alarmMinute: ");
    Serial.println(alarmMinute);
    Serial.print("sound: ");
    Serial.println(sound);
    Serial.print("volume: ");
    Serial.println(volume);
  }

  //CHECK IF IT'S TIME TO SOUND ALARM
  if(alarmHour == hour && minute >= alarmMinute){
    ringtone_1();
  }

  if(localAlarmHour == hour && minute >= localAlarmMinute){
    ringtone_1();
  }
}

The other files haven't changed.

Please let me know if there is a way to work around this conflict, or if there are other libraries that I can use to initialize the clock in the MKR1010.

You do way too much output in loop(). Restrict output to Serial to once per second, or drop it at all if you can see the current time on the display.

If somebody already indicated library problems, ask that person/thread for further assistance. Or ask in the MKR... forum for better diagnosis of such problems.

@chacinelias, do not cross-post. Other thread removed.