16x2 Alphanumeric lcd not displaying data connected to beagle bone black through gpio pins.

Hello Everyone,
I am trying to display some text data on 16x2 alphanumeric lcd display connected through gpio pins of beagle bone black board but the lcd initially displayed the text message in the code for 12 times of execution and later at final time of execution, lcd is simply giving backlight but not text data after thorough debugging of gpio pin mux configurations and pin states. Here is the code for 16x2 lcd:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>

#define LCD_RS “66” // Pin P8_7
#define LCD_EN “67” // Pin P8_8
#define LCD_D4 “69” // Pin P8_9
#define LCD_D5 “68” // Pin P8_10
#define LCD_D6 “45” // Pin P8_11
#define LCD_D7 “44” // Pin P8_12
#define LCD_BACKLIGHT “47” // Pin P8_15

// Function Prototypes
void gpio_export(const char *pin);
void gpio_unexport(const char *pin);
void gpio_direction(const char *pin, const char *dir);
void gpio_write(const char *pin, int value);
void lcd_init();
void lcd_clear();
void lcd_send_command(int command);
void lcd_send_data(int data);
void lcd_message(const char *message);
void lcd_set_backlight(int state);

int main() {
// Initialize GPIO and LCD
lcd_init();

// Display a message on the LCD
lcd_message("Hello, BBB!\n16x2 LCD Demo");

sleep(10);

// Clear the display and show another message
lcd_clear();
lcd_message("LCD Test Done!");
sleep(10);

// Turn off the backlight
lcd_set_backlight(0);

//Unexport pins to start fresh
gpio_unexport(LCD_RS);
gpio_unexport(LCD_EN);
gpio_unexport(LCD_D4);
gpio_unexport(LCD_D5);
gpio_unexport(LCD_D6);
gpio_unexport(LCD_D7);
gpio_unexport(LCD_BACKLIGHT);   

return 0;

}

// Function to export GPIO pin
void gpio_export(const char *pin) {
int fd = open(“/sys/class/gpio/export”, O_WRONLY);
if (fd == -1) {
perror(“Error exporting GPIO”);
return;
}
write(fd, pin, strlen(pin));
close(fd);
usleep(100000);
}

// Function to set GPIO direction
void gpio_direction(const char *pin, const char *dir) {
char path[35];
sprintf(path, “/sys/class/gpio/gpio%s/direction”, pin);
int fd = open(path, O_WRONLY);
if (fd == -1) {
perror(“Error setting GPIO direction”);
return;
}
write(fd, dir, strlen(dir));
close(fd);
usleep(100000);
}

// Function to write GPIO value
void gpio_write(const char *pin, int value) {
char path[35];
sprintf(path, “/sys/class/gpio/gpio%s/value”, pin);
int fd = open(path, O_WRONLY);
if (fd == -1) {
perror(“Error writing GPIO value”);
return;
}
if (value)
{
if(write(fd, “1”, 1)==-1)
perror(“Error writing 1 to GPIO”);
}
else
{
if(write(fd, “0”, 1)==-1)
perror(“Error writing 0 to GPIO”);
}
close(fd);
}

// Initialize the LCD
void lcd_init()
{
// Export pins and set directions
gpio_export(LCD_RS); gpio_direction(LCD_RS, “out”);
gpio_export(LCD_EN); gpio_direction(LCD_EN, “out”);
gpio_export(LCD_D4); gpio_direction(LCD_D4, “out”);
gpio_export(LCD_D5); gpio_direction(LCD_D5, “out”);
gpio_export(LCD_D6); gpio_direction(LCD_D6, “out”);
gpio_export(LCD_D7); gpio_direction(LCD_D7, “out”);
gpio_export(LCD_BACKLIGHT); gpio_direction(LCD_BACKLIGHT, “out”);

// Initialize LCD
gpio_write(LCD_BACKLIGHT, 1);  // Turn on backlight
usleep(15000); // Wait for power up
lcd_send_command(0x03); // Initialization sequence
lcd_send_command(0x02); // 4-bit mode
lcd_send_command(0x28); // 2 lines, 5x8 font
lcd_send_command(0x0C); // Display on, cursor off
lcd_clear();

}

// Clear LCD
void lcd_clear() {
lcd_send_command(0x01);
usleep(2000);
}

// Send command to LCD
void lcd_send_command(int command) {
gpio_write(LCD_RS, 0);
// Send upper nibble
gpio_write(LCD_D4, (command >> 4) & 0x01);
gpio_write(LCD_D5, (command >> 4) & 0x02);
gpio_write(LCD_D6, (command >> 4) & 0x04);
gpio_write(LCD_D7, (command >> 4) & 0x08);
gpio_write(LCD_EN, 1);
usleep(1);
gpio_write(LCD_EN, 0);
usleep(1);

// Send lower nibble
gpio_write(LCD_D4, command & 0x01);
gpio_write(LCD_D5, command & 0x02);
gpio_write(LCD_D6, command & 0x04);
gpio_write(LCD_D7, command & 0x08);
gpio_write(LCD_EN, 1);
usleep(1);
gpio_write(LCD_EN, 0);
usleep(40);

}

// Send data to LCD
void lcd_send_data(int data) {
gpio_write(LCD_RS, 1);
// Send upper nibble
gpio_write(LCD_D4, (data >> 4) & 0x01);
gpio_write(LCD_D5, (data >> 4) & 0x02);
gpio_write(LCD_D6, (data >> 4) & 0x04);
gpio_write(LCD_D7, (data >> 4) & 0x08);
gpio_write(LCD_EN, 1);
usleep(1);
gpio_write(LCD_EN, 0);
usleep(1);

// Send lower nibble
gpio_write(LCD_D4, data & 0x01);
gpio_write(LCD_D5, data & 0x02);
gpio_write(LCD_D6, data & 0x04);
gpio_write(LCD_D7, data & 0x08);
gpio_write(LCD_EN, 1);
usleep(1);
gpio_write(LCD_EN, 0);
usleep(40);

}

// Display message on LCD
void lcd_message(const char *message) {
for (int i = 0; i < strlen(message); i++) {
if (message[i] == ‘\n’) {
lcd_send_command(0xC0); // Move to second line
} else {
lcd_send_data(message[i]);
}
}
}

// Set backlight on or off
void lcd_set_backlight(int state) {
gpio_write(LCD_BACKLIGHT, state);

}

void gpio_unexport(const char *pin)
{
int fd = open(“/sys/class/gpio/unexport”,O_WRONLY);
if (fd == -1)
{
perror(“Error unexporting GPIO”);
return;
}
write(fd, pin, strlen(pin));
close(fd);
}

I request everyone to please help me to resolve the code issue and support me to get the output.
Thanks and regards,
Imran Pathan.

You don’t mention which display. Given that it did work 12 times before failing, we can assume you are talking to the display. I would double check all of the signal timings as that is the most likely cause for an error. Make sure minimum timings are being adhered to. Use of a scope would probably help.

Also try compiling with no optimisation.

gpio_write(LCD_D4, (command >> 4) & 0x01);
gpio_write(LCD_D5, (command >> 4) & 0x02);
gpio_write(LCD_D6, (command >> 4) & 0x04);
gpio_write(LCD_D7, (command >> 4) & 0x08);

Why do the shift ? You could just & 0x10, 0x20, 0x40, 0x80 instead. Not that is matters.

What is the control chip driving the display?

Looking at the Hitachi datasheet, your lcd initialization commands appear to be wrong, but it’s impossible to know without knowing which is the correct datasheet.

Hello Benedict hewson,
Thanks for your valuable feedback. I will definitely try the logic that you have described in your reply and update you. Below is the link for the lcd being used in my project:

Thanks and regards,
Imran Pathan.

I have already mentioned that the lcd chip is being driven by Beagle bone Black board. Hope you understand. Below is the link on the lcd being used in my project:

Thanks,
Imran Pathan.

I was asking about the lcd controller chip - that board uses a chip called SPLC780D, which appears to be a clone of the Hitachi chip. So that means your initialization commands are not correct - look particularly at the ‘data interface length’ command. If that’s not being set correctly, the display is probably working in 8 bit data mode.

Also I am getting the following errors after compiling as per your instructions:
“Error setting GPIO direction” and “Error writing GPIO value”.

Actually, looking at the data sheet, your data length setting might be correct after all - it’s quite confusing.

I’m not clear on what you’re trying to do with the line:
lcd_send_command(0x03); // Initialization sequence
This appears to set 8bit data mode, but in the next line you reset it to 4. Is that correct? What are you wanting to do with this line?

Hi paul,
Now I have changed the lcd initialization command sequence. Thanks for your notification.

@benedict.hewson
I have done code changes as per instructions but no data is being displayed on the lcd and the above mentioned errors are resolved. Please help me out to resolve lcd_send_command and lcd_send_data functions in the above code to get the output.
Thanks.

One thing that bothers me a little with this - you said it worked 12 times but then stopped working. This could suggest a hardware failure. Have you checked the gpio pins with a multimeter to verify they are actually responding?

How are you connecting the module to the bbb? The control pins should be ok connected directly, but on all the modules I’ve seen, the backlight input is connected directly to the LEDs, ie, it’s a power connection not a control connection. The bbb can only supply a few mA but the backlight will use way more than this. If you want to control the backlight with a gpio, you MUST use something like a FET to switch this externally.

1 Like

Ok this is posted from my phone so excuse the brevity.

Get a copy if the datasheet for the driver chip and review the 4 bit interface from power on.

Your initialization is wrong. You are either going to need a 4 bit write command or pass an extra flag to your function such that only 1 r bit write us done.

The power up sequence for 4 bit mode is write 3 wait >4.1ms write 3 wait > 100us write 3 then write 2.

Those all need to be a 4 bit command, but you are doing 2 writes for each command. You are pulsing the E pin twice. This might be confusing the driver chip.

After the 2 command it looks as though your 8 bits writes are then ok.

Also has the module got a reset line?
Because when you run the code once, the module is going to be in 4 bit mode so the next time you run it, the init code ptobably won’t work and may have unexpected results.

Ideally you need to make sure the module is always reset before you run your code.

Have you considered a better solution, I was using that type of display back when they were “NEW” technology. Now days, it best to use something better. That display is fine if you are using an 8 bit microcontroller that is in inherently deterministic. Your BBB is like car compared to hand cart. BBB has advanced resources, so it would be best to use them. We use Nextion HMI, it talks on the UART, your code base shrinks using that, your code is now transportable to other boards that run linux and have a usb or uart port. Plus some models have touch screen. If your customer has spec’d out the LCD you might not have many options, if its open look for a simpler solution.