Problem using Wire library and interrupts

Dear forum readers!
I have a problem using Wire library and interrupts together. Below you will find short program which represent the problem: program newer print “Test point: 2”. I use Arduino Mega 2560. If I remove part one (// Wire) or part two (// Interrupts) everything is OK.
Hope you have some suggestions how to solve this problem or what to try.

Many thanks,
Rok

// Problem: program newer print "Test point: 2". Test on Arduino Mega 2560.
#include <Wire.h>

volatile int puls;
void interrupt() { puls++; }

void setup(void) {
  Serial.begin(9600);
  Wire.begin();
  attachInterrupt(0, interrupt, RISING);
}

void loop(void) {
  // Wire
  Wire.beginTransmission(0x68);
  Wire.write((byte)0);
  Wire.endTransmission();

  // Interrupt
  Serial.println("Test point: 1");
  sei(); delay(1000); cli();
  Serial.println("Test point: 2");
}

When the code go to the interrupt rotine it disable interrupts.Look wire.h source to understand if make interrupts because maybe is this the problem.

Your code doesn't do anything sensible.

  Wire.beginTransmission(0x68);
  Wire.write((byte)0);
  Wire.endTransmission();

This just tells the realtime clock that you are going to read or write to/from its register zero, but then you do neither. It is also NOT a good idea to send to the clock so frequently because it will make the clock drift much faster than it would normally.

  Serial.println("Test point: 1");
  sei(); delay(1000); cli();
  Serial.println("Test point: 2");

This prints a message, turns interrupts on (why?), waits a second, turns interrupts off (WHY?) and prints another message (with interrupts off, maybe it doesn't print).

I think the RTC might, by default, output a 1Hz signal. If it does, and if you have the SQW signal connected to the correct pin, an interrupt will occur once every second. This will cause the interrupt routine to increment puls but you don't do anything with it so I can't see how you know whether or not the clock is interrupting. Turning off interrupts is also going to complicate things.

Now, what did you actually want it be doing?

Pete

Serial printing requires interrupts to be on, as does I2C.

Normally you don't need to turn interrupts off.

http://gammon.com.au/interrupts

Dear all,

I would like to thank you for all your answers!

Sorry that I forget to point out (it was obviously for me) that the program does nothing sensible but it is just (minimal) example that using Wire library together with interrupts don't work in the provided example.

I can provide (quite longer) program which do something useful but this doesn't make sense for me. Maybe it is better to imagine that the first part of the program (// Wire) reads time values from the DS1307 chip (as in example in void get_time() on this page: http://quickstartkitforarduino.blogspot.com/2012/05/simple-labs-quick-start-kit-for-arduino_17.html) and the second part of the program (// Interrupt) counts the number of interrupts (actually rising signal, let say from the hall effect sensor) from Arduino digital input D2 (interrupt 0 location on Arduino Mega) in the time period of one second. Maybe it is necessary that I mention that the second part of the program has nothing to do with the first (so measuring interrupts from hall effect sensor and reading time values from DS1307 chip are two separate things). I just want to have a program that first: reads values from clock and second: count the number of interrupts in one second period. But I have no ideas what this program does not work ... Suggestions are welcomed! Thanks, Rok

Don't turn interrupts off for a second, for a start.

Dear Nick,

thank you for this suggestion! If I remove cli(); program is working. But in this case the hall effect sensor will call interrupt() void all the time. Generally it is nothing wrong with this but it is not optimal (program will have to deal with interrupts when this is not necessary).

Well that would only take around 5 µS per pulse, but if that troubles you, you can detachInterrupt when it is not required.

Dear Nick, it seems that using attachInterrupt and detachInterrupt solve this problem. Thank you for your wise suggestion! Regards, Rok

Hi I am using arduino uno and faced similar kind of issue when when I was trying to periodically update display from DS1307 using TimerOne interrupt. I have got one solution that might be helpful.

unsigned long previousMillis=0;
unsigned long interval=1000;
void setup(){
    //Setup Code
}
void loop(){
    unsigned long currentMillis=millis();
    if(currentMillis - previousMillis > interval){
        myTimerISR();
        previousMillis = currentMillis;
    }
    //Loop Code
}
void myTimerISR(){
    //Timer Code
}

There are two drawback here 1. After 50 days the millis() goes to 0. So the arduino need to be restarted. 2. The timer interrupt is not accurate. It executes all remaining loop code every time then only it can goes to the timerISR again. So the execution time of whole loop should be much lower than timer interval. In case of updating time from RTC generally we update display in 0.5 sec and if the execution time of loop is few mili sec then this solution might be useful.

Regards, Rahul Kundu

rahulkundu4u: 1. After 50 days the millis() goes to 0. So the arduino need to be restarted.

No, it doesn't. The way you have written it is correct. The unsigned long will wrap around and the calculation will be correct.

if(currentMillis - previousMillis > interval){
        myTimerISR();
        previousMillis = currentMillis;
    }

You have a funny notion of what an ISR is. That is just a function call.