The program most likely hangs at Wire.endTransmission();
, because that's where the actual I2C communication happens. Wire.write()
does nothing but placing the data into the internal buffer of the Wire
library.
You experience problems, because you are calling interrupt-dependend code inside an ISR, where interrupts are deactivated by default.
The Wire
library uses the I2C hardware of the Uno. This hardware generated interrupts for the different stages in the communication (for example generating an interrupt so that the library can place the next data byte in the hardware buffer). That means, that the Wire
library will not work, if interrupts are turned of for some reason. It will wait forever for an interrupt, that will never come.
When entering an ISR (in this case of the Timer1 interrupt) other interrupts are deactivated by default. At the end of the ISR the compiler will again turn on interrupts. Any interrupts, which happen during the execution of the current ISR will be executed after it has exited.
With Wire.endTransmission()
you currently have a function call in your Timer1 ISR, which will wait for its corresponding I2C ISRs to run, which cannot happen inside the Timer1 ISR.
What to do now: You need to restructure your code. You shouldn't do that much stuff in an ISR either way. It needs to be as short as possible to not disturb other interrupt based functions. In the ISR just set a simple 1-byte flag variable. Then in loop()
check this flag variable. If it is set, you can do the stuff, which currently is in your ISR. And then you reset the flag to be ready for the next ISR setting it again. For this to work correctly you need to ditch the delay()
call in loop()
. If you want to do timed things, you can use millis()
like in the BlinkWithoutDelay
example, that comes with the Arduino IDE. Make sure, that nothing can block the loop()
function for a long period of time (meaning longer than the interval between 2 interrupts).