Window Positioner w/ DHT22 interrupts stepper

I've been struggling with code. Project works, but there are two issues I would like to sort out. First one is that whenever I read temp and humid from DHT22 (once in 3s) it interrupts stepper if it is in motion. If I disable reading of temp and humid, then lcd interrups stepper but it isn't noticeable which is ok for me.
Second issue is that if DHT22 reported temp is within range of 22.70-23.30 celsius (setTemp 23 +-0.3) and I press switch "opened" stepper starts moving to one direction and if press switch "closed" it moves to other direction, but it shouldn't move while in that state no matter which button is pressed.
This project is for regulating room temperature with window positioning (how wide it is opened or closed). Buttons go HIGH when pressed. If switch "closed" isn't pressed and reported temp is 0.3 celsius lower than setTemp, window starts closing. If switch "opened" isn't pressed and reported temp is 0.3 celsius higher than setTemp, window starts opening.

I'm really beginner at coding even tho I started coding atmel chips back in mid 2000, still a n00b :slight_smile:

I implemented part of a code for controlling stepper with millis() from here A simple sketch to drive Stepper Motor 28BYJ-48 - Exhibition / Gallery - Arduino Forum

My code:

#include <Stepper.h>
#include "DHT.h"
#include "LiquidCrystal.h"

#define DHTPIN 3
#define DHTTYPE DHT22

DHT dht(DHTPIN, DHTTYPE);
LiquidCrystal lcd(1, 2, 4, 5, 6, 7);

const int Opened = 12;
const int Closed = 13;
const int stepsPerRevolution = 2048;

unsigned long goTime;
unsigned long goTime2;

int OpenedState = 0 ;
int ClosedState = 0 ;
int interval = 96;  // initial delay for stepper motor rotation
int nextTime = 3000;

float Hotter;
float Colder;
float SetTemp = 23.00;
float t;
float h;

Stepper myStepper(stepsPerRevolution, 8, 10, 9, 11);

void setup() {
  
  dht.begin();
  lcd.begin(16, 2);
  pinMode(Opened, INPUT_PULLUP);
  pinMode(Closed, INPUT_PULLUP);
  goTime = millis();
  goTime2 = millis();
  myStepper.setSpeed( 0xEFFFFFFFL );  // Just to set the step_delay value to 0, to bypass the delay routine in the Stepper class.
}
/////////////////////////////////////////////////////
void CheckTemperature() {
  // Read temperature as Celsius (the default)
  t = dht.readTemperature();
  
  // Reading temperature or humidity takes about 250 milliseconds!
  // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
  h = dht.readHumidity();
  
  lcd.setCursor(0, 0);
  lcd.print("T: ");
  lcd.print(t);
  lcd.print(" C");
  lcd.setCursor(0, 1);
  lcd.print("H: ");
  lcd.print(h);
  lcd.print(" %");
  lcd.setCursor(10, 1);
  lcd.print(goTime);

  Hotter = t + 0.30;
  Colder = t - 0.30;
  
  goTime2 += nextTime; 
}

/////////////////////////////////////////////
void loop() {

  OpenedState = digitalRead(Opened) ;
  ClosedState = digitalRead(Closed) ;
  int stepsPerRevolution = 0;
  
  if (millis() >= goTime2)
    CheckTemperature();
  
  if (OpenedState == LOW && Hotter >= SetTemp)
    stepsPerRevolution--;
    

  if (ClosedState == LOW && Colder <= SetTemp)
    stepsPerRevolution++;


  if ( stepsPerRevolution ) {

    myStepper.step(stepsPerRevolution);
    interval /= 1.5;
    if(interval < 2)
    interval = 2;
    delay(interval);
    goTime = millis();
  }

  else {
    interval = 96;
    digitalWrite(8,LOW);
    digitalWrite(9,LOW);
    digitalWrite(10,LOW);
    digitalWrite(11,LOW);
  }    
}

Breadboard:

Solved second issue by simplifying code, first issue still exists.

#include <Stepper.h>
#include "DHT.h"
#include "LiquidCrystal.h"

#define DHTPIN 3
#define DHTTYPE DHT22

DHT dht(DHTPIN, DHTTYPE);
LiquidCrystal lcd(1, 2, 4, 5, 6, 7);

const int Opened = 12;
const int Closed = 13;
const int stepsPerRevolution = 2048;

unsigned long goTime;
unsigned long goTime2;

int OpenedState = 0 ;
int ClosedState = 0 ;
int interval = 96;  // initial delay for stepper motor rotation
int nextTime = 3000;

float SetTemp = 23.50;
float t;
float h;

Stepper myStepper(stepsPerRevolution, 8, 10, 9, 11);

void setup() {
  
  dht.begin();
  lcd.begin(16, 2);
  pinMode(Opened, INPUT_PULLUP);
  pinMode(Closed, INPUT_PULLUP);
  goTime = millis();
  goTime2 = millis();
  
  myStepper.setSpeed( 0xEFFFFFFFL );  // Just to set the step_delay value to 0, to bypass the delay routine in the Stepper class.
}
/////////////////////////////////////////////////////
void CheckTemperature() {
  // Read temperature as Celsius (the default)
  t = dht.readTemperature();
  
  // Reading temperature or humidity takes about 250 milliseconds!
  // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
  h = dht.readHumidity();
  
  lcd.setCursor(0, 0);
  lcd.print("T:");
  lcd.print(t);
  lcd.print("C");
  lcd.setCursor(0, 1);
  lcd.print("H:");
  lcd.print(h);
  lcd.print("%");
  
  
  if (OpenedState == LOW && t > SetTemp + 0.20) {
    lcd.setCursor(9,1);
    lcd.print("Opening");
  }
  else if (ClosedState == LOW && t < SetTemp - 0.20) {
    lcd.setCursor(9,1);
    lcd.print("Closing");
  }
 else {
    lcd.setCursor(9,1);
    lcd.print("Normal ");
 }
  
  goTime2 += nextTime; 
}

/////////////////////////////////////////////
void loop() {

  OpenedState = digitalRead(Opened) ;
  ClosedState = digitalRead(Closed) ;
  int stepsPerRevolution = 0;
  

  if (millis() >= goTime2)
    CheckTemperature();
  
  if (OpenedState == LOW && t > SetTemp + 0.20)
    stepsPerRevolution--;
    

  if (ClosedState == LOW && t < SetTemp - 0.20)
    stepsPerRevolution++;
    

  if ( stepsPerRevolution ) {

    myStepper.step(stepsPerRevolution);
    interval /= 1.5;
    if(interval < 2)
    interval = 2;
    delay(interval);
    goTime = millis();
  }
  

  else {
    interval = 96;
    digitalWrite(8,LOW);
    digitalWrite(9,LOW);
    digitalWrite(10,LOW);
    digitalWrite(11,LOW);
  }    
}

This is what I understand from your project:

The "opened" and "closed" switches are limit switches for the window movement, i.e. the switches are pressed by the window?
The switches are active LOW.
Open window decreases the temperature - always?

Right?

DrDiettrich:
This is what I understand from your project:

The "opened" and "closed" switches are limit switches for the window movement, i.e. the switches are pressed by the window?
The switches are active LOW.
Open window decreases the temperature - always?

Right?

Yes, they are limit switches.
Sorry can't understand "The switches are active LOW." But when window reaches full open or closed position it presses switch and goes HIGH. If I disconnect switch from Arduino, Arduino sees that it is HIGH. Connected like that because of safety, in case someone cuts switch wires.
Yes, open window always decreases temperature, because I have 9 GPU's mining in bedroom.

The switches are normally closed?

So what exactly is your question?

DrDiettrich:
The switches are normally closed?

So what exactly is your question?

My question is - why "void CheckTemperature()" interrupts stepper when it spins?

This code seems to take so long, that the stepper cannot be served fast enough. If the sensor reading methods are blocking the controller for a long time, you should search for faster or non-blocking methods. Also get rid of delay(), it only will hinder other activities, like sensor data acquisition.

You also can reduce the stepper speed so much, that it will be possible to measure temperature and humidity between two steps.

So I solved problem by changing code with switch() case and other DHT sensor library, but here comes the other. I can't bend my head around to exit switch (steps) case to go to "default" when these both of these "if" statements are false. When one of this "if" statements goes from true to false it leaves switch (steps) in last used case which means current is applied to stepper and I want it to go LOW on all 4 pins. Pls help, stepper getting hot doing nothing.

2 if statements that uses switch (steps) cases:

if (OpenedState == LOW && temperature > SetTemp + 0.10) {
    steps++;
      if (steps >=8)
        steps=0;
    }

    if (ClosedState == LOW && temperature < SetTemp - 0.10) {
     steps--;
      if (steps <= 0)
        steps=8; 
    }

Whole code:

#include <dht_nonblocking.h>
#define DHT_SENSOR_TYPE DHT_TYPE_22

static const int DHT_SENSOR_PIN = 3;
DHT_nonblocking dht_sensor( DHT_SENSOR_PIN, DHT_SENSOR_TYPE );

#include "LiquidCrystal.h"
LiquidCrystal lcd(1, 2, 4, 5, 6, 7);

#include <AnalogMultiButton.h>
const int BUTTONS_PIN = A0;
const int BUTTONS_TOTAL = 5;
const int BUTTONS_VALUES[BUTTONS_TOTAL] = {0, 289, 452, 555, 627};
const int BUTTON_CLOSE = 0;
const int BUTTON_INCREASE = 1;
const int BUTTON_SET = 2;
const int BUTTON_DECREASE = 3;
const int BUTTON_OPEN = 4;

const int Opened = 12;
const int Closed = 13;

int OpenedState = 0 ;
int ClosedState = 0 ;
int Pin1 = 8; 
int Pin2 = 9; 
int Pin3 = 10; 
int Pin4 = 11; 
int steps = 0;
int interval = 1;
unsigned long previousMillis = 0;
float SetTemp = 23.50;

AnalogMultiButton buttons(BUTTONS_PIN, BUTTONS_TOTAL, BUTTONS_VALUES);

void setup()
{
  pinMode(Pin1, OUTPUT);  
  pinMode(Pin2, OUTPUT);  
  pinMode(Pin3, OUTPUT);  
  pinMode(Pin4, OUTPUT);  
  pinMode(Opened, INPUT_PULLUP);
  pinMode(Closed, INPUT_PULLUP);
  lcd.begin(16, 2); 
}
/*
 * Poll for a measurement, keeping the state machine alive.  Returns
 * true if a measurement is available.
 */
static bool measure_environment( float *temperature, float *humidity )
{
  static unsigned long measurement_timestamp = millis( );

  /* Measure once every four seconds. */
  if( millis( ) - measurement_timestamp > 4000ul )
  {
    if( dht_sensor.measure( temperature, humidity ) == true )
    {
      measurement_timestamp = millis( );
      return( true );
    }
  }

  return( false );
}

/*
 * Main program loop.
 */
void loop() {
  
  unsigned long currentMillis = millis();  
  float temperature;
  float humidity;
  OpenedState = digitalRead(Opened) ;
  ClosedState = digitalRead(Closed) ;
  buttons.update();

if (buttons.onPress(BUTTON_CLOSE))  {
      SetTemp = 40.00;
      lcd.clear();
      lcd.setCursor(5,0);
      lcd.print("Closing");
      interval = 1;
  }

  if (buttons.onPress(BUTTON_INCREASE)) {
      SetTemp = SetTemp + 0.10;
      lcd.clear();
      lcd.setCursor(6,0);
      lcd.print(SetTemp);
  }
  
  if (buttons.onPress(BUTTON_SET))  {
      SetTemp = 23.50;
      lcd.clear();
      lcd.setCursor(4,0);
      lcd.print("Temp Set");
      lcd.setCursor(6,1);
      lcd.print(SetTemp);
      interval = 25;
  }
  
  if (buttons.onPress(BUTTON_DECREASE)) {
      SetTemp = SetTemp - 0.10;
      lcd.clear();
      lcd.setCursor(6,0);
      lcd.print(SetTemp);
  }
  
  if (buttons.onPress(BUTTON_OPEN)) {
      SetTemp = 10.00;
      lcd.clear();
      lcd.setCursor(5,0);
      lcd.print("Opening");
      interval = 1;
  }

if (currentMillis - previousMillis > interval) {
    previousMillis = currentMillis;
    
    if (OpenedState == LOW && temperature > SetTemp + 0.10) {
    steps++;
      if (steps >=8)
        steps=0;
    }

    if (ClosedState == LOW && temperature < SetTemp - 0.10) {
     steps--;
      if (steps <= 0)
        steps=8; 
    }
    
      switch(steps){ 
       case 0: 
        digitalWrite(Pin1, LOW);  
        digitalWrite(Pin2, LOW); 
        digitalWrite(Pin3, LOW); 
        digitalWrite(Pin4, HIGH); 
        break;  
       case 1: 
        digitalWrite(Pin1, LOW);  
        digitalWrite(Pin2, LOW); 
        digitalWrite(Pin3, HIGH); 
        digitalWrite(Pin4, HIGH); 
        break;  
       case 2: 
        digitalWrite(Pin1, LOW);  
        digitalWrite(Pin2, LOW); 
        digitalWrite(Pin3, HIGH); 
        digitalWrite(Pin4, LOW); 
        break;  
       case 3: 
        digitalWrite(Pin1, LOW);  
        digitalWrite(Pin2, HIGH); 
        digitalWrite(Pin3, HIGH); 
        digitalWrite(Pin4, LOW); 
        break;  
       case 4: 
        digitalWrite(Pin1, LOW);  
        digitalWrite(Pin2, HIGH); 
        digitalWrite(Pin3, LOW); 
        digitalWrite(Pin4, LOW); 
        break;  
       case 5: 
        digitalWrite(Pin1, HIGH);  
        digitalWrite(Pin2, HIGH); 
        digitalWrite(Pin3, LOW); 
        digitalWrite(Pin4, LOW); 
        break;  
       case 6: 
        digitalWrite(Pin1, HIGH);  
        digitalWrite(Pin2, LOW); 
        digitalWrite(Pin3, LOW); 
        digitalWrite(Pin4, LOW); 
        break;  
       case 7: 
        digitalWrite(Pin1, HIGH);  
        digitalWrite(Pin2, LOW); 
        digitalWrite(Pin3, LOW); 
        digitalWrite(Pin4, HIGH); 
        break;  
       default: 
        digitalWrite(Pin1, LOW);  
        digitalWrite(Pin2, LOW); 
        digitalWrite(Pin3, LOW); 
        digitalWrite(Pin4, LOW); 
        break;   
    } 
  } 
  
  /* Measure temperature and humidity.  If the functions returns
     true, then a measurement is available. */
  if( measure_environment( &temperature, &humidity ) == true )
  {
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("T:");
    lcd.print(temperature);
    lcd.print("C");
    lcd.setCursor(0, 1);
    lcd.print("H:");
    lcd.print(humidity);
    lcd.print("%");
    lcd.setCursor(9, 0);
    lcd.print("S:");
    lcd.print(SetTemp);  

       if (OpenedState == LOW && temperature > SetTemp + 0.10) {
          lcd.setCursor(9,1);
          lcd.print("Opening");
       }
       else if (ClosedState == LOW && temperature < SetTemp - 0.10) {
          lcd.setCursor(9,1);
          lcd.print("Closing");
       }
       else {
       lcd.setCursor(9,1);
       lcd.print("Normal ");
       }
  }
  
  
}

It's normal stepper operation to continue powering when the motor halts, else the position may change. If you want to reduce the power, detect the idle (not moving) state and act as appropriate. Some driver boards allow to reduce current.

Solved. Added after void loop() int state = 0 and IF that checks if state == 0, if it's 0 then stepper goes off. When stepper is turning state = 1.

int state = 0;
 
    if (currentMillis - previousMillis > interval) {
        previousMillis = currentMillis;
   
        if (OpenedState == LOW && temperature > SetTemp + 0.10) {
            state = 1;
            steps++;
                if (steps >= 8)
                    steps = 0;
        }
 
        if (ClosedState == LOW && temperature < SetTemp - 0.10) {
            state = 1;
            steps--;
                if (steps <= 0)
                    steps = 8;
        }
   
        switch(steps){
            case 0:
                digitalWrite(Pin1, LOW);  
                digitalWrite(Pin2, LOW);
                digitalWrite(Pin3, LOW);
                digitalWrite(Pin4, HIGH);
                break;  
            case 1:
                digitalWrite(Pin1, LOW);  
                digitalWrite(Pin2, LOW);
                digitalWrite(Pin3, HIGH);
                digitalWrite(Pin4, HIGH);
                break;  
            case 2:
                digitalWrite(Pin1, LOW);  
                digitalWrite(Pin2, LOW);
                digitalWrite(Pin3, HIGH);
                digitalWrite(Pin4, LOW);
                break;  
            case 3:
                digitalWrite(Pin1, LOW);  
                digitalWrite(Pin2, HIGH);
                digitalWrite(Pin3, HIGH);
                digitalWrite(Pin4, LOW);
                break;  
            case 4:
                digitalWrite(Pin1, LOW);  
                digitalWrite(Pin2, HIGH);
                digitalWrite(Pin3, LOW);
                digitalWrite(Pin4, LOW);
                break;  
            case 5:
                digitalWrite(Pin1, HIGH);  
                digitalWrite(Pin2, HIGH);
                digitalWrite(Pin3, LOW);
                digitalWrite(Pin4, LOW);
                break;  
            case 6:
                digitalWrite(Pin1, HIGH);  
                digitalWrite(Pin2, LOW);
                digitalWrite(Pin3, LOW);
                digitalWrite(Pin4, LOW);
                break;  
            case 7:
                digitalWrite(Pin1, HIGH);  
                digitalWrite(Pin2, LOW);
                digitalWrite(Pin3, LOW);
                digitalWrite(Pin4, HIGH);
                break;  
            default:
                digitalWrite(Pin1, LOW);  
                digitalWrite(Pin2, LOW);
                digitalWrite(Pin3, LOW);
                digitalWrite(Pin4, LOW);
                break;  
        }
        if (state == 0) {
            steps = 8;
        }
    }