[SOLVED] Liquidcrystal.h not working with Wire.h

Hello together,

I have a 16pin-LCD and am using the LiquidCrystal.h The display is working fine, but my project for now is: Reading my IMU via I2C and then putting the values on the LCD.

Reading the IMU works. I can read the values via the Serial monitor.

The thing is, I now want to use the display in order to display the values.

Here is some code:

void setup() {
  Serial.begin(9600);
  lcd.begin(16, 2);
  
 // Wire.begin();
 // gyro.enableDefault();
}
  //gyro.readGyro(&gX, &gY, &gZ);
  
  //Low-pass filter
  resX = resX * (1 - weight) + gX * weight;
  resY = resY * (1 - weight) + gY * weight;
  resZ = resZ * (1 - weight) + gZ * weight;
  
  printGyro(&resX, &resY, &resZ, true); //true for Display, false for UART
void printGyro(int16_t *x, int16_t *y, int16_t *z, boolean uselcd){

  if (uselcd){
    lcd.setCursor(0,0);
    sprintf(lcdline1, "Gyro:   X:%5d\0", (int) *x);
    lcd.print(lcdline1);
    sprintf(lcdline2, "Y:%5d Z:%5d\0", (int) *y, (int) *z);
    lcd.setCursor(0,1);
    lcd.print(lcdline2);
    
    
  } else {
    Serial.print("Gyro: ");
    Serial.print("X: ");
    Serial.print((int) *x);
    Serial.print("\t");
    Serial.print("Y: ");
    Serial.print((int) *y);
    Serial.print("\t");
    Serial.print("\t");
    Serial.print("Z: ");
    Serial.println((int) *z); 
  }
}

The thing is, that once I uncomment Wire.begin() in setup() or any other method using a Wire.x()-method, all I get on the display is random dots and characters. The display is a 1602A and I'm using this IMU: http://www.pololu.com/catalog/product/1269

If you need anything else in order to help me, please just ask. From my point of view, the libs are in conflict with each other. Or am I wrong?

Thanks for looking into it :)

Elarion

Edit: Btw. I'm using a Leonardo :)

Probably a coding error. You will have to show all your code if you hope to have anyone help you with that.

Hey,

okay, thanks for your reply :slight_smile:

So here is the code:

#include "L3GD20.h"
#include <LiquidCrystal.h>
#include <Wire.h>


// The Arduino two-wire interface uses a 7-bit number for the address,
// and sets the last bit correctly based on reads and writes
#define L3GD20_ADDR 0x6b

////////////////////////////////////////////////////////////////////////////////
///////////////////////////////// Attribute ////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
L3GD20 gyro;                  //Objekt anlegen
//LiquidCrystal lcd(RS, E, D4, D5, D6, D7);
LiquidCrystal lcd(7, 6, 5, 4, 3, 2);      // put your pin numbers here

char lcdline1[16];
char lcdline2[16];
int16_t gX, gY, gZ;           //Variablen fuer Rotationswerte
int16_t resX = 0;
int16_t resY = 0;
int16_t resZ = 0;
int8_t xOffset = 30;
int8_t yOffset = 30;
int8_t zOffset = 110;
float weight = 1;   //1 = nur neuer Wert geht ein, je geringer, desto mehr Einfluss hat der alte Wert

// Public Methods //////////////////////////////////////////////////////////////
L3GD20::L3GD20() {
  I2CAddr = L3GD20_ADDR;
}

// Turns on the L3GD20's gyro and places it in normal mode.
void L3GD20::enableDefault(void) {
  writeReg(L3GD20_CTRL_REG1, 0x0F); // 0x0F = 0b00001111, normal power mode, all axes enabled
}

// Writes a gyro register
void L3GD20::writeReg(uint8_t reg, uint8_t value) {
  Wire.beginTransmission(I2CAddr);
  Wire.write(reg);
  Wire.write(value);
  Wire.endTransmission();
}


// Reads a gyro register
uint8_t L3GD20::readReg(uint8_t reg) {
  uint8_t value;
  
  Wire.beginTransmission(I2CAddr);
  Wire.write(reg);
  Wire.endTransmission();
  Wire.requestFrom(I2CAddr, 1);
  
  while(!Wire.available());
  
  value = Wire.read();
  Wire.endTransmission();
  
  return value;
}

// Reads the 3 gyro channels
  void L3GD20::readGyro(int16_t *pX, int16_t *pY, int16_t *pZ) {
  Wire.beginTransmission(I2CAddr);
  
  // assert the MSB of the address to get the gyro
  // to do slave-transmit subaddress updating.
  Wire.write(L3GD20_OUT_X_L | (1 << 7));
  Wire.endTransmission();
  Wire.requestFrom(I2CAddr, 6);
  
  while (Wire.available() < 6);
  
  uint8_t xla = Wire.read();
  uint8_t xha = Wire.read();
  uint8_t yla = Wire.read();
  uint8_t yha = Wire.read();
  uint8_t zla = Wire.read();
  uint8_t zha = Wire.read();
  
  *pX = (int16_t)(xha << 8 | xla);
  *pY = (int16_t)(yha << 8 | yla);
  *pZ = (int16_t)(zha << 8 | zla);
}

void printGyro(int16_t *x, int16_t *y, int16_t *z, boolean uselcd){
 
  if (uselcd){
    lcd.setCursor(0,0);
    sprintf(lcdline1, "Gyro:   X:%5d\0", (int) *x);
    lcd.print(lcdline1);
    sprintf(lcdline2, "Y:%5d Z:%5d\0", (int) *y, (int) *z);
    lcd.setCursor(0,1);
    lcd.print(lcdline2);
    
    
  } else {
    Serial.print("Gyro: ");
    Serial.print("X: ");
    Serial.print((int) *x);
    Serial.print("\t");
    Serial.print("Y: ");
    Serial.print((int) *y);
    Serial.print("\t");
    Serial.print("\t");
    Serial.print("Z: ");
    Serial.println((int) *z); 
  }
}


///////////////////////////////////////////////////////////////////////////////
///////////////////           Start of Programm            ////////////////////
///////////////////////////////////////////////////////////////////////////////

void setup() {
  Serial.begin(9600);
  lcd.begin(16, 2);
  
 //Wire.begin();
 //gyro.enableDefault();
}

void loop(){
  //gyro.readGyro(&gX, &gY, &gZ);
  
  //Offsets anpassen
  gX += xOffset;
  gY += yOffset;
  gZ += zOffset;
  
  //Low-pass filter
  resX = resX * (1 - weight) + gX * weight;
  resY = resY * (1 - weight) + gY * weight;
  resZ = resZ * (1 - weight) + gZ * weight;
  
  printGyro(&resX, &resY, &resZ, true); //true fuer Display, false fuer UART
  
  delay(100);
}

And it uses this h-file:

#ifndef L3GD20_h
#define L3GD20_h

#include <Arduino.h> // for byte data type

// register addresses

#define L3GD20_WHO_AM_I 0x0F

#define L3GD20_CTRL_REG1 0x20
#define L3GD20_CTRL_REG2 0x21
#define L3GD20_CTRL_REG3 0x22
#define L3GD20_CTRL_REG4 0x23
#define L3GD20_CTRL_REG5 0x24
#define L3GD20_REFERENCE 0x25
#define L3GD20_OUT_TEMP 0x26
#define L3GD20_STATUS_REG 0x27

#define L3GD20_OUT_X_L 0x28
#define L3GD20_OUT_X_H 0x29
#define L3GD20_OUT_Y_L 0x2A
#define L3GD20_OUT_Y_H 0x2B
#define L3GD20_OUT_Z_L 0x2C
#define L3GD20_OUT_Z_H 0x2D

#define L3GD20_FIFO_CTRL_REG 0x2E
#define L3GD20_FIFO_SRC_REG 0x2F

#define L3GD20_INT1_CFG 0x30
#define L3GD20_INT1_SRC 0x31
#define L3GD20_INT1_THS_XH 0x32
#define L3GD20_INT1_THS_XL 0x33
#define L3GD20_INT1_THS_YH 0x34
#define L3GD20_INT1_THS_YL 0x35
#define L3GD20_INT1_THS_ZH 0x36
#define L3GD20_INT1_THS_ZL 0x37
#define L3GD20_INT1_DURATION 0x38

class L3GD20 {
  public:
  L3GD20();
  
  public:
  void enableDefault(void);
  void readGyro(int16_t *pX, int16_t *pY, int16_t *pZ);
  
  protected:
  void writeReg(uint8_t reg, uint8_t value);
  uint8_t readReg(uint8_t reg);
  
  protected:
  int I2CAddr;
};

#endif

I hope this helps :slight_smile:

Hmm, I found a topic addressing a similar issue:
http://forum.arduino.cc/index.php/topic,39323.0.html

Well, it’s three years old and gives a possible soulution, however it isn’t working for me.
The “bug” has also been reported on google:
http://code.google.com/p/arduino/issues/detail?id=125

Well, in the end changing the constructor doesn’t help…
If a uncomment nothing and change the print-Method to print the results to serial and lcd, serial is working but I can’t get the values on the LCD.

Edit:
I adapted a code snippet at google to create a minimum demonstration:

#include <LiquidCrystal.h>
#include <Wire.h>

LiquidCrystal lcd(12, 11, 5,4,3,2);

void setup() {
  // http://code.google.com/p/arduino/issues/detail?id=125#makechanges
  //Wire.begin();                 // uncomment this line to break the LCD output
  lcd.begin(16,2);              // columns, rows.  use 16,2 for a 16x2 LCD, etc.
  lcd.clear();                  // start with a blank screen
}

void alert(int x, int y, char *fmt, ...) {
  char tmp[200];
  va_list args;
  va_start (args, fmt);
  vsnprintf(tmp, 20, fmt, args);
  va_end (args);

  lcd.setCursor(x,y); // column, row
  lcd.print(tmp);
}

void loop() {
  for (int i=0; i < 100; i++) {
    if (i % 2 == 0) lcd.clear();
    alert(i % 11, i % 2, "i: %d", i);
    delay(1000);
  }
}

As stated in the comments: if I uncomment the Wire.begin, the LCD just shows weird things…

It really sounds like a bug in the libs and not some problem in my little code…
Would buying an I2C-Adapter for the display work?
Something like: http://www.ebay.de/itm/Serial-UART-I2C-SPI-Adapter-fur-1602-1604-2002-2004-4002-LCD-Arduino-AVR-PIC-/370780350886?pt=Bauteile&hash=item56543b29a6

Doh! User error. This is just like the issue #125 response #7 which attempts to use an UNO hardware serial pin for the LCD and then complains it doesn't work when the hardware serial port is initialized.

You have pin collisions between the pins used for the LCD and the I2C pins. Digital Pin 2 and Digital Pin 3 are the SDA and SCL pins on Leonardo. SDA is same pin as digital pin 2 SCL is same pin as digital pin 3. Take a look at the variant file {installdir}/hardware/variants/leonardo/pins_arduno.h

What you have will work on a m328 based "duino" since SDA is digital pin 18 and SCL is digital pin 19.

As far as i2c for the LCD yes it works, but I'd get a PCF8574 based board like this one: http://www.ebay.de/itm/5V-IIC-I2C-TWI-SPI-Serial-Interface-Port-For-Arduino-R3-1602-2004-LCD-Converter-/251214363014?pt=Wissenschaftliche_Ger%C3%A4te&hash=item3a7d8af986 and replace the stock LiquidCrystal library with this one: https://bitbucket.org/fmalpartida/new-liquidcrystal/wiki/Home as it supports 4 bit mode using 6 arduino pins, i2c, and 2 and 3 pin shift register interfaces.

--- bill

Oh my god, yess, you are so correct!!! Thank you so much for your help here!

I also changed my lib to the new lib and now it looks the way I want it :) Thanks again! I should not have been so foolish to believe that SDA and SCL are just the ones labeled with SDA and SCL and not also other ones... dumb error...

Another dumb thing... I thought 6 EUR isn't much, so I already bought the other one... And now I see that your's is cheaper and better xD My fault again :) Well if the other one works too I'm fine with that :)

Cheers :)

i am bumping this thread because i have a similar issue with my leonardo http://forum.arduino.cc/index.php?topic=209135.0 I installed the new liquid crystal display library but the issue i have is not resolved. The only time my code works is when i move the pins of the LCD and leave the 2 and 3 pins free which indeed is conflict issue with the pins. Is there a way i can go around this and use the pins i have in my sketch?

kookoo_gr:
i am bumping this thread because i have a similar issue with my leonardo http://forum.arduino.cc/index.php?topic=209135.0 I installed the new liquid crystal display library but the issue i have is not resolved. The only time my code works is when i move the pins of the LCD and leave the 2 and 3 pins free which indeed is conflict issue with the pins. Is there a way i can go around this and use the pins i have in my sketch?

There is no work around.
As stated above given the way the Arduino team designed the Leonardo,
Arduino digital pins 2 & 3 are the same physical pins as the i2c pins on the leonardo.
Have a look at the pinout diagram in this thread:

It shows which physical pin on the AVR chip that is connected
to each Arduino header pin.
Notice that SCL is physically connected to AVR pin 18 (PD0) which is also conected to Arduino digital pin 2
and SDA is physically connected to AVR pin 19 (PD1) which is also connected to Arduino digital pin 3

So while Arduino digital pin 2 and 3 are different Arduino pins from SCL and SDA,
on a leonardo board they are connected to the same AVR pins.

That means that you can’t use Arduino digital pins 2 & 3 when using i2c on Leonardo.

— bill

U r so useful bperrybap!i had the same problem.thanks :)