Aiuto codice per il mio robot

Ciao a tutti, questo fine settimana avendo un po di tempo a mia disposizione mi sono divertito a costruire un piccolo robot rover,
ho montato anche un piccolo display a 16 caratteri con modulo I2C, il display lo gestisco tramite libreria LiquidCrystal_I2C,
ho scritto il primo codice e ho testato il tutto, sembra funzionare tutto abbastanza bene...
Ora vorrei migliorare il codice, in particolare la gestione del display, e la funzione che accendere dei led quando la luce e bassa (Tramite fotoresistenza collegata al PIN A0)
vorrei integrare la funzione millis() per non avere ritardi

Di seguito metto il codice che ho scritto

Scheda 1:

#include <IRremote.h>
#include <SoftwareSerial.h>
#include <Wire.h> 
#include <Servo.h>
#include <LiquidCrystal_I2C.h>
#include "pitches.h"

// BLUETOOTH
const int txPin = 2;
const int rxPin = 3;
SoftwareSerial bluetooth(rxPin, txPin);

// SERVO RUOTE
Servo servo_ruota_destra;   
Servo servo_ruota_sinistra;

// SERVO SENSORE ULTRASUONI
Servo servo_ultrasuoni;

// LED
int led = 7;

// PIEZO
int piezo = 8;
int startMelody[] = {
  NOTE_E4, NOTE_D4, NOTE_E4, 0, NOTE_F4, NOTE_D5, NOTE_C5};
int noteDurations[] = {
  8, 8, 8, 10, 4, 8, 4 };

// CONTROLLO IR
#define tasto_1 0x33B8A05F // AVANTI
#define tasto_2 0x33B8609F // INDIETRO
#define tasto_3 0x33B8E01F // SINISTRA
#define tasto_4 0x33B810EF // DESTRA
#define tasto_5 0x33B820DF // FERMO
#define tasto_6 0x33B8906F // AUMENTA VELOCITA'
#define tasto_7 0x33B850AF // DIMINUISCI VELOCITA'
#define tasto_8 0x33B840BF // START FUNZIONE EVITA OSTACOLI 
#define tasto_9 0x33B8C03F // STOP FUNZIONE EVITA OSTACOLI

const short RECV_PIN = 9;
IRrecv irrecv(RECV_PIN);
decode_results results;

// SENSORE ULTRASUONI HC-SR04
#define trigPin 10
#define echoPin 11
const int distanza_ostacolo = 20;
long duration, distance;
int leftDistance, rightDistance;

// Display LCD
LiquidCrystal_I2C lcd(0x27,16,2);  // set the LCD address to 0x27 for a 16 chars and 2 line display

// SENSORE DI LUCE
int sensore_luce = A0;
int luce = 0;

// SET PRESCALE PORTE ANALOGICHE
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) 
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) 

// VARIABILE PER LA FUNZIONE EVITA OSTACOLI
int funzione_evita_ostacoli = 0;

// VARIABILE PER LA FUNZIONE AUTO-LIGHT
int funzione_auto_light = 0;

// SETUP
void setup() {
  pinMode(led, OUTPUT);
  pinMode(piezo, OUTPUT);
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
  pinMode(sensore_luce, INPUT);
  servo_ruota_destra.attach(4);
  servo_ruota_sinistra.attach(5);
  servo_ultrasuoni.attach(6);
  servo_ruota_destra.write(90);
  servo_ruota_sinistra.write(92);
  servo_ultrasuoni.write(90);
  lcd.init();
  lcd.backlight();
  lcd.print("ARDUROVER-MINI");
  lcd.setCursor(0, 1);
  lcd.print("VERSIONE 1.0");
  for (int thisNote = 0; thisNote < 7; thisNote++) {
    int noteDuration = 1000/noteDurations[thisNote];
    tone(piezo, startMelody[thisNote],noteDuration);
    int pauseBetweenNotes = noteDuration * 1.30;
    delay(pauseBetweenNotes);
    noTone(piezo);
  }
  // Setta  prescale a 32 
  // Riduci la durata della lettura analogica da 128 micros (standard) a 32
  sbi(ADCSRA,ADPS2); 
  cbi(ADCSRA,ADPS1); 
  sbi(ADCSRA,ADPS0);
  // Seriale
  Serial.begin(115200);
  bluetooth.begin(115200);
  Serial.println("Seriali attive...");
  // Avvia la ricezione IR
  //irrecv.enableIRIn();
}

void loop() {
  luce = analogRead(sensore_luce);

  /*-----DEBUG-----*/
  
  // SENSORE DI LUCE
  /*Serial.print("Sensore luce:");
   Serial.println(luce);
   lcd.clear();
   lcd.print("Sensore luce:"); 
   lcd.setCursor(0, 1);
   lcd.print(luce);
   delay(50);*/

  // SENSORE ULTRASUONI HC-SR04
  /*int distance = ping();
  distance = (duration/2) / 29.1;
  if (distance >= 200 || distance <= 0){
    Serial.println("Fuori distanza!");
    lcd.clear();
    lcd.print("Fuori distanza!"); 
  } 
  else {
    Serial.print("DISTANZA:");
    Serial.print(distance);
    Serial.println(" cm");
    lcd.clear();
    lcd.print("Distanza:"); 
    lcd.setCursor(0, 1);
    lcd.print(distance);
    lcd.print("cm");
    delay(50);
  }*/

  /*-----FINE DEBUG-----*/

  // CONTROLLO REMOTO IR
  if (irrecv.decode(&results)) {
    Serial.println("Codice IR:"); 
    Serial.println(results.value, HEX);
    if (results.value == tasto_1) {
      avanti();
    }
    else if (results.value == tasto_2) {
      indietro();
    }
    else if (results.value == tasto_3) {
      sinistra();
    }
    else if (results.value == tasto_4) {
      destra();
    }
    else if (results.value == tasto_5) {
      fermo();
    }
    irrecv.resume();
  }

  // CONTROLLO SERIALE/BLUETOOTH
  byte val;
  if (bluetooth.available()) {  
    val = bluetooth.read();
    if (val == 'w'){
      avanti();
    }  
    else if (val == 'x'){ 
      indietro();
    } 
    else if (val == 'a'){ 
      destra();
    } 
    else if (val == 'd'){
      sinistra(); 
    } 
    else if (val == 's'){ 
      fermo();
    }
    else if (val == 'l'){
      digitalWrite(led, HIGH);
    }
    else if (val == 'L'){
      digitalWrite(led, LOW);
    }
    else if (val == 'c'){
      tone(piezo, NOTE_C5);
      delay(400);
      noTone(piezo);
      delay(100);
      tone(piezo, NOTE_C5);
      delay(300);
      noTone(piezo);
    }
    else if (val == 'o'){
      funzione_auto_light = 1;
    }
    else if (val == 'O'){
      funzione_auto_light = 0;
    }
    else if (val == 'e'){ 
      funzione_evita_ostacoli = 1;
      lcd.clear();
      lcd.print("FUNZIONE");
      lcd.setCursor(0, 1);
      lcd.print("EVITA OSTACOLI");
    }
    else if (val == 'E'){ 
      funzione_evita_ostacoli = 0;
      fermo();
      lcd.clear();
      lcd.print("ARDUROVER-MINI");
      lcd.setCursor(0, 1);
      lcd.print("VERSIONE 1.0");
    }
  }
  // FUNZIONE AUTO-LIGHT
  if (funzione_auto_light == 1) {
    auto_light();
  }
  // FUNZIONE EVITA OSTACOLI
  if (funzione_evita_ostacoli == 1) {
    evita_ostacoli();
  }
}

// SENSORE ULTRASUONI HC-SR04
long ping()
{
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(1000);
  digitalWrite(trigPin, LOW);
  duration = pulseIn(echoPin, HIGH);
  distance = (duration/2) / 29.1;
}

Scheda 2:

// FUNZIONI DI MOVIMENTO
void avanti()
{
  servo_ruota_destra.write(180);
  servo_ruota_sinistra.write(0);
}

void indietro()
{
  servo_ruota_destra.write(0);
  servo_ruota_sinistra.write(180);
}

void destra()
{
  servo_ruota_destra.write(0);
  servo_ruota_sinistra.write(0);
}

void sinistra()
{
  servo_ruota_destra.write(180);
  servo_ruota_sinistra.write(180);

}

void fermo()
{
  servo_ruota_destra.write(90);
  servo_ruota_sinistra.write(92);
}

// FUNZIONE AUTO-LIGHT
void auto_light()
{
if(luce > 900) {
    digitalWrite(led, HIGH);
  } else {
    digitalWrite(led, LOW);
  }
}

// FUNZIONE EVITA OSTACOLI
void evita_ostacoli()
{
  int distanza = ping();
  if (distanza > distanza_ostacolo) {
    avanti();
  } 
  else { 
    fermo();
    servo_ultrasuoni.write(0);
    delay(300);
    rightDistance = ping();
    delay(300);
    servo_ultrasuoni.write(180);
    delay(300);
    leftDistance = ping();
    delay(300);
    servo_ultrasuoni.write(90);
    delay(400);
    compareDistance();
  }
}

void compareDistance()
{
  if (leftDistance>rightDistance)
  {
    indietro();
    delay(300);
    destra();
    delay(400);
    fermo(); 
    delay(100);
  }
  else if (rightDistance>leftDistance)
  {
    indietro();
    delay(300);
    sinistra();
    delay(400);
    fermo(); 
    delay(100);
  } 
  else {
    sinistra();
    delay(600);
    fermo(); 
    delay(100);
  }
}

Se c'è qualcuno che può aiutarmi a migliorarlo accetto tutti i consigli,
avrei anche una domanda riguardo la gestione del display,
in che si fà a cancellare solo una riga sul display senza cancellare tutto?
scrivendo lcd.clear(); si cancella tutto.
Mentre lo scrolling del testo in che modo si fa?

Grazie in anticipo ciao...

lcd.clear cancella tutto lo schermo. Se devi cancellare solo uno o più caratteri basta sovrascriverli con degli spazi vuoti (" ").
Per fare lo scrolling del testo, devi usare una stringa e scrollarla manualmente, spostando l'ultimo carattere a DX in prima posizione a SX.
Esempio:
PREMI IL PULSANTE -1-
-PREMI IL PULSANTE -1
1-PREMI IL PULSANTE -
-1-PREMI IL PULSANTE
1-1PREMI IL PULSANTE
E -1-PREMI IL PULSANT
ecc...

Ciao leo72 grazie per avermi risposto, pensavo ci fosse un stringa per farlo in modo automatico lo scrolling del testo,
non c'è qualche altre libreria che lo faccia in modo automatico che funziona anche con display I2C?
la libreria che si trova nel IDE mi sembra che lo faccia, ma non so come farla funzionare con il mio display I2C.

Ciao.

La lib allegata all'IDE gestisce solo display paralleli con chip HD44780. Un display I2C viene gestito serialmente, spesso il produttore rilascia una lib specifica. Altrimenti devi farlo come ti ho detto, che poi non è difficilissimo. Si tratta solo di spedire ogni tot la stringa scrollata al display.

Ciao leo72 grazie ancora per avermi risposto,
ho un'altro problema sul mio robot c'è anche un ricevitore ir che utilizzo per comandare il robot,
utilizzo la libreria IRremote e penso vada in conflitto con il timer2
non c'è modo di modificare il timer che utilizza la libreria ad esempio utilizzare il timer1?

grazie ciao.

Sì, come ho già detto altre volte si tratta solo di modificare un file della lib (mi sfugge il nome, contiene interrupt mi pare IRremoteInt.h) dove c'è una define che stabilisce quale timer usare, se il 2 o l'1.

Ho cambiato timer2 in timer1 nella libreria IRremote, adesso però mi da errore e non mi compila più perché c'è un conflitto con la libreria tone.h
ho anche un piccolo spiker sul rover, in che modo potrei fare?

Grazie ciao.