Aiuto nella ottimizzazione del codice con la funzione millis

Salve a tutti, sto ultimando un progetto di una dash board per la mia auto, che si interfaccia tramite porta seriale di arduino alla porta OBD 2 della macchina…
In poche parole ho un semplice display TFT sul quale vengono stampate le varie informazione della macchina, esempio: temperatura acqua, giri motore, velocita etc.…
Adesso il mio problema sta nella ottimizzazione del codice, cioè tutto funziona come dovrebbe ma funziona con troppo delay, cioè le informazioni vengono stampate a scatti e con latenza…
Ho provato ad utilizzare la funzione millis, ma ho dubbi nel aver fatto tutto nel modo corretto…
Vi lascio il codice con la speranza che qualcuno mi possa aiutare.

#include <Adafruit_GFX.h>    // Core graphics library
#include <Adafruit_TFTLCD.h> // Hardware-specific library
#include "bitmap_img.h"
#include <OBD.h>
COBD obd;

// OBD PID
int BATTERY;
int RPM;
int SPEED;
int INTAKE;
int COOLANT;
int ENGINE;
int THROTTLE;
int TORQUE;

char rpmString[10];
char speedString[10];

#define LCD_CS A3 // Chip Select goes to Analog 3
#define LCD_CD A2 // Command/Data goes to Analog 2
#define LCD_WR A1 // LCD Write goes to Analog 1
#define LCD_RD A0 // LCD Read goes to Analog 0

#define LCD_RESET A4 // Can alternately just connect to Arduino's reset pin

// Assign human-readable names to some common 16-bit color values:
#define	BLACK   0x0000
#define	BLUE    0x001F
#define	RED     0xF800
#define	GREEN   0x07E0
#define ORANGE  0xFC00
#define CYAN    0x07FF
#define MAGENTA 0xF81F
#define YELLOW  0xFFE0
#define WHITE   0xFFFF

#include <MCUFRIEND_kbv.h>
MCUFRIEND_kbv tft;
// If using the shield, all control and data lines are fixed, and
// a simpler declaration can optionally be used:
// Adafruit_TFTLCD tft;

byte State = 0;
unsigned long previousMillis = 0;
const long interval = 150;
int blink_led = 0;

unsigned long previousMillis1 = 0;
unsigned long interval1 = 10;
unsigned long previousMillis2 = 0;
unsigned long interval2 = 20;
unsigned long previousMillis3 = 0;
unsigned long interval3 = 50;
unsigned long previousMillis4 = 0;
unsigned long interval4 = 200;
unsigned long previousMillis5 = 0;
unsigned long interval5 = 250;
unsigned long previousMillis6 = 0;
unsigned long interval6 = 300;
unsigned long previousMillis7 = 0;
unsigned long interval7 = 350;
unsigned long previousMillis8 = 0;
unsigned long interval8 = 400;
unsigned long previousMillis9 = 0;
unsigned long interval9 = 450;
unsigned long previousMillis10 = 0;
unsigned long interval10 = 500;
unsigned long previousMillis11 = 0;
unsigned long interval11 = 1000;
unsigned int counter = 0;

void setup(void) {
  Serial.begin(9600);
  tft.reset();
  uint16_t identifier = tft.readID();
  tft.begin(identifier);
  tft.setRotation(1);
  tft.fillScreen(BLACK);
  obd.begin();
  while (!obd.init());
  delay(2000);
  // TOP INFO
  tft.fillRoundRect(5, 55, 110, 100, 8, WHITE);
  tft.setCursor(30, 60);
  tft.setTextColor(BLACK);
  tft.setTextSize(2);
  tft.print("WATER");
  tft.fillRoundRect(125, 55, 110, 100, 8, WHITE);
  tft.setCursor(145, 60);
  tft.setTextColor(BLACK);
  tft.setTextSize(2);
  tft.print("INTAKE");
  tft.fillRoundRect(245, 55, 110, 100, 8, WHITE);
  tft.setCursor(265, 60);
  tft.setTextColor(BLACK);
  tft.setTextSize(2);
  tft.print("ENGINE");
  tft.fillRoundRect(365, 55, 110, 100, 8, WHITE);
  
  // BOTTOM INFO
  tft.fillRoundRect(5, 160, 110, 100, 8, WHITE);
  tft.fillRoundRect(125, 160, 110, 100, 8, WHITE);
  tft.fillRoundRect(245, 160, 110, 100, 8, WHITE);
  tft.fillRoundRect(365, 160, 110, 100, 8, WHITE);
  tft.setCursor(380, 165);
  tft.setTextColor(BLACK);
  tft.setTextSize(2);
  tft.print("BATTERY");
  // RPM LED BAR
  tft.drawCircle(20, 25, 16, GREEN);
  tft.drawCircle(60, 25, 16, GREEN);
  tft.drawCircle(100, 25, 16, GREEN);
  tft.drawCircle(140, 25, 16, GREEN);
  tft.drawCircle(180, 25, 16, YELLOW);
  tft.drawCircle(220, 25, 16, YELLOW);
  tft.drawCircle(260, 25, 16, YELLOW);
  tft.drawCircle(300, 25, 16, YELLOW);
  tft.drawCircle(340, 25, 16, RED);
  tft.drawCircle(380, 25, 16, RED);
  tft.drawCircle(420, 25, 16, RED);
  tft.drawCircle(460, 25, 16, RED);

  //extern const uint8_t logo[];
  //tft.setAddrWindow(40, 10, 128, 64);
  //tft.pushColors(logo, 1600, 1);
}

void loop() {
  unsigned long currentMillis = millis();
  /*if (currentMillis - previousMillis > interval) {
    previousMillis = currentMillis;
    if (blink_led == 1) State ^= 1;
  }*/
  // RPM
  if (currentMillis - previousMillis1 > interval1) {
    previousMillis1 = currentMillis;
    if (obd.readPID(PID_RPM, RPM)) {
      obd.readPID(PID_SPEED, SPEED);
    }
    tft.setCursor(10, 270);
    tft.setTextColor(ORANGE, BLACK);
    tft.setTextSize(6);
    if (RPM < 999) {
      tft.print(RPM);
      tft.print(" ");
    } else tft.print(RPM);
  }
  currentMillis = millis();
  // SPEED
  if (currentMillis - previousMillis2 > interval2) {
    previousMillis2 = currentMillis;
    tft.setCursor(365, 270);
    tft.setTextColor(ORANGE, BLACK);    tft.setTextSize(6);
    if (SPEED < 10) {
      tft.print(SPEED);
      tft.print(" ");
    } else tft.print(SPEED);
  }
  currentMillis = millis();
  // RPM LED BAR
  if (currentMillis - previousMillis3 > interval3) {
    previousMillis3 = currentMillis;
    rpm_led();
  }
  currentMillis = millis();
  // WATER
  if (currentMillis - previousMillis4 > interval4) {
    previousMillis4 = currentMillis;
    obd.readPID(PID_COOLANT_TEMP, COOLANT);
    tft.setCursor(30, 90);
    tft.setTextColor(RED, WHITE);
    tft.setTextSize(3);
    if(COOLANT < 99) {
      tft.print(COOLANT);
      tft.print(" ");
    } else tft.print(COOLANT);
  }
  currentMillis = millis();
  // INTAKE
  if (currentMillis - previousMillis5 > interval5) {
    previousMillis5 = currentMillis;
    obd.readPID(PID_INTAKE_TEMP, INTAKE);
    tft.setCursor(145, 90);
    tft.setTextColor(RED, WHITE);
    tft.setTextSize(3);
      if (INTAKE < 10) {
      tft.print(INTAKE);
      tft.print(" ");
      } else tft.print(INTAKE);
  }
  currentMillis = millis();
  // ENGINE
  if (currentMillis - previousMillis6 > interval6) {
    previousMillis6 = currentMillis;
    obd.readPID(PID_ENGINE_LOAD, ENGINE);
    tft.setCursor(265, 90);
    tft.setTextColor(RED, WHITE);
    tft.setTextSize(3);
    if (ENGINE < 10) {
      tft.print(ENGINE);
      tft.print("  ");
    } else tft.print(ENGINE);
  }
  currentMillis = millis();
  if (currentMillis - previousMillis7 > interval7) {
    previousMillis7 = currentMillis;
    //obd.readPID(PID_ENGINE_REF_TORQUE, TORQUE);
    //obd.readPID(PID_THROTTLE, THROTTLE);
  }
  currentMillis = millis();
  // BATTERY VOLTAGE
  if (currentMillis - previousMillis11 > interval11) {
    previousMillis11 = currentMillis;
    tft.setCursor(385, 195);
    tft.setTextColor(RED, WHITE);
    tft.setTextSize(3);
    tft.print(obd.getVoltage(), 1);
  }
}

Non conosco i TFT, quindi non saprei dirti molto, quello che posso dirti sull'uso del millis è che, nel tuo caso, devi leggerlo all'inizio del loop (come hai fatto), e poi utilizzare quel valore per l'intero ciclo, non è necessario rileggerlo prima di ogni confronto, anzi...

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


  if (currentMillis - previousMillis1 > interval1) {
    previousMillis1 = currentMillis;
    //...
  }

  // SPEED
  if (currentMillis - previousMillis2 > interval2) {
    previousMillis2 = currentMillis;
    //...
  }

  //...e così via
}

Federico

A parte il fatto che puoi anche usare direttamente millis(), senza copiarlo in un'altra variabile, non puoi stabilire un intervallo unico, ad esempio una o due volte al secondo, e aggiornare tutti i valori di seguito?

DavidElectroMaker:
con troppo delay, cioè le informazioni vengono stampate a scatti e con latenza…

Se il problema è che si aggiornano a scatti o con troppa latenza anche con millis puoi incappare nel medesimo problema a meno di non aggiornare con frequenza elevata i dati.
In prima battuta proverei ad aggiornare solo se il valore del dato cambia memorizzando in una variabile d'appoggio (una per dato) quello che è stato stampato sul display, se al prossimo giro di loop il valore è il solito non aggiorni il display, altrimenti aggiorni il dato e memorizzi il nuvoo valore.
Se così facendo la frequenza di aggiornamento del display determina sfarfallamenti troppo evidenti o blocchi per eccessivo refresh allora userei la strategia proposta assieme a millis ovvero aggiorno il display se il valore è cambiato e se è trascorso un certo numero di millisecondi dall'ultima volta.
In questo modo se hai dieci grandezze da stampare ma solo una di esse si aggiorna molto rapidamente le altre nove non scriveranno mai sul display determinando comunque un miglioramento delle performance del sistema.

Grazie a tutti per la risposta, il problema principale è la necessità di aggiornare i dati quali: giri motore, velocità, è una barra che si accende in base hai giri motore, questi devono essere più o meno in tempo reale, anche perché nn avrebbe senso altrimenti... Per quando riguarda il resto dei dati non mi serve aggiornarlo in tempo reale ma potrei anche aggiornarlo tipo una volta ogni mezzo secondo o una volta ogni secondo...

Allora fai una temporizzazione a 0,1 secondi per la barra e una a 0,5 per il resto. Forse è anche meglio 0,2 e 1. L'importante è che nulla blocchi il loop in attesa di dati.