I2C gets stuck after a while

Hi!

I built a simple box with a heating element controlled via a transistor, a small fan directly connected to 5V and GND on the Arduino Nano and a thermometer and an oled screen connected via I2C. There also is a rotary encoder to select the temperature.

It’s used to keep the box consistently at a certain temperature and the logic is the most basic: if the temperature is below the chosen one the transistor opens, if the temperature rises above the transistor closes.

The problem I’m facing now: from time to time the screen just freezes. If restart the Arduino really quickly and get a measurement of the temperature it seems as if the transistor would be constantly opened because it gets quite hot. But it seems as if only I2C would be stuck because the LEDs on the Arduino still flicker when turning the rotary encoder.

Does anyone has some tips on how to approach troubleshooting for this?
Here’s the code:

#include <Adafruit_SSD1306.h>
#include <splash.h>

/***************************************************************************
  This is a library for the BME280 humidity, temperature & pressure sensor

  Designed specifically to work with the Adafruit BME280 Breakout
  ----> http://www.adafruit.com/products/2650

  These sensors use I2C or SPI to communicate, 2 or 4 pins are required
  to interface. The device's I2C address is either 0x76 or 0x77.

  Adafruit invests time and resources providing this open source code,
  please support Adafruit andopen-source hardware by purchasing products
  from Adafruit!

  Written by Limor Fried & Kevin Townsend for Adafruit Industries.
  BSD license, all text above must be included in any redistribution
  See the LICENSE file for details.
 ***************************************************************************/

#include <Wire.h>
#include <SPI.h>
#include "cactus_io_BME280_I2C.h"
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Fonts/FreeSans18pt7b.h>
#include <Fonts/FreeSans12pt7b.h>
#include <Fonts/FreeSans9pt7b.h>
#include <Fonts/FreeSansBold12pt7b.h>
#include <Arduino_Helpers.h>

#define encoder0PinA  3
#define encoder0PinB  2

#define raster 1 //rasterung

volatile unsigned int encoder0Pos = 0;

BME280_I2C bme(0x76); // I2C using address 0x76

//für an aus trigger - heizplatte
//#define ButtonPin 4 // blau
#define GatePin 9

int ZielTemp = 60;

int flag = 1;
int ButtonState = 0;
float Temperatur = 0;
int Feucht = 0;

Adafruit_SSD1306 display(128, 64, &Wire, -1);


void setup() {
  Serial.begin(9600);
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display.clearDisplay();
  display.setTextColor(WHITE);
  display.display();

  // pinMode(ButtonPin, INPUT_PULLUP);
  pinMode(GatePin, OUTPUT);
  digitalWrite(GatePin, LOW);


  //encoderAction
  pinMode(encoder0PinA, INPUT);
  pinMode(encoder0PinB, INPUT);

  // encoder pin on interrupt 0 (pin 2)
  attachInterrupt(0, doEncoderA, CHANGE);

  // encoder pin on interrupt 1 (pin 3)
  attachInterrupt(1, doEncoderB, CHANGE);




  if (!bme.begin()) {
    Serial.println("Es konnte kein BME280 Sensor gefunden werden!");
    Serial.println("Bitte überprüfen Sie die Verkabelung!");
    while (1);
  }
}

void loop() {
  //  display.clearDisplay();
  //  display.setFont(&FreeSans9pt7b);
  //  display.setCursor(0, 27);
  //  display.println("Temp");
  //  display.setFont(&FreeSans12pt7b);
  //  display.setCursor(70, 30);
  //  display.println(bme.readTemperature(),1);
  //  display.setFont(&FreeSans9pt7b);
  //  display.setCursor(0, 55);
  //  display.println("Hygro");
  //  display.setCursor(70, 55);
  //  display.println(bme.readHumidity(),1);
  //  display.display();

  bme.readSensor();
  Temperatur = bme.getTemperature_C();
  Feucht = bme.getHumidity();

 displayon();

  if (Temperatur < ZielTemp) {

  displayon();
    digitalWrite(GatePin, HIGH);

    while (Temperatur < ZielTemp) {
      bme.readSensor();
      Temperatur = bme.getTemperature_C();
        Feucht = bme.getHumidity();
      displayon();
      // Do nothing, warten auf nächsten Tastendruck


      delay(100);
    }

  }
  else {
    bme.readSensor();
    Temperatur = bme.getTemperature_C();
      Feucht = bme.getHumidity();
  displayoff();
    digitalWrite(GatePin, LOW);
  }

  delay(100);

  while (Temperatur > ZielTemp) {
    bme.readSensor();
    Temperatur = bme.getTemperature_C();
      Feucht = bme.getHumidity();
    displayoff();
    digitalWrite(GatePin, LOW);


    delay(100);
  }
}

void doEncoderA() {
  // look for a low-to-high on channel A
  if (digitalRead(encoder0PinA) == HIGH) {

    // check channel B to see which way encoder is turning
    if (digitalRead(encoder0PinB) == LOW) {
      encoder0Pos = encoder0Pos + raster;         // CW
    }
    else {
      encoder0Pos = encoder0Pos - raster;         // CCW
    }
  }

  else   // must be a high-to-low edge on channel A
  {
    // check channel B to see which way encoder is turning
    if (digitalRead(encoder0PinB) == HIGH) {
      encoder0Pos = encoder0Pos + raster;          // CW
    }
    else {
      encoder0Pos = encoder0Pos - raster;          // CCW
    }
  }
  Serial.println (encoder0Pos, DEC);

  ZielTemp = encoder0Pos;
}

void doEncoderB() {
  // look for a low-to-high on channel B
  if (digitalRead(encoder0PinB) == HIGH) {

    // check channel A to see which way encoder is turning
    if (digitalRead(encoder0PinA) == HIGH) {
      encoder0Pos = encoder0Pos + raster;         // CW
    }
    else {
      encoder0Pos = encoder0Pos - raster;         // CCW
    }
  }

  // Look for a high-to-low on channel B

  else {
    // check channel B to see which way encoder is turning
    if (digitalRead(encoder0PinA) == LOW) {
      encoder0Pos = encoder0Pos + raster;          // CW
    }
    else {
      encoder0Pos = encoder0Pos - raster;          // CCW
    }
  }
  ZielTemp = encoder0Pos;
}

void displayon() {
   display.clearDisplay();
      display.setFont(&FreeSans9pt7b);
      display.setCursor(0, 63);
      display.println("H");
      display.setCursor(90, 63);
      display.println(Feucht);
      display.setCursor(110, 63);
            display.println("%");
    display.setCursor(39, 45);
      display.setFont(&FreeSansBold12pt7b);
      display.println(Temperatur, 1);
      display.setFont(&FreeSans9pt7b);
    display.setCursor(53, 24);
      display.println(ZielTemp);
      display.display();
}

void displayoff() {
   display.clearDisplay();
      display.setFont(&FreeSans9pt7b);
      display.setCursor(0, 63);
     // display.println("H");
      display.setCursor(90, 63);
      display.println(Feucht);
      display.setCursor(110, 63);
            display.println("%");
    display.setCursor(39, 45);
      display.setFont(&FreeSansBold12pt7b);
      display.println(Temperatur, 1);
      display.setFont(&FreeSans9pt7b);
    display.setCursor(53, 24);
      display.println(ZielTemp);
      display.display();
}

Best
Frank

        while (Temperatur < ZielTemp) {

you have potentially infinite loops that can trap the code

i would check a temperature and perform some action (e.g. turn on a fan), but not continually check the temperature. That happens normally with an “if” each time loop() executes