Problema I2C - Loop se para

Buenos días,

He hecho algunas programaciones en Arduino ya, pero el caso, es que nunca me habia pasado esto.

Con este código el arduino no funciona SIN PANTALLA, y no me explico el porqué.

Con este código, el resultado en el monitor serie es:

13:53:48.569 -> Hasta aquí he llegado

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd2(0x3E, 16, 2);

//int time_check_car_on = 20; // Intervalo de tiempo de comprobación si la furgoneta está encendida (segundos) si hay menos de 13V
//int t_check_car_on = 5; // Tiempo que desconecta y comprueba si la furgonera está ON.

int time_read_values = 2; // tiempo de lectura entre valores toma de valores (segundos)
int time_delay_on_battery = 10;     // T1 - temporización a la conexión del módulo a la alimentación de mechero (segundos)
int time_delay_off_battery = 5*60;  // T2 - temporización a desde que la tensión de "mechero" es inferior a 13V para realizar el "test" de vehiculo encendido (segundos).
int time_delay_check_battery = 5;   // T3 - tiempo de desconexión para compruebar si el vehiculo está ON cuando hay menos de 13V. (segundos)
int time_delay_on_services = 15;    // T4 - temporización a la conexión de los servicios (segundos)
int time_delay_off_services = 2*60; // T5 - temporización a la deconexión de los servicios (segundos)S

unsigned long last_read_values;
//unsigned long last_check_car_on;
unsigned long last_show_values = 2000;
unsigned long last_each_second_services = 1000;
unsigned long last_each_second_battery = 1000;

boolean car_on = false;
boolean check_on = false;
boolean services_on = false;
int delay_on_battery = 0;
int delay_off_battery = 0;
int delay_check_battery = 0;
int delay_on_services = 0;
int delay_off_services = 0;
int battery_relay = 3;
int services_relay = 2;

int van_battery_sensorValue; //lectura digital sensor
float van_battery_voltage;

int box_van_battery_sensorValue; //lectura digital sensor
float box_van_battery_voltage;


void setup() 
{
  Serial.begin(9600);
  Serial.println("Hasta aquí he llegado"); 
  lcd2.init(); //Iniciamos la pantalla // 
  lcd2.backlight(); //Iniciamos el fondo retroiluminado  
  pinMode(battery_relay, OUTPUT);    // sets the digital pin 2 as output
  digitalWrite(battery_relay, LOW);  // sets the digital pin 2 off
  pinMode(services_relay, OUTPUT);    // sets the digital pin 3 as output
  digitalWrite(services_relay, LOW);  // sets the digital pin 2 off
  last_read_values = time_read_values*1000;
  //last_check_car_on = time_check_car_on*1000;
}

void loop() 
{

  if (millis() - last_read_values > (time_read_values*1000)) // Leer valores
  {
    van_battery_sensorValue = analogRead(A4);
    //Convert the analog reading (which goes from 0 - 1023) to a voltage (0 - 5V):
    van_battery_voltage = van_battery_sensorValue * (14.825 / 1023.0);//Ref. 14.84
    if (((digitalRead(battery_relay)) == 1)|| ((digitalRead(services_relay)) == 1)) (van_battery_voltage=van_battery_voltage-0.1);

   
    box_van_battery_sensorValue = analogRead(A5);
    //Convert the analog reading (which goes from 0 - 1023) to a voltage (0 - 5V):
    box_van_battery_voltage = box_van_battery_sensorValue * (15.035 / 1023.0);//Ref. 15.04
    if (((digitalRead(battery_relay)) == 1)|| ((digitalRead(services_relay)) == 1)) (box_van_battery_voltage=box_van_battery_voltage-0.1);
    
    Serial.print("van_battery_sensorValue: ");Serial.println(van_battery_sensorValue);
    Serial.print("van_battery_voltage: ");Serial.print(van_battery_voltage);Serial.println(" V");
    Serial.print("box_van_battery_sensorValue: ");Serial.println(box_van_battery_sensorValue);
    Serial.print("box_van_battery_voltage: ");Serial.print(box_van_battery_voltage);Serial.println(" V");
    Serial.println("");
    
    last_read_values = millis();
  }

 // Comprobar furgo encendida
 // Si tenemos más de 13V, damos por entendido que está funcionando el alternador.
 // Si tenemos menos de 13V, cada x tiempo, "aislamos" para hacer una medición sin el consumo del módulo.

  if (millis() - last_each_second_battery > 1000) // temporización que se repite cada 1 segundo.
  {
    if ((van_battery_voltage >= 13.00) && car_on == false && (check_on == false ) && ~(delay_on_battery == time_delay_on_battery) )
      {delay_on_battery ++;
      delay_off_battery = 0;}
    else if ((van_battery_voltage < 13.00) && car_on == true && (check_on == false ) && ~(delay_off_battery >= time_delay_off_battery))
      {delay_off_battery ++;
      delay_on_battery = 0;}
    else 
      {delay_on_battery = 0;
      delay_off_battery = 0;}


  if (delay_on_battery == time_delay_on_battery ) car_on = true;
  if (delay_off_battery == time_delay_off_battery ) check_on = true;
  if (check_on == true)
    {
      digitalWrite(battery_relay, LOW);
      Serial.print("OSTIA");
      delay_check_battery ++;
      if (delay_check_battery >= time_delay_check_battery)
        {           
              if (van_battery_voltage >= 13.00) car_on = true; else car_on = false;
              delay_check_battery = 0;
              check_on = false;
        }
    }
   
  if (delay_on_battery > time_delay_on_battery) delay_on_battery= 0;
  if (delay_off_battery > time_delay_off_battery) delay_off_battery = 0;
  
  if ((car_on == true ) && (check_on == false )) digitalWrite(battery_relay, HIGH);    
  if (car_on == false ) digitalWrite(battery_relay, LOW);    

    last_each_second_battery = millis();
    }

// Tensión en servicios
    if (millis() - last_each_second_services > 1000)
    {
      if ((box_van_battery_voltage >= 11.00) && services_on == false)
        {delay_on_services ++;
        delay_off_services = 0;}
      else if ((box_van_battery_voltage < 11.00) && services_on == true)
        {delay_off_services ++;
        delay_on_services = 0;}
      else 
        {delay_on_services = 0;
        delay_off_services = 0;}
        
      if (delay_on_services == time_delay_on_services ) services_on = true;
      if (delay_off_services == time_delay_off_services ) services_on = false;
            
      if (delay_on_services > time_delay_on_services) delay_on_services = 0;
      if (delay_off_services > time_delay_off_services) delay_off_services = 0;
      
      if (services_on == true ) digitalWrite(services_relay, HIGH);    
      if (services_on == false ) digitalWrite(services_relay, LOW);    
     
    
    last_each_second_services = millis();
    }

  if (millis() - last_show_values > 4000) // Leer valores
  {
  //Serial.print("Han pasado ");Serial.print((millis() - last_check_car_on)/1000);Serial.println(" segundos");
  Serial.print("Furgo encendida: ");Serial.println(car_on);
  Serial.print("Relé bateria: ");if ((digitalRead(battery_relay)) == 1) Serial.println("On"); else (Serial.println("Off"));
  Serial.print("Servicios habilitados: ");Serial.println(services_on);
  Serial.print("Relé servicios: ");if ((digitalRead(services_relay)) == 1) Serial.println("On"); else (Serial.println("Off"));
  Serial.println("");
    // Resumen estado servicios
  Serial.print("delay to => on servicios : ");Serial.println(delay_on_services);
  Serial.print("delay to => off servicios: ");Serial.println(delay_off_services);
  Serial.println("");  
      // Resumen estado batería furgo
  Serial.print("delay to => on bateria : ");Serial.println(delay_on_battery);
  Serial.print("delay to => off bateria: ");Serial.println(delay_off_battery);
  // resumen del check de furgo encendida:
  Serial.print("¿check on?: ");Serial.println(check_on);
  Serial.print("delay to= > check: ");Serial.println(delay_check_battery);
  Serial.println("");  

  //hueco, linea
  lcd2.setCursor(0, 0);
  lcd2.print("V1:");
  lcd2.print(van_battery_voltage);
  lcd2.print(" V.ON:");
  if (car_on == 1) (lcd2.print("SI "));else (lcd2.print ("NO "));
  lcd2.setCursor(0, 1);
  lcd2.print("V2:");
  lcd2.print(box_van_battery_voltage);
  //lcd2.setCursor(8, 1);
  lcd2.print(" 1K");
  if ((digitalRead(battery_relay)) == 1) (lcd2.print("1"));else (lcd2.print ("0"));
  lcd2.print(" 2K");
  if ((digitalRead(services_relay)) == 1) (lcd2.print("1 "));else (lcd2.print ("0 "));
    
 last_show_values = millis();
  }
}

Si me cargo//comento las líneas

  lcd2.init(); //Iniciamos la pantalla // 
  lcd2.backlight(); //Iniciamos el fondo retroiluminado

el código se ejecuta estupendamente hasta que pido mostrar algo por LCD y ahí se queda.

13:56:48.758 -> Hasta aquí he llegado
13:56:48.758 -> van_battery_sensorValue: 544
13:56:48.791 -> van_battery_voltage: 7.88 V
13:56:48.825 -> box_van_battery_sensorValue: 7
13:56:48.859 -> box_van_battery_voltage: 0.10 V
13:56:48.893 -> 
13:56:48.893 -> Furgo encendida: 0
13:56:48.927 -> Relé bateria: Off
13:56:48.927 -> Servicios habilitados: 0
13:56:48.961 -> Relé servicios: Off
13:56:48.995 -> 
13:56:48.995 -> delay to => on servicios : 0
13:56:49.029 -> delay to => off servicios: 0
13:56:49.063 -> 
13:56:49.063 -> delay to => on bateria : 0
13:56:49.097 -> delay to => off bateria: 0
13:56:49.131 -> ¿check on?: 0
13:56:49.131 -> delay to= > check: 0
13:56:49.131 ->

Yo no quiero tener la pantalla conectada siempre, la idea es que este código funcione( que funciona) sin pantalla, pero me gustaría que si necesito conectar la pantalla en algún momento poder hacerlo, al igual que podría conectar un PC para ver el monitor serie.

Yo pensé que el bus I2C enviaba, si algo lo lee bien, y sino continua la vida...

Además de esto.... pregunto... no hay ningún "error handler" algo como por ejemplo en python o vba... "on error resume next" (si das error, continua el código.. PERO NO TE PARES EDITADO.

Mirá, justo tengo montado un rtc con un display 16x2 i2c.
Probé iniciarlo con el display desconectado y funciona.
Si bien solo puedo escuchar los bips que hace el único pulsador que tiene, responde bien al pulsador, así que el setup lo pasa y las sentencias de impresión en lcd no bloquean el flujo.
Eso si, si conecto el display "sobre la marcha" lo único que responde es el backligth (que es una de las cosas que controlo con el pulsador), texto no sale, imagino porque no se inicializo correctamente el chip del display (sería lo lógico).

En resumen, en mi caso no se bloquea por la falta del display.

¿Cargaste la librería liquidcrystal desde el administrador o la descargaste de otro sitio?

Saludos

PD: Te felicito, tu primer post y está perfectamente publicado.

Moderador:
No se permiten malas palabras ni palabras ofensivas de ningún tipo.
Te envío privado con posibles consecuencias si repites el comentario.

Me quedé pensando que tengo el RTC que también es I2C...

Si el problema lo provocase Wire en lugar de LiquidCrystal, tal vez en mi caso, al estar el RTC, no se bloquea.

Más tarde si puedo cargo algún código solo para el display y quito el RTC del medio a ver que pasa.

Saludos

PD: Me olvidé de tu exabrupto (tiene mucha razón el moderador, o sea @Surbyte ). Retiro los aplausos.

Indica siempre @mos388 de donde has descargado las librerías en uso. Si lo haces del administrador de librerías coloca además a quien pertenece. Autor.
Eso nos permite reproducir tu problema con mayor fidelidad.

Creo que no es posible arrancar como uno quiere. Las cosas o estan o no.
Te podrías ayudar usando una serie de comandos de compilador leyendo por ejemplo algun pin y si esta con jumper hace una cosa y de lo contrario otra.
Imaginemos. Jumper para usar LCD y no jumper para no usarlo y por lo tanto tu versión por defecto.
En el setup pones digamos

// global
int decidoQueHardUso = 0;

void setup() 
{
  Serial.begin(9600);
  Serial.println("Hasta aquí he llegado"); 
  decidoQueHardUso = digitalRead(2); // supongamos que pin 2 libre.
  if (decidoQueHardUso) {
      lcd2.init(); //Iniciamos la pantalla // 
      lcd2.backlight(); //Iniciamos el fondo retroiluminado  
  } 
  pinMode(battery_relay, OUTPUT);    // sets the digital pin 2 as output
  digitalWrite(battery_relay, LOW);  // sets the digital pin 2 off
  pinMode(services_relay, OUTPUT);    // sets the digital pin 3 as output
  digitalWrite(services_relay, LOW);  // sets the digital pin 2 off
  last_read_values = time_read_values*1000;
  //last_check_car_on = time_check_car_on*1000;
}
// repite con 
  if (decidoQueHardUso) {
    // repite esto donde haya lineas lcd.print
  }

NOTA: Hablé de compilador y luego lo resolví sin hacerlo.
Luego mejoro la idea si es posible pero por ahroa no se me ocurrió como manejar el flag para que el compilador vaya por uno u otro lado.

Bueno, acabo de cargar el ejemplo "HelloWorld" de la librería LiquidCrystal_I2C mas "Blink" para tener una indicación visual de que "está vivo" y funciona perfectamente aún con el display desconectado.

Así que descarto que el problema lo generen las librerías.

Saludos

No tiene que ver con el problema o si? haz que estas variables que luego usas con millis() sean unsigned long aunque tus tiempos sean cortos. Evita problemas.

No se como tienes conectados los reles pero esto

digitalWrite(battery_relay, LOW);  // sets the digital pin 2 off

mas que apagar enciende con la conexión habitual.