Skip to main content
Spelling fixes; removed unnecessary and sometimes ungrammatical commas
Source Link

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-dependenddependent 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 or longer than the minimal time resolution, that you want in your system).


Note: You thought of the wrong line while debugging, because of your Serial output. But Serial output is only helping to a certain extendextent with debugging, since it too needs interrupts to work correctly. All the data, that gets printed in your ISR, will only be send once the ISR exits. Serial.print() and it'sits siblings only fill the buffer of the library, while the actual sending is done in the background via ISRs. So the sending stopped, when it got stuck at the ISR, but that doesn't mean, that this actually was, what you printed directly before that line. Even when not having interrupts involved this might not be the case. Just keep that in mind when using Serial prints for debugging.

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 or longer than the minimal time resolution, that you want in your system).


Note: You thought of the wrong line while debugging, because of your Serial output. But Serial output is only helping to a certain extend with debugging, since it too needs interrupts to work correctly. All the data, that gets printed in your ISR, will only be send once the ISR exits. Serial.print() and it's siblings only fill the buffer of the library, while the actual sending is done in the background via ISRs. So the sending stopped, when it got stuck at the ISR, but that doesn't mean, that this actually was, what you printed directly before that line. Even when not having interrupts involved this might not be the case. Just keep that in mind when using Serial prints for debugging.

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-dependent 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 or longer than the minimal time resolution, that you want in your system).


Note: You thought of the wrong line while debugging, because of your Serial output. But Serial output is only helping to a certain extent with debugging, since it too needs interrupts to work correctly. All the data that gets printed in your ISR will only be send once the ISR exits. Serial.print() and its siblings only fill the buffer of the library, while the actual sending is done in the background via ISRs. So the sending stopped when it got stuck at the ISR, but that doesn't mean that this actually was what you printed directly before that line. Even when not having interrupts involved this might not be the case. Just keep that in mind when using Serial prints for debugging.

added 779 characters in body
Source Link
chrisl
  • 16.5k
  • 2
  • 17
  • 27

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 or longer than the minimal time resolution, that you want in your system).


Note: You thought of the wrong line while debugging, because of your Serial output. But Serial output is only helping to a certain extend with debugging, since it too needs interrupts to work correctly. All the data, that gets printed in your ISR, will only be send once the ISR exits. Serial.print() and it's siblings only fill the buffer of the library, while the actual sending is done in the background via ISRs. So the sending stopped, when it got stuck at the ISR, but that doesn't mean, that this actually was, what you printed directly before that line. Even when not having interrupts involved this might not be the case. Just keep that in mind when using Serial prints for debugging.

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).

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 or longer than the minimal time resolution, that you want in your system).


Note: You thought of the wrong line while debugging, because of your Serial output. But Serial output is only helping to a certain extend with debugging, since it too needs interrupts to work correctly. All the data, that gets printed in your ISR, will only be send once the ISR exits. Serial.print() and it's siblings only fill the buffer of the library, while the actual sending is done in the background via ISRs. So the sending stopped, when it got stuck at the ISR, but that doesn't mean, that this actually was, what you printed directly before that line. Even when not having interrupts involved this might not be the case. Just keep that in mind when using Serial prints for debugging.

Source Link
chrisl
  • 16.5k
  • 2
  • 17
  • 27

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).