Integer overflow understanding

I'm trying to understand the integer overflow mechanism, but I don't get it yet.

The following code has unexpected (to me) behavior :

int counter = 0;
uint32_t longcounter = 0;

void loop() {

counter = counter + 5;
longcounter = counter *1000;

}

This works fine until the 'counter' reaches 30. with the next addition of 5 the 'longcounter' will get a -30536 value.

I understand that an integer can only store values from -32,768 to 32,767, but as I'm trying to store the result of the multiplied integer 'counter' into a uint32_t variable I don't understand why 'longcounter' is behaving like a normal integer as well and inherits the overflow behavior of the 'counter' variable.

When I define 'counter' as uint32_t as well the result is ok and a value of 35 on the 'counter' wil result in 35000 on the 'longcounter'.

In my full code, the counter will never go past 200 (well in range of the integer overflow) but the longcounter will because of the multiplication. To my idea defining the counter as a normal integer would save some memory space as opposed to defining it as uint32_t, but it seems that calculations with this integer can never exceed the maximum value of itself even though the variable to store the outcome in, accepts a larger value.

In this code, everything on the right of "=" is treated as a 16 bit integer for calculations. The "=" then stores the result in the unsigned long variable.

longcounter = counter *1000;

To avoid overflow, use a cast, or declare counter to be long, or use a long constant as follows:

longcounter = counter *1000UL;

jremington:
To avoid overflow, use a cast, or declare counter to be long, or use a long constant as follows:

longcounter = counter *1000UL;

Thanks, I now see why the L is used in some examples I came across.

So using the L is the more memory friendly solution, because the global variable mem space of counter will be smaller as integer as opposed to long?

It's nothing to do with memory, it is telling the compiler that the constant is to be treated as an unsigned long, which is also an integer data-type.

AWOL:
It's nothing to do with memory, it is telling the compiler that the constant is to be treated as an unsigned long, which is also an integer data-type.

That I don't understand.

If I declare counter as int (global) it takes 2 bytes of global memory, if I declare it as uint32_t it takes 4 bytes of global memory.

So longcounter = counter *1000; where counter is defined as uint32_t has a larger global memory use than longcounter = counter *1000UL; where counter is defined as int. Or is the fact that I define the constant as UL cancelling that memory benefit?

counter does not change. The constant (which is not stored in SRAM memory) changes.

By promoting the constant it causes the temporary calculation to use more memory (actually registers, not SRAM) so the memory is available for other uses after the calculation has finished.

I understand that an integer can only store values from -32,768 to 32,767

Not strictly true.

A signed int can only store values from -32,768 to 32,767 on a Uno and other ATMEGA based boards, but note that an unsigned int can hold values 0 to 65,535 on a Uno and other ATMEGA based boards.

On a Due the ranges of both signed and unsigned ints is much larger as they are held in 4 bytes as opposed to 4.

If you declare "counter" to be long, you permanently use more SRAM, which is in short supply, so using a cast or a long constant for the calculation is the way to go.

That way the variable "counter" is temporarily converted to long for the purposes of the calculation, then when done the memory is freed.

Don't confuse the data-type "int" and the concept "integer".

char (8 bit), int (16 bit on 8 bit Arduinos), long (32 bit) and long long (64 bit) are all integer data-types.

@OP

1. It looks that you have not said things correctly in your original post.

2. When counter reaches to 30; longcounter is : 30000 (it is fine).

3. When counter reaches to 35; longcounter is: 4294936760 (it is also fine apparently); it is not -30536! See the following screenshot:
sm70.png

int counter = 0;
uint32_t longcounter = 0;

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

void loop() 
{
  counter = counter +5;
  longcounter = counter*1000;
  Serial.println(counter, DEC);
  Serial.println(longcounter, DEC);
  delay(5000);
}

In your post you have said that when counter reaches to 35, loncounter = -30536. This does not happen?

4. When counter is 35, longcounter (as you are expecting) should be 35000; in stead, the longcounter value is 4294936760 which I have termed as correct (apparently).

5. Now, the point should be to understand why the program that you have posted does produce 4294936760 and not 35000. What should we do and why (see this post and also the clue given in Post#8 due to @AWOL) to get 35000? Look at the following screenshot.
Sm71.png

6.

AWOL:
int (16 bit on 8 bit Arduinos)...

sm70.png

Sm71.png

Thanks all.

@AWOL: I indeed created confusion by using the term integer instead of type int.
@UKHeliBob: so on a Due declaring it as type int will give me a bigger range then -32,768 to 32,767 ?

@MorganS & jremington
Thanks for the clarification This is what I expected and what I meant by using the UL as a more global memory saving solution as declaring the counter as uint32_t

GolamMostafa:
@OP

1. It looks that you have not said things correctly in your original post.

2. When counter reaches to 30; longcounter is : 30000 (it is fine).

3. When counter reaches to 35; longcounter is: 4294936760 (it is also fine apparently).

Actually you're right :slight_smile: . I was not reading the value on the serial monitor but on a Nextion touch screen. I returned the value to a Nextion number (16 bit integer?) component which probably causes the overflow and negative value on the Nextion itself.

so on a Due declaring it as type int will give me a bigger range then -32,768 to 32,767 ?

Yes it will. To quote from the Arduino reference for the unsigned int data type

The Due stores a 4 byte (32-bit) value, ranging from 0 to 4,294,967,295 (2^32 - 1).

@OP

This is fine that you have the tool of fixing your codes to get 35000. But, are you thinking why you are getting 4294936760 on Arduino Serial Monitor and -30536 on Nextion touch screen instead of 35000? These values are apparently correct! Posts are saying to do casting by appending UL at the end or uint32_t at the beginning -- these are just fixing your problems. We need to dig a little bit to find the root of the problem you have faced.

@AWOL has given you the following clue -- give a thought on this clue in relation to the details of this link.

AWOL:
int (16 bit on 8 bit Arduinos)...

On the video you can see it happen.

So there is a counter (int) which has with each + button tap increases with 5 (counter). The there is a variable longcounter (uint32_t ) which multiples that counter with 1000 and some code to print that longcounter on the screen. Changing counter to uint32_t fixes the issue as well as the longcounter = counter * 1000UL;

As of why it shows as -30536 seems to have another reason then somewhere in the Nextion HMI....

In my full code, the counter will never go past 200 (well in range of the integer overflow)

If the counter never exceeds 255, byte should be sufficient for the counter.

As for your output on the Nextion, it might help if you could post the complete code, there may be something else causing the odd behavior.

david_2018:
If the counter never exceeds 255, byte should be sufficient for the counter.

As for your output on the Nextion, it might help if you could post the complete code, there may be something else causing the odd behavior.

You're right this could be a byte indeed. It's just a raw try out for irrigation of my greenhouse. It's probably getting a bit more off topic now as solutions are already provided for the problem I faced. Tons of things can be improved on this code but here it is:

#include <Nextion.h>

#include <DHT.h>



#define DHTPIN 2
#define DHTTYPE DHT22

NexButton b0 = NexButton(0, 18, "b0");  // Button added
NexButton b1 = NexButton(0, 19, "b1");  // Button added
NexButton b4 = NexButton(0, 11, "b4");  // Button added
NexRadio r0 = NexRadio(0, 2, "r0");  // Radio checkbox added
NexRadio r1 = NexRadio(0, 4, "r1");  // Radio checkbox added
NexRadio r2 = NexRadio(0, 6, "r2");  // Radio checkbox added
NexRadio r3 = NexRadio(0, 8, "r3");  // Radio checkbox added
NexRadio r4 = NexRadio(0, 10, "r4");  // Radio checkbox added
NexRadio r5 = NexRadio(0, 12, "r5");  // Radio checkbox added
NexCheckbox c1 = NexCheckbox(0, 30, "c1");  // Checkbox added
NexCheckbox c2 = NexCheckbox(0, 29, "c2");  // Checkbox added
NexNumber slider = NexNumber(0, 13, "n0");

NexPage page0 = NexPage(0, 0, "page0");

NexTouch *nex_listen_list[] =
{
  &b0,  // Button added
  &b1,  // Button added
  &r0,  // Button added
  &r1,  // Dual state button added
  &r2,  // Slider added
  &r3,  // Radio checkbox added
  &r4,  // Radio checkbox added
  &r5,  // Radio checkbox added
  &c1,  // Checkbox added
  &c2,  // Progress bar as a button added
  &page0,  // Page added as a touch event
  NULL  // String terminated
};  // End of touch event list

float temperature = 0.0f;
float humidity = 0.0f;
int sensorValue;
int temp;
int b1cnt = 10;
uint32_t interv = 10000;

unsigned long time_1 = 0;
uint32_t timer;

DHT dht(DHTPIN, DHTTYPE);

void b0PushCallback(void *ptr)
{
  b1cnt = b1cnt - 5;
  interv = b1cnt * 1000;
}





void b1PushCallback(void *ptr)
{
  b1cnt = b1cnt + 5;
  interv = b1cnt * 1000;
}


void setup()
{
  Serial.begin(9600);
  dht.begin();
  pinMode(A0, INPUT);
  pinMode(10, OUTPUT);
  b0.attachPush(b0PushCallback, &b0);
  b1.attachPush(b1PushCallback, &b1);
  timer = millis();
}

void loop() {

  if (millis() > time_1 + interv) {
    time_1 = millis();
    digitalWrite(10, HIGH);
    delay(500);
    sensorValue = analogRead(A0);
    //delay(500);
    digitalWrite(10, LOW);



  }

 if (millis() - timer > 500) {
    Serial.print("n0.val=");
    Serial.print(interv);
    Serial.write(0xff);
    Serial.write(0xff);
    Serial.write(0xff);
  }

  readSensor();
  sendHumidityToNextion();
  sendTemperatureToNextion();
  nexLoop(nex_listen_list);
  // delay(2000);
}

void readSensor()
{

  humidity = dht.readHumidity();
  temperature = dht.readTemperature();
}

void sendHumidityToNextion()
{

  String command = "n6.val=" + String(sensorValue);
  Serial.print(command);
  endNextionCommand();
}

void sendTemperatureToNextion()
{
  String command = "n3.val=" + String(temp);
  Serial.print(command);
  endNextionCommand();
}

void endNextionCommand()
{
  Serial.write(0xff);
  Serial.write(0xff);
  Serial.write(0xff);
}

david_2018:
As for your output on the Nextion, it might help if you could post the complete code, there may be something else causing the odd behavior.

No! Absolutely, there is nothing wrong or 'something else' is odd; the MCU is producing a result that the programmer has wanted and the Nextion is just displaying it?

GolamMostafa:
No! Absolutely, there is nothing wrong or 'something else' is odd; the MCU is producing a result that the programmer has wanted and the Nextion is just displaying it?

I checked in the serial monitor and indeed I see ⸮⸮n0.val=4294936760⸮⸮. At the nextion I see the -30536 value at that moment. How is that possible as it is the same variable being output to the serial monitor as on the Nextion?
The MCU produced 4294936760 and the Nextion displays it differently. So the Nextion somehow translates the value.

The Nextion displayed value of -30536 makes more sense to me considering the range of the -32,768 to 32,767. With 30000+5000 it reaches 32767 and continue from -32,768 upwards.

mrcactus:
I checked in the serial monitor and indeed I see ⸮⸮n0.val=4294936760⸮⸮. At the nextion I see the -30536 value at that moment. How is that possible as it is the same variable being output to the serial monitor as on the Nextion?
The MCU produced 4294936760 and the Nextion displays it differently. So the Nextion somehow translates the value.

The Nextion displayed value of -30536 makes more sense to me considering the range of the -32,768 to 32,767. With 30000+5000 it reaches 32767 and continue from -32,768 upwards.

The root point here in the following quote:

AWOL:
int (16 bit on 8 bit Arduinos), ...

From the above quote, it is understood that the ATmega328P will always use 16-bit 'temporary processing buffer' for processing any data though the ALU size of the MCU is 8-bit, and the content will be viewed in 2's complement form where the MS-Bit is the 'sign' bit. In case, the result is more than 16-bit, the upper part of the result will be discarded unless the compiler is forced through casting to keep it. Now, let us see what has happened in your case:

1. you have declared: int counter = 0;.

2. You have declared: uint32_t longcounter = 0;.

3. you are computing:

counter = counter + 5;
longcounter = counter*1000;

(1) When counter = 30, longcounter = 30*1000 = 30000 = 0x7530 (fits in temporary processing buffer). The data size of destination variable (longcounter) is 32-bit; the compiler will try to provide you 32-bit result, and it is done by filling up the upper 16-bit of the 'longcounter' variable by the 'sign bit' of the lower 16-bit result (7530 = 01110101 0011000; here the sign bit is 0).

(2) When counter = 35, longcounter = 35*1000 = 35000 = 0x88B8.
Applying the reasoning of Step-3.1, we get for longcounter this value: 11111111 11111111 88B8 = 0xFFFF88B8. Note that the sign bit of the lower 16-bit result is: 1 (88B8 - 10001000 10111000).

(3) Now, the execution of Serial.print(longcounter, DEC); command nicely produces the unsigned decimal value of FFFF88BF, which is 4294936760.

4. But, we want 35*1000 = 35000 and not 4294936760. What should we do now?
The compiler has computed 35000 (0x88B8) which is in the 'temporary processing buffer'. Let us force the compiler (called casting) to expand the 'temporary processing buffer' size to 'unsigned 32-bit' so that it matches with the type of destination. Now, the compiler fills up the upper 16-bit of the 'unsigned 32-bit' 'temporary processing buffer' by 0s and not be the 'sign bit' of the lower 16-bit result. Please, see the following codes:

int counter = 0;
uint32_t longcounter = 0;

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

void loop()
{
  counter = counter + 5;
  longcounter = (uint32_t) counter*1000; //will show: 35*1000 = 35000
  //longcounter = counter * 1000;    //will show: 35*1000 = 4294936760
  Serial.print("counter is = "); Serial.println(counter);
  Serial.print("longcounter is = "); Serial.println(longcounter, DEC);
  Serial.println();

  delay(2000);
}

Hope, the point clear on the issue of 35000 versus 4294936760!

5. To investigate the issue of 35000 versus -30536, I need to know about Nextion.h Library; unfortunately, I have don't have the Nextion display device. However, it is understood that:

35000 ---> 0x88B8 ---> 0xFFFF88B8 is being considered as signed number. As a result, we get the following decimal value:
-1*231 + 0x7FFF88B8
==> -2147483648 + 2147453112
==> -30536

@GolamMostafa: thanks for your very clear explanation.

I cleaned up the code and make it meet my requirements:

#include <Nextion.h>

#include <DHT.h>

// Humidity/Temp sensor

#define DHTPIN 8
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);


// Pins

// Moisture Sensor pins

int sensorPin1 = A0;
int sensorPin2 = A1;
int sensorPin3 = A2;
int sensorPin4 = A3;
int sensorPin5 = A4;
int sensorPin6 = A5;

// Moisture Sensor Relais

int sensorRelais = 10;

// Solenoid Relais output pins

int relaisPin1 = 2;
int relaisPin2 = 3;
int relaisPin3 = 4;
int relaisPin4 = 5;
int relaisPin5 = 6;
int relaisPin6 = 7;



///// Variables

byte sensorVal1;
byte sensorVal2;
byte sensorVal3;
byte sensorVal4;
byte sensorVal5;
byte sensorVal6;

byte bedSet1;
byte bedSet2;
byte bedSet3;
byte bedSet4;
byte bedSet5;
byte bedSet6;

byte fanSet;

bool bedWater1;
bool bedWater2;
bool bedWater3;
bool bedWater4;
bool bedWater5;
bool bedWater6;

int sensorMins;
byte waterMins;

unsigned long sensorInterval = 10000;
unsigned long waterInterval = 10000;
unsigned long sensorTimer = 0;
unsigned long printTimer;
unsigned long waterTimer1;
unsigned long waterTimer2;
unsigned long waterTimer3;
unsigned long waterTimer4;
unsigned long waterTimer5;
unsigned long waterTimer6;

int sensorHold = 0;

float temperature = 0.0f;
float humidity = 0.0f;

NexButton b0 = NexButton(0, 16, "b0");
NexButton b1 = NexButton(0, 17, "b1");
NexButton b2 = NexButton(0, 20, "b2");
NexButton b3 = NexButton(0, 21, "b3");
NexButton b4 = NexButton(0, 23, "b4");
NexButton b5 = NexButton(0, 24, "b5");
NexButton b6 = NexButton(0, 26, "b6");
NexButton b7 = NexButton(0, 27, "b7");
NexButton b8 = NexButton(0, 29, "b8");
NexButton b9 = NexButton(0, 30, "b9");
NexButton b10 = NexButton(0, 32, "b10");
NexButton b11 = NexButton(0, 33, "b11");
NexButton b12 = NexButton(0, 35, "b12");
NexButton b13 = NexButton(0, 36, "b13");
NexButton b14 = NexButton(0, 43, "b14");
NexButton b15 = NexButton(0, 44, "b15");
NexButton b16 = NexButton(0, 46, "b16");
NexButton b17 = NexButton(0, 47, "b17");
NexRadio r0 = NexRadio(0, 1, "r0");
NexRadio r1 = NexRadio(0, 2, "r1");
NexRadio r2 = NexRadio(0, 3, "r2");
NexRadio r3 = NexRadio(0, 4, "r3");
NexRadio r4 = NexRadio(0, 5, "r4");
NexRadio r5 = NexRadio(0, 6, "r5");
NexCheckbox c1 = NexCheckbox(0, 14, "c1");
NexCheckbox c2 = NexCheckbox(0, 15, "c2");
NexPage page0 = NexPage(0, 0, "page0");

NexTouch *nex_listen_list[] =
{
  &b0,
  &b1,
  &b2,
  &b3,
  &b4,
  &b5,
  &b6,
  &b7,
  &b8,
  &b9,
  &b10,
  &b11,
  &b12,
  &b13,
  &b14,
  &b15,
  &b16,
  &b17,
  &r0,
  &r1,
  &r2,
  &r3,
  &r4,
  &r5,
  &c1,
  &c2,
  &page0,
  NULL  // String terminated
};  // End of touch event list

// Nextion callbacks

void b0PushCallback(void *ptr)
{
  bedSet1 = bedSet1 - 5;
}


void b1PushCallback(void *ptr)
{
  bedSet1 = bedSet1 + 5;
}

void b2PushCallback(void *ptr)
{
  bedSet2 = bedSet2 - 5;
}


void b3PushCallback(void *ptr)
{
  bedSet2 = bedSet2 + 5;
}

void b4PushCallback(void *ptr)
{
  bedSet3 = bedSet3 - 5;
}


void b5PushCallback(void *ptr)
{
  bedSet3 = bedSet3 + 5;
}

void b6PushCallback(void *ptr)
{
  bedSet4 = bedSet4 - 5;
}


void b7PushCallback(void *ptr)
{
  bedSet4 = bedSet4 + 5;
}

void b8PushCallback(void *ptr)
{
  bedSet5 = bedSet5 - 5;
}


void b9PushCallback(void *ptr)
{
  bedSet5 = bedSet5 + 5;
}

void b10PushCallback(void *ptr)
{
  bedSet6 = bedSet6 - 5;
}


void b11PushCallback(void *ptr)
{
  bedSet6 = bedSet6 + 5;
}

void b12PushCallback(void *ptr)
{
  fanSet = fanSet - 1;
}


void b13PushCallback(void *ptr)
{
  fanSet = fanSet + 1;
}


void b14PushCallback(void *ptr)
{
  sensorMins = sensorMins - 1;
  sensorInterval = sensorMins * 60000;
}



void b15PushCallback(void *ptr)
{
  sensorMins = sensorMins + 1;
  sensorInterval = sensorMins * 60000;
}

void b16PushCallback(void *ptr)
{
  waterMins = waterMins - 1;
  waterInterval = waterMins * 60000;
}



void b17PushCallback(void *ptr)
{
  waterMins = waterMins + 1;
  waterInterval = waterMins * 60000;
}


void setup()
{
  Serial.begin(9600);
  dht.begin();
  pinMode(sensorPin1, INPUT);
  pinMode(sensorPin2, INPUT);
  pinMode(sensorPin3, INPUT);
  pinMode(sensorPin4, INPUT);
  pinMode(sensorPin5, INPUT);
  pinMode(sensorPin6, INPUT);
  pinMode(sensorRelais, OUTPUT);
  pinMode(relaisPin1, OUTPUT);
  pinMode(relaisPin2, OUTPUT);
  pinMode(relaisPin3, OUTPUT);
  pinMode(relaisPin4, OUTPUT);
  pinMode(relaisPin5, OUTPUT);
  pinMode(relaisPin6, OUTPUT);
  pinMode(8, INPUT);
  b0.attachPush(b0PushCallback, &b0);
  b1.attachPush(b1PushCallback, &b1);
  b2.attachPush(b2PushCallback, &b2);
  b3.attachPush(b3PushCallback, &b3);
  b4.attachPush(b4PushCallback, &b4);
  b5.attachPush(b5PushCallback, &b5);
  b6.attachPush(b6PushCallback, &b6);
  b7.attachPush(b7PushCallback, &b7);
  b8.attachPush(b8PushCallback, &b8);
  b9.attachPush(b9PushCallback, &b9);
  b10.attachPush(b10PushCallback, &b10);
  b11.attachPush(b11PushCallback, &b11);
  b12.attachPush(b12PushCallback, &b12);
  b13.attachPush(b13PushCallback, &b13);
  b14.attachPush(b14PushCallback, &b14);
  b15.attachPush(b15PushCallback, &b15);
  b16.attachPush(b16PushCallback, &b16);
  b17.attachPush(b17PushCallback, &b17);
  printTimer = millis();
}

void loop() {

  readSensors();
  printValues();
  activateSolenoids();
  deactivateSolenoids();
  readTemphum();
  nexLoop(nex_listen_list);
}

void readSensors()
{
  if (millis() > sensorTimer + sensorInterval) {
    sensorTimer = millis();
    digitalWrite(sensorRelais, HIGH);
    delay(500);
    sensorVal1 = analogRead(sensorPin1) / 10;
    sensorVal2 = analogRead(sensorPin2) / 10;
    sensorVal3 = analogRead(sensorPin3) / 10;
    sensorVal4 = analogRead(sensorPin4) / 10;
    sensorVal5 = analogRead(sensorPin5) / 10;
    sensorVal6 = analogRead(sensorPin6) / 10;
//    delay(500);
    digitalWrite(sensorRelais, LOW);

  }
}

void readTemphum()
{
  humidity = dht.readHumidity();
  temperature = dht.readTemperature();
}


void activateSolenoids()
{
  if (sensorVal1 < bedSet1) {
    waterTimer1 = millis();
    digitalWrite(relaisPin1, LOW);
  }

  if (sensorVal2 < bedSet2) {
    waterTimer2 = millis();
    digitalWrite(relaisPin2, LOW);
  }

  if (sensorVal3 < bedSet3) {
    waterTimer3 = millis();
    digitalWrite(relaisPin3, LOW);
  }

  if (sensorVal4 < bedSet4) {
    waterTimer4 = millis();
    digitalWrite(relaisPin4, LOW);
  }

  if (sensorVal5 < bedSet5) {
    waterTimer5 = millis();
    digitalWrite(relaisPin5, LOW);
  }

  if (sensorVal6 < bedSet6) {
    waterTimer6 = millis();
    digitalWrite(relaisPin6, LOW);
  }
}


void deactivateSolenoids()
{
  if (millis() > waterTimer1 + waterInterval) {
    digitalWrite(relaisPin1, HIGH);
  }

  if (millis() > waterTimer2 + waterInterval) {
    digitalWrite(relaisPin2, HIGH);
  }


  if (millis() > waterTimer3 + waterInterval) {
    digitalWrite(relaisPin3, HIGH);
  }

  if (millis() > waterTimer4 + waterInterval) {
    digitalWrite(relaisPin4, HIGH);
  }

  if (millis() > waterTimer5 + waterInterval) {
    digitalWrite(relaisPin5, HIGH);
  }

  if (millis() > waterTimer6 + waterInterval) {
    digitalWrite(relaisPin6, HIGH);
  }
}

void printValues()
{

  if (millis() - printTimer > 500) {
    //    printTimer = millis();
    Serial.print("n0.val=");
    Serial.print(bedSet1);
    endNextionCommand();

    Serial.print("n1.val=");
    Serial.print(fanSet);
    endNextionCommand();

    Serial.print("n2.val=");
    Serial.print(bedSet2);
    endNextionCommand();

    Serial.print("n3.val=");
    Serial.print(bedSet3);
    endNextionCommand();

    Serial.print("n4.val=");
    Serial.print(bedSet4);
    endNextionCommand();

    Serial.print("n5.val=");
    Serial.print(bedSet5);
    endNextionCommand();

    Serial.print("n14.val=");
    Serial.print(bedSet6);
    endNextionCommand();

    Serial.print("n6.val=");
    Serial.print(sensorVal1);
    endNextionCommand();

    Serial.print("n9.val=");
    Serial.print(sensorVal2);
    endNextionCommand();

    Serial.print("n7.val=");
    Serial.print(sensorVal3);
    endNextionCommand();

    Serial.print("n10.val=");
    Serial.print(sensorVal4);
    endNextionCommand();

    Serial.print("n8.val=");
    Serial.print(sensorVal5);
    endNextionCommand();

    Serial.print("n11.val=");
    Serial.print(sensorVal6);
    endNextionCommand();

    Serial.print("n15.val=");
    Serial.print(sensorMins);
    endNextionCommand();

    Serial.print("n16.val=");
    Serial.print(waterMins);
    endNextionCommand();

    String command = "humidity.txt=\"" + String(humidity) + "\"";
    Serial.print(command);
    endNextionCommand();

    String command2 = "temperature.txt=\"" + String(temperature) + "\"";
    Serial.print(command2);
    endNextionCommand();
  }

}

void endNextionCommand()
{
  Serial.write(0xff);
  Serial.write(0xff);
  Serial.write(0xff);
}