So I'm receiving data from an ESP module via I2C. I then need to send this data immediately over the UART. Not sure how I should do this. Would it be ok to place the UART sending inside the i2c receive interrupt?

  • 1
    \$\begingroup\$ Before you can implement this, you need to decide what should happen if the I2C generates data faster than the serial port can dispose of it, or implement something to make sure that cannot happen. One you have that, you can use an efficient implementation of a transmit buffer. \$\endgroup\$ Feb 27, 2019 at 17:33

1 Answer 1


Are you using the Arduino IDE to program your ESP8266? Never put Serial code into an interrupt function. More info here. Check the section Hints for writing ISRs

Regardless of the IDE you're using, I'd recommend you to define a global variable in your code (generally a boolean) to inform that your data was received over the I2C protocol, then in the main part of the code (loop function in Arduino programs) you could check this variable and then send the received data over the UART.

Here is an example using the Arduino IDE. Of course, you'll have to use the correspondent Wire library to your ESP8266.

EDIT: Added the concept of atomicity to ensure our variable inputString is not messed up with consecutive unhandled interruption. For more details, you can check this demonstration

#include <Wire.h>
#include <util/atomic.h>

String inputString = ""; // a String to hold incoming data
volatile bool stringCompleted = false; // whether the string is complete

void setup() {
  Wire.begin(0x20); // join i2c bus with address 0x20
  Wire.onReceive(receiveEvent); // register event

  // reserve 200 bytes for the inputString:

  Serial.begin(9600); // start serial for output

void loop() {
    // print the string when a newline arrives:
    if(stringCompleted) {
      // clear the string:
      inputString = "";
      stringCompleted = false;

// function that executes whenever data is received from master
// this function is registered as an event, see setup()
void receiveEvent(int howMany) {
  while (Wire.available() > 0) { // loop through all
    char inChar = (char)Wire.read(); // receive byte as a character

    inputString += inChar; // add it to the inputString:

    // if the incoming character is a newline, set a flag so the main loop can
    // do something about it:
    if(inChar == '\n') {
      stringCompleted = true;
  • \$\begingroup\$ I think you need the volatile attribute for your global bool variable. Also, to be precise, serial code in an ISR is fine, calls to Serial.print() should not be in an ISR. \$\endgroup\$ Feb 27, 2019 at 13:03
  • \$\begingroup\$ Yeah! and Serial.read() must not be used also. To avoid problems, I prefer to not put Serial codes in ISRs at all. You are correct about the volatile attribute \$\endgroup\$ Feb 27, 2019 at 13:06
  • \$\begingroup\$ Using the expensive String class for this is unwise. It would actually be better to use the already written efficient transmit buffering in the Serial class, the catch is that you need to detect the overflow condition where it can block. But your code does not handle that either, and with I2C often faster that is quite possible - or probable if you try to use such a slow baud rate! \$\endgroup\$ Feb 27, 2019 at 15:11
  • \$\begingroup\$ Further, unless you can prove that operation on String objects are atomic (which seems unlikely) mutating them in an ISR event is unsafe. In short, this code creates several new problems while trying to solve one simple one. \$\endgroup\$ Feb 27, 2019 at 15:18
  • \$\begingroup\$ @ChrisStratton what do you mean about "atomic"? I have never had any problems with this code before. It works simply fine, even in an expensive code. It's important to say this is one of the standard examples from the Arduino software, provided by the Arduino company. However, I'd like to see your improvement suggestions. Can you please give us some example? \$\endgroup\$ Feb 27, 2019 at 15:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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