Strange programming problem

I have a sketch that uses the DHT11 sensor (humidity & temperature) which was working until I added a second sensor read statement to void Loop (for testing, "tt" is not referenced elsewhere in the sketch).

int tt = dht.readTemperature();

Adding that single extra statement causes the sketch to freeze on a Uno. I attempted to debug it by running it on a Zero but the sketch then works (doesn't freeze). I wrote a simple test program containing little but two similar statements and it works on the both processors.

Before I try adding a bunch of Serial.prints for an attempt to debug on the Uno, I though I would ask here if anyone might have an idea what is wrong here. It seems odd indeed that adding that simple statement would have the unwanted result and, only on the Uno processor. BTW, same result is seen with IDE 1.8.

Obviously, no clearly wrong content in the code you !didn't post!.

Look, you've been here how long? You know the problem is generally in the greater context, not the snippet someone posts.

Please post your code. If it's huge, try producing a small element that exhibits the same issue.
Thanks.

1 Like

Problems like that tend to be related to writing outside the bounds of an array, or just running out of ram.

Does the DHT library allow two? Each object needs a pin assigned.

I didn't post the code for two reasons:

It's almost 300 lines and, I don't really see what "the greater context" would have to do with this type of problem (unless as david 2018 mentions with an out of bounds array or insufficient ram, both of which don't seem to be applicable in this case).

As for a "small element" that may exhibit the same issue approach, I've already spent hours futtzing around with this thing trying to do just that and thought I could possible save a lot of additional time if anyone was willing to possibly provide a simple explanation. Or not....

ETA: FWIW, the sketch uses 69% of "program storage space" and 30% of dynamic memory on the Uno.

Do you mean two sensors? In my case, there is only the one (DHT11) sensor and two separate statements trying to read the same sensor.

I'll say it more clearly. There is nothing wrong with this statement. Therefore, the problem must lie in the greater context. However, you know best, so I'm out. Have a nice time.

1 Like

Short program, and the error is in the code you did not post.

1 Like

No way to tell actual memory usage from that. The program storage space is no problem, but an OLED display that allocates 1024 bytes of ram at run-time, SD card usage that allocates buffers at runtime, extensive use of String, etc, can eat up ram quickly.

Since nothing in the statement you are adding should cause a problem, the general assumption is that the additional function call is altering the code enough to re-arrange something in memory. This is resulting in a previously existing problem now becoming noticeable, while in the previous code it was occurring in a way that was not noticeable.

1 Like

OK, now that is helpful - thank you. As it happens, the setup does include an OLED display.

I have just tried removing a section of code from the sketch and the problem seems to have disappeared so, considering that it runs unaltered on a Zero, maybe RAM is the issue. Is there any way of telling how much ram is used at runtime.?

FWIW, the sketch follows. The offending statement is the first in the void loop (around line # 70).

#include <Servo.h>   //Servo
#include <RTClib.h>  //RT Clock
#include "DHT.h"     // Temperature & Humidity sensor

#include <Adafruit_SSD1306.h>  //OLED display
#include <Adafruit_GFX.h>
#include <Fonts/FreeMono12pt7b.h>

#define SCREEN_WIDTH 128  // OLED display width, in pixels
#define SCREEN_HEIGHT 64  // OLED display height, in pixels

#define DHTPIN 10      // Digital pin connected to the DHT sensor
#define DHTTYPE DHT11  // DHT 11 type of temperature & humidity sensor

DHT dht(DHTPIN, DHTTYPE);  // Initialize DHT sensor

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

Servo myservo;  // Create servo object to control a servo

RTC_DS3231 rtc;  //Initialize RTC

int lowPos = 60;  //Servo position (in degrees) for low heat setting
int hiPos = 150;  //for high (180 degrees is max rotation of servo)
int pos;          //Current servo position - to initiate at 0 position (elec blnk controller at full off)

unsigned long currentMillis = millis();  //Set up timeout for manual increase/decrease of servo position
unsigned long previousMillis;
unsigned long timeOut = 3000;  //Timeout = 3000 milliseconds


void setup() {

  pinMode(3, INPUT_PULLUP);   //Button push for time adjust hour or minute decrease or, decrease servo position
  pinMode(4, INPUT_PULLUP);   //hour or minute increase or, increase servo position
  pinMode(12, INPUT_PULLUP);  //Button to trigger or release hour/minute adjust (button on proto board)

  pinMode(A3, INPUT);  //Input for photocell (measuring ambient light level)

  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  // initialize with the I2C addr
  display.setTextColor(WHITE, BLACK);
  dht.begin();  //Initiate sensor

  myservo.attach(9);  // attaches the servo on pin 9 to the servo object
  myservo.write(0);   //Initiate servo at 0 position (elec blnk controller at full off)

  // SETUP RTC MODULE
  if (!rtc.begin()) {
    Serial.println("Couldn't find RTC");
    Serial.flush();
    while (1)
      ;
  }

  //Manually sets the RTC with an explicit date & time.
  //rtc.adjust(DateTime(2024, 2, 21, 0, 0, 0));

  Serial.begin(9600);
}

void setContrast(Adafruit_SSD1306* display, uint8_t contrast) {  //Code enables OLED brightness adjustment
  display->ssd1306_command(SSD1306_SETCONTRAST);
  display->ssd1306_command(contrast);
}

void loop() {

  int tt = dht.readTemperature();

  //int servoHigh = map(t, 25, 19, 0, hiPos);
  //int servoLow = map(t, 25, 19, 0, lowPos);

  DateTime now = rtc.now();  //Get current time
  int hrs = now.hour();
  int mins = now.minute();
  int secs = now.second();

  //Set time hours & minutes to wanted values
  //Set Hours

  if (digitalRead(12) == 0) {       //Hour/minute adjust button pushed?
    delay(500);                     //Wait ime for button to be released
    while (digitalRead(12) == 1) {  //Stay in hour adjust loop until adjust button again pressed

      display.clearDisplay();
      display.setCursor(0, 50);
      display.print("Hr");
      display.setCursor(70, 50);
      display.print(hrs);
      display.display();
      if (digitalRead(3) == 0) {  //Decrease hours?
        delay(300);
        if (digitalRead(3) == 0) {
          hrs = hrs - 1;
          if (hrs < 0) {
            hrs = 24;
          }
        }
      }
      if (digitalRead(4) == 0) {  //Increase hours?
        delay(300);
        if (digitalRead(4) == 0) {
          hrs = hrs + 1;
          if (hrs > 24) {
            hrs = 1;
          }
        }
      }
    }
    delay(500);  //Wait again for adjust button to be released

    //Set minutes

    delay(500);                     //Wait ime for button to be released
    while (digitalRead(12) == 1) {  //Stay in hour adjust loop until adjust button again pressed

      display.clearDisplay();
      display.setCursor(0, 50);
      display.print("Mn");
      display.setCursor(70, 50);
      display.print(mins);
      display.display();
      if (digitalRead(3) == 0) {
        delay(300);
        if (digitalRead(3) == 0) {
          mins = mins - 1;
          if (mins < 0) {
            mins = 59;
          }
        }
      }
      if (digitalRead(4) == 0) {
        delay(300);
        if (digitalRead(4) == 0) {
          mins = mins + 1;
          if (mins > 59) {
            mins = 0;
          }
        }
      }
    }
    delay(1000);  //Wait agian for finished time adjust button release

    rtc.adjust(DateTime(2024, 2, 21, hrs, mins, secs));  //Finished adjustments - set clock to new time
    //(only hour & minute values needed).
  }

  // Read temperature as Celsius and Humidity
  int t = dht.readTemperature();
  t = int(t * 0.88);  //Emperical correction factor
  int h = dht.readHumidity();
  h = h * 1.01;  //Humidity

  //Serial.println(t);
  //Serial.println(h);

  //Serial.println((String) "Hours = " + hrs + "  Minutes =  " + mins + "  Seconds =  " + secs);

  //Turn controller to high at specified time?

  if (now.hour() == 22 && now.minute() == 30) {
    pos = hiPos;
    myservo.write(pos);  // send servo to position in variable 'pos'
  }

  //Turn controller to low at specified time?

  if (now.hour() == 23 && now.minute() == 0) {
    pos = lowPos;
    myservo.write(pos);  // send servo to position in variable 'pos'
  }

  if (now.hour() == 23 && now.minute() == 1) {  //Repeat to make sure
    pos = lowPos;
    myservo.write(pos);  // send servo to position in variable 'pos'
  }

  //Turn controller to off position?

  if (now.hour() == 9 && now.minute() == 0) {
    myservo.write(0);  // servo to 0 (full off)
  }

  if (now.hour() == 9 && now.minute() == 1) {  //Repeat to make sure it goes to off
    myservo.write(0);                          // servo to 0 (full off)
  }

  //Use 2 buttons (wired to D3 & D4) to increase or decrease servo setting

  if (digitalRead(3) == 0) {
    previousMillis = millis();
    while (millis() - previousMillis <= timeOut) {  //Timed out?
      if (digitalRead(3) == 0) {
        pos = pos - 2;
        if (pos < 0) {
          pos = 0;
        }
        myservo.write(pos);  //Decrease setting a bit

        display.clearDisplay();  //Show it briefly on screen
        display.setCursor(40, 50);
        display.print(pos);
        display.display();
        delay(200);
        previousMillis = millis();
      }
    }
  }

  if (digitalRead(4) == 0) {
    previousMillis = millis();
    while (millis() - previousMillis <= timeOut) {  //Timed out?
      if (digitalRead(4) == 0) {
        pos = pos + 2;
        if (pos > 180) {  //180 degrees is the max the servo can turn
          pos = 180;
        }
        myservo.write(pos);  //Increase setting a bit

        display.clearDisplay();  //Show it briefly on screen
        display.setCursor(40, 50);
        display.print(pos);
        display.display();
        delay(200);
        previousMillis = millis();
      }
    }
  }

  //delay(100);  //Wait so decrease/increase settings goes slowly

  display.clearDisplay();
  display.setFont(&FreeMono12pt7b);

  //Display temperature & humidity every 10 seconds

  if (secs % 10 == 0) {

    display.setTextSize(1);
    display.setCursor(0, 15);
    display.print("Temp  Hum");
    display.setTextSize(2);
    display.setCursor(0, 60);
    display.print(t);
    display.setCursor(76, 60);
    display.print(h);

  }

  else {  //Display time
    display.setTextSize(2);

    if (hrs > 12) {  //Convert time from MST 24 hr clock to MST 12 hr clock
      hrs = hrs - 12;
    }
    if (hrs == 0) {
      hrs = 1;
    }
    if (hrs <= 9) {  //For formatting o/p
      display.setCursor(0, 50);
      display.print(" ");
      display.setCursor(28, 50);
    } else {
      display.setCursor(0, 50);
    }
    display.print(hrs);

    if (secs % 2 == 0) {
      display.print(":");
    } else {
      display.print(" ");
    }

    if (mins <= 9) {  //Display a leading "0"
      display.setCursor(76, 50);
      display.print("0");
      display.setCursor(104, 50);
    } else {
      display.setCursor(76, 50);
    }
    display.print(mins);
  }

  display.display();
  setContrast(&display, 1);  //Turn down display brighness to lowest level (too bright at night & OK during day)
}

Uno - 32k/2k
Zero - 256k/32k
Couldn't matter, could it? Reduced the code footprint, works both places. I think you were ignoring the evidence in front of you.

My browser (the we site) only showed nine posts.

You go to the doctor and demand the doctor tell you why you are sick without tests or information. Wow.

Check the output of the memory report published by the upload operation, and then add to the SRAM total the 1024 bytes (half of the Uno SRAM) that will be instantly consumed by this statement:

display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  // initialize with the I2C addr
1 Like

The sketch seems to run here, but I am using a DHT22 instead of a DHT11. The code will freeze after about a few seconds if I un-comment the line that prints the time to the serial monitor, an indication of memory being used up by the String variables. Changing that line to a sequence of Serial.print() statements, with the F() macro used for the text, does not freeze up.

I'm not familiar with how much memory is needed by the Servo or DHT libraries, or if they allocation any memory at run-time.

1 Like

Your topic does not indicate a problem with the IDE and hence has been moved.

Thank you again. That seems to be the issue alright.

I ran into a somewhat similar issue with another sketch that crashed on a Uno but ran on a Zero. Problem there turned out to be too large a string array so I resolved it by using the SSD1306Ascii Include for the OLED which provides characters only and much lower ram requirement than the Adafruit version. Guess I will have to do the same here (but all the OLED statements will have to be modified).

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