Arduino nano keeps resetting - not usb connected

So my friend and I are trying to set up a temperature and humidity controller using Arduino Nano. I wrote the sketch for it using a youtuber's code and the insights gained from various Arduino forum posts, and I designed the circuitry to collect DHT11 sensor information, and turn on logic level MOSFETs to turn on an ultrasonic fogger control board, and a fan to distribute the humidity better. The Arduino Nano also outputs to a solid-state relay to turn on a couple heater cores normally used for 3d printers, mounted inside a large-ish heat sink with a fan to distribute heat. The heater cores and fan are all controlled by the SSR. The majority of the setup is powered by a 12v, 4A dc power supply, and the ultrasonic control board is powered by a 5v, 2A dc power supply. The grounds are all connected.

I have 220 ohm current limiting resistors on all output pins, and 10k ohm pull-down resistors on the 2 MOSFETs and the SSR, so I'm pretty sure I'm not drawing too much current from the output pins, though I haven't measured it yet.

Now that I've described my set up, my problem is that when I power it on, it will run as intended for a few seconds and then the Nano will restart. I have previously been able to run the project long enough to write the temperature and humidity set points into EEPROM, and it turns the controllers on when it starts so it knows what values it's shooting for before turning off, but it doesn't turn off the heater or humidity control once it reaches those either. I'm assuming that has to do with it resetting constantly though.

I'm enclosing a photo of my circuit schematic, and if I'm not mistaken on how to post my sketch code, that as well.

#include <ezButton.h>
#include <dht.h>
#include <LiquidCrystal.h>
#include <EEPROM.h>

// DHT sensor initialize
#define dht_apin A0                                                 // analog pin the sensor is connected to
dht DHT;                                                            // initialize DHT object

// initialize buttons with debounce functionality (mode button can't be EZ for interrupt purposes)
ezButton buttonUp(10);                                              // initialize up button and set to input_pullup
ezButton buttonDn(9);                                               // initialize down button and set to input_pullup

// initialize the lcd library with the numbers of the interface pins
LiquidCrystal lcd(A1,A2,4,5,6,7);                                   // rs = A1, en = A2

// set up variables
float sensorTemp;                                                   // Temp value read from the sensor
float sensorHum;                                                    // Humidity value read from the sensor
float adjsensorTemp;                                                // Temp value used for comparing made by turning the tsp int into a float
float adjsensorHum;                                                 // Humidity value used for comparing made by turning the hsp int into a float
int tsp,hsp,hst;                                                    // create global variables for temp & humidity setpoint and on/off state of fogger
volatile int m;                                                     // create volatile mode variable for use with interrupt
volatile bool modeChange;                                           // create volatile variable to keep track of whether interrupt button has been pressed within each case
unsigned long lastDebounceTime;                                     // the last time the output pin was toggled
unsigned long debounceDelay = 50;                                   // the debounce time; increase if the output flickers
unsigned long startTime;                                            // beginning of time tracking
unsigned long displayTime;                                          // keep track of how long the display has shown a certain screen
unsigned long dhtDelay = 2000;                                      // length of time DHT11 requires between sensor reads

// begin setup phase
void setup() {
  Serial.begin(9600);                                               // initialize serial communications at 9600 bps
  lcd.begin(16, 2);                                                 // initialize lcd operations
  delay(500);                                                       // delay to let system boot
  
  // input pin set up
  pinMode(2,INPUT_PULLUP);                                          // mode button input pin setup
  attachInterrupt(digitalPinToInterrupt(2), toggle, FALLING);       // allow mode button to be pressed at any time during loop to change modes
  buttonUp.setDebounceTime(50);                                     // set up button debounce time
  buttonDn.setDebounceTime(50);                                     // set down button debounce time
  
  // output pin set up
  pinMode(11,OUTPUT);                                               // heater control relay output pin
  pinMode(12,OUTPUT);                                               // humidifier fan control pin
  pinMode(13,OUTPUT);                                               // humidifier control output pin
  digitalWrite(11,LOW);                                             // default heater value to start with heater pin 'off'
  digitalWrite(12,LOW);                                             // default fogger fan value to start with fan pin 'off'
  digitalWrite(13,LOW);                                             // default fogger value to set up pin to be used as an 'activate upon going low, then high again' mode

  // set default variable values
  m = 0;                                                            // start up in normal operational mode
  modeChange = false;                                               // set default modeChange value to avoid excessive eeprom writes
  tsp= 28;                                                          // set default values in case program acts wrong to prevent overheating chamber
  hsp= 80;                                                          // set default values in case program acts wrong to prevent overhumidifying chamber
  lastDebounceTime = 0;                                             // set lastDebounceTime default value
  startTime = 0;                                                    // set startTime default value  
  
  // print out splash screen and give the user a chance to read it
  lcd.print("Temp & Humidity");
  lcd.setCursor(0, 1);
  lcd.print("Controller");
  delay(2000);                                                      // delay to let user read splash screen and to wait long enough for if statement for initial reading of DHT sensor
} // end "Setup()"

// begin main loop
void loop() {
  buttonUp.loop();                                                  // must call this at beginning of loop for up button functionality
  buttonDn.loop();                                                  // must call this at beginning of loop for down button functionality
  displayTime=millis();
  //serial.print("current time: ");
  //serial.print(displayTime);
  //serial.print(" milliseconds since startTime updated.");
  switch (m){
    case 0:                                                       // regular operational mode -- display and control temp&humidity   
      //display current values every second
      if(displayTime - startTime < 1000 && displayTime % 500 == 0){
        //serial.print("current sensor measurement display expected");
        lcd.clear();        
        lcd.print("Temp:");
        lcd.print(sensorTemp);
        lcd.print("C");
        lcd.setCursor(0,1);                                       // sets cursor at bottom left
        lcd.print("Hum:");
        lcd.print(sensorHum);
        lcd.print("%");
      }

      // wait until screen has shown for a second, clear it and show setpoints for a second
      if(displayTime - startTime >= 1000 && displayTime % 500 == 0){                             
        //serial.print("setpoint display expected");
        tsp=EEPROM.read(0);                                         // read temperature setpoint stored in EEPROM
        hsp=EEPROM.read(1);                                         // read humidity setpoint stored in EEPROM
        adjsensorTemp=float(tsp);                                   // make tsp a float for comparing number in EEPROM with value from sensor
        adjsensorHum=float(hsp);                                    // make hsp a float for comparing number in EEPROM with value from sensor
        lcd.clear();                                                // erases screen and resets position to top left
        lcd.print("TSP:");
        lcd.print(tsp);
        lcd.print("C"); 
        lcd.setCursor(0,1);                                         // sets cursor at bottom left
        lcd.print("HSP:");
        lcd.print(hsp);
        lcd.print("%");
      }
      
      // read DHT sensor and prepare values for comparison
      if(displayTime - startTime >= dhtDelay){                      // only allow DHT11 sensor to read once every 2 seconds
        //serial.print("DHT11 read and startTime update expected");
        DHT.read11(dht_apin);                                       // read the analog in value - can only be read every 2 seconds or so
        sensorTemp=DHT.temperature;                                 // get sensor temp
        sensorHum=DHT.humidity;                                     // get sensor humidity
        startTime=displayTime;                                      // reset displayTime to current time
      }

      // low temp only
      if(sensorTemp<(adjsensorTemp-1)&&sensorHum>(adjsensorHum+1)){ 
        //serial.print("low temp only");
        digitalWrite(11,HIGH);                                      // turn on heater
      }

      // low humidity only
      if(sensorTemp>(adjsensorTemp+1)&&sensorHum<(adjsensorHum-1)){ 
        //serial.print("low humidity only");
        if(hst==0){
          //serial.print("humidifier on");
          digitalWrite(12,HIGH);                                    // turn on fan
          digitalWrite(13,HIGH);                                    // turn on humidifier
          delay(50);                                                // delay for ultrasonic control pin to act like button push
          digitalWrite(13,LOW);
          hst = 1;
        }
      }
      
      // both variables low
      if(sensorTemp<(adjsensorTemp-1)&&sensorHum<(adjsensorHum-1)){ 
        //serial.print("both variables low");

        digitalWrite(11,HIGH);                                      // turn on heater
        if(hst==0){ 
          //serial.print("humidifier on");
          digitalWrite(12,HIGH);                                    // turn on fan
          digitalWrite(13,HIGH);                                    // turn on humidifier
          delay(50);
          digitalWrite(13,LOW);
          hst = 1;
        }
      }
      
      // neither variable low
      if(sensorTemp>(adjsensorTemp+1)&&sensorHum>(adjsensorHum+1)) {
        digitalWrite(11,LOW);                                       // turn off heater
        if(hst==1){                                                 // verify humidifier is on before changing
          digitalWrite(12,LOW);                                     // turn off fan
          digitalWrite(13,HIGH);                                    // turn off humidifier
          delay(50);
          digitalWrite(13,LOW);
          hst = 0;
        }
      }
      if(modeChange==true){
        modeChange=false;                                           // reset modeChange so the program doesn't write to eeprom excessively
      }
      break;                                                        // used to return to beginning of loop without moving through rest of cases
    
    // Temp setpoint change menu
    case 1: 
      // temp setpoint up
      if(buttonUp.getState()==0){ 
        tsp++;                                                      // increase temp setpoint
        if(displayTime - startTime >= 100){                         // prevent the screen from clearing so fast it's not readable
          lcd.clear();
          lcd.print("Set Temp Limit:");
          lcd.setCursor(0, 1);
          lcd.print(tsp);
          lcd.print(" C");
          startTime = displayTime;
        }
      }
      
      // temp setpoint down
      if(buttonDn.getState()==0){ 
        tsp--;                                                      // decrease temp setpoint
        if(displayTime - startTime >= 100){                         // prevent the screen from clearing so fast it's not readable
          lcd.clear();
          lcd.print("Set Temp Limit:");
          lcd.setCursor(0, 1);
          lcd.print(tsp);
          lcd.print(" C");
          startTime = displayTime;
        }
      }
      
      // temp limiters
      if(tsp<0){tsp=0;}
      if(tsp>50){tsp=50;}
      
      // save values in eeprom
      if(modeChange==true){
        EEPROM.write(0, tsp);                                       // write new temp setpoint to eeprom register
        modeChange = false;                                           // reset modeChange state to avoid excessive eeprom writes
      }
      break;                                                        // used to return to beginning of loop without moving through rest of cases
    
    // Humidity setpoint change menu
    case 2: 
      // humidity setpoint up
      if(buttonUp.getState()==0){ 
        hsp++;                                                      // increase humidity setpoint
        if(displayTime - startTime >= 100){
          lcd.clear();
          lcd.print("Set Hum Limit:");
          lcd.setCursor(0, 1);
          lcd.print(hsp);
          lcd.print("%");
          startTime = displayTime;
        }
      }
      
      // humidity setpoint down
      if(buttonDn.getState()==0){ 
        hsp--;                                                      // decrease humidity setpoint
        if(displayTime - startTime >= 100){
          lcd.clear();
          lcd.print("Set Hum Limit:");
          lcd.setCursor(0, 1);
          lcd.print(hsp);
          lcd.print("%");
          delay(1000);
          startTime = displayTime;
        }
      }
      
      // humidity limiters
      if(hsp<20){hsp=20;}
      if(hsp>90){hsp=90;}
      
      // save values in eeprom
      if(modeChange==true){
        EEPROM.write(1, hsp); // write new humidity setpoint to eeprom register
        modeChange=false; // reset modeChange state to avoid excessive eeprom writes
      }
      break;
  }
}

// interrupt service routine 'toggle'
void toggle(){
  unsigned long interruptTime = millis();                           // create local variable to compare current time with last debounce time
  if(interruptTime - lastDebounceTime > debounceDelay){
    m++;                                                            // change mode case
    modeChange = true;                                                // change modeChange to true so EEPROM can write new setpoint values after changing from one mode to another
    if(m>2){                                                        // reset mode to normal operation after moving through temp & humidity setpoint change menus
      m=0;
    }
    lastDebounceTime = interruptTime;                               // update last debounce time variable with new value
  }
}

If anyone can help me figure out why this Arduino keeps resetting, I would be so grateful!

Sounds like a power supply or electrical interference problem.

Remove any external equipment connected to the fan and heat outputs, and test the code using LEDs to indicate whether outputs are turned on/off at the correct time.

I'll give it a shot with the LEDs, but I'm more concerned with the arduino resetting than the controls not turning off at the right times.

If you're saying it sounds like it could be a power supply problem, should I include capacitors (one 47uF electrolytic and 0.1uF ceramic) on the power supply inputs to increase stability?

I agree with the power supply theory.

I also noticed your 10K pull-down resistors are all connected incorrectly. They should be connected from the Arduino output pin to ground, rather than the MOSFET gate pin to ground. The way you have them, the 220R and 10K form a voltage divider which results in less than 5V reaching the gate pin. Ok, not much less than 5V, but it could result in the MOSFET being less than fully switched on and generating more heat, and it's so easily fixed by connecting the 10K correctly.

Oh shoot. ok, so connect the pull-down resistors to the other side of the current limiting resistors?

The LED experiment isolates the issues, and helps decide whether it is a power supply problem.

If with LEDs, the Arduino stops resetting, you have a power supply problem.

Please post a complete wiring diagram, and the details on your power supply and the external components: fan, heater, etc.

Yes. It won't fix your resetting problems, but needs fixing.

Are you supplying the Nano from the 5V supply in to the +5V pin, or from the 12V supply into Vin? The diagram seems to indicate at least the 12V feed connected, but possibly even both? 12V into Vin will make the onboard regulator get a bit toasty.

You might check the voltage at the Nano's 5V pin to see if it is sagging.

It's possible the problem is the heat generated in the Nano's 5v voltage regulator because of the large drop from 12V to 5V. The regulator probably has a thermal shutdown feature.

Fair enough. I can definitely try setting it up to turn on and off LEDs.

I'm using a laptop-type 12v, 4a power supply and a 5v, 2a usb wall wart power supply.

I don't have specific details about the heater cores as my friend provided them for the project, but I can try to get details from him.

The humidity fan is a noctua 40mm pc fan meant to run on 12v, drawing (I believe) up to 100ma.

The ultrasonic fogger board and transducer product page can be found here: https://smile.amazon.com/dp/B09MLSLDQK. I replaced the tactile switch on there with a connection with the drain side of the MOSFET that connects it to ground when turned on.

Other than that stuff, I'm not sure what else you would want in a wiring diagram, Jremington. The heater cores are essentially resistors, and those and the fan are connected in parallel to ground from the negative load connection to the SSR, and the positive load connection to the SSR is connected to 12v.

I'm supplying the Nano from the 12v supply into Vin. There's no connection from the separate 5v power supply to the Nano. Should I not use the 12v supply to power the arduino? I'm already planning on not using the 5v pin on the Nano to power anything, since I have the alternate 5v power supply.

Do you have a Flyback diode on the fan? Without that, maybe the negative voltage spike generated when the fan is switched off could be causing the Nano to reset. And damaging it too.

I don't, but I assumed a noctua pc fan would have stuff like that in it's controlling circuitry. I'll add it to the list of things to try out today.

Measure the heater resistance when cold, using your multimeter, and calculate the startup current.

For reliability, the heater power supply needs to be rated for at least 50% higher current. 2X is recommended.

Although 12V is the nominal maximum, 7V is a significant voltage drop and that power has to go somewhere so gets dissipated in the form of heat in the on-board regulator. The regulator has no heatsink and the Nano board is pretty small, so the generated heat could potentially affect nearby components. None of this is going to help matters.

You might consider powering the board from the 5V supply, assuming it is regulated. Another option might be to use a DC-to-DC converter to reduce the DC voltage to 5V. This is a much more efficient way to reduce the DC voltage and does not generate a lot of heat. You can get them relatively cheaply on eBay.

Maybe try the LED test first and see what results from that. One step at a time.

Never had the need to directly or indirectly ground the unused data pins on the 16x2 as you have done.

Some libraries may not like that.

I set up the Arduino, DHT11 and LCD on a breadboard with the push buttons and some LEDs instead of the controlling mechanisms. I powered everything by one of the 5v, 2a USB wall warts I have, and it ran without resetting at all. Everything that required 5v got it straight from the wall wart. I guess I had thought that giving the Arduino a higher voltage would allow it to draw power from the 5v regulator without being unreliable. Definitely the wrong assumption.

I didn't check to see if trying to power the LCD and DHT11 from the 5v pin on the Arduino would be ok, but if it worked this way, I'm content to not tempt fate by trying to draw any current from that regulator pin.

I still have to set up a board with the new power scheme and the actual controlling mechanisms (MOSFETs and SSR) and see if it still resets with those connected, but I'm happy with how today went. Making progress!

The Arduino has a linear voltage regulator, which means that the higher the input voltage, the more power the regulator has to dissipate as heat, possibly leading to thermal overloading and shutdown of the voltage regulator. With 12V on input, you are strictly limited as to the amount of current you can draw from the 5V output. 7V is much better.

It is much more likely that the reset problem is due to the heater and fan. Use a completely separate power supply for those, and connect all the grounds.

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