LCD I2C Library interfering with serial?

Hi everyone,

Been having some trouble with my sketch (I'll post the parts in question tomorrow) and I've narrowed it down to the I2C LCD library (downloaded here) is causing me some trouble to communicate / receive serial data.

Have anyone ever run into the same kind of problems before? Did a search on the forum but couldn't find anything like it...

Thanks for the help!

Marc

Is the LCD I2C or serial (does it connect to A4 & A5 or does it connect to RX & TX)? How about a link to the LCD datasheet? Which I2C lcd library, there is more than one? Define trouble, like no display, row of black squares, etc.

So here's the link to the LCD :

It is indeed a IIC and I connect to SDA / SCL pins (not A4/A5 on the mega but same purpose). The version of my LCD is version2.

How I narrowed it down is by having a serial routine extracting couple of bytes from a received frame (the TX sender is an external module constantly emitting, no CTS, no RTS etc...) and it didn't work until I removed the display part / library from my sketch.
On the LCD I had random texts but nothing readable.

When I use the test sketch alone from the link above, no problem, when I add the serial, outputting random text. AND serial sketch on it's own, no problem...

Post the code. The whole sketch. In code tags, please.

1/2

#include <Servo.h> 
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <PID_v1.h>
#include <TimerOne.h>

LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);  // Sets the LCD I2C address

Servo servo1;            // Engagement servo declaration   
Servo motor1;            // Starter motor declaration

// PIN affectation
const int start = 14;     //Start button
//const int Emerg = 18;     //Emergency stop button
const int PPump = 45;     //Preheat pump PWM motor driver
const int servo = 42;     //PWM output for starter motor engagement servo
const int motor = 43;     //PWM output for starter motor speed (controls the ESC)
const int modeventil = 3;    //Mode Ventilation switch (HIGH=ON)    15K PULLDOWN INSTALLED
const int modestart = 4;    //Mode Start switch (HIGH=ON)           15K PULLDOWN INSTALLED
const int spark = 34;       //Spark module relay   (LOW=ON)
const int drain = 35;       // Drain Valves relay  (LOW=ON)
const int led = 19;        //status led
const int LED1=22;         //LED1 = STATUS (blinking)
const int LED2=23;         //LED2 = Spark
const int LED3=24;         //LED3 = Servo + Starter Motor
const int LED4=25;         //LED4 = PreHeatPump (PPump)
const int LEDstart=20;     //LED bouton start blinking

double Setpoint, Input, Output;

const long t1 = 0;    //phase 1 duration in ms
const long t2 = 5000;    //phase 2 duration in ms
const long t3 = 6000;    //phase 3 duration in ms
const long t4 = 25000;    //phase 4 duration in ms
const long t5 = 30000;    //phase 5 duration in ms

const long tv = 40;  //ventilation in s

const int v1=5;       //STAND-BY Starter motor Speed (0RPM)
const int v2=50;      //MID starter motor speed (3000RPM)
const int v3=90;      //MAX starter motor speed  (~18000RPM)

int rampstepup=100;        //timestep between two incrementations of Starter motor speed
int rampstepdown=100;      //timestep between two decrementations of PreheatPumpMotor speed
int vtemp=0;             //speed variable to increment the starter motor speed with a ramp
int rampx=0;             //time variable to increment the starter motor speed with a ramp

unsigned long sequencestart = 0;        //Time variables
unsigned long previousMillis=0;
unsigned long currentMillis=0;
unsigned long test3s=0;
int blinkperiod = 200;                  //LED blink period (200ms=5Hz)

boolean sequence_auth=false;       //start authorization flag
boolean sequence_running=false;    //sequence running flag
boolean modeswpos=HIGH;            //mode switch reading : Ventilation=HIGH ; Start=LOW
int state=0;                       //State indicator (will be used to display which phase it is in on the LCD
int pin=0;

int read_state = 1;   //for RS232 Serial communication with FADEC
int readindex = 0;    //for RS232 Serial communication with FADEC
byte trame[48];       //for RS232 Serial communication with FADEC
int i;                //for RS232 Serial communication with FADEC
int egt=0;            //Exhaust gas temperature reading from FADEC
long int RPMN2=0;

unsigned long degt; //time value to "debounce" egt overheat

PID Preheat(&Input, &Output, &Setpoint,2,5,1, DIRECT);



void setup() {      

  digitalWrite(spark,HIGH);    //Switching off Spark relay
  digitalWrite(drain,HIGH);    //Switching off drain relay
  lcd.begin(20,4);   // initialize the lcd for 20 chars 4 lines,  on backlight

  servo1.attach(servo);
  motor1.attach(motor);
  Serial.begin(19200);    //Initializing serial communication with PC (via USB)
  Serial2.begin(2400);    //Initializing the serial communication with the FADEC

  Input=egt;
  Setpoint=250;
  Preheat.SetMode(AUTOMATIC);
  SetOutputLimits(64, 255)    //setting limits to PID outputs

    pinMode(motor, OUTPUT);
  pinMode(start, INPUT); 
  // pinMode(Emerg, INPUT);  
  pinMode(PPump, OUTPUT);
  pinMode(servo, OUTPUT);
  pinMode(modeventil, INPUT);
  pinMode(modestart, INPUT);
  pinMode(spark, OUTPUT);
  pinMode(LED1, OUTPUT);
  pinMode(LED2, OUTPUT);
  pinMode(LED3, OUTPUT);
  pinMode(LED4, OUTPUT);
  digitalWrite(LED1,LOW);      //Lighting the LEDS 1s @ startup (test)
  digitalWrite(LED2,LOW);      //Lighting the LEDS 1s @ startup (test)
  digitalWrite(LED3,LOW);      //Lighting the LEDS 1s @ startup (test)
  digitalWrite(LED4,LOW);      //Lighting the LEDS 1s @ startup (test)
  delay(1000);
  digitalWrite(LED1,HIGH);
  digitalWrite(LED2,HIGH);
  digitalWrite(LED3,HIGH);
  digitalWrite(LED4,HIGH);

  motor1.write(v1);    //Starter Motor ESC STAND-BY

  rampstepup=((t4-t3-1000)/(v3-v2));    //calculating the time step for each +1 speed step #STARTER MOTOR RAMP

  //SPLASH SCREEN
  lcd.backlight();
  delay(250);
  lcd.noBacklight();
  delay(250);
  lcd.backlight();
  lcd.setCursor(0,0);
  lcd.print("xxx Technologies");
  lcd.setCursor(0,3);
  lcd.print("Test Test");
  delay(1000);  
  lcd.clear();
  lcd.setCursor(0,1);
  lcd.print("     READY?        ");
  delay(1000);
  lcd.setCursor(0,3); 
  lcd.print("      GO!        ");
  lcd.clear();

}

void loop() 
{
  currentMillis=millis();
  read_fadec ();
  pollswitch ();
  safety3s ();
  launchpad ();
  tmonitoring();

}

//Polling the switch so that you can't change the sequence while running
void pollswitch ()
{
  if (sequence_auth==false && sequence_running==false /* && state!=10 && state!=11 && state!=2 */)
  {
    if(digitalRead(modestart)==HIGH)
    {
      modeswpos=HIGH;
      state=1;
    }
    else
    {
      if(digitalRead(modeventil)==HIGH)
      {
        modeswpos=LOW;
      }
    }
  }

}


//Temperature monitoring to stop everything in case of an overtemperature 
void tmonitoring ()
{
  if ((egt > 850) && degt==0)
  {
    degt = currentMillis;
  }

  if (degt!=0 && millis()-degt>500)
  {
    if(egt>850){
      overheatstop();
    }
    else if(egt<650){
      degt=0;
    }
  }
}


//Requires to press 3seconds the start button (and keep it pressed) before any action is taken.
void safety3s ()
{
  if (sequence_auth==false && sequence_running==false && digitalRead(start)==HIGH)
  {
    state=2;
    digitalWrite(LED1,LOW);  //Lighting LED1 while waiting the 3seconds
    ledState=LOW;


    if ((currentMillis-test3s)>3000 && digitalRead(start)==HIGH)
    {
      sequence_auth=true;
      if(sequence_running==false);
      {      
        sequencestart=currentMillis;
      }
    }
  }
  else{
    test3s=currentMillis;    //if test3s = currentMillis, it can never reach the 3seconds...

    if(digitalRead(start)==HIGH)  //Blinking LED1 during Start button pressed and sequence running
    {
      if(currentMillis - previousMillis > blinkperiod) {
        previousMillis = currentMillis;   
        if (ledState == LOW)
          ledState = HIGH;
        else
          ledState = LOW;
        digitalWrite(LED1, ledState);
      }
    }
  }
  if(digitalRead(start)==LOW && state!=10 && state!=11)
  {
    sequence_auth=false;
    digitalWrite(LED1,HIGH);
    motor1.write(0);
    servo1.write(0);
    analogWrite(PPump,0);
    digitalWrite(spark,HIGH);
    digitalWrite(drain,HIGH);
    state=1;
  }
}



//SEQUENCE CHOICE AND LAUNCH
void launchpad()
{
  switch (modeswpos)
  {
  case LOW:
    startsequence();
    break;
  case HIGH:
    ventilation();
    break;
  }
}

2/2

//START SEQUENCE
void startsequence()
{
  //PHASE 2 : 0-5(t2)seconds
  if (digitalRead(start)==HIGH && (millis()-sequencestart)<t2)
  {
    sequence_running=true;
    digitalWrite(spark,HIGH);  //spark / glow plug OFF
    servo1.write(95);          //Commanding servo to engage Starter motor
    digitalWrite(LED2,LOW);    //LED2 (Spark indicator) ON
    motor1.write(v2);          //running the starter motor @ 3000RPM
    digitalWrite(drain,LOW);   //Drain relay ON, drains OPEN.
    state=3;
  }

  else        //PHASE 3 : 5-6seconds (IGNITOR ON)
  {
    if (digitalRead(start)==HIGH && (millis()-sequencestart)<t3)
    {
      sequence_running=true;
      digitalWrite(spark,LOW);      //spark module ON
      digitalWrite(drain,HIGH);      //Drain relay OFF / drains closed
      servo1.write(95);
      motor1.write(v2);
      digitalWrite(LED2,LOW);
      analogWrite(PPump,255);
      digitalWrite(LED3,LOW);
      state=4;
    }

    else  //PHASE 4 : 6-25seconds
    {         
      if (digitalRead(start)==HIGH && (millis()-sequencestart)<t4)
      {
        digitalWrite(spark,HIGH);      //SPARK module OFF
        digitalWrite(drain,HIGH);      //Drain relay OFF / drains closed
        servo1.write(95);
        digitalWrite(LED2,HIGH);
        state=5;

        //RAMP2
        if((millis()-rampx)>rampstepup && vtemp<v3 && (millis()-sequencestart<(t4)))
        {
          vtemp=vtemp+1;
          motor1.write(vtemp);
          rampx=millis();
        }      
        else
        {
          motor1.write(vtemp);
        }
        //RAMP2

        Input=egt;
        Preheat.Compute();
        analogWrite(PPump,Output);
        int xxx=255-Output;          //LEDs being negative sunk, PWM has to be inverted.
        analogWrite(LED4,xxx);
        rampstepdown=((t5-t4)/(Output));
      }

      else  //PHASE 5 25-30seconds
      {
        if (digitalRead(start)==HIGH && (millis()-sequencestart)<t5)
        {
          motor1.write(5);
          digitalWrite(LED2,HIGH);
          digitalWrite(spark,HIGH);
          digitalWrite(LED3,HIGH);
          state=6;
          servo1.write(0);

          //RAMPING PPump down
          if((millis()-rampx)>rampstepdown && vtemp>=0 && (millis()-sequencestart<(t5)))
          {
            vtemp=vtemp-1;
            analogWrite(PPump,vtemp);
            int xxx=255-vtemp;          //LEDs being negative sunk, PWM has to be inverted.
            analogWrite(LED4,xxx);
            rampx=millis();
          }      
          else
          {
            analogWrite(PPump,vtemp);
          }


        }
        else
        {
          if (sequence_running==true && sequence_auth == true)
          {
            while(digitalRead(start)==HIGH)
            {
              state=7;      //Waiting for operator to release start button
            }
            sequence_auth=false;
            sequence_running=false;
            motor1.write(5);
            servo1.write(0);
            analogWrite(PPump,0);
            digitalWrite(spark,HIGH);
          }
        }   

      }
    } 
  }

}





//VENTILATION
void ventilation()
{
  //PHASE 1 : continuous
  if (sequence_auth==true && digitalRead(start)==HIGH)

  {
    sequence_running=true;
    servo1.write(95);
    motor1.write(50);        //Ventilating the engine @3000RPM
    digitalWrite(drain,LOW)  //Draining excess fuel
      state=8;
  }

  else
  {
    {
      state=9;
      sequence_running=false;
      motor1.write(5);
      servo1.write(0);
      analogWrite(PPump,0);
      digitalWrite(spark,HIGH);
      digitalWrite(drain,HIGH);
    }
  }

}



void overheatstop()

{
  lcd.setCursor(0,3);
  lcd.print("OVERHEAT!");
  sequence_auth=false;
  state=10;

  if (servo1.read()>45)
  {
    servo1.write(95);
    analogWrite(PPump,0);
    digitalWrite(spark,HIGH);
    digitalWrite(drain, LOW);  //Draining excess fuel    
    motor1.write(64);          //Ventilating @4000RPM
    delay(5000);
    state=1;
    sequence_running=false;
  }
  else
  {
    emergstop();
  }
}

void emergstop()
{
  sequence_auth=false;
  state=11;
  motor1.write(5);
  servo1.write(0);
  analogWrite(PPump,0);
  digitalWrite(spark,HIGH);
  lcd.clear();
  lcd.setCursor(0,3);
  lcd.print("EMERGENCY STOP!");
  delay(2000);
  state=1;
  sequence_running=false;

}

void read_fadec () //extracting temperature and speed informations from FADEC RS232 frames
{
  byte buffer;

  if (Serial2.available()>0)
  {
    buffer = Serial2.read();

    switch (read_state) {
    case 1:
      if (buffer == 252) {
        read_state = 2;
        // debut de trame, on se prepare a recevoir
        readindex = 0;
        break;
      }

    case 2:
      if (buffer == 253) {
        read_state = 3;
      }
      else {
        // mauvaise synchro, on reset 
        read_state = 2;
      }

      break;

    case 3:
      trame[readindex] = buffer;

      if (readindex >= 47) {
        // on a eu le dernier byte
        //for(int i=0;i<47;i++)
        //{
        Serial.print("vitesse : ");
        Serial.print(trame[37]); 
        Serial.println("000 RPM");
        RPMN2 = word (trame[47],trame[46]);
        Serial.print(RPMN2);
        Serial.println("00 RPM");
        Serial.print("Temperature : "); 
        Serial.println(trame[43]*4);
        egt=(trame[43]*4);
        Serial.println(Output);
        Serial.println();
        //}
        read_state = 1;
      }

      readindex ++;
      break;

    }
  }
}

That is the whole sketch...

Sorry for the real programmers out there, have never coded in my life before tinkering with Arduinos (and I have to say I like it!), I know it's not up to your (or any kind...) of standard!

So anyway, when I'm removing all the LCD_I2C related code, everything works correctly, I get my Temperature and speed reading from my FADEC. But as soon as I put it back... not working!

I am not familiar with the Mega, but you have pins 0 and 1 assigned to the LCD. Are those not the RX and TX for the serial port used by USB?

LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);  // Sets the LCD I2C address

mmm... you're right about 0 and 1 being the serial pins but this is a declaration for library so it does not point to arduino pins but to LCD controller pins or so.
I'm only using 2 pins (SDA & SCL) to control the LCD.

You are absolutely right. Those are the I2C expander pins. Nothing to do with serial.