Nextion / Arduino: Optimization of code for efficiency & "best practise"

Hi there ::slight_smile: ,

I'm struggling to improve the code of this project. The input of sensors is processed in an Arduino Micro and displayed on a Nextion Display. The GUI offers a settings menu.
Feel free to let me know anything that could be improved for efficiency and spee. Is everything "good practise"?

Thx in advance.

#include <EEPROM.h>
bool beepSwitchOn = EEPROM.read(1);
bool debugSwitchOn = EEPROM.read(2);

unsigned long previousRefreshMillis = 0;
const unsigned long refreshIntervalBattery = 600000;

const float calibrationalConstant = 190;
const int minimum = 10;

const int batteryPin = A5;
const int buzzerPin = 5

const float batteryMaxVoltage = 4.2;
const float batteryMinVoltage = 3.0;

int batteryInput = 860;
int batteryPercentage = 100;

const int batteryLevelLow = (batteryMinVoltage / 5) * 1023;
const int batteryLevelHigh = (batteryMaxVoltage / 5) * 1023;

float sensorData[4][4] = {};

int8_t incomingByte = 0;

void setup() {
  Serial.begin(9600);
  Serial1.begin(9600);
  pinMode(buzzerPin, OUTPUT);
  sensorData[0][0] = A0;
  sensorData[1][0] = A1;
  sensorData[2][0] = A2;
  sensorData[3][0] = A3;
  switchSetup();
  updateBatteryPercentage();
}

void loop() {
  updateSensorValues();
  switchLoop();
  if(debugSwitchOn) {
    debugMode();
  }
  returnData();
}

void switchSetup() {
  if(beepSwitchOn) {
    Serial1.print("bt0.picc=4");
    Serial1.write(0xff)
    Serial1.write(0xff)
    Serial1.write(0xff);
    Serial1.print("ref bt0");
    Serial1.write(0xff);Serial1.write(0xff);Serial1.write(0xff);
    beepbeep();
  } else {
    Serial1.print("bt0.picc=3");
    Serial1.write(0xff);Serial1.write(0xff);Serial1.write(0xff);
    Serial1.print("ref bt0");
    Serial1.write(0xff);Serial1.write(0xff);Serial1.write(0xff);
  }
  if(debugSwitchOn) {
    Serial1.print("bt1.picc=4");
    Serial1.write(0xff);Serial1.write(0xff);Serial1.write(0xff);
    Serial1.print("ref bt1");
    Serial1.write(0xff);Serial1.write(0xff);Serial1.write(0xff);
  } else {
    Serial1.print("bt1.picc=3");
    Serial1.write(0xff);Serial1.write(0xff);Serial1.write(0xff);
    Serial1.print("ref bt1");
    Serial1.write(0xff);Serial1.write(0xff);Serial1.write(0xff);
  }
}

void switchLoop(){
  if(Serial1.available() > 0) {
    delay(200);
    incomingByte = Serial1.read();
    Serial.println(incomingByte);
    if(incomingByte == 2) {
      beepSwitchOn = !beepSwitchOn;
      EEPROM.write(1, beepSwitchOn);
    }
    if(incomingByte == 3) {
      debugSwitchOn = !debugSwitchOn;
      EEPROM.write(2, debugSwitchOn);
    }
  }
}

void updateSensorValues() {
  for (int i = 0; i <= 3; i++) {
    sensorData[i][1] = analogRead(sensorData[i][0]);
    sensorData[i][2] = sensorData[i][1] * (calibrationalConstant / 1023);
    if (sensorData[i][2] > sensorData[i][3] && sensorData[i][2] >= minimum) {
      sensorData[i][3] = sensorData[i][2];
    }
  }
}

void returnData() {
  Serial1.print("t1.txt=");
  Serial1.print("\"");Serial1.print(String(sensorData[0][2], 1));Serial1.print("\"");
  Serial1.write(0xff);Serial1.write(0xff);Serial1.write(0xff);
  Serial1.print("t2.txt=");
  Serial1.print("\"");Serial1.print(String(sensorData[0][3], 1));Serial1.print("\"");
  Serial1.write(0xff);Serial1.write(0xff);Serial1.write(0xff);
  Serial1.print("t5.txt=");
  Serial1.print("\"");Serial1.print(String(sensorData[1][2], 1));Serial1.print("\"");
  Serial1.write(0xff);Serial1.write(0xff);Serial1.write(0xff);
  Serial1.print("t6.txt=");
  Serial1.print("\"");Serial1.print(String(sensorData[1][3], 1));Serial1.print("\"");
  Serial1.write(0xff);Serial1.write(0xff);Serial1.write(0xff);
  Serial1.print("t3.txt=");
  Serial1.print("\"");Serial1.print(String(sensorData[2][2], 1));Serial1.print("\"");
  Serial1.write(0xff);Serial1.write(0xff);Serial1.write(0xff);
  Serial1.print("t4.txt=");
  Serial1.print("\"");Serial1.print(String(sensorData[2][3], 1));Serial1.print("\"");
  Serial1.write(0xff);Serial1.write(0xff);Serial1.write(0xff);
  Serial1.print("t7.txt=");
  Serial1.print("\"");Serial1.print(String(sensorData[3][2], 1));Serial1.print("\"");
  Serial1.write(0xff);Serial1.write(0xff);Serial1.write(0xff);
  Serial1.print("t8.txt=");
  Serial1.print("\"");Serial1.print(String(sensorData[3][3], 1));Serial1.print("\"");
  Serial1.write(0xff);Serial1.write(0xff);Serial1.write(0xff);
  if (millis() - previousRefreshMillis >= refreshIntervalBattery) {
    updateBatteryPercentage();
    previousRefreshMillis = millis();
  }
}

void updateBatteryPercentage() {
  batteryInput = constrain(analogRead(batteryPin), batteryLevelLow, batteryLevelHigh);
  batteryPercentage = map(batteryInput, batteryLevelLow, batteryLevelHigh, 0, 100);
  Serial1.print("j0.val=");
  Serial1.print(batteryPercentage);
  Serial1.write(0xff);Serial1.write(0xff);Serial1.write(0xff);
  Serial1.print("t0.txt=");
  Serial1.print("\"");Serial1.print(batteryPercentage);Serial1.print("\"");
  Serial1.write(0xff);Serial1.write(0xff);Serial1.write(0xff);
}

void debugMode() {
  for (int i = 0; i <= 3; i++) {
    Serial.print("SENSOR ");
    Serial.print(i+1);Serial.print("\t \t");
    Serial.print(sensorData[i][1]);Serial.print("\t \t");
    Serial.print(sensorData[i][2]);Serial.print("\t \t");
    Serial.println(sensorData[i][3]);
  }
}

void beepbeep() {
  digitalWrite(5, HIGH);
  delay(350);
  digitalWrite(5, LOW);
}

How do you want to improve it? Faster? Smaller? Less RAM? Pretty to look at?
What's your compile tell you about memory and size?

DKWatson:
How do you want to improve it? Faster? Smaller? Less RAM? Pretty to look at?
What's your compile tell you about memory and size?

I would like to make it primarily faster und prettier to look at.

One of the functions is blocking another by requiring too much time. I can't listen to incoming data (in the function switchLoop) and print data to the display (in the function returnData) at the same time. If I do, the output is very weird (26 255 255 255 repeatedly).
On their own all functions do as they should.
I would somehow need the functions to "play nice" with each other as multitasking is not possible.

Compiler says:

Sketch uses 21 % of program storage space.
Global variables use 15 % of dynamic memory.

While I'm trying to add a counter based on millis() to call the functions at specific intervals...
... any suggestions on how to make the code more beautiful and faster?

It looks like Nexion displays will run at a much higher baud rate. That's an easy change to get things running faster.

Every call to Serial incurs overhead. You would save much by consolidating your write statements. Make a char array: char array_name[3] = {0xFF, 0xFF, 0xFF} and then replace all your
Serial1.write(0xff);Serial1.write(0xff);Serial1.write(0xff);
with
Serial1.write(array_name, 3);
Try it.

wildbill:
It looks like Nexion displays will run at a much higher baud rate. That's an easy change to get things running faster.

Thank you for your suggestion.
Apparently, only 9600 for the Nextion work.

DKWatson:
Every call to Serial incurs overhead. You would save much by consolidating your write statements.

´

Thank you! I integrated the array :))

I integrated a timer.
The functions will now be called in the loop after 100 ms from the last call.
However, I still get the weird output when running all functions together.

I picked a random nexion display and scanned its data sheet. its UART defaults to 9600 baud, but it will run much faster or somewhat slower. I didn't dig into how you change it or whether perhaps it can autodetect. I rather suspect yours will exhibit similar behavior (unless perhaps it is an ancient model).

Which model do you have?

wildbill:
Which model do you have?

Nextion 3.2" HMI TFT NX4024T032

Perhaps I can't use a higher baud rate because I don't use the nextion library.

Also post new code.

Any ideas on how to get read and write to work at the same time? :confused:

Any ideas on how to get read and write to work at the same time?

The Arduino has one processor. It can NOT do two or more things at the same time. It can do them sequentially fast enough, usually, that they appear to happen "at the same time", but there will always be a measurable interval between two events.

At 9600 baud, it takes approximately 1ms to transmit 1 character. You are refreshing Sensor, Switch and Display every 100ms. Just in updateDisplay(),

Serial1.print("t1.txt="); -> 7 characters
Serial1.print("\""); -> 1 character
Serial1.print(String(sensorData[0][2], 1)); -> ? characters
Serial1.print("\""); -> 1 character
Serial1.write(clear, 3); -> 3 characters

and you do this 8 times. See where this is going?

DKWatson:
See where this is going?

I think I do! :-\
So I need to run the output function less frequently or I could try to get the baud to 115200.

Do you really need to do all that 10 times a second?

DKWatson:
Do you really need to do all that 10 times a second?

Yes!
The sensor input on the display should be live with many refreshes per second.
Reading the value of the switches in the settings menu every 10 seconds would be enough, so I'll change that interval.

I can change the baud rate of the serial port the nextion is connected to with Serial1.print("baud=38400");.
This makes the weird output disappear and the switch values will be transmitted correctly, but the sensor values no longer update on the display... :o

You'll have to find the corresponding command to change the baud rate on the display, both ends need to be the same.

DKWatson:
You'll have to find the corresponding command to change the baud rate on the display, both ends need to be the same.

Serial1.print("baud=38400"); changes the baudrate for the nextion
Serial1.begin(38400); begins the serial for the arduino

I am able to read but not to write, apparently