Running a sketch does not work .. sometimes

Hello everybody,

first of all: I'm new to this forum and I have no clue if this is the right category. So this is for the mods: please feel free to move my post wherever you want.

I am: new to arduino and C
I am not: new to electronics and programming

I am currently working on a project, that is something like a timer-controlled power-outlet (european SchuKo). The timer function is superimposed by a temperature-override and a manual bypass-switch (turning the outlet "always-on", when at home during a holiday, for example).
The sketch still has a few bugs, but overall, it works as intended. I'm gonna include a screenshot if the serial monitor below.

But here is some behavior, that appears strange to me: compiling and uploading the sketch over the arduino IDE works ("Done uploading"), but the sketch is not executed on first try. The green ON LED on the Arduino lights up and nothing happens. Reuploading does not help.
But, if I upload another sketch, for example one of the library-included example sketches, before reuploading my previous sketch, it works flawlessly.

The arduino does not behave like this with any other sketch. So something is hidden in my „main.ino“. I will include it below. Is there some kind of register, that needs to be flushed or something like that?

Edit: It is an Arduino Uno, that is used.

Code:

//Changelog
//V1-1: added changeIndicator and removed delaytime -> processing input full speed
//      withoud loosing readability
//V1-2: excluded methods from loop()
//V1-3: implemented clock

//important note: implement wait time after power-up to prevent swithing on and off to fast

//include libs
#include <OneWire.h>
#include <DallasTemperature.h>
#include <RTClib.h>
#include <Adafruit_BusIO_Register.h>
#include <Adafruit_I2CDevice.h>
#include <Adafruit_I2CRegister.h>
#include <Adafruit_SPIDevice.h>

//initialize variables
//displayInformation: 1 = Holiday; 2 = Temperature Alert; 3 = Sleeptime; 4 = Waketime
int sensorCount;
double currentTemp;
double tempChangeThreshold = 0.02;
double newTemp;
bool holiday = false;
bool newHoliday = false;
bool sleeptime = true;
bool newSleeptime = true;
int sleepStart1 = 2;
int sleepEnd1 = 5;
int sleepStart2 = 8;
int sleepEnd2 = 15;
bool systemOn = true;
int PowerSystemStatus = 1;
int LEDPort = 7;
int SwitchPort = 8;
int PowerControlPort = 9;
int SensorPort = 2;
bool changeIndicator;
int Wait = 10;
int displayInformation;
String timeNow = "00:00";
bool debugMode = false;

//initialize devices
#define ONE_WIRE_BUS SensorPort
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
RTC_DS3231 rtc;
DateTime now = rtc.now();


// ----------  Setup ----------

void setup(void) { 
 //initialize com
 
    //delay after Serial.begin() is mandatory --> Otherwise "68§6@9jr8/"
    //others are for readability --> optional!
 Serial.begin(57600);
 delay(2000);
 Serial.println("Initializing");
 delay(1000);
 Serial.println("Serial interface established");
 delay(200);

  //initialize temperature sensor on OneWire Bus
 Serial.println("Establishing OneWire Bus - Temperature sensors DS18B20"); 
 sensors.begin();
 delay(500);
 sensorCount = sensors.getDS18Count();
 if(sensorCount==0) {
  Serial.println("Error - no sensor found");
 }
 else {
  Serial.print("Succesfully established connection with ");
  Serial.print(sensorCount);
  Serial.println(" sensors");
 }
 delay(500);
 
 //initzalize RTC Shield Clock DS3231 on I2C Bus
 Serial.println("Establishing I2C bus - realtime-clock DS3231");
 if (! rtc.begin()) {
  Serial.println("Error - no clock found");
 }
 if (rtc.lostPower()) {
  Serial.println("RTC module: startup after power-loss.");
  rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
  delay(1000);
  Serial.println("Date and time were set to: Date and Time this code was compiled.");
 }
 
 delay(3000);
 Serial.println("Succesfully established connection with DS3231");

 //initialize I/O
 pinMode(PowerControlPort, OUTPUT);
 pinMode(LEDPort, OUTPUT);
 pinMode(SwitchPort, INPUT);
 digitalWrite(LEDPort, HIGH);

 //finalize setup
 Serial.println();
 delay(3000);
} 


// -------  Methods  -------

//Temperatures
double requestTemps() {
  //request onewire sensors
  sensors.requestTemperatures();
  //get temperatureinformation for all sensors and return a double
  double tempBuffer = 0;
  if (sensorCount>1) {
    //for multiple sensors, get all and calculate average
    for(int i=0; i<sensorCount; i++) {
      tempBuffer = tempBuffer + sensors.getTempCByIndex(i);
    }
    tempBuffer = tempBuffer / sensorCount;
  }
  else {
    //for a single sensor, just get sensor information
    tempBuffer = sensors.getTempCByIndex(0);
  }
  return tempBuffer;
}

void updateSensors() {
  currentTemp = newTemp;
}


//HolidaySwitch
bool requestSwitch() {
  if (digitalRead(SwitchPort)==0) {
    return false;
  }
  else {
    return true;
  }
}

void updateHolidaySwitch() {
  //Updating Holiday Switch
  if (requestSwitch() == true) {
    holiday = true;
    setLED(1);
  }
  if (requestSwitch() == false) {
    holiday = false;
    setLED(0);
  }
}


//Clock
//Updating Time without checking midnight (future feature)
int requestTime() {
 // return now.hour();
 return 3;
}

//returns bool if it's time to sleep
bool requestSleeptime() {
  bool timebuffer = true;
//  if (requestTime() > sleepStart1 && requestTime() < sleepEnd1) {
//    timebuffer = true;
//  }
//  if (requestTime() > sleepStart2 && requestTime() < sleepEnd2) {
//    timebuffer = true;
//  }
//  else {
//    timebuffer = false;
//  }
  return timebuffer;
}

//updates the sleeptime parameter
void updateTime() {
  sleeptime = newSleeptime;
}

//Serial Display
void displaySerial() {
  //display system state overview
  displayTemps();
  displaySwitchState();
  displayTime();

  //display message
  if (displayInformation == 1) {
    Serial.println(" --> Holiday mode is active, system is set to ON! <-- ");
  }
  if (displayInformation == 2) {
    Serial.println(" --> Alert! Temperature is too low! System is set to ON! <-- ");
  }
  if (displayInformation == 3) {
    Serial.println(" --> It's time to sleep. System is set to OFF <-- ");
  }
  if (displayInformation == 4) {
    Serial.println(" --> Hey, you are finally awake. System is set to ON <-- ");
  }

  Serial.println("");
  Serial.println("");
}

void displayTemps() {
  Serial.println("Information gathered from temperature sensors:");
  
  if (sensorCount == 1) {
    displaySensorInfo(0);
  }
  else {
    for (int i = 0; i < sensorCount; i++) {
      displaySensorInfo(i);
    }
  }
}

void displaySensorInfo(int id) {
   Serial.print("Sensor ");
   Serial.print(id);
   Serial.print(": ");
   Serial.print(sensors.getTempCByIndex(id));
   Serial.println("°C");
}

void displaySwitchState() {
  Serial.println("Current state of the holiday switch:");
  if (holiday == true) {
    Serial.println("Holiday Switch: ON");
  }
  else {
    Serial.println("Holiday Switch: OFF");
  }
}

void displayTime() {
  Serial.println("The Time is:");
  Serial.print("Time: ");
  Serial.print(now.hour());
  Serial.print(":");
  Serial.print(now.minute());
  Serial.print(" --> Time to sleep = ");
  Serial.println(sleeptime);
}

//checking for changes
void checkflag() {
 newTemp = requestTemps();
 newHoliday = requestSwitch();
 newSleeptime = requestSleeptime();

 //for temperature, check if change exceeds threshold
 if ((abs(currentTemp-newTemp)/currentTemp) > tempChangeThreshold) {
  changeIndicator = true;
 }

 //for holiday switch and timeflag, just check if changed
 if (holiday != newHoliday) {
  changeIndicator = true;
 }
 if (sleeptime != newSleeptime) {
  changeIndicator = true;
 }
}

//IO
void setLED(int in) {
  if (in == 1) {
    digitalWrite(LEDPort, HIGH);
  }
  else {
    digitalWrite(LEDPort, LOW);
  }
}

void setSystemState(int in) {
  if (in ==1) {
    digitalWrite(PowerControlPort, HIGH);
  }
  else {
    digitalWrite(PowerControlPort, LOW);
  }
}

//debug Mode
void displayDebug() {
 Serial.print("sleeptime = ");
 Serial.println(sleeptime);
 Serial.print("newSleeptime = ");
 Serial.println(newSleeptime);
 Serial.print("holiday = ");
 Serial.println(holiday);
 Serial.print("newHoliday = ");
 Serial.println(newHoliday);
 Serial.print("currentTemp = ");
 Serial.println(currentTemp);
 Serial.print("newTemp = ");
 Serial.println(newTemp);
 Serial.print("changeIndicator = ");
 Serial.println(changeIndicator);
 Serial.print("now.hour = ");
 Serial.println(requestTime());
 Serial.print("requestSleeptime() = ");
 Serial.println(requestSleeptime());
 Serial.println("");
}

void loop(void) {

 checkflag();

 //updating all criteria
 if (changeIndicator == true) {
  //updating temperature data
  updateSensors();

  //updating state of holiday switch
  updateHolidaySwitch();

  //updating time
  updateTime();
 }


 //core-functionallity: query criteria
 //outer loop to inner loop: more to less important
 if (currentTemp < 5.00) {
  systemOn = true;
  displayInformation = 2;
 }
 else {
  if (holiday == true) {
    systemOn = true;
    displayInformation = 1;
  }
    else {
      if (sleeptime == false) {
        systemOn = true;
        displayInformation = 4;
      }
      else {
        systemOn = false;
        displayInformation = 3;
      }
    }
  }


 //set system state and display parameters if parameters changed
 if (changeIndicator == true) {
  displaySerial();
  if (systemOn == false) {
    setSystemState(0);
  }
  else {
    setSystemState(1);
  }
 }

 //Display Debug Information
 if (debugMode == true && changeIndicator == true) {
  displayDebug();
  delay(5000);
 }
  
 //resetting changeIndicator
 changeIndicator = false;
} 

Welcome to the forum

Your topic was MOVED to its current forum category as it is more suitable than the original

Is your sketch really named main.ino ?

If so then the hidden Arduino main() function will not be compiled into your project and therefore the board hardware may not be properly initialised.

Have you tried using a different name for your sketch ?

For reference, here is the Arduino main() function

/*
  main.cpp - Main loop for Arduino sketches
  Copyright (c) 2005-2013 Arduino Team.  All right reserved.

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

#include <Arduino.h>

// Declared weak in Arduino.h to allow user redefinitions.
int atexit(void (* /*func*/ )())
{
  return 0;
}

// Weak empty variant initialization function.
// May be redefined by variant files.
void initVariant() __attribute__((weak));
void initVariant() { }

void setupUSB() __attribute__((weak));
void setupUSB() { }

int main(void)
{
  init();
  initVariant();
#if defined(USBCON)
  USBDevice.attach();
#endif
  setup();
  for (;;)
  {
    loop();
    if (serialEventRun) serialEventRun();
  }
  return 0;
}

Hi,

thanks for your reply.
It is named 'main_1-3.ino', with 1-3 marking the version number.
I'll try renaming it anyway.

Edit: renamed it to "exec_1-4", same behavior.

Im not trrying to be rude, but thats an awful lot of code to perform a pretty simple function.

Personally, I'd suggest removing about half of your user-defined functions, then creating meaningful 'composite' functions - using passed and returned values.

It will be a lot easier to follow and debug - and you can easily trace execution with some simple Serial.print() statements.

You've done really well as a beginner in the forum, but all I see is a lot of unnecessary complexity where it's not needed.
It's pretty much valid code, but ont for a simple project like this.

It was just a thought, but not likely to be the problem. The problem does arise if you have a function named main() in your sketch, in which case it does override the Arduino main() function

Hi,

yeah, I'm aware of that. It's just I had a lot fun learning C and thats why the code grew and grew and grew.
So your suggestion is to completely redo it and solving the problem just by the new code or at least precisly encounter the reason for the problem by trying the new code step by step?

If I don't find a solution I will consider that.

I noticed something, that might be ralated.

If I
-upload the blink sketch from the basics menu, the arduino will continue working after power-loss
-upload my Main_1-2, my problem does not occur, but the arduino won't continue working after power-loss
-upload my Main_1-3, both problems occur
-upload a ds3231 example, from the rtc library, for my RTC shield, the arduino won't continue working after power-loss, too.

Continuing its duty by restarting the same sketch would be a key request for my project.
Is there something important I don't know about arduino? I thougt the arduino would automatically restart after a power-loss.

Does your DS3231 have a good battery backup?

(I notice the time reads 12 past 63-o'clock.)

yes, it has a battery and it works. in my main_1-3.ino, it is not working properly. So for the purpose of testing the rest, i have bridged it out of the code. It is another problem to discuss in a separate post.

I‘ll give unplugging the RTC a try!

Edit: it works with the sketch from the rtc lib.

You can not call the now() function to retrieve the current time before setup() has run and the wire (i2c) has been initialized. Just declare the variable as global and move the assignment into setup()

RTC_DS3231 rtc;
DateTime now;
//...
void setup() {
  // .... wire.begin(), etc.
  now = rtc.now();
}

Additional tip: enumerations make your code easier to read

//displayInformation: 1 = Holiday; 2 = Temperature Alert; 3 = Sleeptime; 4 = Waketime
enum { HOLIDAY, TEMP_ALERT, SLEEP_TIME, WAKE_TIME };

and then use those constants rather than numbers

  //display message
  //if (displayInformation == 1) {
  if(displayInformation == HOLIDAY ) {
    Serial.println(" --> Holiday mode is active, system is set to ON! <-- ");
  }

You also have lots of code that deals with 1 versus many when it is not necessary

void displayTemps() {
  Serial.println("Information gathered from temperature sensors:");

  if (sensorCount == 1) {
    displaySensorInfo(0);
  }
  else {
    for (int i = 0; i < sensorCount; i++) {
      displaySensorInfo(i);
    }
  }
}

is the same as

void displayTemps() {
  Serial.println("Information gathered from temperature sensors:");
   for (int i = 0; i < sensorCount; i++) {
      displaySensorInfo(i);
    }
}

Thank you, kind stranger, it does indeed look like this

You can not call the now() function to retrieve the current time before setup() has run and the wire (i2c) has been initialized. Just declare the variable as global and move the assignment into setup()

solved my problem. It looks like its working every time I press the upload button and it does boot up correctly after power-loss.

Although: Thanks for the additional tips. I've already scraped the if query in displayTemps().

Just in case anybody minds: here is a picture of my project.

The wire on top is the temperature sensor. A PC can be plugged over the USB type C port on the left.

Here is a screenshot of the serial monitor, with the clock now working.

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