Problem with power supply/code

I'm making an aquarium chiller using a Peltier device, and a water pump, which both run on 12VDC, I have an Arduino Nano and a DS18B20 temp sensor, simple push buttons, and a 1.9 i2C OLED. I have a 12V 15A 180W wall power supply. The peltier device and its fans are connected to an optoisolator relay, that is controlled by the nano on pin d4. The pump is just connected to the 12v directly. The OLED and Push buttons are on a separate shield brd. To power the Nano I have a 7805 circuit that connects to the +5v pin.

here's the code for the project:

#include <Wire.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

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

const int relayPin = 4; // Output pin for D4 relay
const int hysteresis = 1; // Hysteresis value in degrees Fahrenheit
bool relayState = false; // Variable to keep track of D4 relay state
int set_temp = 60;
int temp;

// Set up I2C OLED screen
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
OneWire oneWire(A1); // Pin A1
DallasTemperature sensors(&oneWire);


void printText(const char* text, uint8_t size, uint8_t x, uint8_t y) {
  display.setTextSize(size);
  display.setTextColor(WHITE);
  display.setCursor(x, y);
  display.println(text);
  display.display();
}

void getUP() {
  if (set_temp < 70) {
    set_temp++;
  }
  else {}
  display.fillRect(10, 40, 48, 24, BLACK);
  printText(String(set_temp).c_str(), 2, 10, 40);
  display.display(); // Display the text on the screen
}

void getDWN() {
  if (set_temp > 45) {
    set_temp--;
  }
  else {}
  display.fillRect(10, 40, 48, 24, BLACK);
  printText(String(set_temp).c_str(), 2, 10, 40);
  display.display(); // Display the text on the screen
}

void getTemp() {
  sensors.requestTemperatures(); // Request temperature from sensor
  temp = sensors.getTempFByIndex(0); // Get temperature value in Fahrenheit
  display.fillRect(80, 40, 48, 24, BLACK);
  printText(String(temp).c_str(), 2, 80, 40);
  display.display(); // Display the text on the screen
}

void setup() {
  pinMode(3, INPUT_PULLUP);
  pinMode(2, INPUT_PULLUP);
  pinMode(relayPin, OUTPUT);

  sensors.begin(); // Start temperature sensor

  // Start I2C OLED screen
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display.clearDisplay();

  getTemp();

  display.clearDisplay();
  printText("WATER COOLING", 1, 20, 0);
  printText("TEMP", 2, 64, 20);
  printText("SET", 2, 0, 20);
  printText(String(set_temp).c_str(), 2, 10, 40);
  printText(String(temp).c_str(), 2, 80, 40);
  display.display(); // Display the text on the screen


}

void loop() {

  getTemp();

  if (digitalRead(2) == LOW) {
    getUP();
  }
  if (digitalRead(3) == LOW) {
    getDWN();
  }


  if (relayState == false && temp > set_temp + hysteresis) {
    digitalWrite(relayPin, HIGH); // Turn on D4 relay
    relayState = true; // Update relay state
  }
  if (relayState == true && temp <= set_temp) {
    digitalWrite(relayPin, LOW); // Turn off D4 relay
    relayState = false; // Update relay state
  }

}

The problem I have is when I power the system, the OLED displays the first temperature reading, and the set temperature, but pressing the push buttons does nothing, and the temperature reading does not change. However, if I keep the power on but plug a USB into the nano and restart it, it will work as expected for about 10-15 mins before going back to the condition described. I don't know if it's the power supply that is the issue, on the 5v pin I read 5.028vDC with a DMM, or if the code and an error that I'm overlooking. The problem is not just the OLED displaying the correct data, the system will not operate correctly, i.e. if the screen freezes with a set temp of 60 and a temp reading of 70 the relay will keep the Peltier device on regardless of the temp. It seems like it's somehow getting stuck in a loop. I am by no means a coder so it could be a very simple mistake. The part that baffles me is why it works for longer with the USB connection.

here is the wiring schematic

as you can see the OLED and push buttons are connected to a shield brd which can be seen here.

image

thanks for your help!

  • Switches should be monitored for a switch change in state not the switch level.

  • Place some Serial.print( )s throughout your sketch to confirm variables are what you think they are.

  • Good try on making your schematic but all connections should be obvious; don’t make the viewer guess how things are interconnected.

  • why is 3v3 connected to Aref ?

  • a ceramic 100nF decoupling capacitor from 5v regulator pin 1 to 2 is needed. Close the the regulator.

I added a serial.print after the getTemp() is called, it follows the behavior of the OLED screen, when the screen freezes the serial monitor does as well.

you're saying I should replace the 10uF cap with a 100nF ?

As well as, the 100nF capacitor must be connected as close to the regulator terminals as possible.


What does the 5 volt output measure through the process; a scope can tell if there is oscillations on the 5v level.


BTW, suggest you use a Buck converter (step down).

Linear regulators for digital circuits might better be switched out to SMPS/Buck converters.

  • Make sure you adjust the output voltage to ~4.9v before connecting to the Nano 5v pin.

About $2.00

What results do you get from this version of your sketch ?



#include <Wire.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

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

OneWire oneWire(A1);
DallasTemperature sensors(&oneWire);

const byte heartbeatLED  = 13;
const byte relayPin      = 4;     //Output pin for D4 relay
const byte downSwitch    = 3;
const byte upSwitch      = 2;
const byte hysteresis    = 1;     //Hysteresis value in degrees Fahrenheit

byte lastDownSwitch      = HIGH;
byte lastUpSwitch        = HIGH;

bool relayState          = false; //Variable to keep track of D4 relay state
int set_temp             = 60;

int temp;

//Set up I2C OLED screen
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

//timing stuff
unsigned long heartbeatMillis;
unsigned long switchMillis;
unsigned long DS18B20Millis;
const unsigned long DS18B20Interval     = 1000ul;  //1 second


//**********************************************************************************
void setup()
{
  Serial.begin(115200);

  pinMode(downSwitch, INPUT_PULLUP);
  pinMode(upSwitch, INPUT_PULLUP);

  pinMode(relayPin, OUTPUT);
  pinMode(heartbeatLED, OUTPUT);

  //Start temperature sensor
  sensors.begin();

  //Start I2C OLED screen
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display.clearDisplay();

  display.clearDisplay();

  //read the temperature
  sensors.requestTemperatures();

  printText("WATER COOLING", 1, 20, 0);
  printText("TEMP", 2, 64, 20);
  printText("SET", 2, 0, 20);
  printText(String(set_temp).c_str(), 2, 10, 40);
  printText(String(temp).c_str(), 2, 80, 40);

  display.display(); //Display the text on the screen

  //read the temperature
  sensors.requestTemperatures();

} //END of   setup()


//**********************************************************************************
void loop()
{
  //*********************************
  //is it time to toggle the heartbeatLED ?
  if (millis() - heartbeatMillis >= 500)
  {
    //restart this TIMER
    heartbeatMillis = millis();

    //toggle the heartbeatLED
    digitalWrite(heartbeatLED, !digitalRead(heartbeatLED));
  }

  //*********************************
  //is it time to check the switches ?
  if (millis() - switchMillis >= 50)
  {
    //restart this TIMER
    switchMillis = millis();

    checkSwitches();
  }

  //*********************************
  //is it time to read the temperature ?
  if (millis() - DS18B20Millis >= DS18B20Interval)
  {
    //restart this TIMER
    DS18B20Millis = millis();

    temp = sensors.getTempFByIndex(0); // Get temperature value in Fahrenheit
    display.fillRect(80, 40, 48, 24, BLACK);
    printText(String(temp).c_str(), 2, 80, 40);

    display.display(); //Display the text on the screen

    //start a new conversion request
    sensors.setWaitForConversion(false);
    sensors.requestTemperatures();
    sensors.setWaitForConversion(true);
  }

  //*******************************************
  if (relayState == false && temp > set_temp + hysteresis)
  {
    digitalWrite(relayPin, HIGH); //Turn on D4 relay
    relayState = true;            //Update relay state
  }

  //*******************************************
  if (relayState == true && temp <= set_temp)
  {
    digitalWrite(relayPin, LOW); //Turn off D4 relay
    relayState = false;          //Update relay state
  }

} //END of   loop()


//********************************************^************************************************
//
void checkSwitches()
{
  byte currentState;

  //*********************************
  currentState = digitalRead(upSwitch);

  //has this switch changed state ?
  if (lastUpSwitch != currentState)
  {
    //update to the new switch state
    lastUpSwitch = currentState;

    //******************
    //was the switch pushed ?
    if (currentState == LOW)
    {
      getUP();
    }

  } //END of    this switch

  //*********************************
  currentState = digitalRead(downSwitch);

  //has this switch changed state ?
  if (lastDownSwitch != currentState)
  {
    //update to the new switch state
    lastDownSwitch = currentState;

    //******************
    //was the switch pushed ?
    if (currentState == LOW)
    {
      getDWN();
    }

  } //END of    this switch

} //END of   checkSwitches()


//**********************************************************************************
void printText(const char* text, uint8_t size, uint8_t x, uint8_t y)
{
  display.setTextSize(size);
  display.setTextColor(WHITE);
  display.setCursor(x, y);
  display.println(text);

  display.display();

} //END of   printText()


//**********************************************************************************
void getUP()
{
  if (set_temp < 70)
  {
    set_temp++;
  }

  display.fillRect(10, 40, 48, 24, BLACK);
  printText(String(set_temp).c_str(), 2, 10, 40);

  display.display(); //Display the text on the screen

} //END of   getUP()


//**********************************************************************************
void getDWN()
{
  if (set_temp > 45)
  {
    set_temp--;
  }

  display.fillRect(10, 40, 48, 24, BLACK);
  printText(String(set_temp).c_str(), 2, 10, 40);

  display.display(); //Display the text on the screen

} //END of   getDWN()


This seems to have solved the issue, I suppose that the code was getting stuck in a loop in my version of the code. Thanks

BTW

5v linear regulators are old technology that have poor power efficiency.


Look at how conventual schematics are drawn, then redraw yours to match that style.

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