How do you add two variables together?

Okay, this is my third update of my thread, and I think it's going to be my last. I have more or less solved the problem of me not being able to update an integer every 60 seconds, and I guess I'm just trying to make a small explanation of how I fixed it and some small sketches of code that can help you fix the same problem if you're somehow stuck in the same situation.

This was the specific bit of code I was having problems with. And the code below is my current version of the code, which I think works correctly.

if (millis() + runtime >= runtime + 60000 ) {
     runtime = runtime + millis();
     Serial.println("runtime update");
  }
  if (millis() - runtime >= timeupdatedelay ) {
      runtime += millis() 
      Serial.println("runtime update");
   }

How I solved the problem was instead of doing plus, I used minus, and then added another integer. And I also found out that if I ever want to add two valuables together, which was the thing I was having problems with in the beginning, I should just do this thing +=

This thing basically takes itself plus another integer as the new value. If you want more information, you could go to the Arduino reference sheet.

If you're interested, my new code will be at the bottom of the page. Thank you for watching.

Anything that is written below this line is my initial explanation of the problem I was having, which actually isn't a very good explanation of the problem I was having, I realize now, much later.


I have this small problem in my code when I want runtime to be equal to runtime plus how long the device has been turned on. But I don't know how to add the variables together. This is my full code. Any help is appreciated

Just one more question when I'm already creating a thread. Is there a way to get a bar graph in the serial monitor in the Arduino IDE? Because the example bar graph sketch that they give you requires you to use different software, and it doesn't work like I want it to. I want it to just be like the bar graph you use on an LCD display?

const int analogWriteSpeed = 55;
const int motorpin1 = 5;  // Example valid pin number
const int motorpin2 = 6;  // Example valid pin number
const int buttonPin = 2;  // Pin where the button is connected

unsigned long shortPressCount = 0;
unsigned long runtime = 0;
unsigned long buttonPressTime = 0;
const long timeupdatedelay = 60000;

bool motorstart = false;
int bitch;


void shortPressAction();
void longPressAction();

void setup() {
  Serial.begin(9600);
while (Serial) {}
Serial.println("hello world");

  pinMode(motorpin1, OUTPUT);
  pinMode(motorpin2, OUTPUT);
  pinMode(buttonPin, INPUT_PULLUP); // Using internal pull-up resistor
  
}

void loop() {
bool buttonState = digitalRead(buttonPin);
//Serial.println(buttonState);
delay(100);


 if (buttonState == HIGH ) {
   bitch = millis();
   
   while(digitalRead(buttonPin) == HIGH){
   delay(100);
   Serial.println("help");
  }

   if(millis() - bitch >= 3000) {
    //Serial.println("Long press triggered?");
    longPressAction();
    
   } 
   if (millis() - bitch >= 50 ) {
   
   motorstart = true;
   }


 
}


  //This is the bottom of void loop
}

void loop1(){
   if (millis() - runtime >= timeupdatedelay ) {
      runtime += millis() 
      Serial.println("runtime update");
   }

 if (motorstart == true) {
  shortPressAction();
 }


delay(100);
}


void longPressAction() {
  Serial.begin(9600);
  Serial.println("Long press action triggered");
  analogWriteSpeed += 10;
  
  if (Serial) {
    unsigned long totalMinutes = runtime / 60000;
    unsigned long minutes = totalMinutes % 60;
    unsigned long totalHours = totalMinutes / 60;
    unsigned long hours = totalHours % 24;
    unsigned long days = totalHours / 24;

    Serial.print("Device run time: ");
    Serial.print(days);
    Serial.print(" days, ");
    Serial.print(hours);
    Serial.print(" hours, ");
    Serial.print(minutes);
    Serial.println(" minutes");

    Serial.print("Short press action triggered ");
    Serial.print(shortPressCount);
    Serial.println(" times");


}
}
void shortPressAction(){
  
  Serial.println("shortPressAction triggered");
  
  
  shortPressCount ++;
  for (int i = 0; i < 10; i++) {
    digitalWrite(LED_BUILTIN, LOW);
    analogWrite(motorpin1, analogWriteSpeed);
    delay(2000);
    digitalWrite(motorpin1, LOW);
    delay(1000);
    digitalWrite(LED_BUILTIN, HIGH);
    analogWrite(motorpin2, analogWriteSpeed);
    delay(2000);
    digitalWrite(motorpin2, LOW);
    delay(1000);
}
motorstart = false;
digitalWrite(LED_BUILTIN, LOW);
}

How do you add two variables together?

With the plus-sign

example

unsigned long myVar1;
unsigned long myVar2;
unsigned long myVar3;

myVar1 = 1000;
myVar2 = 123;
myVar3 = 0;

myVar3 = myVar1 + myVar2;

I guess you know this detail.
So you might mean something different.
You will have to post a much more precise description of what you want to do.
One way to write such a description is to describe in normal words and with example-numbers what the code shall do.

Me personal I will not speculate what you might mean.
Post a more precise description

1 Like

Sit down with a piece of paper and work though this with some values. I think you'll see that it's completely wrong.

Have a look at the famous "BlinkWithoutDelay" example in the IDE and one or two of the thousands of various tutorials on that topic and you'll learn how to do this correctly.

1 Like

Okay, this is how far I've gotten. It works the first time it needs to update, but after that it goes back to the same problem. This would be much faster for me if you could just tell me how to do it, instead of redirecting me to other places. And, if you're going to redirect me, could you at least give me a link to a YouTube video?

 if (millis() - runtime >= timeupdatedelay ) {
     runtime = millis() + runtime;
     Serial.println("runtime update");
  }

You should always post your complete sketch.
If I search through your code posted in post # 1

the is not a single call to function loop1 ()

Here is a WokSim with serial debug-output to make visible what your code is really doing

I can't speak for all the members of the forum, but we aim to teach, not do it for you. As far as videos, they are good 'eye candy' but the learning comes from reading the accompanying document. If there is no document, find another video.

1 Like

Sorry I didn't help you the way you wanted. I'll mute your thread and won't bother you again. My bad.

But again,I'll leave you with the advice to sit with a piece of paper and work through that with some values and see if you can't see what's wrong. You're adding your runtime to millis for some reason. You should be adding the interval. Look again at the examples.

Good luck.

explaining non-blocking timing
I want to comment on the basic blink_without_delay example-code.

The basic basic blink_without_delay example-code makes understanding non-blocking timing
harder than it must be for multiple reasons:

It starts with postings that have sentences like "use function millis() instead of delay()"
There is a pretty high danger that this sentence creates a totally wrong picture of how non-blocking timing works.
Such a sentence initiates a wrong picture of

replace delay() with millis() and you are done.

non-blocking timing requires more than a simple replacing.

  1. the blink without delay-example does NOT mention that there is a fundamental difference
    between delay() and non-blocking timing
    Without explicitly explaining this difference newcomers are in danger to see a delay()-similar-Thing
    And trying to see a delay()-similar thing will cause extra confusion because there is NO similarity!

  2. a part of the variable-names is badly chosen.

  3. the demo-code distributes the variables to mutliple places

The variable-distribution makes it harder to understand the basic principle.

I suggest that you watch this video as the introduction to non-blocking timing
It will guide you on the right track and explain it step by step

1 Like

If you subtracted runtime from both sides, what would your if statement look like?

Returns the number of milliseconds passed since the Arduino board began running the current program.

How does your 'runtime' variable differ from what millis() is?

Also, I tried playing with your code on my uno, and it didn't get past the while line:

did it print for you?

2 Likes

Let us assume that you have just finished uploading your sketch. So, the elapse time is 0 ms. That elapsed time has been recored inside the MCU using a 32-bit unsigned counter named as mlliscounter. The millisCounter is updated/incremented by 1 ms in the backgorund on interrupts. The present content of the millisCounter can be known on-the-fly (without disturbing the counting process) by executing this function: millis(). So,

unsigned long int runtime = millis();     //runtime = 0 ms 

Let us see by manual computation what your above-mentioned codes do produce:

Assume that 60000 ms has gone since the recording of last runtime (0 ms).

runtime = runtime + millis();
==> runtime = 0 + 60000 (0 + 60000)
==> runtime = 60000 ms

Is this 60000 ms that you are expecting?

The test sketch would appear as follows:

unsigned long int runtime = millis();  //runtime ~= 0

void setup()
{
  Serial.begin(9600);
  Serial.print("Runtime at t1: "); Serial.println(runtime);
}

void loop()
{
  if (millis() + runtime >= runtime + 60000ul)
  {
    runtime = runtime + millis();
    Serial.print("Runtime at t2: "); Serial.println(runtime);
    while(true);
  }
}

Output:

12:49:53.412 -> Runtime at t1: 0
12:50:53.498 -> Runtime at t2: 60000

is this what you're trying to do?
millis() counts the # of msec since the processor is started. so that's the runtime you seem interested in until it overflows after 49 days

a 2nd variable, msecLst, can be used to keep track of when the last print occured and must eb updated each time it prints

const unsigned long MsecPeriod = 2000;      // 2 seconds
      unsigned long msecLst;

void
loop ()
{
    unsigned long msec = millis ();

    if (msec - msecLst >= MsecPeriod ) {
        msecLst += MsecPeriod;

        Serial.print   ("runtime ");
        Serial.println (msec);
    }
}


void setup ()
{
    Serial.begin (9600);
}


Thank you for taking your time to reply to my post. It's very nice. And I'm starting to understand what's going on. If I subtract runtime from both sides, it looks pretty stupid. And what I'm trying to make happen is if it has been more than 60 seconds since the runtime has been updated, then we update runtime. And the only difference really between millis() and runtime is that I'm planning for the future. Because I'm going to use the runtime variable to remove things like milliseconds and only keep minutes. Because I only need the useful information like how many minutes have this thing been running total.Because in the future I'm planning to put how many minutes it has been running in total in EEPROM, and I want as small of a bit of information as I can get, so I can store a larger number, so that I don't have to store how many milliseconds it has been on. Now, the only reason I'm using a while serial is for debugging. I put it there in the Past. to make sure serial is initialized, so I could get any information on how the code is running. And it does not print in Hello World after serial is initialized, but somehow the rest of the code works just fine. I guess I just haven't gotten around to removing it just yet, but if you are wondering how the code looks now, this is the update on how I managed to get the runtime variable to update :slight_smile:

if (millis() - runtime >= timeupdatedelay ) {
      runtime += millis() 
      Serial.println("runtime update");
  }

Thanks for replying. I guess I should explain what I want this small piece of code to do in the future. I want to be able to store the runtime of my device in minutes, without fractions. That is the final state I want this code. What the code is doing currently is mostly just updating every 60,000 milliseconds. And after that I was just planning on removing everything except how many minutes my system has been on. instead of requiring milliseconds or seconds because I want to put all of this in eprom and by not requiring to storing. Millie seconds and seconds I was hoping I could store a much longer amount of time in eprom Before
Roll over

Thanks for replying, but this is the reason I actually came and made this thread to begin with, is because the if-loop would run continuously instead of doing what I wanted to. I think I have fixed the code, so it works fine right now, I think. But what I'm trying to do is just keep an integer of how long the system has been running in minutes, so I can put that in EEPROM and store a lot of time Before rollover. so it won't roll over every 50 or so days. I'm trying to store a huge amount of time in EEPROM, so to say.
That's all :slight_smile:

the if condition is NOT true continuously, it is only true every MsecPeriod msecs,

you could set MsecPeriod to 60,000 so that the condition is only true every minute and incremement a minute variable. this would be consistent even after millis() wraps after 49 days

1 Like

i don't think the code is doing what you expect.

consider this code

void
loop (void)
{
    if (millis() + runtime >= runtime + 1000) {
        runtime = runtime + millis();

        Serial.print   (millis());
        Serial.print   (" ");
        Serial.println (runtime);
    }
}

and this output

1000 1000
1000 2000
1000 3000
1001 4001
1001 5002
1002 6004
1002 7006
1012 8018
1024 9042
1035 10077
1047 11124
1060 12184
1073 13257
1085 14342
1097 15439
1110 16549
1123 17672
1135 18807
1147 19954
1160 21114
1172 22286
1184 23470
1198 24668
1210 25878
1222 27100
1234 28334
1247 29581
1260 30841
1272 32113
1285 33398
1297 34695
1309 36004
1323 37327
1335 38662
1347 40009
1359 41368

the if condition remains true without millis() advancing because when runtime is zero and millis() is still 1000, millis() + runtime continues to be >= runtime + 1000.

1 Like

Some terrible things will happen with that math as well, since millis() will keep growing. Expanding that snippet into something executable:

uint32_t runtime = 0, timeupdatedelay = 1000;

void setup() {
  Serial.begin(115200);
}

void loop() {
  if (millis() - runtime >= timeupdatedelay ) {
    runtime += millis();
    Serial.print(millis());
    Serial.print(" ");
    Serial.print(runtime);
    Serial.print(" ");
    Serial.print(millis() - runtime);
    Serial.println(" runtime update");
  }
}

gives:

1000 1000 0 runtime update
2000 3000 4294966296 runtime update
2001 5001 4294964296 runtime update
2002 7003 4294962295 runtime update
2004 9007 4294960295 runtime update
2008 11015 4294958290 runtime update
...

This happens because runtime gets another dose of +millis() every time it is triggered, and so on the second iteration at 2000ms, it adds on another 2000 to the 1000 from the first iteration to accumulate to 3000. The next bad thing to happen is that 2000-3000 is -1000, which rolls under the 0 lower limits of an unsigned long into a really big number that is far larger than 1000, and so triggers immediately and blows up fast.

I think you want intervals that are timeupdatedelay long, and you can use a couple methods:

  if (millis() - runtime >= timeupdatedelay ) {
    runtime = millis();
    ...
   }

which marks the current millis() as the point from which you want to measure the next timeupdatedelay interval.

or

  if (millis() - runtime >= timeupdatedelay ) {
    runtime += timeupdatedelay;
    ...
   }

which advances the runtime precisely timeupdatedelay milliseconds after the last planned time.

Thanks @gcjr -- I didn't see your post while I was writing.

Ah-- If you are trying to use millis() to plan for things in the future rather than as an interval from a time in the past, you have to be careful to handle the unsigned long roll-under inherent in:

  if (millis() - runtime >= timeupdatedelay ) {

You can handle scheduling future events with:

if((signed long)(millis() - scheduledMillis >=0){
  scheduledMillis = ....;
  ...
}          

See Doing 1000 independent things at the same time with millis() for some discussion of the math.

Here is a demo-code for a completely software-based realtime-clock.

Though software-based RTCs are pretty unprecise.
For more precision you should use a hardware-RTC-module like the DS3231

If you add another variable which I would name with a name that says spot-on what its purpose is
something like "totalRunTimeMinutes"

that is increased inside the if-condition where the variable RTC_Minute is increased by one you have this minute-counter.

For storing this value inside the eeprom you have to take care of that this EEPROM can only stand 100.000 write-cycles. If your code has a fault that you write to the EEPROM at high speed the EEPROM will quickly wear out.

Writing to the eeprom once every minute gives you 100000 / (24 * 60) = 69.44 days
I haven't done much with EEPROMs. There might be libraries that do wear-out-leveling by writing to an always different EEPROM-adress but I don't know if this works the same way for EEPROMs like for flash-memory or SSDs.

One solution can be using an SPI-FRAM-Chip like this one

or an I2C-FRAM-Chip like this one

FRAM-chips have 12.000.000.000 write-cycles
Which gives you 12000000000/(2460365) = 22831 years writing once per minute

As you might see now. It is always a good idea to give an overview about your project