DS3231 + Temp sensor error


I’m writing a code for my fish tank, but the temperature sensor’s value wasn’t smooth enough, so I would like to use the “Smooth” example. It 's working fine if I upload just the example, but with my whole code, it isn’t good. Normally it sends a value like 430, but in the big code, it gives me more and more, like 430-560-700-900 and so on.

I’ve figured it out, that it has some problem with the DS3231, if i // just this one row: “byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;”, it’s working fine. Full code attached.

Can the DS3231 internal temp sensor cause this, (maybe the library) or what should I do?

English is not my native language, sorry about that, and thanks for reading this!

#include <DS3231.h>
#include <SoftwareSerial.h>
#include <Wire.h>
#include <FastIO.h>
#include <I2CIO.h>
#include <LCD.h>
#include <LiquidCrystal.h>
#include <LiquidCrystal_I2C.h>
#include <LiquidCrystal_SR.h>
#include <LiquidCrystal_SR2W.h>
#include <LiquidCrystal_SR3W.h>
#include <microsmooth.h>
#define aref_voltage 3.3
#include <math.h>
#include <ClickEncoder.h>
#include <TimerOne.h>
#define THERMISTORNOMINAL 10000      
#define BCOEFFICIENT 3950
#define SERIESRESISTOR 10000
#define DS3231_I2C_ADDRESS 0x68
DS3231 Clock;

int relay = 11; // relay1 -------
int neon = 12; // relay1 neon lights
int pump = 4; // relay3 pump
int heater = 5; // relay4 heater
int LED = 6; // PWM RED LED
int wls = 8; // Water level switch
int moon = 9; // PWM ORANGE
int fan = 10; // PWM  WHITE FAN
int e1 = A2; //Error LED 1 water level
int e2 = A1; //Error LED 2 water temp
int lcdbl = A0; //LCD BackLight
int eled = 13; // Internal Error LED
int temppin = A3; //temp sensor
int wlsv = LOW; // water level value változó
int tempMin = 24; //FAN speed min, 24C
int tempLed = 26;
int tempMax = 26; //FAN speed max, 26C
int FANspeed; //FAN speed változó
int FANsz;
int FANl;
int neonv;
int allminute;
int LED_UPFADEON = 570;
int LED_UPFADEOFF = 600;
int LED_DOWNFADEON = 1320;
int LEDv;
int leddisp;
unsigned long previousMillistemp;
unsigned long previousMillistempz;
unsigned long timeoutTime = 10000;
unsigned long previousMilliswlsv;
unsigned long previousMillispump;
int intervalpump = 5000;
int lastvalue = 0;
int menuTimeout = 10000;
int intervaltemp = 1000;
int blinktimetemp = 1000;
int intervalwlsv = 5000;
int blinktimewlsv =50;
LiquidCrystal_I2C  lcd(0x27,2,1,0,4,5,6,7); // 0x27 is the I2C bus address for an unmodified backpack
byte decToBcd(byte val) {return( (val/10*16) + (val%10) );}
byte bcdToDec(byte val){return( (val/16*10) + (val%16) );}
bool h12;
bool PM;
ClickEncoder *encoder;
int16_t last, value;
void timerIsr() {encoder->service();}
float steinhart;
 long uptimedays=0;
 long uptimehours=0;
 long uptimemins=0;
 long uptimesecs=0;
int const offpump = 5;
const int numReadings = 10;
int readings[numReadings];      // the readings from the analog input
int readIndex = 0;              // the index of the current reading
int total = 0;                  // the running total
int average1;                // the average

void setup() {
  pinMode (neon, OUTPUT);
  pinMode (heater, OUTPUT);
  pinMode (pump, OUTPUT);
  pinMode (LED, OUTPUT);
  pinMode (wls, INPUT_PULLUP);
  pinMode (moon, OUTPUT);
  pinMode (fan, OUTPUT);
  pinMode (e1, OUTPUT);
  pinMode (e2, OUTPUT);
  pinMode (eled, OUTPUT);
  pinMode (temppin, INPUT);
  pinMode (lcdbl, OUTPUT);
  digitalWrite (pump, HIGH);    ///////////
lcd.begin (16,2); // for 16 x 2 LCD module
  digitalWrite (heater, HIGH);
  digitalWrite (LED, LOW);     //////////
  digitalWrite (moon, HIGH);   //////////
  digitalWrite (fan, LOW);
  digitalWrite (eled, LOW);
  digitalWrite (e1, HIGH);
  digitalWrite (e2, HIGH);
  digitalWrite (lcdbl, HIGH);
  digitalWrite (e1, LOW);
  digitalWrite (e2, LOW);
  digitalWrite (neon, LOW); 
encoder = new ClickEncoder(2, 3, 7);
Timer1.attachInterrupt(timerIsr); last = -1;}

void readDS3231time(byte *second,
byte *minute,
byte *hour,
byte *dayOfWeek,
byte *dayOfMonth,
byte *month,
byte *year)
{ Wire.beginTransmission(DS3231_I2C_ADDRESS);
  Wire.write(0); // set DS3231 register pointer to 00h
  Wire.requestFrom(DS3231_I2C_ADDRESS, 7);
  // request seven bytes of data from DS3231 starting from register 00h
  *second = bcdToDec(Wire.read() & 0x7f);
  *minute = bcdToDec(Wire.read());
  *hour = bcdToDec(Wire.read() & 0x3f);
  *dayOfWeek = bcdToDec(Wire.read());
  *dayOfMonth = bcdToDec(Wire.read());
  *month = bcdToDec(Wire.read());
  *year = bcdToDec(Wire.read());  
  for (int thisReading = 0; thisReading < numReadings; thisReading++)    readings[thisReading] = 0;

void loop() {

  total = total - readings[readIndex];
  readings[readIndex] = analogRead(temppin);
  total = total + readings[readIndex];
  readIndex = readIndex + 1;
  if (readIndex >= numReadings)
    readIndex = 0;
  average1 = total / numReadings; 
  delay(100);        // delay in between reads for stability
  average1 = 1023 / average1 - 1;
  average1 = SERIESRESISTOR / average1;
  steinhart = THERMISTORNOMINAL / average1 ;     // (R/Ro)
  steinhart = log(steinhart);                  // ln(R/Ro)
  steinhart /= BCOEFFICIENT;                   // 1/B * ln(R/Ro)
  steinhart += 1.0 / (TEMPERATURENOMINAL + 273.15); // + (1/To)
  steinhart = 1.0 / steinhart;                 // Invert
  steinhart -= 273.4;                         // convert to C
  Serial.print("Temperature "); 
  Serial.println(" *C");

  byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;                 // retrieve data from DS3231
 readDS3231time(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year); 

nagyprojekt.ino (11.9 KB)

Why do you include a DS3231 library, and then not use it? Also, please try again to explain the problem. Please be more specific. It's hard to understand what trouble you're experiencing.

The code is not done yet, and I will use the alarm fuctions, that's why that's included. The problem is, if I upload just the Smooth example, it works fine, I serialPrint a value like 430. That means ~24,3 Celsius, so it works fine.

When I use this code above, I don't get a stable value, it keeps growing with every read till 3200, then there is a rollover to -3000, and it happens again and again.

Which Arduino are you running that code on? How much memory is available when the code is running?


It's a Duemilanove Clone.
Free memory: 884
I made a picture.

You've declared average1 to be an integer so these three statements:

 average1 = 1023 / average1 - 1;
  average1 = SERIESRESISTOR / average1;
  steinhart = THERMISTORNOMINAL / average1 ;     // (R/Ro)

will be done with integer arithmetic. If an expected average is 430, the first statement will set average1 to 1. The second will then set average1 to SERIESRESISTOR which is 10000. The end result is that 'steinhart' will always be set to one.

In the loop function you always call the readDS3231time function. And in readDS3231time you always zero the readings array which means that your smoothing is only ever going to see one reading and nine zeroes which will make the average very small.


I've changed average1 to be a float, thanks for that.

But with the other thing, what should I do? I have to know what is the time, because of the lights. And for extended use, the millis() is not precise.

 for (int thisReading = 0; thisReading < numReadings; thisReading++)    readings[thisReading] = 0;

el_supremo has pointed out that this line is the last line of the readDS3231() function. All the readings are set to zero. It is some sort of stray line that needs to be up where you declare the array, or wherever you want to start a new series of readings.

When you enter your smoothing routine, the first subtraction total = total - readings[readIndex]; readings[readIndex] is 0 and you are subtracting 0. Total will continue to grow by one reading each time. You never subtract a value, so it grows until it overflows and starts around again.