1

I have started a thread on the Arduino forum. If someone could have a look at the thread and give me some help either here or there that would be great. (I don't want to have to add all the information from that thread into this one).

https://forum.arduino.cc/index.php?topic=691659.15

The background of the code is that I am trying to call a function within the void loop() and make it loop so that it updates values on the OLED screen for temperature and humidity from a sensor. I have had this working before, but now I have a menu and cant run it straight from the void loop() as I have a menu structure.

Hi, I have been working on this project where I am monitoring and controlling humidity/temperature for a humidor I am going to build. I am using an OLED screen and right now i've been designing the menu/ UI. I know that the code right now isnt the best but I have just been trying to make it work then finalise the workings and details once its fully working. (sorry im not a big commentor in my code). I am using a rotary encoder to navigate the menu.

    if (value == 0){ //Encoder Position
Menu();
display.setTextSize(1);
display.setCursor(0,15);
display.print(">");
display.display(); 
  if(buttonState== LOW){ //If encoder is pressed
    value = 6;
    while (value == 6){
      MainDisplay(t,h);
    }       
}

This is the problem I have, I want to call the MainDisplay() function which displays the temperature and humidity easily to read, I have tried to use a while loop while runs the function while the encoder value is equal to 6, but when I try to loop this function the OLED screen freezes and so does the serial readout in the IDE. This function calls fine when I don't try to loop it, however that isn't very useful because the screen will only display the temp & humidity from when the function is called and remains stationary.

I'm pretty new to arduino code and this is my first project, so any help or advice would be very much appreciated. Once again, I know the other parts of the code may not be the most efficient but I plan to fix this when I get the code to work and I will tidy it up.

I want this loop to run for long peroids of time because the mainDisplay() function will be on the display when not operating. I have tried changing it so when the encoder button is pressed it will exit the loop but the same thing is happening. The loop doesn't run with the code shown, the arduino just crashes and must be reset. For the other options in the menu they work fine to call the function when selected, however they aren't being looped, and they are exited when the encoder position is lowered.

Here is the full code.

#include <ClickEncoder.h>
#include <TimerOne.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include "DHT.h"
#define DHTPIN 12     // what pin we're connected to
#define DHTTYPE DHT22   // DHT 22  (AM2302)
DHT dht(DHTPIN, DHTTYPE);

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

#define Pa 2 //Encoder Pin A
#define Pb 3 //Encoder Pin B
#define SW A1 //Encoder Button

ClickEncoder *encoder;
int16_t last, value;
const int buttonPin = SW; //Encoder Button
int buttonState;    // variable for reading the pushbutton status
int standby = 15;
int leftnumber;

float t;
float h;
float highT;
float lowT = 50;
float highH;
float lowH = 100;

void timerIsr() {
  encoder->service();
}

// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

void setup() {
  Serial.begin(9600);
   
  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3D for 128x64
    Serial.println(F("SSD1306 allocation failed"));
    for(;;);
  }
  encoder = new ClickEncoder(Pa, Pb, SW);
  Timer1.initialize(1000);
  Timer1.attachInterrupt(timerIsr);
  last = -1;
    // initialize the pushbutton pin as an input:
  pinMode(buttonPin, INPUT_PULLUP);

 Menu();
}

void MainDisplay(float t, float h){

  //RESET
  //delay(100);
  display.clearDisplay();
 
  //TEMP1
  display.setTextColor(WHITE);
  display.setTextSize(1);
  display.setCursor(0,0);
  display.print("Temperature: ");
  display.setTextSize(2);
  display.setCursor(0,10);
  display.print(t);
  display.print(" ");
  display.setTextSize(1);
  display.cp437(true);
  display.write(167);
  display.setTextSize(2);
  display.print("C");
  //HUMIDITY1
  display.setTextSize(1);
  display.setCursor(0, 35);
  display.print("Humidity: ");
  display.setTextSize(2);
  display.setCursor(0, 45);
  display.print(h);
  display.print(" %");
 
  //ICON-*Flashes*
  display.fillRoundRect(100, 10, 20, 44, 2, WHITE);
  display.setCursor(105,15);
  display.setTextColor(BLACK);
  display.print("J");
  display.setCursor(105,35);
  display.print("B");
  display.display();
  //delay(20);
  //display.fillRoundRect(100, 10, 20, 44, 2, WHITE); //FLASH (copy Temp1 & Humidity1)

}
void Menu(){

    //TITLE
    display.clearDisplay();
    delay(50);
    display.setTextColor(WHITE);
    display.setTextSize(2);
    display.setCursor(40,0);
    display.print("MENU");
    //MENU1 Temp   
    display.setTextSize(1);
    display.setCursor(10,25);
    display.print("Temperature Set");
    //MENU2 Humid
    display.setCursor(10,35);
    display.print("Humidity Set");
    //MENU3 Setting
    display.setCursor(10,45);
    display.print("Settings");
    //24HR Min/Max
    display.setCursor(10,55);
    display.print("Daily Min/Max");
    //RETURN
    display.setCursor(10,15);
    display.print("Main Display");

    display.setCursor(115,0);
    display.print(value);
   
    display.display();
           
}

void TempMenu(){ //Set Temperature
 value = 6;
 //ActualTEMP
  display.clearDisplay();
  display.setTextColor(WHITE);
  display.setTextSize(1);
  display.setCursor(0,0);
  display.print("Set Temperature =");
  display.setTextSize(1);
  display.cp437(true);
  display.write(167);
  display.setTextSize(2);
  display.print("C");
  display.display();
}
void HumMenu(){
 
}
void SetMenu(){
 
}
void MaxMenu(){ //Max/Min Temp&Hum
  value = 6;
  display.clearDisplay();
  display.setTextColor(WHITE);
  display.setTextSize(2);
  display.setCursor(30,0);
  display.print("MIN/MAX"); 
  display.setTextSize(1);
  display.setCursor(0,25);
  display.print("Max Temperature=");
  display.print(highT);
  display.setCursor(0,35);
  display.print("Min Temperature=");
  display.print(lowT);
  display.setCursor(0,45);
  display.print("Max Humidity =");
  display.print(highH);
  display.setCursor(0,55);
  display.print("Min Humidity =");
  display.print(lowH);
  display.display();
}

void loop() {
  // Reading temperature or humidity takes about 250 milliseconds!
  // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
  float h = dht.readHumidity();
  // Read temperature as Celsius
  float t = dht.readTemperature();
  // Read temperature as Fahrenheit
  float f = dht.readTemperature(true);

    if (t > highT){
      highT = t; //Highest Temperature
  }
    if (t < lowT){
      lowT = t; //Lowest Temperature
  }
    if (h > highH){
      highH = h; //Highest Humidity
  }
    if (h < lowH){
      lowH = h; //Lowest Humidity
  }


  value += encoder->getValue();
  if (value != last) {
    last = value;
    Serial.print("Encoder Value: ");
    Serial.println(value);
 }
  // read the state of the pushbutton value:
  buttonState = digitalRead(buttonPin);
  // check if the pushbutton is pressed. If it is, the buttonState is LOW:

    if(value < 0){
      value = 0; // Doesnt allow encoder to go below 0
  }

    if (value == 0){ //Encoder Position
    Menu();
    display.setTextSize(1);
    display.setCursor(0,15);
    display.print(">");
    display.display(); 
      if(buttonState== LOW){ //If encoder is pressed
        value = 6;
        while (value == 6){
          MainDisplay(t,h);
        }       
    }
  }   
   
    if (value == 1){ //Encoder Position
    Menu();
    display.setTextSize(1);
    display.setCursor(0,25);
    display.print(">");
    display.display(); 
      if (buttonState == LOW){ //If encoder is pressed
        TempMenu();   
      }
  }
    if (value == 2){ //Encoder Position
    Menu(); 
    display.setTextSize(1);
    display.setCursor(0,35);
    display.print(">");
    display.display();
      if (buttonState == LOW){ //If encoder is pressed
        HumMenu();   
      }     
  }
    if (value == 3){ //Encoder Position
    Menu(); 
    display.setTextSize(1);
    display.setCursor(0,45);
    display.print(">");
    display.display();
      if (buttonState == LOW){ //If encoder is pressed
        SetMenu(); 
      }     
  }
    if (value == 4){ //Encoder Position
    Menu(); 
    display.setTextSize(1);
    display.setCursor(0,55);
    display.print(">");
    display.display();
          if (buttonState == LOW){ //If encoder is pressed
        MaxMenu();   
      }   
  }
}


3
  • 1
    I have had responses which have provided no solution. I came here to try and get some better advice as I have had better responses on stackoverflow in the past with other situations. – jburke424 Jun 21 '20 at 21:16
  • couple of things stand out ... the cursor movement code should be totally separate from the button press code .... all of the if (value == x) statements should be eliminated because the cursor position can be calculated display.setCursor(0,value * 10 + 15 ); .... put the button press code after the cursor code .... the button press code should run only once when the button transition happens .... it should not repeat if the button is held down .... use if (value == x) statements to choose the correct menu to display – jsotola Jun 22 '20 at 2:05
  • look at the code where you update the highest/lowest ... if there is a change, then also set a flag, such as minmax_change = true; ... check if temperature and humidity have changed ... set flag temp_hum_change = true; .... further down in your code, check if the current screen should be refreshed – jsotola Jun 22 '20 at 3:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.