Page 1 of 1

LCD1602 not initializing properly

Posted: Fri Aug 16, 2024 5:52 am
by inder1207
I am writing a I2C Driver for the LCD1602 (with PCF8574) Module when connected to ESP32. I have read the I2C Seciion of the ESP32 Datasheet to understand the working of it in ESP32. I am using the 'i2c.h' inside the driver folder as the Hardware Abstraction Layer in my custom driver. So, I also have gone through the datasheet of the LCD1602 and PCF8574 to understand the peripheral allocation and timing constraints. Before you can send any data to be displayed on the LCD, it needs to be initilaized by sending it commands. The PCF8574 is a 8-bit I/O expander. However, the LCD1602 only operated in 4-bit, hence we need some set of commands for the LCD's initialization. I think my initialization maybe is not working correctly which I am unable to find why. Here is the snippet of my code:
  1. [code]#include <stdio.h>
  2. #include "driver/i2c.h"
  3. #include "freertos/FreeRTOS.h"
  4. #include "freertos/task.h"
  5. #include "esp_intr_alloc.h"
  6. #include "esp_rom_sys.h"
  7.  
  8. #define En 0b00000100 //Defining enable bit, 1<<2
  9.  
  10. void i2c_Scan();
  11. void screen_init();
  12. void command(uint8_t data);
  13. void data_send(uint8_t data);
  14. void write_to_expander(uint8_t data);
  15. void strobe_enable(uint8_t data);
  16.  
  17. uint8_t blVAL= 0x00;
  18.  
  19. void app_main(void)
  20. {
  21. vTaskDelay(15 / portTICK_PERIOD_MS);
  22. i2c_Scan();
  23.  
  24. }
  25.  
  26. void i2c_Scan(){
  27. i2c_config_t conf = {0} ;
  28. conf.mode = I2C_MODE_MASTER;
  29. conf.sda_io_num = 21;
  30. conf.sda_pullup_en = GPIO_PULLUP_ENABLE;
  31. conf.scl_io_num = 22;
  32. conf.scl_pullup_en = GPIO_PULLUP_ENABLE;
  33. conf.master.clk_speed = 100000;
  34.  
  35. i2c_param_config(I2C_NUM_0,&conf);
  36. i2c_driver_install(I2C_NUM_0,conf.mode,0,0,0);
  37.  
  38. printf("Let's start the i2c communication \n");
  39.  
  40. screen_init();
  41. }
  42.  
  43. void screen_init(){
  44.  
  45. vTaskDelay(15 / portTICK_PERIOD_MS);
  46. command(0x30); ///Interface is 8-bit
  47.  
  48. vTaskDelay(4.1/portTICK_PERIOD_MS);
  49.  
  50. command(0x30); //Interface is 8-bit
  51.  
  52. esp_rom_delay_us(100);
  53.  
  54. command(0x30); //Interface is 8-bit
  55. esp_rom_delay_us(150);
  56. command(0x20); //Interface is 4-bit
  57.  
  58. command(0x28); //Setting Display Line and font size
  59.  
  60. command(0x0c); //Display Set On, Cursor Off
  61.  
  62. command(0x01); //Clear Display
  63. vTaskDelay(2/ portTICK_PERIOD_MS); //This extra delay is for Clearing
  64.  
  65. command(0x06); //Set moving direction of cursor
  66.  
  67. vTaskDelay(2/ portTICK_PERIOD_MS);
  68. blVAL = 0x01; //Turning backlight On
  69. command(0x02); //Cursor Return to Home.
  70. vTaskDelay(2/ portTICK_PERIOD_MS);
  71. }
  72.  
  73. void command(uint8_t data){
  74. uint8_t top4 = (data & 0xf0);
  75. uint8_t bottom4 = ((data & 0x0f)<<4);
  76.  
  77. //write_to_expander(top4);
  78. strobe_enable(top4);
  79.  
  80. //write_to_expander(bottom4);
  81. strobe_enable(bottom4);
  82. }
  83.  
  84. void strobe_enable(uint8_t data){
  85.     write_to_expander(((data | En) | blVAL<<3));
  86. esp_rom_delay_us(1);
  87.  
  88. write_to_expander(((data & (~En)) | blVAL<<3));
  89. esp_rom_delay_us(50);
  90. }
  91.  
  92. void write_to_expander(uint8_t data){
  93. //Command is enable here and timed for 1000ns
  94. i2c_cmd_handle_t cmd = i2c_cmd_link_create();
  95. i2c_master_start(cmd);
  96. i2c_master_write_byte(cmd,(0x27<<1)|0,true);
  97. i2c_master_write_byte(cmd,data,true);
  98. i2c_master_stop(cmd);
  99. esp_err_t ret = i2c_master_cmd_begin(I2C_NUM_0,cmd,10/portTICK_PERIOD_MS);
  100. i2c_cmd_link_delete(cmd);
  101.  
  102. if(ret == ESP_OK){
  103.     printf("The i2c command has begun.\n");
  104. }
  105.  
  106. }
  107.  
  108.  
  109. void data_send(uint8_t data){
  110. uint8_t top4 = (data & 0xf0);
  111. uint8_t bottom4 = ((data & 0x0f)<<4);
  112.  
  113. write_to_expander(top4 | 1<<0);
  114. write_to_expander(bottom4 | 1<< 0);
  115. }[/code]
Resources Used:
1.) ESP32 (I2C) : https://docs.espressif.com/projects/esp ... s/i2c.html
2.) PCF8574 Datasheet: "https://www.ti.com/lit/ds/symlink/pcf8574.pdf"
3.) LCD1602 Datasheet: "https://www.waveshare.com/datasheet/LCD ... CD1602.pdf"

Re: LCD1602 not initializing properly

Posted: Sun Aug 18, 2024 9:27 am
by aliarifat794
Hi? Which part of your code deals with the LCD initialization?

Re: LCD1602 not initializing properly

Posted: Tue Aug 20, 2024 11:43 pm
by inder1207
The function called screen_init() is the one where I send the commands as shown in the LCD1602's datasheet. Then I use the functions called command(), strobe_enable() and write_to_expander().

In the function:
1.) command() - I break down the 8-bit data into two 4-it nibbles and call strobe_enable()
2.) strobe_enable() - I enable the data that is being fed to the LCD1602 via PCF8574 expander module and call write_to_expander()
3.) write_to_expander() - I start the i2c communication that is explained in the resource that I shared for the ESP32's i2c driver.