I2C stops working

I have a project where I read temperature from a Si7051 sensor using I2C. To set parameters in this project I use a rotary encoder, and when I turn the encoder CCW +1 clicks the temp sensor running on I2C stops working, last thing it does is setting the temp to around -323.
This does not happen when I turn CW, or when I use the pushbutton on the encoder, and only the I2C stops working, my DS18B20s keep working and so does serial to the Nextion display.
Any help would be really splendid, and yes my program structure is horrible :o)

/**************************************************************************************
This is example for ClosedCube Si7051 ±0.1°C Digital Temperature Sensor breakout board

Initial Date: 15-May-2016

Hardware connections for Arduino Mega:
VDD to 3.3V DC
SCL to 21
SDA to 20
GND to common ground

Written by AA for ClosedCube

MIT License
**************************************************************************************/

#include <Wire.h>
#include "ClosedCube_Si7051.h"
#include <Encoder.h>
#include <OneWire.h>
#include <DallasTemperature.h>

// Data wire is plugged into port 2 on the Arduino
#define ONE_WIRE_BUS 3

// Setup a oneWire instance to communicate with any OneWire devices
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);

// Addresses of 3 DS18B20s
uint8_t sensor1[8] = { 0x28, 0xF2, 0x21, 0x0A, 0x06, 0x00, 0x00, 0xFD };
uint8_t sensor2[8] = { 0x28, 0xFF, 0xC1, 0xAE, 0x4E, 0x04, 0x00, 0xE5 };
//uint8_t sensor3[8] = { 0x28, 0x61, 0x64, 0x12, 0x3F, 0xFD, 0x80, 0xC6 }; // Spare sensor

ClosedCube_Si7051 si7051;



int Kp=2, Ki=5, Kd=1;   //PID variables start-up values
float SetTemp;

const int buttonPin = 2;     // the number of the pushbutton pin
int buttonPushCounter = 0;   // counter for the number of button presses
int buttonState = 0;         // current state of the button
int lastButtonState = 0;     // previous state of the button
int MaxTemp = 25;

Encoder myEnc(18, 19);

void setup()
{
  
  sensors.setResolution(sensor1, 9);
  sensors.setResolution(sensor2, 9);
//  sensors.setResolution(sensor3, 9);
  
  sensors.begin();  

  pinMode(18, INPUT_PULLUP); // initialize the pushbutton pin as an input
  pinMode(19, INPUT_PULLUP); // initialize the pushbutton pin as an input  pinMode(2, INPUT_PULLUP);
  
  pinMode(buttonPin, INPUT_PULLUP); // initialize the pushbutton pin as an input
  pinMode(10, OUTPUT);    // sets the digital pin 10 as output
  
   
	//Serial.begin(9600);
  Serial3.begin(9600);

	si7051.begin(0x40); // default I2C address is 0x40 and 14-bit measurement resolution

//	switch (si7051.readFirmwareVersion())
//	{
//	case 0xFF:
//		Serial.println("version 1.0");
//		break;
//	case 0x20:
//		Serial.println("version 2.0");
//		break;
//	default:
//		Serial.println("unknow");
//			break;
//	}

}

int oldPosition  = -999; //rotary encoder

int realPosition;
int pid_p_bit;      //ensures PID values arent overwritten by encoder.h value
int pid_i_bit;      //ensures PID values arent overwritten by encoder.h value
int pid_d_bit;      //ensures PID values arent overwritten by encoder.h value
int t_max_bit;

int test_1 = 11;
int test_2 = 22;
int test_3 = 33;

void loop()
{  
 

  //************** DS18S20 **********************

  sensors.requestTemperatures();

  
  //************** DS18S20 **********************
  
   //-------------------PID STATE
  buttonState = digitalRead(buttonPin);
  // compare the buttonState to its previous state
  if (buttonState != lastButtonState) {
    // if the state has changed, increment the counter
    if (buttonState == LOW && buttonPushCounter < 4) {
        buttonPushCounter++;
    } else if (buttonState == LOW && buttonPushCounter == 4)
    {   buttonPushCounter = 0;
      // if the current state is LOW then the button went from on to off:
    }
    else
    // Delay a little bit to avoid bouncing
    delay(50);
  }
  // save the current state as the last state, for next time through the loop
  lastButtonState = buttonState;
    
 //*****************BUTTON STOP
  int temp_pos;
  int newPosition = myEnc.read()/4;    //rotary encoder
  if (newPosition != oldPosition) {   //rotary encoder
    oldPosition = newPosition;        //rotary encoder
    Serial.println(newPosition);      //rotary encoder
     }                                //rotary encoder

//********************************************SWITCH - CASE

    switch (buttonPushCounter) {
    case 0:    // no input allowed

      pid_p_bit = 0;            // resets pid value protection bit
      pid_i_bit = 0;            // resets pid value protection bit
      pid_d_bit = 0;            // resets pid value protection bit
      t_max_bit = 0;

      myEnc.write(temp_pos);
      
      break;
    case 1:    // P input allowed

       if( pid_p_bit == 0 )
        {
          temp_pos = newPosition;         
          pid_p_bit = 1;
        }

        if (newPosition != temp_pos)
        {
          Kp += (newPosition % temp_pos);
          myEnc.write(temp_pos);
          }     
      break;
      
    case 2:    // I input allowed
    
       if( pid_i_bit == 0 )
        {
          temp_pos = newPosition;         
          pid_i_bit = 1;
        }

        if (newPosition != temp_pos)
        {
          Ki += (newPosition % temp_pos);
          myEnc.write(temp_pos);
          }  
      break;
      
    case 3:    // D input allowed
          
       if( pid_d_bit == 0 )
        {
          temp_pos = newPosition;         
          pid_d_bit = 1;
        }

        if (newPosition != temp_pos)
        {
          Kd += (newPosition % temp_pos);
          myEnc.write(temp_pos);
          }    
      break;

      case 4:    // T Max input allowed
          
       if( t_max_bit == 0 )
        {
          temp_pos = newPosition;         
          t_max_bit = 1;
        }

        if (newPosition != temp_pos)
        {
           MaxTemp += (newPosition % temp_pos);
          myEnc.write(temp_pos);
          }    
      break;
  }
  
//********************************************SWITCH - CASE
  
  float T_floatx100;                            //converting float to int
  int T_intx100;                                //converting float to int
  
  T_floatx100 = si7051.readTemperature()*100;   //converting float to int, multiply x100

  T_intx100 = (int) T_floatx100;                //converting float to int



  int T_Left_int;                                //converting float to int
  int T_Right_int;                                //converting float to int
  
  float T_Left_float = sensors.getTempC(sensor1);
  T_Left_int = (int) T_Left_float;                //converting float to int

  float T_Right_float = sensors.getTempC(sensor2);
  T_Right_int = (int) T_Right_float;                //converting float to int

  
  // ********* Temperature alarm
  if (T_intx100 > (MaxTemp*100))
  {
    digitalWrite(10, HIGH); // sets the digital pin 10 on
    }
    else if (T_intx100 < (MaxTemp*100))
    {
      digitalWrite(10, LOW); // sets the digital pin 10 off

      }


  
  
  Serial3.print("x1.val="); //declare which Nextion variable will receive
  Serial3.print(T_intx100);  // value sent to Nextion 
  Serial3.write(0xff);  //remember to do this 3 times when sending to Nextion
  Serial3.write(0xff);
  Serial3.write(0xff);

  Serial3.print("n0.val="); // state
  Serial3.print(buttonPushCounter);
  Serial3.write(0xff);  //remember to do this 3 times when sending to Nextion
  Serial3.write(0xff);
  Serial3.write(0xff);

  Serial3.print("n1.val="); // should be PID, Kp
  Serial3.print(Kp);
  Serial3.write(0xff);  //remember to do this 3 times when sending to Nextion
  Serial3.write(0xff);
  Serial3.write(0xff);


 
  
	//delay(100);

}

Post a schematic, not a frizzy thing showing all interconnections etc. Explain how you kjo9w the I2C quit working?

Image as link, I couldnt insert it otherwise

Can you give a link to where you bought your Si7051 module ? This one ? https://www.tindie.com/products/closedcube/si7051-01degc-max-digital-temperature-sensor/.

The Si7051 is a 3.3V sensor with a 3.3V I2C bus and the Arduino Mega has a 5V I2C bus with onboard pullup resistors of 10k to 5V.

Suppose you have that module, then you have a voltage divider with the resistors.
10k + 50k to 5V combined with 10k to 3.3V makes 4.2V.
If you measure SDA and SCL when the I2C bus is idle (but after calling Wire.begin), then you should measure 4.2V.

Since a pin of the Si7051 can be maximum 3.6V, you put too much voltage at its SDA and SCL pins.

Do you use long wires or a cable for the I2C bus ?

Where is the blue wire of the Nextion display ?

How do you power the Mega board ? Can you measure its 5V pin ? it should be above 4.5V. The Arduino Uno can work at lower voltages but the ATmega2560 microcontroller needs at least 4.5V.
How noisy is your power supply ?

There is no limit for the amount of data send to Serial3. Can you at least put some delay back ? 10ms or 100ms.

There is no limit for the amount of requests for the temperatures. The DallasTemperature solves that internally, but the temperature from Si7051 is requested a lot. It would be better to do that once per 2 or per 5 seconds or so.
The temperature sensors might have "self-heating", that is when the chips heats up because it is kept too busy by the Arduino.

Does the problem still occur when you disconnect the wires to the relay module ?

Si7051 is from ClosedCube, the one from your link.
Length of I2C bus ~20cm
I connected a CJMCU-0108 level shifter to Si7051, that did not have any effect.
Nextion blue wire is not connected.
5V from Mega board is measured to 4,93V.
It is supplied from the PC's USB, I dont know how noisy it is?
I had a problem with delays in the main loop, making the encoder sluggish, so I set the DS temp. sensors bit resolution to 9.

I have tried placing a delay(300) at the end of the loop, after serial3, no effect. Same with delay after Si7051 function call.
The problem persists with the solid state disconnected.

I'm sorry, but I don't see the problem :frowning:

Something could be broken or a connection could be bad or there is something with the Encoder library.
The I2C bus can halt a sketch, that is the first place to look, but I don't see a problem with that.

Can you do more tests ?

  • Check all the wires. Sometimes jumper wires are broken and breadboards have bad contacts.
  • If you have enough hardware, then you could build your project twice and check if you have the same problem.
  • The Encoder library has a number of issues. Can you try to make a test-sketch in which you run the non-interrupt version.
  • You could send a text to the serial monitor before and after a Wire.requestFrom() and also before and after Wire.endTransmission(). Use Serial.print() or Serial.println() followed by Serial.flush().
  • Is there an other Encoder library ?
  • The I2C sensor could be broken, or the Mega board could be broken. Can you try with another I2C sensor (it does not have to be a temperature sensor.

The chance that the problem can be found with this list is less than 50%, but you have to do something. Now and then someone replies on this forum that new hardware was bought and everything works.

Check out this page on how to clean up the I2C bus.

I found the problem.
I needed to set the variable reading from the encoder to volatile. For some reason this conflicts with my I2C bus, if it is not volatile, a little odd that it is not volatile in the basic encoder example I would think.

volatile int newPosition = myEnc.read()/4;    //rotary encoder

I'm glad that your sketch is working :smiley: However, that is not the problem.

It could be a compiler bug, but that chance is very low.
Such weird problems is an indication of writing to unknown memory location (beyond the array limits) or overwriting the stack. I don't think that this is the problem.

By adding the keyword 'volatile', the compiler optimizes less extreme. That might solve a problem in the Encoder library.
With interrupts enabled, the myEnc.read() is a inline function.

I can not pinpoint the problem in the Encoder library, so I can not make an issue for the Encoder library :frowning:

Can you add comment or keep in mind that the Encoder library might not always work in your sketch ?

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.