Strange analogRead (0,256,512) behavior in combination with DS18B20 on onewire.

Hello, I am new to this forum so hello everyone :).

I have strange behavior of analogRead. I know from this forum and another sources that people have distorted readings when they read from separate Analog pins without delay. But my behavior is weird in another way. Reading from A0 is ok, and reading from A1 gives only values 0, 256, 512 but when I comment out reading temperature from onewire sensor, than readings on both A0 and A1 works as expected.

Affected reading: int soilHumidity2 = analogRead(A1); (I tried to move to A2 too, and I tried differend ATmega328p chip)

After I comment out this line: float soilTemperature2 = tempSensors.getTempCByIndex(1);

than readings are fine as expected.

I use 2x DS18B20 and 2x Capacitive Soil Moisture v1.2 sensor with output pin connected to A0 and A1, both A0 and A1 are connected by 1M pull down.

In this case my ATmega328P-PU is on breadboard without external oscilator on 8Mhz. Powered from AA batteries, input voltage was 5.02 V. AREF is connected to VCC.

My code (I skipped how I handle buttons, unimportant screens with settings etc. but kept all important parts):

#include <Wire.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <SSD1306Ascii.h>
#include <SSD1306AsciiAvrI2c.h>
#include <Sodaq_DS3231.h>
#include <avr/sleep.h>
#include <avr/power.h>
#include <EEPROM.h>

#define F_CPU 8000000L
#define I2C_OLED_ADDRESS 0x3C
#define ONE_WIRE_BUS_PIN 4

#define ANALOG_SENSOR_CONTROL 10

#define SLEEP_EEPROM_ADDR 0

unsigned long lastBtnPress = 0; // time in ms
unsigned char lastButton = 0; // number of button

bool sleeping = true;
unsigned int sleepAfter = 30000;

DateTime now;
OneWire oneWire(ONE_WIRE_BUS_PIN);
DallasTemperature tempSensors(&oneWire);
SSD1306AsciiAvrI2c oled;


void setup(void)
{
  wakeUp();
}

void loop(void) {
  [b]tempSensors.requestTemperatures(); // Send the command to get temperatures
  float soilTemperature1 = tempSensors.getTempCByIndex(0);
  float soilTemperature2 = tempSensors.getTempCByIndex(1);
  int soilHumidity1 = analogRead(A0);
  delay(100);
  int soilHumidity2 = analogRead(A1);[/b]
  
  now = rtc.now();
  char actual_time[16];
  sprintf(actual_time, "%02d:%02d %02d.%02d.%04d", now.hour(), now.minute(), now.date(), now.month(), now.year());

  oled.setRow(1);
  oled.setCol(3);
  oled.print(actual_time);
  oled.clearToEOL ();

  oled.setRow(4);
  oled.setCol(1);
  oled.print("Teplota 1: ");
  oled.print(soilTemperature1);
  oled.clearToEOL ();

  oled.setRow(5);
  oled.setCol(1);
  oled.print("Vlh. pody 1: ");
  oled.print(soilHumidity1);
  oled.clearToEOL ();

  oled.setRow(6);
  oled.setCol(1);
  oled.print("Teplota 2: ");
  oled.print(soilTemperature2);
  oled.clearToEOL ();

  oled.setRow(7);
  oled.setCol(1);
  oled.print("Vlh. pody 2: ");
  oled.print(soilHumidity2);
  oled.clearToEOL ();


  if (millis() - lastBtnPress > sleepAfter) {
    putToSleep();
  } else {
    delay(100);
  }
}


void wakeUp() {
  if (sleeping) {
    noInterrupts();
    sleeping = false;
    sleep_disable();
    power_all_enable();
    ADCSRA |= (1 << ADEN); // wake up ADC
    pinMode(ANALOG_SENSOR_CONTROL, OUTPUT);
    digitalWrite(ANALOG_SENSOR_CONTROL, LOW);
    delay(20);
    tempSensors.begin();
    rtc.begin();
    oled.begin(&Adafruit128x64, I2C_OLED_ADDRESS);
    oled.setFont(Adafruit5x7);
    oled.clear();
    interrupts();
  }
}

void putToSleep() {
  noInterrupts();
  digitalWrite(ANALOG_SENSOR_CONTROL, HIGH); // turn of power to analog capacitive moisture sensors v1.2 by PNP 
  oled.ssd1306WriteCmd(0xAE); // turn off oled
  set_sleep_mode(SLEEP_MODE_PWR_DOWN); // set powerdown state for ATmega
  ADCSRA = 0; // put ADC to sleep, save around 0.250mA
  power_all_disable(); // put everything other to sleep
  sleep_enable();
  sleeping = true;
  interrupts();
  sleep_cpu(); // When sleeping current goes down to 0.035mA
  lastButton = NO_BTN; // after waking up by any button don't do action assignet to button
}

My advice would be to write a sketch that reproduces the problem with the absolute minimum amount of code. Right now your sketch has a lot of complexity that makes the troubleshooting process unnecessarily difficult.

The ideal minimal sketch would look like this:

void setup() {
  Serial.begin(9600);
}

void loop() {
  Serial.println(analogRead(A1));
  delay(1000);
}

Likely that will not reproduce the problem, but it sounds like you already know which specific code needs to be added to cause the problem, so add only that code to the sketch above. Does the problem now occur? If so, disconnect all the parts from your Arduino except for the DS18B20 and the moisture sensors. Does the problem still occur?

Hello, thanks for suggestion, I will do it as soon as possible. Probably tomorrow evening.

So it will take time to find minimal configuration to emulate this problem since on arduino with only 4 sensors with simple sketch it works without problem. I will need lot of time to find out where is problematic part but i will add sensors and code in small steps.

Try just adding the float soilTemperature2 = tempSensors.getTempCByIndex(1); (and the necessary supporting code to the simple sketch I posted above. It sounds like you already pinpointed that code as the culprit, but it would be good to make sure there is no interaction with all the other code in your original sketch. When you have undefined behavior happening (not that I'm saying your problem is necessarily caused by UB), sometimes changing a random bit of code can cause/fix a problem even though that bit of code has nothing to do with the actual bug.

 char actual_time[16];
  sprintf(actual_time, "%02d:%02d %02d.%02d.%04d", now.hour(), now.minute(), now.date(), now.month(), now.year());

Forgot the null terminator and overran your array.

Anytime you see something where changing some seemingly innocuous line of code totally screws with some other seemingly completely unrelated piece of code, look for buffer overruns. You've got something stepping on the wrong spot in memory.

 if (sleeping) {
    noInterrupts();
    sleeping = false;
    sleep_disable();
    power_all_enable();
    ADCSRA |= (1 << ADEN); // wake up ADC
    pinMode(ANALOG_SENSOR_CONTROL, OUTPUT);
    digitalWrite(ANALOG_SENSOR_CONTROL, LOW);
    delay(20);
    tempSensors.begin();
    rtc.begin();
    oled.begin(&Adafruit128x64, I2C_OLED_ADDRESS);
    oled.setFont(Adafruit5x7);
    oled.clear();
    interrupts();
  }
}

This may also be an issue. delay doesn’t work very well with interrupts off. Best not to use it there. There’s an interrupt that has to run to update the value of millis for delay to work right. I don’t see why the delay or anything after it needs to be no interrupts, so you could turn them back on a little earlier maybe.

pert:
Try just adding the float soilTemperature2 = tempSensors.getTempCByIndex(1); (and the necessary supporting code to the simple sketch I posted above. It sounds like you already pinpointed that code as the culprit, but it would be good to make sure there is no interaction with all the other code in your original sketch. When you have undefined behavior happening (not that I’m saying your problem is necessarily caused by UB), sometimes changing a random bit of code can cause/fix a problem even though that bit of code has nothing to do with the actual bug.

Yes I already tried your suggested code, with just temp and humidity reading and serial output but in this configuration it works fine. So I will need to try components and code one by one until I identify problematic part.

Delta_G: thank you for suggestions, I will look at it.

Problem was fixed by extending actual_time[16] to [17]. It was caused with sprintf writing null terminator to possition outside of my array as Delta_G suggested. Thank you for help. It saved me lot of time because i forget about null terminators because i didn't work with c long time.