I2C 20x4 and LiquidCrystal_I2C library issue

Hi,

I'm following this tutorial https://www.instructables.com/id/How-to-Connect-I2C-Lcd-Display-to-Arduino-Uno/

Only difference is that I use another LCD with the following specs:

Specification:

Supply voltage: 5V
Interface: I2C
I2C address: 0x27 or 0x3F
Pin definition: GND, VCC, SDA, SCL
Contrast adjust: potentiometer
The module is a low-power consumption character LCD module with a built-in controller
The module can be easily interfaced with a MCU
Display format: 20 Characters x 4 lines
Fully assembled and tested serial LCD 20 x 4 module
White text, blue backlight
It is fantastic for Arduino based project
Size: 9.8 x 6 x 1.2mm

I ran an I2C scan I can confirm my screen is at 0x27

When I run this code

/* www.learningbuz.com */
/*Impport following Libraries*/
#include <Wire.h> 
#include <LiquidCrystal_I2C.h>
//I2C pins declaration
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); 

void setup() 
{

lcd.begin(16,2);//Defining 16 columns and 2 rows of lcd display
lcd.backlight();//To Power ON the back light
//lcd.backlight();// To Power OFF the back light

}

void loop() 
{
//Write your code
lcd.setCursor(0,0); //Defining positon to write from first row,first column .
lcd.print(" Tech Maker "); //You can write 16 Characters per line .
delay(1000);//Delay used to give a dynamic effect
lcd.setCursor(0,1);  //Defining positon to write from second row,first column .
lcd.print("Like | Share");
delay(8000); 

lcd.clear();//Clean the screen
lcd.setCursor(0,0); 
lcd.print(" SUBSCRIBE ");
lcd.setCursor(0,1);
lcd.print(" TECH MAKER ");
delay(8000); 
}

I get this error message

I2C_LCD_TUTORIAL:6: error: 'POSITIVE' was not declared in this scope
 LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); 
                                                     ^
exit status 1
'POSITIVE' was not declared in this scope

I've searched the forum but I'm not sure about how to solve this issue, it looks like the library isn't recognized even if I have LiquidCristal I2C by Frank de Bradander v 1.1.2 installed

Thanks for your help

This sort of thing is usually a mismatch between the library and the example you are using. Lots of libraries exist and they may have subtle differences in parameters etc. Look in the library to see if it has its own example sketches and use one of those.

Filter out the I2C parts of my code below! I use a different library that works excellent. Just change the setup from 16 * 2 to 20 * 4! The hd44780 library is super!

#include<arduino.h>
#include <SMT172.h>

//I2C for LCD
//boolean debug = false;

#include <SoftwareSerial.h>

#include <Wire.h>
#include <hd44780.h>
#include <hd44780ioClass/hd44780_I2Cexp.h>

//#define BACKLIGHT_PIN     13

hd44780_I2Cexp mylcd; // declare lcd object: auto locate & config exapander chip

// LCD geometry
#define LCD_COLS 16
#define LCD_ROWS 2

// The TinyGPS++ object

uint32_t LastSensorUpdate;
unsigned long sec_1_diff_measure_time;
unsigned long sec_10_diff_measure_time;
unsigned long minute_1_diff_measure_time;
unsigned long minute_10_diff_measure_time;
float sec_1_diff_measure_data = -1.1;
float sec_10_diff_measure_data = -1.1;
float minute_1_diff_measure_data = -1.1;
float minute_10_diff_measure_data = -1.1;


//The setup function is called once at startup of the sketch
void setup() {
  unsigned long tmp_millis;
  pinMode(8, INPUT_PULLUP);
  pinMode(12, OUTPUT);
  pinMode(3, OUTPUT);
  digitalWrite(3, LOW);
  Serial.begin(115200);
  Serial.println(F("Demo sketch SMT172"));

  //	The following code fragment sets up phase-correct PWM on pins 3 and 11 (Timer 2).
  //	The waveform generation mode bits WGM are set to to 001 for phase-correct PWM.
  //	The other bits are the same as for fast PWM.

  //  pinMode(3, OUTPUT);
  //  pinMode(11, OUTPUT);
  TCCR2A = _BV(COM2A1) | _BV(COM2B1) | _BV(WGM20);
  // TCCR2B = _BV(CS22); // Output frequency: 16 MHz / 64 / 255 / 2 =  490.196 Hz
  TCCR2B = _BV(CS21); // Output frequency: 16 MHz /  8 / 255 / 2 = 3921.569 Hz
  OCR2A = 237; // Output A duty cycle: 237 / 255 = 92.94%	= 129.58 C	on pin 11
  OCR2B = 28;	 // Output B duty cycle:  28 / 255 = 10.98%	= -45.06 C	on pin 3

  //Send temp via I2C to LCD
  int status;

  status = mylcd.begin(LCD_COLS, LCD_ROWS);
  if (status) // non zero status means it was unsuccesful
  {
    status = -status; // convert negative status value to positive number

    // begin() failed so blink error code using the onboard LED if possible
    hd44780::fatalError(status); // does not return
  }
  mylcd.clear();
  // initalization was successful, the backlight should be on now

  // Print start message to the LCD
  mylcd.print("Started");
  sec_1_diff_measure_time = tmp_millis + 1000;
  sec_10_diff_measure_time =    tmp_millis + 10000;
  minute_1_diff_measure_time =  tmp_millis + 60000;
  minute_10_diff_measure_time = tmp_millis + 600000;
  //  mylcd.setCursor(12, 2); mylcd.print(minute_1_diff_measure_time / 1000);
}

// The loop function is called in an endless loop
void loop()
{
  float tmp_temp;
  unsigned long mill_tmp;
  if ((millis() % 100) > 75)
    digitalWrite(3, LOW);
  else
    digitalWrite(3, HIGH);

  // read the sensor every 250 millisecond
  if ((unsigned long) (millis() - LastSensorUpdate) >= 500)
  {
    LastSensorUpdate = millis();

    SMT172::startTemperature(0.002);

repeat:
    switch (SMT172::getStatus()) {
      case 0: goto repeat; // O Dijkstra, be merciful onto me, for I have sinned against you :)
      case 1:
        //		    Serial.print(F("Measuring time   [ms]: "));
        //				Serial.println(SMT172::getTime() * 1e3, 2); // convert to milliseconds
        //				Serial.print(F("Sensor frequency [Hz]: "));
        //				Serial.println(SMT172::getFrequency(), 2);
        //				Serial.print(F("Duty cycle        [%]: "));
        //				Serial.println(SMT172::getDutyCycle() * 100, 2);

        tmp_temp = SMT172::getTemperature();
        mill_tmp = millis();

        //        Serial.print(F("Temperature       [C]: "));
        //        Serial.println(tmp_temp, 2);

        mylcd.setCursor(0, 0);
        mylcd.print(tmp_temp, 2);
        //        mylcd.print(F(" [C]"));
        mylcd.print(" [C]");

        /*        if (tmp_temp > 30.0 )
                {
                  Serial.println(tmp_temp);
                  mylcd.setCursor(0, 0);
                  mylcd.print(F("Err. [C]: "));
                  mylcd.print(tmp_temp, 4);
                }
        */
        if (sec_1_diff_measure_data < 0.0)//Initiate
        {
          sec_1_diff_measure_data = tmp_temp;
          sec_10_diff_measure_data = tmp_temp;
          minute_1_diff_measure_data = tmp_temp;
          minute_10_diff_measure_data = tmp_temp;
          sec_1_diff_measure_time = mill_tmp + 1000;
          sec_10_diff_measure_time = mill_tmp + 10000;
          minute_1_diff_measure_time = mill_tmp + 60000;
          minute_10_diff_measure_time = mill_tmp + 600000;
        }
        else
        {
          if (mill_tmp > sec_1_diff_measure_time )
          {
            //        Serial.print("1  Sec value "); Serial.print(tmp_temp);Serial .print(" ");Serial.println(mill_tmp/1000);
            sec_1_diff_measure_time = mill_tmp + 1 * 1000;//Set next measure time
            mylcd.setCursor(10, 0); mylcd.print("      ");
            mylcd.setCursor(10, 0); mylcd.print(tmp_temp - sec_1_diff_measure_data, 2); // mylcd.print(" ");
            sec_1_diff_measure_data = tmp_temp;
          }

          if (mill_tmp > sec_10_diff_measure_time )
          {
            Serial.print("10 Sec value "); Serial.print(tmp_temp); Serial .print(" "); Serial.println(mill_tmp / 1000);
            sec_10_diff_measure_time = mill_tmp + 10 * 1000;//Set next measure time
            mylcd.setCursor(0, 1); mylcd.print("      ");
            mylcd.setCursor(0, 1); mylcd.print(tmp_temp - sec_10_diff_measure_data, 2);// mylcd.print(" ");
            sec_10_diff_measure_data = tmp_temp;
          }
          if (mill_tmp > minute_1_diff_measure_time )
          {
            Serial.print("1  Min value "); Serial.print(tmp_temp); Serial .print(" "); Serial.println(mill_tmp / 1000);
            minute_1_diff_measure_time = mill_tmp + 60000;//Set next measure time
            mylcd.setCursor(6, 1);  mylcd.print("      ");
            mylcd.setCursor(6, 1); mylcd.print(tmp_temp - minute_1_diff_measure_data, 2);// mylcd.print(" ");
            minute_1_diff_measure_data = tmp_temp;
          }
          if (mill_tmp > minute_10_diff_measure_time )
          {
            Serial.print("10 Min value "); Serial.print(tmp_temp); Serial .print(" "); Serial.println(mill_tmp / 1000);
            minute_10_diff_measure_time = mill_tmp + 600000;//Set next measure time
            mylcd.setCursor(12, 1);  mylcd.print("    ");
            mylcd.setCursor(12, 1); mylcd.print(tmp_temp - minute_10_diff_measure_data, 1);// mylcd.print(" ");
            minute_10_diff_measure_data = tmp_temp;
          }
        }
        //        mylcd.setCursor(0, 3); mylcd.print(mill_tmp / 1000); mylcd.print(" "); mylcd.print(minute_1_diff_measure_time / 1000);
        //        mylcd.setCursor(16, 3); mylcd.print(mill_tmp / 1000);

        //				Serial.print(F("Error            [mK]: "));
        //				Serial.println(SMT172::getError() * 1000, 2);
        //				Serial.println();
        break;
      case 2: Serial.println(F("**** Sensor disconnected ****"));
        Serial.println();
    }
//    delay(500);
  }
}

I always use the LiquidCrystal_PCF8574 library.

Works for me out of the box with the common I2C backpacks.

+1 for the hd44780 LCD library. The library will auto detect the I2C address and the I2C backpack to LDC pin mapping. Makes things much easier. The library is available through the library manager in the IDE.

groundFungus:
The library is availale through the library manager in the IDE.

That's the big +1 in my book.

There are dozens of forks and versions of the LiquidCrystal_I2C library available. All named the same thing, but with various subtle and not-so-subtle differences, particularly with the constructor. Sometimes they are documented. Sometimes the examples are updated to work with the version that includes them. Sometimes not (because of how easy it is to fork repos on github, many of these versions arent even meant for public consumption).

This is an issue with many libraries. But the situation is particularly bad with this one, im not sure why.

The hd44780 LCD lib handles both 20 * 4 and 16 * 2 LCD. Just define LCD_COLS and LCD_ROWS accordingly. Startup, clear display etc. has the same syntax.

Hi Guys,

Thanks for your feedback, I've now installed the hd44780 LCD lib from the IDE.

I've ran the diagnostic tool and it looks like everything is well set-up

********************************************************************
Serial Initialized
--------------------------------------------------------------------
I2CexpDiag - i2c LCD i/o expander backpack diagnostic tool
--------------------------------------------------------------------
hd44780 lib version: 1.0.1
--------------------------------------------------------------------
Reported Arduino Revision: 1.8.5
CPU ARCH: AVR - F_CPU: 16000000
--------------------------------------------------------------------
SDA digital pin: 18 A4
SCL digital pin: 19 A5
--------------------------------------------------------------------
Checking for required external I2C pull-up on SDA - YES
Checking for required external I2C pull-up on SCL - YES
Checking for I2C pins shorted together - Not Shorted
--------------------------------------------------------------------
Scanning i2c bus for devices..
 i2c device found at address 0x27
Total I2C devices found: 1
--------------------------------------------------------------------
Scanning i2c bus for all lcd displays
 LCD at address: 0x27 | config: P01245673H | R/W control: Yes
Total LCD devices found: 1
--------------------------------------------------------------------
LCD Display Memory Test
Display: 0
 Walking 1s data test:	PASSED
 Address line test:	PASSED
--------------------------------------------------------------------
Each working display should have its backlight on
and be displaying its #, address, and config information
If all pixels are on, or no pixels are showing, but backlight is on, try adjusting contrast pot
If backlight is off, wait for next test
--------------------------------------------------------------------
Blinking backlight test: to verify BL level autodetection
If backlight is mostly off but
you briefly see "BL Off" on display with backlight on,
then the library autodetected incorrect BL level
and the library cannot autoconfigure the device
--------------------------------------------------------------------
Displaying 'uptime' on all displays
--------------------------------------------------------------------

But I still can't see anything when I try to display text on the LCD, here is the helloworld script I use

// vi:ts=4
// ----------------------------------------------------------------------------
// HelloWorld - simple demonstration of lcd
// Created by Bill Perry 2016-07-02
// bperrybap@opensource.billsworld.billandterrie.com
//
// This example code is unlicensed and is released into the public domain
// ----------------------------------------------------------------------------
//
// This sketch is for LCDs with PCF8574 or MCP23008 chip based backpacks
// WARNING:
//	Use caution when using 3v only processors like arm and ESP8266 processors
//	when interfacing with 5v modules as not doing proper level shifting or
//	incorrectly hooking things up can damage the processor.
// 
// Sketch prints "Hello, World!" on the lcd
//
// If initialization of the LCD fails and the arduino supports a built in LED,
// the sketch will simply blink the built in LED.
//
// NOTE:
//	If the sketch fails to produce the expected results, or blinks the LED,
//	run the included I2CexpDiag sketch to test the i2c signals and the LCD.
//
// ----------------------------------------------------------------------------
// LiquidCrystal compability:
// Since hd44780 is LiquidCrystal API compatible, most existing LiquidCrystal
// sketches should work with hd44780 hd44780_I2Cexp i/o class once the
// includes are changed to use hd44780 and the lcd object constructor is
// changed to use the hd44780_I2Cexp i/o class.

#include <Wire.h>
#include <hd44780.h>                       // main hd44780 header
#include <hd44780ioClass/hd44780_I2Cexp.h> // i2c expander i/o class header

hd44780_I2Cexp lcd; // declare lcd object: auto locate & auto config expander chip

// If you wish to use an i/o expander at a specific address, you can specify the
// i2c address and let the library auto configure it. If you don't specify
// the address, or use an address of zero, the library will search for the
// i2c address of the device.
// hd44780_I2Cexp lcd(i2c_address); // specify a specific i2c address
//
// It is also possible to create multiple/seperate lcd objects
// and the library can still automatically locate them.
// Example:
// hd4480_I2Cexp lcd1;
// hd4480_I2Cexp lcd2;
// The individual lcds would be referenced as lcd1 and lcd2
// i.e. lcd1.home() or lcd2.clear()
//
// It is also possible to specify the i2c address
// when declaring the lcd object.
// Example:
// hd44780_I2Cexp lcd1(0x20);
// hd44780_I2Cexp lcd2(0x27);
// This ensures that each each lcd object is assigned to a specific
// lcd device rather than letting the library automatically asign it.

// LCD geometry
const int LCD_COLS = 20;
const int LCD_ROWS = 4;

void setup()
{
int status;

	// initialize LCD with number of columns and rows: 
	// hd44780 returns a status from begin() that can be used
	// to determine if initalization failed.
	// the actual status codes are defined in <hd44780.h>
	// See the values RV_XXXX
	//
	// looking at the return status from begin() is optional
	// it is being done here to provide feedback should there be an issue
	//
	// note:
	//	begin() will automatically turn on the backlight
	//
	status = lcd.begin(LCD_COLS, LCD_ROWS);
	if(status) // non zero status means it was unsuccesful
	{
		status = -status; // convert negative status value to positive number

		// begin() failed so blink error code using the onboard LED if possible
		hd44780::fatalError(status); // does not return
	}

	// initalization was successful, the backlight should be on now

	// Print a message to the LCD
	lcd.print("Hello, World!");
}

void loop() {}

My LED is not blinking on the arduino board and I can't see any error message indicating something is wrong.

Any idea regarding what I'm doing wrong with this?

I've also double checked and I use a PCF8574 based chip for the backpack.

Thanks

Did you try adjusting the contrast pot, again, with the hd44780 example running?

the issue was myself not using a potentiometer to adjust the contrast. I've added a 10K pot and it works like a charm. Thank you for your help

DrAzzy:
There are dozens of forks and versions of the LiquidCrystal_I2C library available. All named the same thing, but with various subtle and not-so-subtle differences, particularly with the constructor. Sometimes they are documented. Sometimes the examples are updated to work with the version that includes them. Sometimes not (because of how easy it is to fork repos on github, many of these versions arent even meant for public consumption).

This is an issue with many libraries. But the situation is particularly bad with this one, im not sure why.

OT but I agree entirely. I wish we could deal with this problem. Real Time Clock modules have also spawned a whole proliferation of "libraries" in various states of maintenance and documentation.

It would be great if if there was an easily referenced section of the forum where libraries could be evaluated, maybe with a points system or general recommendations and comments.

@6v6gt.
I agree wirh You. In one project I got a tip of one library that probably was a bit old and its result, temperature measurements, was incorrect and jumpy. New tip and then success using another library.