Using Wire2 with LCD screens

curt820

New member
I am trying to use Wire2 on my Teensy4.1 to communicate with 4 LCD screens. When I use the scanner code and replace Wire with Wire2 I am able to find all of the screens on the bus, but I am unsure how to communicate with the screens in my code. I tried lcd.init(&Wire2) because I achieved communication on Wire1 by adding &Wire1 in setup but no luck with the screens. I am using Wire and Wire1 to successfully communicate with other sensors but I can't seem to figure this one out. What am I missing? I thought maybe I could run my code faster by using all 3 busses simultaneously as opposed to communicating with all of the sensors and screens on 1 bus. Am I wrong in assuming this?

Code:
#include <Wire.h>
#include <Servo.h>
#include <LiquidCrystal_I2C.h>
#include "Adafruit_MCP9600.h"
#include <Adafruit_Sensor.h>
#include <Adafruit_ADXL345_U.h>


//LCDS
    LiquidCrystal_I2C lcd1(0x24, 20, 4); // << Address 1
    LiquidCrystal_I2C lcd2(0x25, 20, 4); // << Address 1
    LiquidCrystal_I2C lcd3(0x26, 20, 4); // << Address 1
    LiquidCrystal_I2C lcd4(0x27, 20, 4); // << Address 1

//TEMPERATURE SENSORS
    Adafruit_MCP9600 engineTempSensor;
    Adafruit_MCP9600 exhaustTempSensor;
   

//INPUTS
    //FAN
    int fanSpeedPot = 22;
    int fanAuto = 2; //ACTIVE LOW
    
    //THROTTLE
    int throttlePot = 27;
    int throttleAuto = 26; //ACTIVE LOW
    
    //HEATER
    int heaterOnOff = 29;
    int heaterAuto = 28;// ACTIVE LOW

    //NOISE
    int decibelMeter = 14;

    //AFR
    int afr = 15;
    
    

//OUTPUTS
    //FAN
    int fan = 3;
    
    //THROTTLE
    Servo throttle;

    //HEATER
    int heater = 5;


//DATA
    //TEMPERATURE
    float engTemp;
    float exhTemp;

    //AFR
    float afrLevel;

    //NOISE
    float decibelLevel;

//TAGS
    //FAN
    int fanSpeed;

    //HEATER STATE
    int heaterState;

    //THROTTLE POSITION
    int throttlePosition;

void setup() {
  Wire.begin();
  Wire1.begin();
  Wire2.begin();

  lcd1.init();
  lcd2.init();
  lcd3.init();
  lcd4.init();
  lcd1.backlight();
  lcd2.backlight();
  lcd3.backlight();
  lcd4.backlight();
  
  pinMode(fanSpeedPot, INPUT);
  pinMode(fanAuto, INPUT_PULLUP);
  pinMode(throttlePot, INPUT);
  pinMode(throttleAuto, INPUT_PULLUP);
  pinMode(heaterOnOff, INPUT_PULLUP);
  pinMode(heaterAuto, INPUT_PULLUP);
  pinMode(fan, OUTPUT);
  pinMode(heater, OUTPUT);
  pinMode(decibelMeter, INPUT);
  pinMode(afr, INPUT);
  throttle.attach(4);

  Serial.begin(9600);
  Serial5.begin(9600);

  engineTempSensor.begin(0x65, &Wire1);
  exhaustTempSensor.begin(0x66, &Wire1);

  engineTempSensor.setADCresolution(MCP9600_ADCRESOLUTION_18);
  engineTempSensor.setThermocoupleType(MCP9600_TYPE_K);
  engineTempSensor.setFilterCoefficient(3);

  exhaustTempSensor.setADCresolution(MCP9600_ADCRESOLUTION_18);
  exhaustTempSensor.setThermocoupleType(MCP9600_TYPE_K);
  exhaustTempSensor.setFilterCoefficient(3);
}

void loop() {

//FAN
    if(digitalRead(fanAuto) == HIGH){
    fanSpeed = analogRead(fanSpeedPot);
    fanSpeed = map(fanSpeed, 0, 1023, 0, 255);
    analogWrite(fan, fanSpeed);
    }

//HEATER
    if(digitalRead(heaterAuto) == HIGH){
    heaterState = digitalRead(heaterOnOff);
    heaterState = !heaterState;
    digitalWrite(heater, heaterState);
    }

//Throttle
    if(digitalRead(throttleAuto) == HIGH){
    throttlePosition = analogRead(throttlePot);
    throttlePosition = map(throttlePosition, 0, 1023, 0, 180);
    throttle.write(throttlePosition);
    }

//TEMPERATURE
    engTemp = engineTempSensor.readThermocouple();
    exhTemp = exhaustTempSensor.readThermocouple();

//NOISE
    decibelLevel = analogRead(decibelMeter);
    decibelLevel = decibelLevel / 1023;
    decibelLevel = decibelLevel * 50;

//AFR
    afrLevel = analogRead(afr);
    afrLevel = afrLevel * .0306;

  

//LCDS
    //LCD 1
      //ENGINE TEMPERATURE
      lcd1.setCursor(0,0);
      lcd1.print("ENG TEMP: ");
      lcd1.print(engTemp);
      lcd1.print("C  ");
    
      //EXHAUST TEMPERATURE
      lcd1.setCursor(0,1);
      lcd1.print("EXH TEMP: ");
      lcd1.print(exhTemp);
      lcd1.print("C  ");
     
      //ALTERNATOR TEMPERATURE
      lcd1.setCursor(0,2);
      lcd1.print("NOISE: ");
      lcd1.print(decibelLevel);
      lcd1.print("dB  ");
  
      //AFR
      lcd1.setCursor(0,3);
      lcd1.print("AFR: ");
      lcd1.print(afrLevel);
      lcd1.print("/ 1  ");
      

    //LCD 2
      //THROTTLE
      lcd2.setCursor(0,0);
      lcd2.print("THROTTLE: ");
      throttlePosition = map(throttlePosition, 0, 180, 0, 100);
      lcd2.print(throttlePosition);
      lcd2.print("%   ");
    
      //FAN
      lcd2.setCursor(0,1);
      lcd2.print("FAN SPEED: ");
      fanSpeed = map(fanSpeed, 0, 255, 0, 100);
      lcd2.print(fanSpeed);
      lcd2.print("%   ");
      
      //HEATER
      lcd2.setCursor(0,2);
      lcd2.print("HEATER ");
      if(heaterState == HIGH){
        lcd2.print("ON  ");
      }
      else{
      lcd2.print("OFF  ");
      }
  
}
 
Going to make an assumption that you are using the Arduino library: https://github.com/johnrickman/LiquidCrystal_I2C

If that is the case you are going to have to edit the library since it is hard coded to use Wire. For instance in the https://github.com/johnrickman/LiquidCrystal_I2C/blob/master/LiquidCrystal_I2C.cpp file you are going to see things like:
Code:
#define printIIC(args)	Wire.send(args)

So in all the place it has Wire.xxxxxx you will need to change it to Wire2.xxxx. Thats the simplest approach.
 
Going to make an assumption that you are using the Arduino library: https://github.com/johnrickman/LiquidCrystal_I2C

If that is the case you are going to have to edit the library since it is hard coded to use Wire. For instance in the https://github.com/johnrickman/LiquidCrystal_I2C/blob/master/LiquidCrystal_I2C.cpp file you are going to see things like:
Code:
#define printIIC(args)	Wire.send(args)

So in all the place it has Wire.xxxxxx you will need to change it to Wire2.xxxx. Thats the simplest approach.

Also, clone the library to a different name (i.e. something like LiquidCrystal_I2C_Wire2), and then do the replacement. That way if you update your libraries, your version won't get over-written.

It would be nice if the library could be fixed so the constructor has an optional argument to specify a different Wire structure. But a lot of the historical Arduino libraries are riddled with the highlander approach (i.e. there can only be one), since the original AVR's only had one I2C device.
 
Also, clone the library to a different name (i.e. something like LiquidCrystal_I2C_Wire2), and then do the replacement. That way if you update your libraries, your version won't get over-written.

It would be nice if the library could be fixed so the constructor has an optional argument to specify a different Wire structure. But a lot of the historical Arduino libraries are riddled with the highlander approach (i.e. there can only be one), since the original AVR's only had one I2C device.

Agree on both accounts Michael. When I was looking at the library it would be to say the least annoying to make generic.
 
It would be good if someone actually updated the library to allow you to specify which Wire object to use... I have done that for others, but.
Then you look at the library properties and it points to:
https://github.com/johnrickman/LiquidCrystal_I2C

Where the code has not changed for 5 years, and there are lots of issues and PR's.

The readme says that the project is in an archive state and moved:
Status: Archived This repository has been transfered to GitLab at https://gitlab.com/tandembyte/LCD_I2C

Then it looks like you have to join... So I did... And then it cannot find the project. And the user's profile is private.
 
If you do a search of libraries for LiquidCrystal I2C libraries you can turn up several libraries that all are variations on existing Arduino libraries and all are several years old and don't seem to be maintained.

Think if I was going to do port one to use with Teensy would try and find a good one and then rework it to fit what we are doing.
 
Back
Top